Rework message parser

This commit is contained in:
Fabio Bas 2015-07-12 23:56:32 +02:00
parent 97f298452e
commit 87c70466a4
2 changed files with 199 additions and 274 deletions

View file

@ -53,14 +53,15 @@ QTextCursor ChatView::prepareBlock(bool same)
QTextCursor cursor(document()->lastBlock());
cursor.movePosition(QTextCursor::End);
if (!same) {
if (same) {
cursor.insertHtml("<br>");
} else {
QTextBlockFormat blockFormat;
if ((evenNumber = !evenNumber))
blockFormat.setBackground(palette().alternateBase());
blockFormat.setBottomMargin(4);
cursor.insertBlock(blockFormat);
} else
cursor.insertHtml("<br>");
}
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<QString, UserListTWI *> 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<QString, UserListTWI *> 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<QString, UserListTWI *> 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<ServerInfo_User::UserLevelFlag> userLevelFlag, QString message)
{
int userLevel = QString::number(userLevelFlag).toInt();

View file

@ -44,6 +44,9 @@ private:
bool shouldShowSystemPopup();
void showSystemPopup(QString &sender);
bool isModeratorSendingGlobal(QFlags<ServerInfo_User::UserLevelFlag> 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();