More doxys.

This commit is contained in:
Brübach, Lukas 2025-11-29 23:37:13 +01:00
parent 61c7d2a05f
commit 75c674e6bb
4 changed files with 312 additions and 28 deletions

View file

@ -6,36 +6,122 @@
#include <QString> #include <QString>
#include <QWidget> #include <QWidget>
/**
* @class ColorBar
* @brief A widget for visualizing proportional color distributions as a horizontal bar.
*
* This widget renders a horizontal bar divided into colored segments whose widths reflect
* the relative values associated with each color key in a `QMap<QString, int>`. The class
* is designed as a small, lightweight, and self-contained visualization component suitable
* for representing distributions such as color counts, mana statistics, categorical frequencies, and similar data sets.
*
* Key features:
* - Filled segments for better visual clarity.
* - Deterministic alphabetical ordering of color keys.
* - Optional minimum percentage threshold for filtering out insignificant segments.
* - Mouse-hover tooltips showing each segments key, count, and percentage of total.
*
* Default color mappings exist for `"R"`, `"G"`, `"U"`, `"W"`, and `"B"`, using named
* colors, but any string recognized by `QColor` may be used. If an unknown name is provided,
* the segment will fall back to gray.
*
* This component is display-only and does not interpret or mutate domain-level data.
*/
class ColorBar : public QWidget class ColorBar : public QWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
/**
* @brief Constructs a ColorBar widget.
*
* @param colors Map of color identifiers to integer counts.
* @param parent Optional parent widget.
*/
explicit ColorBar(const QMap<QString, int> &colors, QWidget *parent = nullptr); explicit ColorBar(const QMap<QString, int> &colors, QWidget *parent = nullptr);
/**
* @brief Updates the color distribution map.
* @param colors New color count mapping.
*
* Triggers an immediate repaint.
*/
void setColors(const QMap<QString, int> &colors); void setColors(const QMap<QString, int> &colors);
/**
* @brief Sets a minimum percentage threshold below which segments are not drawn.
*
* @param treshold Percentage from 0 to 100.
*
* Internally converted into a ratio (0.05 = 5%).
*/
void setMinPercentThreshold(double treshold) void setMinPercentThreshold(double treshold)
{ {
minRatioThreshold = treshold / 100.0; // store as ratio minRatioThreshold = treshold / 100.0;
} }
/**
* @brief Returns the recommended minimum size.
*/
QSize minimumSizeHint() const override; QSize minimumSizeHint() const override;
protected: protected:
/**
* @brief Paints the color distribution bar.
*
* Draws:
* - A rounded border
* - Filled segments for each color
* - Only segments above the minimum ratio threshold
*/
void paintEvent(QPaintEvent *event) override; void paintEvent(QPaintEvent *event) override;
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
/**
* @brief Handles mouse hover entering (Qt6 version).
*/
void enterEvent(QEnterEvent *event) override; void enterEvent(QEnterEvent *event) override;
#else #else
/**
* @brief Handles mouse hover entering (Qt5 version).
*/
void enterEvent(QEvent *event) override; void enterEvent(QEvent *event) override;
#endif #endif
/**
* @brief Handles mouse hover leaving.
*/
void leaveEvent(QEvent *event) override; void leaveEvent(QEvent *event) override;
/**
* @brief Handles mouse movement to update contextual tooltips.
*/
void mouseMoveEvent(QMouseEvent *event) override; void mouseMoveEvent(QMouseEvent *event) override;
private: private:
/// Map of color keys to counts used for rendering.
QMap<QString, int> colors; QMap<QString, int> colors;
bool isHovered = false;
double minRatioThreshold = 0.0; // 0.05 means 5%
/// True if the mouse is currently inside the widget.
bool isHovered = false;
/// Minimum ratio a segment must exceed to be drawn.
double minRatioThreshold = 0.0;
/**
* @brief Converts a color name into a display QColor.
*
* Recognized special keys: `"R", "G", "U", "W", "B"`.
* Other strings are treated as QColor names or fall back to gray.
*/
QColor colorFromName(const QString &name) const; QColor colorFromName(const QString &name) const;
/**
* @brief Returns tooltip text for a given x-coordinate in the bar.
*
* @param x Horizontal coordinate relative to widget.
* @return Tooltip text or empty string if no segment applies.
*/
QString tooltipForPosition(int x) const; QString tooltipForPosition(int x) const;
}; };

View file

@ -14,42 +14,111 @@
#include <QVBoxLayout> #include <QVBoxLayout>
#include <QWidget> #include <QWidget>
/**
* @class ArchidektApiResponseDeckDisplayWidget
* @brief Displays a full deck fetched from an Archidekt API response.
*
* This widget visualizes all cards in a deck retrieved from the Archidekt API.
* It supports:
* - Interactive display options via a VisualDeckDisplayOptionsWidget.
* - Scrollable display of deck zones/cards with DeckCardZoneDisplayWidget.
* - Integration with a CardSizeWidget slider for card scaling.
* - Opening the deck in a deck editor.
*
* The widget internally constructs a DeckListModel from the Archidekt API response,
* then builds zone widgets for each group of cards according to the active group
* criteria. It also responds dynamically to model resets or sorting/grouping changes.
*
* ### Signals
* - `requestNavigation(QString url)` triggered when navigation to a deck URL is requested.
* - `openInDeckEditor(DeckLoader *loader)` emitted when the user chooses to open the deck
* in the deck editor.
*
* ### Features
* - Automatically generates DeckCardZoneDisplayWidget instances for each card group.
* - Provides a scrollable layout for decks of arbitrary size.
* - Updates layouts dynamically when resized or when display/group/sort criteria change.
*/
class ArchidektApiResponseDeckDisplayWidget : public QWidget class ArchidektApiResponseDeckDisplayWidget : public QWidget
{ {
Q_OBJECT Q_OBJECT
signals: signals:
/**
* @brief Emitted when navigation to a deck URL is requested.
* @param url URL of the deck on Archidekt.
*/
void requestNavigation(QString url); void requestNavigation(QString url);
/**
* @brief Emitted when the deck should be opened in the deck editor.
* @param loader Initialized DeckLoader containing the deck data.
*/
void openInDeckEditor(DeckLoader *loader); void openInDeckEditor(DeckLoader *loader);
public: public:
/**
* @brief Constructs a display widget for an Archidekt deck.
* @param parent Parent widget.
* @param response API deck data container.
* @param cardSizeSlider Slider controlling card scaling.
*/
explicit ArchidektApiResponseDeckDisplayWidget(QWidget *parent, explicit ArchidektApiResponseDeckDisplayWidget(QWidget *parent,
ArchidektApiResponseDeck response, ArchidektApiResponseDeck response,
CardSizeWidget *cardSizeSlider); CardSizeWidget *cardSizeSlider);
/**
* @brief Updates all UI text for retranslation/localization.
*
* Called when the application language changes.
*/
void retranslateUi(); void retranslateUi();
/**
* @brief Opens the deck in the deck editor via DeckLoader.
*/
void actOpenInDeckEditor(); void actOpenInDeckEditor();
/**
* @brief Clears all dynamically generated card zone display widgets.
*/
void clearAllDisplayWidgets(); void clearAllDisplayWidgets();
/**
* @brief Handles model reset by clearing and reconstructing display widgets.
*/
void decklistModelReset(); void decklistModelReset();
/**
* @brief Builds DeckCardZoneDisplayWidget instances from the current DeckListModel.
*/
void constructZoneWidgetsFromDeckListModel(); void constructZoneWidgetsFromDeckListModel();
private slots: private slots:
/**
* @brief Slot triggered when the active group criteria change.
* @param activeGroupCriteria Name of the new grouping criteria.
*/
void onGroupCriteriaChange(const QString &activeGroupCriteria); void onGroupCriteriaChange(const QString &activeGroupCriteria);
private: private:
ArchidektApiResponseDeck response; ArchidektApiResponseDeck response; ///< API deck data container
CardSizeWidget *cardSizeSlider; CardSizeWidget *cardSizeSlider; ///< Slider for adjusting card sizes
QVBoxLayout *layout; QVBoxLayout *layout; ///< Main vertical layout
QPushButton *openInEditorButton; QPushButton *openInEditorButton; ///< Button to open deck in editor
VisualDeckDisplayOptionsWidget *displayOptionsWidget; VisualDeckDisplayOptionsWidget *displayOptionsWidget; ///< Controls grouping/sorting/display
QScrollArea *scrollArea; QScrollArea *scrollArea; ///< Scrollable area for deck zones
QWidget *zoneContainer; QWidget *zoneContainer; ///< Container for deck zones
QVBoxLayout *zoneContainerLayout; QVBoxLayout *zoneContainerLayout; ///< Layout for deck zones
QWidget *container; QWidget *container; ///< Outer container for scroll area
QHash<QPersistentModelIndex, QWidget *> indexToWidgetMap; QHash<QPersistentModelIndex, QWidget *> indexToWidgetMap; ///< Maps model indices to widgets
QVBoxLayout *containerLayout; QVBoxLayout *containerLayout; ///< Layout for container
DeckListModel *model; DeckListModel *model; ///< Deck list model
protected slots: protected slots:
/**
* @brief Updates layout and display on resize.
* @param event Resize event.
*/
void resizeEvent(QResizeEvent *event) override; void resizeEvent(QResizeEvent *event) override;
}; };

View file

@ -12,44 +12,110 @@
#include <QWidget> #include <QWidget>
class BackgroundPlateWidget; class BackgroundPlateWidget;
/**
* @class ArchidektApiResponseDeckEntryDisplayWidget
* @brief Displays a single Archidekt deck listing as a preview card with metadata.
*
* This widget renders a deck entry received from an Archidekt API response. It includes:
* - A scaled deck preview image loaded asynchronously via QNetworkAccessManager.
* - Elided deck name in the top-left corner.
* - Deck size, EDH bracket, and view count labels.
* - A color distribution bar summarizing deck colors.
* - Metadata labels including owner, creation date, and last update date.
*
* The widget dynamically scales the preview image and labels according to a linked
* CardSizeWidget slider. Hovering over the widget highlights the background plate,
* and clicking emits a `requestNavigation` signal pointing to the deck URL.
*
* ### Features
* - Asynchronous image loading with fallback to a default placeholder image.
* - Maintains a fixed aspect ratio for the preview image (150:267).
* - Updates text elision dynamically when resized or scaled.
* - Integrates with FlowWidget containers for scrollable deck galleries.
* - Supports Qt5 and Qt6 enterEvent signatures for hover behavior.
*
* ### Signals
* - `requestNavigation(QString url)` emitted when the widget is clicked to request
* navigation to the deck's Archidekt page.
*
* ### Slots
* - `actRequestNavigationToDeck()` programmatically triggers navigation.
* - `setScaleFactor(int scale)` adjusts preview image scaling.
*/
class ArchidektApiResponseDeckEntryDisplayWidget : public QWidget class ArchidektApiResponseDeckEntryDisplayWidget : public QWidget
{ {
Q_OBJECT Q_OBJECT
signals: signals:
/**
* @brief Emitted when the user requests navigation to this deck.
* @param url Full URL to the Archidekt deck page.
*/
void requestNavigation(QString url); void requestNavigation(QString url);
public: public:
/**
* @brief Constructs a deck entry display widget.
* @param parent Parent widget.
* @param response API container holding deck listing data.
* @param imageNetworkManager Shared network manager for fetching preview images.
*/
explicit ArchidektApiResponseDeckEntryDisplayWidget(QWidget *parent, explicit ArchidektApiResponseDeckEntryDisplayWidget(QWidget *parent,
ArchidektApiResponseDeckListingContainer response, ArchidektApiResponseDeckListingContainer response,
QNetworkAccessManager *imageNetworkManager); QNetworkAccessManager *imageNetworkManager);
/**
* @brief Handles finished network replies for preview images.
* @param reply QNetworkReply containing image data.
*
* Validates that the reply corresponds to this widget and updates the preview image.
*/
void onPreviewImageLoadFinished(QNetworkReply *reply); void onPreviewImageLoadFinished(QNetworkReply *reply);
/**
* @brief Updates the scaled preview image and adjusts layout accordingly.
*/
void updateScaledPreview(); void updateScaledPreview();
/**
* @brief Ensures layout responds correctly on resize events.
* @param event Resize event.
*/
void resizeEvent(QResizeEvent *event) override; void resizeEvent(QResizeEvent *event) override;
public slots: public slots:
/**
* @brief Emits `requestNavigation` for the deck's URL.
*/
void actRequestNavigationToDeck(); void actRequestNavigationToDeck();
/**
* @brief Sets a scaling factor (percentage) for the preview image.
* @param scale Scale percentage (100 = normal size).
*/
void setScaleFactor(int scale); void setScaleFactor(int scale);
protected: protected:
void mousePressEvent(QMouseEvent *event) override; void mousePressEvent(QMouseEvent *event) override;
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
void enterEvent(QEnterEvent *event) override; // Qt6 signature void enterEvent(QEnterEvent *event) override; ///< Qt6 hover enter
#else #else
void enterEvent(QEvent *event) override; // Qt5 signature void enterEvent(QEvent *event) override; ///< Qt5 hover enter
#endif #endif
void leaveEvent(QEvent *event) override; void leaveEvent(QEvent *event) override;
private: private:
QVBoxLayout *layout; QVBoxLayout *layout; ///< Main vertical layout
ArchidektApiResponseDeckListingContainer response; ArchidektApiResponseDeckListingContainer response; ///< Deck data
QUrl imageUrl; QUrl imageUrl; ///< URL of the deck's preview image
QNetworkAccessManager *imageNetworkManager; QNetworkAccessManager *imageNetworkManager; ///< Shared network manager
ArchidektDeckPreviewImageDisplayWidget *previewWidget; ArchidektDeckPreviewImageDisplayWidget *previewWidget; ///< Widget showing the deck preview
QLabel *picture; QLabel *picture; ///< QLabel displaying the scaled pixmap
QPixmap originalPixmap; QPixmap originalPixmap; ///< Original image for scaling (avoids degradation)
int scaleFactor = 100; int scaleFactor = 100; ///< Current scaling percentage
BackgroundPlateWidget *backgroundPlateWidget; BackgroundPlateWidget *backgroundPlateWidget; ///< Plate for metadata labels
}; };
#endif // COCKATRICE_ARCHIDEKT_API_RESPONSE_DECK_ENTRY_DISPLAY_WIDGET_H #endif // COCKATRICE_ARCHIDEKT_API_RESPONSE_DECK_ENTRY_DISPLAY_WIDGET_H

View file

@ -11,23 +11,86 @@
#include <QVBoxLayout> #include <QVBoxLayout>
#include <QWidget> #include <QWidget>
/**
* @class ArchidektApiResponseDeckListingsDisplayWidget
* @brief Displays a scrollable horizontal list of Archidekt deck listings with dynamic card sizing.
*
* This widget serves as a container for multiple
* ArchidektApiResponseDeckEntryDisplayWidget instances, each representing one deck listing
* returned from an Archidekt API call.
*
* ### Responsibilities
* - Creates a **FlowWidget** that arranges deck entries horizontally with wrapping.
* - Creates a shared **QNetworkAccessManager** for entry widgets to fetch card thumbnails.
* - Connects a **CardSizeWidget** slider to all deck entries to dynamically rescale their preview cards.
* - Propagates deck-navigation requests (`requestNavigation`) from children to the parent.
*
* ### Layout
* The widget uses a single `QHBoxLayout` containing the `FlowWidget`.
* The FlowWidget automatically manages child flow and scrollbar behavior (horizontal = off,
* vertical = auto), providing an efficient scrollable gallery of deck entries.
*
* ### API Integration
* The constructor consumes an `ArchidektDeckListingApiResponse`, iterates through its
* `results`, and instantiates a child entry widget for each deck.
*
* ### Signals
* - `requestNavigation(QString url)` emitted whenever a child entry widget requests
* navigation to a deck or related Archidekt page.
*
* ### Performance Notes
* - All entry widgets share a single QNetworkAccessManager instance to reuse connections
* and avoid redundant session creation.
* - `resizeEvent()` forces layout invalidation to ensure the flow layout responds properly
* to container resizing.
*/
class ArchidektApiResponseDeckListingsDisplayWidget : public QWidget class ArchidektApiResponseDeckListingsDisplayWidget : public QWidget
{ {
Q_OBJECT Q_OBJECT
signals: signals:
/**
* @brief Emitted when a child deck entry requests that the UI navigate to a particular URL.
* @param url The destination URL (typically an Archidekt deck page).
*/
void requestNavigation(QString url); void requestNavigation(QString url);
public: public:
/**
* @brief Constructs a widget that displays multiple deck listing previews.
*
* @param parent Parent widget.
* @param response The Archidekt API response containing deck listings.
* @param cardSizeSlider A slider widget used to dynamically resize card previews.
*
* Each deck in `response.results` becomes its own
* ArchidektApiResponseDeckEntryDisplayWidget, added to the FlowWidget.
*/
explicit ArchidektApiResponseDeckListingsDisplayWidget(QWidget *parent, explicit ArchidektApiResponseDeckListingsDisplayWidget(QWidget *parent,
ArchidektDeckListingApiResponse response, ArchidektDeckListingApiResponse response,
CardSizeWidget *cardSizeSlider); CardSizeWidget *cardSizeSlider);
/**
* @brief Ensures FlowWidget layout properly recomputes on resize.
*
* Forces the layout to invalidate and activate itself so that the
* FlowWidget recalculates wrapping and child placement.
*
* @param event Resize event.
*/
void resizeEvent(QResizeEvent *event) override; void resizeEvent(QResizeEvent *event) override;
private: private:
/// Slider controlling the scale of card thumbnails in all deck entry widgets.
CardSizeWidget *cardSizeSlider; CardSizeWidget *cardSizeSlider;
/// Main horizontal layout containing the FlowWidget.
QHBoxLayout *layout; QHBoxLayout *layout;
/// Container providing scrollable multi-row flow layout of deck entries.
FlowWidget *flowWidget; FlowWidget *flowWidget;
/// Shared network manager used to download card images for all child entry widgets.
QNetworkAccessManager *imageNetworkManager; QNetworkAccessManager *imageNetworkManager;
}; };