/* * chat_moc.cpp, part of VCMI engine * * Authors: listed in file AUTHORS in main folder * * License: GNU General Public License v2.0 or later * Full text of license available in license.txt file, in main folder * */ #include "StdInc.h" #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([[maybe_unused]] auto i : {GLOBAL, ROOM}) chatDocuments.push_back(new QTextDocument(this)); setChatId(GLOBAL); } Chat::~Chat() { delete ui; } void Chat::setUsername(const QString & user) { username = user; } void Chat::setSession(const QString & s) { session = s; on_chatSwitch_clicked(); } void Chat::setChannel(const QString & channel) { static const QMap chatNames{{"global", GLOBAL}, {"room", ROOM}}; setChatId(chatNames.value(channel)); } void Chat::addUser(const QString & user) { ui->listUsers->addItem(new QListWidgetItem("@" + user)); } void Chat::clearUsers() { ui->listUsers->clear(); } void Chat::chatMessage(const QString & title, const QString & channel, QString body, bool isSystem) { const QTextCharFormat regularFormat; const QString boldHtml = "%1"; const QString colorHtml = "%2"; bool meMentioned = false; bool isScrollBarBottom = (ui->chat->verticalScrollBar()->maximum() - ui->chat->verticalScrollBar()->value() < 24); static const QMap chatNames{{"global", GLOBAL}, {"room", ROOM}}; QTextDocument * doc = ui->chat->document(); if(chatNames.contains(channel)) doc = chatDocuments[chatNames.value(channel)]; QTextCursor curs(doc); 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(doc == ui->chat->document() && (meMentioned || isScrollBarBottom)) { ui->chat->ensureCursorVisible(); ui->chat->verticalScrollBar()->setValue(ui->chat->verticalScrollBar()->maximum()); } } void Chat::chatMessage(const QString & title, QString body, bool isSystem) { chatMessage(title, "", body, isSystem); } void Chat::sysMessage(QString body) { chatMessage("System", body, true); } void Chat::sendMessage() { QString msg(ui->messageEdit->text()); ui->messageEdit->clear(); emit messageSent(msg); } void Chat::on_messageEdit_returnPressed() { sendMessage(); } void Chat::on_sendButton_clicked() { sendMessage(); } void Chat::on_chatSwitch_clicked() { static const QMap chatNames{{GLOBAL, "global"}, {ROOM, "room"}}; if(chatId == GLOBAL && !session.isEmpty()) emit channelSwitch(chatNames[ROOM]); else emit channelSwitch(chatNames[GLOBAL]); } void Chat::setChatId(ChatId _chatId) { static const QMap chatNames{{GLOBAL, "Global"}, {ROOM, "Room"}}; chatId = _chatId; ui->chatSwitch->setText(chatNames[chatId] + " chat"); ui->chat->setDocument(chatDocuments[chatId]); }