diff --git a/src/chatwindow.cpp b/src/chatwindow.cpp index 49121f3..3572676 100644 --- a/src/chatwindow.cpp +++ b/src/chatwindow.cpp @@ -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); } diff --git a/src/chatwindow.hpp b/src/chatwindow.hpp index 10c79c3..1da87cd 100644 --- a/src/chatwindow.hpp +++ b/src/chatwindow.hpp @@ -1,9 +1,12 @@ #pragma once #include +#include +#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(); }; diff --git a/src/chatwindow.ui b/src/chatwindow.ui index d527737..9486e3d 100644 --- a/src/chatwindow.ui +++ b/src/chatwindow.ui @@ -1,21 +1,71 @@ + - - - - Form - + ChatWindow + 0 0 - 400 - 300 + 807 + 519 - Form + + + + + + + + + + 697 + 0 + + + + Contact PeerID: + + + + + + + + + + Send + + + + + + + true + + + + - - + + + + msgEdit + returnPressed() + sendMsgButton + click() + + + 360 + 497 + + + 757 + 497 + + + + diff --git a/src/kernel/handler.cpp b/src/kernel/handler.cpp index 676615f..465718e 100644 --- a/src/kernel/handler.cpp +++ b/src/kernel/handler.cpp @@ -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()); +} diff --git a/src/kernel/handler.hpp b/src/kernel/handler.hpp index a436845..de2dca9 100644 --- a/src/kernel/handler.hpp +++ b/src/kernel/handler.hpp @@ -2,22 +2,32 @@ #include "network.hpp" #include +#include 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> 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); }; diff --git a/src/kernel/network.cpp b/src/kernel/network.cpp index 12340fc..892c717 100644 --- a/src/kernel/network.cpp +++ b/src/kernel/network.cpp @@ -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; } diff --git a/src/kernel/network.hpp b/src/kernel/network.hpp index 6b0679f..f94b89f 100644 --- a/src/kernel/network.hpp +++ b/src/kernel/network.hpp @@ -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(); }; diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 389ab1e..71a0bf1 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -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(); + } + } } diff --git a/src/mainwindow.h b/src/mainwindow.h index 69905db..918790a 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -3,9 +3,12 @@ #include #include "kernel/network.hpp" #include "kernel/handler.hpp" +#include "chatwindow.hpp" +#include #include #include #include +#include namespace Ui { @@ -19,18 +22,24 @@ class MainWindow : public QMainWindow public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); + QVector 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(); + bool receive = false; }; diff --git a/src/mainwindow.ui b/src/mainwindow.ui index 0eb633a..d8c0504 100644 --- a/src/mainwindow.ui +++ b/src/mainwindow.ui @@ -39,15 +39,21 @@ + + + - Мой IP: + My IPv6: + + + - Подключиться + Connect