From 1de09deb596426e2f032ff4e30e6650e0acab615 Mon Sep 17 00:00:00 2001 From: RickyRister <42636155+RickyRister@users.noreply.github.com> Date: Sun, 2 Feb 2025 07:08:23 -0800 Subject: [PATCH] Fix size and image quality issues with new user icons (#5546) --- cockatrice/src/client/tabs/tab_supervisor.cpp | 4 +-- .../src/client/ui/pixel_map_generator.cpp | 23 +++++++++++----- .../src/client/ui/pixel_map_generator.h | 2 +- cockatrice/src/game/game_selector.cpp | 1 + cockatrice/src/game/games_model.cpp | 5 ++-- .../src/game/player/player_list_widget.cpp | 4 +-- cockatrice/src/server/user/user_info_box.cpp | 27 ++++++++++++++++--- cockatrice/src/server/user/user_info_box.h | 2 ++ 8 files changed, 50 insertions(+), 18 deletions(-) diff --git a/cockatrice/src/client/tabs/tab_supervisor.cpp b/cockatrice/src/client/tabs/tab_supervisor.cpp index 49090d1fc..cfd50da02 100644 --- a/cockatrice/src/client/tabs/tab_supervisor.cpp +++ b/cockatrice/src/client/tabs/tab_supervisor.cpp @@ -809,10 +809,10 @@ void TabSupervisor::processUserJoined(const ServerInfo_User &userInfoJoined) if (auto *tab = getTabAccount()) { if (tab != currentWidget()) { tab->setContentsChanged(true); - QPixmap avatarPixmap = UserLevelPixmapGenerator::generatePixmap( + QIcon avatarIcon = UserLevelPixmapGenerator::generateIcon( 13, (UserLevelFlags)userInfoJoined.user_level(), userInfoJoined.pawn_colors(), true, QString::fromStdString(userInfoJoined.privlevel())); - setTabIcon(indexOf(tab), QPixmap(avatarPixmap)); + setTabIcon(indexOf(tab), avatarIcon); } } diff --git a/cockatrice/src/client/ui/pixel_map_generator.cpp b/cockatrice/src/client/ui/pixel_map_generator.cpp index 501fa3c95..670a18873 100644 --- a/cockatrice/src/client/ui/pixel_map_generator.cpp +++ b/cockatrice/src/client/ui/pixel_map_generator.cpp @@ -129,9 +129,18 @@ void setAttrRecur(QDomElement &elem, } /** - * Returns an icon of the svg that has its color filled in + * Loads the usericon svg and fills in its colors. + * The image is kept as a QIcon to preserve the image quality. + * + * Call icon.pixmap(w, h) in order to convert this icon into a pixmap with the given dimensions. + * Avoid scaling the pixmap in other ways, as that destroys image quality. + * + * @param minSize If the dimensions of the source svg is smaller than this, then it will be scaled up to this size */ -QIcon changeSVGColor(const QString &iconPath, const QString &colorLeft, const std::optional &colorRight) +static QIcon loadAndColorSvg(const QString &iconPath, + const QString &colorLeft, + const std::optional &colorRight, + const int minSize) { QFile file(iconPath); if (!file.open(QIODevice::ReadOnly)) { @@ -152,7 +161,7 @@ QIcon changeSVGColor(const QString &iconPath, const QString &colorLeft, const st QSvgRenderer svgRenderer(doc.toByteArray()); - QPixmap pix(svgRenderer.defaultSize()); + QPixmap pix(svgRenderer.defaultSize().expandedTo(QSize(minSize, minSize))); pix.fill(Qt::transparent); QPainter pixPainter(&pix); @@ -171,7 +180,7 @@ QPixmap UserLevelPixmapGenerator::generatePixmap(int height, return generateIcon(height, userLevel, pawnColorsOverride, isBuddy, privLevel).pixmap(height, height); } -QIcon UserLevelPixmapGenerator::generateIcon(int height, +QIcon UserLevelPixmapGenerator::generateIcon(int minHeight, UserLevelFlags userLevel, ServerInfo_User::PawnColorsOverride pawnColorsOverride, bool isBuddy, @@ -189,11 +198,11 @@ QIcon UserLevelPixmapGenerator::generateIcon(int height, // Has Color Override if (colorLeft.has_value()) { - return generateIconWithColorOverride(height, isBuddy, privLevel, colorLeft, colorRight); + return generateIconWithColorOverride(minHeight, isBuddy, privLevel, colorLeft, colorRight); } // Has No Color Override - return generateIconDefault(height, userLevel, isBuddy, privLevel); + return generateIconDefault(minHeight, userLevel, isBuddy, privLevel); } QIcon UserLevelPixmapGenerator::generateIconDefault(int height, @@ -263,7 +272,7 @@ QIcon UserLevelPixmapGenerator::generateIconWithColorOverride(int height, QString iconPath = QString("theme:usericons/%1_%2.svg").arg(iconType).arg(arity); - QIcon icon(changeSVGColor(iconPath, colorLeft.value(), colorRight)); + QIcon icon = loadAndColorSvg(iconPath, colorLeft.value(), colorRight, height); iconCache.insert(key, icon); return icon; } diff --git a/cockatrice/src/client/ui/pixel_map_generator.h b/cockatrice/src/client/ui/pixel_map_generator.h index b206ee0ea..fc18f107d 100644 --- a/cockatrice/src/client/ui/pixel_map_generator.h +++ b/cockatrice/src/client/ui/pixel_map_generator.h @@ -81,7 +81,7 @@ public: bool isBuddy, const QString &privLevel); - static QIcon generateIcon(int height, + static QIcon generateIcon(int minHeight, UserLevelFlags userLevel, ServerInfo_User::PawnColorsOverride pawnColors, bool isBuddy, diff --git a/cockatrice/src/game/game_selector.cpp b/cockatrice/src/game/game_selector.cpp index 3ee07b192..694e79ec9 100644 --- a/cockatrice/src/game/game_selector.cpp +++ b/cockatrice/src/game/game_selector.cpp @@ -50,6 +50,7 @@ GameSelector::GameSelector(AbstractClient *_client, } else { gameListView->setModel(gameListModel); } + gameListView->setIconSize(QSize(13, 13)); gameListView->setSortingEnabled(true); gameListView->sortByColumn(gameListModel->startTimeColIndex(), Qt::AscendingOrder); gameListView->setAlternatingRowColors(true); diff --git a/cockatrice/src/game/games_model.cpp b/cockatrice/src/game/games_model.cpp index 319aa2c57..93dbb7f20 100644 --- a/cockatrice/src/game/games_model.cpp +++ b/cockatrice/src/game/games_model.cpp @@ -118,11 +118,10 @@ QVariant GamesModel::data(const QModelIndex &index, int role) const case Qt::DisplayRole: return QString::fromStdString(gameentry.creator_info().name()); case Qt::DecorationRole: { - QPixmap avatarPixmap = UserLevelPixmapGenerator::generatePixmap( - 13, (UserLevelFlags)gameentry.creator_info().user_level(), + return UserLevelPixmapGenerator::generateIcon( + 13, UserLevelFlags(gameentry.creator_info().user_level()), gameentry.creator_info().pawn_colors(), false, QString::fromStdString(gameentry.creator_info().privlevel())); - return QIcon(avatarPixmap); } default: return QVariant(); diff --git a/cockatrice/src/game/player/player_list_widget.cpp b/cockatrice/src/game/player/player_list_widget.cpp index c8771968d..a5901c392 100644 --- a/cockatrice/src/game/player/player_list_widget.cpp +++ b/cockatrice/src/game/player/player_list_widget.cpp @@ -140,9 +140,9 @@ void PlayerListWidget::updatePlayerProperties(const ServerInfo_PlayerProperties } if (prop.has_user_info()) { player->setData(3, Qt::UserRole, prop.user_info().user_level()); - player->setIcon(3, QIcon(UserLevelPixmapGenerator::generatePixmap( + player->setIcon(3, UserLevelPixmapGenerator::generateIcon( 12, UserLevelFlags(prop.user_info().user_level()), prop.user_info().pawn_colors(), false, - QString::fromStdString(prop.user_info().privlevel())))); + QString::fromStdString(prop.user_info().privlevel()))); 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/server/user/user_info_box.cpp b/cockatrice/src/server/user/user_info_box.cpp index 53e1d3379..3f2381011 100644 --- a/cockatrice/src/server/user/user_info_box.cpp +++ b/cockatrice/src/server/user/user_info_box.cpp @@ -9,6 +9,7 @@ #include "../pending_command.h" #include "passwordhasher.h" #include "pb/response_get_user_info.pb.h" +#include "pb/serverinfo_user.pb.h" #include "pb/session_commands.pb.h" #include @@ -84,14 +85,27 @@ void UserInfoBox::retranslateUi() avatarButton.setText(tr("Change avatar")); } +/** + * Creates the default profile pic that is used when the user doesn't have a custom pic + */ +static QPixmap createDefaultAvatar(int height, const ServerInfo_User &user) +{ + return UserLevelPixmapGenerator::generatePixmap(height, UserLevelFlags(user.user_level()), user.pawn_colors(), + false, QString::fromStdString(user.privlevel())); +} + void UserInfoBox::updateInfo(const ServerInfo_User &user) { + currentUserInfo = &user; + const UserLevelFlags userLevel(user.user_level()); const std::string &bmp = user.avatar_bmp(); if (!avatarPixmap.loadFromData((const uchar *)bmp.data(), static_cast(bmp.size()))) { - avatarPixmap = UserLevelPixmapGenerator::generatePixmap(64, userLevel, user.pawn_colors(), false, - QString::fromStdString(user.privlevel())); + avatarPixmap = createDefaultAvatar(64, user); + hasAvatar = false; + } else { + hasAvatar = true; } nameLabel.setText(QString::fromStdString(user.name())); @@ -363,7 +377,14 @@ void UserInfoBox::processAvatarResponse(const Response &r) void UserInfoBox::resizeEvent(QResizeEvent *event) { - QPixmap resizedPixmap = avatarPixmap.scaled(avatarPic.size(), Qt::KeepAspectRatio, Qt::SmoothTransformation); + QPixmap resizedPixmap; + if (hasAvatar) { + resizedPixmap = avatarPixmap.scaled(avatarPic.size(), Qt::KeepAspectRatio, Qt::SmoothTransformation); + } else { + int height = qMin(avatarPic.size().width(), avatarPic.size().height()); + resizedPixmap = createDefaultAvatar(height, *currentUserInfo); + } avatarPic.setPixmap(resizedPixmap); + QWidget::resizeEvent(event); } diff --git a/cockatrice/src/server/user/user_info_box.h b/cockatrice/src/server/user/user_info_box.h index 1fa5bb308..170c27bb2 100644 --- a/cockatrice/src/server/user/user_info_box.h +++ b/cockatrice/src/server/user/user_info_box.h @@ -20,6 +20,8 @@ private: countryLabel3, userLevelLabel1, userLevelLabel2, accountAgeLabel1, accountAgeLabel2; QPushButton editButton, passwordButton, avatarButton; QPixmap avatarPixmap; + bool hasAvatar; + const ServerInfo_User *currentUserInfo; static QString getAgeString(int ageSeconds);