Added the ability to correspond, performed a small optimization (fixed the memory leak), changed the structure of all the code (in particular, changed the names of many variables, etc.)

Also translated all into English.
This commit is contained in:
Denis Davydov 2018-07-26 11:33:47 +03:00
parent 9475414ecd
commit 630f739538
10 changed files with 350 additions and 53 deletions

View File

@ -1,14 +1,67 @@
#include "chatwindow.hpp"
#include "ui_chatwindow.h"
ChatWindow::ChatWindow(QWidget *parent) :
ChatWindow::ChatWindow(QString pID, QString cUUID, Handler *h, Network *n, QWidget *parent) :
QWidget(parent),
ui(new Ui::Form)
ui(new Ui::ChatWindow)
{
ui->setupUi(this);
this->setAttribute(Qt::WA_DeleteOnClose);
chatID = cUUID;
peerID = pID;
handler = h;
network = n;
ui->peerIDLabel->setText(ui->peerIDLabel->text() + pID);
connect(ui->sendMsgButton, &QAbstractButton::clicked, this, &ChatWindow::sendMsgButtonClicked);
}
ChatWindow::~ChatWindow()
{
leftFromChat();
emit deleteChat(chatID);
delete ui;
this->deleteLater();
}
void ChatWindow::sendMessage(QString msgText)
{
QJsonObject jSend;
jSend["action"] = "msgSend";
jSend["peerID"] = *network->myIPv6;
jSend["chatID"] = chatID;
jSend["msgText"] = msgText;
network->sendDatagram(jSend, peerID);
ui->chatEdit->append(tr("You: ") + msgText);
}
void ChatWindow::sendMsgButtonClicked()
{
QString msg = ui->msgEdit->text();
sendMessage(msg);
ui->msgEdit->setText("");
}
void ChatWindow::displayMsg(QString msgText)
{
ui->chatEdit->append(peerID + ": " + msgText);
}
void ChatWindow::leftFromChat()
{
QJsonObject json;
json["action"] = "leftChat";
json["peerID"] = *network->myIPv6;
json["chatID"] = chatID;
network->sendDatagram(json, peerID);
}
void ChatWindow::peerReceiverLeftFromChat()
{
QString msg;
msg += tr("Peer ");
msg += peerID;
msg += tr(" left from this chat.");
QMessageBox::warning(this, tr("Peer receiver left from chat!"), msg, QMessageBox::Ok);
ui->chatEdit->append(peerID + tr("left from this chat."));
ui->msgEdit->setEnabled(false);
ui->sendMsgButton->setEnabled(false);
}

View File

@ -1,9 +1,12 @@
#pragma once
#include <QWidget>
#include <QJsonObject>
#include "kernel/handler.hpp"
#include "kernel/network.hpp"
namespace Ui {
class Form;
class ChatWindow;
}
class ChatWindow : public QWidget
@ -11,9 +14,20 @@ class ChatWindow : public QWidget
Q_OBJECT
public:
explicit ChatWindow(QWidget *parent = 0);
explicit ChatWindow(QString pID, QString cUUID, Handler *h, Network *n, QWidget *parent = 0);
~ChatWindow();
QString chatID;
QString peerID;
Handler *handler;
Network *network;
void displayMsg(QString msgText);
void peerReceiverLeftFromChat();
private:
Ui::ChatWindow *ui;
void sendMessage(QString msgText);
void leftFromChat();
signals:
void deleteChat(QString cID);
private slots:
void sendMsgButtonClicked();
};

View File

@ -1,21 +1,71 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<author/>
<comment/>
<exportmacro/>
<class>Form</class>
<widget class="QWidget" name="Form">
<class>ChatWindow</class>
<widget class="QWidget" name="ChatWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
<width>807</width>
<height>519</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
<string/>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="2" column="0" colspan="2">
<widget class="QLineEdit" name="msgEdit"/>
</item>
<item row="0" column="0">
<widget class="QLabel" name="peerIDLabel">
<property name="minimumSize">
<size>
<width>697</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Contact PeerID: </string>
</property>
</widget>
<pixmapfunction/>
<connections/>
</item>
<item row="2" column="2">
<widget class="QPushButton" name="sendMsgButton">
<property name="locale">
<locale language="English" country="UnitedStates"/>
</property>
<property name="text">
<string>Send</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="3">
<widget class="QTextEdit" name="chatEdit">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>msgEdit</sender>
<signal>returnPressed()</signal>
<receiver>sendMsgButton</receiver>
<slot>click()</slot>
<hints>
<hint type="sourcelabel">
<x>360</x>
<y>497</y>
</hint>
<hint type="destinationlabel">
<x>757</x>
<y>497</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -5,30 +5,97 @@ Handler::Handler()
using namespace std::placeholders;
handlers = {
{"checkPeer", std::bind(&Handler::createSession, this, _1)},
{"checkPeerSuccess", std::bind(&Handler::checkPeerSuccessMethod, this, _1)}
{"checkPeer", std::bind(&Handler::checkPeer, this, _1)},
{"checkPeerSuccess", std::bind(&Handler::checkPeerSuccessMethod, this, _1)},
{"createChat", std::bind(&Handler::createChatMethod, this, _1)},
{"createChatSuccess", std::bind(&Handler::createChatSuccessMethod, this, _1)},
{"createChatFailed", std::bind(&Handler::createChatFailedMethod, this, _1)},
{"msgSend", std::bind(&Handler::msgReceiveMethod, this, _1)},
{"leftChat", std::bind(&Handler::peerReceiverLeftFromChatMethod, this, _1)}
};
peerReceiver = new QString();
network = new Network();
connect(network, &Network::json_received, this, &Handler::handle);
connect(network, &Network::jsonReceived, this, &Handler::handle);
}
void Handler::handle(QJsonObject jsonReceived)
{
QString action = jsonReceived["action"].toString();
*peerReceiver = jsonReceived["peerID"].toString();
handlers[action](jsonReceived);
}
void Handler::createSession(QJsonObject jsonReceived)
void Handler::checkPeer(QJsonObject jsonReceived)
{
QJsonObject jsonSend;
jsonSend["peerID"] = my_ipv6;
jsonSend["peerID"] = *network->myIPv6;
jsonSend["action"] = "checkPeerSuccess";
QString peerReceiver = jsonReceived["peerID"].toString();
network->sendDatagram(jsonSend, peerReceiver);
network->sendDatagram(jsonSend, *peerReceiver);
}
void Handler::createSessionSuccessMethod(QJsonObject jsonReceived)
void Handler::checkPeerSuccessMethod(QJsonObject jsonReceived)
{
emit checkPeerSuccess();
}
Handler::~Handler()
{
delete peerReceiver;
delete network;
//delete handlers;
}
void Handler::createChatMethod(QJsonObject jsonReceived)
{
QWidget *parent = 0;
QString msgTitle;
QString msg;
msgTitle += "Create chat";
msg += tr("Peer ");
msg += *peerReceiver;
msg += tr(" want to create chat with you.\n");
msg += tr("Do you want to create chat?");
int ret = QMessageBox::warning(parent, msgTitle, msg, QMessageBox::Yes | QMessageBox::No);
if(ret == QMessageBox::Yes)
{
QJsonObject jsonSend;
jsonSend["peerID"] = *network->myIPv6;
jsonSend["action"] = "createChatSuccess";
jsonSend["chatID"] = jsonReceived["chatUUID"].toString();
network->sendDatagram(jsonSend, *peerReceiver);
}
else
{
QJsonObject jsonSend;
jsonSend["peerID"] = *network->myIPv6;
jsonSend["action"] = "createChatFailed";
network->sendDatagram(jsonSend, *peerReceiver);
}
}
void Handler::createChatFailedMethod(QJsonObject jsonReceived)
{
QString msg;
msg += tr("Peer ");
msg += *peerReceiver;
msg += tr(" refused to create a chat with you");
QWidget *parent = 0;
QMessageBox::critical(parent, tr("Create chat failed!"), msg, QMessageBox::Ok);
emit createChatFailed();
}
void Handler::createChatSuccessMethod(QJsonObject jsonReceived)
{
emit createChatSuccess(jsonReceived["peerID"].toString(), jsonReceived["chatID"].toString());
}
void Handler::msgReceiveMethod(QJsonObject jsonReceived)
{
emit msgReceived(jsonReceived["peerID"].toString(), jsonReceived["chatID"].toString(), jsonReceived["msgText"].toString());
}
void Handler::peerReceiverLeftFromChatMethod(QJsonObject jsonReceived)
{
emit peerReceiverLeftFromChat(jsonReceived["peerID"].toString(), jsonReceived["chatID"].toString());
}

View File

@ -2,22 +2,32 @@
#include "network.hpp"
#include <QJsonObject>
#include <QMessageBox>
class Handler : public QObject
{
Q_OBJECT
const QString my_ipv6 = Network::local_ipv6();
public:
Handler();
signals:
void checkPeerSuccess();
~Handler();
QString *peerReceiver;
private:
Network *network;
void createSession(QJsonObject jsonReceived);
void checkPeer(QJsonObject jsonReceived);
std::map<QString, std::function<void(QJsonObject)>> handlers;
void checkPeerSuccessMethod(QJsonObject jsonReceived);
void createChatMethod(QJsonObject jsonReceived);
void createChatSuccessMethod(QJsonObject jsonReceived);
void createChatFailedMethod(QJsonObject jsonReceived);
void msgReceiveMethod(QJsonObject jsonReceived);
void peerReceiverLeftFromChatMethod(QJsonObject jsonReceived);
signals:
void checkPeerSuccess();
void createChatSuccess(QString peerID, QString chatID);
void createChatFailed();
void msgReceived(QString peerID, QString chatID, QString msgText);
void peerReceiverLeftFromChat(QString peerID, QString chatID);
private slots:
void handle(QJsonObject jsonReceived);
};

View File

@ -1,4 +1,5 @@
#include "network.hpp"
Network::Network(bool is_server)
{
udpSocket = new QUdpSocket(this);
@ -7,6 +8,7 @@ Network::Network(bool is_server)
udpSocket->bind(QHostAddress::AnyIPv6, 6552);
connect(udpSocket, SIGNAL(readyRead()), this, SLOT(processTheDatagram()));
}
myIPv6 = new QString(localIPv6());
}
void Network::sendDatagram(QJsonObject j, QString s)
@ -23,16 +25,16 @@ void Network::processTheDatagram()
{
QByteArray baDatagram;
do {
baDatagram.resize(udpSocket->pendingDatagramSize ()) ;
baDatagram.resize(udpSocket->pendingDatagramSize()) ;
udpSocket->readDatagram (baDatagram.data(), baDatagram.size()) ;
} while (udpSocket->hasPendingDatagrams()) ;
QJsonDocument jbuff = QJsonDocument::fromJson(baDatagram);
QJsonObject j = QJsonObject(jbuff.object());
emit json_received(j);
emit jsonReceived(j);
}
QString Network::local_ipv6()
QString Network::localIPv6()
{
QHostAddress address;
foreach (address, QNetworkInterface::allAddresses()) {
@ -45,4 +47,5 @@ QString Network::local_ipv6()
Network::~Network()
{
delete udpSocket;
delete myIPv6;
}

View File

@ -9,15 +9,18 @@ class Network : public QObject
{
Q_OBJECT
private:
QUdpSocket* udpSocket;
public:
Network(bool is_server = true);
static QString local_ipv6();
~Network();
static QString localIPv6();
const QString *myIPv6;
private:
QUdpSocket* udpSocket;
public slots:
void sendDatagram(QJsonObject j, QString s);
signals:
void json_received(QJsonObject &jsonReceived);
void jsonReceived(QJsonObject &jsonReceived);
private slots:
void processTheDatagram();
};

View File

@ -10,21 +10,28 @@ MainWindow::MainWindow(QWidget *parent) :
handler = new Handler();
timer = new QTimer();
connect(timer, SIGNAL(timeout()), this, SLOT(slotTimerAlarm()));
connect(handler, &Handler::checkPeerSuccessSuccess, this, &MainWindow::peerReceiverAvailable);
ui->myIP->setText(my_ipv6);
connect(handler, &Handler::checkPeerSuccess, this, &MainWindow::peerReceiverAvailable);
connect(handler, &Handler::createChatSuccess, this, &MainWindow::createChat);
connect(handler, &Handler::createChatFailed, this, &MainWindow::createChatFailedMethod);
connect(handler, &Handler::msgReceived, this, &MainWindow::msgReceivedMethod);
connect(handler, &Handler::peerReceiverLeftFromChat, this, &MainWindow::peerReceiverLeftFromChatMethod);
ui->myIP->setText(*network->myIPv6);
}
MainWindow::~MainWindow()
{
delete ui;
delete network;
delete handler;
delete timer;
}
void MainWindow::on_connectToPeer_clicked()
{
ui->connectToPeer->setEnabled(false);
ui->connectToPeer->setText("Ожидание...");
setButtonToWaiting();
QJsonObject j;
j["peerID"] = my_ipv6;
j["peerID"] = *network->myIPv6;
j["action"] = "checkPeer";
QString s = ui->peerID->text();
network->sendDatagram(j, s);
@ -40,10 +47,9 @@ void MainWindow::slotTimerAlarm()
}
else
{
int ret = QMessageBox::critical(this,QObject::tr("Error"),tr("Timeout Error"));
QMessageBox::critical(this, tr("Error"), tr("Timeout Error"));
timer->stop();
ui->connectToPeer->setEnabled(true);
ui->connectToPeer->setText("Подключиться");
setButtonToConnect();
}
}
@ -51,7 +57,83 @@ void MainWindow::slotTimerAlarm()
void MainWindow::peerReceiverAvailable()
{
receive = true;
int ret = QMessageBox::information(this,QObject::tr("Info"),tr("Peer Available!"));
ui->connectToPeer->setEnabled(true);
ui->connectToPeer->setText("Подключиться");
int ret = QMessageBox::information(this, tr("Peer Available!"),
tr("Peer Available!\n Do you want to create chat?"), QMessageBox::Yes | QMessageBox::No);
if(ret == QMessageBox::Yes)
{
createChatSendDatagram(*handler->peerReceiver);
}
else
{
setButtonToConnect();
}
}
void MainWindow::setButtonToWaiting() // Function, which sets button "connectToPeer" in status "Waiting..."
{
ui->connectToPeer->setEnabled(false);
ui->connectToPeer->setText(tr("Waiting..."));
}
void MainWindow::setButtonToConnect() // Function, which sets button "connectToPeer" in status "Connect"
{
ui->connectToPeer->setEnabled(true);
ui->connectToPeer->setText(tr("Connect"));
}
void MainWindow::createChatSendDatagram(QString peerReceiver)
{
QUuid chatID = QUuid::createUuid();
QJsonObject jSend;
jSend["action"] = "createChat";
jSend["peerID"] = *network->myIPv6;
jSend["chatUUID"] = chatID.toString();
network->sendDatagram(jSend, peerReceiver);
}
void MainWindow::createChat(QString peerID, QString chatID)
{
pChatWindows.push_back(new ChatWindow(peerID, chatID, handler, network));
connect(pChatWindows.back(), &ChatWindow::deleteChat, this, &MainWindow::deleteChatMethod);
pChatWindows.back()->show();
setButtonToConnect();
}
void MainWindow::createChatFailedMethod()
{
setButtonToConnect();
}
void MainWindow::deleteChatMethod(QString cID)
{
for(int i = 0; i < pChatWindows.size(); i++)
{
if(pChatWindows.at(i)->chatID == cID)
{
pChatWindows.remove(i);
break;
}
}
}
void MainWindow::msgReceivedMethod(QString peerID, QString chatID, QString msgText)
{
for(int i = 0; i < pChatWindows.size(); i++)
{
if(pChatWindows.at(i)->peerID == peerID && pChatWindows.at(i)->chatID == chatID)
{
pChatWindows.at(i)->displayMsg(msgText);
}
}
}
void MainWindow::peerReceiverLeftFromChatMethod(QString peerID, QString chatID)
{
for(int i = 0; i < pChatWindows.size(); i++)
{
if(pChatWindows.at(i)->peerID == peerID && pChatWindows.at(i)->chatID == chatID)
{
pChatWindows.at(i)->peerReceiverLeftFromChat();
}
}
}

View File

@ -3,9 +3,12 @@
#include <QMainWindow>
#include "kernel/network.hpp"
#include "kernel/handler.hpp"
#include "chatwindow.hpp"
#include <QUuid>
#include <QMessageBox>
#include <QJsonObject>
#include <QJsonDocument>
#include <QObject>
namespace Ui {
@ -19,18 +22,24 @@ class MainWindow : public QMainWindow
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
QVector<ChatWindow*> pChatWindows;
void setButtonToWaiting();
void setButtonToConnect();
public slots:
void peerReceiverAvailable();
private slots:
void on_connectToPeer_clicked();
void slotTimerAlarm();
void createChatFailedMethod();
void createChat(QString peerID, QString chatID);
void deleteChatMethod(QString cID);
void msgReceivedMethod(QString peerID, QString chatID, QString msgText);
void peerReceiverLeftFromChatMethod(QString peerID, QString chatID);
private:
void createChatSendDatagram(QString peerReceiver);
Ui::MainWindow *ui;
QTimer *timer;
Network *network;
Handler *handler;
bool receive = false;
const QString my_ipv6 = Network::local_ipv6();
};

View File

@ -39,15 +39,21 @@
</item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="locale">
<locale language="English" country="UnitedStates"/>
</property>
<property name="text">
<string>Мой IP:</string>
<string>My IPv6:</string>
</property>
</widget>
</item>
<item row="1" column="4">
<widget class="QPushButton" name="connectToPeer">
<property name="locale">
<locale language="English" country="UnitedStates"/>
</property>
<property name="text">
<string>Подключиться</string>
<string>Connect</string>
</property>
</widget>
</item>