diff --git a/cockatrice/src/chatview.cpp b/cockatrice/src/chatview.cpp index 4863b2c1..87548832 100644 --- a/cockatrice/src/chatview.cpp +++ b/cockatrice/src/chatview.cpp @@ -53,14 +53,15 @@ QTextCursor ChatView::prepareBlock(bool same) QTextCursor cursor(document()->lastBlock()); cursor.movePosition(QTextCursor::End); - if (!same) { + if (same) { + cursor.insertHtml("
"); + } else { QTextBlockFormat blockFormat; if ((evenNumber = !evenNumber)) blockFormat.setBackground(palette().alternateBase()); blockFormat.setBottomMargin(4); cursor.insertBlock(blockFormat); - } else - cursor.insertHtml("
"); + } return cursor; } @@ -120,6 +121,7 @@ void ChatView::appendMessage(QString message, QString sender, UserLevelFlags use QTextCursor cursor = prepareBlock(sameSender); lastSender = sender; + // timestamp if (showTimestamps && !sameSender) { QTextCharFormat timeFormat; timeFormat.setForeground(QColor(SERVER_MESSAGE_COLOR)); @@ -128,7 +130,8 @@ void ChatView::appendMessage(QString message, QString sender, UserLevelFlags use cursor.setCharFormat(timeFormat); cursor.insertText(QDateTime::currentDateTime().toString("[hh:mm:ss] ")); } - + + // nickname QTextCharFormat senderFormat; if (tabSupervisor && tabSupervisor->getUserInfo() && (sender == QString::fromStdString(tabSupervisor->getUserInfo()->name()))) { senderFormat.setForeground(QBrush(getCustomMentionColor())); @@ -140,7 +143,9 @@ void ChatView::appendMessage(QString message, QString sender, UserLevelFlags use } senderFormat.setAnchor(true); senderFormat.setAnchorHref("user://" + QString::number(userLevel) + "_" + sender); - if (!sameSender) { + if (sameSender) { + cursor.insertText(" "); + } else { if (!sender.isEmpty() && tabSupervisor->getUserListsTab()) { const int pixelSize = QFontInfo(cursor.charFormat().font()).pixelSize(); QMap buddyList = tabSupervisor->getUserListsTab()->getBuddyList()->getUsers(); @@ -151,288 +156,38 @@ void ChatView::appendMessage(QString message, QString sender, UserLevelFlags use if (!sender.isEmpty()) sender.append(": "); cursor.insertText(sender); - } else - cursor.insertText(" "); - + } + QTextCharFormat messageFormat; if (sender.isEmpty()) { messageFormat.setForeground(Qt::darkGreen); messageFormat.setFontWeight(QFont::Bold); } cursor.setCharFormat(messageFormat); - - int index = -1, bracketFirstIndex = -1, mentionFirstIndex = -1, urlFirstIndex = -1, highlightWordFirstIndex = -1; + bool mentionEnabled = settingsCache->getChatMention(); - const QRegExp urlStarter = QRegExp("https?://|\\bwww\\."); - const QRegExp phraseEnder = QRegExp("\\s"); - const QRegExp notALetterOrNumber = QRegExp("[^a-zA-Z0-9]"); - const QStringList highlightedWords = settingsCache->getHighlightWords(); - + // parse the message while (message.size()) { - bracketFirstIndex = message.indexOf('['); - mentionFirstIndex = message.indexOf('@'); - urlFirstIndex = message.indexOf(urlStarter); - highlightWordFirstIndex = -1; - - foreach (QString word, message.simplified().split(" ")) + QChar c = message.at(0); + switch(c.toLatin1()) { - if (highlightedWords.contains(word, Qt::CaseInsensitive)) - { - highlightWordFirstIndex = message.indexOf(word); + case '[': + checkTag(cursor, message); break; - } - } - - bool startsWithBracket = (bracketFirstIndex != -1); - bool startsWithAtSymbol = (mentionFirstIndex != -1); - bool startsWithUrl = (urlFirstIndex != -1); - bool startsWithHighlightWord = (highlightWordFirstIndex != -1); - - - if (!startsWithBracket && !startsWithAtSymbol && !startsWithUrl && !startsWithHighlightWord) - { - // No functions need to be run. Send message as normal - cursor.insertText(message); - break; - } - else if (startsWithBracket && !startsWithAtSymbol && !startsWithUrl && !startsWithHighlightWord) - { - // Contains a bracket - index = bracketFirstIndex; - } - else if (!startsWithBracket && startsWithAtSymbol && !startsWithUrl && !startsWithHighlightWord) - { - // Contains an @ symbol - index = mentionFirstIndex; - } - else if (!startsWithBracket && !startsWithAtSymbol && startsWithUrl && !startsWithHighlightWord) - { - // Contains URL stuff (http or www.) - index = urlFirstIndex; - } - else if (!startsWithBracket && !startsWithAtSymbol && !startsWithUrl && startsWithHighlightWord) - { - // Contains a word the user wants highlighted - index = highlightWordFirstIndex; - } - else if (startsWithBracket && startsWithAtSymbol && !startsWithUrl && !startsWithHighlightWord) - { - // Contains both a bracket and an @ symbol - index = std::min(bracketFirstIndex, mentionFirstIndex); - } - else if (startsWithBracket && !startsWithAtSymbol && startsWithUrl && !startsWithHighlightWord) - { - // Contains both a bracket and URL stuff - index = std::min(bracketFirstIndex, urlFirstIndex); - } - else if (startsWithBracket && !startsWithAtSymbol && !startsWithUrl && startsWithHighlightWord) - { - // Contains both a bracket and a word the user wants highlighted - index = std::min(bracketFirstIndex, highlightWordFirstIndex); - } - else if (!startsWithBracket && startsWithAtSymbol && startsWithUrl && !startsWithHighlightWord) - { - // Contains both an @ symbol and URL stuff - index = std::min(mentionFirstIndex, urlFirstIndex); - } - else if (!startsWithBracket && startsWithAtSymbol && !startsWithUrl && startsWithHighlightWord) - { - // Contains both an @ symbol and a word the user wants highlighted - index = std::min(mentionFirstIndex, highlightWordFirstIndex); - } - else if (!startsWithBracket && !startsWithAtSymbol && startsWithUrl && startsWithHighlightWord) - { - // Contains both URL stuff and a word the user wants highlighted - index = std::min(urlFirstIndex, highlightWordFirstIndex); - } - else if (!startsWithBracket && startsWithAtSymbol && startsWithUrl && startsWithHighlightWord) - { - // Contains an @ symbol, URL stuff, and a word the user wants highlighted - index = std::min(mentionFirstIndex, std::min(urlFirstIndex, highlightWordFirstIndex)); - } - else if (startsWithBracket && !startsWithAtSymbol && startsWithUrl && startsWithHighlightWord) - { - // Contains a bracket, URL stuff, and a word the user wants highlighted - index = std::min(bracketFirstIndex, std::min(urlFirstIndex, highlightWordFirstIndex)); - } - else if (startsWithBracket && startsWithAtSymbol && !startsWithUrl && startsWithHighlightWord) - { - // Contains a bracket, an @ symbol, and a word the user wants highlighted - index = std::min(bracketFirstIndex, std::min(mentionFirstIndex, highlightWordFirstIndex)); - } - else if (startsWithBracket && startsWithAtSymbol && startsWithUrl && !startsWithHighlightWord) - { - // Contains a bracket, an @ symbol, and URL stuff - index = std::min(bracketFirstIndex, std::min(mentionFirstIndex, urlFirstIndex)); - } - else if (startsWithBracket && startsWithAtSymbol && startsWithUrl && startsWithHighlightWord) - { - // Contains a bracket, an @ symbol, URL stuff, and a word the user wants highlighted - index = std::min(highlightWordFirstIndex, std::min(bracketFirstIndex, std::min(mentionFirstIndex, urlFirstIndex))); - } - - if (index > 0) - { - cursor.insertText(message.left(index), defaultFormat); - message = message.mid(index); - } - - if (index == bracketFirstIndex) // The message now starts with a bracket ->> [ <<- that symbol - { - if (message.startsWith("[card]")) - { - message = message.mid(6); - int closeTagIndex = message.indexOf("[/card]"); - QString cardName = message.left(closeTagIndex); - if (closeTagIndex == -1) - message.clear(); + case '@': + if(mentionEnabled) + checkMention(cursor, message, sender, userLevel); else - message = message.mid(closeTagIndex + 7); - - appendCardTag(cursor, cardName); - } - else if (message.startsWith("[[")) - { - message = message.mid(2); - int closeTagIndex = message.indexOf("]]"); - QString cardName = message.left(closeTagIndex); - if (closeTagIndex == -1) - message.clear(); - else - message = message.mid(closeTagIndex + 2); - - appendCardTag(cursor, cardName); - } - else if (message.startsWith("[url]")) - { - message = message.mid(5); - int closeTagIndex = message.indexOf("[/url]"); - QString url = message.left(closeTagIndex); - if (closeTagIndex == -1) - message.clear(); - else - message = message.mid(closeTagIndex + 6); - - appendUrlTag(cursor, url); - } - else - { - // Not a valid tag - cursor.insertText("[", defaultFormat); + checkWord(cursor, message); + break; + case ' ': + cursor.insertText(" ", defaultFormat); message = message.mid(1); - } - } - else if (index == urlFirstIndex) // The message now starts with either: www. , http:// , or https:// - { - int urlEndIndex = message.indexOf(phraseEnder, 0); - if (urlEndIndex == -1) - urlEndIndex = message.size(); - QString urlText = message.left(urlEndIndex); - QUrl qUrl(urlText); - if (qUrl.isValid()) - appendUrlTag(cursor, urlText); - else - cursor.insertText(urlText); - if (urlEndIndex == -1) - message.clear(); - else - message = message.mid(urlEndIndex); - } - else if (index == mentionFirstIndex) - { - int firstSpace = message.indexOf(" "); - QString fullMentionUpToSpaceOrEnd = (firstSpace == -1) ? message.mid(1) : message.mid(1, firstSpace - 1); - QString mentionIntact = fullMentionUpToSpaceOrEnd; - - if ((!mentionEnabled && !isModeratorSendingGlobal(userLevel, fullMentionUpToSpaceOrEnd)) || tabSupervisor->getIsLocalGame()) - { - cursor.insertText("@"); - message = message.mid(1); - } - else - { - QMap userList = tabSupervisor->getUserListsTab()->getAllUsersList()->getUsers(); - - do - { - if (isFullMentionAValidUser(userList, fullMentionUpToSpaceOrEnd)) // Is there a user online named this? - { - if (userName.toLower() == fullMentionUpToSpaceOrEnd.toLower()) // Is this user you? - { - // You have received a valid mention!! - mentionFormat.setBackground(QBrush(getCustomMentionColor())); - mentionFormat.setForeground(settingsCache->getChatMentionForeground() ? QBrush(Qt::white) : QBrush(Qt::black)); - cursor.insertText(mention, mentionFormat); - message = message.mid(mention.size()); - QApplication::alert(this); - if (settingsCache->getShowMentionPopup() && shouldShowSystemPopup()) - { - QString ref = sender.left(sender.length() - 2); - showSystemPopup(ref); - } - } - else - { - QString correctUserName = getNameFromUserList(userList, fullMentionUpToSpaceOrEnd); - UserListTWI *vlu = userList.value(correctUserName); - mentionFormatOtherUser.setAnchorHref("user://" + QString::number(vlu->getUserInfo().user_level()) + "_" + correctUserName); - cursor.insertText("@" + correctUserName, mentionFormatOtherUser); - - message = message.mid(correctUserName.size() + 1); - } - - cursor.setCharFormat(defaultFormat); - break; - } - else if (isModeratorSendingGlobal(userLevel, fullMentionUpToSpaceOrEnd)) - { - // Moderator Sending Global Message - mentionFormat.setBackground(QBrush(getCustomMentionColor())); - mentionFormat.setForeground(settingsCache->getChatMentionForeground() ? QBrush(Qt::white) : QBrush(Qt::black)); - cursor.insertText("@" + fullMentionUpToSpaceOrEnd, mentionFormat); - message = message.mid(fullMentionUpToSpaceOrEnd.size() + 1); - QApplication::alert(this); - if (settingsCache->getShowMentionPopup() && shouldShowSystemPopup()) - { - QString ref = sender.left(sender.length() - 2); - showSystemPopup(ref); - } - - cursor.setCharFormat(defaultFormat); - break; - } - else if (fullMentionUpToSpaceOrEnd.right(1).indexOf(notALetterOrNumber) == -1 || fullMentionUpToSpaceOrEnd.size() < 2) - { - cursor.insertText("@" + mentionIntact, defaultFormat); - message = message.mid(mentionIntact.size() + 1); - cursor.setCharFormat(defaultFormat); - break; - } - else - { - fullMentionUpToSpaceOrEnd.chop(1); - } - } - while (fullMentionUpToSpaceOrEnd.size()); - } - } - else if (index == highlightWordFirstIndex) - { - // You have received a valid mention of custom word!! - int firstSpace = (message.indexOf(" ") == -1 ? message.size() : message.indexOf(" ")); - mentionFormat.setBackground(QBrush(getCustomMentionColor())); - mentionFormat.setForeground(settingsCache->getChatMentionForeground() ? QBrush(Qt::white) : QBrush(Qt::black)); - cursor.insertText(message.mid(0, firstSpace), mentionFormat); - cursor.setCharFormat(defaultFormat); - message = message.mid(firstSpace); - QApplication::alert(this); - } - else - { - // Not certain when this would ever be reached, but just incase lets skip the character - cursor.insertText(message.mid(0), defaultFormat); - message = message.mid(1); + break; + default: + checkWord(cursor, message); + break; } } @@ -440,6 +195,173 @@ void ChatView::appendMessage(QString message, QString sender, UserLevelFlags use verticalScrollBar()->setValue(verticalScrollBar()->maximum()); } +void ChatView::checkTag(QTextCursor &cursor, QString &message) +{ + if (message.startsWith("[card]")) + { + message = message.mid(6); + int closeTagIndex = message.indexOf("[/card]"); + QString cardName = message.left(closeTagIndex); + if (closeTagIndex == -1) + message.clear(); + else + message = message.mid(closeTagIndex + 7); + + appendCardTag(cursor, cardName); + return; + } + + if (message.startsWith("[[")) + { + message = message.mid(2); + int closeTagIndex = message.indexOf("]]"); + QString cardName = message.left(closeTagIndex); + if (closeTagIndex == -1) + message.clear(); + else + message = message.mid(closeTagIndex + 2); + + appendCardTag(cursor, cardName); + return; + } + + if (message.startsWith("[url]")) + { + message = message.mid(5); + int closeTagIndex = message.indexOf("[/url]"); + QString url = message.left(closeTagIndex); + if (closeTagIndex == -1) + message.clear(); + else + message = message.mid(closeTagIndex + 6); + + appendUrlTag(cursor, url); + return; + } + + // no valid tag found + checkWord(cursor, message); +} + +void ChatView::checkMention(QTextCursor &cursor, QString &message, QString &sender, UserLevelFlags userLevel) +{ + const QRegExp notALetterOrNumber = QRegExp("[^a-zA-Z0-9]"); + + int firstSpace = message.indexOf(' '); + QString fullMentionUpToSpaceOrEnd = (firstSpace == -1) ? message.mid(1) : message.mid(1, firstSpace - 1); + QString mentionIntact = fullMentionUpToSpaceOrEnd; + + QMap userList = tabSupervisor->getUserListsTab()->getAllUsersList()->getUsers(); + + while (fullMentionUpToSpaceOrEnd.size()) + { + if (isFullMentionAValidUser(userList, fullMentionUpToSpaceOrEnd)) // Is there a user online named this? + { + if (userName.toLower() == fullMentionUpToSpaceOrEnd.toLower()) // Is this user you? + { + // You have received a valid mention!! + mentionFormat.setBackground(QBrush(getCustomMentionColor())); + mentionFormat.setForeground(settingsCache->getChatMentionForeground() ? QBrush(Qt::white) : QBrush(Qt::black)); + cursor.insertText(mention, mentionFormat); + message = message.mid(mention.size()); + QApplication::alert(this); + if (settingsCache->getShowMentionPopup() && shouldShowSystemPopup()) + { + QString ref = sender.left(sender.length() - 2); + showSystemPopup(ref); + } + } else { + QString correctUserName = getNameFromUserList(userList, fullMentionUpToSpaceOrEnd); + UserListTWI *vlu = userList.value(correctUserName); + mentionFormatOtherUser.setAnchorHref("user://" + QString::number(vlu->getUserInfo().user_level()) + "_" + correctUserName); + cursor.insertText("@" + correctUserName, mentionFormatOtherUser); + + message = message.mid(correctUserName.size() + 1); + } + + cursor.setCharFormat(defaultFormat); + return; + } + + if (isModeratorSendingGlobal(userLevel, fullMentionUpToSpaceOrEnd)) { + // Moderator Sending Global Message + mentionFormat.setBackground(QBrush(getCustomMentionColor())); + mentionFormat.setForeground(settingsCache->getChatMentionForeground() ? QBrush(Qt::white) : QBrush(Qt::black)); + cursor.insertText("@" + fullMentionUpToSpaceOrEnd, mentionFormat); + message = message.mid(fullMentionUpToSpaceOrEnd.size() + 1); + QApplication::alert(this); + if (settingsCache->getShowMentionPopup() && shouldShowSystemPopup()) + { + QString ref = sender.left(sender.length() - 2); + showSystemPopup(ref); + } + + cursor.setCharFormat(defaultFormat); + return; + } + + if (fullMentionUpToSpaceOrEnd.right(1).indexOf(notALetterOrNumber) == -1 || fullMentionUpToSpaceOrEnd.size() < 2) + { + cursor.insertText("@" + mentionIntact, defaultFormat); + message = message.mid(mentionIntact.size() + 1); + cursor.setCharFormat(defaultFormat); + return; + } + + fullMentionUpToSpaceOrEnd.chop(1); + } + + // no valid mention found + checkWord(cursor, message); +} + +void ChatView::checkWord(QTextCursor &cursor, QString &message) +{ + // extract the first word + int firstSpace = message.indexOf(' '); + QString fullWordUpToSpaceOrEnd; + if(firstSpace == -1) + { + fullWordUpToSpaceOrEnd = message; + message.clear(); + } else { + fullWordUpToSpaceOrEnd = message.mid(0, firstSpace); + message = message.mid(firstSpace); + } + + // check urls + if (fullWordUpToSpaceOrEnd.startsWith("http://", Qt::CaseInsensitive) || + fullWordUpToSpaceOrEnd.startsWith("https://", Qt::CaseInsensitive) || + fullWordUpToSpaceOrEnd.startsWith("www.", Qt::CaseInsensitive)) + { + QUrl qUrl(fullWordUpToSpaceOrEnd); + if (qUrl.isValid()) + { + appendUrlTag(cursor, fullWordUpToSpaceOrEnd); + return; + } + } + + // check word mentions + const QStringList highlightedWords = settingsCache->getHighlightWords(); + foreach (QString word, highlightedWords) + { + if (fullWordUpToSpaceOrEnd.compare(word, Qt::CaseInsensitive) == 0) + { + // You have received a valid mention of custom word!! + mentionFormat.setBackground(QBrush(getCustomMentionColor())); + mentionFormat.setForeground(settingsCache->getChatMentionForeground() ? QBrush(Qt::white) : QBrush(Qt::black)); + cursor.insertText(fullWordUpToSpaceOrEnd, mentionFormat); + cursor.setCharFormat(defaultFormat); + QApplication::alert(this); + return; + } + } + + // not a special word; just print it + cursor.insertText(fullWordUpToSpaceOrEnd, defaultFormat); +} + bool ChatView::isModeratorSendingGlobal(QFlags userLevelFlag, QString message) { int userLevel = QString::number(userLevelFlag).toInt(); diff --git a/cockatrice/src/chatview.h b/cockatrice/src/chatview.h index 17d73d72..144097f0 100644 --- a/cockatrice/src/chatview.h +++ b/cockatrice/src/chatview.h @@ -44,6 +44,9 @@ private: bool shouldShowSystemPopup(); void showSystemPopup(QString &sender); bool isModeratorSendingGlobal(QFlags userLevelFlag, QString message); + void checkTag(QTextCursor &cursor, QString &message); + void checkMention(QTextCursor &cursor, QString &message, QString &sender, UserLevelFlags userLevel); + void checkWord(QTextCursor &cursor, QString &message); private slots: void openLink(const QUrl &link); void actMessageClicked();