Merge branch 'master' into 6269/ci/strip-fat-bins

This commit is contained in:
Bruno Alexandre Rosa 2025-11-16 00:47:52 -03:00
commit c9686b854b
169 changed files with 2663 additions and 1687 deletions

View file

@ -991,7 +991,7 @@ WARN_LOGFILE =
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
# Note: If this tag is empty the current directory is searched.
INPUT = cockatrice doc/doxygen-groups libcockatrice_card libcockatrice_deck_list libcockatrice_filters libcockatrice_interfaces libcockatrice_models libcockatrice_network libcockatrice_protocol libcockatrice_rng libcockatrice_settings libcockatrice_utility
INPUT = cockatrice doc/doxygen-extra-pages doc/doxygen-groups libcockatrice_card libcockatrice_deck_list libcockatrice_filters libcockatrice_interfaces libcockatrice_models libcockatrice_network libcockatrice_protocol libcockatrice_rng libcockatrice_settings libcockatrice_utility
# This tag can be used to specify the character encoding of the source files
# that Doxygen parses. Internally Doxygen uses the UTF-8 encoding. Doxygen uses
@ -1145,7 +1145,7 @@ EXAMPLE_RECURSIVE = NO
# that contain images that are to be included in the documentation (see the
# \image command).
IMAGE_PATH =
IMAGE_PATH = doc/doxygen-images
# The INPUT_FILTER tag can be used to specify a program that Doxygen should
# invoke to filter for each input file. Doxygen will invoke the filter program

View file

@ -57,27 +57,27 @@ protected:
}
public:
QString getName() const
[[nodiscard]] QString getName() const
{
return name;
}
QString getDescriptionUrl() const
[[nodiscard]] QString getDescriptionUrl() const
{
return descriptionUrl;
}
QString getDownloadUrl() const
[[nodiscard]] QString getDownloadUrl() const
{
return downloadUrl;
}
QString getCommitHash() const
[[nodiscard]] QString getCommitHash() const
{
return commitHash;
}
QDate getPublishDate() const
[[nodiscard]] QDate getPublishDate() const
{
return publishDate;
}
bool isCompatibleVersionFound() const
[[nodiscard]] bool isCompatibleVersionFound() const
{
return compatibleVersionFound;
}
@ -97,15 +97,15 @@ protected:
protected:
static bool downloadMatchesCurrentOS(const QString &fileName);
virtual QString getReleaseChannelUrl() const = 0;
[[nodiscard]] virtual QString getReleaseChannelUrl() const = 0;
public:
Release *getLastRelease()
{
return lastRelease;
}
virtual QString getManualDownloadUrl() const = 0;
virtual QString getName() const = 0;
[[nodiscard]] virtual QString getManualDownloadUrl() const = 0;
[[nodiscard]] virtual QString getName() const = 0;
void checkForUpdates();
signals:
void finishedCheck(bool needToUpdate, bool isCompatible, Release *release);
@ -122,12 +122,12 @@ public:
explicit StableReleaseChannel() = default;
~StableReleaseChannel() override = default;
QString getManualDownloadUrl() const override;
[[nodiscard]] QString getManualDownloadUrl() const override;
QString getName() const override;
[[nodiscard]] QString getName() const override;
protected:
QString getReleaseChannelUrl() const override;
[[nodiscard]] QString getReleaseChannelUrl() const override;
protected slots:
void releaseListFinished() override;
@ -143,12 +143,12 @@ public:
BetaReleaseChannel() = default;
~BetaReleaseChannel() override = default;
QString getManualDownloadUrl() const override;
[[nodiscard]] QString getManualDownloadUrl() const override;
QString getName() const override;
[[nodiscard]] QString getName() const override;
protected:
QString getReleaseChannelUrl() const override;
[[nodiscard]] QString getReleaseChannelUrl() const override;
protected slots:
void releaseListFinished() override;

View file

@ -5,7 +5,7 @@
#include <QtMath>
CardCounterSettings::CardCounterSettings(const QString &settingsPath, QObject *parent)
: SettingsManager(settingsPath + "global.ini", parent)
: SettingsManager(settingsPath + "global.ini", "cards", "counters", parent)
{
}

View file

@ -27,22 +27,22 @@ public:
{
Type = typeCardDrag
};
int type() const override
[[nodiscard]] int type() const override
{
return Type;
}
AbstractCardDragItem(AbstractCardItem *_item, const QPointF &_hotSpot, AbstractCardDragItem *parentDrag = 0);
QRectF boundingRect() const override
[[nodiscard]] QRectF boundingRect() const override
{
return QRectF(0, 0, CARD_WIDTH, CARD_HEIGHT);
}
QPainterPath shape() const override;
[[nodiscard]] QPainterPath shape() const override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
AbstractCardItem *getItem() const
[[nodiscard]] AbstractCardItem *getItem() const
{
return item;
}
QPointF getHotSpot() const
[[nodiscard]] QPointF getHotSpot() const
{
return hotSpot;
}

View file

@ -85,9 +85,13 @@ void AbstractCounter::retranslateUi()
void AbstractCounter::setShortcutsActive()
{
if (!menu) {
return;
}
if (!player->getPlayerInfo()->getLocal()) {
return;
}
ShortcutsSettings &shortcuts = SettingsCache::instance().shortcuts();
if (name == "life") {
shortcutActive = true;
@ -104,6 +108,10 @@ void AbstractCounter::setShortcutsActive()
void AbstractCounter::setShortcutsInactive()
{
if (!menu) {
return;
}
shortcutActive = false;
if (name == "life" || useNameForShortcut) {
aSet->setShortcut(QKeySequence());

View file

@ -36,22 +36,22 @@ public:
ArrowItem(Player *_player, int _id, ArrowTarget *_startItem, ArrowTarget *_targetItem, const QColor &color);
~ArrowItem() override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
QRectF boundingRect() const override
[[nodiscard]] QRectF boundingRect() const override
{
return path.boundingRect();
}
QPainterPath shape() const override
[[nodiscard]] QPainterPath shape() const override
{
return path;
}
void updatePath();
void updatePath(const QPointF &endPoint);
int getId() const
[[nodiscard]] int getId() const
{
return id;
}
Player *getPlayer() const
[[nodiscard]] Player *getPlayer() const
{
return player;
}
@ -63,11 +63,11 @@ public:
{
targetItem = _item;
}
ArrowTarget *getStartItem() const
[[nodiscard]] ArrowTarget *getStartItem() const
{
return startItem;
}
ArrowTarget *getTargetItem() const
[[nodiscard]] ArrowTarget *getTargetItem() const
{
return targetItem;
}

View file

@ -28,18 +28,18 @@ public:
explicit ArrowTarget(Player *_owner, QGraphicsItem *parent = nullptr);
~ArrowTarget() override;
Player *getOwner() const
[[nodiscard]] Player *getOwner() const
{
return owner;
}
void setBeingPointedAt(bool _beingPointedAt);
bool getBeingPointedAt() const
[[nodiscard]] bool getBeingPointedAt() const
{
return beingPointedAt;
}
const QList<ArrowItem *> &getArrowsFrom() const
[[nodiscard]] const QList<ArrowItem *> &getArrowsFrom() const
{
return arrowsFrom;
}
@ -51,7 +51,7 @@ public:
{
arrowsFrom.removeOne(arrow);
}
const QList<ArrowItem *> &getArrowsTo() const
[[nodiscard]] const QList<ArrowItem *> &getArrowsTo() const
{
return arrowsTo;
}

View file

@ -51,7 +51,7 @@ public:
{
Type = typeCard
};
int type() const override
[[nodiscard]] int type() const override
{
return Type;
}
@ -62,13 +62,13 @@ public:
CardZoneLogic *_zone = nullptr);
void retranslateUi();
CardZoneLogic *getZone() const
[[nodiscard]] CardZoneLogic *getZone() const
{
return zone;
}
void setZone(CardZoneLogic *_zone);
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
QPoint getGridPoint() const
[[nodiscard]] QPoint getGridPoint() const
{
return gridPoint;
}
@ -76,11 +76,11 @@ public:
{
gridPoint = _gridPoint;
}
QPoint getGridPos() const
[[nodiscard]] QPoint getGridPos() const
{
return gridPoint;
}
Player *getOwner() const
[[nodiscard]] Player *getOwner() const
{
return owner;
}
@ -88,32 +88,32 @@ public:
{
owner = _owner;
}
bool getAttacking() const
[[nodiscard]] bool getAttacking() const
{
return attacking;
}
void setAttacking(bool _attacking);
const QMap<int, int> &getCounters() const
[[nodiscard]] const QMap<int, int> &getCounters() const
{
return counters;
}
void setCounter(int _id, int _value);
QString getAnnotation() const
[[nodiscard]] QString getAnnotation() const
{
return annotation;
}
void setAnnotation(const QString &_annotation);
bool getDoesntUntap() const
[[nodiscard]] bool getDoesntUntap() const
{
return doesntUntap;
}
void setDoesntUntap(bool _doesntUntap);
QString getPT() const
[[nodiscard]] QString getPT() const
{
return pt;
}
void setPT(const QString &_pt);
bool getDestroyOnZoneChange() const
[[nodiscard]] bool getDestroyOnZoneChange() const
{
return destroyOnZoneChange;
}
@ -121,7 +121,7 @@ public:
{
destroyOnZoneChange = _destroy;
}
CardItem *getAttachedTo() const
[[nodiscard]] CardItem *getAttachedTo() const
{
return attachedTo;
}
@ -134,7 +134,7 @@ public:
{
attachedCards.removeOne(card);
}
const QList<CardItem *> &getAttachedCards() const
[[nodiscard]] const QList<CardItem *> &getAttachedCards() const
{
return attachedCards;
}

View file

@ -41,8 +41,8 @@ void DeckViewCardDragItem::updatePosition(const QPointF &cursorScenePos)
void DeckViewCardDragItem::handleDrop(DeckViewCardContainer *target)
{
DeckViewCard *card = static_cast<DeckViewCard *>(item);
DeckViewCardContainer *start = static_cast<DeckViewCardContainer *>(item->parentItem());
auto *card = static_cast<DeckViewCard *>(item);
auto *start = static_cast<DeckViewCardContainer *>(item->parentItem());
start->removeCard(card);
target->addCard(card);
card->setParentItem(target);
@ -51,13 +51,13 @@ void DeckViewCardDragItem::handleDrop(DeckViewCardContainer *target)
void DeckViewCardDragItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
setCursor(Qt::OpenHandCursor);
DeckViewScene *sc = static_cast<DeckViewScene *>(scene());
auto *sc = static_cast<DeckViewScene *>(scene());
sc->removeItem(this);
if (currentZone) {
handleDrop(currentZone);
for (int i = 0; i < childDrags.size(); i++) {
DeckViewCardDragItem *c = static_cast<DeckViewCardDragItem *>(childDrags[i]);
auto *c = static_cast<DeckViewCardDragItem *>(childDrags[i]);
c->handleDrop(currentZone);
sc->removeItem(c);
}
@ -118,12 +118,12 @@ void DeckViewCard::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
QList<QGraphicsItem *> sel = scene()->selectedItems();
int j = 0;
for (int i = 0; i < sel.size(); i++) {
DeckViewCard *c = static_cast<DeckViewCard *>(sel.at(i));
auto *c = static_cast<DeckViewCard *>(sel.at(i));
if (c == this)
continue;
++j;
QPointF childPos = QPointF(j * CARD_WIDTH / 2, 0);
DeckViewCardDragItem *drag = new DeckViewCardDragItem(c, childPos, dragItem);
auto childPos = QPointF(j * CARD_WIDTH / 2, 0);
auto *drag = new DeckViewCardDragItem(c, childPos, dragItem);
drag->setPos(dragItem->pos() + childPos);
scene()->addItem(drag);
}
@ -140,8 +140,8 @@ void DeckView::mouseDoubleClickEvent(QMouseEvent *event)
QList<QGraphicsItem *> sel = scene()->selectedItems();
for (int i = 0; i < sel.size(); i++) {
DeckViewCard *c = static_cast<DeckViewCard *>(sel.at(i));
DeckViewCardContainer *zone = static_cast<DeckViewCardContainer *>(c->parentItem());
auto *c = static_cast<DeckViewCard *>(sel.at(i));
auto *zone = static_cast<DeckViewCardContainer *>(c->parentItem());
MoveCard_ToZone m;
m.set_card_name(c->getName().toStdString());
m.set_start_zone(zone->getName().toStdString());
@ -345,7 +345,7 @@ void DeckViewScene::rebuildTree()
InnerDecklistNode *listRoot = deck->getRoot();
for (int i = 0; i < listRoot->size(); i++) {
InnerDecklistNode *currentZone = dynamic_cast<InnerDecklistNode *>(listRoot->at(i));
auto *currentZone = dynamic_cast<InnerDecklistNode *>(listRoot->at(i));
DeckViewCardContainer *container = cardContainers.value(currentZone->getName(), 0);
if (!container) {
@ -355,12 +355,12 @@ void DeckViewScene::rebuildTree()
}
for (int j = 0; j < currentZone->size(); j++) {
DecklistCardNode *currentCard = dynamic_cast<DecklistCardNode *>(currentZone->at(j));
auto *currentCard = dynamic_cast<DecklistCardNode *>(currentZone->at(j));
if (!currentCard)
continue;
for (int k = 0; k < currentCard->getNumber(); ++k) {
DeckViewCard *newCard = new DeckViewCard(container, currentCard->toCardRef(), currentZone->getName());
auto *newCard = new DeckViewCard(container, currentCard->toCardRef(), currentZone->getName());
container->addCard(newCard);
emit newCardAdded(newCard);
}

View file

@ -35,7 +35,7 @@ public:
const QString &_originZone = QString());
~DeckViewCard() override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
const QString &getOriginZone() const
[[nodiscard]] const QString &getOriginZone() const
{
return originZone;
}
@ -71,34 +71,34 @@ private:
QMultiMap<QString, DeckViewCard *> cardsByType;
QList<QPair<int, int>> currentRowsAndCols;
qreal width, height;
int getCardTypeTextWidth() const;
[[nodiscard]] int getCardTypeTextWidth() const;
public:
enum
{
Type = typeDeckViewCardContainer
};
int type() const override
[[nodiscard]] int type() const override
{
return Type;
}
explicit DeckViewCardContainer(const QString &_name);
QRectF boundingRect() const override;
[[nodiscard]] QRectF boundingRect() const override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
void addCard(DeckViewCard *card);
void removeCard(DeckViewCard *card);
const QList<DeckViewCard *> &getCards() const
[[nodiscard]] const QList<DeckViewCard *> &getCards() const
{
return cards;
}
const QString &getName() const
[[nodiscard]] const QString &getName() const
{
return name;
}
void setWidth(qreal _width);
QList<QPair<int, int>> getRowsAndCols() const;
QSizeF calculateBoundingRect(const QList<QPair<int, int>> &rowsAndCols) const;
[[nodiscard]] QList<QPair<int, int>> getRowsAndCols() const;
[[nodiscard]] QSizeF calculateBoundingRect(const QList<QPair<int, int>> &rowsAndCols) const;
void rearrangeItems(const QList<QPair<int, int>> &rowsAndCols);
};
@ -123,7 +123,7 @@ public:
{
locked = _locked;
}
bool getLocked() const
[[nodiscard]] bool getLocked() const
{
return locked;
}
@ -135,7 +135,7 @@ public:
}
void rearrangeItems();
void updateContents();
QList<MoveCard_ToZone> getSideboardPlan() const;
[[nodiscard]] QList<MoveCard_ToZone> getSideboardPlan() const;
void resetSideboardPlan();
void applySideboardPlan(const QList<MoveCard_ToZone> &plan);
};
@ -162,7 +162,7 @@ public:
{
deckViewScene->setLocked(_locked);
}
QList<MoveCard_ToZone> getSideboardPlan() const
[[nodiscard]] QList<MoveCard_ToZone> getSideboardPlan() const
{
return deckViewScene->getSideboardPlan();
}

View file

@ -32,7 +32,7 @@ signals:
public:
explicit ToggleButton(QWidget *parent = nullptr);
bool getState() const
[[nodiscard]] bool getState() const
{
return state;
}

View file

@ -67,7 +67,7 @@ DlgCreateToken::DlgCreateToken(const QStringList &_predefinedTokens, QWidget *pa
faceDownCheckBox = new QCheckBox(tr("Create face-down (Only hides name)"));
connect(faceDownCheckBox, &QCheckBox::toggled, this, &DlgCreateToken::faceDownCheckBoxToggled);
QGridLayout *grid = new QGridLayout;
auto *grid = new QGridLayout;
grid->addWidget(nameLabel, 0, 0);
grid->addWidget(nameEdit, 0, 1);
grid->addWidget(colorLabel, 1, 0);
@ -79,7 +79,7 @@ DlgCreateToken::DlgCreateToken(const QStringList &_predefinedTokens, QWidget *pa
grid->addWidget(destroyCheckBox, 4, 0, 1, 2);
grid->addWidget(faceDownCheckBox, 5, 0, 1, 2);
QGroupBox *tokenDataGroupBox = new QGroupBox(tr("Token data"));
auto *tokenDataGroupBox = new QGroupBox(tr("Token data"));
tokenDataGroupBox->setLayout(grid);
cardDatabaseModel = new CardDatabaseModel(CardDatabaseManager::getInstance(), false, this);
@ -125,25 +125,25 @@ DlgCreateToken::DlgCreateToken(const QStringList &_predefinedTokens, QWidget *pa
#endif
}
QVBoxLayout *tokenChooseLayout = new QVBoxLayout;
auto *tokenChooseLayout = new QVBoxLayout;
tokenChooseLayout->addWidget(chooseTokenFromAllRadioButton);
tokenChooseLayout->addWidget(chooseTokenFromDeckRadioButton);
tokenChooseLayout->addWidget(chooseTokenView);
QGroupBox *tokenChooseGroupBox = new QGroupBox(tr("Choose token from list"));
auto *tokenChooseGroupBox = new QGroupBox(tr("Choose token from list"));
tokenChooseGroupBox->setLayout(tokenChooseLayout);
QGridLayout *hbox = new QGridLayout;
auto *hbox = new QGridLayout;
hbox->addWidget(pic, 0, 0, 1, 1);
hbox->addWidget(tokenDataGroupBox, 1, 0, 1, 1);
hbox->addWidget(tokenChooseGroupBox, 0, 1, 2, 1);
hbox->setColumnStretch(1, 1);
QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
auto *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
connect(buttonBox, &QDialogButtonBox::accepted, this, &DlgCreateToken::actOk);
connect(buttonBox, &QDialogButtonBox::rejected, this, &DlgCreateToken::actReject);
QVBoxLayout *mainLayout = new QVBoxLayout;
auto *mainLayout = new QVBoxLayout;
mainLayout->addLayout(hbox);
mainLayout->addWidget(buttonBox);
setLayout(mainLayout);

View file

@ -39,7 +39,7 @@ class DlgCreateToken : public QDialog
Q_OBJECT
public:
explicit DlgCreateToken(const QStringList &_predefinedTokens, QWidget *parent = nullptr);
TokenInfo getTokenInfo() const;
[[nodiscard]] TokenInfo getTokenInfo() const;
protected:
void closeEvent(QCloseEvent *event) override;

View file

@ -34,10 +34,10 @@ public:
QStringList exprs = QStringList(),
uint numberOfHits = 1,
bool autoPlay = false);
QString getExpr() const;
QStringList getExprs() const;
uint getNumberOfHits() const;
bool isAutoPlay() const;
[[nodiscard]] QString getExpr() const;
[[nodiscard]] QStringList getExprs() const;
[[nodiscard]] uint getNumberOfHits() const;
[[nodiscard]] bool isAutoPlay() const;
};
#endif // DLG_MOVE_TOP_CARDS_UNTIL_H

View file

@ -45,10 +45,10 @@ public:
QGraphicsItem *parent = nullptr,
QAction *_doubleClickAction = nullptr,
bool _highlightable = true);
QRectF boundingRect() const override;
[[nodiscard]] QRectF boundingRect() const override;
void setWidth(double _width);
void setActive(bool _active);
bool getActive() const
[[nodiscard]] bool getActive() const
{
return active;
}
@ -77,18 +77,18 @@ private:
public:
explicit PhasesToolbar(QGraphicsItem *parent = nullptr);
QRectF boundingRect() const override;
[[nodiscard]] QRectF boundingRect() const override;
void retranslateUi();
void setHeight(double _height);
double getWidth() const
[[nodiscard]] double getWidth() const
{
return width;
}
int phaseCount() const
[[nodiscard]] int phaseCount() const
{
return buttonList.size();
}
QString getLongPhaseName(int phase) const;
[[nodiscard]] QString getLongPhaseName(int phase) const;
public slots:
void setActivePhase(int phase);
void triggerPhaseAction(int phase);

View file

@ -49,15 +49,15 @@ public:
}
// expose useful actions/menus if PlayerMenu needs them
QMenu *revealLibrary() const
[[nodiscard]] QMenu *revealLibrary() const
{
return mRevealLibrary;
}
QMenu *lendLibraryMenu() const
[[nodiscard]] QMenu *lendLibraryMenu() const
{
return mLendLibrary;
}
QMenu *revealTopCardMenu() const
[[nodiscard]] QMenu *revealTopCardMenu() const
{
return mRevealTopCard;
}

View file

@ -61,7 +61,7 @@ public:
return utilityMenu;
}
bool getShortcutsActive() const
[[nodiscard]] bool getShortcutsActive() const
{
return shortcutsActive;
}

View file

@ -194,7 +194,7 @@ void Player::processPlayerInfo(const ServerInfo_Player &info)
} else {
for (int j = 0; j < cardListSize; ++j) {
const ServerInfo_Card &cardInfo = zoneInfo.card_list(j);
CardItem *card = new CardItem(this);
auto *card = new CardItem(this);
card->processCardInfo(cardInfo);
zone->addCard(card, false, cardInfo.x(), cardInfo.y());
}

View file

@ -63,7 +63,7 @@ public:
void moveOneCardUntil(CardItem *card);
void stopMoveTopCardsUntil();
bool isMovingCardsUntil() const
[[nodiscard]] bool isMovingCardsUntil() const
{
return movingCardsUntil;
}

View file

@ -28,13 +28,13 @@ public:
{
Type = typeOther
};
int type() const override
[[nodiscard]] int type() const override
{
return Type;
}
explicit PlayerArea(QGraphicsItem *parent = nullptr);
QRectF boundingRect() const override
[[nodiscard]] QRectF boundingRect() const override
{
return bRect;
}
@ -43,7 +43,7 @@ public:
void setSize(qreal width, qreal height);
void setPlayerZoneId(int _playerZoneId);
int getPlayerZoneId() const
[[nodiscard]] int getPlayerZoneId() const
{
return playerZoneId;
}

View file

@ -50,8 +50,8 @@ void PlayerGraphicsItem::onPlayerActiveChanged(bool _active)
void PlayerGraphicsItem::initializeZones()
{
deckZoneGraphicsItem = new PileZone(player->getDeckZone(), this);
QPointF base = QPointF(counterAreaWidth + (CARD_HEIGHT - CARD_WIDTH + 15) / 2.0,
10 + playerTarget->boundingRect().height() + 5 - (CARD_HEIGHT - CARD_WIDTH) / 2.0);
auto base = QPointF(counterAreaWidth + (CARD_HEIGHT - CARD_WIDTH + 15) / 2.0,
10 + playerTarget->boundingRect().height() + 5 - (CARD_HEIGHT - CARD_WIDTH) / 2.0);
deckZoneGraphicsItem->setPos(base);
qreal h = deckZoneGraphicsItem->boundingRect().width() + 5;
@ -147,7 +147,7 @@ void PlayerGraphicsItem::rearrangeCounters()
void PlayerGraphicsItem::rearrangeZones()
{
QPointF base = QPointF(CARD_HEIGHT + counterAreaWidth + 15, 0);
auto base = QPointF(CARD_HEIGHT + counterAreaWidth + 15, 0);
if (SettingsCache::instance().getHorizontalHand()) {
if (mirrored) {
if (player->getHandZone()->contentsKnown()) {

View file

@ -27,7 +27,7 @@ bool PlayerListItemDelegate::editorEvent(QEvent *event,
const QModelIndex &index)
{
if ((event->type() == QEvent::MouseButtonPress) && index.isValid()) {
QMouseEvent *const mouseEvent = static_cast<QMouseEvent *>(event);
auto *const mouseEvent = static_cast<QMouseEvent *>(event);
if (mouseEvent->button() == Qt::RightButton) {
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
static_cast<PlayerListWidget *>(parent())->showContextMenu(mouseEvent->globalPosition().toPoint(), index);

View file

@ -27,39 +27,39 @@ public:
bool localPlayerIsSpectator;
QMap<int, ServerInfo_User> spectators;
bool isSpectator() const
[[nodiscard]] bool isSpectator() const
{
return localPlayerIsSpectator;
}
bool isJudge() const
[[nodiscard]] bool isJudge() const
{
return localPlayerIsJudge;
}
int getLocalPlayerId() const
[[nodiscard]] int getLocalPlayerId() const
{
return localPlayerId;
}
const QMap<int, Player *> &getPlayers() const
[[nodiscard]] const QMap<int, Player *> &getPlayers() const
{
return players;
}
int getPlayerCount() const
[[nodiscard]] int getPlayerCount() const
{
return players.size();
}
Player *getActiveLocalPlayer(int activePlayer) const;
[[nodiscard]] Player *getActiveLocalPlayer(int activePlayer) const;
bool isLocalPlayer(int playerId);
Player *addPlayer(int playerId, const ServerInfo_User &info);
void removePlayer(int playerId);
Player *getPlayer(int playerId) const;
[[nodiscard]] Player *getPlayer(int playerId) const;
void onPlayerConceded(int playerId, bool conceded);
@ -70,17 +70,17 @@ public:
return playerId == getLocalPlayerId();
}
const QMap<int, ServerInfo_User> &getSpectators() const
[[nodiscard]] const QMap<int, ServerInfo_User> &getSpectators() const
{
return spectators;
}
ServerInfo_User getSpectator(int playerId) const
[[nodiscard]] ServerInfo_User getSpectator(int playerId) const
{
return spectators.value(playerId);
}
QString getSpectatorName(int spectatorId) const
[[nodiscard]] QString getSpectatorName(int spectatorId) const
{
return QString::fromStdString(spectators.value(spectatorId).name());
}
@ -100,7 +100,7 @@ public:
emit spectatorRemoved(spectatorId, spectatorInfo);
}
AbstractGame *getGame() const
[[nodiscard]] AbstractGame *getGame() const
{
return game;
}

View file

@ -63,16 +63,16 @@ public:
{
cards.sortBy(options);
}
QString getName() const
[[nodiscard]] QString getName() const
{
return name;
}
QString getTranslatedName(bool theirOwn, GrammaticalCase gc) const;
Player *getPlayer() const
[[nodiscard]] QString getTranslatedName(bool theirOwn, GrammaticalCase gc) const;
[[nodiscard]] Player *getPlayer() const
{
return player;
}
bool contentsKnown() const
[[nodiscard]] bool contentsKnown() const
{
return cards.getContentsKnown();
}
@ -84,15 +84,15 @@ public:
{
alwaysRevealTopCard = _alwaysRevealTopCard;
}
bool getAlwaysRevealTopCard() const
[[nodiscard]] bool getAlwaysRevealTopCard() const
{
return alwaysRevealTopCard;
}
bool getHasCardAttr() const
[[nodiscard]] bool getHasCardAttr() const
{
return hasCardAttr;
}
bool getIsShufflable() const
[[nodiscard]] bool getIsShufflable() const
{
return isShufflable;
}

View file

@ -84,7 +84,7 @@ private:
*/
bool active = false;
bool isInverted() const;
[[nodiscard]] bool isInverted() const;
private slots:
/**
@ -110,7 +110,7 @@ public:
/**
@return a QRectF of the TableZone bounding box.
*/
QRectF boundingRect() const override;
[[nodiscard]] QRectF boundingRect() const override;
/**
Render the TableZone
@ -140,12 +140,12 @@ public:
/**
@return CardItem from grid location
*/
CardItem *getCardFromGrid(const QPoint &gridPoint) const;
[[nodiscard]] CardItem *getCardFromGrid(const QPoint &gridPoint) const;
/**
@return CardItem from coordinate location
*/
CardItem *getCardFromCoords(const QPointF &point) const;
[[nodiscard]] CardItem *getCardFromCoords(const QPointF &point) const;
QPointF closestGridPoint(const QPointF &point) override;
@ -157,7 +157,7 @@ public:
*/
void resizeToContents();
int getMinimumWidth() const
[[nodiscard]] int getMinimumWidth() const
{
return currentMinimumWidth;
}
@ -166,7 +166,7 @@ public:
prepareGeometryChange();
width = _width;
}
qreal getWidth() const
[[nodiscard]] qreal getWidth() const
{
return width;
}
@ -188,13 +188,13 @@ private:
/*
Mapping functions for points to/from gridpoints.
*/
QPointF mapFromGrid(QPoint gridPoint) const;
QPoint mapToGrid(const QPointF &mapPoint) const;
[[nodiscard]] QPointF mapFromGrid(QPoint gridPoint) const;
[[nodiscard]] QPoint mapToGrid(const QPointF &mapPoint) const;
/*
Helper function to create a single key from a card stack location.
*/
int getCardStackMapKey(int x, int y) const
[[nodiscard]] int getCardStackMapKey(int x, int y) const
{
return x + (y * 1000);
}

View file

@ -58,12 +58,12 @@ private:
public:
ZoneViewZone(ZoneViewZoneLogic *_logic, QGraphicsItem *parent);
QRectF boundingRect() const override;
[[nodiscard]] QRectF boundingRect() const override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
void reorganizeCards() override;
void initializeCards(const QList<const ServerInfo_Card *> &cardList = QList<const ServerInfo_Card *>());
void setGeometry(const QRectF &rect) override;
QRectF getOptimumRect() const
[[nodiscard]] QRectF getOptimumRect() const
{
return optimumRect;
}
@ -83,7 +83,7 @@ signals:
void wheelEventReceived(QGraphicsSceneWheelEvent *event);
protected:
QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const override;
[[nodiscard]] QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const override;
void wheelEvent(QGraphicsSceneWheelEvent *event) override;
};

View file

@ -1,9 +1,3 @@
/**
* @file card_picture_loader.h
* @ingroup PictureLoader
* @brief TODO: Document this.
*/
#ifndef CARD_PICTURE_LOADER_H
#define CARD_PICTURE_LOADER_H
@ -16,10 +10,37 @@
inline Q_LOGGING_CATEGORY(CardPictureLoaderLog, "card_picture_loader");
inline Q_LOGGING_CATEGORY(CardPictureLoaderCardBackCacheFailLog, "card_picture_loader.card_back_cache_fail");
/**
* @class CardPictureLoader
* @ingroup PictureLoader
* @brief Singleton class to manage card image loading and caching. Provides functionality to asynchronously load,
* cache, and manage card images for the client.
*
* This class is a singleton and handles:
* - Loading card images from disk or network.
* - Caching images in QPixmapCache for fast reuse.
* - Providing themed card backs, including fallback and in-progress/failed states.
* - Emitting updates when pixmaps are loaded.
*
* It interacts with CardPictureLoaderWorker for background loading and
* CardPictureLoaderStatusBar to display loading progress in the main window.
*
* Provides static accessors for:
* - Card images by ExactCard.
* - Card back images (normal, in-progress, failed).
* - Cache management (clearPixmapCache(), clearNetworkCache(), cacheCardPixmaps(const QList<ExactCard> &cards)).
*
* Uses a worker thread for asynchronous image loading and a status bar widget
* to track load progress.
*/
class CardPictureLoader : public QObject
{
Q_OBJECT
public:
/**
* @brief Access the singleton instance of CardPictureLoader.
* @return Reference to the singleton.
*/
static CardPictureLoader &getInstance()
{
static CardPictureLoader instance;
@ -29,30 +50,87 @@ public:
private:
explicit CardPictureLoader();
~CardPictureLoader() override;
// Singleton - Don't implement copy constructor and assign operator
CardPictureLoader(CardPictureLoader const &);
void operator=(CardPictureLoader const &);
CardPictureLoaderWorker *worker;
CardPictureLoaderStatusBar *statusBar;
// Disable copy and assignment for singleton
CardPictureLoader(CardPictureLoader const &) = delete;
void operator=(CardPictureLoader const &) = delete;
CardPictureLoaderWorker *worker; ///< Worker thread for async image loading
CardPictureLoaderStatusBar *statusBar; ///< Status bar widget showing load progress
public:
/**
* @brief Retrieve a card pixmap, either from cache or enqueued for loading.
* @param pixmap Reference to QPixmap where result will be stored.
* @param card ExactCard to load.
* @param size Desired size of pixmap.
*/
static void getPixmap(QPixmap &pixmap, const ExactCard &card, QSize size);
/**
* @brief Retrieve a generic card back pixmap.
* @param pixmap Reference to QPixmap where result will be stored.
* @param size Desired size of pixmap.
*/
static void getCardBackPixmap(QPixmap &pixmap, QSize size);
/**
* @brief Retrieve a card back pixmap for the loading-in-progress state.
* @param pixmap Reference to QPixmap where result will be stored.
* @param size Desired size of pixmap.
*/
static void getCardBackLoadingInProgressPixmap(QPixmap &pixmap, QSize size);
/**
* @brief Retrieve a card back pixmap for the loading-failed state.
* @param pixmap Reference to QPixmap where result will be stored.
* @param size Desired size of pixmap.
*/
static void getCardBackLoadingFailedPixmap(QPixmap &pixmap, QSize size);
static void clearPixmapCache();
/**
* @brief Preload a list of cards into the pixmap cache (limited to CACHED_CARD_PER_DECK_MAX).
* @param cards List of ExactCard objects to preload.
*/
static void cacheCardPixmaps(const QList<ExactCard> &cards);
/**
* @brief Check if the user has custom card art in the picsPath directory.
* @return True if any custom art exists.
*/
static bool hasCustomArt();
/**
* @brief Clears the in-memory QPixmap cache for all cards.
*/
static void clearPixmapCache();
public slots:
/**
* @brief Clears the network disk cache of the worker.
*/
static void clearNetworkCache();
private slots:
void picDownloadChanged();
void picsPathChanged();
public slots:
/**
* @brief Slot called by the worker when an image is loaded.
* Inserts the pixmap into the cache and emits pixmap updated signals.
* @param card ExactCard that was loaded.
* @param image Loaded QImage.
*/
void imageLoaded(const ExactCard &card, const QImage &image);
private slots:
/**
* @brief Triggered when the user changes the picture download settings.
* Clears the QPixmap cache to reload images.
*/
void picDownloadChanged();
/**
* @brief Triggered when the pictures path changes.
* Clears the QPixmap cache to reload images.
*/
void picsPathChanged();
};
#endif

View file

@ -47,12 +47,6 @@ void CardPictureLoaderLocal::refreshIndex()
<< customFolderIndex.size() << "entries.";
}
/**
* Tries to load the card image from the local images.
*
* @param toLoad The card to load
* @return The loaded image, or an empty QImage if loading failed.
*/
QImage CardPictureLoaderLocal::tryLoad(const ExactCard &toLoad) const
{
PrintingInfo setInstance = toLoad.getPrinting();

View file

@ -1,9 +1,3 @@
/**
* @file card_picture_loader_local.h
* @ingroup PictureLoader
* @brief TODO: Document this.
*/
#ifndef PICTURE_LOADER_LOCAL_H
#define PICTURE_LOADER_LOCAL_H
@ -15,32 +9,80 @@
inline Q_LOGGING_CATEGORY(CardPictureLoaderLocalLog, "card_picture_loader.local");
/**
* Handles searching for and loading card images from the local pics and custom image folders.
* This class maintains an index of the CUSTOM folder, to avoid repeatedly searching the entire directory.
* @class CardPictureLoaderLocal
* @ingroup PictureLoader
* @brief Handles searching for and loading card images from local and custom image folders.
*
* This class maintains an index of the CUSTOM folder to avoid repeatedly scanning
* directories, and supports periodic refreshes to update the index.
*
* Responsibilities:
* - Load images for ExactCard objects from local disk or custom folders.
* - Maintain an index for fast lookup of images in the CUSTOM folder.
* - Refresh the index periodically to account for changes in local image directories.
*/
class CardPictureLoaderLocal : public QObject
{
Q_OBJECT
public:
/**
* @brief Constructs a CardPictureLoaderLocal object.
* @param parent Optional parent QObject.
*
* Initializes paths from SettingsCache, connects to settings change signals,
* builds the initial folder index, and starts a periodic refresh timer.
*/
explicit CardPictureLoaderLocal(QObject *parent);
/**
* @brief Attempts to load a card image from local disk or custom folders.
* @param toLoad ExactCard object representing the card to load.
* @return Loaded QImage if found; otherwise, an empty QImage.
*
* Uses a set of name variants and folder paths to attempt to locate the correct image.
*/
QImage tryLoad(const ExactCard &toLoad) const;
private:
QString picsPath, customPicsPath;
QString picsPath; ///< Path to standard card image folder
QString customPicsPath; ///< Path to custom card image folder
QMultiHash<QString, QString> customFolderIndex; // multimap of cardName to picPaths
QTimer *refreshTimer;
QMultiHash<QString, QString> customFolderIndex; ///< Multimap from cardName to file paths in CUSTOM folder
QTimer *refreshTimer; ///< Timer for periodic folder index refresh
/**
* @brief Rebuilds the index of the custom image folder.
*
* Iterates through all subdirectories of the CUSTOM folder and populates
* `customFolderIndex` with all discovered image files keyed by base name
* and complete base name.
*/
void refreshIndex();
/**
* @brief Attempts to load a card image from disk given its set and name info.
* @param setName Corrected short name of the card's set.
* @param correctedCardName Corrected card name (e.g., normalized name).
* @param collectorNumber Collector number of the card.
* @param providerId Optional provider UUID of the card.
* @return Loaded QImage if found; otherwise, an empty QImage.
*
* Searches in both the custom folder index and standard pictures paths.
* Uses several filename patterns to match card images, in order from
* most-specific to least-specific.
*/
QImage tryLoadCardImageFromDisk(const QString &setName,
const QString &correctedCardName,
const QString &collectorNumber,
const QString &providerId) const;
private slots:
/**
* @brief Updates internal paths when the user changes picture settings.
*
* Triggered by `SettingsCache::picsPathChanged`.
*/
void picsPathChanged();
};

View file

@ -1,26 +1,43 @@
/**
* @file card_picture_loader_request_status_display_widget.h
* @ingroup PictureLoader
* @brief TODO: Document this.
*/
#ifndef PICTURE_LOADER_REQUEST_STATUS_DISPLAY_WIDGET_H
#define PICTURE_LOADER_REQUEST_STATUS_DISPLAY_WIDGET_H
#include "card_picture_loader_worker_work.h"
#include <QHBoxLayout>
#include <QLabel>
#include <QWidget>
/**
* @class CardPictureLoaderRequestStatusDisplayWidget
* @ingroup PictureLoader
* @brief A small widget to display the status of a single card image request.
*
* Displays:
* - Card name
* - Set short name
* - Provider ID
* - Start time of request
* - Elapsed time since start
* - Finished status
* - URL of the requested image
*/
class CardPictureLoaderRequestStatusDisplayWidget : public QWidget
{
Q_OBJECT
public:
/**
* @brief Constructs a new status widget for a specific card image request.
* @param parent Parent widget
* @param url URL of the image being requested
* @param card The ExactCard being downloaded
* @param setName Set name for the card
*/
CardPictureLoaderRequestStatusDisplayWidget(QWidget *parent,
const QUrl &url,
const ExactCard &card,
const QString &setName);
/** Marks the request as finished */
void setFinished()
{
finished->setText("True");
@ -28,19 +45,25 @@ public:
repaint();
}
bool getFinished() const
/** Returns whether the request has finished */
[[nodiscard]] bool getFinished() const
{
return finished->text() == "True";
}
/** Updates the elapsed time display */
void setElapsedTime(const QString &_elapsedTime) const
{
elapsedTime->setText(_elapsedTime);
}
/**
* @brief Queries the elapsed time in seconds since the request started
* @return Elapsed time in seconds
*/
int queryElapsedSeconds()
{
if (!finished) {
if (!getFinished()) {
int elapsedSeconds = QDateTime::fromString(startTime->text()).secsTo(QDateTime::currentDateTime());
elapsedTime->setText(QString::number(elapsedSeconds));
update();
@ -50,25 +73,27 @@ public:
return elapsedTime->text().toInt();
}
QString getStartTime() const
/** Returns the start time as a string */
[[nodiscard]] QString getStartTime() const
{
return startTime->text();
}
QString getUrl() const
/** Returns the URL of the request */
[[nodiscard]] QString getUrl() const
{
return url->text();
}
private:
QHBoxLayout *layout;
QLabel *name;
QLabel *setShortname;
QLabel *providerId;
QLabel *startTime;
QLabel *elapsedTime;
QLabel *finished;
QLabel *url;
QHBoxLayout *layout; ///< Horizontal layout for arranging labels
QLabel *name; ///< Card name
QLabel *setShortname; ///< Set short name
QLabel *providerId; ///< Provider ID for the card
QLabel *startTime; ///< Start time of the request
QLabel *elapsedTime; ///< Elapsed time since start
QLabel *finished; ///< Whether the request has finished
QLabel *url; ///< URL of the requested image
};
#endif // PICTURE_LOADER_REQUEST_STATUS_DISPLAY_WIDGET_H

View file

@ -1,9 +1,3 @@
/**
* @file card_picture_loader_status_bar.h
* @ingroup PictureLoader
* @brief TODO: Document this.
*/
#ifndef PICTURE_LOADER_STATUS_BAR_H
#define PICTURE_LOADER_STATUS_BAR_H
@ -12,24 +6,56 @@
#include <QHBoxLayout>
#include <QProgressBar>
#include <QTimer>
#include <QWidget>
/**
* @class CardPictureLoaderStatusBar
* @ingroup PictureLoader
* @brief Displays the status of card image downloads in a horizontal progress bar with a log popup.
*
* Responsibilities:
* - Shows overall progress of image downloads.
* - Maintains a log of individual requests via a popup (SettingsButtonWidget).
* - Cleans up finished request entries automatically after a delay.
*/
class CardPictureLoaderStatusBar : public QWidget
{
Q_OBJECT
public:
/**
* @brief Constructs a status bar with progress bar and log button.
* @param parent Parent widget
*/
explicit CardPictureLoaderStatusBar(QWidget *parent);
public slots:
/**
* @brief Adds a queued image download to the log and increments the progress bar maximum.
* @param url URL of the image
* @param card The card being loaded
* @param setName The set name of the card
*/
void addQueuedImageLoad(const QUrl &url, const ExactCard &card, const QString &setName);
/**
* @brief Marks an image as successfully loaded.
* Updates the progress bar and marks the corresponding log entry as finished.
* @param url URL of the successfully loaded image
*/
void addSuccessfulImageLoad(const QUrl &url);
/**
* @brief Cleans up old entries from the log that have finished more than 10 seconds ago.
* Adjusts the progress bar accordingly.
*/
void cleanOldEntries();
private:
QHBoxLayout *layout;
QProgressBar *progressBar;
SettingsButtonWidget *loadLog;
QTimer *cleaner;
QHBoxLayout *layout; ///< Horizontal layout containing progress bar and log button
QProgressBar *progressBar; ///< Progress bar showing overall download progress
SettingsButtonWidget *loadLog; ///< Popup log showing individual request statuses
QTimer *cleaner; ///< Timer for periodically cleaning old log entries
};
#endif // PICTURE_LOADER_STATUS_BAR_H

View file

@ -105,9 +105,6 @@ void CardPictureLoaderWorker::resetRequestQuota()
processQueuedRequests();
}
/**
* Keeps processing requests from the queue until it is empty or until the quota runs out.
*/
void CardPictureLoaderWorker::processQueuedRequests()
{
while (requestQuota > 0 && processSingleRequest()) {
@ -115,10 +112,6 @@ void CardPictureLoaderWorker::processQueuedRequests()
}
}
/**
* Immediately processes a single queued request. No-ops if the load queue is empty
* @return If a request was processed
*/
bool CardPictureLoaderWorker::processSingleRequest()
{
if (!requestLoadQueue.isEmpty()) {

View file

@ -1,9 +1,3 @@
/**
* @file card_picture_loader_worker.h
* @ingroup PictureLoader
* @brief TODO: Document this.
*/
#ifndef PICTURE_LOADER_WORKER_H
#define PICTURE_LOADER_WORKER_H
@ -27,57 +21,131 @@
#define REDIRECT_TIMESTAMP "timestamp"
#define REDIRECT_CACHE_FILENAME "cache.ini"
inline Q_LOGGING_CATEGORY(CardPictureLoaderWorkerLog, "card_picture_loader.worker");
inline Q_LOGGING_CATEGORY(CardPictureLoaderWorkerLog, "card_picture_loader.worker")
class CardPictureLoaderWorkerWork;
class CardPictureLoaderWorkerWork;
/**
* @class CardPictureLoaderWorker
* @ingroup PictureLoader
* @brief Handles asynchronous loading of card images, both locally and via network.
*
* Responsibilities:
* - Maintain a queue of network image requests with rate-limiting.
* - Load images from local cache first via CardPictureLoaderLocal.
* - Handle network redirects and persistent caching of redirects.
* - Deduplicate simultaneous requests for the same card.
* - Emit signals for status updates and loaded images.
*/
class CardPictureLoaderWorker : public QObject
{
Q_OBJECT
public:
/**
* @brief Constructs a CardPictureLoaderWorker.
*
* Initializes network manager, cache, redirect cache, local loader, and request quota timer.
*/
explicit CardPictureLoaderWorker();
~CardPictureLoaderWorker() override;
void enqueueImageLoad(const ExactCard &card); // Starts a thread for the image to be loaded
void queueRequest(const QUrl &url, CardPictureLoaderWorkerWork *worker); // Queues network requests for load threads
/**
* @brief Enqueues an ExactCard for loading.
* @param card ExactCard to load
*
* This will first try to load the image locally; if that fails, it will enqueue a network request.
*/
void enqueueImageLoad(const ExactCard &card);
/**
* @brief Queues a network request for a given URL and worker thread.
* @param url URL to load
* @param worker Worker handling this request
*/
void queueRequest(const QUrl &url, CardPictureLoaderWorkerWork *worker);
/** @brief Clears the network cache and redirect cache. */
void clearNetworkCache();
public slots:
/**
* @brief Makes a network request for the given URL using the specified worker.
* @param url URL to load
* @param workThread Worker handling the request
* @return The QNetworkReply object representing the request
*/
QNetworkReply *makeRequest(const QUrl &url, CardPictureLoaderWorkerWork *workThread);
/** @brief Processes all queued requests respecting the request quota. */
void processQueuedRequests();
/**
* @brief Processes a single queued request.
* @return true if a request was processed, false if queue is empty.
*/
bool processSingleRequest();
/**
* @brief Handles an image that has finished loading.
* @param card The ExactCard that was loaded
* @param image The loaded QImage; empty if loading failed
*/
void handleImageLoaded(const ExactCard &card, const QImage &image);
/** @brief Caches a redirect mapping between original and redirected URL. */
void cacheRedirect(const QUrl &originalUrl, const QUrl &redirectUrl);
/** @brief Removes a URL from the network cache. */
void removedCachedUrl(const QUrl &url);
private:
QThread *pictureLoaderThread;
QNetworkAccessManager *networkManager;
QNetworkDiskCache *cache;
QHash<QUrl, QPair<QUrl, QDateTime>> redirectCache; // Stores redirect and timestamp
QString cacheFilePath; // Path to persistent storage
static constexpr int CacheTTLInDays = 30; // TODO: Make user configurable
bool picDownload;
QQueue<QPair<QUrl, CardPictureLoaderWorkerWork *>> requestLoadQueue;
QThread *pictureLoaderThread; ///< Thread for executing worker tasks
QNetworkAccessManager *networkManager; ///< Network manager for HTTP requests
QNetworkDiskCache *cache; ///< Disk cache for downloaded images
QHash<QUrl, QPair<QUrl, QDateTime>> redirectCache; ///< Maps original URLs to redirects with timestamp
QString cacheFilePath; ///< Path to persistent redirect cache file
static constexpr int CacheTTLInDays = 30; ///< Time-to-live for redirect cache entries (days)
bool picDownload; ///< Whether downloading images from network is enabled
QQueue<QPair<QUrl, CardPictureLoaderWorkerWork *>> requestLoadQueue; ///< Queue of pending network requests
int requestQuota;
QTimer requestTimer; // Timer for refreshing request quota
int requestQuota; ///< Remaining requests allowed per second
QTimer requestTimer; ///< Timer to reset the request quota
CardPictureLoaderLocal *localLoader;
QSet<QString> currentlyLoading; // for deduplication purposes. Contains pixmapCacheKey
CardPictureLoaderLocal *localLoader; ///< Loader for local images
QSet<QString> currentlyLoading; ///< Deduplication: contains pixmapCacheKey currently being loaded
QUrl getCachedRedirect(const QUrl &originalUrl) const;
/** @brief Returns cached redirect URL for the given original URL, if available. */
[[nodiscard]] QUrl getCachedRedirect(const QUrl &originalUrl) const;
/** @brief Loads redirect cache from disk. */
void loadRedirectCache();
/** @brief Saves redirect cache to disk. */
void saveRedirectCache() const;
/** @brief Removes stale redirect entries older than TTL. */
void cleanStaleEntries();
private slots:
/** @brief Resets the request quota for rate-limiting. */
void resetRequestQuota();
/** @brief Handles image load requests enqueued on this worker. */
void handleImageLoadEnqueued(const ExactCard &card);
signals:
/** @brief Emitted when an image load is enqueued. */
void imageLoadEnqueued(const ExactCard &card);
/** @brief Emitted when an image has finished loading. */
void imageLoaded(const ExactCard &card, const QImage &image);
/** @brief Emitted when a request is added to the network queue. */
void imageRequestQueued(const QUrl &url, const ExactCard &card, const QString &setName);
/** @brief Emitted when a network request successfully completes. */
void imageRequestSucceeded(const QUrl &url);
};

View file

@ -51,10 +51,6 @@ void CardPictureLoaderWorkerWork::startNextPicDownload()
}
}
/**
* Starts another pic download using the next possible url combination for the card.
* If all possibilities are exhausted, then concludes the image loading with an empty QImage.
*/
void CardPictureLoaderWorkerWork::picDownloadFailed()
{
/* Take advantage of short-circuiting here to call the nextUrl until one
@ -73,10 +69,6 @@ void CardPictureLoaderWorkerWork::picDownloadFailed()
}
}
/**
*
* @param reply The reply. Takes ownership of the object
*/
void CardPictureLoaderWorkerWork::handleNetworkReply(QNetworkReply *reply)
{
QVariant redirectTarget = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
@ -180,10 +172,6 @@ void CardPictureLoaderWorkerWork::handleSuccessfulReply(QNetworkReply *reply)
}
}
/**
* @param reply The reply to load the image from
* @return The loaded image, or an empty QImage if loading failed
*/
QImage CardPictureLoaderWorkerWork::tryLoadImageFromReply(QNetworkReply *reply)
{
static constexpr int riffHeaderSize = 12; // RIFF_HEADER_SIZE from webp/format_constants.h
@ -207,10 +195,6 @@ QImage CardPictureLoaderWorkerWork::tryLoadImageFromReply(QNetworkReply *reply)
return imgReader.read();
}
/**
* Call this method when the image has finished being loaded.
* @param image The image that was loaded. Empty QImage indicates failure.
*/
void CardPictureLoaderWorkerWork::concludeImageLoad(const QImage &image)
{
emit imageLoaded(cardToDownload.getCard(), image);

View file

@ -1,9 +1,3 @@
/**
* @file picture_loader_worker_work.h
* @ingroup PictureLoader
* @brief TODO: Document this.
*/
#ifndef PICTURE_LOADER_WORKER_WORK_H
#define PICTURE_LOADER_WORKER_WORK_H
@ -17,55 +11,96 @@
#include <QThread>
#include <libcockatrice/card/database/card_database.h>
#define REDIRECT_HEADER_NAME "redirects"
#define REDIRECT_ORIGINAL_URL "original"
#define REDIRECT_URL "redirect"
#define REDIRECT_TIMESTAMP "timestamp"
#define REDIRECT_CACHE_FILENAME "cache.ini"
inline Q_LOGGING_CATEGORY(CardPictureLoaderWorkerWorkLog, "card_picture_loader.worker");
class CardPictureLoaderWorker;
/**
* @class CardPictureLoaderWorkerWork
* @ingroup PictureLoader
* @brief Handles downloading a single card image from network or local sources.
*
* Responsibilities:
* - Try to load images from all possible URLs and sets for a given ExactCard.
* - Handle network redirects and cache invalidation.
* - Check for blacklisted images and discard them.
* - Emit signals when image is successfully loaded or all attempts fail.
* - Delete itself after loading completes.
*/
class CardPictureLoaderWorkerWork : public QObject
{
Q_OBJECT
public:
/**
* @brief Constructs a worker for downloading a specific card image.
* @param worker The orchestrating CardPictureLoaderWorker
* @param toLoad The ExactCard to download
*/
explicit CardPictureLoaderWorkerWork(const CardPictureLoaderWorker *worker, const ExactCard &toLoad);
CardPictureToLoad cardToDownload;
CardPictureToLoad cardToDownload; ///< The card and associated URLs to try downloading
public slots:
/**
* @brief Handles a finished network reply for the card image.
* @param reply The QNetworkReply object to process. Ownership is transferred.
*/
void handleNetworkReply(QNetworkReply *reply);
private:
bool picDownload;
bool picDownload; ///< Whether network downloading is enabled
/** @brief Starts downloading the next URL for this card. */
void startNextPicDownload();
/** @brief Called when all URLs have been exhausted or download failed. */
void picDownloadFailed();
/** @brief Processes a failed network reply. */
void handleFailedReply(const QNetworkReply *reply);
/** @brief Processes a successful network reply. */
void handleSuccessfulReply(QNetworkReply *reply);
/**
* @brief Attempts to read an image from a network reply.
* @param reply The network reply
* @return The loaded QImage or an empty image if reading failed
*/
QImage tryLoadImageFromReply(QNetworkReply *reply);
/**
* @brief Finalizes the image loading process.
* @param image The loaded image (empty if failed)
*
* Emits imageLoaded() and deletes this object.
*/
void concludeImageLoad(const QImage &image);
private slots:
/** @brief Updates the picDownload setting when it changes. */
void picDownloadChanged();
signals:
/**
* Emitted when this worker has successfully loaded the image or has exhausted all attempts at loading the image.
* Failures are represented by an empty QImage.
* Note that this object will delete itself as this signal is emitted.
* @brief Emitted when the image has been loaded or all attempts failed.
* @param card The card corresponding to the image
* @param image The loaded image (empty if failed)
*
* The worker deletes itself after emitting this signal.
*/
void imageLoaded(const ExactCard &card, const QImage &image);
/**
* Emitted when a request did not return a 400 or 500 response
*/
/** @brief Emitted when a network request completes successfully. */
void requestSucceeded(const QUrl &url);
/** @brief Request that a URL be downloaded. */
void requestImageDownload(const QUrl &url, CardPictureLoaderWorkerWork *instance);
/** @brief Emitted when a URL has been redirected. */
void urlRedirected(const QUrl &originalUrl, const QUrl &redirectUrl);
/** @brief Emitted when a cached URL is invalid and must be removed. */
void cachedUrlInvalidated(const QUrl &url);
};

View file

@ -20,12 +20,6 @@ CardPictureToLoad::CardPictureToLoad(const ExactCard &_card)
}
}
/**
* Extracts a list of all the sets from the card, sorted in priority order.
* If the card does not contain any sets, then a dummy set will be inserted into the list.
*
* @return A list of sets. Will not be empty.
*/
QList<CardSetPtr> CardPictureToLoad::extractSetsSorted(const ExactCard &card)
{
QList<CardSetPtr> sortedSets;
@ -109,11 +103,6 @@ void CardPictureToLoad::populateSetUrls()
(void)nextUrl();
}
/**
* Advances the currentSet to the next set in the list. Then repopulates the url list with the urls from that set.
* If we are already at the end of the list, then currentSet is set to empty.
* @return If we are already at the end of the list
*/
bool CardPictureToLoad::nextSet()
{
if (!sortedSets.isEmpty()) {
@ -125,11 +114,6 @@ bool CardPictureToLoad::nextSet()
return false;
}
/**
* Advances the currentUrl to the next url in the list.
* If we are already at the end of the list, then currentUrl is set to empty.
* @return If we are already at the end of the list
*/
bool CardPictureToLoad::nextUrl()
{
if (!currentSetUrls.isEmpty()) {

View file

@ -1,9 +1,3 @@
/**
* @file card_picture_to_load.h
* @ingroup PictureLoader
* @brief TODO: Document this.
*/
#ifndef PICTURE_TO_LOAD_H
#define PICTURE_TO_LOAD_H
@ -12,37 +6,97 @@
inline Q_LOGGING_CATEGORY(CardPictureToLoadLog, "card_picture_loader.picture_to_load");
/**
* @class CardPictureToLoad
* @ingroup PictureLoader
* @brief Manages all URLs and sets for downloading a specific card image.
*
* Responsibilities:
* - Maintains a sorted list of sets for a card.
* - Generates URLs to download images from, including custom URLs and URL templates.
* - Tracks which URL and set is currently being attempted.
* - Provides helper methods to advance to next URL or set.
*/
class CardPictureToLoad
{
private:
ExactCard card;
QList<CardSetPtr> sortedSets;
QList<QString> urlTemplates;
QList<QString> currentSetUrls;
QString currentUrl;
CardSetPtr currentSet;
ExactCard card; ///< The ExactCard being downloaded
QList<CardSetPtr> sortedSets; ///< All sets for this card, sorted by priority
QList<QString> urlTemplates; ///< URL templates from settings
QList<QString> currentSetUrls; ///< URLs for the current set being attempted
QString currentUrl; ///< Currently active URL to download
CardSetPtr currentSet; ///< Currently active set
public:
/**
* @brief Constructs a CardPictureToLoad for a given ExactCard.
* @param _card The card to download
*
* Initializes URL templates and pre-populates the first set URLs.
*/
explicit CardPictureToLoad(const ExactCard &_card);
const ExactCard &getCard() const
/** @return The card being loaded. */
[[nodiscard]] const ExactCard &getCard() const
{
return card;
}
QString getCurrentUrl() const
/** @return The current URL being attempted. */
[[nodiscard]] QString getCurrentUrl() const
{
return currentUrl;
}
CardSetPtr getCurrentSet() const
/** @return The current set being attempted. */
[[nodiscard]] CardSetPtr getCurrentSet() const
{
return currentSet;
}
QString getSetName() const;
/** @return The short name of the current set, or empty string if no set. */
[[nodiscard]] QString getSetName() const;
/**
* @brief Transforms a URL template into a concrete URL for this card/set.
* @param urlTemplate The URL template to transform
* @return The transformed URL or empty string if the template cannot be fulfilled
*/
QString transformUrl(const QString &urlTemplate) const;
/**
* @brief Advance to the next set in the list.
* @return True if a next set exists and was selected, false if at the end.
*
* Updates currentSet and repopulates currentSetUrls.
* If we are already at the end of the list, then currentSet is set to empty.
*/
bool nextSet();
/**
* @brief Advance to the next URL in the current set's list.
* @return True if a next URL exists, false if at the end.
*
* Updates currentUrl.
* If we are already at the end of the list, then currentUrl is set to empty.
*/
bool nextUrl();
/**
* @brief Populates the currentSetUrls list with URLs for the current set.
*
* Includes custom URLs first, followed by template-based URLs.
*/
void populateSetUrls();
/**
* @brief Extract all sets from the card and sort them by priority.
* @param card The card to extract sets from
* @return A non-empty list of CardSetPtr, sorted by priority
*
* If the card has no sets, a dummy set is inserted. Also ensures
* the printing corresponding to the ExactCard is first in the list.
*/
static QList<CardSetPtr> extractSetsSorted(const ExactCard &card);
};

View file

@ -33,6 +33,7 @@ DeckLoader::DeckLoader(QObject *parent)
DeckLoader::DeckLoader(QObject *parent, DeckList *_deckList)
: QObject(parent), deckList(_deckList), lastFileFormat(CockatriceFormat), lastRemoteDeckId(-1)
{
deckList->setParent(this);
}
DeckLoader::DeckLoader(const DeckLoader &other)
@ -44,6 +45,7 @@ DeckLoader::DeckLoader(const DeckLoader &other)
void DeckLoader::setDeckList(DeckList *_deckList)
{
deckList = _deckList;
deckList->setParent(this);
}
bool DeckLoader::loadFromFile(const QString &fileName, FileFormat fmt, bool userRequest)

View file

@ -27,18 +27,18 @@ public:
void insertWidgetAtIndex(QWidget *toInsert, int index);
void addItem(QLayoutItem *item) override;
int count() const override;
QLayoutItem *itemAt(int index) const override;
[[nodiscard]] int count() const override;
[[nodiscard]] QLayoutItem *itemAt(int index) const override;
QLayoutItem *takeAt(int index) override;
void setGeometry(const QRect &rect) override;
QSize minimumSize() const override;
QSize sizeHint() const override;
[[nodiscard]] QSize minimumSize() const override;
[[nodiscard]] QSize sizeHint() const override;
void setMaxColumns(int _maxColumns);
void setMaxRows(int _maxRows);
int calculateMaxColumns() const;
int calculateRowsForColumns(int columns) const;
int calculateMaxRows() const;
int calculateColumnsForRows(int rows) const;
[[nodiscard]] int calculateMaxColumns() const;
[[nodiscard]] int calculateRowsForColumns(int columns) const;
[[nodiscard]] int calculateMaxRows() const;
[[nodiscard]] int calculateColumnsForRows(int rows) const;
void setDirection(Qt::Orientation _direction);
private:
@ -50,7 +50,7 @@ private:
Qt::Orientation flowDirection;
// Calculate the preferred size of the layout
QSize calculatePreferredSize() const;
[[nodiscard]] QSize calculatePreferredSize() const;
};
#endif // OVERLAP_LAYOUT_H

View file

@ -20,15 +20,15 @@ public:
void toggleSymbol();
void setColorActive(bool active);
void updateOpacity();
bool isColorActive() const
[[nodiscard]] bool isColorActive() const
{
return isActive;
};
QString getSymbol() const
[[nodiscard]] QString getSymbol() const
{
return symbol;
};
QChar getSymbolChar() const
[[nodiscard]] QChar getSymbolChar() const
{
return symbol[0];
};

View file

@ -78,20 +78,14 @@ void ManaBaseWidget::updateDisplay()
QHash<QString, int> ManaBaseWidget::analyzeManaBase()
{
manaBaseMap.clear();
InnerDecklistNode *listRoot = deckListModel->getDeckList()->getRoot();
for (int i = 0; i < listRoot->size(); i++) {
InnerDecklistNode *currentZone = dynamic_cast<InnerDecklistNode *>(listRoot->at(i));
for (int j = 0; j < currentZone->size(); j++) {
DecklistCardNode *currentCard = dynamic_cast<DecklistCardNode *>(currentZone->at(j));
if (!currentCard)
continue;
QList<DecklistCardNode *> cardsInDeck = deckListModel->getDeckList()->getCardNodes();
for (int k = 0; k < currentCard->getNumber(); ++k) {
CardInfoPtr info = CardDatabaseManager::query()->getCardInfo(currentCard->getName());
if (info) {
auto devotion = determineManaProduction(info->getText());
mergeManaCounts(manaBaseMap, devotion);
}
for (auto currentCard : cardsInDeck) {
for (int k = 0; k < currentCard->getNumber(); ++k) {
CardInfoPtr info = CardDatabaseManager::query()->getCardInfo(currentCard->getName());
if (info) {
auto devotion = determineManaProduction(info->getText());
mergeManaCounts(manaBaseMap, devotion);
}
}
}

View file

@ -44,20 +44,15 @@ void ManaCurveWidget::setDeckModel(DeckListModel *deckModel)
std::unordered_map<int, int> ManaCurveWidget::analyzeManaCurve()
{
manaCurveMap.clear();
InnerDecklistNode *listRoot = deckListModel->getDeckList()->getRoot();
for (int i = 0; i < listRoot->size(); i++) {
InnerDecklistNode *currentZone = dynamic_cast<InnerDecklistNode *>(listRoot->at(i));
for (int j = 0; j < currentZone->size(); j++) {
DecklistCardNode *currentCard = dynamic_cast<DecklistCardNode *>(currentZone->at(j));
if (!currentCard)
continue;
for (int k = 0; k < currentCard->getNumber(); ++k) {
CardInfoPtr info = CardDatabaseManager::query()->getCardInfo(currentCard->getName());
if (info) {
int cmc = info->getCmc().toInt();
manaCurveMap[cmc]++;
}
QList<DecklistCardNode *> cardsInDeck = deckListModel->getDeckList()->getCardNodes();
for (auto currentCard : cardsInDeck) {
for (int k = 0; k < currentCard->getNumber(); ++k) {
CardInfoPtr info = CardDatabaseManager::query()->getCardInfo(currentCard->getName());
if (info) {
int cmc = info->getCmc().toInt();
manaCurveMap[cmc]++;
}
}
}

View file

@ -46,20 +46,15 @@ void ManaDevotionWidget::setDeckModel(DeckListModel *deckModel)
std::unordered_map<char, int> ManaDevotionWidget::analyzeManaDevotion()
{
manaDevotionMap.clear();
InnerDecklistNode *listRoot = deckListModel->getDeckList()->getRoot();
for (int i = 0; i < listRoot->size(); i++) {
InnerDecklistNode *currentZone = dynamic_cast<InnerDecklistNode *>(listRoot->at(i));
for (int j = 0; j < currentZone->size(); j++) {
DecklistCardNode *currentCard = dynamic_cast<DecklistCardNode *>(currentZone->at(j));
if (!currentCard)
continue;
for (int k = 0; k < currentCard->getNumber(); ++k) {
CardInfoPtr info = CardDatabaseManager::query()->getCardInfo(currentCard->getName());
if (info) {
auto devotion = countManaSymbols(info->getManaCost());
mergeManaCounts(manaDevotionMap, devotion);
}
QList<DecklistCardNode *> cardsInDeck = deckListModel->getDeckList()->getCardNodes();
for (auto currentCard : cardsInDeck) {
for (int k = 0; k < currentCard->getNumber(); ++k) {
CardInfoPtr info = CardDatabaseManager::query()->getCardInfo(currentCard->getName());
if (info) {
auto devotion = countManaSymbols(info->getManaCost());
mergeManaCounts(manaDevotionMap, devotion);
}
}
}

View file

@ -34,7 +34,7 @@ void DeckEditorDeckDockWidget::createDeckDock()
deckLoader = new DeckLoader(this, deckModel->getDeckList());
DeckListStyleProxy *proxy = new DeckListStyleProxy(this);
proxy = new DeckListStyleProxy(this);
proxy->setSourceModel(deckModel);
deckView = new QTreeView();
@ -233,9 +233,7 @@ ExactCard DeckEditorDeckDockWidget::getCurrentCard()
const QString zoneName = gparent.sibling(gparent.row(), 1).data(Qt::EditRole).toString();
if (!current.model()->hasChildren(current.sibling(current.row(), 0))) {
QString cardName = current.sibling(current.row(), 1).data().toString();
QString providerId = current.sibling(current.row(), 4).data().toString();
if (ExactCard selectedCard = CardDatabaseManager::query()->getCard({cardName, providerId})) {
if (ExactCard selectedCard = CardDatabaseManager::query()->getCard({cardName, cardProviderID})) {
return selectedCard;
}
}
@ -285,18 +283,12 @@ void DeckEditorDeckDockWidget::updateBannerCardComboBox()
// Prepare the new items with deduplication
QSet<QPair<QString, QString>> bannerCardSet;
InnerDecklistNode *listRoot = deckModel->getDeckList()->getRoot();
for (int i = 0; i < listRoot->size(); i++) {
InnerDecklistNode *currentZone = dynamic_cast<InnerDecklistNode *>(listRoot->at(i));
for (int j = 0; j < currentZone->size(); j++) {
DecklistCardNode *currentCard = dynamic_cast<DecklistCardNode *>(currentZone->at(j));
if (!currentCard)
continue;
QList<DecklistCardNode *> cardsInDeck = deckModel->getDeckList()->getCardNodes();
for (int k = 0; k < currentCard->getNumber(); ++k) {
if (CardDatabaseManager::query()->getCard(currentCard->toCardRef())) {
bannerCardSet.insert({currentCard->getName(), currentCard->getCardProviderId()});
}
for (auto currentCard : cardsInDeck) {
for (int k = 0; k < currentCard->getNumber(); ++k) {
if (CardDatabaseManager::query()->getCard(currentCard->toCardRef())) {
bannerCardSet.insert({currentCard->getName(), currentCard->getCardProviderId()});
}
}
}
@ -375,6 +367,7 @@ void DeckEditorDeckDockWidget::syncBannerCardComboBoxSelectionWithDeck()
void DeckEditorDeckDockWidget::setDeck(DeckLoader *_deck)
{
deckLoader = _deck;
deckLoader->setParent(this);
deckModel->setDeckList(deckLoader->getDeckList());
connect(deckLoader, &DeckLoader::deckLoaded, deckModel, &DeckListModel::rebuildTree);
connect(deckLoader->getDeckList(), &DeckList::deckHashChanged, deckModel, &DeckListModel::deckHashChanged);
@ -439,7 +432,9 @@ QModelIndexList DeckEditorDeckDockWidget::getSelectedCardNodes() const
{
auto selectedRows = deckView->selectionModel()->selectedRows();
const auto notLeafNode = [this](const auto &index) { return deckModel->hasChildren(index); };
const auto notLeafNode = [this](const QModelIndex &index) {
return deckModel->hasChildren(proxy->mapToSource(index));
};
selectedRows.erase(std::remove_if(selectedRows.begin(), selectedRows.end(), notLeafNode), selectedRows.end());
std::reverse(selectedRows.begin(), selectedRows.end());
@ -506,7 +501,7 @@ bool DeckEditorDeckDockWidget::swapCard(const QModelIndex &currentIndex)
QModelIndex newCardIndex = card ? deckModel->addCard(card, otherZoneName)
// Third argument (true) says create the card no matter what, even if not in DB
: deckModel->addPreferredPrintingCard(cardName, otherZoneName, true);
recursiveExpand(newCardIndex);
recursiveExpand(proxy->mapToSource(newCardIndex));
return true;
}
@ -527,7 +522,7 @@ void DeckEditorDeckDockWidget::actDecrementCard(const ExactCard &card, QString z
}
deckView->clearSelection();
deckView->setCurrentIndex(idx);
deckView->setCurrentIndex(proxy->mapToSource(idx));
offsetCountAtIndex(idx, -1);
}
@ -563,7 +558,8 @@ void DeckEditorDeckDockWidget::actRemoveCard()
if (!index.isValid() || deckModel->hasChildren(index)) {
continue;
}
deckModel->removeRow(index.row(), index.parent());
QModelIndex sourceIndex = proxy->mapToSource(index);
deckModel->removeRow(sourceIndex.row(), sourceIndex.parent());
isModified = true;
}
@ -580,13 +576,17 @@ void DeckEditorDeckDockWidget::offsetCountAtIndex(const QModelIndex &idx, int of
return;
}
const QModelIndex numberIndex = idx.sibling(idx.row(), 0);
QModelIndex sourceIndex = proxy->mapToSource(idx);
const QModelIndex numberIndex = sourceIndex.sibling(sourceIndex.row(), 0);
const int count = deckModel->data(numberIndex, Qt::EditRole).toInt();
const int new_count = count + offset;
if (new_count <= 0)
deckModel->removeRow(idx.row(), idx.parent());
else
if (new_count <= 0) {
deckModel->removeRow(sourceIndex.row(), sourceIndex.parent());
} else {
deckModel->setData(numberIndex, new_count, Qt::EditRole);
}
emit deckModified();
}

View file

@ -12,6 +12,7 @@
#include "../../key_signals.h"
#include "../utility/custom_line_edit.h"
#include "../visual_deck_storage/deck_preview/deck_preview_deck_tags_display_widget.h"
#include "deck_list_style_proxy.h"
#include <QComboBox>
#include <QDockWidget>
@ -28,6 +29,7 @@ class DeckEditorDeckDockWidget : public QDockWidget
public:
explicit DeckEditorDeckDockWidget(AbstractTabDeckEditor *parent);
DeckLoader *deckLoader;
DeckListStyleProxy *proxy;
DeckListModel *deckModel;
QTreeView *deckView;
QComboBox *bannerCardComboBox;

View file

@ -9,7 +9,7 @@ class DeckListStyleProxy : public QIdentityProxyModel
public:
using QIdentityProxyModel::QIdentityProxyModel;
QVariant data(const QModelIndex &index, int role) const override;
[[nodiscard]] QVariant data(const QModelIndex &index, int role) const override;
};
#endif // COCKATRICE_DECK_LIST_STYLE_PROXY_H

View file

@ -34,16 +34,16 @@ signals:
public:
explicit DlgConnect(QWidget *parent = nullptr);
~DlgConnect() override;
QString getHost() const;
int getPort() const
[[nodiscard]] QString getHost() const;
[[nodiscard]] int getPort() const
{
return portEdit->text().toInt();
}
QString getPlayerName() const
[[nodiscard]] QString getPlayerName() const
{
return playernameEdit->text();
}
QString getPassword() const
[[nodiscard]] QString getPassword() const
{
return passwordEdit->text();
}

View file

@ -35,7 +35,7 @@ void DlgCreateGame::sharedCtor()
maxPlayersEdit->setValue(2);
maxPlayersLabel->setBuddy(maxPlayersEdit);
QGridLayout *generalGrid = new QGridLayout;
auto *generalGrid = new QGridLayout;
generalGrid->addWidget(descriptionLabel, 0, 0);
generalGrid->addWidget(descriptionEdit, 0, 1);
generalGrid->addWidget(maxPlayersLabel, 1, 0);
@ -43,17 +43,17 @@ void DlgCreateGame::sharedCtor()
generalGroupBox = new QGroupBox(tr("General"));
generalGroupBox->setLayout(generalGrid);
QVBoxLayout *gameTypeLayout = new QVBoxLayout;
auto *gameTypeLayout = new QVBoxLayout;
QMapIterator<int, QString> gameTypeIterator(gameTypes);
while (gameTypeIterator.hasNext()) {
gameTypeIterator.next();
QRadioButton *gameTypeRadioButton = new QRadioButton(gameTypeIterator.value(), this);
auto *gameTypeRadioButton = new QRadioButton(gameTypeIterator.value(), this);
gameTypeLayout->addWidget(gameTypeRadioButton);
gameTypeCheckBoxes.insert(gameTypeIterator.key(), gameTypeRadioButton);
bool isChecked = SettingsCache::instance().getGameTypes().contains(gameTypeIterator.value() + ", ");
gameTypeCheckBoxes[gameTypeIterator.key()]->setChecked(isChecked);
}
QGroupBox *gameTypeGroupBox = new QGroupBox(tr("Game type"));
auto *gameTypeGroupBox = new QGroupBox(tr("Game type"));
gameTypeGroupBox->setLayout(gameTypeLayout);
passwordLabel = new QLabel(tr("&Password:"));
@ -70,13 +70,13 @@ void DlgCreateGame::sharedCtor()
onlyRegisteredCheckBox->setEnabled(false);
}
QGridLayout *joinRestrictionsLayout = new QGridLayout;
auto *joinRestrictionsLayout = new QGridLayout;
joinRestrictionsLayout->addWidget(passwordLabel, 0, 0);
joinRestrictionsLayout->addWidget(passwordEdit, 0, 1);
joinRestrictionsLayout->addWidget(onlyBuddiesCheckBox, 1, 0, 1, 2);
joinRestrictionsLayout->addWidget(onlyRegisteredCheckBox, 2, 0, 1, 2);
QGroupBox *joinRestrictionsGroupBox = new QGroupBox(tr("Joining restrictions"));
auto *joinRestrictionsGroupBox = new QGroupBox(tr("Joining restrictions"));
joinRestrictionsGroupBox->setLayout(joinRestrictionsLayout);
spectatorsAllowedCheckBox = new QCheckBox(tr("&Spectators can watch"));
@ -86,7 +86,7 @@ void DlgCreateGame::sharedCtor()
spectatorsCanTalkCheckBox = new QCheckBox(tr("Spectators can &chat"));
spectatorsSeeEverythingCheckBox = new QCheckBox(tr("Spectators can see &hands"));
createGameAsSpectatorCheckBox = new QCheckBox(tr("Create game as spectator"));
QVBoxLayout *spectatorsLayout = new QVBoxLayout;
auto *spectatorsLayout = new QVBoxLayout;
spectatorsLayout->addWidget(spectatorsAllowedCheckBox);
spectatorsLayout->addWidget(spectatorsNeedPasswordCheckBox);
spectatorsLayout->addWidget(spectatorsCanTalkCheckBox);
@ -106,7 +106,7 @@ void DlgCreateGame::sharedCtor()
shareDecklistsOnLoadCheckBox = new QCheckBox();
shareDecklistsOnLoadLabel->setBuddy(shareDecklistsOnLoadCheckBox);
QGridLayout *gameSetupOptionsLayout = new QGridLayout;
auto *gameSetupOptionsLayout = new QGridLayout;
gameSetupOptionsLayout->addWidget(startingLifeTotalLabel, 0, 0);
gameSetupOptionsLayout->addWidget(startingLifeTotalEdit, 0, 1);
gameSetupOptionsLayout->addWidget(shareDecklistsOnLoadLabel, 1, 0);
@ -136,7 +136,7 @@ void DlgCreateGame::sharedCtor()
buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok);
connect(buttonBox, &QDialogButtonBox::rejected, this, &DlgCreateGame::reject);
QVBoxLayout *mainLayout = new QVBoxLayout;
auto *mainLayout = new QVBoxLayout;
mainLayout->addLayout(grid);
mainLayout->addWidget(buttonBox);
@ -275,7 +275,7 @@ void DlgCreateGame::actOK()
cmd.set_starting_life_total(startingLifeTotalEdit->value());
cmd.set_share_decklists_on_load(shareDecklistsOnLoadCheckBox->isChecked());
QString _gameTypes = QString();
auto _gameTypes = QString();
QMapIterator<int, QRadioButton *> gameTypeCheckBoxIterator(gameTypeCheckBoxes);
while (gameTypeCheckBoxIterator.hasNext()) {
gameTypeCheckBoxIterator.next();

View file

@ -23,16 +23,16 @@ DlgEditAvatar::DlgEditAvatar(QWidget *parent) : QDialog(parent), image()
browseButton = new QPushButton(tr("Browse..."));
connect(browseButton, &QPushButton::clicked, this, &DlgEditAvatar::actBrowse);
QGridLayout *grid = new QGridLayout;
auto *grid = new QGridLayout;
grid->addWidget(imageLabel, 0, 0, 1, 2);
grid->addWidget(textLabel, 1, 0);
grid->addWidget(browseButton, 1, 1);
QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
auto *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
connect(buttonBox, &QDialogButtonBox::accepted, this, &DlgEditAvatar::actOk);
connect(buttonBox, &QDialogButtonBox::rejected, this, &DlgEditAvatar::reject);
QVBoxLayout *mainLayout = new QVBoxLayout;
auto *mainLayout = new QVBoxLayout;
mainLayout->addLayout(grid);
mainLayout->addWidget(buttonBox);
setLayout(mainLayout);

View file

@ -23,15 +23,15 @@ public:
QString email = QString(),
QString country = QString(),
QString realName = QString());
QString getEmail() const
[[nodiscard]] QString getEmail() const
{
return emailEdit->text();
}
QString getCountry() const
[[nodiscard]] QString getCountry() const
{
return countryEdit->currentIndex() == 0 ? "" : countryEdit->currentText();
}
QString getRealName() const
[[nodiscard]] QString getRealName() const
{
return realnameEdit->text();
}

View file

@ -66,7 +66,7 @@ DlgForgotPasswordChallenge::DlgForgotPasswordChallenge(QWidget *parent) : QDialo
playernameEdit->hide();
}
QGridLayout *grid = new QGridLayout;
auto *grid = new QGridLayout;
grid->addWidget(infoLabel, 0, 0, 1, 2);
grid->addWidget(hostLabel, 1, 0);
grid->addWidget(hostEdit, 1, 1);
@ -77,11 +77,11 @@ DlgForgotPasswordChallenge::DlgForgotPasswordChallenge(QWidget *parent) : QDialo
grid->addWidget(emailLabel, 4, 0);
grid->addWidget(emailEdit, 4, 1);
QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
auto *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
connect(buttonBox, &QDialogButtonBox::accepted, this, &DlgForgotPasswordChallenge::actOk);
connect(buttonBox, &QDialogButtonBox::rejected, this, &DlgForgotPasswordChallenge::reject);
QVBoxLayout *mainLayout = new QVBoxLayout;
auto *mainLayout = new QVBoxLayout;
mainLayout->addLayout(grid);
mainLayout->addWidget(buttonBox);
setLayout(mainLayout);

View file

@ -20,19 +20,19 @@ class DlgForgotPasswordChallenge : public QDialog
Q_OBJECT
public:
explicit DlgForgotPasswordChallenge(QWidget *parent = nullptr);
QString getHost() const
[[nodiscard]] QString getHost() const
{
return hostEdit->text();
}
int getPort() const
[[nodiscard]] int getPort() const
{
return portEdit->text().toInt();
}
QString getPlayerName() const
[[nodiscard]] QString getPlayerName() const
{
return playernameEdit->text();
}
QString getEmail() const
[[nodiscard]] QString getEmail() const
{
return emailEdit->text();
}

View file

@ -45,7 +45,7 @@ DlgForgotPasswordRequest::DlgForgotPasswordRequest(QWidget *parent) : QDialog(pa
playernameEdit->setMaxLength(MAX_NAME_LENGTH);
playernameLabel->setBuddy(playernameEdit);
QGridLayout *grid = new QGridLayout;
auto *grid = new QGridLayout;
grid->addWidget(infoLabel, 0, 0, 1, 2);
grid->addWidget(hostLabel, 1, 0);
grid->addWidget(hostEdit, 1, 1);
@ -54,11 +54,11 @@ DlgForgotPasswordRequest::DlgForgotPasswordRequest(QWidget *parent) : QDialog(pa
grid->addWidget(playernameLabel, 3, 0);
grid->addWidget(playernameEdit, 3, 1);
QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
auto *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
connect(buttonBox, &QDialogButtonBox::accepted, this, &DlgForgotPasswordRequest::actOk);
connect(buttonBox, &QDialogButtonBox::rejected, this, &DlgForgotPasswordRequest::reject);
QVBoxLayout *mainLayout = new QVBoxLayout;
auto *mainLayout = new QVBoxLayout;
mainLayout->addLayout(grid);
mainLayout->addWidget(buttonBox);
setLayout(mainLayout);

View file

@ -24,7 +24,7 @@ AbstractDlgDeckTextEdit::AbstractDlgDeckTextEdit(QWidget *parent) : QDialog(pare
refreshButton = new QPushButton(tr("&Refresh"));
connect(refreshButton, &QPushButton::clicked, this, &AbstractDlgDeckTextEdit::actRefresh);
QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
auto *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
buttonBox->addButton(refreshButton, QDialogButtonBox::ActionRole);
connect(buttonBox, &QDialogButtonBox::accepted, this, &AbstractDlgDeckTextEdit::actOK);
connect(buttonBox, &QDialogButtonBox::rejected, this, &AbstractDlgDeckTextEdit::reject);

View file

@ -39,7 +39,7 @@ public:
* to use it, since otherwise it will get destroyed once this dlg is destroyed
* @return The DeckLoader
*/
virtual DeckLoader *getDeckList() const = 0;
[[nodiscard]] virtual DeckLoader *getDeckList() const = 0;
protected:
void setText(const QString &text);
@ -67,7 +67,7 @@ private:
public:
explicit DlgLoadDeckFromClipboard(QWidget *parent = nullptr);
DeckLoader *getDeckList() const override
[[nodiscard]] DeckLoader *getDeckList() const override
{
return deckList;
}
@ -90,7 +90,7 @@ private:
public:
explicit DlgEditDeckInClipboard(const DeckLoader &deckList, bool _annotated, QWidget *parent = nullptr);
DeckLoader *getDeckList() const override
[[nodiscard]] DeckLoader *getDeckList() const override
{
return deckLoader;
}

View file

@ -18,7 +18,7 @@ DlgLoadRemoteDeck::DlgLoadRemoteDeck(AbstractClient *_client, QWidget *parent) :
connect(buttonBox, &QDialogButtonBox::accepted, this, &DlgLoadRemoteDeck::accept);
connect(buttonBox, &QDialogButtonBox::rejected, this, &DlgLoadRemoteDeck::reject);
QVBoxLayout *mainLayout = new QVBoxLayout;
auto *mainLayout = new QVBoxLayout;
mainLayout->addWidget(dirView);
mainLayout->addWidget(buttonBox);

View file

@ -28,7 +28,7 @@ private slots:
public:
explicit DlgLoadRemoteDeck(AbstractClient *_client, QWidget *parent = nullptr);
int getDeckId() const;
[[nodiscard]] int getDeckId() const;
};
#endif

View file

@ -321,7 +321,7 @@ DlgRegister::DlgRegister(QWidget *parent) : QDialog(parent)
realnameEdit->setMaxLength(MAX_NAME_LENGTH);
realnameLabel->setBuddy(realnameEdit);
QGridLayout *grid = new QGridLayout;
auto *grid = new QGridLayout;
grid->addWidget(infoLabel, 0, 0, 1, 2);
grid->addWidget(hostLabel, 1, 0);
grid->addWidget(hostEdit, 1, 1);
@ -342,11 +342,11 @@ DlgRegister::DlgRegister(QWidget *parent) : QDialog(parent)
grid->addWidget(realnameLabel, 10, 0);
grid->addWidget(realnameEdit, 10, 1);
QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
auto *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
connect(buttonBox, &QDialogButtonBox::accepted, this, &DlgRegister::actOk);
connect(buttonBox, &QDialogButtonBox::rejected, this, &DlgRegister::reject);
QVBoxLayout *mainLayout = new QVBoxLayout;
auto *mainLayout = new QVBoxLayout;
mainLayout->addLayout(grid);
mainLayout->addWidget(buttonBox);
setLayout(mainLayout);

View file

@ -209,30 +209,19 @@ QMap<QString, int> DlgSelectSetForCards::getSetsForCards()
if (!decklist)
return setCounts;
InnerDecklistNode *listRoot = decklist->getRoot();
if (!listRoot)
return setCounts;
QList<DecklistCardNode *> cardsInDeck = decklist->getCardNodes();
for (auto *i : *listRoot) {
auto *countCurrentZone = dynamic_cast<InnerDecklistNode *>(i);
if (!countCurrentZone)
for (auto currentCard : cardsInDeck) {
CardInfoPtr infoPtr = CardDatabaseManager::query()->getCardInfo(currentCard->getName());
if (!infoPtr)
continue;
for (auto *cardNode : *countCurrentZone) {
auto *currentCard = dynamic_cast<DecklistCardNode *>(cardNode);
if (!currentCard)
continue;
CardInfoPtr infoPtr = CardDatabaseManager::query()->getCardInfo(currentCard->getName());
if (!infoPtr)
continue;
SetToPrintingsMap setMap = infoPtr->getSets();
for (auto &setName : setMap.keys()) {
setCounts[setName]++;
}
SetToPrintingsMap setMap = infoPtr->getSets();
for (auto &setName : setMap.keys()) {
setCounts[setName]++;
}
}
return setCounts;
}
@ -263,48 +252,36 @@ void DlgSelectSetForCards::updateCardLists()
if (!decklist)
return;
InnerDecklistNode *listRoot = decklist->getRoot();
if (!listRoot)
return;
QList<DecklistCardNode *> cardsInDeck = decklist->getCardNodes();
for (auto *i : *listRoot) {
auto *countCurrentZone = dynamic_cast<InnerDecklistNode *>(i);
if (!countCurrentZone)
continue;
for (auto currentCard : cardsInDeck) {
bool found = false;
QString foundSetName;
for (auto *cardNode : *countCurrentZone) {
auto *currentCard = dynamic_cast<DecklistCardNode *>(cardNode);
if (!currentCard)
continue;
bool found = false;
QString foundSetName;
// Check across all sets if the card is present
for (auto it = selectedCardsBySet.begin(); it != selectedCardsBySet.end(); ++it) {
if (it.value().contains(currentCard->getName())) {
found = true;
foundSetName = it.key(); // Store the set name where it was found
break; // Stop at the first match
}
// Check across all sets if the card is present
for (auto it = selectedCardsBySet.begin(); it != selectedCardsBySet.end(); ++it) {
if (it.value().contains(currentCard->getName())) {
found = true;
foundSetName = it.key(); // Store the set name where it was found
break; // Stop at the first match
}
}
if (!found) {
// The card was not in any selected set
ExactCard card = CardDatabaseManager::query()->getCard({currentCard->getName()});
CardInfoPictureWidget *picture_widget = new CardInfoPictureWidget(uneditedCardsFlowWidget);
picture_widget->setCard(card);
uneditedCardsFlowWidget->addWidget(picture_widget);
} else {
ExactCard card = CardDatabaseManager::query()->getCard(
{currentCard->getName(), CardDatabaseManager::getInstance()
->query()
->getSpecificPrinting(currentCard->getName(), foundSetName, "")
.getUuid()});
CardInfoPictureWidget *picture_widget = new CardInfoPictureWidget(modifiedCardsFlowWidget);
picture_widget->setCard(card);
modifiedCardsFlowWidget->addWidget(picture_widget);
}
if (!found) {
// The card was not in any selected set
ExactCard card = CardDatabaseManager::query()->getCard({currentCard->getName()});
CardInfoPictureWidget *picture_widget = new CardInfoPictureWidget(uneditedCardsFlowWidget);
picture_widget->setCard(card);
uneditedCardsFlowWidget->addWidget(picture_widget);
} else {
ExactCard card = CardDatabaseManager::query()->getCard(
{currentCard->getName(), CardDatabaseManager::getInstance()
->query()
->getSpecificPrinting(currentCard->getName(), foundSetName, "")
.getUuid()});
CardInfoPictureWidget *picture_widget = new CardInfoPictureWidget(modifiedCardsFlowWidget);
picture_widget->setCard(card);
modifiedCardsFlowWidget->addWidget(picture_widget);
}
}
}
@ -364,30 +341,19 @@ QMap<QString, QStringList> DlgSelectSetForCards::getCardsForSets()
if (!decklist)
return setCards;
InnerDecklistNode *listRoot = decklist->getRoot();
if (!listRoot)
return setCards;
QList<DecklistCardNode *> cardsInDeck = decklist->getCardNodes();
for (auto *i : *listRoot) {
auto *countCurrentZone = dynamic_cast<InnerDecklistNode *>(i);
if (!countCurrentZone)
for (auto currentCard : cardsInDeck) {
CardInfoPtr infoPtr = CardDatabaseManager::query()->getCardInfo(currentCard->getName());
if (!infoPtr)
continue;
for (auto *cardNode : *countCurrentZone) {
auto *currentCard = dynamic_cast<DecklistCardNode *>(cardNode);
if (!currentCard)
continue;
CardInfoPtr infoPtr = CardDatabaseManager::query()->getCardInfo(currentCard->getName());
if (!infoPtr)
continue;
SetToPrintingsMap setMap = infoPtr->getSets();
for (auto it = setMap.begin(); it != setMap.end(); ++it) {
setCards[it.key()].append(currentCard->getName());
}
SetToPrintingsMap setMap = infoPtr->getSets();
for (auto it = setMap.begin(); it != setMap.end(); ++it) {
setCards[it.key()].append(currentCard->getName());
}
}
return setCards;
}

View file

@ -78,7 +78,7 @@ public:
QStringList getAllCardsForSet();
void populateCardList();
void updateCardDisplayWidgets();
bool isChecked() const;
[[nodiscard]] bool isChecked() const;
DlgSelectSetForCards *parent;
QString setName;
bool expanded;

View file

@ -141,38 +141,38 @@ GeneralSettingsPage::GeneralSettingsPage()
deckPathEdit = new QLineEdit(settings.getDeckPath());
deckPathEdit->setReadOnly(true);
QPushButton *deckPathButton = new QPushButton("...");
auto *deckPathButton = new QPushButton("...");
connect(deckPathButton, &QPushButton::clicked, this, &GeneralSettingsPage::deckPathButtonClicked);
filtersPathEdit = new QLineEdit(settings.getFiltersPath());
filtersPathEdit->setReadOnly(true);
QPushButton *filtersPathButton = new QPushButton("...");
auto *filtersPathButton = new QPushButton("...");
connect(filtersPathButton, &QPushButton::clicked, this, &GeneralSettingsPage::filtersPathButtonClicked);
replaysPathEdit = new QLineEdit(settings.getReplaysPath());
replaysPathEdit->setReadOnly(true);
QPushButton *replaysPathButton = new QPushButton("...");
auto *replaysPathButton = new QPushButton("...");
connect(replaysPathButton, &QPushButton::clicked, this, &GeneralSettingsPage::replaysPathButtonClicked);
picsPathEdit = new QLineEdit(settings.getPicsPath());
picsPathEdit->setReadOnly(true);
QPushButton *picsPathButton = new QPushButton("...");
auto *picsPathButton = new QPushButton("...");
connect(picsPathButton, &QPushButton::clicked, this, &GeneralSettingsPage::picsPathButtonClicked);
cardDatabasePathEdit = new QLineEdit(settings.getCardDatabasePath());
cardDatabasePathEdit->setReadOnly(true);
QPushButton *cardDatabasePathButton = new QPushButton("...");
auto *cardDatabasePathButton = new QPushButton("...");
connect(cardDatabasePathButton, &QPushButton::clicked, this, &GeneralSettingsPage::cardDatabasePathButtonClicked);
customCardDatabasePathEdit = new QLineEdit(settings.getCustomCardDatabasePath());
customCardDatabasePathEdit->setReadOnly(true);
QPushButton *customCardDatabasePathButton = new QPushButton("...");
auto *customCardDatabasePathButton = new QPushButton("...");
connect(customCardDatabasePathButton, &QPushButton::clicked, this,
&GeneralSettingsPage::customCardDatabaseButtonClicked);
tokenDatabasePathEdit = new QLineEdit(settings.getTokenDatabasePath());
tokenDatabasePathEdit->setReadOnly(true);
QPushButton *tokenDatabasePathButton = new QPushButton("...");
auto *tokenDatabasePathButton = new QPushButton("...");
connect(tokenDatabasePathButton, &QPushButton::clicked, this, &GeneralSettingsPage::tokenDatabasePathButtonClicked);
// Required init here to avoid crashing on Portable builds

View file

@ -26,7 +26,7 @@ public:
void setText(const QString &text) const;
void setClickable(bool _clickable);
void setBuddy(QWidget *_buddy);
QString getText() const
[[nodiscard]] QString getText() const
{
return bannerLabel->text();
}

View file

@ -266,35 +266,16 @@ int CardAmountWidget::countCardsInZone(const QString &deckZone)
return -1;
}
InnerDecklistNode *listRoot = decklist->getRoot();
if (!listRoot) {
return -1;
}
QList<DecklistCardNode *> cardsInDeck = decklist->getCardNodes({deckZone});
int count = 0;
for (auto *i : *listRoot) {
auto *countCurrentZone = dynamic_cast<InnerDecklistNode *>(i);
if (!countCurrentZone) {
continue;
}
if (countCurrentZone->getName() != deckZone) {
continue;
}
for (auto *cardNode : *countCurrentZone) {
auto *currentCard = dynamic_cast<DecklistCardNode *>(cardNode);
if (!currentCard) {
continue;
}
for (int k = 0; k < currentCard->getNumber(); ++k) {
if (currentCard->getCardProviderId() == rootCard.getPrinting().getProperty("uuid")) {
count++;
}
for (auto currentCard : cardsInDeck) {
for (int k = 0; k < currentCard->getNumber(); ++k) {
if (currentCard->getCardProviderId() == rootCard.getPrinting().getProperty("uuid")) {
count++;
}
}
}
return count;
}

View file

@ -218,7 +218,7 @@ void PrintingSelector::getAllSetsForCurrentCard()
connect(widgetLoadingBufferTimer, &QTimer::timeout, this, [=, this]() mutable {
for (int i = 0; i < BATCH_SIZE && currentIndex < printingsToUse.size(); ++i, ++currentIndex) {
ExactCard card = ExactCard(selectedCard, printingsToUse[currentIndex]);
auto card = ExactCard(selectedCard, printingsToUse[currentIndex]);
auto *cardDisplayWidget = new PrintingSelectorCardDisplayWidget(
this, deckEditor, deckModel, deckView, cardSizeWidget->getSlider(), card, currentZone);
flowWidget->addWidget(cardDisplayWidget);

View file

@ -36,7 +36,7 @@ public:
void setCard(const CardInfoPtr &newCard, const QString &_currentZone);
void getAllSetsForCurrentCard();
DeckListModel *getDeckModel() const
[[nodiscard]] DeckListModel *getDeckModel() const
{
return deckModel;
};

View file

@ -47,7 +47,7 @@ void PrintingSelectorCardSelectionWidget::connectSignals()
void PrintingSelectorCardSelectionWidget::selectSetForCards()
{
DlgSelectSetForCards *setSelectionDialog = new DlgSelectSetForCards(nullptr, parent->getDeckModel());
auto *setSelectionDialog = new DlgSelectSetForCards(nullptr, parent->getDeckModel());
if (!setSelectionDialog->exec()) {
return;
}

View file

@ -68,7 +68,7 @@ private:
QAction *messageClicked;
QMap<QString, QVector<UserMessagePosition>> userMessagePositions;
QTextFragment getFragmentUnderMouse(const QPoint &pos) const;
[[nodiscard]] QTextFragment getFragmentUnderMouse(const QPoint &pos) const;
QTextCursor prepareBlock(bool same = false);
void appendCardTag(QTextCursor &cursor, const QString &cardName);
void appendUrlTag(QTextCursor &cursor, QString url);

View file

@ -28,7 +28,7 @@ enum GameListColumn
const int DEFAULT_MAX_PLAYERS_MIN = 1;
const int DEFAULT_MAX_PLAYERS_MAX = 99;
constexpr QTime DEFAULT_MAX_GAME_AGE = QTime();
constexpr auto DEFAULT_MAX_GAME_AGE = QTime();
const QString GamesModel::getGameCreatedString(const int secs)
{
@ -333,7 +333,7 @@ void GamesProxyModel::setGameFilters(bool _hideBuddiesOnlyGames,
int GamesProxyModel::getNumFilteredGames() const
{
GamesModel *model = qobject_cast<GamesModel *>(sourceModel());
auto *model = qobject_cast<GamesModel *>(sourceModel());
if (!model)
return 0;

View file

@ -48,7 +48,7 @@ int RemoteReplayList_TreeModel::rowCount(const QModelIndex &parent) const
if (!parent.isValid())
return replayMatches.size();
MatchNode *matchNode = dynamic_cast<MatchNode *>(static_cast<Node *>(parent.internalPointer()));
auto *matchNode = dynamic_cast<MatchNode *>(static_cast<Node *>(parent.internalPointer()));
if (matchNode)
return matchNode->size();
else
@ -62,7 +62,7 @@ QVariant RemoteReplayList_TreeModel::data(const QModelIndex &index, int role) co
if (index.column() >= numberOfColumns)
return QVariant();
ReplayNode *replayNode = dynamic_cast<ReplayNode *>(static_cast<Node *>(index.internalPointer()));
auto *replayNode = dynamic_cast<ReplayNode *>(static_cast<Node *>(index.internalPointer()));
if (replayNode) {
const ServerInfo_Replay &replayInfo = replayNode->getReplayInfo();
switch (role) {
@ -84,7 +84,7 @@ QVariant RemoteReplayList_TreeModel::data(const QModelIndex &index, int role) co
return index.column() == 0 ? fileIcon : QVariant();
}
} else {
MatchNode *matchNode = dynamic_cast<MatchNode *>(static_cast<Node *>(index.internalPointer()));
auto *matchNode = dynamic_cast<MatchNode *>(static_cast<Node *>(index.internalPointer()));
const ServerInfo_ReplayMatch &matchInfo = matchNode->getMatchInfo();
switch (role) {
case Qt::TextAlignmentRole:
@ -170,7 +170,7 @@ QModelIndex RemoteReplayList_TreeModel::index(int row, int column, const QModelI
if (!hasIndex(row, column, parent))
return QModelIndex();
MatchNode *matchNode = dynamic_cast<MatchNode *>(static_cast<Node *>(parent.internalPointer()));
auto *matchNode = dynamic_cast<MatchNode *>(static_cast<Node *>(parent.internalPointer()));
if (matchNode) {
if (row >= matchNode->size())
return QModelIndex();
@ -188,7 +188,7 @@ QModelIndex RemoteReplayList_TreeModel::parent(const QModelIndex &ind) const
if (matchNode)
return QModelIndex();
else {
ReplayNode *replayNode = dynamic_cast<ReplayNode *>(static_cast<Node *>(ind.internalPointer()));
auto *replayNode = dynamic_cast<ReplayNode *>(static_cast<Node *>(ind.internalPointer()));
return createIndex(replayNode->getParent()->indexOf(replayNode), 0, replayNode->getParent());
}
}
@ -206,7 +206,7 @@ ServerInfo_Replay const *RemoteReplayList_TreeModel::getReplay(const QModelIndex
if (!index.isValid())
return 0;
ReplayNode *node = dynamic_cast<ReplayNode *>(static_cast<Node *>(index.internalPointer()));
auto *node = dynamic_cast<ReplayNode *>(static_cast<Node *>(index.internalPointer()));
if (!node)
return 0;
return &node->getReplayInfo();

View file

@ -110,7 +110,7 @@ void UserContextMenu::gamesOfUserReceived(const Response &resp, const CommandCon
gameTypeMap.insert(roomInfo.room_id(), tempMap);
}
GameSelector *selector = new GameSelector(client, tabSupervisor, nullptr, roomMap, gameTypeMap, false, false);
auto *selector = new GameSelector(client, tabSupervisor, nullptr, roomMap, gameTypeMap, false, false);
selector->setParent(static_cast<QWidget *>(parent()), Qt::Window);
const int gameListSize = response.game_list_size();
for (int i = 0; i < gameListSize; ++i) {
@ -128,7 +128,7 @@ void UserContextMenu::banUser_processUserInfoResponse(const Response &r)
const Response_GetUserInfo &response = r.GetExtension(Response_GetUserInfo::ext);
// The dialog needs to be non-modal in order to not block the event queue of the client.
BanDialog *dlg = new BanDialog(response.user_info(), static_cast<QWidget *>(parent()));
auto *dlg = new BanDialog(response.user_info(), static_cast<QWidget *>(parent()));
connect(dlg, &QDialog::accepted, this, &UserContextMenu::banUser_dialogFinished);
dlg->show();
}
@ -141,7 +141,7 @@ void UserContextMenu::warnUser_processGetWarningsListResponse(const Response &r)
QString clientid = QString::fromStdString(response.user_clientid()).simplified();
// The dialog needs to be non-modal in order to not block the event queue of the client.
WarningDialog *dlg = new WarningDialog(user, clientid, static_cast<QWidget *>(parent()));
auto *dlg = new WarningDialog(user, clientid, static_cast<QWidget *>(parent()));
connect(dlg, &QDialog::accepted, this, &UserContextMenu::warnUser_dialogFinished);
if (response.warning_size() > 0) {
@ -171,7 +171,7 @@ void UserContextMenu::banUserHistory_processResponse(const Response &resp)
if (resp.response_code() == Response::RespOk) {
if (response.ban_list_size() > 0) {
QTableWidget *table = new QTableWidget();
auto *table = new QTableWidget();
table->setWindowTitle(tr("Ban History"));
table->setRowCount(response.ban_list_size());
table->setColumnCount(5);
@ -209,7 +209,7 @@ void UserContextMenu::warnUserHistory_processResponse(const Response &resp)
if (resp.response_code() == Response::RespOk) {
if (response.warn_list_size() > 0) {
QTableWidget *table = new QTableWidget();
auto *table = new QTableWidget();
table->setWindowTitle(tr("Warning History"));
table->setRowCount(response.warn_list_size());
table->setColumnCount(4);
@ -278,7 +278,7 @@ void UserContextMenu::adjustMod_processUserResponse(const Response &resp, const
void UserContextMenu::banUser_dialogFinished()
{
BanDialog *dlg = static_cast<BanDialog *>(sender());
auto *dlg = static_cast<BanDialog *>(sender());
Command_BanFromServer cmd;
cmd.set_user_name(dlg->getBanName().toStdString());
@ -297,7 +297,7 @@ void UserContextMenu::banUser_dialogFinished()
void UserContextMenu::warnUser_dialogFinished()
{
WarningDialog *dlg = static_cast<WarningDialog *>(sender());
auto *dlg = static_cast<WarningDialog *>(sender());
if (dlg->getName().isEmpty() || userListProxy->getOwnUsername().simplified().isEmpty())
return;
@ -433,7 +433,7 @@ void UserContextMenu::showContextMenu(const QPoint &pos,
QAction *actionClicked = menu->exec(pos);
if (actionClicked == nullptr) {
} else if (actionClicked == aDetails) {
UserInfoBox *infoWidget =
auto *infoWidget =
new UserInfoBox(client, false, static_cast<QWidget *>(parent()),
Qt::Dialog | Qt::WindowTitleHint | Qt::CustomizeWindowHint | Qt::WindowCloseButtonHint);
infoWidget->setAttribute(Qt::WA_DeleteOnClose);

View file

@ -18,11 +18,11 @@ class ServerInfo_User;
class UserListProxy
{
public:
virtual bool isOwnUserRegistered() const = 0;
virtual QString getOwnUsername() const = 0;
virtual bool isUserBuddy(const QString &userName) const = 0;
virtual bool isUserIgnored(const QString &userName) const = 0;
virtual const ServerInfo_User *getOnlineUser(const QString &userName) const = 0; // Can return nullptr
[[nodiscard]] virtual bool isOwnUserRegistered() const = 0;
[[nodiscard]] virtual QString getOwnUsername() const = 0;
[[nodiscard]] virtual bool isUserBuddy(const QString &userName) const = 0;
[[nodiscard]] virtual bool isUserIgnored(const QString &userName) const = 0;
[[nodiscard]] virtual const ServerInfo_User *getOnlineUser(const QString &userName) const = 0; // Can return nullptr
};
#endif // COCKATRICE_USERLISTPROXY_H

View file

@ -20,39 +20,39 @@ public:
void debugPrint() const;
// Getter methods for card prices
const QJsonObject &getCardhoarder() const
[[nodiscard]] const QJsonObject &getCardhoarder() const
{
return cardhoarder;
}
const QJsonObject &getCardkingdom() const
[[nodiscard]] const QJsonObject &getCardkingdom() const
{
return cardkingdom;
}
const QJsonObject &getCardmarket() const
[[nodiscard]] const QJsonObject &getCardmarket() const
{
return cardmarket;
}
const QJsonObject &getFace2face() const
[[nodiscard]] const QJsonObject &getFace2face() const
{
return face2face;
}
const QJsonObject &getManapool() const
[[nodiscard]] const QJsonObject &getManapool() const
{
return manapool;
}
const QJsonObject &getMtgstocks() const
[[nodiscard]] const QJsonObject &getMtgstocks() const
{
return mtgstocks;
}
const QJsonObject &getScg() const
[[nodiscard]] const QJsonObject &getScg() const
{
return scg;
}
const QJsonObject &getTcgl() const
[[nodiscard]] const QJsonObject &getTcgl() const
{
return tcgl;
}
const QJsonObject &getTcgplayer() const
[[nodiscard]] const QJsonObject &getTcgplayer() const
{
return tcgplayer;
}

View file

@ -20,7 +20,7 @@ public:
explicit TabEdhRec(TabSupervisor *_tabSupervisor);
void retranslateUi() override;
QString getTabText() const override
[[nodiscard]] QString getTabText() const override
{
auto cardName = cardToQuery.isNull() ? QString() : cardToQuery->getName();
return tr("EDHREC: ") + cardName;

View file

@ -64,14 +64,14 @@ TabEdhRecMain::TabEdhRecMain(TabSupervisor *_tabSupervisor) : Tab(_tabSupervisor
auto cardDatabaseModel = new CardDatabaseModel(CardDatabaseManager::getInstance(), false, this);
auto displayModel = new CardDatabaseDisplayModel(this);
displayModel->setSourceModel(cardDatabaseModel);
CardSearchModel *searchModel = new CardSearchModel(displayModel, this);
auto *searchModel = new CardSearchModel(displayModel, this);
CardCompleterProxyModel *proxyModel = new CardCompleterProxyModel(this);
auto *proxyModel = new CardCompleterProxyModel(this);
proxyModel->setSourceModel(searchModel);
proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
proxyModel->setFilterRole(Qt::DisplayRole);
QCompleter *completer = new QCompleter(proxyModel, this);
auto *completer = new QCompleter(proxyModel, this);
completer->setCompletionRole(Qt::DisplayRole);
completer->setCompletionMode(QCompleter::PopupCompletion);
completer->setCaseSensitivity(Qt::CaseInsensitive);

View file

@ -17,22 +17,22 @@
ShutdownDialog::ShutdownDialog(QWidget *parent) : QDialog(parent)
{
QLabel *reasonLabel = new QLabel(tr("&Reason for shutdown:"));
auto *reasonLabel = new QLabel(tr("&Reason for shutdown:"));
reasonEdit = new QLineEdit;
reasonEdit->setMaxLength(MAX_TEXT_LENGTH);
reasonLabel->setBuddy(reasonEdit);
QLabel *minutesLabel = new QLabel(tr("&Time until shutdown (minutes):"));
auto *minutesLabel = new QLabel(tr("&Time until shutdown (minutes):"));
minutesEdit = new QSpinBox;
minutesLabel->setBuddy(minutesEdit);
minutesEdit->setMinimum(0);
minutesEdit->setValue(5);
minutesEdit->setMaximum(999);
QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
auto *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
connect(buttonBox, &QDialogButtonBox::accepted, this, &ShutdownDialog::accept);
connect(buttonBox, &QDialogButtonBox::rejected, this, &ShutdownDialog::reject);
QGridLayout *mainLayout = new QGridLayout;
auto *mainLayout = new QGridLayout;
mainLayout->addWidget(reasonLabel, 0, 0);
mainLayout->addWidget(reasonEdit, 0, 1);
mainLayout->addWidget(minutesLabel, 1, 0);
@ -109,7 +109,7 @@ TabAdmin::TabAdmin(TabSupervisor *_tabSupervisor, AbstractClient *_client, bool
lockButton->setEnabled(false);
connect(lockButton, &QPushButton::clicked, this, &TabAdmin::actLock);
QVBoxLayout *mainLayout = new QVBoxLayout;
auto *mainLayout = new QVBoxLayout;
mainLayout->addWidget(adminGroupBox);
mainLayout->addWidget(moderatorGroupBox);
mainLayout->addStretch();
@ -118,7 +118,7 @@ TabAdmin::TabAdmin(TabSupervisor *_tabSupervisor, AbstractClient *_client, bool
retranslateUi();
QWidget *mainWidget = new QWidget(this);
auto *mainWidget = new QWidget(this);
mainWidget->setLayout(mainLayout);
setCentralWidget(mainWidget);

View file

@ -29,8 +29,8 @@ private:
public:
explicit ShutdownDialog(QWidget *parent = nullptr);
QString getReason() const;
int getMinutes() const;
[[nodiscard]] QString getReason() const;
[[nodiscard]] int getMinutes() const;
};
class TabAdmin : public Tab
@ -62,11 +62,11 @@ private slots:
public:
TabAdmin(TabSupervisor *_tabSupervisor, AbstractClient *_client, bool _fullAdmin);
void retranslateUi() override;
QString getTabText() const override
[[nodiscard]] QString getTabText() const override
{
return tr("Administration");
}
bool getLocked() const
[[nodiscard]] bool getLocked() const
{
return locked;
}

View file

@ -86,7 +86,7 @@ public:
void retranslateUi() override;
/** @brief Returns the tab text, including modified mark if applicable. */
QString getTabText() const override;
[[nodiscard]] QString getTabText() const override;
/** @brief Creates menus for deck editing and view options. */
void createMenus() override;

View file

@ -982,7 +982,7 @@ void TabGame::createMenuItems()
phasesMenu = new TearOffMenu(this);
for (int i = 0; i < phasesToolbar->phaseCount(); ++i) {
QAction *temp = new QAction(QString(), this);
auto *temp = new QAction(QString(), this);
connect(temp, &QAction::triggered, this, &TabGame::actPhaseAction);
phasesMenu->addAction(temp);
phaseActions.append(temp);

View file

@ -183,9 +183,9 @@ public:
void updatePlayerListDockTitle();
bool closeRequest() override;
QString getTabText() const override;
[[nodiscard]] QString getTabText() const override;
AbstractGame *getGame() const
[[nodiscard]] AbstractGame *getGame() const
{
return game;
}

View file

@ -62,7 +62,7 @@ public:
TabLog(TabSupervisor *_tabSupervisor, AbstractClient *_client);
~TabLog() override;
void retranslateUi() override;
QString getTabText() const override
[[nodiscard]] QString getTabText() const override
{
return tr("Logs");
}

View file

@ -34,7 +34,7 @@ TabMessage::TabMessage(TabSupervisor *_tabSupervisor,
sayEdit->setMaxLength(MAX_TEXT_LENGTH);
connect(sayEdit, &LineEditUnfocusable::returnPressed, this, &TabMessage::sendMessage);
QVBoxLayout *vbox = new QVBoxLayout;
auto *vbox = new QVBoxLayout;
vbox->addWidget(chatView);
vbox->addWidget(sayEdit);
@ -47,7 +47,7 @@ TabMessage::TabMessage(TabSupervisor *_tabSupervisor,
retranslateUi();
QWidget *mainWidget = new QWidget(this);
auto *mainWidget = new QWidget(this);
mainWidget->setLayout(vbox);
setCentralWidget(mainWidget);
}

View file

@ -84,7 +84,7 @@ signals:
public:
TabReplays(TabSupervisor *_tabSupervisor, AbstractClient *_client, const ServerInfo_User *currentUserInfo);
void retranslateUi() override;
QString getTabText() const override
[[nodiscard]] QString getTabText() const override
{
return tr("Game Replays");
}

View file

@ -67,7 +67,7 @@ TabRoom::TabRoom(TabSupervisor *_tabSupervisor,
sayLabel->setBuddy(sayEdit);
connect(sayEdit, &LineEditCompleter::returnPressed, this, &TabRoom::sendMessage);
QMenu *chatSettingsMenu = new QMenu(this);
auto *chatSettingsMenu = new QMenu(this);
aClearChat = chatSettingsMenu->addAction(QString());
connect(aClearChat, &QAction::triggered, this, &TabRoom::actClearChat);
@ -77,28 +77,28 @@ TabRoom::TabRoom(TabSupervisor *_tabSupervisor,
aOpenChatSettings = chatSettingsMenu->addAction(QString());
connect(aOpenChatSettings, &QAction::triggered, this, &TabRoom::actOpenChatSettings);
QToolButton *chatSettingsButton = new QToolButton;
auto *chatSettingsButton = new QToolButton;
chatSettingsButton->setIcon(QPixmap("theme:icons/settings"));
chatSettingsButton->setMenu(chatSettingsMenu);
chatSettingsButton->setPopupMode(QToolButton::InstantPopup);
QHBoxLayout *sayHbox = new QHBoxLayout;
auto *sayHbox = new QHBoxLayout;
sayHbox->addWidget(sayLabel);
sayHbox->addWidget(sayEdit);
sayHbox->addWidget(chatSettingsButton);
QVBoxLayout *chatVbox = new QVBoxLayout;
auto *chatVbox = new QVBoxLayout;
chatVbox->addWidget(chatView);
chatVbox->addLayout(sayHbox);
chatGroupBox = new QGroupBox;
chatGroupBox->setLayout(chatVbox);
QSplitter *splitter = new QSplitter(Qt::Vertical);
auto *splitter = new QSplitter(Qt::Vertical);
splitter->addWidget(gameSelector);
splitter->addWidget(chatGroupBox);
QHBoxLayout *hbox = new QHBoxLayout;
auto *hbox = new QHBoxLayout;
hbox->addWidget(splitter, 3);
hbox->addWidget(userList, 1);
@ -133,7 +133,7 @@ TabRoom::TabRoom(TabSupervisor *_tabSupervisor,
retranslateUi();
QWidget *mainWidget = new QWidget(this);
auto *mainWidget = new QWidget(this);
mainWidget->setLayout(hbox);
setCentralWidget(mainWidget);
}

View file

@ -68,7 +68,7 @@ private:
QAction *aLeaveRoom;
QAction *aOpenChatSettings;
QAction *aClearChat;
QString sanitizeHtml(QString dirty) const;
[[nodiscard]] QString sanitizeHtml(QString dirty) const;
QStringList autocompleteUserList;
QCompleter *completer;
@ -106,23 +106,23 @@ public:
void retranslateUi() override;
void tabActivated() override;
void processRoomEvent(const RoomEvent &event);
int getRoomId() const
[[nodiscard]] int getRoomId() const
{
return roomId;
}
const QMap<int, QString> &getGameTypes() const
[[nodiscard]] const QMap<int, QString> &getGameTypes() const
{
return gameTypes;
}
QString getChannelName() const
[[nodiscard]] QString getChannelName() const
{
return roomName;
}
QString getTabText() const override
[[nodiscard]] QString getTabText() const override
{
return roomName;
}
const ServerInfo_User *getUserInfo() const
[[nodiscard]] const ServerInfo_User *getUserInfo() const
{
return ownUser;
}

View file

@ -63,7 +63,7 @@ private:
public:
TabServer(TabSupervisor *_tabSupervisor, AbstractClient *_client);
void retranslateUi() override;
QString getTabText() const override
[[nodiscard]] QString getTabText() const override
{
return tr("Server");
}

View file

@ -931,7 +931,7 @@ void TabSupervisor::deckEditorClosed(AbstractTabDeckEditor *tab)
void TabSupervisor::tabUserEvent(bool globalEvent)
{
Tab *tab = static_cast<Tab *>(sender());
auto *tab = static_cast<Tab *>(sender());
if (tab != currentWidget()) {
tab->setContentsChanged(true);
setTabIcon(indexOf(tab), QPixmap("theme:icons/tab_changed"));
@ -1032,7 +1032,7 @@ void TabSupervisor::processUserJoined(const ServerInfo_User &userInfoJoined)
void TabSupervisor::updateCurrent(int index)
{
if (index != -1) {
Tab *tab = static_cast<Tab *>(widget(index));
auto *tab = static_cast<Tab *>(widget(index));
if (tab->getContentsChanged()) {
setTabIcon(index, QIcon());
tab->setContentsChanged(false);

View file

@ -64,8 +64,8 @@ class CloseButton : public QAbstractButton
Q_OBJECT
public:
explicit CloseButton(QWidget *parent = nullptr);
QSize sizeHint() const override;
inline QSize minimumSizeHint() const override
[[nodiscard]] QSize sizeHint() const override;
[[nodiscard]] QSize minimumSizeHint() const override
{
return sizeHint();
}
@ -129,36 +129,36 @@ public:
void start(const ServerInfo_User &userInfo);
void startLocal(const QList<AbstractClient *> &_clients);
void stop();
bool getIsLocalGame() const
[[nodiscard]] bool getIsLocalGame() const
{
return isLocalGame;
}
int getGameCount() const
[[nodiscard]] int getGameCount() const
{
return gameTabs.size();
}
TabAccount *getTabAccount() const
[[nodiscard]] TabAccount *getTabAccount() const
{
return tabAccount;
}
ServerInfo_User *getUserInfo() const
[[nodiscard]] ServerInfo_User *getUserInfo() const
{
return userInfo;
}
AbstractClient *getClient() const;
const UserListManager *getUserListManager() const
[[nodiscard]] AbstractClient *getClient() const;
[[nodiscard]] const UserListManager *getUserListManager() const
{
return userListManager;
}
const QMap<int, TabRoom *> &getRoomTabs() const
[[nodiscard]] const QMap<int, TabRoom *> &getRoomTabs() const
{
return roomTabs;
}
QList<AbstractTabDeckEditor *> getDeckEditorTabs() const
[[nodiscard]] QList<AbstractTabDeckEditor *> getDeckEditorTabs() const
{
return deckEditorTabs;
}
bool getAdminLocked() const;
[[nodiscard]] bool getAdminLocked() const;
void closeEvent(QCloseEvent *event) override;
bool switchToGameTabIfAlreadyExists(const int gameId);
static void actShowPopup(const QString &message);

View file

@ -23,7 +23,7 @@ private:
public:
TabVisualDatabaseDisplay(TabSupervisor *_tabSupervisor);
void retranslateUi() override;
QString getTabText() const override
[[nodiscard]] QString getTabText() const override
{
return tr("Visual Database Display");
}

View file

@ -125,7 +125,7 @@ public:
* @brief Get the display text for the tab.
* @return Tab text with optional modification indicator.
*/
QString getTabText() const override;
[[nodiscard]] QString getTabText() const override;
/**
* @brief Update the currently selected card in the deck and UI.

View file

@ -73,10 +73,10 @@ public:
void setTabTitle(int index, const QString &title);
/// Get the currently active tab widget.
QWidget *getCurrentTab() const;
[[nodiscard]] QWidget *getCurrentTab() const;
/// Get the total number of tabs.
int getTabCount() const;
[[nodiscard]] int getTabCount() const;
VisualDeckEditorWidget *visualDeckView; ///< Visual deck editor widget.
DeckAnalyticsWidget *deckAnalytics; ///< Deck analytics widget.

View file

@ -67,21 +67,13 @@ void VisualDatabaseDisplayNameFilterWidget::actLoadFromDeck()
DeckList *decklist = deckListModel->getDeckList();
if (!decklist)
return;
InnerDecklistNode *listRoot = decklist->getRoot();
if (!listRoot)
return;
for (int i = 0; i < listRoot->size(); i++) {
InnerDecklistNode *currentZone = dynamic_cast<InnerDecklistNode *>(listRoot->at(i));
if (!currentZone)
continue;
for (int j = 0; j < currentZone->size(); j++) {
DecklistCardNode *currentCard = dynamic_cast<DecklistCardNode *>(currentZone->at(j));
if (!currentCard)
continue;
createNameFilter(currentCard->getName());
}
QList<DecklistCardNode *> cardsInDeck = decklist->getCardNodes();
for (auto currentCard : cardsInDeck) {
createNameFilter(currentCard->getName());
}
updateFilterModel();
}

View file

@ -25,7 +25,7 @@ public:
void retranslateUi();
void createSubTypeButtons();
void updateSubTypeButtonsVisibility();
int getMaxSubTypeCount() const;
[[nodiscard]] int getMaxSubTypeCount() const;
void handleSubTypeToggled(const QString &mainType, bool active);
void updateSubTypeFilter();

View file

@ -83,28 +83,15 @@ QList<ExactCard> VisualDeckEditorSampleHandWidget::getRandomCards(int amountToGe
DeckList *decklist = deckListModel->getDeckList();
if (!decklist)
return randomCards;
InnerDecklistNode *listRoot = decklist->getRoot();
if (!listRoot)
return randomCards;
QList<DecklistCardNode *> cardsInDeck = decklist->getCardNodes({DECK_ZONE_MAIN});
// Collect all cards in the main deck, allowing duplicates based on their count
for (int i = 0; i < listRoot->size(); i++) {
InnerDecklistNode *currentZone = dynamic_cast<InnerDecklistNode *>(listRoot->at(i));
if (!currentZone)
continue;
if (currentZone->getName() != DECK_ZONE_MAIN)
continue; // Only process the main deck
for (int j = 0; j < currentZone->size(); j++) {
DecklistCardNode *currentCard = dynamic_cast<DecklistCardNode *>(currentZone->at(j));
if (!currentCard)
continue;
for (int k = 0; k < currentCard->getNumber(); ++k) {
ExactCard card = CardDatabaseManager::query()->getCard(currentCard->toCardRef());
if (card) {
mainDeckCards.append(card);
}
for (auto currentCard : cardsInDeck) {
for (int k = 0; k < currentCard->getNumber(); ++k) {
ExactCard card = CardDatabaseManager::query()->getCard(currentCard->toCardRef());
if (card) {
mainDeckCards.append(card);
}
}
}

View file

@ -25,7 +25,7 @@ public:
explicit DeckPreviewTagDialog(const QStringList &knownTags,
const QStringList &activeTags,
QWidget *parent = nullptr);
QStringList getActiveTags() const;
[[nodiscard]] QStringList getActiveTags() const;
void filterTags(const QString &text);
private slots:

View file

@ -19,7 +19,7 @@ public:
DeckPreviewTagItemWidget(const QString &tagName, bool isChecked, QWidget *parent = nullptr);
// Accessor for the checkbox widget
QCheckBox *checkBox() const;
[[nodiscard]] QCheckBox *checkBox() const;
private:
QCheckBox *checkBox_; // Checkbox to represent the tag's state

View file

@ -232,17 +232,12 @@ void DeckPreviewWidget::updateBannerCardComboBox()
// Prepare the new items with deduplication
QSet<QPair<QString, QString>> bannerCardSet;
InnerDecklistNode *listRoot = deckLoader->getDeckList()->getRoot();
for (auto i : *listRoot) {
auto *currentZone = dynamic_cast<InnerDecklistNode *>(i);
for (auto j : *currentZone) {
auto *currentCard = dynamic_cast<DecklistCardNode *>(j);
if (!currentCard)
continue;
for (int k = 0; k < currentCard->getNumber(); ++k) {
bannerCardSet.insert(QPair<QString, QString>(currentCard->getName(), currentCard->getCardProviderId()));
}
QList<DecklistCardNode *> cardsInDeck = deckLoader->getDeckList()->getCardNodes();
for (auto currentCard : cardsInDeck) {
for (int k = 0; k < currentCard->getNumber(); ++k) {
bannerCardSet.insert(QPair<QString, QString>(currentCard->getName(), currentCard->getCardProviderId()));
}
}

View file

@ -33,7 +33,7 @@ public:
const QString &_filePath);
void retranslateUi();
QString getColorIdentity();
QString getDisplayName() const;
[[nodiscard]] QString getDisplayName() const;
VisualDeckStorageWidget *visualDeckStorageWidget;
QVBoxLayout *layout;
@ -47,7 +47,7 @@ public:
bool filteredBySearch = false;
bool filteredByColor = false;
bool filteredByTags = false;
bool checkVisibility() const;
[[nodiscard]] bool checkVisibility() const;
signals:
void deckLoadRequested(const QString &filePath);

View file

@ -27,8 +27,8 @@ public:
void createWidgetsForFiles();
void createWidgetsForFolders();
void flattenFolderStructure();
QStringList gatherAllTagsFromFlowWidget() const;
FlowWidget *getFlowWidget() const
[[nodiscard]] QStringList gatherAllTagsFromFlowWidget() const;
[[nodiscard]] FlowWidget *getFlowWidget() const
{
return flowWidget;
};

View file

@ -47,14 +47,14 @@ public:
void retranslateUi();
bool getShowFolders() const;
bool getDrawUnusedColorIdentities() const;
bool getShowBannerCardComboBox() const;
bool getShowTagFilter() const;
bool getShowTagsOnDeckPreviews() const;
int getUnusedColorIdentitiesOpacity() const;
TooltipType getDeckPreviewTooltip() const;
int getCardSize() const;
[[nodiscard]] bool getShowFolders() const;
[[nodiscard]] bool getDrawUnusedColorIdentities() const;
[[nodiscard]] bool getShowBannerCardComboBox() const;
[[nodiscard]] bool getShowTagFilter() const;
[[nodiscard]] bool getShowTagsOnDeckPreviews() const;
[[nodiscard]] int getUnusedColorIdentitiesOpacity() const;
[[nodiscard]] TooltipType getDeckPreviewTooltip() const;
[[nodiscard]] int getCardSize() const;
signals:
void showFoldersChanged(bool enabled);

View file

@ -18,7 +18,7 @@ class VisualDeckStorageTagFilterWidget : public QWidget
VisualDeckStorageWidget *parent;
QSet<QString> gatherAllTags() const;
[[nodiscard]] QSet<QString> gatherAllTags() const;
void removeTagsNotInList(const QSet<QString> &tags);
void addTagsIfNotPresent(const QSet<QString> &tags);
void addTagIfNotPresent(const QString &tag);
@ -26,7 +26,7 @@ class VisualDeckStorageTagFilterWidget : public QWidget
public:
explicit VisualDeckStorageTagFilterWidget(VisualDeckStorageWidget *_parent);
QStringList getAllKnownTags() const;
[[nodiscard]] QStringList getAllKnownTags() const;
void filterDecksBySelectedTags(const QList<DeckPreviewWidget *> &deckPreviews) const;
public slots:

Some files were not shown because too many files have changed in this diff Show more