UI: highlight pinned printings in Printing Selector (#6252)

* UI: highlight pinned printings in Printing Selector

Fixes #5930.

Signed-off-by: Gauwal <gauwain2611@hotmail.com>

* Fix: adjust pin highlighting behavior + making it sharp/not blurry

* Using qceil

* Isolating pin badge init to it's own method + adding comments

* Cleaning up unnecessary #includes

---------

Signed-off-by: Gauwal <gauwain2611@hotmail.com>
This commit is contained in:
Gauwal 2025-11-09 09:53:27 +01:00 committed by GitHub
parent 0ad31fea46
commit e5d5dfa8d8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 130 additions and 0 deletions

View file

@ -3,9 +3,12 @@
#include "../../../client/settings/cache_settings.h"
#include "printing_selector_card_display_widget.h"
#include <QImageReader>
#include <QLabel>
#include <QMenu>
#include <QMouseEvent>
#include <QVBoxLayout>
#include <QtMath>
#include <libcockatrice/card/database/card_database_manager.h>
#include <libcockatrice/card/relation/card_relation.h>
#include <utility>
@ -46,6 +49,15 @@ PrintingSelectorCardOverlayWidget::PrintingSelectorCardOverlayWidget(QWidget *pa
cardInfoPicture->setCard(_rootCard);
mainLayout->addWidget(cardInfoPicture);
initializePinBadge();
// Update when this overlay emits cardPreferenceChanged or when size/scale changes
connect(this, &PrintingSelectorCardOverlayWidget::cardPreferenceChanged, this,
&PrintingSelectorCardOverlayWidget::updatePinBadgeVisibility);
connect(cardSizeSlider, &QSlider::valueChanged, this, &PrintingSelectorCardOverlayWidget::updatePinBadgeVisibility);
// initial state
updatePinBadgeVisibility();
// Add AllZonesCardAmountWidget
allZonesCardAmountWidget =
new AllZonesCardAmountWidget(this, deckEditor, deckModel, deckView, cardSizeSlider, _rootCard);
@ -128,6 +140,40 @@ void PrintingSelectorCardOverlayWidget::enterEvent(QEvent *event)
// Show the widget if amounts are 0
allZonesCardAmountWidget->setVisible(true);
}
/**
* @brief Updates the pin badge visibility and position based on the card's pinned state.
*
* This method checks whether the current card printing is pinned and updates the
* pin badge accordingly. If the card is pinned, the badge is made visible and positioned in the
* top-right corner of the card image with appropriate margins. If the card is not pinned, the
* badge is hidden.
*
* The method is called whenever the card preference changes or the card size is adjusted via
* the slider to ensure the badge remains properly positioned.
*/
void PrintingSelectorCardOverlayWidget::updatePinBadgeVisibility()
{
if (!pinBadge || !cardInfoPicture)
return;
// Query the persisted preference override to decide whether this printing is pinned.
const auto &preferredProviderId =
SettingsCache::instance().cardOverrides().getCardPreferenceOverride(rootCard.getName());
const auto &cardProviderId = rootCard.getPrinting().getUuid();
const bool isPinned = (!preferredProviderId.isEmpty() && preferredProviderId == cardProviderId);
// Toggle the badge once; the pixmap was already rasterized in initializePinBadge().
pinBadge->setVisible(isPinned);
if (isPinned) {
// Keep a small margin that scales with the card size to avoid obscuring stuff.
const int margin = qMax(3, int(cardInfoPicture->width() * 0.03));
int x = qMax(0, cardInfoPicture->width() - pinBadge->width() - margin);
int y = margin * 3;
pinBadge->move(x, y);
pinBadge->raise();
}
}
/**
* @brief Handles the mouse leave event when the cursor leaves the overlay widget area.
@ -204,3 +250,57 @@ void PrintingSelectorCardOverlayWidget::customMenu(QPoint point)
}
menu.exec(this->mapToGlobal(point));
}
/**
* @brief Initializes the pin badge overlay and loads its icon with DPI-aware rasterization.
*
* The icon is rasterized once using the label's device pixel ratio so it stays crisp on HiDPI
* displays. The resulting pixmap is cached on the QLabel and simply shown/hidden when needed.
* If the SVG cannot be read, a textual fallback badge is created instead.
*/
void PrintingSelectorCardOverlayWidget::initializePinBadge()
{
if (!pinBadge) {
// construct the overlay label once
pinBadge = new QLabel(this);
pinBadge->setObjectName(QStringLiteral("printingSelectorPinBadge"));
} else {
// Clear any previous pixmap / style in case we reinitialize for a DPR change.
pinBadge->clear();
pinBadge->setStyleSheet(QString());
}
bool pinLoaded = false;
QImageReader pinReader(QStringLiteral("theme:icons/pin"));
if (pinReader.canRead()) {
// Rasterize a 64×64 logical icon so it has a consistent size regardless of card scaling.
const QSize targetSize(64, 64);
const qreal dpr = pinBadge->devicePixelRatioF();
const QSize rasterSize(qMax(1, qCeil(targetSize.width() * dpr)), qMax(1, qCeil(targetSize.height() * dpr)));
pinReader.setScaledSize(rasterSize);
const QImage pinImage = pinReader.read();
if (!pinImage.isNull()) {
// Tag the pixmap with the same DPR so Qt renders it at the correct physical size.
QPixmap pinPix = QPixmap::fromImage(pinImage);
pinPix.setDevicePixelRatio(dpr);
pinBadge->setPixmap(pinPix);
pinBadge->setFixedSize(targetSize);
pinBadge->setStyleSheet(QStringLiteral("background: transparent;"));
pinLoaded = true;
}
}
if (!pinLoaded) {
// Fall back to a text badge when the SVG cannot be decoded (e.g., missing theme resource).
pinBadge->setText(QStringLiteral("PIN"));
pinBadge->setAlignment(Qt::AlignCenter);
pinBadge->setFixedSize(24, 12);
pinBadge->setStyleSheet(QStringLiteral("background: yellow; color: black; border: 1px solid red;"));
}
// The overlay is mouse-transparent and hidden until we know the card is pinned.
pinBadge->setAttribute(Qt::WA_TransparentForMouseEvents);
pinBadge->setVisible(false);
pinBadge->raise();
}

View file

@ -42,9 +42,14 @@ protected:
signals:
void cardPreferenceChanged();
private slots:
void updatePinBadgeVisibility();
private:
void initializePinBadge();
CardInfoPictureWidget *cardInfoPicture;
AllZonesCardAmountWidget *allZonesCardAmountWidget;
QLabel *pinBadge = nullptr;
AbstractTabDeckEditor *deckEditor;
DeckListModel *deckModel;
QTreeView *deckView;