1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-03-17 20:58:07 +02:00

Move chat logic to separate class

This commit is contained in:
nordsoft 2023-09-03 03:05:48 +04:00
parent d0b3567447
commit ef853ab96d
7 changed files with 396 additions and 158 deletions

View File

@ -18,6 +18,7 @@ set(launcher_SRCS
lobby/lobby.cpp
lobby/lobby_moc.cpp
lobby/lobbyroomrequest_moc.cpp
lobby/chat_moc.cpp
)
set(launcher_HEADERS
@ -39,6 +40,7 @@ set(launcher_HEADERS
lobby/lobby.h
lobby/lobby_moc.h
lobby/lobbyroomrequest_moc.h
lobby/chat_moc.h
main.h
)
@ -52,6 +54,7 @@ set(launcher_FORMS
updatedialog_moc.ui
lobby/lobby_moc.ui
lobby/lobbyroomrequest_moc.ui
lobby/chat_moc.ui
)
set(launcher_TS

141
launcher/lobby/chat_moc.cpp Normal file
View File

@ -0,0 +1,141 @@
#include "chat_moc.h"
#include "ui_chat_moc.h"
Chat::Chat(QWidget *parent) :
QWidget(parent),
ui(new Ui::Chat)
{
ui->setupUi(this);
namesCompleter.setModel(ui->listUsers->model());
namesCompleter.setCompletionMode(QCompleter::InlineCompletion);
ui->messageEdit->setCompleter(&namesCompleter);
for(auto i : {GLOBAL, ROOM})
chatDocuments.push_back(new QTextDocument(this));
ui->chat->setDocument(chatDocuments[GLOBAL]);
}
Chat::~Chat()
{
delete ui;
}
void Chat::setUsername(const QString & user)
{
username = user;
}
void Chat::setSession(const QString & s)
{
session = s;
if(session.isEmpty())
setChatId(GLOBAL);
else
setChatId(ROOM);
}
void Chat::addUser(const QString & user)
{
ui->listUsers->addItem(new QListWidgetItem("@" + user));
}
void Chat::clearUsers()
{
ui->listUsers->clear();
}
void Chat::chatMessage(const QString & title, QString body, bool isSystem)
{
const QTextCharFormat regularFormat;
const QString boldHtml = "<b>%1</b>";
const QString colorHtml = "<font color=\"%1\">%2</font>";
bool meMentioned = false;
bool isScrollBarBottom = (ui->chat->verticalScrollBar()->maximum() - ui->chat->verticalScrollBar()->value() < 24);
QTextCursor curs(ui->chat->document());
curs.movePosition(QTextCursor::End);
QString titleColor = "Olive";
if(isSystem || title == "System")
titleColor = "ForestGreen";
if(title == username)
titleColor = "Gold";
curs.insertHtml(boldHtml.arg(colorHtml.arg(titleColor, title + ": ")));
QRegularExpression mentionRe("@[\\w\\d]+");
auto subBody = body;
int mem = 0;
for(auto match = mentionRe.match(subBody); match.hasMatch(); match = mentionRe.match(subBody))
{
body.insert(mem + match.capturedEnd(), QChar(-1));
body.insert(mem + match.capturedStart(), QChar(-1));
mem += match.capturedEnd() + 2;
subBody = body.right(body.size() - mem);
}
auto pieces = body.split(QChar(-1));
for(auto & block : pieces)
{
if(block.startsWith("@"))
{
if(block == "@" + username)
{
meMentioned = true;
curs.insertHtml(boldHtml.arg(colorHtml.arg("IndianRed", block)));
}
else
curs.insertHtml(colorHtml.arg("DeepSkyBlue", block));
}
else
{
if(isSystem)
curs.insertHtml(colorHtml.arg("ForestGreen", block));
else
curs.insertText(block, regularFormat);
}
}
curs.insertText("\n", regularFormat);
if(meMentioned || isScrollBarBottom)
{
ui->chat->ensureCursorVisible();
ui->chat->verticalScrollBar()->setValue(ui->chat->verticalScrollBar()->maximum());
}
}
void Chat::sysMessage(QString body)
{
chatMessage("System", body, true);
}
void Chat::on_messageEdit_returnPressed()
{
emit messageSent(ui->messageEdit->text());
ui->messageEdit->clear();
}
void Chat::on_sendButton_clicked()
{
emit messageSent(ui->messageEdit->text());
ui->messageEdit->clear();
}
void Chat::on_chatSwitch_clicked()
{
if(chatId == GLOBAL && !session.isEmpty())
setChatId(ROOM);
else
setChatId(GLOBAL);
}
void Chat::setChatId(ChatId _chatId)
{
static const QMap<ChatId, QString> chatNames{{GLOBAL, "Global"}, {ROOM, "Room"}};
chatId = _chatId;
ui->chatSwitch->setText(chatNames[chatId] + " chat");
ui->chat->setDocument(chatDocuments[chatId]);
}

58
launcher/lobby/chat_moc.h Normal file
View File

@ -0,0 +1,58 @@
#ifndef CHAT_MOC_H
#define CHAT_MOC_H
#include <QWidget>
namespace Ui {
class Chat;
}
class Chat : public QWidget
{
Q_OBJECT
enum ChatId
{
GLOBAL = 0,
ROOM
};
QCompleter namesCompleter;
QString username, session;
ChatId chatId = GLOBAL;
QVector<QTextDocument*> chatDocuments;
private:
void setChatId(ChatId);
public:
explicit Chat(QWidget *parent = nullptr);
~Chat();
void setUsername(const QString &);
void setSession(const QString &);
void clearUsers();
void addUser(const QString & user);
void chatMessage(const QString & title, QString body, bool isSystem = false);
signals:
void messageSent(QString);
public slots:
void sysMessage(QString body);
private slots:
void on_messageEdit_returnPressed();
void on_sendButton_clicked();
void on_chatSwitch_clicked();
private:
Ui::Chat *ui;
};
#endif // CHAT_MOC_H

121
launcher/lobby/chat_moc.ui Normal file
View File

@ -0,0 +1,121 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Chat</class>
<widget class="QWidget" name="Chat">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>465</width>
<height>413</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>2</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout2">
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Users in lobby</string>
</property>
<property name="indent">
<number>-1</number>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="chatSwitch">
<property name="text">
<string>Global chat</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QListWidget" name="listUsers">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>96</height>
</size>
</property>
<property name="midLineWidth">
<number>0</number>
</property>
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::NoSelection</enum>
</property>
<property name="isWrapping" stdset="0">
<bool>true</bool>
</property>
<property name="layoutMode">
<enum>QListView::SinglePass</enum>
</property>
</widget>
</item>
<item>
<widget class="QTextBrowser" name="chat"/>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
<number>-1</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLineEdit" name="messageEdit">
<property name="text">
<string/>
</property>
<property name="placeholderText">
<string>type you message</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="sendButton">
<property name="text">
<string>send</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -34,19 +34,18 @@ Lobby::Lobby(QWidget *parent) :
{
ui->setupUi(this);
connect(&socketLobby, SIGNAL(text(QString)), this, SLOT(sysMessage(QString)));
connect(&socketLobby, SIGNAL(text(QString)), ui->chatWidget, SLOT(sysMessage(QString)));
connect(&socketLobby, SIGNAL(receive(QString)), this, SLOT(dispatchMessage(QString)));
connect(&socketLobby, SIGNAL(disconnect()), this, SLOT(onDisconnected()));
connect(ui->chatWidget, SIGNAL(messageSent(QString)), this, SLOT(onMessageSent(QString)));
QString hostString("%1:%2");
hostString = hostString.arg(QString::fromStdString(settings["launcher"]["lobbyUrl"].String()));
hostString = hostString.arg(settings["launcher"]["lobbyPort"].Integer());
namesCompleter.setModel(ui->listUsers->model());
namesCompleter.setCompletionMode(QCompleter::InlineCompletion);
ui->serverEdit->setText(hostString);
ui->userEdit->setText(QString::fromStdString(settings["launcher"]["lobbyUsername"].String()));
ui->kickButton->setVisible(false);
ui->messageEdit->setCompleter(&namesCompleter);
}
void Lobby::changeEvent(QEvent *event)
@ -112,7 +111,7 @@ void Lobby::serverCommand(const ServerCommand & command) try
{
case SRVERROR:
protocolAssert(args.size());
chatMessage("System error", args[0], true);
ui->chatWidget->chatMessage("System error", args[0], true);
if(authentificationStatus == AuthStatus::AUTH_NONE)
authentificationStatus = AuthStatus::AUTH_ERROR;
break;
@ -121,7 +120,8 @@ void Lobby::serverCommand(const ServerCommand & command) try
protocolAssert(args.size());
hostSession = args[0];
session = args[0];
sysMessage("new session started");
ui->chatWidget->setSession(session);
ui->chatWidget->sysMessage("new session started");
break;
case SESSIONS:
@ -154,6 +154,7 @@ void Lobby::serverCommand(const ServerCommand & command) try
case KICKED:
protocolAssert(args.size() == 2);
session = "";
ui->chatWidget->setSession(session);
joinStr = (command.command == JOINED ? "%1 joined to the session %2" : "%1 left session %2");
if(args[1] == username)
@ -161,8 +162,9 @@ void Lobby::serverCommand(const ServerCommand & command) try
hostModsMap.clear();
ui->buttonReady->setText("Ready");
ui->optNewGame->setChecked(true);
sysMessage(joinStr.arg("you", args[0]));
ui->chatWidget->sysMessage(joinStr.arg("you", args[0]));
session = args[0];
ui->chatWidget->setSession(session);
bool isHost = command.command == JOINED && hostSession == session;
ui->optNewGame->setEnabled(isHost);
ui->optLoadGame->setEnabled(isHost);
@ -170,7 +172,7 @@ void Lobby::serverCommand(const ServerCommand & command) try
}
else
{
sysMessage(joinStr.arg(args[1], args[0]));
ui->chatWidget->sysMessage(joinStr.arg(args[1], args[0]));
}
break;
@ -247,7 +249,7 @@ void Lobby::serverCommand(const ServerCommand & command) try
QString msg;
for(int i = 1; i < args.size(); ++i)
msg += args[i];
chatMessage(args[0], msg);
ui->chatWidget->chatMessage(args[0], msg);
break;
}
@ -261,10 +263,10 @@ void Lobby::serverCommand(const ServerCommand & command) try
amount = args[0].toInt();
protocolAssert(amount == (args.size() - 1));
ui->listUsers->clear();
ui->chatWidget->clearUsers();
for(int i = 0; i < amount; ++i)
{
ui->listUsers->addItem(new QListWidgetItem("@" + args[i + 1]));
ui->chatWidget->addUser(args[i + 1]);
}
break;
}
@ -280,7 +282,7 @@ void Lobby::serverCommand(const ServerCommand & command) try
}
default:
sysMessage("Unknown server command");
ui->chatWidget->sysMessage("Unknown server command");
}
if(authentificationStatus == AuthStatus::AUTH_ERROR)
@ -295,7 +297,7 @@ void Lobby::serverCommand(const ServerCommand & command) try
}
catch(const ProtocolError & e)
{
chatMessage("System error", e.what(), true);
ui->chatWidget->chatMessage("System error", e.what(), true);
}
void Lobby::dispatchMessage(QString txt) try
@ -319,13 +321,14 @@ void Lobby::dispatchMessage(QString txt) try
}
catch(const ProtocolError & e)
{
chatMessage("System error", e.what(), true);
ui->chatWidget->chatMessage("System error", e.what(), true);
}
void Lobby::onDisconnected()
{
authentificationStatus = AuthStatus::AUTH_NONE;
session = "";
ui->chatWidget->setSession(session);
ui->stackedWidget->setCurrentWidget(ui->sessionsPage);
ui->connectButton->setChecked(false);
ui->serverEdit->setEnabled(true);
@ -335,82 +338,12 @@ void Lobby::onDisconnected()
ui->sessionsTable->setRowCount(0);
}
void Lobby::chatMessage(QString title, QString body, bool isSystem)
{
const QTextCharFormat regularFormat;
const QString boldHtml = "<b>%1</b>";
const QString colorHtml = "<font color=\"%1\">%2</font>";
bool meMentioned = false;
bool isScrollBarBottom = (ui->chat->verticalScrollBar()->maximum() - ui->chat->verticalScrollBar()->value() < 24);
QTextCursor curs(ui->chat->document());
curs.movePosition(QTextCursor::End);
QString titleColor = "Olive";
if(isSystem || title == "System")
titleColor = "ForestGreen";
if(title == username)
titleColor = "Gold";
curs.insertHtml(boldHtml.arg(colorHtml.arg(titleColor, title + ": ")));
QRegularExpression mentionRe("@[\\w\\d]+");
auto subBody = body;
int mem = 0;
for(auto match = mentionRe.match(subBody); match.hasMatch(); match = mentionRe.match(subBody))
{
body.insert(mem + match.capturedEnd(), QChar(-1));
body.insert(mem + match.capturedStart(), QChar(-1));
mem += match.capturedEnd() + 2;
subBody = body.right(body.size() - mem);
}
auto pieces = body.split(QChar(-1));
for(auto & block : pieces)
{
if(block.startsWith("@"))
{
if(block == "@" + username)
{
meMentioned = true;
curs.insertHtml(boldHtml.arg(colorHtml.arg("IndianRed", block)));
}
else
curs.insertHtml(colorHtml.arg("DeepSkyBlue", block));
}
else
{
if(isSystem)
curs.insertHtml(colorHtml.arg("ForestGreen", block));
else
curs.insertText(block, regularFormat);
}
}
curs.insertText("\n", regularFormat);
if(meMentioned || isScrollBarBottom)
{
ui->chat->ensureCursorVisible();
ui->chat->verticalScrollBar()->setValue(ui->chat->verticalScrollBar()->maximum());
}
}
void Lobby::sysMessage(QString body)
{
chatMessage("System", body, true);
}
void Lobby::protocolAssert(bool expr)
{
if(!expr)
throw ProtocolError("Protocol error");
}
void Lobby::on_messageEdit_returnPressed()
{
socketLobby.send(ProtocolStrings[MESSAGE].arg(ui->messageEdit->text()));
ui->messageEdit->clear();
}
void Lobby::on_connectButton_toggled(bool checked)
{
if(checked)
@ -418,6 +351,7 @@ void Lobby::on_connectButton_toggled(bool checked)
ui->connectButton->setText(tr("Disconnect"));
authentificationStatus = AuthStatus::AUTH_NONE;
username = ui->userEdit->text();
ui->chatWidget->setUsername(username);
const int connectionTimeout = settings["launcher"]["connectionTimeout"].Integer();
auto serverStrings = ui->serverEdit->text().split(":");
@ -438,9 +372,9 @@ void Lobby::on_connectButton_toggled(bool checked)
ui->serverEdit->setEnabled(false);
ui->userEdit->setEnabled(false);
sysMessage("Connecting to " + serverUrl + ":" + QString::number(serverPort));
ui->chatWidget->sysMessage("Connecting to " + serverUrl + ":" + QString::number(serverPort));
//show text immediately
ui->chat->repaint();
ui->chatWidget->repaint();
qApp->processEvents();
socketLobby.connectServer(serverUrl, serverPort, username, connectionTimeout);
@ -450,7 +384,7 @@ void Lobby::on_connectButton_toggled(bool checked)
ui->connectButton->setText(tr("Connect"));
ui->serverEdit->setEnabled(true);
ui->userEdit->setEnabled(true);
ui->listUsers->clear();
ui->chatWidget->clearUsers();
hostModsMap.clear();
updateMods();
socketLobby.disconnectServer();
@ -613,9 +547,7 @@ void Lobby::on_optLoadGame_toggled(bool checked)
}
}
void Lobby::on_chatSwither_clicked()
void Lobby::onMessageSent(QString message)
{
isGlobalChat = session.isEmpty() ? true : !isGlobalChat;
ui->chatSwither->setText(isGlobalChat ? tr("Global chat") : tr("Room chat"));
socketLobby.send(ProtocolStrings[MESSAGE].arg(message));
}

View File

@ -33,12 +33,9 @@ public slots:
void updateMods();
private slots:
void on_messageEdit_returnPressed();
void chatMessage(QString title, QString body, bool isSystem = false);
void sysMessage(QString body);
void dispatchMessage(QString);
void serverCommand(const ServerCommand &);
void onMessageSent(QString message);
void on_connectButton_toggled(bool checked);
@ -64,8 +61,6 @@ private slots:
void on_optLoadGame_toggled(bool checked);
void on_chatSwither_clicked();
private:
QString serverUrl;
int serverPort;
@ -78,7 +73,6 @@ private:
QString username;
QStringList gameArgs;
QMap<QString, QString> hostModsMap;
QCompleter namesCompleter;
enum AuthStatus
{
@ -86,9 +80,6 @@ private:
};
AuthStatus authentificationStatus = AUTH_NONE;
bool isGlobalChat = true;
std::chrono::time_point<std::chrono::high_resolution_clock> lastTimePointScrollBar;
private:
QMap<QString, QString> buildModsMap() const;

View File

@ -14,6 +14,9 @@
<string/>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="bottomMargin">
<number>0</number>
</property>
<item row="0" column="3">
<widget class="QLabel" name="label_4">
<property name="sizePolicy">
@ -62,77 +65,31 @@
</item>
<item row="1" column="0" colspan="6">
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
<number>-1</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>10</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Users in lobby</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="chatSwither">
<property name="text">
<string>Global chat</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QListWidget" name="listUsers">
<widget class="Chat" name="chatWidget" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Maximum">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>96</height>
</size>
</property>
<property name="midLineWidth">
<number>0</number>
</property>
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::NoSelection</enum>
</property>
<property name="isWrapping" stdset="0">
<bool>true</bool>
</property>
<property name="layoutMode">
<enum>QListView::SinglePass</enum>
</property>
</widget>
</item>
<item>
<widget class="QTextBrowser" name="chat"/>
</item>
<item>
<widget class="QLineEdit" name="messageEdit">
<property name="text">
<string/>
</property>
<property name="placeholderText">
<string>type you message</string>
</property>
</widget>
</item>
</layout>
@ -150,6 +107,18 @@
</property>
<widget class="QWidget" name="sessionsPage">
<layout class="QGridLayout" name="gridLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item row="1" column="0">
<widget class="QPushButton" name="newButton">
<property name="enabled">
@ -220,6 +189,21 @@
</widget>
<widget class="QWidget" name="roomPage">
<layout class="QGridLayout" name="gridLayout_3">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<property name="verticalSpacing">
<number>-1</number>
</property>
<item row="1" column="1">
<widget class="QPushButton" name="kickButton">
<property name="text">
@ -314,6 +298,14 @@
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>Chat</class>
<extends>QWidget</extends>
<header>lobby/chat_moc.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>