From ce82fb32e58218e5325da64fc72d58f854db8e6e Mon Sep 17 00:00:00 2001 From: semenov Date: Tue, 14 Jan 2025 11:16:16 +0300 Subject: [PATCH] =?UTF-8?q?feat:=20=D0=BE=D1=82=D0=B4=D0=B5=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20=D0=BE=D0=B1=D1=89=D0=B8=D1=85=20=D1=80?= =?UTF-8?q?=D0=B0=D1=81=D1=81=D1=8B=D0=BB=D0=BE=D0=BA=20=D0=BF=D0=BE=20?= =?UTF-8?q?=D0=BA=D0=BB=D0=B8=D0=B5=D0=BD=D1=82=D0=B0=D0=BC=20=D0=B2=20?= =?UTF-8?q?=D0=BE=D1=82=D0=B4=D0=B5=D0=BB=D1=8C=D0=BD=D1=8B=D0=B9=20=D1=81?= =?UTF-8?q?=D0=B5=D1=80=D0=B2=D0=B8=D1=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DOCS/.obsidian/workspace.json | 14 +- DOCS/MainScheme.md | 143 +++++++++--------- ServerLMS/ServerLMS/CMakeLists.txt | 2 + .../ServerLMS/Systems/commonclienthandler.cpp | 140 +++++++++++++++++ .../ServerLMS/Systems/commonclienthandler.h | 39 +++++ .../ServerLMS/Systems/processingsystem.cpp | 13 +- .../ServerLMS/Systems/processingsystem.h | 4 +- .../ServerLMS/Systems/updatecontroller.cpp | 24 +-- .../ServerLMS/Systems/updatecontroller.h | 5 +- ServerLMS/ServerLMS/serverlmswidget.cpp | 136 ++--------------- ServerLMS/ServerLMS/serverlmswidget.h | 12 +- 11 files changed, 299 insertions(+), 233 deletions(-) create mode 100644 ServerLMS/ServerLMS/Systems/commonclienthandler.cpp create mode 100644 ServerLMS/ServerLMS/Systems/commonclienthandler.h diff --git a/DOCS/.obsidian/workspace.json b/DOCS/.obsidian/workspace.json index 46000b6..dbd38c5 100644 --- a/DOCS/.obsidian/workspace.json +++ b/DOCS/.obsidian/workspace.json @@ -65,14 +65,12 @@ "id": "9608f84166966ca9", "type": "leaf", "state": { - "type": "markdown", + "type": "excalidraw", "state": { - "file": "Как умеем принимать, как умеем отправлять!.md", - "mode": "source", - "source": false + "file": "MainScheme.md" }, - "icon": "lucide-file", - "title": "Как умеем принимать, как умеем отправлять!" + "icon": "excalidraw-icon", + "title": "MainScheme" } } ], @@ -221,14 +219,14 @@ }, "active": "9608f84166966ca9", "lastOpenFiles": [ + "AssetManagerScheme.md", + "Как умеем принимать, как умеем отправлять!.md", "Порядок сборки Unity билда под сервер.md", "Образец отправки сообщения с маркером.md", - "Как умеем принимать, как умеем отправлять!.md", "Алексей/Board.md", "Алексей/DataParser scheme.md", "Алексей/ProcessingSystem scheme.md", "MainScheme.md", - "AssetManagerScheme.md", "Что умеем отправлять Server - Client QT.md", "CLIENT SERVER.canvas", "Алексей/Рефакторинг.md", diff --git a/DOCS/MainScheme.md b/DOCS/MainScheme.md index 05b3183..fba2e6e 100644 --- a/DOCS/MainScheme.md +++ b/DOCS/MainScheme.md @@ -80,6 +80,7 @@ Mainthread: *processingSystem *dataParser *MultiThreadServer +* commonClientHandler ^ite9vjus @@ -314,144 +315,146 @@ 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 -/HAAj9BRul1GY4nUUrQQAA== +ISZCsFtWpPId5DtZjRCCgCFDfskGwZOgZCTYv5CvIVZCpzsscn8JFD0gIYsySgSZ2JqlDmUrrxmiLgJh8ApDmAB014OgQZuRObxbIBbFdgmn86qA+hiofCArJL/QoUE71mIGftT4pAAjAGwADANd0GAAQAC0Bt0nRnMA/ONlD3ITy5OCgpDgwCQAS/LmBxIRNC8iicBX0ggh0tiQAAQEDoEAIYtcAJoBggFgEloYWdn6Ak98APkRSAMoBmMAAAKP + +fD6Bc6F2MK8BX1EYAAASn9Ap9GUA6aDHwR0NOhFsQuhaUWPGAoBuh90KGhcUP4wjkNPIsKWaAmAMy2p9B1wQvFD6III2hW0Pqug6iIAr6UGGIvBEhBvxzYx9AaBUBiGhdgC3QDE2YARIIdiK0NWA60M2hhDmLwiEz0WCAGaInUKXsteVaiYQGCA5MLde8YhqiU9H0AeUJ2YVQx3qj/AvQ5MMYAVMJdAEPXX44AEfoFN0uozHE6ilaCAAA=== ``` %% \ No newline at end of file diff --git a/ServerLMS/ServerLMS/CMakeLists.txt b/ServerLMS/ServerLMS/CMakeLists.txt index 492cb4d..8805faa 100644 --- a/ServerLMS/ServerLMS/CMakeLists.txt +++ b/ServerLMS/ServerLMS/CMakeLists.txt @@ -47,6 +47,8 @@ add_library(ServerLMS SHARED Systems/recognizesystem.h Systems/updatecontroller.cpp Systems/updatecontroller.h + Systems/commonclienthandler.cpp + Systems/commonclienthandler.h Systems/logger.cpp Systems/logger.h Systems/dataparser.cpp diff --git a/ServerLMS/ServerLMS/Systems/commonclienthandler.cpp b/ServerLMS/ServerLMS/Systems/commonclienthandler.cpp new file mode 100644 index 0000000..64d4c09 --- /dev/null +++ b/ServerLMS/ServerLMS/Systems/commonclienthandler.cpp @@ -0,0 +1,140 @@ +#include "commonclienthandler.h" + +CommonClientHandler::CommonClientHandler(QObject *parent) : QObject(parent) +{ + +} + +void CommonClientHandler::initialize(QMap *clientsMap, ProcessingSystem *processingSystem, DataParser *dataParser, Logger *logger) +{ + this->clientsMap = clientsMap; + this->processingSystem = processingSystem; + this->dataParser = dataParser; + this->logger = logger; +} + +void CommonClientHandler::sendNewVersionListToAllClient() +{ + foreach(int idSocket,clientsMap->keys()) + { + ClientHandler *handler = clientsMap->value(idSocket); + + if (!handler->getClient()->getIsLoggedIn()) continue; + + handler->sendVersionList(); + } +} + +void CommonClientHandler::sendCurrentVersionToAllClient() +{ + foreach(int idSocket,clientsMap->keys()) + { + ClientHandler *handler = clientsMap->value(idSocket); + + if (!handler->getClient()->getIsLoggedIn()) continue; + handler->sendVersion(); + + } +} + +void CommonClientHandler::slot_AuthChanged() +{ + //Проходим все открытые сокеты + foreach(int idSocket, clientsMap->keys()) + { + ClientHandler *handler = clientsMap->value(idSocket); + //Проверяем, есть ли клиенты TYPE_GUI + if(handler->getClient()->getTypeClient() == TypeClientAutorization::TYPE_GUI) + {//Отправляем этому клиенту обновление списков + ClientQueryToDB queryToDB; + queryToDB.typeQuery = TypeQueryToDB::TYPE_QUERY_GET_ALL_LISTS; + processingSystem->processingClientQueryToDB(handler, queryToDB); + } + } +} + +void CommonClientHandler::slot_sendPacketToAllClients(PacketType packetType) +{ + foreach(int idSocket, clientsMap->keys()) + { + ClientHandler *handler = clientsMap->value(idSocket); + + if (!handler->getClient()->getIsLoggedIn()) continue; + + handler->sendPacketType(packetType); + } +} + +void CommonClientHandler::slot_msgToClientFromGUI(QString login, QString text) +{ + QString textMsg = text; + + QByteArray byteArrayMsg = dataParser->xmlAnswer_message(textMsg); + + //Проходим все открытые сокеты, ищем нужный + foreach(int idSocket, clientsMap->keys()) + { + ClientHandler *handler = clientsMap->value(idSocket); + if(handler->getClient()->getLogin() == login) + {//Отправляем ему + + handler->sendXmlAnswer(byteArrayMsg); + + QString peerAddress = handler->getSocket()->peerAddress().toString(); + QString peerPort = QString::number(handler->getSocket()->peerPort()); + + QString str = "Msg To Client [" + peerAddress + ":" + peerPort + "] : " + textMsg; + + logger->addTextToLogger(str); + break; + } + } +} + +void CommonClientHandler::slot_msgToGUIfromClient(QString login, QString text) +{ + QString textMsg = text; + + QByteArray byteArrayMsg = dataParser->xmlAnswer_message(textMsg, login); + + //Проходим все открытые сокеты, ищем нужный + foreach(int idSocket, clientsMap->keys()) + { + ClientHandler *handler = clientsMap->value(idSocket);; + if(handler->getClient()->getTypeClient() == TypeClientAutorization::TYPE_GUI) + {//Отправляем GUI-клиенту для отображения в Мессенджере + + handler->sendXmlAnswer(byteArrayMsg, PacketType::TYPE_XMLANSWER); + + QString peerAddress = handler->getSocket()->peerAddress().toString(); + QString peerPort = QString::number(handler->getSocket()->peerPort()); + + QString str = "Msg From Client [" + peerAddress + ":" + peerPort + "] : " + textMsg; + + logger->addTextToLogger(str); + break; + } + } +} + +void CommonClientHandler::slot_sendTaskToClient(QString fullNameClient,QString textTask) +{ + QByteArray byteArrayTask = dataParser->xmlAnswer_task(textTask); + + //Проходим все открытые сокеты + foreach(int idSocket, clientsMap->keys()) + { + ClientHandler *handler = clientsMap->value(idSocket); + + if(handler->getClient()->getFullName() == fullNameClient) + {//Отправляем ему + handler->getSocket()->write(byteArrayTask); + + QString peerAddress = handler->getSocket()->peerAddress().toString(); + QString peerPort = QString::number(handler->getSocket()->peerPort()); + + QString str = "Task To Client [" + peerAddress + ":" + peerPort + "] : " + textTask; + logger->addTextToLogger(str); + } + } +} diff --git a/ServerLMS/ServerLMS/Systems/commonclienthandler.h b/ServerLMS/ServerLMS/Systems/commonclienthandler.h new file mode 100644 index 0000000..e4af2bd --- /dev/null +++ b/ServerLMS/ServerLMS/Systems/commonclienthandler.h @@ -0,0 +1,39 @@ +#ifndef COMMONCLIENTHANDLER_H +#define COMMONCLIENTHANDLER_H + +#include +#include + +class ProcessingSystem; +class DataParser; +class Logger; + +class CommonClientHandler : public QObject +{ + Q_OBJECT +public: + explicit CommonClientHandler(QObject *parent = nullptr); + void initialize(QMap *clientsMap, + ProcessingSystem *processingSystem, + DataParser *dataParser, + Logger *logger); + + void sendNewVersionListToAllClient(); + void sendCurrentVersionToAllClient(); + void slot_AuthChanged(); + void slot_sendPacketToAllClients(PacketType packetType); + //слот обработки сигнала о готовности нового сообщения на отправку клиенту от мессенджера + void slot_msgToClientFromGUI(QString login, QString text); + void slot_msgToGUIfromClient(QString login, QString text); + void slot_sendTaskToClient(QString fullNameClient, QString textTask); +signals: + +private: + QMap *clientsMap; + ProcessingSystem *processingSystem; + DataParser *dataParser; + Logger *logger; + +}; + +#endif // COMMONCLIENTHANDLER_H diff --git a/ServerLMS/ServerLMS/Systems/processingsystem.cpp b/ServerLMS/ServerLMS/Systems/processingsystem.cpp index 7338c1b..10aba0f 100644 --- a/ServerLMS/ServerLMS/Systems/processingsystem.cpp +++ b/ServerLMS/ServerLMS/Systems/processingsystem.cpp @@ -8,16 +8,17 @@ ProcessingSystem::ProcessingSystem(ProviderDBLMS* providerDBLMS, QObject *parent this->providerDBLMS = providerDBLMS; } -void ProcessingSystem::initialize(DataParser *dataParser, ServerLMSWidget *server) +void ProcessingSystem::initialize(ServerLMSWidget *server, DataParser *dataParser, CommonClientHandler *commonClientHandler,Logger *logger) { - this->server = server; + this->commonClientServer = commonClientHandler; this->dataParser = dataParser; + this->server = server; - connect(this,&ProcessingSystem::sigAuthChanged,server, &ServerLMSWidget::slot_AuthChanged,Qt::AutoConnection); + connect(this,&ProcessingSystem::sigAuthChanged,commonClientHandler, &CommonClientHandler::slot_AuthChanged,Qt::AutoConnection); connect(this,&ProcessingSystem::sigUpdateListClients,server, &ServerLMSWidget::slotUpdateListClients,Qt::AutoConnection); - connect(this,&ProcessingSystem::sigLogMessage,server->getLogger(),&Logger::addTextToLogger,Qt::QueuedConnection); - connect(this,&ProcessingSystem::signal_msgToClientReady,server, &ServerLMSWidget::slot_msgToClientFromGUI); - connect(this,&ProcessingSystem::signal_msgFromClientReady,server, &ServerLMSWidget::slot_msgToGUIfromClient); + connect(this,&ProcessingSystem::signal_msgToClientReady,commonClientHandler, &CommonClientHandler::slot_msgToClientFromGUI); + connect(this,&ProcessingSystem::signal_msgFromClientReady,commonClientHandler, &CommonClientHandler::slot_msgToGUIfromClient); + connect(this,&ProcessingSystem::sigLogMessage,logger,&Logger::addTextToLogger,Qt::QueuedConnection); } void ProcessingSystem::processingClientAutorization(ClientHandler *client, ClientAutorization clientAutorization) diff --git a/ServerLMS/ServerLMS/Systems/processingsystem.h b/ServerLMS/ServerLMS/Systems/processingsystem.h index 3a82519..22dc00d 100644 --- a/ServerLMS/ServerLMS/Systems/processingsystem.h +++ b/ServerLMS/ServerLMS/Systems/processingsystem.h @@ -15,6 +15,7 @@ class InstructorsAndTrainees; class Logger; class DataParser; class ClientHandler; +class CommonClientHandler; class ProcessingSystem : public QObject { @@ -22,7 +23,7 @@ class ProcessingSystem : public QObject public: explicit ProcessingSystem(ProviderDBLMS* providerDBLMS, QObject *parent = nullptr); - void initialize(DataParser* dataParser,ServerLMSWidget *server); //TODO: проверить необходимость зависимости на ServerLMS + void initialize(ServerLMSWidget *server,DataParser* dataParser,CommonClientHandler *commonClientServer,Logger *logger); void processingClientAutorization(ClientHandler *client, ClientAutorization clientAutorization); void processingClientDeAutorization(ClientHandler *client, ClientDeAutorization clientDeAutorization); void processingClientQueryToDB(ClientHandler *client, ClientQueryToDB clientQueryToDB, int id = 0, void* data = nullptr); @@ -40,6 +41,7 @@ signals: void signal_msgFromClientReady(QString login, QString text); private: + CommonClientHandler *commonClientServer; ServerLMSWidget *server; DataParser *dataParser; //InstructorsAndTraineesWidget *pInstructorsAndTrainees; diff --git a/ServerLMS/ServerLMS/Systems/updatecontroller.cpp b/ServerLMS/ServerLMS/Systems/updatecontroller.cpp index c9e5105..98f5965 100644 --- a/ServerLMS/ServerLMS/Systems/updatecontroller.cpp +++ b/ServerLMS/ServerLMS/Systems/updatecontroller.cpp @@ -2,7 +2,7 @@ UpdateController::UpdateController(QObject *parent) : QObject(parent), - server(nullptr) + commonClientHandler(nullptr) { buildPath = QDir::currentPath() + "/" + applicationFolderName; sharedDataPath = QDir::currentPath() + "/" + sharedDataFolderName; @@ -10,9 +10,9 @@ UpdateController::UpdateController(QObject *parent) : qDebug() << hashFileName; } -void UpdateController::initialize(ServerLMSWidget *server,DataParser *dataParser,AssetsManager *assetManager) +void UpdateController::initialize(CommonClientHandler *commonClientHandler,DataParser *dataParser,AssetsManager *assetManager) { - this->server = server; + this->commonClientHandler = commonClientHandler; this->dataParser = dataParser; this->assetManager = assetManager; @@ -29,21 +29,21 @@ void UpdateController::initialize(ServerLMSWidget *server,DataParser *dataParser void UpdateController::changeAssetVersion(QString versionName) { - server->slot_sendPacketToAllClients(PacketType::BUSY); + commonClientHandler->slot_sendPacketToAllClients(PacketType::BUSY); qDebug() << "UpdateController thread ID " << QThread::currentThreadId(); currentStreamingPath = assetManager->setVersion(versionName); setUpCurrentServerHash(); - server->slot_sendPacketToAllClients(PacketType::HASH_READY); - server->sendCurrentVersionToAllClient(); + commonClientHandler->slot_sendPacketToAllClients(PacketType::HASH_READY); + commonClientHandler->sendCurrentVersionToAllClient(); - server->slot_sendPacketToAllClients(PacketType::FREE); + commonClientHandler->slot_sendPacketToAllClients(PacketType::FREE); } void UpdateController::createCopyVersion(QString versionName,QString newVersionName) { - server->slot_sendPacketToAllClients(PacketType::BUSY); + commonClientHandler->slot_sendPacketToAllClients(PacketType::BUSY); assetManager->createCopyVersion(versionName,newVersionName); - server->slot_sendPacketToAllClients(PacketType::FREE); + commonClientHandler->slot_sendPacketToAllClients(PacketType::FREE); } void UpdateController::deleteAssetVersion(QString versionName) @@ -72,12 +72,12 @@ void UpdateController::showHash() void UpdateController::calculateFullHash() { - server->slot_sendPacketToAllClients(PacketType::BUSY); + commonClientHandler->slot_sendPacketToAllClients(PacketType::BUSY); auto *list = calculateHash(buildPath); saveHash(buildHashName,list); calculateSharedHash(); emit sigLogMessage("Calculate hash complete"); - server->slot_sendPacketToAllClients(PacketType::FREE); + commonClientHandler->slot_sendPacketToAllClients(PacketType::FREE); } void UpdateController::saveHash(QString fileName,QList *fileList) @@ -426,7 +426,7 @@ void UpdateController::calculateSharedHash() void UpdateController::sendNewVersionList() { - server->sendNewVersionListToAllClient(); + commonClientHandler->sendNewVersionListToAllClient(); } bool UpdateController::checkDuplicate(QString versionName) diff --git a/ServerLMS/ServerLMS/Systems/updatecontroller.h b/ServerLMS/ServerLMS/Systems/updatecontroller.h index 5bbaa02..ab7c0f1 100644 --- a/ServerLMS/ServerLMS/Systems/updatecontroller.h +++ b/ServerLMS/ServerLMS/Systems/updatecontroller.h @@ -19,6 +19,7 @@ class DataParser; class ClientHandler; class AssetsManager; class ServerLMSWidget; +class CommonClientHandler; class UpdateController : public QObject { @@ -27,7 +28,7 @@ class UpdateController : public QObject public: explicit UpdateController(QObject *parent = 0); - void initialize(ServerLMSWidget* server,DataParser *dataParser,AssetsManager *assetManager); + void initialize(CommonClientHandler* commonClientHandler,DataParser *dataParser,AssetsManager *assetManager); void compareFiles(ClientHandler* handler, QByteArray array); void showHash(); void calculateFullHash(); @@ -65,7 +66,7 @@ private: QString buildPath; QString currentStreamingPath; QString sharedDataPath; - ServerLMSWidget *server; + CommonClientHandler *commonClientHandler; DataParser *dataParser; AssetsManager *assetManager; quint64 sizeToSend; diff --git a/ServerLMS/ServerLMS/serverlmswidget.cpp b/ServerLMS/ServerLMS/serverlmswidget.cpp index 4e7ec52..c1b09d4 100644 --- a/ServerLMS/ServerLMS/serverlmswidget.cpp +++ b/ServerLMS/ServerLMS/serverlmswidget.cpp @@ -56,16 +56,19 @@ ServerLMSWidget::ServerLMSWidget(QWidget *parent) : processingSystem = new ProcessingSystem(providerDBLMS); processingSystem->moveToThread(updateThread); + dataParser = new DataParser(assetsManager,processingSystem); updateController = new UpdateController; updateController->moveToThread(updateThread); + commonClientHandler = new CommonClientHandler; + loggerThread->start(); updateThread->start(); - - processingSystem->initialize(dataParser,this); + commonClientHandler->initialize(&clientsMap,processingSystem,dataParser,logger); + processingSystem->initialize(this,dataParser,commonClientHandler,logger); logger->setTypeLog("widget"); @@ -76,7 +79,7 @@ ServerLMSWidget::ServerLMSWidget(QWidget *parent) : connect(this,&ServerLMSWidget::sigLog,logger,&Logger::addTextToLogger,Qt::AutoConnection); connect(this,&ServerLMSWidget::sigCalculateFullHash,updateController,&UpdateController::calculateFullHash,Qt::AutoConnection); - emit sigUpdateController(this,dataParser,assetsManager); + emit sigUpdateController(commonClientHandler,dataParser,assetsManager); on_btnStartServer_clicked(); first = true; @@ -97,30 +100,6 @@ void ServerLMSWidget::autorizationHandler(QString login) } } -void ServerLMSWidget::sendNewVersionListToAllClient() //Выделить в сервис отправки сервера(не конкретный клиент) -{ - foreach(int idSocket,clientsMap.keys()) - { - ClientHandler *handler = clientsMap[idSocket]; - - if (!handler->getClient()->getIsLoggedIn()) continue; - - handler->sendVersionList(); - } -} - -void ServerLMSWidget::sendCurrentVersionToAllClient() //Выделить в сервис отправки сервера(не конкретный клиент) -{ - foreach(int idSocket,clientsMap.keys()) - { - ClientHandler *handler = clientsMap[idSocket]; - - if (!handler->getClient()->getIsLoggedIn()) continue; - handler->sendVersion(); - - } -} - ServerLMSWidget::~ServerLMSWidget() { stopServer(); @@ -226,33 +205,6 @@ void ServerLMSWidget::slot_BlockAutorization(bool block) unBlockAutorization(); } -void ServerLMSWidget::slot_AuthChanged() //Выделить в сервис отправки сервера(не конкретный клиент) -{ - //Проходим все открытые сокеты - foreach(int idSocket, clientsMap.keys()) - { - //Проверяем, есть ли клиенты TYPE_GUI - if(clientsMap[idSocket]->getClient()->getTypeClient() == TypeClientAutorization::TYPE_GUI) - {//Отправляем этому клиенту обновление списков - ClientQueryToDB queryToDB; - queryToDB.typeQuery = TypeQueryToDB::TYPE_QUERY_GET_ALL_LISTS; - processingSystem->processingClientQueryToDB(clientsMap[idSocket], queryToDB); - } - } -} - -void ServerLMSWidget::slot_sendPacketToAllClients(PacketType packetType) //Выделить в сервис отправки сервера(не конкретный клиент) -{ - foreach(int idSocket, clientsMap.keys()) - { - ClientHandler *handler = clientsMap[idSocket]; - - if (!handler->getClient()->getIsLoggedIn()) continue; - - handler->sendPacketType(packetType); - } -} - void ServerLMSWidget::removeClient(int idSocket) { clientsMap.remove(idSocket); @@ -272,56 +224,12 @@ void ServerLMSWidget::slot_LanguageChanged(QString language) } -void ServerLMSWidget::slot_msgToClientFromGUI(QString login, QString text) //Выделить в сервис отправки сервера(не конкретный клиент) +void ServerLMSWidget::on_btnTaskSet_clicked() { - QString textMsg = text; + QString fullNameClient = ui->listWidget_Clients->currentItem()->text(); + QString textTask = ui->comboTasks->currentText(); - QByteArray byteArrayMsg = dataParser->xmlAnswer_message(textMsg); - - //Проходим все открытые сокеты, ищем нужный - foreach(int idSocket, clientsMap.keys()) - { - ClientHandler *handler = clientsMap[idSocket]; - if(handler->getClient()->getLogin() == login) - {//Отправляем ему - - handler->sendXmlAnswer(byteArrayMsg); - - QString peerAddress = clientsMap[idSocket]->getSocket()->peerAddress().toString(); - QString peerPort = QString::number(clientsMap[idSocket]->getSocket()->peerPort()); - - QString str = "Msg To Client [" + peerAddress + ":" + peerPort + "] : " + textMsg; - - logger->addTextToLogger(str); - break; - } - } -} - -void ServerLMSWidget::slot_msgToGUIfromClient(QString login, QString text) //Выделить в сервис отправки сервера(не конкретный клиент) -{ - QString textMsg = text; - - QByteArray byteArrayMsg = dataParser->xmlAnswer_message(textMsg, login); - - //Проходим все открытые сокеты, ищем нужный - foreach(int idSocket, clientsMap.keys()) - { - ClientHandler *handler = clientsMap[idSocket]; - if(handler->getClient()->getTypeClient() == TypeClientAutorization::TYPE_GUI) - {//Отправляем GUI-клиенту для отображения в Мессенджере - - handler->sendXmlAnswer(byteArrayMsg, PacketType::TYPE_XMLANSWER); - - QString peerAddress = clientsMap[idSocket]->getSocket()->peerAddress().toString(); - QString peerPort = QString::number(clientsMap[idSocket]->getSocket()->peerPort()); - - QString str = "Msg From Client [" + peerAddress + ":" + peerPort + "] : " + textMsg; - - logger->addTextToLogger(str); - break; - } - } + commonClientHandler->slot_sendTaskToClient(fullNameClient,textTask); } void ServerLMSWidget::slotAddToLog(QString msg) @@ -355,30 +263,6 @@ void ServerLMSWidget::on_btnStopServer_clicked() } } -void ServerLMSWidget::on_btnTaskSet_clicked() //Выделить в сервис отправки сервера(не конкретный клиент) -{ - QString fullNameClient = ui->listWidget_Clients->currentItem()->text(); - - QString textTask = ui->comboTasks->currentText(); - - QByteArray byteArrayTask = dataParser->xmlAnswer_task(textTask); - - //Проходим все открытые сокеты - foreach(int idSocket, clientsMap.keys()) - { - if(clientsMap[idSocket]->getClient()->getFullName() == fullNameClient) - {//Отправляем ему - clientsMap[idSocket]->getSocket()->write(byteArrayTask); - - QString peerAddress = clientsMap[idSocket]->getSocket()->peerAddress().toString(); - QString peerPort = QString::number(clientsMap[idSocket]->getSocket()->peerPort()); - - QString str = "Task To Client [" + peerAddress + ":" + peerPort + "] : " + textTask; - logger->addTextToLogger(str); - } - } -} - void ServerLMSWidget::changeEvent(QEvent *event) { // В случае получения события изменения языка приложения diff --git a/ServerLMS/ServerLMS/serverlmswidget.h b/ServerLMS/ServerLMS/serverlmswidget.h index 6935fab..75c60f0 100644 --- a/ServerLMS/ServerLMS/serverlmswidget.h +++ b/ServerLMS/ServerLMS/serverlmswidget.h @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -47,8 +48,7 @@ public: ~ServerLMSWidget(); void autorizationHandler(QString login); - void sendNewVersionListToAllClient(); - void sendCurrentVersionToAllClient(); + protected: // Метод получения событий @@ -59,7 +59,7 @@ signals: void sigRecognize(); void sigLog(QString log); void sigCalculateFullHash(); - void sigUpdateController(ServerLMSWidget* server,DataParser *dataParser,AssetsManager *assetManager); + void sigUpdateController(CommonClientHandler* commonClientHandler,DataParser *dataParser,AssetsManager *assetManager); QTcpSocket* sigGetSocket(); @@ -68,11 +68,6 @@ public slots: void addClient(qintptr descriptor, ClientHandler *client); void slotUpdateListClients(); void slot_BlockAutorization(bool block); - void slot_AuthChanged(); - void slot_sendPacketToAllClients(PacketType packetType); - //слот обработки сигнала о готовности нового сообщения на отправку клиенту от мессенджера - void slot_msgToClientFromGUI(QString login, QString text); - void slot_msgToGUIfromClient(QString login, QString text); void slotAddToLog(QString msg); public: @@ -127,6 +122,7 @@ private: UpdateController *updateController; AssetsManager *assetsManager; Logger *logger; + CommonClientHandler *commonClientHandler; ProviderDBLMS* providerDBLMS;