From 927bd79488d6918691d5da0a1606e3d6a569a738 Mon Sep 17 00:00:00 2001 From: Alessandro Portale Date: Wed, 2 Oct 2024 19:24:15 +0200 Subject: [PATCH] ExtensionManager: Implement badge for recently published items This adds a "New" onto the upper left card corner for recently published items. For QtC 15, we mark all remote extensions as recently published. Fixes: QTCREATORBUG-31587 Change-Id: If460f33ebb76c72bb1af6935deb2db7678dcf550 Reviewed-by: Marcus Tillmanns --- .../extensionmanager/extensionsbrowser.cpp | 36 ++++++++++++++++++- .../extensionmanager/extensionsbrowser.h | 1 + .../extensionmanager/extensionsmodel.cpp | 17 +++++++-- .../extensionmanager/extensionsmodel.h | 3 +- 4 files changed, 53 insertions(+), 4 deletions(-) diff --git a/src/plugins/extensionmanager/extensionsbrowser.cpp b/src/plugins/extensionmanager/extensionsbrowser.cpp index 2e14aa6df19..91a58f62259 100644 --- a/src/plugins/extensionmanager/extensionsbrowser.cpp +++ b/src/plugins/extensionmanager/extensionsbrowser.cpp @@ -267,6 +267,10 @@ public: const QPixmap icon = itemIcon(index, SizeSmall); painter->drawPixmap(iconBgR.topLeft(), icon); } + { + const QPixmap badge = itemBadge(index, SizeSmall); + painter->drawPixmap(bgR.topLeft(), badge); + } if (isPack) { constexpr int circleSize = 18; constexpr int circleOverlap = 3; // Protrusion from lower right corner of iconRect @@ -700,6 +704,8 @@ QLabel *tfLabel(const TextFormat &tf, bool singleLine) return label; } +const int iconRectRounding = 4; + QPixmap itemIcon(const QModelIndex &index, Size size) { const QSize iconBgS = size == SizeSmall ? iconBgSizeSmall : iconBgSizeBig; @@ -730,7 +736,6 @@ QPixmap itemIcon(const QModelIndex &index, Size size) const ItemType itemType = index.data(RoleItemType).value(); const QIcon &icon = (itemType == ItemTypePack) ? (size == SizeSmall ? packS : packB) : (size == SizeSmall ? extensionS : extensionB); - const int iconRectRounding = 4; const qreal iconOpacityDisabled = 0.6; QPainter p(&pixmap); @@ -744,4 +749,33 @@ QPixmap itemIcon(const QModelIndex &index, Size size) return pixmap; } +QPixmap itemBadge(const QModelIndex &index, [[maybe_unused]] Size size) +{ + const QString badgeText = index.data(RoleBadge).toString(); + if (badgeText.isNull()) + return {}; + + constexpr TextFormat badgeTF + {Theme::Token_Basic_White, UiElement::UiElementLabelSmall}; + + const QFont font = badgeTF.font(); + const int textWidth = QFontMetrics(font).horizontalAdvance(badgeText); + const QSize badgeS(ExPaddingGapM + textWidth + ExPaddingGapM, + ExPaddingGapS + badgeTF.lineHeight() + ExPaddingGapS); + const QRect badgeR(QPoint(), badgeS); + const qreal dpr = qApp->devicePixelRatio(); + QPixmap pixmap(badgeS * dpr); + pixmap.fill(Qt::transparent); + pixmap.setDevicePixelRatio(dpr); + + QPainter p(&pixmap); + WelcomePageHelpers::drawCardBackground(&p, badgeR, + creatorColor(Theme::Token_Notification_Neutral), + Qt::NoPen, iconRectRounding); + p.setFont(font); + p.setPen(badgeTF.color()); + p.drawText(badgeR, Qt::AlignCenter, badgeText); + return pixmap; +} + } // ExtensionManager::Internal diff --git a/src/plugins/extensionmanager/extensionsbrowser.h b/src/plugins/extensionmanager/extensionsbrowser.h index 0b4254e02cd..620c581de71 100644 --- a/src/plugins/extensionmanager/extensionsbrowser.h +++ b/src/plugins/extensionmanager/extensionsbrowser.h @@ -50,5 +50,6 @@ enum Size { SizeBig, }; QPixmap itemIcon(const QModelIndex &index, Size size); +QPixmap itemBadge(const QModelIndex &index, Size size); } // ExtensionManager::Internal diff --git a/src/plugins/extensionmanager/extensionsmodel.cpp b/src/plugins/extensionmanager/extensionsmodel.cpp index cf348b99673..e28f716e90f 100644 --- a/src/plugins/extensionmanager/extensionsmodel.cpp +++ b/src/plugins/extensionmanager/extensionsmodel.cpp @@ -240,6 +240,13 @@ int ExtensionsModel::rowCount([[maybe_unused]] const QModelIndex &parent) const return d->responseItems.count() + d->localPlugins.count(); } +static QString badgeText(const QModelIndex &index) +{ + if (index.data(RoleDownloadUrl).isNull()) + return {}; + return Tr::tr("New"); +} + ExtensionState extensionState(const QModelIndex &index) { if (index.data(RoleItemType) != ItemTypeExtension) @@ -265,10 +272,16 @@ static QString searchText(const QModelIndex &index) QVariant ExtensionsModel::data(const QModelIndex &index, int role) const { - if (role == RoleExtensionState) + switch (role) { + case RoleBadge: + return badgeText(index); + case RoleExtensionState: return extensionState(index); - if (role == RoleSearchText) + case RoleSearchText: return searchText(index); + default: + break; + } const bool isRemoteExtension = index.row() < d->responseItems.count(); const int itemIndex = index.row() - (isRemoteExtension ? 0 : d->responseItems.count()); diff --git a/src/plugins/extensionmanager/extensionsmodel.h b/src/plugins/extensionmanager/extensionsmodel.h index eb3d289630c..ce51d5a15d9 100644 --- a/src/plugins/extensionmanager/extensionsmodel.h +++ b/src/plugins/extensionmanager/extensionsmodel.h @@ -27,7 +27,9 @@ enum ExtensionState { enum Role { RoleName = Qt::UserRole, + RoleBadge, RoleCopyright, + RoleDateUpdated, RoleDependencies, RoleDescriptionLong, RoleDescriptionShort, @@ -39,7 +41,6 @@ enum Role { RoleLicense, RolePlatforms, RolePlugins, - RoleDateUpdated, RoleSearchText, RoleTags, RoleVendor,