#include "chatroom.h" #include "ui_chatroom.h" list sendQueue; std::mutex myMutex; std::mutex msgMutex; unique_lock* msgLock; std::condition_variable msgListNotEmpty; Chatroom::Chatroom(QWidget *parent) : QMainWindow(parent), ui(new Ui::Chatroom) { ui->setupUi(this); QList chatSizes; QList splitSizes; chatSizes.push_front(ui->chatText->height()); chatSizes.push_front(100); splitSizes.push_front(ui->chatWindow->width()); splitSizes.push_front(200); ui->chatSplitter->setSizes(chatSizes); ui->windowSplitter->setSizes(splitSizes); connected = false; msgLock = new unique_lock(msgMutex,std::defer_lock); send = NULL; recv = NULL; connect(ui->actionConnect,SIGNAL(triggered()),this,SLOT(startSession())); connect(ui->actionExit,SIGNAL(triggered()),this,SLOT(finish())); connect(this,SIGNAL(threadsFinished(bool)),this,SLOT(finishThreads(bool))); connect(ui->inputText,SIGNAL(msgReady()),this,SLOT(sendMsg())); connect(ui->actionDisconnect,SIGNAL(triggered()),this,SLOT(disconnectChatroom())); connect(ui->sendButton,SIGNAL(clicked()),this,SLOT(sendMsg())); connect(this,SIGNAL(messagesToPrint()),this,SLOT(printMsg())); } void sendThread(Socket* s, Chatroom* chat) { string send; while(chat->getConnected()) { while(sendQueue.empty()) { msgLock->lock(); msgListNotEmpty.wait(*msgLock); if(!chat->getConnected()) { return; } msgLock->unlock(); } msgLock->lock(); send = sendQueue.front().toStdString(); sendQueue.pop_front(); try { if(send[0] == '@') { send = '1' + send; } else { send = '0' + send; } *s << send; msgLock->unlock(); send = send.substr(1); if(send == "/disconnect" || send == "/exit") { break; } chat->putMsgToPrintQueue(chat->getNickname().toStdString().append(": ").append(send)); } catch(SocketException& e) { cout << e.description() << endl; } } cout << "sendThread finished" << endl; } void recvThread(Socket* s, Chatroom* chat) { string recv; while(true) { try { *s >> recv; if(recv[0] == '1') { recv = recv.substr(1); chat->relayMsg(recv); continue; } else if(recv[0] == '0') { recv = recv.substr(1); } } catch(SocketException &e) { chat->setConnected(false); cout << e.description() << endl; msgListNotEmpty.notify_all(); emit chat->threadsFinished(false); break; } if(recv == "DISC_OK") { cout << "Disconnecting" << endl; chat->setConnected(false); msgListNotEmpty.notify_all(); emit chat->threadsFinished(false); break; } else if(recv == "EXIT_OK") { cout << "Exiting" << endl; chat->setConnected(false); msgListNotEmpty.notify_all(); emit chat->threadsFinished(true); break; } else { chat->putMsgToPrintQueue(recv); } } cout << "recvThread finished" << endl; } bool Chatroom::getConnected() { myMutex.lock(); bool val = connected; myMutex.unlock(); return val; } void Chatroom::setConnected(bool status) { myMutex.lock(); connected = status; myMutex.unlock(); } void Chatroom::putMsgToPrintQueue(string &msg) { printQueue.push_back(msg); emit messagesToPrint(); } string Chatroom::getSender(string& msg) { return msg.substr(5,msg.find(':')-5); } void Chatroom::relayMsg(string& msg) { string sender = getSender(msg); map::iterator it = activeChats.begin(); if(activeChats.find(sender) == activeChats.end()) { //LAUNCH new windowchat } it = activeChats.find(sender); it->second.printMsg(msg); } void Chatroom::printMsg() { while(!printQueue.empty()) { string msg = printQueue.front(); ui->chatText->printMsg(msg); printQueue.pop_front(); } } void Chatroom::putMsgToSendQueue(QString& msg) { msgMutex.lock(); sendQueue.push_back(msg); msgMutex.unlock(); msgListNotEmpty.notify_all(); } void Chatroom::setNickname(QString nick) { nickname = nick; } QString Chatroom::getNickname() { return nickname; } void Chatroom::startSession() { LoginScreen login(&s,this); login.exec(); int result = login.result(); if(result == QDialog::Accepted) { ui->inputText->setReadOnly(false); } else if(result == QDialog::Rejected) { return; } connected = true; ui->chatText->printServerMsg("Connected to chatroom"); recv = new std::thread(recvThread,&s,this); send = new std::thread(sendThread,&s,this); } void Chatroom::sendMsg() { QString msg = ui->inputText->toPlainText(); ui->inputText->clear(); putMsgToSendQueue(msg); } void Chatroom::finish() { if(recv == NULL && send == NULL) { ui->inputText->setReadOnly(true); ui->chatText->printServerMsg("Disconnected"); this->close(); } msgMutex.lock(); sendQueue.clear(); sendQueue.push_back("/exit"); msgMutex.unlock(); msgListNotEmpty.notify_all(); } void Chatroom::disconnectChatroom() { msgMutex.lock(); sendQueue.clear(); sendQueue.push_back("/disconnect"); msgMutex.unlock(); msgListNotEmpty.notify_all(); } void Chatroom::finishThreads(bool exit) { myMutex.lock(); ui->inputText->setReadOnly(true); recv->join(); send->join(); myMutex.unlock(); ui->chatText->printServerMsg("Disconnected"); send = NULL; recv = NULL; if(exit) { this->close(); } } Chatroom::~Chatroom() { delete msgLock; delete recv; delete send; delete ui; }