diff --git a/cockatrice/cockatrice.qrc b/cockatrice/cockatrice.qrc index 08e2a43ac..e982f5847 100644 --- a/cockatrice/cockatrice.qrc +++ b/cockatrice/cockatrice.qrc @@ -322,6 +322,10 @@ resources/userlevels/registered.svg resources/userlevels/moderator.svg resources/userlevels/admin.svg + + resources/userlevels/registered_buddy.svg + resources/userlevels/admin_buddy.svg + resources/userlevels/moderator_buddy.svg resources/news/exclamation_mark.svg resources/news/question_mark.svg diff --git a/cockatrice/resources/userlevels/admin_buddy.svg b/cockatrice/resources/userlevels/admin_buddy.svg new file mode 100644 index 000000000..0d4defb53 --- /dev/null +++ b/cockatrice/resources/userlevels/admin_buddy.svg @@ -0,0 +1,125 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cockatrice/resources/userlevels/moderator_buddy.svg b/cockatrice/resources/userlevels/moderator_buddy.svg new file mode 100644 index 000000000..677c6e13a --- /dev/null +++ b/cockatrice/resources/userlevels/moderator_buddy.svg @@ -0,0 +1,147 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cockatrice/resources/userlevels/registered_buddy.svg b/cockatrice/resources/userlevels/registered_buddy.svg new file mode 100644 index 000000000..14fcd596c --- /dev/null +++ b/cockatrice/resources/userlevels/registered_buddy.svg @@ -0,0 +1,115 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cockatrice/src/chatview.cpp b/cockatrice/src/chatview.cpp index f93980e83..098808f5e 100644 --- a/cockatrice/src/chatview.cpp +++ b/cockatrice/src/chatview.cpp @@ -10,8 +10,10 @@ #include "pixmapgenerator.h" #include "settingscache.h" #include "main.h" +#include "userlist.h" #include "tab_userlists.h" +const QColor OTHER_USER_MENTION_COLOR = QColor(145, 210, 255); // light blue const QColor MENTION_COLOR = QColor(190, 25, 85); // maroon const QColor OTHER_USER_COLOR = QColor(0, 65, 255); // dark blue @@ -21,7 +23,7 @@ ChatView::ChatView(const TabSupervisor *_tabSupervisor, TabGame *_game, bool _sh document()->setDefaultStyleSheet("a { text-decoration: none; color: blue; }"); userContextMenu = new UserContextMenu(tabSupervisor, this, game); connect(userContextMenu, SIGNAL(openMessageDialog(QString, bool)), this, SIGNAL(openMessageDialog(QString, bool))); - + userName = QString::fromStdString(tabSupervisor->getUserInfo()->name()); mention = "@" + userName.toLower(); @@ -31,6 +33,7 @@ ChatView::ChatView(const TabSupervisor *_tabSupervisor, TabGame *_game, bool _sh mentionFormatOtherUser.setFontWeight(QFont::Bold); mentionFormatOtherUser.setForeground(Qt::blue); + mentionFormatOtherUser.setBackground(QBrush(OTHER_USER_MENTION_COLOR)); mentionFormatOtherUser.setAnchor(true); viewport()->setCursor(Qt::IBeamCursor); @@ -48,7 +51,7 @@ void ChatView::retranslateUi() QTextCursor ChatView::prepareBlock(bool same) { lastSender.clear(); - + QTextCursor cursor(document()->lastBlock()); cursor.movePosition(QTextCursor::End); if (!same) { @@ -59,7 +62,7 @@ QTextCursor ChatView::prepareBlock(bool same) cursor.insertBlock(blockFormat); } else cursor.insertHtml("
"); - + return cursor; } @@ -78,7 +81,7 @@ void ChatView::appendCardTag(QTextCursor &cursor, const QString &cardName) anchorFormat.setForeground(Qt::blue); anchorFormat.setAnchor(true); anchorFormat.setAnchorHref("card://" + cardName); - + cursor.setCharFormat(anchorFormat); cursor.insertText(cardName); cursor.setCharFormat(oldFormat); @@ -88,7 +91,7 @@ void ChatView::appendUrlTag(QTextCursor &cursor, QString url) { if (!url.contains("://")) url.prepend("http://"); - + QTextCharFormat oldFormat = cursor.charFormat(); QTextCharFormat anchorFormat = oldFormat; anchorFormat.setForeground(Qt::blue); @@ -96,7 +99,7 @@ void ChatView::appendUrlTag(QTextCursor &cursor, QString url) anchorFormat.setAnchorHref(url); anchorFormat.setUnderlineColor(Qt::blue); anchorFormat.setFontUnderline(true); - + cursor.setCharFormat(anchorFormat); cursor.insertText(url); cursor.setCharFormat(oldFormat); @@ -108,14 +111,14 @@ void ChatView::appendMessage(QString message, QString sender, UserLevelFlags use bool sameSender = (sender == lastSender) && !lastSender.isEmpty(); QTextCursor cursor = prepareBlock(sameSender); lastSender = sender; - + if (showTimestamps && !sameSender) { QTextCharFormat timeFormat; timeFormat.setForeground(Qt::black); cursor.setCharFormat(timeFormat); cursor.insertText(QDateTime::currentDateTime().toString("[hh:mm:ss] ")); } - + QTextCharFormat senderFormat; if (tabSupervisor && tabSupervisor->getUserInfo() && (sender == QString::fromStdString(tabSupervisor->getUserInfo()->name()))) { senderFormat.setFontWeight(QFont::Bold); @@ -130,7 +133,8 @@ void ChatView::appendMessage(QString message, QString sender, UserLevelFlags use if (!sameSender) { if (!sender.isEmpty()) { const int pixelSize = QFontInfo(cursor.charFormat().font()).pixelSize(); - cursor.insertImage(UserLevelPixmapGenerator::generatePixmap(pixelSize, userLevel).toImage(), QString::number(pixelSize) + "_" + QString::number((int) userLevel)); + QMap buddyList = tabSupervisor->getUserListsTab()->getBuddyList()->getUsers(); + cursor.insertImage(UserLevelPixmapGenerator::generatePixmap(pixelSize, userLevel, buddyList.contains(sender)).toImage(), QString::number(pixelSize) + "_" + QString::number((int) userLevel)); cursor.insertText(" "); } cursor.setCharFormat(senderFormat); @@ -139,12 +143,12 @@ void ChatView::appendMessage(QString message, QString sender, UserLevelFlags use cursor.insertText(sender); } else cursor.insertText(" "); - + QTextCharFormat messageFormat; if (sender.isEmpty()) messageFormat.setForeground(Qt::darkGreen); cursor.setCharFormat(messageFormat); - + int from = 0, index = 0; while ((index = message.indexOf('[', from)) != -1) { cursor.insertText(message.left(index)); @@ -160,7 +164,7 @@ void ChatView::appendMessage(QString message, QString sender, UserLevelFlags use message.clear(); else message = message.mid(closeTagIndex + 7); - + appendCardTag(cursor, cardName); } else if (message.startsWith("[[")) { message = message.mid(2); @@ -170,7 +174,7 @@ void ChatView::appendMessage(QString message, QString sender, UserLevelFlags use message.clear(); else message = message.mid(closeTagIndex + 2); - + appendCardTag(cursor, cardName); } else if (message.startsWith("[url]")) { message = message.mid(5); @@ -180,7 +184,7 @@ void ChatView::appendMessage(QString message, QString sender, UserLevelFlags use message.clear(); else message = message.mid(closeTagIndex + 6); - + appendUrlTag(cursor, url); } else from = 1; @@ -188,7 +192,8 @@ void ChatView::appendMessage(QString message, QString sender, UserLevelFlags use if (settingsCache->getChatMention()) { index = 0; - while((index = message.indexOf('@')) != -1) { + from = 0; + while((index = message.indexOf('@', from)) != -1) { cursor.insertText(message.left(index), defaultFormat); message = message.mid(index); if (message.isEmpty()) @@ -207,40 +212,24 @@ void ChatView::appendMessage(QString message, QString sender, UserLevelFlags use QString userMention = message.left(mentionEndIndex); QString userName = userMention.right(userMention.size()-1).normalized(QString::NormalizationForm_D); QMap userList = tabSupervisor->getUserListsTab()->getAllUsersList()->getUsers(); - QString correctUserName = getNameFromUserList(userList, userName); - if (!correctUserName.isEmpty()) { - UserListTWI *vlu = userList.value(correctUserName); - mentionFormatOtherUser.setAnchorHref("user://" + QString::number(vlu->getUserInfo().user_level()) + "_" + correctUserName); - cursor.insertText("@" + correctUserName, mentionFormatOtherUser); + if (userList.contains(userName)) { + UserListTWI *vlu = userList.value(userName); + mentionFormatOtherUser.setAnchorHref("user://" + QString::number(vlu->getUserInfo().user_level()) + "_" + userName); + cursor.insertText("@" + userName, mentionFormatOtherUser); } else cursor.insertText("@" + userName, defaultFormat); message = message.mid(userName.size() + 1); } - cursor.setCharFormat(defaultFormat); // reset format after each itteration } } if (!message.isEmpty()) - cursor.insertText(message); + cursor.insertText(message, defaultFormat); if (atBottom) verticalScrollBar()->setValue(verticalScrollBar()->maximum()); } -/** - Returns the correct case version of the provided username, if no correct casing version - was found then the provided name is not available and will return an empty QString. - */ -QString ChatView::getNameFromUserList(QMap &userList, QString &userName) { - QMap::iterator i; - QString lowerUserName = userName.toLower(); - for (i = userList.begin(); i != userList.end(); ++i) { - if (i.key().toLower() == lowerUserName) - return i.key(); - } - return QString(); -} - void ChatView::clearChat() { document()->clear(); } @@ -292,41 +281,41 @@ void ChatView::mouseMoveEvent(QMouseEvent *event) hoveredItemType = HoveredNothing; viewport()->setCursor(Qt::IBeamCursor); } - + QTextBrowser::mouseMoveEvent(event); } void ChatView::mousePressEvent(QMouseEvent *event) { switch (hoveredItemType) { - case HoveredCard: { - if ((event->button() == Qt::MidButton) || (event->button() == Qt::LeftButton)) - emit showCardInfoPopup(event->globalPos(), hoveredContent); - break; - } - case HoveredUser: { - if (event->button() != Qt::MidButton) { - const int delimiterIndex = hoveredContent.indexOf("_"); - const QString userName = hoveredContent.mid(delimiterIndex + 1); - switch(event->button()) { - case Qt::RightButton :{ - UserLevelFlags userLevel(hoveredContent.left(delimiterIndex).toInt()); - userContextMenu->showContextMenu(event->globalPos(), userName, userLevel); - break; - } - case Qt::LeftButton :{ - emit addMentionTag("@" + userName); - break; - } - default: - break; - } + case HoveredCard: { + if ((event->button() == Qt::MidButton) || (event->button() == Qt::LeftButton)) + emit showCardInfoPopup(event->globalPos(), hoveredContent); + break; + } + case HoveredUser: { + if (event->button() != Qt::MidButton) { + const int delimiterIndex = hoveredContent.indexOf("_"); + const QString userName = hoveredContent.mid(delimiterIndex + 1); + switch(event->button()) { + case Qt::RightButton :{ + UserLevelFlags userLevel(hoveredContent.left(delimiterIndex).toInt()); + userContextMenu->showContextMenu(event->globalPos(), userName, userLevel); + break; + } + case Qt::LeftButton :{ + emit addMentionTag("@" + userName); + break; + } + default: + break; } - break; - } - default: { - QTextBrowser::mousePressEvent(event); } + break; + } + default: { + QTextBrowser::mousePressEvent(event); + } } } @@ -334,7 +323,7 @@ void ChatView::mouseReleaseEvent(QMouseEvent *event) { if ((event->button() == Qt::MidButton) || (event->button() == Qt::LeftButton)) emit deleteCardInfoPopup(QString("_")); - + QTextBrowser::mouseReleaseEvent(event); } @@ -342,6 +331,6 @@ void ChatView::openLink(const QUrl &link) { if ((link.scheme() == "card") || (link.scheme() == "user")) return; - + QDesktopServices::openUrl(link); } diff --git a/cockatrice/src/gamesmodel.cpp b/cockatrice/src/gamesmodel.cpp index 1ef81e164..716ff085a 100644 --- a/cockatrice/src/gamesmodel.cpp +++ b/cockatrice/src/gamesmodel.cpp @@ -115,7 +115,7 @@ QVariant GamesModel::data(const QModelIndex &index, int role) const case Qt::DisplayRole: return QString::fromStdString(g.creator_info().name()); case Qt::DecorationRole: { - QPixmap avatarPixmap = UserLevelPixmapGenerator::generatePixmap(13, (UserLevelFlags)g.creator_info().user_level()); + QPixmap avatarPixmap = UserLevelPixmapGenerator::generatePixmap(13, (UserLevelFlags)g.creator_info().user_level(), false); return QIcon(avatarPixmap); } default: diff --git a/cockatrice/src/pixmapgenerator.cpp b/cockatrice/src/pixmapgenerator.cpp index 8bae48539..688e5d254 100644 --- a/cockatrice/src/pixmapgenerator.cpp +++ b/cockatrice/src/pixmapgenerator.cpp @@ -15,9 +15,9 @@ QPixmap PhasePixmapGenerator::generatePixmap(int height, QString name) QString key = name + QString::number(height); if (pmCache.contains(key)) return pmCache.value(key); - + QSvgRenderer svg(QString(":/resources/phases/icon_phase_" + name + ".svg")); - + QPixmap pixmap(height, height); pixmap.fill(Qt::transparent); QPainter painter(&pixmap); @@ -35,16 +35,16 @@ QPixmap CounterPixmapGenerator::generatePixmap(int height, QString name, bool hi QString key = name + QString::number(height); if (pmCache.contains(key)) return pmCache.value(key); - + QSvgRenderer svg(QString(":/resources/counters/" + name + ".svg")); - + if (!svg.isValid()) { name = "general"; if (highlight) name.append("_highlight"); svg.load(QString(":/resources/counters/" + name + ".svg")); } - + int width = (int) round(height * (double) svg.defaultSize().width() / (double) svg.defaultSize().height()); QPixmap pixmap(width, height); pixmap.fill(Qt::transparent); @@ -59,7 +59,7 @@ QPixmap PingPixmapGenerator::generatePixmap(int size, int value, int max) int key = size * 1000000 + max * 1000 + value; if (pmCache.contains(key)) return pmCache.value(key); - + QPixmap pixmap(size, size); pixmap.fill(Qt::transparent); QPainter painter(&pixmap); @@ -68,12 +68,12 @@ QPixmap PingPixmapGenerator::generatePixmap(int size, int value, int max) color = Qt::black; else color.setHsv(120 * (1.0 - ((double) value / max)), 255, 255); - + QRadialGradient g(QPointF((double) pixmap.width() / 2, (double) pixmap.height() / 2), qMin(pixmap.width(), pixmap.height()) / 2.0); g.setColorAt(0, color); g.setColorAt(1, Qt::transparent); painter.fillRect(0, 0, pixmap.width(), pixmap.height(), QBrush(g)); - + pmCache.insert(key, pixmap); return pixmap; @@ -86,25 +86,25 @@ QPixmap GenderPixmapGenerator::generatePixmap(int height, int _gender) ServerInfo_User::Gender gender = static_cast(_gender); if ((gender != ServerInfo_User::Male) && (gender != ServerInfo_User::Female)) gender = ServerInfo_User::GenderUnknown; - + int key = gender * 100000 + height; if (pmCache.contains(key)) return pmCache.value(key); - + QString genderStr; switch (gender) { - case ServerInfo_User::Male: genderStr = "male"; break; - case ServerInfo_User::Female: genderStr = "female"; break; - default: genderStr = "unknown"; + case ServerInfo_User::Male: genderStr = "male"; break; + case ServerInfo_User::Female: genderStr = "female"; break; + default: genderStr = "unknown"; }; - + QSvgRenderer svg(QString(":/resources/genders/" + genderStr + ".svg")); int width = (int) round(height * (double) svg.defaultSize().width() / (double) svg.defaultSize().height()); QPixmap pixmap(width, height); pixmap.fill(Qt::transparent); QPainter painter(&pixmap); svg.render(&painter, QRectF(0, 0, width, height)); - + pmCache.insert(key, pixmap); return pixmap; } @@ -118,7 +118,7 @@ QPixmap CountryPixmapGenerator::generatePixmap(int height, const QString &countr QString key = countryCode + QString::number(height); if (pmCache.contains(key)) return pmCache.value(key); - + QSvgRenderer svg(QString(":/resources/countries/" + countryCode + ".svg")); int width = (int) round(height * (double) svg.defaultSize().width() / (double) svg.defaultSize().height()); QPixmap pixmap(width, height); @@ -127,19 +127,20 @@ QPixmap CountryPixmapGenerator::generatePixmap(int height, const QString &countr svg.render(&painter, QRectF(0, 0, width, height)); painter.setPen(Qt::black); painter.drawRect(0, 0, width - 1, height - 1); - + pmCache.insert(key, pixmap); return pixmap; } QMap CountryPixmapGenerator::pmCache; -QPixmap UserLevelPixmapGenerator::generatePixmap(int height, UserLevelFlags userLevel) +QPixmap UserLevelPixmapGenerator::generatePixmap(int height, UserLevelFlags userLevel, bool isBuddy) { + int key = height * 10000 + (int) userLevel; if (pmCache.contains(key)) return pmCache.value(key); - + QString levelString; if (userLevel.testFlag(ServerInfo_User::IsAdmin)) levelString = "admin"; @@ -149,15 +150,35 @@ QPixmap UserLevelPixmapGenerator::generatePixmap(int height, UserLevelFlags user levelString = "registered"; else levelString = "normal"; + + if (isBuddy) + levelString.append("_buddy"); + QSvgRenderer svg(QString(":/resources/userlevels/" + levelString + ".svg")); int width = (int) round(height * (double) svg.defaultSize().width() / (double) svg.defaultSize().height()); QPixmap pixmap(width, height); pixmap.fill(Qt::transparent); QPainter painter(&pixmap); svg.render(&painter, QRectF(0, 0, width, height)); - + pmCache.insert(key, pixmap); return pixmap; } +QMap PixmapGenerator::pmCache; +QPixmap PixmapGenerator::generatePixmap(int height, QString resourceName) { + if (pmCache.contains(resourceName)) + return pmCache.value(resourceName); + + QSvgRenderer svg(resourceName); + int width = (int) round(height * (double) svg.defaultSize().width() / (double) svg.defaultSize().height()); + QPixmap pixmap(width, height); + pixmap.fill(Qt::transparent); + QPainter painter(&pixmap); + svg.render(&painter, QRectF(0, 0, width, height)); + + pmCache.insert(resourceName, pixmap); + return pixmap; +} + QMap UserLevelPixmapGenerator::pmCache; diff --git a/cockatrice/src/pixmapgenerator.h b/cockatrice/src/pixmapgenerator.h index 67a8b2b2e..023675b11 100644 --- a/cockatrice/src/pixmapgenerator.h +++ b/cockatrice/src/pixmapgenerator.h @@ -50,7 +50,15 @@ class UserLevelPixmapGenerator { private: static QMap pmCache; public: - static QPixmap generatePixmap(int height, UserLevelFlags userLevel); + static QPixmap generatePixmap(int height, UserLevelFlags userLevel, bool isBuddy); + static void clear() { pmCache.clear(); } +}; + +class PixmapGenerator { +private: + static QMap pmCache; +public: + static QPixmap generatePixmap(int height, QString resourceName); static void clear() { pmCache.clear(); } }; diff --git a/cockatrice/src/playerlistwidget.cpp b/cockatrice/src/playerlistwidget.cpp index 4edf26edb..e18bab98c 100644 --- a/cockatrice/src/playerlistwidget.cpp +++ b/cockatrice/src/playerlistwidget.cpp @@ -118,7 +118,7 @@ void PlayerListWidget::updatePlayerProperties(const ServerInfo_PlayerProperties player->setIcon(2, gameStarted ? (prop.conceded() ? concededIcon : QIcon()) : (prop.ready_start() ? readyIcon : notReadyIcon)); if (prop.has_user_info()) { player->setData(3, Qt::UserRole, prop.user_info().user_level()); - player->setIcon(3, QIcon(UserLevelPixmapGenerator::generatePixmap(12, UserLevelFlags(prop.user_info().user_level())))); + player->setIcon(3, QIcon(UserLevelPixmapGenerator::generatePixmap(12, UserLevelFlags(prop.user_info().user_level()), false))); player->setText(4, QString::fromStdString(prop.user_info().name())); const QString country = QString::fromStdString(prop.user_info().country()); if (!country.isEmpty()) diff --git a/cockatrice/src/playertarget.cpp b/cockatrice/src/playertarget.cpp index 98b266dfd..d1081797a 100644 --- a/cockatrice/src/playertarget.cpp +++ b/cockatrice/src/playertarget.cpp @@ -98,7 +98,7 @@ void PlayerTarget::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*o QPixmap tempPixmap; if (fullPixmap.isNull()) - tempPixmap = UserLevelPixmapGenerator::generatePixmap(translatedSize.height(), UserLevelFlags(info->user_level())); + tempPixmap = UserLevelPixmapGenerator::generatePixmap(translatedSize.height(), UserLevelFlags(info->user_level()), false); else tempPixmap = fullPixmap.scaled(translatedSize, Qt::KeepAspectRatio, Qt::SmoothTransformation); diff --git a/cockatrice/src/userinfobox.cpp b/cockatrice/src/userinfobox.cpp index 6c33bbf72..0fd0e5694 100644 --- a/cockatrice/src/userinfobox.cpp +++ b/cockatrice/src/userinfobox.cpp @@ -60,7 +60,7 @@ void UserInfoBox::updateInfo(const ServerInfo_User &user) QPixmap avatarPixmap; const std::string bmp = user.avatar_bmp(); if (!avatarPixmap.loadFromData((const uchar *) bmp.data(), bmp.size())) - avatarPixmap = UserLevelPixmapGenerator::generatePixmap(64, userLevel); + avatarPixmap = UserLevelPixmapGenerator::generatePixmap(64, userLevel, false); avatarLabel.setPixmap(avatarPixmap); nameLabel.setText(QString::fromStdString(user.name())); @@ -69,7 +69,7 @@ void UserInfoBox::updateInfo(const ServerInfo_User &user) QString country = QString::fromStdString(user.country()); countryLabel2.setPixmap(CountryPixmapGenerator::generatePixmap(15, country)); countryLabel3.setText(QString("(%1)").arg(country.toUpper())); - userLevelLabel2.setPixmap(UserLevelPixmapGenerator::generatePixmap(15, userLevel)); + userLevelLabel2.setPixmap(UserLevelPixmapGenerator::generatePixmap(15, userLevel, false)); QString userLevelText; if (userLevel.testFlag(ServerInfo_User::IsAdmin)) userLevelText = tr("Administrator"); diff --git a/cockatrice/src/userlist.cpp b/cockatrice/src/userlist.cpp index c6174a6e5..5e9e24905 100644 --- a/cockatrice/src/userlist.cpp +++ b/cockatrice/src/userlist.cpp @@ -181,7 +181,7 @@ void UserListTWI::setUserInfo(const ServerInfo_User &_userInfo) userInfo = _userInfo; setData(0, Qt::UserRole, userInfo.user_level()); - setIcon(0, QIcon(UserLevelPixmapGenerator::generatePixmap(12, UserLevelFlags(userInfo.user_level())))); + setIcon(0, QIcon(UserLevelPixmapGenerator::generatePixmap(12, UserLevelFlags(userInfo.user_level()), false))); setIcon(1, QIcon(CountryPixmapGenerator::generatePixmap(12, QString::fromStdString(userInfo.country())))); setData(2, Qt::UserRole, QString::fromStdString(userInfo.name())); setData(2, Qt::DisplayRole, QString::fromStdString(userInfo.name()));