From 1a62f82aeed2086210c194442988b4e6e021f552 Mon Sep 17 00:00:00 2001 From: DawnFire42 Date: Sun, 10 May 2026 22:10:14 -0400 Subject: [PATCH 01/51] Refactor vertical card stacking with clip containers for variable zone sizes (#6774) * Refactor vertical card stacking with opt-in overflow for variable zone sizes Introduce a shared vertical stacking layout system in SelectZone that replaces the old divideCardSpaceInZone() free function with structured layout computation (StackLayoutParams, ZoneLayout, computeZoneLayout). By default, cards are guaranteed to fit within zone bounds (no overflow). Zones can opt-in to bottom overflow via allowBottomOverflow flag, with sqrt-scaled compression for smooth visual transitions. A clip container mechanism is available for future zones that need visual clipping. Key changes: - SelectZone: new layout engine with allowBottomOverflow opt-in; clip container infrastructure for future zones needing visual clipping - StackZone: uses new layout (no overflow); adds setHeight() for dynamic resizing capabilities - HandZone: vertical layout delegates to SelectZone's shared stacking - AbstractCardItem: preserves hover z-value during layout passes; invalidates scene rect on hover exit for proper sibling repainting - CardZone::onCardAdded made virtual for clip container reparenting - Zone widths updated to CardDimensions::WIDTH_F * 1.5 * Changed anonymous namespace for static and braced functions * CI tests re-run --- .../src/game/board/abstract_card_item.cpp | 16 +- .../src/game/board/abstract_card_item.h | 6 +- cockatrice/src/game/game_scene.cpp | 21 +- cockatrice/src/game/game_scene.h | 6 + cockatrice/src/game/zones/card_zone.cpp | 1 + cockatrice/src/game/zones/card_zone.h | 7 +- cockatrice/src/game/zones/hand_zone.cpp | 58 +++-- cockatrice/src/game/zones/hand_zone.h | 5 +- cockatrice/src/game/zones/select_zone.cpp | 209 ++++++++++++++++-- cockatrice/src/game/zones/select_zone.h | 109 ++++++++- cockatrice/src/game/zones/stack_zone.cpp | 71 +++--- cockatrice/src/game/zones/stack_zone.h | 4 +- 12 files changed, 402 insertions(+), 111 deletions(-) diff --git a/cockatrice/src/game/board/abstract_card_item.cpp b/cockatrice/src/game/board/abstract_card_item.cpp index 9ec6ada9a..a519fa4b6 100644 --- a/cockatrice/src/game/board/abstract_card_item.cpp +++ b/cockatrice/src/game/board/abstract_card_item.cpp @@ -85,7 +85,11 @@ const CardInfo &AbstractCardItem::getCardInfo() const void AbstractCardItem::setRealZValue(qreal _zValue) { realZValue = _zValue; - setZValue(_zValue); + // During hover, zValue is overridden to HOVERED_CARD. Layout operations + // like reorganizeCards() call setRealZValue() on all cards including the + // hovered one — skip setZValue() here to avoid clobbering the override. + if (!isHovered) + setZValue(_zValue); } QSizeF AbstractCardItem::getTranslatedSize(QPainter *painter) const @@ -213,8 +217,16 @@ void AbstractCardItem::setHovered(bool _hovered) if (isHovered == _hovered) return; - if (_hovered) + if (_hovered) { processHoverEvent(); + } else { + // Mark the hovered card's current scene footprint dirty so overlapped + // sibling zones (e.g. StackZone) repaint after the card moves away. + if (scene()) { + scene()->update(sceneBoundingRect()); + } + } + isHovered = _hovered; setZValue(_hovered ? ZValues::HOVERED_CARD : realZValue); setScale(_hovered && SettingsCache::instance().getScaleCards() ? 1.1 : 1); diff --git a/cockatrice/src/game/board/abstract_card_item.h b/cockatrice/src/game/board/abstract_card_item.h index 7d2c29cae..517b5cf28 100644 --- a/cockatrice/src/game/board/abstract_card_item.h +++ b/cockatrice/src/game/board/abstract_card_item.h @@ -1,7 +1,7 @@ /** * @file abstract_card_item.h * @ingroup GameGraphicsCards - * @brief TODO: Document this. + * @brief Base class for graphical card items, providing shared rendering, identity, and interaction logic. */ #ifndef ABSTRACTCARDITEM_H @@ -96,6 +96,10 @@ public: } void setRealZValue(qreal _zValue); void setHovered(bool _hovered); + bool getIsHovered() const + { + return isHovered; + } QString getColor() const { return color; diff --git a/cockatrice/src/game/game_scene.cpp b/cockatrice/src/game/game_scene.cpp index 323adda38..aa6f1e6f1 100644 --- a/cockatrice/src/game/game_scene.cpp +++ b/cockatrice/src/game/game_scene.cpp @@ -5,6 +5,7 @@ #include "phases_toolbar.h" #include "player/player.h" #include "player/player_graphics_item.h" +#include "zones/select_zone.h" #include "zones/view_zone.h" #include "zones/view_zone_widget.h" @@ -356,12 +357,26 @@ void GameScene::updateHover(const QPointF &scenePos) void GameScene::updateHoveredCard(CardItem *newCard) { if (hoveredCard && (newCard != hoveredCard)) - hoveredCard->setHovered(false); + endCardHover(hoveredCard); if (newCard && (newCard != hoveredCard)) - newCard->setHovered(true); + beginCardHover(newCard); hoveredCard = newCard; } +void GameScene::beginCardHover(CardItem *card) +{ + card->setHovered(true); + if (auto *zone = SelectZone::findOwningSelectZone(card)) + zone->escapeClipForHover(card); +} + +void GameScene::endCardHover(CardItem *card) +{ + if (auto *zone = SelectZone::findOwningSelectZone(card)) + zone->restoreClipAfterHover(card); + card->setHovered(false); +} + CardZone *GameScene::findTopmostZone(const QList &items) { for (QGraphicsItem *item : items) @@ -496,6 +511,8 @@ bool GameScene::event(QEvent *event) { if (event->type() == QEvent::GraphicsSceneMouseMove) updateHover(static_cast(event)->scenePos()); + else if (event->type() == QEvent::Leave) + updateHoveredCard(nullptr); return QGraphicsScene::event(event); } diff --git a/cockatrice/src/game/game_scene.h b/cockatrice/src/game/game_scene.h index 2ce92b775..6d491297c 100644 --- a/cockatrice/src/game/game_scene.h +++ b/cockatrice/src/game/game_scene.h @@ -56,6 +56,12 @@ private: */ void updateHover(const QPointF &scenePos); + /// Activates hover state and escapes the card from its clip container so hover scaling is visible beyond zone + /// bounds. + void beginCardHover(CardItem *card); + /// Deactivates hover state and restores the card to its clip container. + void endCardHover(CardItem *card); + public: /** * @brief Constructs the GameScene. diff --git a/cockatrice/src/game/zones/card_zone.cpp b/cockatrice/src/game/zones/card_zone.cpp index 0c189cd2b..cd7ae6a56 100644 --- a/cockatrice/src/game/zones/card_zone.cpp +++ b/cockatrice/src/game/zones/card_zone.cpp @@ -19,6 +19,7 @@ CardZone::CardZone(CardZoneLogic *_logic, QGraphicsItem *parent) void CardZone::onCardAdded(CardItem *addedCard) { addedCard->setParentItem(this); + addedCard->setVisible(true); addedCard->update(); } diff --git a/cockatrice/src/game/zones/card_zone.h b/cockatrice/src/game/zones/card_zone.h index 6fe8157e4..5df48f7fb 100644 --- a/cockatrice/src/game/zones/card_zone.h +++ b/cockatrice/src/game/zones/card_zone.h @@ -1,7 +1,7 @@ /** * @file card_zone.h * @ingroup GameGraphicsZones - * @brief TODO: Document this. + * @brief Base graphics item for zones that contain cards. */ #ifndef CARDZONE_H @@ -40,7 +40,10 @@ protected: } public slots: bool showContextMenu(const QPoint &screenPos); - void onCardAdded(CardItem *addedCard); + /// @brief Called when a card is added to this zone. Default: reparents card to this item. + /// Virtual so subclasses (e.g. SelectZone) can override parenting behavior — the Qt signal + /// connection in CardZone's constructor dispatches through the vtable. + virtual void onCardAdded(CardItem *addedCard); public: enum diff --git a/cockatrice/src/game/zones/hand_zone.cpp b/cockatrice/src/game/zones/hand_zone.cpp index 7badfcca4..506a26a80 100644 --- a/cockatrice/src/game/zones/hand_zone.cpp +++ b/cockatrice/src/game/zones/hand_zone.cpp @@ -27,6 +27,10 @@ void HandZone::handleDropEvent(const QList &dragItems, CardZoneLogic *startZone, const QPoint &dropPoint) { + if (startZone == nullptr || startZone->getPlayer() == nullptr || dragItems.isEmpty()) { + return; + } + QPoint point = dropPoint + scenePos().toPoint(); int x = -1; if (SettingsCache::instance().getHorizontalHand()) { @@ -34,9 +38,7 @@ void HandZone::handleDropEvent(const QList &dragItems, if (point.x() < static_cast(getLogic()->getCards().at(x))->scenePos().x()) break; } else { - for (x = 0; x < getLogic()->getCards().size(); x++) - if (point.y() < static_cast(getLogic()->getCards().at(x))->scenePos().y()) - break; + x = calcDropIndexFromY(dropPoint.y()); } Command_MoveCard cmd; @@ -58,7 +60,7 @@ QRectF HandZone::boundingRect() const if (SettingsCache::instance().getHorizontalHand()) return QRectF(0, 0, width, CardDimensions::HEIGHT_F + 10); else - return QRectF(0, 0, 100, zoneHeight); + return QRectF(0, 0, CardDimensions::WIDTH_F * 1.5, zoneHeight); } void HandZone::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*option*/, QWidget * /*widget*/) @@ -78,35 +80,31 @@ void HandZone::reorganizeCards() qreal totalWidth = leftJustified ? boundingRect().width() - (1 * xPadding) - 5 : boundingRect().width() - 2 * xPadding; - for (int i = 0; i < cardCount; i++) { - CardItem *c = getLogic()->getCards().at(i); - // If the total width of the cards is smaller than the available width, - // the cards do not need to overlap and are displayed in the center of the area. - if (cardWidth * cardCount > totalWidth) - c->setPos(xPadding + ((qreal)i) * (totalWidth - cardWidth) / (cardCount - 1), 5); - else { - qreal xPosition = - leftJustified ? xPadding + ((qreal)i) * cardWidth - : xPadding + ((qreal)i) * cardWidth + (totalWidth - cardCount * cardWidth) / 2; - c->setPos(xPosition, 5); + if (cardCount == 1) { + CardItem *c = getLogic()->getCards().at(0); + qreal xPosition = leftJustified ? xPadding : xPadding + (totalWidth - cardWidth) / 2; + c->setPos(xPosition, 5); + c->setRealZValue(0); + } else { + for (int i = 0; i < cardCount; i++) { + CardItem *c = getLogic()->getCards().at(i); + // If the total width of the cards is smaller than the available width, + // the cards do not need to overlap and are displayed in the center of the area. + if (cardWidth * cardCount > totalWidth) + c->setPos(xPadding + ((qreal)i) * (totalWidth - cardWidth) / (cardCount - 1), 5); + else { + qreal xPosition = leftJustified ? xPadding + ((qreal)i) * cardWidth + : xPadding + ((qreal)i) * cardWidth + + (totalWidth - cardCount * cardWidth) / 2; + c->setPos(xPosition, 5); + } + c->setRealZValue(i); } - c->setRealZValue(i); } } else { - qreal totalWidth = boundingRect().width(); - qreal cardWidth = getLogic()->getCards().at(0)->boundingRect().width(); - qreal xspace = 5; - qreal x1 = xspace; - qreal x2 = totalWidth - xspace - cardWidth; - - for (int i = 0; i < cardCount; i++) { - CardItem *card = getLogic()->getCards().at(i); - qreal x = (i % 2) ? x2 : x1; - qreal y = divideCardSpaceInZone(i, cardCount, boundingRect().height(), - getLogic()->getCards().at(0)->boundingRect().height()); - card->setPos(x, y); - card->setRealZValue(i); - } + // No clip container: hand cards should always be visible to the player. + const auto params = buildStackParams(); + layoutCardsVertically(params); } } update(); diff --git a/cockatrice/src/game/zones/hand_zone.h b/cockatrice/src/game/zones/hand_zone.h index 25f4148bd..586302308 100644 --- a/cockatrice/src/game/zones/hand_zone.h +++ b/cockatrice/src/game/zones/hand_zone.h @@ -1,7 +1,7 @@ /** * @file hand_zone.h * @ingroup GameGraphicsZones - * @brief TODO: Document this. + * @brief Graphical zone for the player's hand, supporting horizontal and vertical layouts. */ #ifndef HANDZONE_H @@ -14,7 +14,8 @@ class HandZone : public SelectZone { Q_OBJECT private: - qreal width, zoneHeight; + qreal width = 0.0; + qreal zoneHeight; private slots: void updateBg(); public slots: diff --git a/cockatrice/src/game/zones/select_zone.cpp b/cockatrice/src/game/zones/select_zone.cpp index 9bf5f9faf..fd733e01f 100644 --- a/cockatrice/src/game/zones/select_zone.cpp +++ b/cockatrice/src/game/zones/select_zone.cpp @@ -4,38 +4,207 @@ #include "../board/card_item.h" #include "../game_scene.h" -#include +#include #include +#include -qreal divideCardSpaceInZone(qreal index, int cardCount, qreal totalHeight, qreal cardHeight, bool reverse) +static qreal stackingOffset(qreal cardHeight) { - qreal cardMinOverlap = cardHeight * SettingsCache::instance().getStackCardOverlapPercent() / 100; - qreal desiredHeight = cardHeight * cardCount - cardMinOverlap * (cardCount - 1); - qreal y; - if (desiredHeight > totalHeight) { - if (reverse) { - y = index / ((totalHeight - cardHeight) / (cardCount - 1)); + const qreal overlapPercent = SettingsCache::instance().getStackCardOverlapPercent(); + return cardHeight * (100.0 - overlapPercent) / 100.0; +} + +SelectZone::ZoneLayout SelectZone::computeZoneLayout(const StackLayoutParams ¶ms) +{ + if (params.cardCount <= 0) { + return {0.0, 0.0}; + } + qreal effectiveOffset = params.desiredOffset; + if (params.cardCount > 1) { + qreal fitOffset; + if (params.totalHeight < params.cardHeight && params.minOffset > 0.0) { + // Zone is shorter than a card (e.g. minimized). Compress offsets so + // every card has at least minOffset pixels of its top visible. + fitOffset = (params.totalHeight - params.minOffset) / (params.cardCount - 1); + effectiveOffset = qMax(0.0, qMin(params.desiredOffset, fitOffset)); } else { - y = index * (totalHeight - cardHeight) / (cardCount - 1); - } - } else { - qreal start = (totalHeight - desiredHeight) / 2; - if (reverse) { - if (index <= start) { - return 0; + qreal reservedForBottomCard; + if (params.allowBottomOverflow) { + // Allow the bottom card to partially overflow in tight zones, scaling the + // overflow allowance by sqrt(cardCount-1) so offsets decrease smoothly + // as cards are added rather than dropping by 1/(n-1) each time. + // The 0.75 ratio was tuned experimentally to balance card visibility vs. overflow. + constexpr qreal bottomCardZoneRatio = 0.75; + const qreal adjustedRatio = bottomCardZoneRatio / qSqrt(static_cast(params.cardCount - 1)); + reservedForBottomCard = qMin(params.cardHeight, params.totalHeight * adjustedRatio); + } else { + // No overflow: reserve full card height for the bottom card + reservedForBottomCard = params.cardHeight; } - y = (index - start) / (cardHeight - cardMinOverlap); - } else { - y = index * (cardHeight - cardMinOverlap) + start; + fitOffset = (params.totalHeight - reservedForBottomCard) / (params.cardCount - 1); + effectiveOffset = qMax(params.minOffset, qMin(params.desiredOffset, fitOffset)); } } - return y; + qreal stackHeight = (params.cardCount - 1) * effectiveOffset + params.cardHeight; + qreal start = (stackHeight <= params.totalHeight) ? (params.totalHeight - stackHeight) / 2.0 : 0.0; + return {effectiveOffset, start}; +} + +SelectZone *SelectZone::findOwningSelectZone(const QGraphicsItem *card) +{ + QGraphicsItem *parent = card ? card->parentItem() : nullptr; + if (!parent) { + return nullptr; + } + // Card may be direct child of zone (escaped for hover) or child of clip container. + if (auto *zone = dynamic_cast(parent)) { + return zone; + } + if (auto *zone = dynamic_cast(parent->parentItem())) { + return zone; + } + return nullptr; +} + +SelectZone::StackLayoutParams SelectZone::buildStackParams(qreal minOffset) const +{ + const auto &cards = getLogic()->getCards(); + if (cards.isEmpty()) + return {0, boundingRect().height(), 0.0, 0.0, minOffset}; + const auto cardCount = static_cast(cards.size()); + const qreal cardHeight = cards.at(0)->boundingRect().height(); + const qreal offset = stackingOffset(cardHeight); + return {cardCount, boundingRect().height(), cardHeight, offset, minOffset}; +} + +int SelectZone::calcDropIndexFromY(qreal dropY, qreal minOffset) const +{ + const auto &cards = getLogic()->getCards(); + if (cards.isEmpty()) { + return 0; + } + const auto params = buildStackParams(minOffset); + auto [effectiveOffset, start] = computeZoneLayout(params); + if (effectiveOffset <= 0.0) { + return 0; + } + return qBound(0, qRound((dropY - start) / effectiveOffset), params.cardCount - 1); +} + +void SelectZone::restoreStaleEscapedCards() +{ + if (!cardClipContainer) + return; + for (auto *card : getLogic()->getCards()) { + // A card parented to the zone (instead of the clip container) should + // only occur while it is actively hovered. If hover cleanup was + // missed, reparent it back so clipping resumes. + if (card && card->parentItem() == this && !card->getIsHovered()) { + card->setParentItem(cardClipContainer); + } + } +} + +void SelectZone::layoutCardsVertically(const StackLayoutParams ¶ms) +{ + const auto &cards = getLogic()->getCards(); + if (cards.isEmpty() || params.cardCount <= 0) + return; + if (params.cardCount > cards.size()) + return; + + constexpr qreal xspace = 5; + const qreal cardWidth = cards.at(0)->boundingRect().width(); + const qreal totalWidth = boundingRect().width(); + const qreal x1 = xspace; + const qreal x2 = totalWidth - xspace - cardWidth; + const qreal xCentered = (totalWidth - cardWidth) / 2.0; + + auto [effectiveOffset, start] = computeZoneLayout(params); + for (int i = 0; i < params.cardCount; i++) { + CardItem *card = cards.at(i); + qreal y = start + i * effectiveOffset; + // Center single card; alternate left/right for multiple cards + qreal x = (params.cardCount == 1) ? xCentered : ((i % 2) ? x2 : x1); + card->setPos(x, y); + card->setRealZValue(i); + } } SelectZone::SelectZone(CardZoneLogic *_logic, QGraphicsItem *parent) : CardZone(_logic, parent) { } +SelectZone::~SelectZone() +{ + if (cardClipContainer) { + // Reparent any hover-escaped cards back to the clip container so Qt's + // parent-child tree is consistent for destruction. setParentItem() does + // not invalidate getLogic()->getCards() (it modifies the graphics tree, + // not the zone's logical card list). + for (auto *card : getLogic()->getCards()) { + if (card && card->parentItem() == this) { + card->setParentItem(cardClipContainer); + } + } + } +} + +void SelectZone::onCardAdded(CardItem *addedCard) +{ + if (cardClipContainer && addedCard) { + addedCard->setParentItem(cardClipContainer); + addedCard->setVisible(true); + addedCard->update(); + } else { + CardZone::onCardAdded(addedCard); + } +} + +void SelectZone::setupClipContainer(std::optional zValue) +{ + if (cardClipContainer) + return; + + setFlag(QGraphicsItem::ItemClipsChildrenToShape, false); + + cardClipContainer = new QGraphicsRectItem(this); // Owned by Qt parent-child tree; deleted with this zone. + cardClipContainer->setFlag(QGraphicsItem::ItemClipsChildrenToShape, true); + cardClipContainer->setPen(Qt::NoPen); + cardClipContainer->setBrush(Qt::NoBrush); + cardClipContainer->setRect(boundingRect()); + if (zValue.has_value()) { + cardClipContainer->setZValue(*zValue); + } +} + +void SelectZone::escapeClipForHover(QGraphicsItem *card) +{ + // Reparent from clip container to zone so the hover-scaled card is visible + // beyond clip bounds. Coordinates are identical because the clip container + // is at (0,0) with no transform relative to this zone. + if (cardClipContainer && card && card->parentItem() == cardClipContainer) { + card->setParentItem(this); + cardClipContainer->update(); + } +} + +void SelectZone::restoreClipAfterHover(QGraphicsItem *card) +{ + // Restore card to clip container. If card's parent is not this zone, + // a zone transition already reparented it via onCardAdded — skip. + if (cardClipContainer && card && card->parentItem() == this) { + card->setParentItem(cardClipContainer); + } +} + +void SelectZone::updateClipRect() +{ + if (cardClipContainer) { + cardClipContainer->setRect(boundingRect()); + } +} + void SelectZone::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { if (event->buttons().testFlag(Qt::LeftButton)) { @@ -56,7 +225,7 @@ void SelectZone::mouseMoveEvent(QGraphicsSceneMouseEvent *event) continue; } - bool inRect = selectionRect.intersects(card->mapRectToParent(card->boundingRect())); + bool inRect = selectionRect.intersects(card->mapRectToItem(this, card->boundingRect())); if (inRect && !cardsInSelectionRect.contains(card)) { // selection has just expanded to cover the card cardsInSelectionRect.insert(card); diff --git a/cockatrice/src/game/zones/select_zone.h b/cockatrice/src/game/zones/select_zone.h index d6fd3e10e..1da5c1988 100644 --- a/cockatrice/src/game/zones/select_zone.h +++ b/cockatrice/src/game/zones/select_zone.h @@ -1,7 +1,7 @@ /** * @file select_zone.h * @ingroup GameGraphicsZones - * @brief TODO: Document this. + * @brief Base class for zones where cards are laid out and individually interactable. */ #ifndef SELECTZONE_H @@ -10,6 +10,9 @@ #include "card_zone.h" #include +#include + +class QGraphicsRectItem; /** * A CardZone where the cards are laid out, with each card directly interactable by clicking. @@ -17,19 +20,113 @@ class SelectZone : public CardZone { Q_OBJECT +public: + /// Finds the SelectZone that owns a card, regardless of whether the card is parented + /// to the zone directly or to its clip container. Returns nullptr if not in a SelectZone. + static SelectZone *findOwningSelectZone(const QGraphicsItem *card); + + SelectZone(CardZoneLogic *logic, QGraphicsItem *parent = nullptr); + ~SelectZone() override; + void onCardAdded(CardItem *addedCard) override; + + /// @brief Temporarily reparents a card from the clip container to this zone so hover scaling is visible beyond clip + /// bounds. Safe no-op if no clip container exists. Coordinates are preserved (clip container is at (0,0) with no + /// transform). + void escapeClipForHover(QGraphicsItem *card); + /// @brief Restores a hover-escaped card back to the clip container. Guards against zone transitions that already + /// reparented the card. + void restoreClipAfterHover(QGraphicsItem *card); + private: QPointF selectionOrigin; QSet cardsInSelectionRect; + /// Invisible clipping parent for cards; owned by Qt parent-child tree (parented to this zone). + /// Created by setupClipContainer(); null when no clip container is active. + QGraphicsRectItem *cardClipContainer = nullptr; protected: + // -- Layout computation -- + + /// Parameters describing a vertical card stack's geometry. + struct StackLayoutParams + { + int cardCount; ///< Number of cards in the stack + qreal totalHeight; ///< Available height for the stack (zone height) + qreal cardHeight; ///< Height of a single card + qreal desiredOffset; ///< Preferred vertical offset between card tops + qreal minOffset = 0.0; ///< Minimum offset to preserve (0 allows full compression) + /// When false (default), reserves full cardHeight for the bottom card, ensuring + /// all cards remain within zone bounds. When true, allows the bottom card to + /// partially overflow using sqrt-scaled allowance. Use with setupClipContainer() + /// for zones too short to fit a full card. + bool allowBottomOverflow = false; + }; + + /// Result of computing a vertical stack layout. + struct ZoneLayout + { + qreal effectiveOffset; ///< Actual offset between card tops (may be compressed) + qreal start; ///< Y coordinate of the first card's top edge + }; + + /// Minimum visible pixels of each card's top edge when stacking compresses offsets in tight zones. + static constexpr qreal MIN_CARD_VISIBLE = 10.0; + + /** + * @brief Computes layout for a vertical card stack (effective offset and start position). + * + * Three regimes: + * 1. Minimized zone (totalHeight < card height with minOffset > 0): offsets compress + * so each card retains at least minOffset visible pixels of its top edge. + * 2. Normal zone with allowBottomOverflow=false (default): the bottom card is + * guaranteed to fit within the zone boundary. Offsets compress as needed. + * 3. Normal zone with allowBottomOverflow=true: the bottom card may partially + * overflow. The overflow allowance is scaled by sqrt(cardCount-1) so that + * adding one card shifts existing cards smoothly. + * + * When the stack fits with room to spare, it is centered vertically. + */ + static ZoneLayout computeZoneLayout(const StackLayoutParams ¶ms); + + /// Builds StackLayoutParams from the current card list and zone geometry. + StackLayoutParams buildStackParams(qreal minOffset = 0.0) const; + + /// Computes the card index at a given y-coordinate within the zone's vertical layout. + /// Returns 0 if the zone has no cards or the offset is zero. + int calcDropIndexFromY(qreal dropY, qreal minOffset = 0.0) const; + + /** + * @brief Positions cards vertically with alternating left/right x-offsets. + * + * Cards alternate between left and right margins (5px padding from zone edges): + * even-indexed cards at left, odd-indexed at right. + * Cards are assigned ascending z-values. + * + * @param params Stack layout geometry parameters (use allowBottomOverflow to control overflow) + */ + void layoutCardsVertically(const StackLayoutParams ¶ms); + + // -- Clip container -- + // The clip container mechanism is available for future zones that need visual clipping + // (e.g., zones too short to fit a full card). To enable: call setupClipContainer() in the + // zone's constructor, and set allowBottomOverflow=true in layout params. + + /// Restores any cards that were hover-escaped but whose hover state was not properly cleaned up. + /// Call at the start of reorganizeCards() in zones that use a clip container. + void restoreStaleEscapedCards(); + + /// Creates a clip container child item that clips card overflow to zone bounds. + /// Cards entering this zone are reparented to this container by the onCardAdded override. + /// Disables zone-level child clipping; clipping is delegated to the container. + /// @param zValue Optional z-value for the clip container (e.g. ZValues::CARD_BASE) + void setupClipContainer(std::optional zValue = std::nullopt); + + /// Updates the clip container rect to match this zone's current boundingRect(). + void updateClipRect(); + void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override; void mousePressEvent(QGraphicsSceneMouseEvent *event) override; void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override; - -public: - SelectZone(CardZoneLogic *logic, QGraphicsItem *parent = nullptr); }; -qreal divideCardSpaceInZone(qreal index, int cardCount, qreal totalHeight, qreal cardHeight, bool reverse = false); - #endif diff --git a/cockatrice/src/game/zones/stack_zone.cpp b/cockatrice/src/game/zones/stack_zone.cpp index a9d649a4a..c0da0bfd2 100644 --- a/cockatrice/src/game/zones/stack_zone.cpp +++ b/cockatrice/src/game/zones/stack_zone.cpp @@ -1,10 +1,9 @@ #include "stack_zone.h" -#include "../../client/settings/cache_settings.h" #include "../../interface/theme_manager.h" -#include "../board/arrow_item.h" #include "../board/card_drag_item.h" #include "../board/card_item.h" +#include "../card_dimensions.h" #include "../player/player.h" #include "../player/player_actions.h" #include "logic/stack_zone_logic.h" @@ -27,7 +26,7 @@ void StackZone::updateBg() QRectF StackZone::boundingRect() const { - return {0, 0, 100, zoneHeight}; + return {0, 0, CardDimensions::WIDTH_F * 1.5, zoneHeight}; } void StackZone::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*option*/, QWidget * /*widget*/) @@ -40,7 +39,15 @@ void StackZone::handleDropEvent(const QList &dragItems, CardZoneLogic *startZone, const QPoint &dropPoint) { - if (startZone == nullptr || startZone->getPlayer() == nullptr) { + if (startZone == nullptr || startZone->getPlayer() == nullptr || dragItems.isEmpty()) { + return; + } + + int index = calcDropIndexFromY(dropPoint.y(), MIN_CARD_VISIBLE); + + // Same-zone no-op: don't move a card onto itself + const auto &cards = getLogic()->getCards(); + if (!cards.isEmpty() && startZone == getLogic() && cards.at(index)->getId() == dragItems.at(0)->getId()) { return; } @@ -49,36 +56,12 @@ void StackZone::handleDropEvent(const QList &dragItems, cmd.set_start_zone(startZone->getName().toStdString()); cmd.set_target_player_id(getLogic()->getPlayer()->getPlayerInfo()->getId()); cmd.set_target_zone(getLogic()->getName().toStdString()); - - int index = 0; - - if (!getLogic()->getCards().isEmpty()) { - const auto cardCount = static_cast(getLogic()->getCards().size()); - const auto &card = getLogic()->getCards().at(0); - - index = qRound(divideCardSpaceInZone(dropPoint.y(), cardCount, boundingRect().height(), - card->boundingRect().height(), true)); - - // divideCardSpaceInZone is not guaranteed to return a valid index - // currently, so clamp it to avoid crashes. - index = qBound(0, index, cardCount - 1); - - if (startZone == getLogic()) { - const auto &dragItem = dragItems.at(0); - const auto &card = getLogic()->getCards().at(index); - - if (card->getId() == dragItem->getId()) { - return; - } - } - } - cmd.set_x(index); cmd.set_y(0); - for (CardDragItem *item : dragItems) { + for (const CardDragItem *item : dragItems) { if (item) { - auto cardToMove = cmd.mutable_cards_to_move()->add_card(); + auto *cardToMove = cmd.mutable_cards_to_move()->add_card(); cardToMove->set_card_id(item->getId()); if (item->isForceFaceDown()) { cardToMove->set_face_down(true); @@ -89,24 +72,22 @@ void StackZone::handleDropEvent(const QList &dragItems, getLogic()->getPlayer()->getPlayerActions()->sendGameCommand(cmd); } +void StackZone::setHeight(qreal newHeight) +{ + if (qFuzzyCompare(1.0 + zoneHeight, 1.0 + newHeight)) { + return; + } + prepareGeometryChange(); + zoneHeight = newHeight; + reorganizeCards(); + update(); +} + void StackZone::reorganizeCards() { if (!getLogic()->getCards().isEmpty()) { - const auto cardCount = static_cast(getLogic()->getCards().size()); - qreal totalWidth = boundingRect().width(); - qreal cardWidth = getLogic()->getCards().at(0)->boundingRect().width(); - qreal xspace = 5; - qreal x1 = xspace; - qreal x2 = totalWidth - xspace - cardWidth; - - for (int i = 0; i < cardCount; i++) { - CardItem *card = getLogic()->getCards().at(i); - qreal x = (i % 2) ? x2 : x1; - qreal y = divideCardSpaceInZone(i, cardCount, boundingRect().height(), - getLogic()->getCards().at(0)->boundingRect().height()); - card->setPos(x, y); - card->setRealZValue(i); - } + const auto params = buildStackParams(MIN_CARD_VISIBLE); + layoutCardsVertically(params); } update(); } diff --git a/cockatrice/src/game/zones/stack_zone.h b/cockatrice/src/game/zones/stack_zone.h index 7c98f5128..8f5bed09d 100644 --- a/cockatrice/src/game/zones/stack_zone.h +++ b/cockatrice/src/game/zones/stack_zone.h @@ -1,7 +1,7 @@ /** * @file stack_zone.h * @ingroup GameGraphicsZones - * @brief TODO: Document this. + * @brief Graphical zone for the stack, displaying cards in a vertical pile. */ #ifndef STACKZONE_H @@ -20,6 +20,8 @@ private slots: public: StackZone(StackZoneLogic *_logic, int _zoneHeight, QGraphicsItem *parent); + /// @brief Resizes the stack zone height, e.g. when sharing vertical space with the command zone. + void setHeight(qreal newHeight); void handleDropEvent(const QList &dragItems, CardZoneLogic *startZone, const QPoint &dropPoint) override; QRectF boundingRect() const override; From b66743c83c7f5b5dcbb9a239ece3ec611aa499f9 Mon Sep 17 00:00:00 2001 From: RickyRister <42636155+RickyRister@users.noreply.github.com> Date: Mon, 11 May 2026 20:23:12 -0700 Subject: [PATCH 02/51] [DeckEditor] Refactor searchEdit highlighting after add card (#6874) * [DeckEditor] Refactor searchEdit highlighting after add card * make searchEdit private --- .../deck_editor/deck_editor_card_database_dock_widget.cpp | 4 ---- .../deck_editor/deck_editor_card_database_dock_widget.h | 1 - .../deck_editor/deck_editor_database_display_widget.cpp | 7 +++++++ .../deck_editor/deck_editor_database_display_widget.h | 4 +++- .../interface/widgets/tabs/abstract_tab_deck_editor.cpp | 2 -- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/cockatrice/src/interface/widgets/deck_editor/deck_editor_card_database_dock_widget.cpp b/cockatrice/src/interface/widgets/deck_editor/deck_editor_card_database_dock_widget.cpp index bacebe385..f2a2ab4ea 100644 --- a/cockatrice/src/interface/widgets/deck_editor/deck_editor_card_database_dock_widget.cpp +++ b/cockatrice/src/interface/widgets/deck_editor/deck_editor_card_database_dock_widget.cpp @@ -58,7 +58,3 @@ void DeckEditorCardDatabaseDockWidget::clearAllDatabaseFilters() { databaseDisplayWidget->clearAllDatabaseFilters(); } -void DeckEditorCardDatabaseDockWidget::highlightAllSearchEdit() -{ - databaseDisplayWidget->searchEdit->setSelection(0, databaseDisplayWidget->searchEdit->text().length()); -} diff --git a/cockatrice/src/interface/widgets/deck_editor/deck_editor_card_database_dock_widget.h b/cockatrice/src/interface/widgets/deck_editor/deck_editor_card_database_dock_widget.h index 6ad442075..bff9ee36f 100644 --- a/cockatrice/src/interface/widgets/deck_editor/deck_editor_card_database_dock_widget.h +++ b/cockatrice/src/interface/widgets/deck_editor/deck_editor_card_database_dock_widget.h @@ -23,7 +23,6 @@ public: public slots: void retranslateUi(); void clearAllDatabaseFilters(); - void highlightAllSearchEdit(); private: void createDatabaseDisplayDock(AbstractTabDeckEditor *deckEditor); diff --git a/cockatrice/src/interface/widgets/deck_editor/deck_editor_database_display_widget.cpp b/cockatrice/src/interface/widgets/deck_editor/deck_editor_database_display_widget.cpp index c625ff1d9..20eef180a 100644 --- a/cockatrice/src/interface/widgets/deck_editor/deck_editor_database_display_widget.cpp +++ b/cockatrice/src/interface/widgets/deck_editor/deck_editor_database_display_widget.cpp @@ -147,11 +147,13 @@ void DeckEditorDatabaseDisplayWidget::updateCard(const QModelIndex ¤t, con void DeckEditorDatabaseDisplayWidget::actAddCardToMainDeck() { + highlightAllSearchEdit(); emit addCardToMainDeck(currentCard()); } void DeckEditorDatabaseDisplayWidget::actAddCardToSideboard() { + highlightAllSearchEdit(); emit addCardToSideboard(currentCard()); } @@ -240,4 +242,9 @@ void DeckEditorDatabaseDisplayWidget::retranslateUi() { aAddCard->setText(tr("Add card to &maindeck")); aAddCardToSideboard->setText(tr("Add card to &sideboard")); +} + +void DeckEditorDatabaseDisplayWidget::highlightAllSearchEdit() +{ + searchEdit->setSelection(0, searchEdit->text().length()); } \ No newline at end of file diff --git a/cockatrice/src/interface/widgets/deck_editor/deck_editor_database_display_widget.h b/cockatrice/src/interface/widgets/deck_editor/deck_editor_database_display_widget.h index 16ae6e255..0f62998ef 100644 --- a/cockatrice/src/interface/widgets/deck_editor/deck_editor_database_display_widget.h +++ b/cockatrice/src/interface/widgets/deck_editor/deck_editor_database_display_widget.h @@ -25,7 +25,6 @@ class DeckEditorDatabaseDisplayWidget : public QWidget public: explicit DeckEditorDatabaseDisplayWidget(QWidget *parent, AbstractTabDeckEditor *deckEditor); AbstractTabDeckEditor *deckEditor; - SearchLineEdit *searchEdit; CardDatabaseModel *databaseModel; CardDatabaseDisplayModel *databaseDisplayModel; @@ -58,10 +57,13 @@ private: KeySignals searchKeySignals; QTreeView *databaseView; QHBoxLayout *searchLayout; + SearchLineEdit *searchEdit; QAction *aAddCard, *aAddCardToSideboard; QVBoxLayout *centralFrame; QWidget *centralWidget; + void highlightAllSearchEdit(); + private slots: void retranslateUi(); void saveDbHeaderState(); diff --git a/cockatrice/src/interface/widgets/tabs/abstract_tab_deck_editor.cpp b/cockatrice/src/interface/widgets/tabs/abstract_tab_deck_editor.cpp index afc834e10..a739ac83b 100644 --- a/cockatrice/src/interface/widgets/tabs/abstract_tab_deck_editor.cpp +++ b/cockatrice/src/interface/widgets/tabs/abstract_tab_deck_editor.cpp @@ -137,8 +137,6 @@ void AbstractTabDeckEditor::onDeckModified() void AbstractTabDeckEditor::addCardHelper(const ExactCard &card, const QString &zoneName) { deckStateManager->addCard(card, zoneName); - - cardDatabaseDockWidget->highlightAllSearchEdit(); } /** From d18f3bce47c13952622a73d400df75148c6b045f Mon Sep 17 00:00:00 2001 From: RickyRister <42636155+RickyRister@users.noreply.github.com> Date: Mon, 11 May 2026 20:23:29 -0700 Subject: [PATCH 03/51] [VisualDatabaseDisplayWidget] Refactor: Make all fields private (#6875) --- .../tabs/tab_visual_database_display.h | 4 ++-- ...database_display_filter_toolbar_widget.cpp | 2 +- .../visual_database_display_widget.cpp | 5 +++++ .../visual_database_display_widget.h | 22 ++++++++++++++----- 4 files changed, 24 insertions(+), 9 deletions(-) diff --git a/cockatrice/src/interface/widgets/tabs/tab_visual_database_display.h b/cockatrice/src/interface/widgets/tabs/tab_visual_database_display.h index 66f38fb3d..4fe4d3e8f 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_visual_database_display.h +++ b/cockatrice/src/interface/widgets/tabs/tab_visual_database_display.h @@ -23,8 +23,8 @@ public: void retranslateUi() override; [[nodiscard]] QString getTabText() const override { - return visualDatabaseDisplayWidget->displayModeButton->isChecked() ? tr("Database Display") - : tr("Visual Database Display"); + return visualDatabaseDisplayWidget->isVisualDisplayMode() ? tr("Visual Database Display") + : tr("Database Display"); } }; diff --git a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_filter_toolbar_widget.cpp b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_filter_toolbar_widget.cpp index 3cc1bf23b..790ac771a 100644 --- a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_filter_toolbar_widget.cpp +++ b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_filter_toolbar_widget.cpp @@ -101,7 +101,7 @@ void VisualDatabaseDisplayFilterToolbarWidget::initialize() filterLayout->setAlignment(Qt::AlignLeft); // create settings widgets - auto filterModel = visualDatabaseDisplay->filterModel; + auto filterModel = visualDatabaseDisplay->getFilterModel(); saveLoadWidget = new VisualDatabaseDisplayFilterSaveLoadWidget(this, filterModel); nameFilterWidget = diff --git a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.cpp b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.cpp index b9f8dab51..25b3c33f8 100644 --- a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.cpp +++ b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.cpp @@ -237,6 +237,11 @@ void VisualDatabaseDisplayWidget::updateSearch(const QString &search) const QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows); } +bool VisualDatabaseDisplayWidget::isVisualDisplayMode() const +{ + return !displayModeButton->isChecked(); +} + void VisualDatabaseDisplayWidget::onSearchModelChanged() { if (flowWidget->isVisible()) { diff --git a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.h b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.h index 3aa8d7f8e..5c112b4e4 100644 --- a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.h +++ b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.h @@ -62,12 +62,15 @@ public: return databaseView; } - QWidget *searchContainer; - QHBoxLayout *searchLayout; - SearchLineEdit *searchEdit; - QPushButton *displayModeButton; - FilterTreeModel *filterModel; - VisualDatabaseDisplayColorFilterWidget *colorFilterWidget; + FilterTreeModel *getFilterModel() + { + return filterModel; + } + + /** + * @return False if the widget is in database display mode and true if it's in visual display mode + */ + bool isVisualDisplayMode() const; public slots: void onSearchModelChanged(); @@ -88,6 +91,13 @@ protected slots: void onDisplayModeChanged(bool checked); private: + QWidget *searchContainer; + QHBoxLayout *searchLayout; + SearchLineEdit *searchEdit; + QPushButton *displayModeButton; + FilterTreeModel *filterModel; + VisualDatabaseDisplayColorFilterWidget *colorFilterWidget; + QLabel *databaseLoadIndicator; QToolButton *clearFilterWidget; From fe12f4cbb9c4281fdb9bc561fb8989f21dc8f29e Mon Sep 17 00:00:00 2001 From: RickyRister <42636155+RickyRister@users.noreply.github.com> Date: Mon, 11 May 2026 20:23:44 -0700 Subject: [PATCH 04/51] [VisualDeckEditor] Highlight searchEdit after add card (#6876) --- .../visual_database_display_widget.cpp | 10 ++++++++++ .../visual_database_display_widget.h | 2 ++ 2 files changed, 12 insertions(+) diff --git a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.cpp b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.cpp index 25b3c33f8..9c4432042 100644 --- a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.cpp +++ b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.cpp @@ -99,6 +99,11 @@ VisualDatabaseDisplayWidget::VisualDatabaseDisplayWidget(QWidget *parent, &DeckEditorDatabaseDisplayWidget::copyDatabaseCellContents); connect(help, &QAction::triggered, this, [this] { createSearchSyntaxHelpWindow(searchEdit); }); + connect(databaseDisplayWidget, &DeckEditorDatabaseDisplayWidget::addCardToMainDeck, this, + &VisualDatabaseDisplayWidget::highlightAllSearchEdit); + connect(databaseDisplayWidget, &DeckEditorDatabaseDisplayWidget::addCardToSideboard, this, + &VisualDatabaseDisplayWidget::highlightAllSearchEdit); + databaseView = databaseDisplayWidget->getDatabaseView(); databaseView->setFocusProxy(searchEdit); databaseView->setItemDelegate(nullptr); @@ -181,6 +186,11 @@ void VisualDatabaseDisplayWidget::retranslateUi() clearFilterWidget->setToolTip(tr("Clear all filters")); } +void VisualDatabaseDisplayWidget::highlightAllSearchEdit() +{ + searchEdit->setSelection(0, searchEdit->text().length()); +} + void VisualDatabaseDisplayWidget::resizeEvent(QResizeEvent *event) { QWidget::resizeEvent(event); diff --git a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.h b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.h index 5c112b4e4..190ea1f6d 100644 --- a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.h +++ b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.h @@ -122,6 +122,8 @@ private: int currentPage = 0; // Current page index int cardsPerPage = 100; // Number of cards per page + void highlightAllSearchEdit(); + protected: void resizeEvent(QResizeEvent *event) override; }; From 7507103bb2d47314e52e10bd0572aa014b3375a6 Mon Sep 17 00:00:00 2001 From: tooomm Date: Wed, 13 May 2026 14:54:47 +0200 Subject: [PATCH 05/51] CI: Update trigger for doc builds (#6871) * Update trigger * use `published` trigger * narrow deploy step filter * re-add deployments on manual runs --- .github/workflows/documentation-build.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/documentation-build.yml b/.github/workflows/documentation-build.yml index 7306c726a..b0093d6b1 100644 --- a/.github/workflows/documentation-build.yml +++ b/.github/workflows/documentation-build.yml @@ -1,9 +1,9 @@ name: Generate Docs on: - push: - tags: - - '*' # Only re-generate docs when a new tagged version is pushed + release: + types: + - published # publishing of stable releases and pre-releases pull_request: paths: - 'doc/doxygen/**' @@ -53,11 +53,11 @@ jobs: run: doxygen Doxyfile - name: Deploy to cockatrice.github.io - if: github.event_name != 'pull_request' + if: github.event_name == 'release' || github.event_name == 'workflow_dispatch' uses: peaceiris/actions-gh-pages@v4 with: deploy_key: ${{ secrets.DOCS_DEPLOY_KEY }} external_repository: Cockatrice/cockatrice.github.io publish_branch: master publish_dir: ./docs/html - destination_dir: docs # Docs will live under https://cockatrice.github.io/docs/ + destination_dir: docs # Docs will live under https://cockatrice.github.io/docs/ From 67f6ab66f03c663a5725c1477997c67c642d894c Mon Sep 17 00:00:00 2001 From: RickyRister <42636155+RickyRister@users.noreply.github.com> Date: Wed, 13 May 2026 11:32:05 -0700 Subject: [PATCH 06/51] [DeckLoader] Don't modify text deck files on load (#6888) * [DeckLoader] Don't modify text deck files on load * formatter --- .../src/interface/deck_loader/deck_loader.cpp | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/cockatrice/src/interface/deck_loader/deck_loader.cpp b/cockatrice/src/interface/deck_loader/deck_loader.cpp index d71dca24a..e616c5eb5 100644 --- a/cockatrice/src/interface/deck_loader/deck_loader.cpp +++ b/cockatrice/src/interface/deck_loader/deck_loader.cpp @@ -181,6 +181,11 @@ bool DeckLoader::saveToNewFile(LoadedDeck &deck, const QString &fileName, DeckFi */ bool DeckLoader::updateLastLoadedTimestamp(LoadedDeck &deck) { + // text format doesn't support lastLoadedTimestamp, so there's no point in proceeding + if (deck.lastLoadInfo.fileFormat != DeckFileFormat::Cockatrice) { + return false; + } + QString fileName = deck.lastLoadInfo.fileName; QFileInfo fileInfo(fileName); @@ -201,15 +206,8 @@ bool DeckLoader::updateLastLoadedTimestamp(LoadedDeck &deck) bool result = false; // Perform file modifications - switch (deck.lastLoadInfo.fileFormat) { - case DeckFileFormat::PlainText: - result = deck.deckList.saveToFile_Plain(&file); - break; - case DeckFileFormat::Cockatrice: - deck.deckList.setLastLoadedTimestamp(QDateTime::currentDateTime().toString()); - result = deck.deckList.saveToFile_Native(&file); - break; - } + deck.deckList.setLastLoadedTimestamp(QDateTime::currentDateTime().toString()); + result = deck.deckList.saveToFile_Native(&file); file.close(); // Close the file to ensure changes are flushed @@ -429,8 +427,7 @@ void DeckLoader::saveToStream_DeckZoneCards(QTextStream &out, } if (addSetNameAndNumber) { if (!card->getCardSetShortName().isNull() && !card->getCardSetShortName().isEmpty()) { - out << " " - << "(" << card->getCardSetShortName() << ")"; + out << " " << "(" << card->getCardSetShortName() << ")"; } if (!card->getCardCollectorNumber().isNull()) { out << " " << card->getCardCollectorNumber(); From 762e742be0b7987f2c908ffe38ba9301253523cd Mon Sep 17 00:00:00 2001 From: RickyRister <42636155+RickyRister@users.noreply.github.com> Date: Wed, 13 May 2026 15:03:41 -0700 Subject: [PATCH 07/51] [Game] Implement action to automatically take damage from creatures (#6869) * [Game] Implement action to automatically take damage from creatures * cleanup --- .../src/client/settings/shortcuts_settings.h | 3 +++ cockatrice/src/game/player/menu/card_menu.cpp | 9 +++++++ cockatrice/src/game/player/menu/card_menu.h | 1 + cockatrice/src/game/player/player.cpp | 10 +++++++ cockatrice/src/game/player/player.h | 5 ++++ cockatrice/src/game/player/player_actions.cpp | 27 +++++++++++++++++++ cockatrice/src/game/player/player_actions.h | 3 +++ 7 files changed, 58 insertions(+) diff --git a/cockatrice/src/client/settings/shortcuts_settings.h b/cockatrice/src/client/settings/shortcuts_settings.h index d9ea494dc..fc159db48 100644 --- a/cockatrice/src/client/settings/shortcuts_settings.h +++ b/cockatrice/src/client/settings/shortcuts_settings.h @@ -537,6 +537,9 @@ private: {"Player/aSetAnnotation", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Set Annotation..."), parseSequenceString("Alt+N"), ShortcutGroup::Playing_Area)}, + {"Player/aReduceLifeByPower", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Reduce Life by Power"), + parseSequenceString("Ctrl+Shift+L"), + ShortcutGroup::Playing_Area)}, {"Player/aSelectAll", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Select All Cards in Zone"), parseSequenceString("Ctrl+A"), ShortcutGroup::Playing_Area)}, diff --git a/cockatrice/src/game/player/menu/card_menu.cpp b/cockatrice/src/game/player/menu/card_menu.cpp index 34ed254fb..54403e237 100644 --- a/cockatrice/src/game/player/menu/card_menu.cpp +++ b/cockatrice/src/game/player/menu/card_menu.cpp @@ -62,6 +62,9 @@ CardMenu::CardMenu(Player *_player, const CardItem *_card, bool _shortcutsActive aSelectColumn = new QAction(this); connect(aSelectColumn, &QAction::triggered, playerActions, &PlayerActions::actSelectColumn); + aReduceLifeByPower = new QAction(this); + connect(aReduceLifeByPower, &QAction::triggered, playerActions, &PlayerActions::actReduceLifeByPower); + aPlay = new QAction(this); connect(aPlay, &QAction::triggered, playerActions, &PlayerActions::actPlay); aHide = new QAction(this); @@ -153,6 +156,8 @@ void CardMenu::createTableMenu(bool canModifyCard) addSeparator(); addAction(aClone); addSeparator(); + addAction(aReduceLifeByPower); + addSeparator(); addAction(aSelectAll); addAction(aSelectRow); addRelatedCardView(); @@ -179,6 +184,8 @@ void CardMenu::createTableMenu(bool canModifyCard) addMenu(new PtMenu(player)); addAction(aSetAnnotation); addSeparator(); + addAction(aReduceLifeByPower); + addSeparator(); addAction(aSelectAll); addAction(aSelectRow); @@ -463,6 +470,7 @@ void CardMenu::retranslateUi() aUnattach->setText(tr("Unattac&h")); aDrawArrow->setText(tr("&Draw arrow...")); aSetAnnotation->setText(tr("&Set annotation...")); + aReduceLifeByPower->setText(tr("Reduce life by power")); mCardCounters->setTitle(tr("Ca&rd counters")); @@ -497,6 +505,7 @@ void CardMenu::setShortcutsActive() aUnattach->setShortcuts(shortcuts.getShortcut("Player/aUnattach")); aDrawArrow->setShortcuts(shortcuts.getShortcut("Player/aDrawArrow")); aSetAnnotation->setShortcuts(shortcuts.getShortcut("Player/aSetAnnotation")); + aReduceLifeByPower->setShortcuts(shortcuts.getShortcut("Player/aReduceLifeByPower")); aSelectAll->setShortcuts(shortcuts.getShortcut("Player/aSelectAll")); aSelectRow->setShortcuts(shortcuts.getShortcut("Player/aSelectRow")); diff --git a/cockatrice/src/game/player/menu/card_menu.h b/cockatrice/src/game/player/menu/card_menu.h index b7f2f8241..3cff238de 100644 --- a/cockatrice/src/game/player/menu/card_menu.h +++ b/cockatrice/src/game/player/menu/card_menu.h @@ -36,6 +36,7 @@ public: QAction *aFlip, *aPeek; QAction *aAttach, *aUnattach; QAction *aSetAnnotation; + QAction *aReduceLifeByPower; QList aAddCounter, aSetCounter, aRemoveCounter; diff --git a/cockatrice/src/game/player/player.cpp b/cockatrice/src/game/player/player.cpp index e95e2b2ef..8f5067eae 100644 --- a/cockatrice/src/game/player/player.cpp +++ b/cockatrice/src/game/player/player.cpp @@ -343,6 +343,16 @@ void Player::incrementAllCardCounters() } } +AbstractCounter *Player::getLifeCounter() const +{ + for (auto counter : counters.values()) { + if (counter->getName() == "life") { + return counter; + } + } + return nullptr; +} + ArrowItem *Player::addArrow(const ServerInfo_Arrow &arrow) { const QMap &playerList = game->getPlayerManager()->getPlayers(); diff --git a/cockatrice/src/game/player/player.h b/cockatrice/src/game/player/player.h index 9b8456aaf..1e7bc928d 100644 --- a/cockatrice/src/game/player/player.h +++ b/cockatrice/src/game/player/player.h @@ -199,6 +199,11 @@ public: return counters; } + /** + * Gets the counter that represents the life total. + */ + AbstractCounter *getLifeCounter() const; + ArrowItem *addArrow(const ServerInfo_Arrow &arrow); ArrowItem *addArrow(int arrowId, CardItem *startCard, ArrowTarget *targetItem, const QColor &color); void delArrow(int arrowId); diff --git a/cockatrice/src/game/player/player_actions.cpp b/cockatrice/src/game/player/player_actions.cpp index bce8af74b..24da37c82 100644 --- a/cockatrice/src/game/player/player_actions.cpp +++ b/cockatrice/src/game/player/player_actions.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -1378,6 +1379,32 @@ void PlayerActions::actFlowT() actIncPT(-1, 1); } +void PlayerActions::actReduceLifeByPower() +{ + // find life counter + auto lifeCounter = player->getLifeCounter(); + if (!lifeCounter) { + return; + } + + // calculate total power + auto cards = player->getGameScene()->selectedCards(); + int total = 0; + for (auto card : cards) { + QVariantList parsed = CardItem::parsePT(card->getPT()); + if (!parsed.isEmpty()) { + int power = parsed.first().toInt(); // toInt will default to 0 if it's not an int + total += qMax(power, 0); + } + } + + // send cmd + Command_IncCounter cmd; + cmd.set_counter_id(lifeCounter->getId()); + cmd.set_delta(-total); + sendGameCommand(prepareGameCommand(cmd)); +} + void AnnotationDialog::keyPressEvent(QKeyEvent *event) { if (event->key() == Qt::Key_Return && event->modifiers() & Qt::ControlModifier) { diff --git a/cockatrice/src/game/player/player_actions.h b/cockatrice/src/game/player/player_actions.h index 181b1b135..ba62f1c59 100644 --- a/cockatrice/src/game/player/player_actions.h +++ b/cockatrice/src/game/player/player_actions.h @@ -145,6 +145,9 @@ public slots: void actDecPT(); void actFlowP(); void actFlowT(); + + void actReduceLifeByPower(); + void actSetAnnotation(); void actReveal(QAction *action); void actRevealHand(int revealToPlayerId); From 7153f7d4c11d92cc8690e1365037896e28da8d3d Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Thu, 14 May 2026 19:07:15 +0200 Subject: [PATCH 08/51] [VDD] Fix minimum size by adding a compact mode to quickSettingsButtons (#6890) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [VDD] Fix minimum size by adding a compact mode to quickSettingsButtons Took 17 minutes Took 5 seconds * Fix and use FlowWidget/FlowLayout Took 35 minutes Took 4 seconds * Set spacings. Took 12 minutes * Make VDE tools flow Took 1 hour 23 minutes Took 5 seconds * Squeeze and flow even more. Took 11 minutes * Make pushbutton compact. Took 54 minutes Took 7 seconds --------- Co-authored-by: Lukas Brübach --- cockatrice/CMakeLists.txt | 2 + .../src/interface/layouts/flow_layout.cpp | 696 +++++++----------- .../src/interface/layouts/flow_layout.h | 58 +- .../draw_probability_widget.cpp | 20 +- .../draw_probability_widget.h | 5 +- .../deck_analytics/deck_analytics_widget.cpp | 14 +- .../deck_analytics/deck_analytics_widget.h | 4 +- .../general/layout_containers/flow_widget.cpp | 144 ++-- .../general/layout_containers/flow_widget.h | 14 +- .../quick_settings/settings_button_widget.cpp | 26 +- .../quick_settings/settings_button_widget.h | 7 + .../widgets/utility/compact_push_button.cpp | 73 ++ .../widgets/utility/compact_push_button.h | 31 + ...database_display_filter_toolbar_widget.cpp | 48 +- ...l_database_display_filter_toolbar_widget.h | 9 +- .../visual_database_display_widget.cpp | 12 +- .../visual_database_display_widget.h | 3 +- .../visual_deck_display_options_widget.cpp | 30 +- .../visual_deck_display_options_widget.h | 5 +- .../visual_deck_editor_widget.cpp | 70 +- .../visual_deck_editor_widget.h | 12 +- 21 files changed, 666 insertions(+), 617 deletions(-) create mode 100644 cockatrice/src/interface/widgets/utility/compact_push_button.cpp create mode 100644 cockatrice/src/interface/widgets/utility/compact_push_button.h diff --git a/cockatrice/CMakeLists.txt b/cockatrice/CMakeLists.txt index 1d07371d8..1017f1247 100644 --- a/cockatrice/CMakeLists.txt +++ b/cockatrice/CMakeLists.txt @@ -327,6 +327,8 @@ set(cockatrice_SOURCES src/interface/widgets/tabs/api/edhrec/display/commander/edhrec_commander_api_response_bracket_navigation_widget.h src/interface/widgets/tabs/api/edhrec/display/commander/edhrec_commander_api_response_budget_navigation_widget.cpp src/interface/widgets/tabs/api/edhrec/display/commander/edhrec_commander_api_response_budget_navigation_widget.h + src/interface/widgets/utility/compact_push_button.cpp + src/interface/widgets/utility/compact_push_button.h ) add_subdirectory(sounds) diff --git a/cockatrice/src/interface/layouts/flow_layout.cpp b/cockatrice/src/interface/layouts/flow_layout.cpp index f7ebbfb79..36edd2c21 100644 --- a/cockatrice/src/interface/layouts/flow_layout.cpp +++ b/cockatrice/src/interface/layouts/flow_layout.cpp @@ -1,7 +1,16 @@ /** * @file flow_layout.cpp - * @brief Implementation of the FlowLayout class, a custom layout for dynamically organizing widgets - * in rows within the constraints of available width or parent scroll areas. + * @brief Implementation of FlowLayout — a QLayout that wraps child widgets into rows + * (Qt::Horizontal flow) or columns (Qt::Vertical flow). + * + * Design contract (following Qt layout conventions): + * - setGeometry() places children inside the given rect. Nothing else. + * - sizeHint() reports the unconstrained preferred size (all items in one line). + * - minimumSize() reports the minimum size (largest single item). + * - heightForWidth() reports the height needed for a given width (horizontal flow only). + * + * The layout never calls setFixedSize() or adjustSize() on its parent widget; + * that is the responsibility of the parent widget / scroll area. */ #include "flow_layout.h" @@ -12,27 +21,18 @@ #include #include #include +#include -/** - * @brief Constructs a FlowLayout instance with the specified parent widget, margin, and spacing values. - * @param parent The parent widget for this layout. - * @param margin The layout margin. - * @param hSpacing The horizontal spacing between items. - * @param vSpacing The vertical spacing between items. - */ FlowLayout::FlowLayout(QWidget *parent, - const Qt::Orientation _flowDirection, + const Qt::Orientation flowDirection, const int margin, const int hSpacing, const int vSpacing) - : QLayout(parent), flowDirection(_flowDirection), horizontalMargin(hSpacing), verticalMargin(vSpacing) + : QLayout(parent), flowDirection(flowDirection), horizontalMargin(hSpacing), verticalMargin(vSpacing) { setContentsMargins(margin, margin, margin, margin); } -/** - * @brief Destructor for FlowLayout, which cleans up all items in the layout. - */ FlowLayout::~FlowLayout() { QLayoutItem *item; @@ -42,499 +42,349 @@ FlowLayout::~FlowLayout() } /** - * @brief Indicates the layout's support for expansion in both horizontal and vertical directions. - * @return The orientations (Qt::Horizontal | Qt::Vertical) this layout can expand to fill. + * @brief Reports which axis the layout can expand along. + * + * A horizontally-flowing layout expands horizontally (and wraps vertically, + * but that is governed by heightForWidth, not by this flag). + * A vertically-flowing layout expands vertically. */ Qt::Orientations FlowLayout::expandingDirections() const { - return Qt::Horizontal | Qt::Vertical; + return (flowDirection == Qt::Horizontal) ? Qt::Horizontal : Qt::Vertical; } /** - * @brief Indicates that this layout's height depends on its width. - * @return True, as the layout adjusts its height to fit the specified width. + * @brief Height-for-width is only meaningful for horizontal (wrapping) flow. */ bool FlowLayout::hasHeightForWidth() const { - return true; + return flowDirection == Qt::Horizontal; } /** - * @brief Calculates the required height to display all items within the specified width. - * @param width The available width for arranging items. - * @return The total height needed to fit all items in rows constrained by the specified width. + * @brief Returns the height required to display all items within @p width. + * + * Only valid for horizontal flow; returns -1 otherwise so Qt ignores it. + * Spacing is counted once between adjacent items, never before the first + * or after the last. */ int FlowLayout::heightForWidth(const int width) const { - if (flowDirection == Qt::Vertical) { - int height = 0; - int rowWidth = 0; - int rowHeight = 0; + if (flowDirection != Qt::Horizontal) + return -1; - for (const QLayoutItem *item : items) { - if (item == nullptr || item->isEmpty()) { - continue; - } + int totalHeight = 0; + int rowUsedWidth = 0; + int rowHeight = 0; - int itemWidth = item->sizeHint().width() + horizontalSpacing(); - if (rowWidth + itemWidth > width) { - height += rowHeight + verticalSpacing(); - rowWidth = itemWidth; - rowHeight = item->sizeHint().height(); - } else { - rowWidth += itemWidth; - rowHeight = qMax(rowHeight, item->sizeHint().height()); - } - } - height += rowHeight; // Add height of the last row - return height; - } else { - int width = 0; - int colWidth = 0; - int colHeight = 0; - - for (const QLayoutItem *item : items) { - if (item == nullptr || item->isEmpty()) { - continue; - } - - int itemHeight = item->sizeHint().height(); - if (colHeight + itemHeight > width) { - width += colWidth; - colHeight = itemHeight; - colWidth = item->sizeHint().width(); - } else { - colHeight += itemHeight; - colWidth = qMax(colWidth, item->sizeHint().width()); - } - } - width += colWidth; // Add width of the last column - return width; - } -} - -/** - * @brief Arranges layout items in rows within the specified rectangle bounds. - * @param rect The area within which to position layout items. - */ -void FlowLayout::setGeometry(const QRect &rect) -{ - QLayout::setGeometry(rect); // Sets the geometry of the layout based on the given rectangle. - - if (flowDirection == Qt::Horizontal) { - // If we have a parent scroll area, we're clamped to that, else we use our own rectangle. - const int availableWidth = getParentScrollAreaWidth() == 0 ? rect.width() : getParentScrollAreaWidth(); - - const int totalHeight = layoutAllRows(rect.x(), rect.y(), availableWidth); - - if (QWidget *parentWidgetPtr = parentWidget()) { - parentWidgetPtr->setFixedSize(availableWidth, totalHeight); - } - } else { - const int availableHeight = qMax(rect.height(), getParentScrollAreaHeight()); - - const int totalWidth = layoutAllColumns(rect.x(), rect.y(), availableHeight); - - if (QWidget *parentWidgetPtr = parentWidget()) { - parentWidgetPtr->setFixedSize(totalWidth, availableHeight); - } - } -} - -/** - * @brief Lays out items into rows according to the available width, starting from a given origin. - * Each row is arranged within `availableWidth`, wrapping to a new row as necessary. - * @param originX The x-coordinate for the layout start position. - * @param originY The y-coordinate for the layout start position. - * @param availableWidth The width within which each row is constrained. - * @return The total height after arranging all rows. - */ -int FlowLayout::layoutAllRows(const int originX, const int originY, const int availableWidth) -{ - QVector rowItems; // Holds items for the current row - int currentXPosition = originX; // Tracks the x-coordinate while placing items - int currentYPosition = originY; // Tracks the y-coordinate, moving down after each row - - int rowHeight = 0; // Tracks the maximum height of items in the current row - - for (QLayoutItem *item : items) { - if (item == nullptr || item->isEmpty()) { + for (const QLayoutItem *item : items) { + if (!item || item->isEmpty()) { continue; } - QSize itemSize = item->sizeHint(); // The suggested size for the current item - int itemWidth = itemSize.width() + horizontalSpacing(); // Item width plus spacing + const QSize itemSize = item->sizeHint(); + // Spacing is only inserted between items, not before the first. + const int spaceX = (rowUsedWidth > 0) ? horizontalSpacing() : 0; - // Check if the current item fits in the remaining width of the current row - if (currentXPosition + itemWidth > availableWidth) { - // If not, layout the current row and start a new row - layoutSingleRow(rowItems, originX, currentYPosition); - rowItems.clear(); // Reset the list for the new row - currentXPosition = originX; // Reset x-position to the row's start - currentYPosition += rowHeight + verticalSpacing(); // Move y-position down to the next row - rowHeight = 0; // Reset row height for the new row + if (rowUsedWidth > 0 && rowUsedWidth + spaceX + itemSize.width() > width) { + // This item overflows the current row — commit the row and start a new one. + totalHeight += rowHeight + verticalSpacing(); + rowUsedWidth = itemSize.width(); + rowHeight = itemSize.height(); + } else { + rowUsedWidth += spaceX + itemSize.width(); + rowHeight = qMax(rowHeight, itemSize.height()); + } + } + + return totalHeight + rowHeight; // Include the final (possibly only) row. +} + +/** + * @brief Places all children within @p rect. + * + * This is the only method that may move/resize children. It does NOT resize + * the parent widget; that would break Qt's layout protocol. + */ +void FlowLayout::setGeometry(const QRect &rect) +{ + QLayout::setGeometry(rect); + + if (flowDirection == Qt::Horizontal) { + layoutAllRows(rect.x(), rect.y(), rect.width()); + } else { + layoutAllColumns(rect.x(), rect.y(), rect.height()); + } +} + +QSize FlowLayout::sizeHint() const +{ + return (flowDirection == Qt::Horizontal) ? calculateSizeHintHorizontal() : calculateSizeHintVertical(); +} + +QSize FlowLayout::minimumSize() const +{ + return (flowDirection == Qt::Horizontal) ? calculateMinimumSizeHorizontal() : calculateMinimumSizeVertical(); +} + +// ─── Row layout (horizontal flow) ──────────────────────────────────────────── + +/** + * @brief Places all items into wrapping rows within @p availableWidth. + * @return The y-coordinate of the bottom edge of the last row. + */ +int FlowLayout::layoutAllRows(const int originX, const int originY, const int availableWidth) +{ + QVector rowItems; + int rowUsedWidth = 0; // Width consumed by items already in the current row. + int currentY = originY; + int rowHeight = 0; + + for (QLayoutItem *item : items) { + if (!item || item->isEmpty()) { + continue; + } + + const QSize itemSize = item->sizeHint(); + // No leading space for the first item in a row. + const int spaceX = rowItems.isEmpty() ? 0 : horizontalSpacing(); + + if (!rowItems.isEmpty() && rowUsedWidth + spaceX + itemSize.width() > availableWidth) { + // Current item does not fit — flush the current row, begin a new one. + layoutSingleRow(rowItems, originX, currentY, availableWidth); + rowItems.clear(); + currentY += rowHeight + verticalSpacing(); + rowUsedWidth = 0; + rowHeight = 0; } // Add the item to the current row rowItems.append(item); - rowHeight = qMax(rowHeight, itemSize.height()); // Update the row's height to the tallest item - currentXPosition += itemWidth + horizontalSpacing(); // Move x-position for the next item + // `rowItems.size() > 1` is equivalent to "this is not the first item in the row" + // because we just appended above. + rowUsedWidth += (rowItems.size() > 1 ? horizontalSpacing() : 0) + itemSize.width(); + rowHeight = qMax(rowHeight, itemSize.height()); } - // Layout the final row if there are any remaining items - layoutSingleRow(rowItems, originX, currentYPosition); - - // Return the total height used, including the last row's height - return currentYPosition + rowHeight; + layoutSingleRow(rowItems, originX, currentY, availableWidth); // Flush the final row. + return currentY + rowHeight; } /** - * @brief Arranges a single row of items within specified x and y starting positions. - * @param rowItems A list of items to be arranged in the row. - * @param x The starting x-coordinate for the row. - * @param y The starting y-coordinate for the row. + * @brief Sets the geometry for every item in @p rowItems, starting at (@p x, @p y). + * + * Items whose horizontal size policy includes the Expand or MinimumExpanding flag + * share the leftover row width proportionally (like QHBoxLayout stretch), so that + * e.g. a QLineEdit can fill remaining space while fixed-size buttons stay compact. + * + * Items without an expanding policy are placed at their sizeHint, clamped to maximumSize. */ -void FlowLayout::layoutSingleRow(const QVector &rowItems, int x, const int y) +void FlowLayout::layoutSingleRow(const QVector &rowItems, int x, const int y, const int availableWidth) { + if (rowItems.isEmpty()) + return; + + // ── Pass 1: measure fixed width and count expanding items ──────────────── + int fixedWidth = 0; + int expandingCount = 0; + int spacingTotal = (rowItems.size() - 1) * horizontalSpacing(); + for (QLayoutItem *item : rowItems) { - if (item == nullptr || item->isEmpty()) { + if (!item || item->isEmpty()) { continue; } - // Get the maximum allowed size for the item - QSize itemMaxSize = item->widget()->maximumSize(); - // Constrain the item's width and height to its size hint or maximum size - const int itemWidth = qMin(item->sizeHint().width(), itemMaxSize.width()); - const int itemHeight = qMin(item->sizeHint().height(), itemMaxSize.height()); - // Set the item's geometry based on the computed size and position + QWidget *widget = item->widget(); + const QSizePolicy::Policy hPolicy = widget ? widget->sizePolicy().horizontalPolicy() : QSizePolicy::Fixed; + + if (hPolicy & QSizePolicy::ExpandFlag) { + ++expandingCount; + } else { + const int maxW = widget ? widget->maximumWidth() : QWIDGETSIZE_MAX; + fixedWidth += qMin(item->sizeHint().width(), maxW); + } + } + + // Extra pixels to share among expanding items (never negative). + const int extra = qMax(0, availableWidth - spacingTotal - fixedWidth); + const int expandingShare = (expandingCount > 0) ? extra / expandingCount : 0; + + // ── Pass 2: place items ────────────────────────────────────────────────── + for (QLayoutItem *item : rowItems) { + if (!item || item->isEmpty()) + continue; + + QWidget *widget = item->widget(); + if (!widget) + continue; + + const QSizePolicy::Policy hPolicy = widget->sizePolicy().horizontalPolicy(); + const QSize maxSize = widget->maximumSize(); + const bool expands = hPolicy & QSizePolicy::ExpandFlag; + + const int itemWidth = + expands ? qMin(expandingShare, maxSize.width()) : qMin(item->sizeHint().width(), maxSize.width()); + const int itemHeight = qMin(item->sizeHint().height(), maxSize.height()); + item->setGeometry(QRect(QPoint(x, y), QSize(itemWidth, itemHeight))); - // Move the x-position to the right, leaving space for horizontal spacing x += itemWidth + horizontalSpacing(); } } +// ─── Column layout (vertical flow) ─────────────────────────────────────────── + /** - * @brief Lays out items into columns according to the available height, starting from a given origin. - * Each column is arranged within `availableHeight`, wrapping to a new column as necessary. - * @param originX The x-coordinate for the layout start position. - * @param originY The y-coordinate for the layout start position. - * @param availableHeight The height within which each column is constrained. - * @return The total width after arranging all columns. + * @brief Places all items into wrapping columns within @p availableHeight. + * @return The x-coordinate of the right edge of the last column. */ int FlowLayout::layoutAllColumns(const int originX, const int originY, const int availableHeight) { - QVector colItems; // Holds items for the current column - int currentXPosition = originX; // Tracks the x-coordinate while placing items - int currentYPosition = originY; // Tracks the y-coordinate, resetting for each new column - - int colWidth = 0; // Tracks the maximum width of items in the current column + QVector colItems; + int colUsedHeight = 0; // Height consumed by items already in the current column. + int currentX = originX; + int colWidth = 0; for (QLayoutItem *item : items) { - if (item == nullptr || item->isEmpty()) { + if (!item || item->isEmpty()) { continue; } - QSize itemSize = item->sizeHint(); // The suggested size for the current item + const QSize itemSize = item->sizeHint(); + // No leading space for the first item in a column. + const int spaceY = colItems.isEmpty() ? 0 : verticalSpacing(); - // Check if the current item fits in the remaining height of the current column - if (currentYPosition + itemSize.height() > availableHeight) { - // If not, layout the current column and start a new column - layoutSingleColumn(colItems, currentXPosition, originY); - colItems.clear(); // Reset the list for the new column - currentYPosition = originY; // Reset y-position to the column's start - currentXPosition += colWidth; // Move x-position to the next column - colWidth = 0; // Reset column width for the new column + if (!colItems.isEmpty() && colUsedHeight + spaceY + itemSize.height() > availableHeight) { + // Current item does not fit — flush the current column, begin a new one. + layoutSingleColumn(colItems, currentX, originY); + colItems.clear(); + currentX += colWidth + horizontalSpacing(); + colUsedHeight = 0; + colWidth = 0; } - // Add the item to the current column colItems.append(item); - colWidth = qMax(colWidth, itemSize.width()); // Update the column's width to the widest item - currentYPosition += itemSize.height(); // Move y-position for the next item + colUsedHeight += (colItems.size() > 1 ? verticalSpacing() : 0) + itemSize.height(); + colWidth = qMax(colWidth, itemSize.width()); } - // Layout the final column if there are any remaining items - layoutSingleColumn(colItems, currentXPosition, originY); - - // Return the total width used, including the last column's width - return currentXPosition + colWidth; + layoutSingleColumn(colItems, currentX, originY); // Flush the final column. + return currentX + colWidth; } /** - * @brief Arranges a single column of items within specified x and y starting positions. - * @param colItems A list of items to be arranged in the column. - * @param x The starting x-coordinate for the column. - * @param y The starting y-coordinate for the column. + * @brief Sets the geometry for every item in @p colItems, starting at (@p x, @p y). + * + * Each item is placed at its sizeHint, clamped to its maximumSize. */ void FlowLayout::layoutSingleColumn(const QVector &colItems, const int x, int y) { for (QLayoutItem *item : colItems) { - if (item == nullptr) { - qCDebug(FlowLayoutLog) << "Item is null."; + if (!item || item->isEmpty()) { + qCDebug(FlowLayoutLog) << "Skipping null or empty item in column."; continue; } - if (item->isEmpty()) { - qCDebug(FlowLayoutLog) << "Skipping empty item."; - continue; - } - - // Debugging: Print the item's widget class name and size hint QWidget *widget = item->widget(); - if (widget) { - qCDebug(FlowLayoutLog) << "Widget class:" << widget->metaObject()->className(); - qCDebug(FlowLayoutLog) << "Widget size hint:" << widget->sizeHint(); - qCDebug(FlowLayoutLog) << "Widget maximum size:" << widget->maximumSize(); - qCDebug(FlowLayoutLog) << "Widget minimum size:" << widget->minimumSize(); - - // Debugging: Print child widgets - const QObjectList &children = widget->children(); - qCDebug(FlowLayoutLog) << "Child widgets:"; - for (QObject *child : children) { - if (QWidget *childWidget = qobject_cast(child)) { - qCDebug(FlowLayoutLog) << " - Child widget class:" << childWidget->metaObject()->className(); - qCDebug(FlowLayoutLog) << " Size hint:" << childWidget->sizeHint(); - qCDebug(FlowLayoutLog) << " Maximum size:" << childWidget->maximumSize(); - } - } - } else { - qCDebug(FlowLayoutLog) << "Item does not have a widget."; + if (!widget) { + qCDebug(FlowLayoutLog) << "Item has no widget; skipping."; + continue; } - // Get the maximum allowed size for the item - QSize itemMaxSize = widget->maximumSize(); - // Constrain the item's width and height to its size hint or maximum size - const int itemWidth = qMin(item->sizeHint().width(), itemMaxSize.width()); - const int itemHeight = qMin(item->sizeHint().height(), itemMaxSize.height()); - // Debugging: Print the computed geometry - qCDebug(FlowLayoutLog) << "Computed geometry: x=" << x << ", y=" << y << ", width=" << itemWidth - << ", height=" << itemHeight; + qCDebug(FlowLayoutLog) << "Widget:" << widget->metaObject()->className() << "sizeHint:" << widget->sizeHint() + << "maximumSize:" << widget->maximumSize() << "minimumSize:" << widget->minimumSize(); + + const QSize maxSize = widget->maximumSize(); + const int itemWidth = qMin(item->sizeHint().width(), maxSize.width()); + const int itemHeight = qMin(item->sizeHint().height(), maxSize.height()); + + qCDebug(FlowLayoutLog) << "Placing at x=" << x << "y=" << y << "w=" << itemWidth << "h=" << itemHeight; // Set the item's geometry based on the computed size and position item->setGeometry(QRect(QPoint(x, y), QSize(itemWidth, itemHeight))); - - // Move the y-position down by the item's height to place the next item below - y += itemHeight; + y += itemHeight + verticalSpacing(); } } /** - * @brief Calculates the preferred size of the layout based on the flow direction. - * @return A QSize representing the ideal dimensions of the layout. - */ -QSize FlowLayout::sizeHint() const -{ - if (flowDirection == Qt::Horizontal) { - return calculateSizeHintHorizontal(); - } else { - return calculateSizeHintVertical(); - } -} - -/** - * @brief Calculates the minimum size required by the layout based on the flow direction. - * @return A QSize representing the minimum required dimensions. - */ -QSize FlowLayout::minimumSize() const -{ - if (flowDirection == Qt::Horizontal) { - return calculateMinimumSizeHorizontal(); - } else { - return calculateMinimumSizeVertical(); - } -} - -/** - * @brief Calculates the size hint for horizontal flow direction. - * @return A QSize representing the preferred dimensions. + * @brief Preferred size for horizontal flow: all items in a single row (unconstrained). + * + * The actual displayed height is determined by heightForWidth() once Qt knows the + * real available width. */ QSize FlowLayout::calculateSizeHintHorizontal() const { - int maxWidth = 0; // Tracks the maximum width needed - int totalHeight = 0; // Tracks the total height across all rows - int rowHeight = 0; // Tracks the height of the current row - int currentWidth = 0; // Tracks the current row's width - - const int availableWidth = getParentScrollAreaWidth() == 0 ? parentWidget()->width() : getParentScrollAreaWidth(); - - qCDebug(FlowLayoutLog) << "Calculating horizontal size hint. Available width:" << availableWidth; + int totalWidth = 0; + int maxHeight = 0; for (const QLayoutItem *item : items) { if (!item || item->isEmpty()) { - qCDebug(FlowLayoutLog) << "Skipping empty item."; continue; } - - QSize itemSize = item->sizeHint(); - int itemWidth = itemSize.width() + horizontalSpacing(); - qCDebug(FlowLayoutLog) << "Processing item. Size:" << itemSize << "Width with spacing:" << itemWidth; - - if (currentWidth + itemWidth > availableWidth) { - qCDebug(FlowLayoutLog) << "Row overflow. Current width:" << currentWidth << "Row height:" << rowHeight; - maxWidth = qMax(maxWidth, currentWidth); - totalHeight += rowHeight + verticalSpacing(); - qCDebug(FlowLayoutLog) << "Updated total height:" << totalHeight << "Max width so far:" << maxWidth; - - currentWidth = 0; - rowHeight = 0; + const QSize s = item->sizeHint(); + if (totalWidth > 0) { + totalWidth += horizontalSpacing(); } - - currentWidth += itemWidth; - rowHeight = qMax(rowHeight, itemSize.height()); - qCDebug(FlowLayoutLog) << "Updated current width:" << currentWidth << "Updated row height:" << rowHeight; + totalWidth += s.width(); + maxHeight = qMax(maxHeight, s.height()); } - - // Account for the final row - maxWidth = qMax(maxWidth, currentWidth); - totalHeight += rowHeight; - qCDebug(FlowLayoutLog) << "Final total height:" << totalHeight << "Final max width:" << maxWidth; - - return QSize(maxWidth, totalHeight); + return QSize(totalWidth, maxHeight); } /** - * @brief Calculates the minimum size for horizontal flow direction. - * @return A QSize representing the minimum required dimensions. + * @brief Minimum size for horizontal flow: the largest single item. + * + * This guarantees we can always display at least one item per row. */ QSize FlowLayout::calculateMinimumSizeHorizontal() const { - int maxWidth = 0; // Tracks the maximum width of a row - int totalHeight = 0; // Tracks the total height across all rows - int rowHeight = 0; // Tracks the height of the current row - int currentWidth = 0; // Tracks the current row's width + QSize size(0, 0); + for (const QLayoutItem *item : items) { + if (!item || item->isEmpty()) { + qCDebug(FlowLayoutLog) << "Skipping empty item."; + continue; + } + size = size.expandedTo(item->minimumSize()); + } + return size; +} - const int availableWidth = getParentScrollAreaWidth() == 0 ? parentWidget()->width() : getParentScrollAreaWidth(); - - qCDebug(FlowLayoutLog) << "Calculating horizontal minimum size. Available width:" << availableWidth; +/** + * @brief Preferred size for vertical flow: all items in a single column (unconstrained). + */ +QSize FlowLayout::calculateSizeHintVertical() const +{ + int maxWidth = 0; + int totalHeight = 0; for (const QLayoutItem *item : items) { if (!item || item->isEmpty()) { qCDebug(FlowLayoutLog) << "Skipping empty item."; continue; } - - QSize itemMinSize = item->minimumSize(); - int itemWidth = itemMinSize.width() + horizontalSpacing(); - qCDebug(FlowLayoutLog) << "Processing item. Minimum size:" << itemMinSize << "Width with spacing:" << itemWidth; - - if (currentWidth + itemWidth > availableWidth) { - qCDebug(FlowLayoutLog) << "Row overflow. Current width:" << currentWidth << "Row height:" << rowHeight; - maxWidth = qMax(maxWidth, currentWidth); - totalHeight += rowHeight + verticalSpacing(); - qCDebug(FlowLayoutLog) << "Updated total height:" << totalHeight << "Max width so far:" << maxWidth; - - currentWidth = 0; - rowHeight = 0; + const QSize s = item->sizeHint(); + if (totalHeight > 0) { + totalHeight += verticalSpacing(); } - - currentWidth += itemWidth; - rowHeight = qMax(rowHeight, itemMinSize.height()); - qCDebug(FlowLayoutLog) << "Updated current width:" << currentWidth << "Updated row height:" << rowHeight; + totalHeight += s.height(); + maxWidth = qMax(maxWidth, s.width()); } - - // Account for the final row - maxWidth = qMax(maxWidth, currentWidth); - totalHeight += rowHeight; - qCDebug(FlowLayoutLog) << "Final total height:" << totalHeight << "Final max width:" << maxWidth; - return QSize(maxWidth, totalHeight); } /** - * @brief Calculates the size hint for vertical flow direction. - * @return A QSize representing the preferred dimensions. - */ -QSize FlowLayout::calculateSizeHintVertical() const -{ - int totalWidth = 0; - int maxHeight = 0; - int colWidth = 0; - int currentHeight = 0; - - const int availableHeight = qMax(parentWidget()->height(), getParentScrollAreaHeight()); - - qCDebug(FlowLayoutLog) << "Calculating vertical size hint. Available height:" << availableHeight; - - for (const QLayoutItem *item : items) { - if (!item || item->isEmpty()) { - qCDebug(FlowLayoutLog) << "Skipping empty item."; - continue; - } - - QSize itemSize = item->sizeHint(); - qCDebug(FlowLayoutLog) << "Processing item. Size:" << itemSize; - - if (currentHeight + itemSize.height() > availableHeight) { - qCDebug(FlowLayoutLog) << "Column overflow. Current height:" << currentHeight - << "Column width:" << colWidth; - totalWidth += colWidth + horizontalSpacing(); - maxHeight = qMax(maxHeight, currentHeight); - qCDebug(FlowLayoutLog) << "Updated total width:" << totalWidth << "Max height so far:" << maxHeight; - - currentHeight = 0; - colWidth = 0; - } - - currentHeight += itemSize.height() + verticalSpacing(); - colWidth = qMax(colWidth, itemSize.width()); - qCDebug(FlowLayoutLog) << "Updated current height:" << currentHeight << "Updated column width:" << colWidth; - } - - // Account for the final column - totalWidth += colWidth; - maxHeight = qMax(maxHeight, currentHeight); - qCDebug(FlowLayoutLog) << "Final total width:" << totalWidth << "Final max height:" << maxHeight; - - return QSize(totalWidth, maxHeight); -} - -/** - * @brief Calculates the minimum size for vertical flow direction. - * @return A QSize representing the minimum required dimensions. + * @brief Minimum size for vertical flow: the largest single item. */ QSize FlowLayout::calculateMinimumSizeVertical() const { - int totalWidth = 0; // Tracks the total width across all columns - int maxHeight = 0; // Tracks the maximum height of a column - int colWidth = 0; // Tracks the width of the current column - int currentHeight = 0; // Tracks the current column's height - - const int availableHeight = qMax(parentWidget()->height(), getParentScrollAreaHeight()); - - qCDebug(FlowLayoutLog) << "Calculating vertical minimum size. Available height:" << availableHeight; - + QSize size(0, 0); for (const QLayoutItem *item : items) { if (!item || item->isEmpty()) { qCDebug(FlowLayoutLog) << "Skipping empty item."; continue; } - - QSize itemMinSize = item->minimumSize(); - int itemHeight = itemMinSize.height() + verticalSpacing(); - qCDebug(FlowLayoutLog) << "Processing item. Minimum size:" << itemMinSize - << "Height with spacing:" << itemHeight; - - if (currentHeight + itemHeight > availableHeight) { - qCDebug(FlowLayoutLog) << "Column overflow. Current height:" << currentHeight - << "Column width:" << colWidth; - totalWidth += colWidth + horizontalSpacing(); - maxHeight = qMax(maxHeight, currentHeight); - qCDebug(FlowLayoutLog) << "Updated total width:" << totalWidth << "Max height so far:" << maxHeight; - - currentHeight = 0; - colWidth = 0; - } - - currentHeight += itemHeight; - colWidth = qMax(colWidth, itemMinSize.width()); - qCDebug(FlowLayoutLog) << "Updated current height:" << currentHeight << "Updated column width:" << colWidth; + size = size.expandedTo(item->minimumSize()); } - - // Account for the final column - totalWidth += colWidth; - maxHeight = qMax(maxHeight, currentHeight); - qCDebug(FlowLayoutLog) << "Final total width:" << totalWidth << "Final max height:" << maxHeight; - - return QSize(totalWidth, maxHeight); + return size; } /** @@ -543,7 +393,7 @@ QSize FlowLayout::calculateMinimumSizeVertical() const */ void FlowLayout::addItem(QLayoutItem *item) { - if (item != nullptr) { + if (item) { items.append(item); } } @@ -551,11 +401,8 @@ void FlowLayout::addItem(QLayoutItem *item) void FlowLayout::insertWidgetAtIndex(QWidget *toInsert, int index) { addChildWidget(toInsert); - - // We don't want to fail on an index that violates the bounds, so we just clamp it. - int boundedIndex = qBound(0, index, qMax(0, static_cast(items.size()))); - items.insert(boundedIndex, new QWidgetItem(toInsert)); - + const int bounded = qBound(0, index, static_cast(items.size())); + items.insert(bounded, new QWidgetItem(toInsert)); invalidate(); } @@ -613,52 +460,13 @@ int FlowLayout::verticalSpacing() const */ int FlowLayout::smartSpacing(const QStyle::PixelMetric pm) const { - QObject *parent = this->parent(); - - if (!parent) { + QObject *p = parent(); + if (!p) { return -1; } - - if (parent->isWidgetType()) { - const auto *pw = dynamic_cast(parent); + if (p->isWidgetType()) { + const auto *pw = static_cast(p); return pw->style()->pixelMetric(pm, nullptr, pw); } - - return dynamic_cast(parent)->spacing(); -} - -/** - * @brief Gets the width of the parent scroll area, if any. - * @return The width of the scroll area's viewport, or 0 if not found. - */ -int FlowLayout::getParentScrollAreaWidth() const -{ - QWidget *parent = parentWidget(); - - while (parent) { - if (const auto *scrollArea = qobject_cast(parent)) { - return scrollArea->viewport()->width(); - } - parent = parent->parentWidget(); - } - - return 0; -} - -/** - * @brief Gets the height of the parent scroll area, if any. - * @return The height of the scroll area's viewport, or 0 if not found. - */ -int FlowLayout::getParentScrollAreaHeight() const -{ - QWidget *parent = parentWidget(); - - while (parent) { - if (const auto *scrollArea = qobject_cast(parent)) { - return scrollArea->viewport()->height(); - } - parent = parent->parentWidget(); - } - - return 0; -} + return static_cast(p)->spacing(); +} \ No newline at end of file diff --git a/cockatrice/src/interface/layouts/flow_layout.h b/cockatrice/src/interface/layouts/flow_layout.h index cf109d260..cc206afae 100644 --- a/cockatrice/src/interface/layouts/flow_layout.h +++ b/cockatrice/src/interface/layouts/flow_layout.h @@ -1,7 +1,8 @@ /** * @file flow_layout.h * @ingroup UI - * @brief TODO: Document this. + * @brief A QLayout subclass that arranges child widgets in wrapping rows (horizontal flow) + * or wrapping columns (vertical flow). */ #ifndef FLOW_LAYOUT_H @@ -10,8 +11,8 @@ #include #include #include +#include #include -#include inline Q_LOGGING_CATEGORY(FlowLayoutLog, "flow_layout", QtInfoMsg); @@ -19,42 +20,55 @@ class FlowLayout : public QLayout { public: explicit FlowLayout(QWidget *parent = nullptr); - FlowLayout(QWidget *parent, Qt::Orientation _flowDirection, int margin = 0, int hSpacing = 0, int vSpacing = 0); + FlowLayout(QWidget *parent, Qt::Orientation flowDirection, int margin = 0, int hSpacing = 0, int vSpacing = 0); ~FlowLayout() override; + void insertWidgetAtIndex(QWidget *toInsert, int index); - [[nodiscard]] QSize calculateMinimumSizeHorizontal() const; - [[nodiscard]] QSize calculateSizeHintVertical() const; - [[nodiscard]] QSize calculateMinimumSizeVertical() const; + // QLayout interface void addItem(QLayoutItem *item) override; [[nodiscard]] int count() const override; [[nodiscard]] QLayoutItem *itemAt(int index) const override; QLayoutItem *takeAt(int index) override; - [[nodiscard]] int horizontalSpacing() const; + void setGeometry(const QRect &rect) override; + // Size negotiation [[nodiscard]] Qt::Orientations expandingDirections() const override; [[nodiscard]] bool hasHeightForWidth() const override; [[nodiscard]] int heightForWidth(int width) const override; - [[nodiscard]] int verticalSpacing() const; - [[nodiscard]] int doLayout(const QRect &rect, bool testOnly) const; - [[nodiscard]] int smartSpacing(QStyle::PixelMetric pm) const; - [[nodiscard]] int getParentScrollAreaWidth() const; - [[nodiscard]] int getParentScrollAreaHeight() const; - - void setGeometry(const QRect &rect) override; - virtual int layoutAllRows(int originX, int originY, int availableWidth); - virtual void layoutSingleRow(const QVector &rowItems, int x, int y); - int layoutAllColumns(int originX, int originY, int availableHeight); - void layoutSingleColumn(const QVector &colItems, int x, int y); [[nodiscard]] QSize sizeHint() const override; [[nodiscard]] QSize minimumSize() const override; - [[nodiscard]] QSize calculateSizeHintHorizontal() const; + + // Spacing helpers + void setHorizontalMargin(int margin) + { + horizontalMargin = margin; + } + [[nodiscard]] int horizontalSpacing() const; + void setVerticalMargin(int margin) + { + verticalMargin = margin; + } + [[nodiscard]] int verticalSpacing() const; + [[nodiscard]] int smartSpacing(QStyle::PixelMetric pm) const; + + // Layout passes (virtual so subclasses can override placement logic) + virtual int layoutAllRows(int originX, int originY, int availableWidth); + virtual void layoutSingleRow(const QVector &rowItems, int x, int y, int availableWidth); + int layoutAllColumns(int originX, int originY, int availableHeight); + void layoutSingleColumn(const QVector &colItems, int x, int y); protected: - QList items; // List to store layout items + // Size-hint helpers split by direction + [[nodiscard]] QSize calculateSizeHintHorizontal() const; + [[nodiscard]] QSize calculateMinimumSizeHorizontal() const; + [[nodiscard]] QSize calculateSizeHintVertical() const; + [[nodiscard]] QSize calculateMinimumSizeVertical() const; + + QList items; Qt::Orientation flowDirection; - int horizontalMargin; - int verticalMargin; + int horizontalMargin; ///< Horizontal spacing between items (-1 = use style default) + int verticalMargin; ///< Vertical spacing between items (-1 = use style default) }; #endif // FLOW_LAYOUT_H \ No newline at end of file diff --git a/cockatrice/src/interface/widgets/deck_analytics/analyzer_modules/draw_probability/draw_probability_widget.cpp b/cockatrice/src/interface/widgets/deck_analytics/analyzer_modules/draw_probability/draw_probability_widget.cpp index 4931aeaa4..0107294c7 100644 --- a/cockatrice/src/interface/widgets/deck_analytics/analyzer_modules/draw_probability/draw_probability_widget.cpp +++ b/cockatrice/src/interface/widgets/deck_analytics/analyzer_modules/draw_probability/draw_probability_widget.cpp @@ -20,12 +20,11 @@ DrawProbabilityWidget::DrawProbabilityWidget(QWidget *parent, DeckListStatisticsAnalyzer *analyzer) : AbstractAnalyticsPanelWidget(parent, analyzer) { - controls = new QWidget(this); - controlLayout = new QHBoxLayout(controls); - controlLayout->setContentsMargins(11, 0, 11, 0); + controls = new FlowWidget(this, Qt::Horizontal, Qt::ScrollBarAlwaysOff, Qt::ScrollBarAlwaysOff); + controls->setSpacing(4, 4); labelPrefix = new QLabel(this); - controlLayout->addWidget(labelPrefix); + controls->addWidget(labelPrefix); criteriaCombo = new QComboBox(this); // Give these things item-data so we can translate the actual user-facing strings @@ -33,33 +32,32 @@ DrawProbabilityWidget::DrawProbabilityWidget(QWidget *parent, DeckListStatistics criteriaCombo->addItem(QString(), "type"); criteriaCombo->addItem(QString(), "subtype"); criteriaCombo->addItem(QString(), "cmc"); - controlLayout->addWidget(criteriaCombo); + controls->addWidget(criteriaCombo); exactnessCombo = new QComboBox(this); exactnessCombo->addItem(QString(), true); // At least exactnessCombo->addItem(QString(), false); // Exactly - controlLayout->addWidget(exactnessCombo); + controls->addWidget(exactnessCombo); quantitySpin = new QSpinBox(this); quantitySpin->setRange(1, 60); - controlLayout->addWidget(quantitySpin); + controls->addWidget(quantitySpin); labelMiddle = new QLabel(this); - controlLayout->addWidget(labelMiddle); + controls->addWidget(labelMiddle); drawnSpin = new QSpinBox(this); drawnSpin->setRange(1, 60); drawnSpin->setValue(7); - controlLayout->addWidget(drawnSpin); + controls->addWidget(drawnSpin); labelSuffix = new QLabel(this); - controlLayout->addWidget(labelSuffix); + controls->addWidget(labelSuffix); labelPrefix->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); labelMiddle->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); labelSuffix->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); - controlLayout->addStretch(1); layout->addWidget(controls); // Table diff --git a/cockatrice/src/interface/widgets/deck_analytics/analyzer_modules/draw_probability/draw_probability_widget.h b/cockatrice/src/interface/widgets/deck_analytics/analyzer_modules/draw_probability/draw_probability_widget.h index 80015999f..9f7b971b1 100644 --- a/cockatrice/src/interface/widgets/deck_analytics/analyzer_modules/draw_probability/draw_probability_widget.h +++ b/cockatrice/src/interface/widgets/deck_analytics/analyzer_modules/draw_probability/draw_probability_widget.h @@ -1,6 +1,8 @@ #ifndef COCKATRICE_DRAW_PROBABILITY_WIDGET_H #define COCKATRICE_DRAW_PROBABILITY_WIDGET_H +#include "../../../../layouts/flow_layout.h" +#include "../../../general/layout_containers/flow_widget.h" #include "../../abstract_analytics_panel_widget.h" #include "../../deck_list_statistics_analyzer.h" #include "draw_probability_config.h" @@ -31,8 +33,7 @@ private slots: private: DrawProbabilityConfig config; - QWidget *controls; - QHBoxLayout *controlLayout; + FlowWidget *controls; QLabel *labelPrefix; QLabel *labelMiddle; QLabel *labelSuffix; diff --git a/cockatrice/src/interface/widgets/deck_analytics/deck_analytics_widget.cpp b/cockatrice/src/interface/widgets/deck_analytics/deck_analytics_widget.cpp index 147675e21..76552ea2f 100644 --- a/cockatrice/src/interface/widgets/deck_analytics/deck_analytics_widget.cpp +++ b/cockatrice/src/interface/widgets/deck_analytics/deck_analytics_widget.cpp @@ -23,8 +23,8 @@ DeckAnalyticsWidget::DeckAnalyticsWidget(QWidget *parent, DeckListStatisticsAnal layout = new QVBoxLayout(this); // Controls - controlContainer = new QWidget(this); - controlLayout = new QHBoxLayout(controlContainer); + controlContainer = new FlowWidget(this, Qt::Horizontal, Qt::ScrollBarAlwaysOff, Qt::ScrollBarAlwaysOff); + controlContainer->setSpacing(4, 4); addButton = new QPushButton(this); removeButton = new QPushButton(this); saveButton = new QPushButton(this); @@ -32,11 +32,11 @@ DeckAnalyticsWidget::DeckAnalyticsWidget(QWidget *parent, DeckListStatisticsAnal includeSideboardCheckBox = new QCheckBox(this); includeSideboardCheckBox->setChecked(false); - controlLayout->addWidget(addButton); - controlLayout->addWidget(removeButton); - controlLayout->addWidget(saveButton); - controlLayout->addWidget(loadButton); - controlLayout->addWidget(includeSideboardCheckBox); + controlContainer->addWidget(addButton); + controlContainer->addWidget(removeButton); + controlContainer->addWidget(saveButton); + controlContainer->addWidget(loadButton); + controlContainer->addWidget(includeSideboardCheckBox); layout->addWidget(controlContainer); diff --git a/cockatrice/src/interface/widgets/deck_analytics/deck_analytics_widget.h b/cockatrice/src/interface/widgets/deck_analytics/deck_analytics_widget.h index 09618c3f8..3c73deca2 100644 --- a/cockatrice/src/interface/widgets/deck_analytics/deck_analytics_widget.h +++ b/cockatrice/src/interface/widgets/deck_analytics/deck_analytics_widget.h @@ -7,6 +7,7 @@ #ifndef DECK_ANALYTICS_WIDGET_H #define DECK_ANALYTICS_WIDGET_H +#include "../general/layout_containers/flow_widget.h" #include "abstract_analytics_panel_widget.h" #include "deck_list_statistics_analyzer.h" #include "resizable_panel.h" @@ -51,8 +52,7 @@ private: void addPanelInstance(const QString &typeId, AbstractAnalyticsPanelWidget *panel, const QJsonObject &cfg = {}); QVBoxLayout *layout; - QWidget *controlContainer; - QHBoxLayout *controlLayout; + FlowWidget *controlContainer; QPushButton *addButton; QPushButton *removeButton; diff --git a/cockatrice/src/interface/widgets/general/layout_containers/flow_widget.cpp b/cockatrice/src/interface/widgets/general/layout_containers/flow_widget.cpp index 75ab56b34..59c657724 100644 --- a/cockatrice/src/interface/widgets/general/layout_containers/flow_widget.cpp +++ b/cockatrice/src/interface/widgets/general/layout_containers/flow_widget.cpp @@ -1,42 +1,52 @@ /** * @file flow_widget.cpp - * @brief Implementation of the FlowWidget class for organizing widgets in a flow layout within a scrollable area. + * @brief Implementation of FlowWidget — a QWidget hosting a FlowLayout inside an + * optional QScrollArea. */ #include "flow_widget.h" #include #include +#include +#include #include -#include -#include /** - * @brief Constructs a FlowWidget with a scrollable layout. + * @brief Constructs a FlowWidget. * - * @param parent The parent widget of this FlowWidget. - * @param horizontalPolicy The horizontal scroll bar policy for the scroll area. - * @param verticalPolicy The vertical scroll bar policy for the scroll area. + * When both scroll policies are Qt::ScrollBarAlwaysOff the scroll area is + * omitted entirely and the container is placed directly in the main layout. + * + * @param parent Parent widget. + * @param _flowDirection Qt::Horizontal for row-wrapping, Qt::Vertical for column-wrapping. + * @param horizontalPolicy Horizontal scroll-bar policy. + * @param verticalPolicy Vertical scroll-bar policy. */ FlowWidget::FlowWidget(QWidget *parent, const Qt::Orientation _flowDirection, const Qt::ScrollBarPolicy horizontalPolicy, const Qt::ScrollBarPolicy verticalPolicy) - : QWidget(parent), flowDirection(_flowDirection) + : QWidget(parent), scrollArea(nullptr), flowDirection(_flowDirection) + { - // Main Widget and Layout - if (_flowDirection == Qt::Horizontal) { - setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); - setMinimumWidth(0); + // Top-level size policy + // Horizontal flow: expand horizontally, let height be determined by wrapping. + // Vertical flow: expand vertically, let width be determined by wrapping. + if (flowDirection == Qt::Horizontal) { + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); } else { - setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding); - setMinimumHeight(0); + setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding); } + mainLayout = new QHBoxLayout(this); + mainLayout->setContentsMargins(0, 0, 0, 0); setLayout(mainLayout); - if (horizontalPolicy != Qt::ScrollBarAlwaysOff || verticalPolicy != Qt::ScrollBarAlwaysOff) { - // Scroll Area, which should expand as much as possible, since it should be the only direct child widget. + const bool useScrollArea = (horizontalPolicy != Qt::ScrollBarAlwaysOff || verticalPolicy != Qt::ScrollBarAlwaysOff); + + // Scroll area (optional) + if (useScrollArea) { scrollArea = new QScrollArea(this); scrollArea->setWidgetResizable(true); scrollArea->setMinimumSize(0, 0); @@ -48,39 +58,28 @@ FlowWidget::FlowWidget(QWidget *parent, scrollArea = nullptr; } - // Flow Layout inside the scroll area - if (horizontalPolicy == Qt::ScrollBarAlwaysOff && verticalPolicy == Qt::ScrollBarAlwaysOff) { - container = new QWidget(this); - } else { - container = new QWidget(scrollArea); - } + // Container widget (holds the FlowLayout) + container = new QWidget(useScrollArea ? static_cast(scrollArea) : this); + + // The container should be willing to grow in both axes; its actual size is + // governed by the FlowLayout's sizeHint / heightForWidth, not by a fixed policy. + container->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); + container->setMinimumSize(0, 0); flowLayout = new FlowLayout(container, flowDirection); - container->setLayout(flowLayout); - // The container should expand as much as possible, trusting the scrollArea to constrain it. - if (_flowDirection == Qt::Horizontal) { - container->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); - container->setMinimumWidth(0); - } else { - container->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); - container->setMinimumHeight(0); - } - // Use the FlowLayout container directly if we disable the ScrollArea - if (horizontalPolicy == Qt::ScrollBarAlwaysOff && verticalPolicy == Qt::ScrollBarAlwaysOff) { - mainLayout->addWidget(container); - } else { + if (useScrollArea) { scrollArea->setWidget(container); mainLayout->addWidget(scrollArea); + } else { + mainLayout->addWidget(container); } } /** * @brief Adds a widget to the flow layout within the FlowWidget. * - * Adjusts the widget's size policy based on the scroll bar policies. - * * @param widget_to_add The widget to add to the flow layout. */ void FlowWidget::addWidget(QWidget *widget_to_add) const @@ -100,77 +99,74 @@ void FlowWidget::removeWidget(QWidget *widgetToRemove) const } /** - * @brief Clears all widgets from the flow layout. + * @brief Removes all widgets from the flow layout and deletes them. * - * Deletes each widget and layout item, and recreates the flow layout if it was removed. + * If the layout pointer has somehow been lost it is recreated before returning. */ void FlowWidget::clearLayout() { - if (flowLayout != nullptr) { + if (flowLayout) { QLayoutItem *item; - while ((item = flowLayout->takeAt(0)) != nullptr) { - item->widget()->deleteLater(); // Delete the widget - delete item; // Delete the layout item + while ((item = flowLayout->takeAt(0))) { + if (item->widget()) + item->widget()->deleteLater(); + delete item; } } else { + // Defensive fallback: recreate the layout if it was deleted externally. flowLayout = new FlowLayout(container, flowDirection); container->setLayout(flowLayout); } } /** - * @brief Handles resize events for the FlowWidget. + * @brief Marks the flow layout as dirty so Qt recomputes item positions. * - * Triggers layout recalculation and adjusts the scroll area content size. - * - * @param event The resize event containing the new size information. + * We do NOT call adjustSize() or activate() here: + * - adjustSize() would freeze geometry by calling setFixedSize internally. + * - activate() called inside a resize event can cause synchronous re-entrancy. + * Qt automatically calls setGeometry on the layout after a resize, so simply + * invalidating is sufficient. */ void FlowWidget::resizeEvent(QResizeEvent *event) { QWidget::resizeEvent(event); + qCDebug(FlowWidgetSizeLog) << "resizeEvent:" << event->size(); - qCDebug(FlowWidgetSizeLog) << event->size(); - - // Trigger the layout to recalculate - if (flowLayout != nullptr) { - flowLayout->invalidate(); // Marks the layout as dirty and requires recalculation - flowLayout->activate(); // Recalculate the layout based on the new size - } - - // Ensure the scroll area and its content adjust correctly - if (scrollArea != nullptr && scrollArea->widget() != nullptr) { - qCDebug(FlowWidgetSizeLog) << "Got a scrollarea: " << scrollArea->widget()->size(); - scrollArea->widget()->adjustSize(); - } else { - container->adjustSize(); + if (flowLayout) { + flowLayout->invalidate(); } } +void FlowWidget::setSpacing(int hSpacing, int vSpacing) +{ + flowLayout->setHorizontalMargin(hSpacing); + flowLayout->setVerticalMargin(vSpacing); + flowLayout->invalidate(); +} + /** - * @brief Sets the minimum size for all widgets inside the FlowWidget to the maximum sizeHint of all of them. + * @brief Sets every child widget's minimum size to the largest sizeHint in the layout. + * + * Useful for toolbars or button bars where all items should be the same size. */ void FlowWidget::setMinimumSizeToMaxSizeHint() { - QSize maxSize(0, 0); // Initialize to a zero size + QSize maxSize(0, 0); // Iterate over all widgets in the flow layout to find the maximum sizeHint for (int i = 0; i < flowLayout->count(); ++i) { - if (QLayoutItem *item = flowLayout->itemAt(i)) { - if (QWidget *widget = item->widget()) { - // Update the max size based on the sizeHint of each widget - QSize widgetSizeHint = widget->sizeHint(); - maxSize.setWidth(qMax(maxSize.width(), widgetSizeHint.width())); - maxSize.setHeight(qMax(maxSize.height(), widgetSizeHint.height())); - } + QLayoutItem *item = flowLayout->itemAt(i); + if (item && item->widget()) { + maxSize = maxSize.expandedTo(item->widget()->sizeHint()); } } // Set the minimum size for all widgets to the max sizeHint for (int i = 0; i < flowLayout->count(); ++i) { - if (QLayoutItem *item = flowLayout->itemAt(i)) { - if (QWidget *widget = item->widget()) { - widget->setMinimumSize(maxSize); - } + QLayoutItem *item = flowLayout->itemAt(i); + if (item && item->widget()) { + item->widget()->setMinimumSize(maxSize); } } } diff --git a/cockatrice/src/interface/widgets/general/layout_containers/flow_widget.h b/cockatrice/src/interface/widgets/general/layout_containers/flow_widget.h index d9fa49937..1932ce70a 100644 --- a/cockatrice/src/interface/widgets/general/layout_containers/flow_widget.h +++ b/cockatrice/src/interface/widgets/general/layout_containers/flow_widget.h @@ -1,22 +1,23 @@ /** * @file flow_widget.h * @ingroup UI - * @brief TODO: Document this. + * @brief A QWidget that wraps a FlowLayout inside an optional QScrollArea. */ #ifndef FLOW_WIDGET_H #define FLOW_WIDGET_H + #include "../../../layouts/flow_layout.h" #include #include +#include #include -#include inline Q_LOGGING_CATEGORY(FlowWidgetLog, "flow_widget", QtInfoMsg); inline Q_LOGGING_CATEGORY(FlowWidgetSizeLog, "flow_widget.size", QtInfoMsg); -class FlowWidget final : public QWidget +class FlowWidget : public QWidget { Q_OBJECT @@ -25,17 +26,20 @@ public: Qt::Orientation orientation, Qt::ScrollBarPolicy horizontalPolicy, Qt::ScrollBarPolicy verticalPolicy); + void addWidget(QWidget *widget_to_add) const; void insertWidgetAtIndex(QWidget *toInsert, int index); void removeWidget(QWidget *widgetToRemove) const; void clearLayout(); + [[nodiscard]] int count() const; [[nodiscard]] QLayoutItem *itemAt(int index) const; - QScrollArea *scrollArea; + QScrollArea *scrollArea; ///< Null when both scroll policies are AlwaysOff. public slots: void setMinimumSizeToMaxSizeHint(); + void setSpacing(int hSpacing, int vSpacing); protected: void resizeEvent(QResizeEvent *event) override; @@ -47,4 +51,4 @@ private: QWidget *container; }; -#endif // FLOW_WIDGET_H +#endif // FLOW_WIDGET_H \ No newline at end of file diff --git a/cockatrice/src/interface/widgets/quick_settings/settings_button_widget.cpp b/cockatrice/src/interface/widgets/quick_settings/settings_button_widget.cpp index 81812104a..badc437ee 100644 --- a/cockatrice/src/interface/widgets/quick_settings/settings_button_widget.cpp +++ b/cockatrice/src/interface/widgets/quick_settings/settings_button_widget.cpp @@ -35,19 +35,33 @@ void SettingsButtonWidget::setButtonIcon(QPixmap iconMap) button->setIcon(iconMap); } -void SettingsButtonWidget::setButtonText(const QString &buttonText) +void SettingsButtonWidget::setButtonText(const QString &text) { - // 🔓 unlock size constraints + buttonText = text; + button->setMinimumSize(QSize(0, 0)); button->setMaximumSize(QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX)); - button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); - button->setText(buttonText); - + button->setText(text); button->setFixedHeight(32); button->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); - button->setMinimumWidth(button->sizeHint().width()); + button->setMinimumWidth(32); // icon-only fallback minimum +} + +void SettingsButtonWidget::setCompact(bool _compact) +{ + compact = _compact; + if (compact) { + button->setToolButtonStyle(Qt::ToolButtonIconOnly); + button->setFixedWidth(32); + } else { + button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + button->setText(buttonText); + button->setFixedWidth(QWIDGETSIZE_MAX); // release fixed width + button->setMinimumWidth(32); + button->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); + } } void SettingsButtonWidget::togglePopup() diff --git a/cockatrice/src/interface/widgets/quick_settings/settings_button_widget.h b/cockatrice/src/interface/widgets/quick_settings/settings_button_widget.h index 36f01ac38..43de8183f 100644 --- a/cockatrice/src/interface/widgets/quick_settings/settings_button_widget.h +++ b/cockatrice/src/interface/widgets/quick_settings/settings_button_widget.h @@ -23,6 +23,11 @@ public: void removeSettingsWidget(QWidget *toRemove) const; void setButtonIcon(QPixmap iconMap); void setButtonText(const QString &buttonText); + void setCompact(bool compact); + bool isCompact() const + { + return compact; + }; protected: void mousePressEvent(QMouseEvent *event) override; @@ -34,6 +39,8 @@ private slots: private: QHBoxLayout *layout; QToolButton *button; + QString buttonText; + bool compact; public: SettingsPopupWidget *popup; diff --git a/cockatrice/src/interface/widgets/utility/compact_push_button.cpp b/cockatrice/src/interface/widgets/utility/compact_push_button.cpp new file mode 100644 index 000000000..cf98bfede --- /dev/null +++ b/cockatrice/src/interface/widgets/utility/compact_push_button.cpp @@ -0,0 +1,73 @@ +#include "compact_push_button.h" + +CompactPushButton::CompactPushButton(QWidget *parent) : QPushButton(parent) +{ + setCheckable(true); + setFixedHeight(32); + + // default sizing + setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); + + connect(this, &QPushButton::clicked, this, [] { + // your popup logic here + }); +} + +void CompactPushButton::setButtonText(const QString &text) +{ + fullText = text; + + if (!compact) { + setText(fullText); + } + + updateGeometryState(); +} + +void CompactPushButton::setButtonIcon(const QIcon &icon) +{ + setIcon(icon); +} + +void CompactPushButton::setCompact(bool enabled) +{ + compact = enabled; + + if (compact) { + setText(QString()); // icon only + } else { + setText(fullText); + } + + updateGeometryState(); +} + +void CompactPushButton::updateGeometryState() +{ + const int buttonHeight = 32; + + setMinimumHeight(buttonHeight); + setMaximumHeight(buttonHeight); + + if (compact) { + setMinimumWidth(buttonHeight); + setMaximumWidth(buttonHeight); + } else { + setMinimumWidth(0); + setMaximumWidth(QWIDGETSIZE_MAX); + } + + updateGeometry(); +} + +int CompactPushButton::expandedWidth() const +{ + QFontMetrics fm(font()); + + return fm.horizontalAdvance(fullText) + 48; // icon + padding +} + +int CompactPushButton::compactWidth() const +{ + return 32; +} \ No newline at end of file diff --git a/cockatrice/src/interface/widgets/utility/compact_push_button.h b/cockatrice/src/interface/widgets/utility/compact_push_button.h new file mode 100644 index 000000000..b0017beee --- /dev/null +++ b/cockatrice/src/interface/widgets/utility/compact_push_button.h @@ -0,0 +1,31 @@ +#ifndef COCKATRICE_COMPACT_PUSH_BUTTON_H +#define COCKATRICE_COMPACT_PUSH_BUTTON_H + +#include + +class CompactPushButton : public QPushButton +{ + Q_OBJECT + +public: + explicit CompactPushButton(QWidget *parent = nullptr); + + void setButtonText(const QString &text); + + void setButtonIcon(const QIcon &icon); + + void setCompact(bool enabled); + + int expandedWidth() const; + + int compactWidth() const; + +private: + void updateGeometryState(); + +private: + QString fullText; + bool compact = false; +}; + +#endif // COCKATRICE_COMPACT_PUSH_BUTTON_H diff --git a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_filter_toolbar_widget.cpp b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_filter_toolbar_widget.cpp index 790ac771a..885925694 100644 --- a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_filter_toolbar_widget.cpp +++ b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_filter_toolbar_widget.cpp @@ -5,16 +5,9 @@ #include VisualDatabaseDisplayFilterToolbarWidget::VisualDatabaseDisplayFilterToolbarWidget(VisualDatabaseDisplayWidget *_parent) - : QWidget(_parent), visualDatabaseDisplay(_parent) + : FlowWidget(_parent, Qt::Horizontal, Qt::ScrollBarAlwaysOff, Qt::ScrollBarAlwaysOff), + visualDatabaseDisplay(_parent) { - filterContainerLayout = new QHBoxLayout(this); - filterContainerLayout->setContentsMargins(11, 0, 11, 0); - filterContainerLayout->setSpacing(2); - setLayout(filterContainerLayout); - filterContainerLayout->setAlignment(Qt::AlignLeft); - - setMaximumHeight(80); - connect(this, &VisualDatabaseDisplayFilterToolbarWidget::searchModelChanged, visualDatabaseDisplay, &VisualDatabaseDisplayWidget::onSearchModelChanged); @@ -131,10 +124,18 @@ void VisualDatabaseDisplayFilterToolbarWidget::initialize() filterLayout->addWidget(quickFilterFormatLegalityWidget); // put everything into main layout - filterContainerLayout->addWidget(sortGroupBox); - filterContainerLayout->addWidget(filterGroupBox); - filterContainerLayout->addStretch(); - filterContainerLayout->addWidget(quickFilterSaveLoadWidget); + addWidget(sortGroupBox); + addWidget(filterGroupBox); + auto *spacer = new QWidget(this); + spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); + spacer->setAttribute(Qt::WA_TransparentForMouseEvents); + addWidget(spacer); + addWidget(quickFilterSaveLoadWidget); + addWidget(quickFilterSaveLoadWidget); + + // Force a layout pass so sizeHint() is accurate + layout()->activate(); + fullWidthHint = sizeHint().width(); } void VisualDatabaseDisplayFilterToolbarWidget::retranslateUi() @@ -155,4 +156,25 @@ void VisualDatabaseDisplayFilterToolbarWidget::retranslateUi() quickFilterSubTypeWidget->setButtonText(tr("Sub Type")); quickFilterSetWidget->setButtonText(tr("Sets")); quickFilterFormatLegalityWidget->setButtonText(tr("Formats")); +} + +void VisualDatabaseDisplayFilterToolbarWidget::resizeEvent(QResizeEvent *event) +{ + QWidget::resizeEvent(event); + updateCompactMode(event->size().width()); +} + +void VisualDatabaseDisplayFilterToolbarWidget::updateCompactMode(int availableWidth) +{ + const bool compact = availableWidth < fullWidthHint; + + const QList filterButtons = { + quickFilterSaveLoadWidget, quickFilterNameWidget, quickFilterMainTypeWidget, + quickFilterSubTypeWidget, quickFilterSetWidget, quickFilterFormatLegalityWidget, + }; + + for (auto *btn : filterButtons) { + if (btn->isCompact() != compact) // only act on transitions + btn->setCompact(compact); + } } \ No newline at end of file diff --git a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_filter_toolbar_widget.h b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_filter_toolbar_widget.h index 5cca5187a..5b55f4ba6 100644 --- a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_filter_toolbar_widget.h +++ b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_filter_toolbar_widget.h @@ -10,7 +10,7 @@ class VisualDatabaseDisplayWidget; -class VisualDatabaseDisplayFilterToolbarWidget : public QWidget +class VisualDatabaseDisplayFilterToolbarWidget : public FlowWidget { Q_OBJECT @@ -32,7 +32,6 @@ private: QGroupBox *filterGroupBox; QLabel *filterByLabel; - QHBoxLayout *filterContainerLayout; SettingsButtonWidget *quickFilterSaveLoadWidget; VisualDatabaseDisplayFilterSaveLoadWidget *saveLoadWidget; SettingsButtonWidget *quickFilterNameWidget; @@ -45,6 +44,12 @@ private: VisualDatabaseDisplaySetFilterWidget *setFilterWidget; SettingsButtonWidget *quickFilterFormatLegalityWidget; VisualDatabaseDisplayFormatLegalityFilterWidget *formatLegalityWidget; + + int fullWidthHint = 0; + void updateCompactMode(int availableWidth); + +protected: + void resizeEvent(QResizeEvent *event) override; }; #endif // COCKATRICE_VISUAL_DATABASE_DISPLAY_FILTER_TOOLBAR_WIDGET_H diff --git a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.cpp b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.cpp index 9c4432042..f9a783a3c 100644 --- a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.cpp +++ b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.cpp @@ -51,9 +51,7 @@ VisualDatabaseDisplayWidget::VisualDatabaseDisplayWidget(QWidget *parent, connect(cardSizeWidget, &CardSizeWidget::cardSizeSettingUpdated, &SettingsCache::instance(), &SettingsCache::setVisualDatabaseDisplayCardSize); - searchContainer = new QWidget(this); - searchLayout = new QHBoxLayout(searchContainer); - searchContainer->setLayout(searchLayout); + searchContainer = new FlowWidget(this, Qt::Horizontal, Qt::ScrollBarAlwaysOff, Qt::ScrollBarAlwaysOff); searchEdit = new SearchLineEdit(); searchEdit->setObjectName("searchEdit"); @@ -152,10 +150,10 @@ void VisualDatabaseDisplayWidget::initialize() filterContainer->initialize(); filterContainer->setVisible(true); - searchLayout->addWidget(colorFilterWidget); - searchLayout->addWidget(clearFilterWidget); - searchLayout->addWidget(searchEdit); - searchLayout->addWidget(displayModeButton); + searchContainer->addWidget(colorFilterWidget); + searchContainer->addWidget(clearFilterWidget); + searchContainer->addWidget(searchEdit); + searchContainer->addWidget(displayModeButton); mainLayout->addWidget(searchContainer); diff --git a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.h b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.h index 190ea1f6d..1db953b26 100644 --- a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.h +++ b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.h @@ -91,8 +91,7 @@ protected slots: void onDisplayModeChanged(bool checked); private: - QWidget *searchContainer; - QHBoxLayout *searchLayout; + FlowWidget *searchContainer; SearchLineEdit *searchEdit; QPushButton *displayModeButton; FilterTreeModel *filterModel; diff --git a/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_display_options_widget.cpp b/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_display_options_widget.cpp index 79a98fda6..f44c9c3ef 100644 --- a/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_display_options_widget.cpp +++ b/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_display_options_widget.cpp @@ -72,7 +72,7 @@ VisualDeckDisplayOptionsWidget::VisualDeckDisplayOptionsWidget(QWidget *parent) sortCriteriaButton->addSettingsWidget(sortLabel); sortCriteriaButton->addSettingsWidget(sortByListWidget); - displayTypeButton = new QPushButton(this); + displayTypeButton = new CompactPushButton(this); connect(displayTypeButton, &QPushButton::clicked, this, &VisualDeckDisplayOptionsWidget::updateDisplayType); groupAndSortLayout->addWidget(groupByLabel); @@ -91,7 +91,8 @@ void VisualDeckDisplayOptionsWidget::retranslateUi() sortByLabel->setText(tr("Sort by:")); sortLabel->setText(tr("Click and drag to change the sort order within the groups")); sortCriteriaButton->setToolTip(tr("Configure how cards are sorted within their groups")); - displayTypeButton->setText(tr("Toggle Layout: Overlap")); + displayTypeButton->setButtonText(tr("Toggle Layout: Overlap")); + displayTypeButton->setButtonIcon(QPixmap("theme:icons/scales")); displayTypeButton->setToolTip( tr("Change how cards are displayed within zones (i.e. overlapped or fully visible.)")); } @@ -115,11 +116,32 @@ void VisualDeckDisplayOptionsWidget::updateDisplayType() // Update UI and emit signal switch (currentDisplayType) { case DisplayType::Flat: - displayTypeButton->setText(tr("Toggle Layout: Flat")); + displayTypeButton->setButtonText(tr("Toggle Layout: Flat")); + displayTypeButton->setButtonIcon(QPixmap("theme:icons/scroll")); break; case DisplayType::Overlap: - displayTypeButton->setText(tr("Toggle Layout: Overlap")); + displayTypeButton->setButtonText(tr("Toggle Layout: Overlap")); + displayTypeButton->setButtonIcon(QPixmap("theme:icons/scales")); break; } emit displayTypeChanged(currentDisplayType); } + +void VisualDeckDisplayOptionsWidget::updateCompactMode(bool mode) +{ + displayTypeButton->setCompact(mode); +} + +int VisualDeckDisplayOptionsWidget::expandedWidth() const +{ + return groupByLabel->sizeHint().width() + groupByComboBox->sizeHint().width() + sortByLabel->sizeHint().width() + + sortCriteriaButton->sizeHint().width() + displayTypeButton->expandedWidth() + + (groupAndSortLayout->spacing() * 4); +} + +int VisualDeckDisplayOptionsWidget::compactWidth() const +{ + return groupByLabel->sizeHint().width() + groupByComboBox->sizeHint().width() + sortByLabel->sizeHint().width() + + sortCriteriaButton->sizeHint().width() + displayTypeButton->compactWidth() + + (groupAndSortLayout->spacing() * 4); +} diff --git a/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_display_options_widget.h b/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_display_options_widget.h index 7a447753f..9930ff50b 100644 --- a/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_display_options_widget.h +++ b/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_display_options_widget.h @@ -53,6 +53,9 @@ public slots: * Called when the application language changes. */ void retranslateUi(); + void updateCompactMode(bool mode); + int expandedWidth() const; + int compactWidth() const; public: /** @@ -108,7 +111,7 @@ private: DisplayType currentDisplayType = DisplayType::Overlap; /// Button used to toggle the display layout. - QPushButton *displayTypeButton; + CompactPushButton *displayTypeButton; /// Label for the group-by selector. QLabel *groupByLabel; diff --git a/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.cpp b/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.cpp index e957eb304..19a99d3e9 100644 --- a/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.cpp +++ b/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.cpp @@ -9,6 +9,7 @@ #include "../general/layout_containers/flow_widget.h" #include "../tabs/visual_deck_editor/tab_deck_editor_visual.h" #include "../tabs/visual_deck_editor/tab_deck_editor_visual_tab_widget.h" +#include "../utility/compact_push_button.h" #include "visual_deck_display_options_widget.h" #include @@ -69,7 +70,13 @@ VisualDeckEditorWidget::VisualDeckEditorWidget(QWidget *parent, void VisualDeckEditorWidget::initializeSearchBarAndCompleter() { - searchBar = new QLineEdit(this); + searchContainer = new QWidget(this); + searchContainer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); + searchLayout = new QHBoxLayout(searchContainer); + searchContainer->setLayout(searchLayout); + + searchBar = new QLineEdit(searchContainer); + searchContainer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); connect(searchBar, &QLineEdit::returnPressed, this, [=, this]() { if (!searchBar->hasFocus()) return; @@ -80,6 +87,8 @@ void VisualDeckEditorWidget::initializeSearchBarAndCompleter() } }); + searchLayout->addWidget(searchBar); + setFocusProxy(searchBar); setFocusPolicy(Qt::ClickFocus); @@ -133,13 +142,16 @@ void VisualDeckEditorWidget::initializeSearchBarAndCompleter() }); // Search button functionality - searchPushButton = new QPushButton(this); + searchPushButton = new CompactPushButton(searchContainer); + searchPushButton->setButtonIcon(QPixmap("theme:icons/search")); connect(searchPushButton, &QPushButton::clicked, this, [=, this]() { ExactCard card = CardDatabaseManager::query()->getCard({searchBar->text()}); if (card) { emit cardAdditionRequested(card); } }); + + searchLayout->addWidget(searchPushButton); } void VisualDeckEditorWidget::initializeDisplayOptionsWidget() @@ -156,18 +168,14 @@ void VisualDeckEditorWidget::initializeDisplayOptionsWidget() void VisualDeckEditorWidget::initializeDisplayOptionsAndSearchWidget() { initializeSearchBarAndCompleter(); - initializeDisplayOptionsWidget(); - displayOptionsAndSearch = new QWidget(this); - displayOptionsAndSearchLayout = new QHBoxLayout(displayOptionsAndSearch); - displayOptionsAndSearchLayout->setContentsMargins(0, 0, 0, 0); - displayOptionsAndSearchLayout->setAlignment(Qt::AlignLeft); - displayOptionsAndSearch->setLayout(displayOptionsAndSearchLayout); + displayOptionsAndSearch = new FlowWidget(this, Qt::Horizontal, Qt::ScrollBarAlwaysOff, Qt::ScrollBarAlwaysOff); - displayOptionsAndSearchLayout->addWidget(displayOptionsWidget); - displayOptionsAndSearchLayout->addWidget(searchBar); - displayOptionsAndSearchLayout->addWidget(searchPushButton); + // We split into two sub-widgets here so that the searchBar and button wrap together. At this point, we've done + // pretty much all we can and have reached our minimum size. + displayOptionsAndSearch->addWidget(displayOptionsWidget); + displayOptionsAndSearch->addWidget(searchContainer); // Expanding — fills remainder of its row } void VisualDeckEditorWidget::initializeScrollAreaAndZoneContainer() @@ -205,7 +213,7 @@ void VisualDeckEditorWidget::connectDeckListModel() void VisualDeckEditorWidget::retranslateUi() { searchBar->setPlaceholderText(tr("Type a card name here for suggestions from the database...")); - searchPushButton->setText(tr("Quick search and add card")); + searchPushButton->setButtonText(tr("Quick search and add card")); searchPushButton->setToolTip(tr("Search for closest match in the database (with auto-suggestions) and add " "preferred printing to the deck on pressing enter")); @@ -214,6 +222,44 @@ void VisualDeckEditorWidget::retranslateUi() } } +void VisualDeckEditorWidget::resizeEvent(QResizeEvent *event) +{ + QWidget::resizeEvent(event); + updateCompactMode(); +} + +void VisualDeckEditorWidget::updateCompactMode() +{ + const int spacing = displayOptionsAndSearch->layout()->spacing(); + + const int available = displayOptionsAndSearch->width(); + + const int searchExpanded = + searchBar->sizeHint().width() + searchPushButton->expandedWidth() + searchLayout->spacing(); + + const int fullWidth = displayOptionsWidget->expandedWidth() + spacing + searchExpanded; + + const int displayCompactWidth = displayOptionsWidget->compactWidth() + spacing + searchExpanded; + + // everything expanded + if (available >= fullWidth) { + displayOptionsWidget->updateCompactMode(false); + searchPushButton->setCompact(false); + return; + } + + // only display compact + if (available >= displayCompactWidth) { + displayOptionsWidget->updateCompactMode(true); + searchPushButton->setCompact(false); + return; + } + + // both compact + displayOptionsWidget->updateCompactMode(true); + searchPushButton->setCompact(true); +} + void VisualDeckEditorWidget::updatePlaceholderVisibility() { if (placeholderWidget) { diff --git a/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.h b/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.h index 13065d623..3b90ee4e2 100644 --- a/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.h +++ b/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.h @@ -11,6 +11,7 @@ #include "../cards/card_size_widget.h" #include "../general/layout_containers/overlap_control_widget.h" #include "../quick_settings/settings_button_widget.h" +#include "../utility/compact_push_button.h" #include "visual_deck_editor_placeholder_widget.h" #include @@ -39,6 +40,7 @@ class VisualDeckEditorWidget : public QWidget public: explicit VisualDeckEditorWidget(QWidget *parent, DeckListModel *deckListModel, QItemSelectionModel *selectionModel); void retranslateUi(); + void updateCompactMode(); void clearAllDisplayWidgets(); void setDeckList(const DeckList &_deckListModel); @@ -82,19 +84,23 @@ protected slots: void onHover(const ExactCard &hoveredCard); void onCardClick(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *instance, QString zoneName); void decklistModelReset(); + void resizeEvent(QResizeEvent *event) override; private: + int expandedWidthAll = -1; + int expandedWidthDisplayCompact = -1; DeckListModel *deckListModel; QItemSelectionModel *selectionModel; QVBoxLayout *mainLayout; CardDatabaseModel *cardDatabaseModel; CardDatabaseDisplayModel *cardDatabaseDisplayModel; CardCompleterProxyModel *proxyModel; + QWidget *searchContainer; + QHBoxLayout *searchLayout; QCompleter *completer; - QWidget *displayOptionsAndSearch; - QHBoxLayout *displayOptionsAndSearchLayout; + FlowWidget *displayOptionsAndSearch; VisualDeckDisplayOptionsWidget *displayOptionsWidget; - QPushButton *searchPushButton; + CompactPushButton *searchPushButton; QScrollArea *scrollArea; QWidget *zoneContainer; QVBoxLayout *zoneContainerLayout; From aadee342381ad4a7aea84ea1217e872956cd95ac Mon Sep 17 00:00:00 2001 From: DawnFire42 Date: Sat, 16 May 2026 13:19:53 -0400 Subject: [PATCH 09/51] style: Add braces to all control flow statements (#6887) * style: Add braces to all control flow statements Standardize code style by adding explicit braces to all single-statement control flow blocks (if, else, for, while) across the entire codebase. Also documents the InsertBraces clang-format option (requires v15+) for future automated enforcement. * InsertBraces-check-enabled --- .clang-format | 2 + .../remote_connection_controller.cpp | 20 +- .../interfaces/tapped_out_interface.cpp | 8 +- .../network/update/client/release_channel.cpp | 6 +- .../update/client/update_downloader.cpp | 6 +- .../src/client/settings/cache_settings.cpp | 51 ++- .../client/settings/card_counter_settings.cpp | 3 +- cockatrice/src/client/sound_engine.cpp | 6 +- cockatrice/src/filters/deck_filter_string.cpp | 21 +- cockatrice/src/filters/filter_builder.cpp | 12 +- cockatrice/src/filters/filter_tree_model.cpp | 96 +++-- cockatrice/src/game/abstract_game.cpp | 11 +- .../game/board/abstract_card_drag_item.cpp | 3 +- .../src/game/board/abstract_card_item.cpp | 37 +- .../src/game/board/abstract_counter.cpp | 22 +- cockatrice/src/game/board/arrow_item.cpp | 41 +- cockatrice/src/game/board/arrow_target.cpp | 6 +- cockatrice/src/game/board/card_drag_item.cpp | 31 +- cockatrice/src/game/board/card_item.cpp | 69 ++-- cockatrice/src/game/deckview/deck_view.cpp | 82 ++-- .../src/game/deckview/deck_view_container.cpp | 9 +- .../src/game/dialogs/dlg_create_token.cpp | 6 +- cockatrice/src/game/game_event_handler.cpp | 48 ++- cockatrice/src/game/game_meta_info.h | 6 +- cockatrice/src/game/game_scene.cpp | 74 ++-- cockatrice/src/game/game_view.cpp | 12 +- cockatrice/src/game/phases_toolbar.cpp | 30 +- .../src/game/player/menu/grave_menu.cpp | 3 +- cockatrice/src/game/player/menu/hand_menu.cpp | 12 +- .../src/game/player/menu/library_menu.cpp | 9 +- cockatrice/src/game/player/player.cpp | 3 +- cockatrice/src/game/player/player_actions.cpp | 3 +- .../src/game/player/player_list_widget.cpp | 43 +- cockatrice/src/game/player/player_manager.cpp | 12 +- cockatrice/src/game/player/player_target.cpp | 6 +- cockatrice/src/game/zones/card_zone.cpp | 14 +- cockatrice/src/game/zones/hand_zone.cpp | 18 +- .../src/game/zones/logic/card_zone_logic.cpp | 27 +- .../src/game/zones/logic/pile_zone_logic.cpp | 3 +- .../src/game/zones/logic/table_zone_logic.cpp | 3 +- cockatrice/src/game/zones/pile_zone.cpp | 18 +- cockatrice/src/game/zones/select_zone.cpp | 30 +- cockatrice/src/game/zones/table_zone.cpp | 56 ++- cockatrice/src/game/zones/view_zone.cpp | 7 +- .../src/game/zones/view_zone_widget.cpp | 21 +- .../board/abstract_graphics_item.cpp | 12 +- .../card_picture_loader.cpp | 3 +- .../card_picture_to_load.cpp | 3 +- cockatrice/src/interface/key_signals.cpp | 34 +- cockatrice/src/interface/logger.cpp | 3 +- .../src/interface/pixel_map_generator.cpp | 32 +- cockatrice/src/interface/theme_manager.cpp | 6 +- .../card_group_display_widget.cpp | 3 +- .../cards/card_info_display_widget.cpp | 6 +- .../widgets/cards/card_info_text_widget.cpp | 3 +- .../analytics_panel_widget_factory.cpp | 3 +- .../mana_base/mana_base_config_dialog.cpp | 3 +- .../mana_curve/mana_curve_config_dialog.cpp | 6 +- .../mana_curve/mana_curve_total_widget.cpp | 6 +- .../mana_curve/mana_curve_widget.cpp | 9 +- .../mana_devotion_config_dialog.cpp | 3 +- .../mana_distribution_config.cpp | 3 +- .../mana_distribution_config_dialog.cpp | 6 +- .../deck_list_statistics_analyzer.cpp | 6 +- .../deck_editor_database_display_widget.cpp | 3 +- .../deck_editor_deck_dock_widget.cpp | 9 +- .../deck_editor_filter_dock_widget.cpp | 6 +- .../deck_editor/deck_list_style_proxy.cpp | 3 +- .../deck_editor/deck_state_manager.cpp | 9 +- .../interface/widgets/dialogs/dlg_connect.cpp | 8 +- .../widgets/dialogs/dlg_create_game.cpp | 7 +- .../dialogs/dlg_default_tags_editor.cpp | 6 +- .../widgets/dialogs/dlg_edit_tokens.cpp | 12 +- .../widgets/dialogs/dlg_edit_user.cpp | 3 +- .../widgets/dialogs/dlg_filter_games.cpp | 6 +- .../widgets/dialogs/dlg_manage_sets.cpp | 21 +- .../widgets/dialogs/dlg_register.cpp | 3 +- .../dialogs/dlg_select_set_for_cards.cpp | 6 +- .../widgets/dialogs/dlg_settings.cpp | 45 ++- .../interface/widgets/dialogs/dlg_update.cpp | 3 +- .../widgets/dialogs/dlg_view_log.cpp | 3 +- .../widgets/dialogs/tip_of_the_day.cpp | 3 +- .../widgets/general/background_sources.h | 9 +- .../display/charts/bars/bar_chart_widget.cpp | 9 +- .../general/display/charts/bars/color_bar.cpp | 30 +- .../charts/bars/segmented_bar_widget.cpp | 6 +- .../general/display/charts/pies/color_pie.cpp | 3 +- .../interface/widgets/general/home_widget.cpp | 3 +- .../printing_selector_card_overlay_widget.cpp | 3 +- .../widgets/replay/replay_manager.cpp | 9 +- .../widgets/replay/replay_timeline_widget.cpp | 21 +- .../widgets/server/chat_view/chat_view.cpp | 57 ++- .../widgets/server/game_selector.cpp | 27 +- .../game_selector_quick_filter_toolbar.cpp | 3 +- .../interface/widgets/server/games_model.cpp | 81 ++-- .../widgets/server/handle_public_servers.cpp | 6 +- .../remote/remote_decklist_tree_widget.cpp | 60 ++- .../remote/remote_decklist_tree_widget.h | 3 +- .../remote/remote_replay_list_tree_widget.cpp | 72 ++-- .../widgets/server/user/user_context_menu.cpp | 15 +- .../widgets/server/user/user_info_box.cpp | 30 +- .../server/user/user_info_connection.cpp | 6 +- .../widgets/server/user/user_list_widget.cpp | 33 +- .../widgets/tabs/abstract_tab_deck_editor.cpp | 62 ++- .../api_response/archidekt_formats.h | 72 ++-- ...api_response_deck_entry_display_widget.cpp | 18 +- .../tabs/api/archidekt/tab_archidekt.cpp | 18 +- .../widgets/tabs/tab_deck_editor.cpp | 7 +- .../widgets/tabs/tab_deck_storage.cpp | 57 ++- .../src/interface/widgets/tabs/tab_game.cpp | 76 ++-- .../src/interface/widgets/tabs/tab_logs.cpp | 12 +- .../interface/widgets/tabs/tab_message.cpp | 18 +- .../interface/widgets/tabs/tab_replays.cpp | 21 +- .../src/interface/widgets/tabs/tab_room.cpp | 27 +- .../src/interface/widgets/tabs/tab_server.cpp | 42 +- .../interface/widgets/tabs/tab_supervisor.cpp | 112 +++-- .../tab_deck_editor_visual.cpp | 3 +- .../widgets/utility/custom_line_edit.cpp | 21 +- .../widgets/utility/line_edit_completer.cpp | 9 +- ...tabase_display_filter_save_load_widget.cpp | 12 +- ...al_database_display_name_filter_widget.cpp | 9 +- .../visual_database_display_widget.cpp | 3 +- .../visual_deck_editor_sample_hand_widget.cpp | 6 +- .../visual_deck_editor_widget.cpp | 3 +- .../visual_deck_storage_tag_filter_widget.cpp | 3 +- cockatrice/src/interface/window_main.cpp | 27 +- cockatrice/src/main.cpp | 6 +- .../card/database/card_database.cpp | 15 +- .../card/database/card_database_loader.cpp | 3 +- .../card/database/card_database_querier.cpp | 15 +- .../card/database/parser/cockatrice_xml_4.cpp | 3 +- .../card/format/format_legality_rules.h | 15 +- .../libcockatrice/card/game_specific_terms.h | 30 +- .../libcockatrice/card/set/card_set.cpp | 25 +- .../libcockatrice/deck_list/deck_list.cpp | 12 +- .../deck_list/deck_list_history_manager.cpp | 6 +- .../deck_list/deck_list_node_tree.cpp | 3 +- .../deck_list/sideboard_plan.cpp | 14 +- .../tree/abstract_deck_list_card_node.cpp | 3 +- .../deck_list/tree/inner_deck_list_node.cpp | 9 +- .../client/abstract/abstract_client.cpp | 3 +- .../network/client/remote/remote_client.cpp | 45 ++- .../remote/game/server_abstract_player.cpp | 6 +- .../server/remote/game/server_arrow.cpp | 3 +- .../server/remote/game/server_card.cpp | 29 +- .../server/remote/game/server_cardzone.cpp | 97 +++-- .../server/remote/game/server_game.cpp | 76 ++-- .../network/server/remote/server.cpp | 92 +++-- .../remote/server_abstractuserinterface.cpp | 18 +- .../server/remote/server_protocolhandler.cpp | 158 +++++--- .../remote/server_response_containers.cpp | 21 +- .../network/server/remote/server_room.cpp | 56 ++- .../remote/serverinfo_user_container.cpp | 8 +- .../protocol/debug_pb_message.cpp | 3 +- .../libcockatrice/protocol/featureset.cpp | 6 +- .../protocol/get_pb_extension.cpp | 6 +- .../libcockatrice/rng/rng_abstract.cpp | 11 +- .../libcockatrice/rng/rng_sfmt.cpp | 3 +- .../settings/servers_settings.cpp | 12 +- .../libcockatrice/utility/color.h | 6 +- .../libcockatrice/utility/expression.cpp | 3 +- .../libcockatrice/utility/levenshtein.cpp | 6 +- .../libcockatrice/utility/qt_utils.h | 9 +- oracle/src/oracleimporter.cpp | 21 +- servatrice/src/isl_interface.cpp | 25 +- servatrice/src/main.cpp | 19 +- servatrice/src/servatrice.cpp | 86 ++-- .../src/servatrice_database_interface.cpp | 338 ++++++++++------ servatrice/src/server_logger.cpp | 24 +- servatrice/src/serversocketinterface.cpp | 381 ++++++++++++------ servatrice/src/settingscache.cpp | 6 +- servatrice/src/signalhandler.cpp | 5 +- servatrice/src/smtpclient.cpp | 9 +- 173 files changed, 2725 insertions(+), 1461 deletions(-) diff --git a/.clang-format b/.clang-format index 1ef3ca6db..4be096155 100644 --- a/.clang-format +++ b/.clang-format @@ -26,6 +26,8 @@ PointerAlignment: Right SortIncludes: true IncludeBlocks: Regroup StatementAttributeLikeMacros: [emit] +# requires clang-format 15 +InsertBraces: true # requires clang-format 16 # RemoveSemicolon: true --- diff --git a/cockatrice/src/client/network/connection_controller/remote_connection_controller.cpp b/cockatrice/src/client/network/connection_controller/remote_connection_controller.cpp index f517acdc4..75cedcafc 100644 --- a/cockatrice/src/client/network/connection_controller/remote_connection_controller.cpp +++ b/cockatrice/src/client/network/connection_controller/remote_connection_controller.cpp @@ -140,13 +140,15 @@ void ConnectionController::onConnectionClosedEvent(const Event_ConnectionClosed } case Event_ConnectionClosed::BANNED: { reasonStr = tr("Banned by moderator"); - if (event.has_end_time()) + if (event.has_end_time()) { reasonStr.append( "\n" + tr("Expected end time: %1").arg(QDateTime::fromSecsSinceEpoch(event.end_time()).toString())); - else + } else { reasonStr.append("\n" + tr("This ban lasts indefinitely.")); - if (event.has_reason_str()) + } + if (event.has_reason_str()) { reasonStr.append("\n\n" + QString::fromStdString(event.reason_str())); + } break; } case Event_ConnectionClosed::SERVER_SHUTDOWN: { @@ -240,8 +242,9 @@ void ConnectionController::onLoginError(int r, QString bannedStr = endTime ? tr("You are banned until %1.").arg(QDateTime::fromSecsSinceEpoch(endTime).toString()) : tr("You are banned indefinitely."); - if (!reasonStr.isEmpty()) + if (!reasonStr.isEmpty()) { bannedStr.append("\n\n" + reasonStr); + } QMessageBox::critical(dialogParent, tr("Error"), bannedStr); break; } @@ -354,8 +357,9 @@ void ConnectionController::onRegisterError(int r, QString reasonStr, quint32 end QString bannedStr = endTime ? tr("You are banned until %1.").arg(QDateTime::fromSecsSinceEpoch(endTime).toString()) : tr("You are banned indefinitely."); - if (!reasonStr.isEmpty()) + if (!reasonStr.isEmpty()) { bannedStr.append("\n\n" + reasonStr); + } QMessageBox::critical(dialogParent, tr("Error"), bannedStr); break; } @@ -545,8 +549,9 @@ QString ConnectionController::extractInvalidUsernameMessage(QString &in) out += "
  • " + tr("can %1 contain numeric characters").arg((rules.at(4).toInt() > 0) ? "" : tr("NOT")) + "
  • "; - if (rules.at(6).size() > 0) + if (rules.at(6).size() > 0) { out += "
  • " + tr("can contain the following punctuation: %1").arg(rules.at(6).toHtmlEscaped()) + "
  • "; + } out += "
  • " + tr("first character can %1 be a punctuation mark").arg((rules.at(5).toInt() > 0) ? "" : tr("NOT")) + @@ -566,10 +571,11 @@ QString ConnectionController::extractInvalidUsernameMessage(QString &in) } } - if (rules.at(8).size() > 0) + if (rules.at(8).size() > 0) { out += "
  • " + tr("can not match any of the following expressions: %1").arg(rules.at(8).toHtmlEscaped()) + "
  • "; + } } out += ""; diff --git a/cockatrice/src/client/network/interfaces/tapped_out_interface.cpp b/cockatrice/src/client/network/interfaces/tapped_out_interface.cpp index af377d176..cd39ea251 100644 --- a/cockatrice/src/client/network/interfaces/tapped_out_interface.cpp +++ b/cockatrice/src/client/network/interfaces/tapped_out_interface.cpp @@ -99,14 +99,16 @@ void TappedOutInterface::copyDeckSplitMainAndSide(const DeckList &source, DeckLi { auto copyMainOrSide = [this, &mainboard, &sideboard](const auto node, const auto card) { CardInfoPtr dbCard = cardDatabase.query()->getCardInfo(card->getName()); - if (!dbCard || dbCard->getIsToken()) + if (!dbCard || dbCard->getIsToken()) { return; + } DecklistCardNode *addedCard; - if (node->getName() == DECK_ZONE_SIDE) + if (node->getName() == DECK_ZONE_SIDE) { addedCard = sideboard.addCard(card->getName(), node->getName(), -1); - else + } else { addedCard = mainboard.addCard(card->getName(), node->getName(), -1); + } addedCard->setNumber(card->getNumber()); }; diff --git a/cockatrice/src/client/network/update/client/release_channel.cpp b/cockatrice/src/client/network/update/client/release_channel.cpp index 9edfe7caf..260167bc8 100644 --- a/cockatrice/src/client/network/update/client/release_channel.cpp +++ b/cockatrice/src/client/network/update/client/release_channel.cpp @@ -129,8 +129,9 @@ void StableReleaseChannel::releaseListFinished() return; } - if (!lastRelease) + if (!lastRelease) { lastRelease = new Release; + } lastRelease->setName(resultMap["name"].toString()); lastRelease->setDescriptionUrl(resultMap["html_url"].toString()); @@ -246,8 +247,9 @@ void BetaReleaseChannel::releaseListFinished() return; } - if (lastRelease == nullptr) + if (lastRelease == nullptr) { lastRelease = new Release; + } lastRelease->setCommitHash(resultMap["target_commitish"].toString()); lastRelease->setPublishDate(resultMap["published_at"].toDate()); diff --git a/cockatrice/src/client/network/update/client/update_downloader.cpp b/cockatrice/src/client/network/update/client/update_downloader.cpp index c0f3e945c..a71bcf8f8 100644 --- a/cockatrice/src/client/network/update/client/update_downloader.cpp +++ b/cockatrice/src/client/network/update/client/update_downloader.cpp @@ -10,8 +10,9 @@ UpdateDownloader::UpdateDownloader(QObject *parent) : QObject(parent), response( void UpdateDownloader::beginDownload(QUrl downloadUrl) { // Save the original URL because we need it for the filename - if (originalUrl.isEmpty()) + if (originalUrl.isEmpty()) { originalUrl = downloadUrl; + } response = netMan->get(QNetworkRequest(downloadUrl)); connect(response, &QNetworkReply::finished, this, &UpdateDownloader::fileFinished); @@ -21,8 +22,9 @@ void UpdateDownloader::beginDownload(QUrl downloadUrl) void UpdateDownloader::downloadError(QNetworkReply::NetworkError) { - if (response == nullptr) + if (response == nullptr) { return; + } emit error(response->errorString().toUtf8()); } diff --git a/cockatrice/src/client/settings/cache_settings.cpp b/cockatrice/src/client/settings/cache_settings.cpp index 9a46c6426..779522b72 100644 --- a/cockatrice/src/client/settings/cache_settings.cpp +++ b/cockatrice/src/client/settings/cache_settings.cpp @@ -24,10 +24,11 @@ SettingsCache &SettingsCache::instance() QString SettingsCache::getDataPath() { - if (isPortableBuild) + if (isPortableBuild) { return qApp->applicationDirPath() + "/data"; - else + } else { return QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation); + } } QString SettingsCache::getSettingsPath() @@ -37,10 +38,11 @@ QString SettingsCache::getSettingsPath() QString SettingsCache::getCachePath() const { - if (isPortableBuild) + if (isPortableBuild) { return qApp->applicationDirPath() + "/cache"; - else + } else { return QStandardPaths::writableLocation(QStandardPaths::CacheLocation); + } } QString SettingsCache::getNetworkCachePath() const @@ -50,14 +52,17 @@ QString SettingsCache::getNetworkCachePath() const void SettingsCache::translateLegacySettings() { - if (isPortableBuild) + if (isPortableBuild) { return; + } // Layouts QFile layoutFile(getSettingsPath() + "layouts/deckLayout.ini"); - if (layoutFile.exists()) - if (layoutFile.copy(getSettingsPath() + "layouts.ini")) + if (layoutFile.exists()) { + if (layoutFile.copy(getSettingsPath() + "layouts.ini")) { layoutFile.remove(); + } + } QStringList usedKeys; QSettings legacySetting; @@ -116,10 +121,11 @@ void SettingsCache::translateLegacySettings() gameFilters().setHideIgnoredUserGames(legacySetting.value("hide_ignored_user_games").toBool()); gameFilters().setMinPlayers(legacySetting.value("min_players").toInt()); - if (legacySetting.value("max_players").toInt() > 1) + if (legacySetting.value("max_players").toInt() > 1) { gameFilters().setMaxPlayers(legacySetting.value("max_players").toInt()); - else + } else { gameFilters().setMaxPlayers(99); // This prevents a bug where no games will show if max was not set before + } QStringList allFilters = legacySetting.allKeys(); for (int i = 0; i < allFilters.size(); ++i) { @@ -135,8 +141,9 @@ void SettingsCache::translateLegacySettings() QStringList allLegacyKeys = legacySetting.allKeys(); for (int i = 0; i < allLegacyKeys.size(); ++i) { - if (usedKeys.contains(allLegacyKeys.at(i))) + if (usedKeys.contains(allLegacyKeys.at(i))) { continue; + } settings->setValue(allLegacyKeys.at(i), legacySetting.value(allLegacyKeys.at(i))); } } @@ -147,8 +154,9 @@ QString SettingsCache::getSafeConfigPath(QString configEntry, QString defaultPat // if the config settings is empty or refers to a not-existing folder, // ensure that the defaut path exists and return it if (tmp.isEmpty() || !QDir(tmp).exists()) { - if (!QDir().mkpath(defaultPath)) + if (!QDir().mkpath(defaultPath)) { qCInfo(SettingsCacheLog) << "[SettingsCache] Could not create folder:" << defaultPath; + } tmp = defaultPath; } return tmp; @@ -159,8 +167,9 @@ QString SettingsCache::getSafeConfigFilePath(QString configEntry, QString defaul QString tmp = settings->value(configEntry).toString(); // if the config settings is empty or refers to a not-existing file, // return the default Path - if (!QFile::exists(tmp) || tmp.isEmpty()) + if (!QFile::exists(tmp) || tmp.isEmpty()) { tmp = std::move(defaultPath); + } return tmp; } @@ -168,8 +177,9 @@ SettingsCache::SettingsCache() { // first, figure out if we are running in portable mode isPortableBuild = QFile::exists(qApp->applicationDirPath() + "/portable.dat"); - if (isPortableBuild) + if (isPortableBuild) { qCInfo(SettingsCacheLog) << "Portable mode enabled"; + } // define a dummy context that will be used where needed QString dummy = QT_TRANSLATE_NOOP("i18n", "English"); @@ -189,8 +199,9 @@ SettingsCache::SettingsCache() cardCounterSettings = new CardCounterSettings(settingsPath, this); - if (!QFile(settingsPath + "global.ini").exists()) + if (!QFile(settingsPath + "global.ini").exists()) { translateLegacySettings(); + } // updates - don't reorder them or their index in the settings won't match // append channels one by one, or msvc will add them in the wrong order. @@ -257,11 +268,13 @@ SettingsCache::SettingsCache() settings->setValue("personal/pixmapCacheSize", pixmapCacheSize); settings->setValue("personal/picturedownloadhq", false); settings->setValue("revert/pixmapCacheSize", true); - } else + } else { pixmapCacheSize = settings->value("personal/pixmapCacheSize", PIXMAPCACHE_SIZE_DEFAULT).toInt(); + } // sanity check - if (pixmapCacheSize < PIXMAPCACHE_SIZE_MIN || pixmapCacheSize > PIXMAPCACHE_SIZE_MAX) + if (pixmapCacheSize < PIXMAPCACHE_SIZE_MIN || pixmapCacheSize > PIXMAPCACHE_SIZE_MAX) { pixmapCacheSize = PIXMAPCACHE_SIZE_DEFAULT; + } networkCacheSize = settings->value("personal/networkCacheSize", NETWORK_CACHE_SIZE_DEFAULT).toInt(); redirectCacheTtl = settings->value("personal/redirectCacheTtl", NETWORK_REDIRECT_CACHE_TTL_DEFAULT).toInt(); @@ -770,8 +783,9 @@ void SettingsCache::setPrintingSelectorCardSize(int _printingSelectorCardSize) void SettingsCache::setIncludeRebalancedCards(bool _includeRebalancedCards) { - if (includeRebalancedCards == _includeRebalancedCards) + if (includeRebalancedCards == _includeRebalancedCards) { return; + } includeRebalancedCards = _includeRebalancedCards; settings->setValue("cards/includerebalancedcards", includeRebalancedCards); @@ -1310,8 +1324,9 @@ void SettingsCache::setMaxFontSize(int _max) void SettingsCache::setRoundCardCorners(bool _roundCardCorners) { - if (_roundCardCorners == roundCardCorners) + if (_roundCardCorners == roundCardCorners) { return; + } roundCardCorners = _roundCardCorners; settings->setValue("cards/roundcardcorners", _roundCardCorners); diff --git a/cockatrice/src/client/settings/card_counter_settings.cpp b/cockatrice/src/client/settings/card_counter_settings.cpp index 399365c99..662ae0c7d 100644 --- a/cockatrice/src/client/settings/card_counter_settings.cpp +++ b/cockatrice/src/client/settings/card_counter_settings.cpp @@ -15,8 +15,9 @@ void CardCounterSettings::setColor(int counterId, const QColor &color) QString key = QString("cards/counters/%1/color").arg(counterId); - if (settings.value(key).value() == color) + if (settings.value(key).value() == color) { return; + } settings.setValue(key, color); emit colorChanged(counterId, color); diff --git a/cockatrice/src/client/sound_engine.cpp b/cockatrice/src/client/sound_engine.cpp index 31cb2a35e..e592b5ea0 100644 --- a/cockatrice/src/client/sound_engine.cpp +++ b/cockatrice/src/client/sound_engine.cpp @@ -105,8 +105,9 @@ QStringMap &SoundEngine::getAvailableThemes() dir.setPath(SettingsCache::instance().getDataPath() + "/sounds"); for (const QString &themeName : dir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot, QDir::Name)) { - if (!availableThemes.contains(themeName)) + if (!availableThemes.contains(themeName)) { availableThemes.insert(themeName, dir.absoluteFilePath(themeName)); + } } // load themes from cockatrice system dir @@ -121,8 +122,9 @@ QStringMap &SoundEngine::getAvailableThemes() ); for (const QString &themeName : dir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot, QDir::Name)) { - if (!availableThemes.contains(themeName)) + if (!availableThemes.contains(themeName)) { availableThemes.insert(themeName, dir.absoluteFilePath(themeName)); + } } return availableThemes; diff --git a/cockatrice/src/filters/deck_filter_string.cpp b/cockatrice/src/filters/deck_filter_string.cpp index 6b671831d..dd873cfa5 100644 --- a/cockatrice/src/filters/deck_filter_string.cpp +++ b/cockatrice/src/filters/deck_filter_string.cpp @@ -88,20 +88,27 @@ static void setupParserRules() const auto arg = std::any_cast(sv[1]); const auto op = std::any_cast(sv[0]); - if (op == ">") + if (op == ">") { return [=](const int s) { return s > arg; }; - if (op == ">=") + } + if (op == ">=") { return [=](const int s) { return s >= arg; }; - if (op == "<") + } + if (op == "<") { return [=](const int s) { return s < arg; }; - if (op == "<=") + } + if (op == "<=") { return [=](const int s) { return s <= arg; }; - if (op == "=") + } + if (op == "=") { return [=](const int s) { return s == arg; }; - if (op == ":") + } + if (op == ":") { return [=](const int s) { return s == arg; }; - if (op == "!=") + } + if (op == "!=") { return [=](const int s) { return s != arg; }; + } return [](int) { return false; }; }; diff --git a/cockatrice/src/filters/filter_builder.cpp b/cockatrice/src/filters/filter_builder.cpp index 7178ce95a..785f753e7 100644 --- a/cockatrice/src/filters/filter_builder.cpp +++ b/cockatrice/src/filters/filter_builder.cpp @@ -11,13 +11,15 @@ FilterBuilder::FilterBuilder(QWidget *parent) : QWidget(parent) { filterCombo = new QComboBox; filterCombo->setObjectName("filterCombo"); - for (int i = 0; i < CardFilter::AttrEnd; i++) + for (int i = 0; i < CardFilter::AttrEnd; i++) { filterCombo->addItem(CardFilter::attrName(static_cast(i)), QVariant(i)); + } typeCombo = new QComboBox; typeCombo->setObjectName("typeCombo"); - for (int i = 0; i < CardFilter::TypeEnd; i++) + for (int i = 0; i < CardFilter::TypeEnd; i++) { typeCombo->addItem(CardFilter::typeName(static_cast(i)), QVariant(i)); + } QPushButton *ok = new QPushButton(QPixmap("theme:icons/increment"), QString()); ok->setObjectName("ok"); @@ -53,8 +55,9 @@ FilterBuilder::~FilterBuilder() void FilterBuilder::destroyFilter() { - if (fltr) + if (fltr) { delete fltr; + } } static int comboCurrentIntData(const QComboBox *combo) @@ -67,8 +70,9 @@ void FilterBuilder::emit_add() QString txt; txt = edit->text(); - if (txt.length() < 1) + if (txt.length() < 1) { return; + } destroyFilter(); fltr = new CardFilter(txt, static_cast(comboCurrentIntData(typeCombo)), diff --git a/cockatrice/src/filters/filter_tree_model.cpp b/cockatrice/src/filters/filter_tree_model.cpp index f0a02ec79..33b54530e 100644 --- a/cockatrice/src/filters/filter_tree_model.cpp +++ b/cockatrice/src/filters/filter_tree_model.cpp @@ -23,8 +23,9 @@ void FilterTreeModel::proxyBeginInsertRow(const FilterTreeNode *node, int i) int idx; idx = node->index(); - if (idx >= 0) + if (idx >= 0) { beginInsertRows(createIndex(idx, 0, (void *)node), i, i); + } } void FilterTreeModel::proxyEndInsertRow(const FilterTreeNode *node, int) @@ -32,8 +33,9 @@ void FilterTreeModel::proxyEndInsertRow(const FilterTreeNode *node, int) int idx; idx = node->index(); - if (idx >= 0) + if (idx >= 0) { endInsertRows(); + } } void FilterTreeModel::proxyBeginRemoveRow(const FilterTreeNode *node, int i) @@ -41,8 +43,9 @@ void FilterTreeModel::proxyBeginRemoveRow(const FilterTreeNode *node, int i) int idx; idx = node->index(); - if (idx >= 0) + if (idx >= 0) { beginRemoveRows(createIndex(idx, 0, (void *)node), i, i); + } } void FilterTreeModel::proxyEndRemoveRow(const FilterTreeNode *node, int) @@ -50,8 +53,9 @@ void FilterTreeModel::proxyEndRemoveRow(const FilterTreeNode *node, int) int idx; idx = node->index(); - if (idx >= 0) + if (idx >= 0) { endRemoveRows(); + } } FilterTreeNode *FilterTreeModel::indexToNode(const QModelIndex &idx) const @@ -59,12 +63,14 @@ FilterTreeNode *FilterTreeModel::indexToNode(const QModelIndex &idx) const void *ip; FilterTreeNode *node; - if (!idx.isValid()) + if (!idx.isValid()) { return fTree; + } ip = idx.internalPointer(); - if (ip == NULL) + if (ip == NULL) { return fTree; + } node = static_cast(ip); return node; @@ -145,14 +151,16 @@ int FilterTreeModel::rowCount(const QModelIndex &parent) const const FilterTreeNode *node; int result; - if (parent.column() > 0) + if (parent.column() > 0) { return 0; + } node = indexToNode(parent); - if (node) + if (node) { result = node->childCount(); - else + } else { result = 0; + } return result; } @@ -166,14 +174,17 @@ QVariant FilterTreeModel::data(const QModelIndex &index, int role) const { const FilterTreeNode *node; - if (!index.isValid()) + if (!index.isValid()) { return QVariant(); - if (index.column() >= columnCount()) + } + if (index.column() >= columnCount()) { return QVariant(); + } node = indexToNode(index); - if (node == NULL) + if (node == NULL) { return QVariant(); + } switch (role) { case Qt::FontRole: @@ -190,10 +201,11 @@ QVariant FilterTreeModel::data(const QModelIndex &index, int role) const case Qt::WhatsThisRole: return node->text(); case Qt::CheckStateRole: - if (node->isEnabled()) + if (node->isEnabled()) { return Qt::Checked; - else + } else { return Qt::Unchecked; + } default: return QVariant(); } @@ -205,22 +217,27 @@ bool FilterTreeModel::setData(const QModelIndex &index, const QVariant &value, i { FilterTreeNode *node; - if (!index.isValid()) + if (!index.isValid()) { return false; - if (index.column() >= columnCount()) + } + if (index.column() >= columnCount()) { return false; - if (role != Qt::CheckStateRole) + } + if (role != Qt::CheckStateRole) { return false; + } node = indexToNode(index); - if (node == NULL || node == fTree) + if (node == NULL || node == fTree) { return false; + } Qt::CheckState state = static_cast(value.toInt()); - if (state == Qt::Checked) + if (state == Qt::Checked) { node->enable(); - else + } else { node->disable(); + } emit dataChanged(index, index); return true; @@ -231,16 +248,19 @@ Qt::ItemFlags FilterTreeModel::flags(const QModelIndex &index) const const FilterTreeNode *node; Qt::ItemFlags result; - if (!index.isValid()) + if (!index.isValid()) { return Qt::NoItemFlags; + } node = indexToNode(index); - if (node == NULL) + if (node == NULL) { return Qt::NoItemFlags; + } result = Qt::ItemIsEnabled; - if (node == fTree) + if (node == fTree) { return result; + } result |= Qt::ItemIsSelectable; result |= Qt::ItemIsUserCheckable; @@ -252,8 +272,9 @@ QModelIndex FilterTreeModel::nodeIndex(const FilterTreeNode *node, int row, int { FilterTreeNode *child; - if (column > 0 || row >= node->childCount()) + if (column > 0 || row >= node->childCount()) { return QModelIndex(); + } child = node->nodeAt(row); return createIndex(row, column, child); @@ -263,12 +284,14 @@ QModelIndex FilterTreeModel::index(int row, int column, const QModelIndex &paren { const FilterTreeNode *node; - if (!hasIndex(row, column, parent)) + if (!hasIndex(row, column, parent)) { return QModelIndex(); + } node = indexToNode(parent); - if (node == NULL) + if (node == NULL) { return QModelIndex(); + } return nodeIndex(node, row, column); } @@ -279,18 +302,21 @@ QModelIndex FilterTreeModel::parent(const QModelIndex &ind) const FilterTreeNode *parent; QModelIndex idx; - if (!ind.isValid()) + if (!ind.isValid()) { return QModelIndex(); + } node = indexToNode(ind); - if (node == NULL || node == fTree) + if (node == NULL || node == fTree) { return QModelIndex(); + } parent = node->parent(); if (parent) { int row = parent->index(); - if (row < 0) + if (row < 0) { return QModelIndex(); + } idx = createIndex(row, 0, parent); return idx; } @@ -304,18 +330,22 @@ bool FilterTreeModel::removeRows(int row, int count, const QModelIndex &parent) int i, last; last = row + count - 1; - if (!parent.isValid() || count < 1 || row < 0) + if (!parent.isValid() || count < 1 || row < 0) { return false; + } node = indexToNode(parent); - if (node == NULL || last >= node->childCount()) + if (node == NULL || last >= node->childCount()) { return false; + } - for (i = 0; i < count; i++) + for (i = 0; i < count; i++) { node->deleteAt(row); + } - if (node != fTree && node->childCount() < 1) + if (node != fTree && node->childCount() < 1) { return removeRow(parent.row(), parent.parent()); + } return true; } diff --git a/cockatrice/src/game/abstract_game.cpp b/cockatrice/src/game/abstract_game.cpp index 9216f9174..8c777d587 100644 --- a/cockatrice/src/game/abstract_game.cpp +++ b/cockatrice/src/game/abstract_game.cpp @@ -24,10 +24,11 @@ AbstractClient *AbstractGame::getClientForPlayer(int playerId) const } return gameState->getClients().at(playerId); - } else if (gameState->getClients().isEmpty()) + } else if (gameState->getClients().isEmpty()) { return nullptr; - else + } else { return gameState->getClients().first(); + } } void AbstractGame::loadReplay(GameReplay *replay) @@ -44,12 +45,14 @@ void AbstractGame::setActiveCard(CardItem *card) CardItem *AbstractGame::getCard(int playerId, const QString &zoneName, int cardId) const { Player *player = playerManager->getPlayer(playerId); - if (!player) + if (!player) { return nullptr; + } CardZoneLogic *zone = player->getZones().value(zoneName, 0); - if (!zone) + if (!zone) { return nullptr; + } return zone->getCard(cardId); } \ No newline at end of file diff --git a/cockatrice/src/game/board/abstract_card_drag_item.cpp b/cockatrice/src/game/board/abstract_card_drag_item.cpp index 8e3def4ca..026efd60d 100644 --- a/cockatrice/src/game/board/abstract_card_drag_item.cpp +++ b/cockatrice/src/game/board/abstract_card_drag_item.cpp @@ -25,11 +25,12 @@ AbstractCardDragItem::AbstractCardDragItem(AbstractCardItem *_item, setCursor(Qt::ClosedHandCursor); setZValue(ZValues::DRAG_ITEM); } - if (item->getTapped()) + if (item->getTapped()) { setTransform(QTransform() .translate(CardDimensions::WIDTH_HALF_F, CardDimensions::HEIGHT_HALF_F) .rotate(90) .translate(-CardDimensions::WIDTH_HALF_F, -CardDimensions::HEIGHT_HALF_F)); + } setCacheMode(DeviceCoordinateCache); diff --git a/cockatrice/src/game/board/abstract_card_item.cpp b/cockatrice/src/game/board/abstract_card_item.cpp index a519fa4b6..d9458990b 100644 --- a/cockatrice/src/game/board/abstract_card_item.cpp +++ b/cockatrice/src/game/board/abstract_card_item.cpp @@ -88,8 +88,9 @@ void AbstractCardItem::setRealZValue(qreal _zValue) // During hover, zValue is overridden to HOVERED_CARD. Layout operations // like reorganizeCards() call setRealZValue() on all cards including the // hovered one — skip setZValue() here to avoid clobbering the override. - if (!isHovered) + if (!isHovered) { setZValue(_zValue); + } } QSizeF AbstractCardItem::getTranslatedSize(QPainter *painter) const @@ -130,8 +131,9 @@ void AbstractCardItem::paintPicture(QPainter *painter, const QSizeF &translatedS // don't even spend time trying to load the picture if our size is too small if (translatedSize.width() > 10) { CardPictureLoader::getPixmap(translatedPixmap, exactCard, translatedSize.toSize()); - if (translatedPixmap.isNull()) + if (translatedPixmap.isNull()) { paintImage = false; + } } else { paintImage = false; } @@ -156,9 +158,9 @@ void AbstractCardItem::paintPicture(QPainter *painter, const QSizeF &translatedS painter->setBackground(Qt::black); painter->setBackgroundMode(Qt::OpaqueMode); QString nameStr; - if (facedown) + if (facedown) { nameStr = "# " + QString::number(id); - else { + } else { QString prefix = ""; if (SettingsCache::instance().debug().getShowCardId()) { prefix = "#" + QString::number(id) + " "; @@ -185,10 +187,12 @@ void AbstractCardItem::paint(QPainter *painter, const QStyleOptionGraphicsItem * if (isSelected() || isHovered) { QPen pen; - if (isHovered) + if (isHovered) { pen.setColor(Qt::yellow); - if (isSelected()) + } + if (isSelected()) { pen.setColor(Qt::red); + } pen.setWidth(0); // Cosmetic pen painter->setPen(pen); painter->drawPath(shape()); @@ -214,8 +218,9 @@ void AbstractCardItem::setCardRef(const CardRef &_cardRef) void AbstractCardItem::setHovered(bool _hovered) { - if (isHovered == _hovered) + if (isHovered == _hovered) { return; + } if (_hovered) { processHoverEvent(); @@ -277,13 +282,14 @@ void AbstractCardItem::cacheBgColor() void AbstractCardItem::setTapped(bool _tapped, bool canAnimate) { - if (tapped == _tapped) + if (tapped == _tapped) { return; + } tapped = _tapped; - if (SettingsCache::instance().getTapAnimation() && canAnimate) + if (SettingsCache::instance().getTapAnimation() && canAnimate) { static_cast(scene())->registerAnimationItem(this); - else { + } else { tapAngle = tapped ? 90 : 0; setTransform(QTransform() .translate(CardDimensions::WIDTH_HALF_F, CardDimensions::HEIGHT_HALF_F) @@ -309,17 +315,19 @@ void AbstractCardItem::mousePressEvent(QGraphicsSceneMouseEvent *event) scene()->clearSelection(); setSelected(true); } - if (event->button() == Qt::LeftButton) + if (event->button() == Qt::LeftButton) { setCursor(Qt::ClosedHandCursor); - else if (event->button() == Qt::MiddleButton) + } else if (event->button() == Qt::MiddleButton) { emit showCardInfoPopup(event->screenPos(), cardRef); + } event->accept(); } void AbstractCardItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { - if (event->button() == Qt::MiddleButton) + if (event->button() == Qt::MiddleButton) { emit deleteCardInfoPopup(cardRef.name); + } // This function ensures the parent function doesn't mess around with our selection. event->accept(); @@ -335,6 +343,7 @@ QVariant AbstractCardItem::itemChange(QGraphicsItem::GraphicsItemChange change, if (change == ItemSelectedHasChanged) { update(); return value; - } else + } else { return ArrowTarget::itemChange(change, value); + } } diff --git a/cockatrice/src/game/board/abstract_counter.cpp b/cockatrice/src/game/board/abstract_counter.cpp index 08d19ec8a..ef3efb539 100644 --- a/cockatrice/src/game/board/abstract_counter.cpp +++ b/cockatrice/src/game/board/abstract_counter.cpp @@ -43,10 +43,11 @@ AbstractCounter::AbstractCounter(Player *_player, menu->addSeparator(); } else { QAction *aIncrement = new QAction(QString(i < 0 ? "%1" : "+%1").arg(i), this); - if (i == -1) + if (i == -1) { aDec = aIncrement; - else if (i == 1) + } else if (i == 1) { aInc = aIncrement; + } aIncrement->setData(i); connect(aIncrement, &QAction::triggered, this, &AbstractCounter::incrementCounter); menu->addAction(aIncrement); @@ -69,10 +70,11 @@ AbstractCounter::~AbstractCounter() void AbstractCounter::delCounter() { - if (dialogSemaphore) + if (dialogSemaphore) { deleteAfterDialog = true; - else + } else { deleteLater(); + } } void AbstractCounter::retranslateUi() @@ -136,8 +138,9 @@ void AbstractCounter::mousePressEvent(QGraphicsSceneMouseEvent *event) { if (isUnderMouse() && player->getPlayerInfo()->getLocalOrJudge()) { if (event->button() == Qt::MiddleButton || (QApplication::keyboardModifiers() & Qt::ShiftModifier)) { - if (menu) + if (menu) { menu->exec(event->screenPos()); + } event->accept(); } else if (event->button() == Qt::LeftButton) { Command_IncCounter cmd; @@ -152,8 +155,9 @@ void AbstractCounter::mousePressEvent(QGraphicsSceneMouseEvent *event) player->getPlayerActions()->sendGameCommand(cmd); event->accept(); } - } else + } else { event->ignore(); + } } void AbstractCounter::hoverEnterEvent(QGraphicsSceneHoverEvent * /*event*/) @@ -189,8 +193,9 @@ void AbstractCounter::setCounter() } dialogSemaphore = false; - if (!ok) + if (!ok) { return; + } Expression exp(value); int newValue = static_cast(exp.parse(dialog.textValue())); @@ -231,8 +236,9 @@ void AbstractCounterDialog::changeValue(int diff) { bool ok; int curValue = textValue().toInt(&ok); - if (!ok) + if (!ok) { return; + } curValue += diff; setTextValue(QString::number(curValue)); } diff --git a/cockatrice/src/game/board/arrow_item.cpp b/cockatrice/src/game/board/arrow_item.cpp index 60585a774..53d8ea33e 100644 --- a/cockatrice/src/game/board/arrow_item.cpp +++ b/cockatrice/src/game/board/arrow_item.cpp @@ -27,13 +27,16 @@ ArrowItem::ArrowItem(Player *_player, int _id, ArrowTarget *_startItem, ArrowTar { setZValue(ZValues::ARROWS); - if (startItem) + if (startItem) { startItem->addArrowFrom(this); - if (targetItem) + } + if (targetItem) { targetItem->addArrowTo(this); + } - if (startItem && targetItem) + if (startItem && targetItem) { updatePath(); + } } ArrowItem::~ArrowItem() @@ -59,8 +62,9 @@ void ArrowItem::delArrow() void ArrowItem::updatePath() { - if (!targetItem) + if (!targetItem) { return; + } QPointF endPoint = targetItem->mapToScene( QPointF(targetItem->boundingRect().width() / 2, targetItem->boundingRect().height() / 2)); @@ -75,8 +79,9 @@ void ArrowItem::updatePath(const QPointF &endPoint) headWidth / qPow(2, 0.5); // aka headWidth / sqrt (2) but this produces a compile error with MSVC++ const double phi = 15; - if (!startItem) + if (!startItem) { return; + } QPointF startPoint = startItem->mapToScene(QPointF(startItem->boundingRect().width() / 2, startItem->boundingRect().height() / 2)); @@ -84,9 +89,9 @@ void ArrowItem::updatePath(const QPointF &endPoint) qreal lineLength = line.length(); prepareGeometryChange(); - if (lineLength < 30) + if (lineLength < 30) { path = QPainterPath(); - else { + } else { QPointF c(lineLength / 2, qTan(phi * M_PI / 180) * lineLength); QPainterPath centerLine; @@ -123,10 +128,11 @@ void ArrowItem::updatePath(const QPointF &endPoint) void ArrowItem::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*option*/, QWidget * /*widget*/) { QColor paintColor(color); - if (fullColor) + if (fullColor) { paintColor.setAlpha(200); - else + } else { paintColor.setAlpha(150); + } painter->setBrush(paintColor); painter->drawPath(path); } @@ -168,8 +174,9 @@ void ArrowDragItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { // This ensures that if a mouse move event happens after a call to delArrow(), // the event will be discarded as it would create some stray pointers. - if (targetLocked || !startItem) + if (targetLocked || !startItem) { return; + } QPointF endPos = event->scenePos(); @@ -213,8 +220,9 @@ void ArrowDragItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) void ArrowDragItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { - if (!startItem) + if (!startItem) { return; + } if (targetItem && (targetItem != startItem)) { CardZoneLogic *startZone = static_cast(startItem)->getZone(); @@ -246,10 +254,11 @@ void ArrowDragItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) bool playToStack = SettingsCache::instance().getPlayToStack(); if (ci && ((!playToStack && ci->getUiAttributes().tableRow == 3) || (playToStack && ci->getUiAttributes().tableRow != 0 && - startCard->getZone()->getName() != ZoneNames::STACK))) + startCard->getZone()->getName() != ZoneNames::STACK))) { cmd.set_start_zone(ZoneNames::STACK); - else + } else { cmd.set_start_zone(playToStack ? ZoneNames::STACK : ZoneNames::TABLE); + } } if (deleteInPhase != 0) { @@ -277,8 +286,9 @@ void ArrowAttachItem::addChildArrow(ArrowAttachItem *childArrow) void ArrowAttachItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { - if (targetLocked || !startItem) + if (targetLocked || !startItem) { return; + } QPointF endPos = event->scenePos(); @@ -343,8 +353,9 @@ void ArrowAttachItem::attachCards(CardItem *startCard, const CardItem *targetCar void ArrowAttachItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { - if (!startItem) + if (!startItem) { return; + } // Attaching could move startItem under the current cursor position, causing all children to retarget to it right // before they are processed. Prevent that. diff --git a/cockatrice/src/game/board/arrow_target.cpp b/cockatrice/src/game/board/arrow_target.cpp index 2dbd913fa..2c7cdfec8 100644 --- a/cockatrice/src/game/board/arrow_target.cpp +++ b/cockatrice/src/game/board/arrow_target.cpp @@ -30,11 +30,13 @@ void ArrowTarget::setBeingPointedAt(bool _beingPointedAt) QVariant ArrowTarget::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) { if (change == ItemScenePositionHasChanged && scene()) { - for (auto *arrow : arrowsFrom) + for (auto *arrow : arrowsFrom) { arrow->updatePath(); + } - for (auto *arrow : arrowsTo) + for (auto *arrow : arrowsTo) { arrow->updatePath(); + } } return QGraphicsItem::itemChange(change, value); diff --git a/cockatrice/src/game/board/card_drag_item.cpp b/cockatrice/src/game/board/card_drag_item.cpp index 5ae56ccba..49467c5c9 100644 --- a/cockatrice/src/game/board/card_drag_item.cpp +++ b/cockatrice/src/game/board/card_drag_item.cpp @@ -24,8 +24,9 @@ void CardDragItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *opti { AbstractCardDragItem::paint(painter, option, widget); - if (occupied) + if (occupied) { painter->fillPath(shape(), QColor(200, 0, 0, 100)); + } } void CardDragItem::updatePosition(const QPointF &cursorScenePos) @@ -38,16 +39,19 @@ void CardDragItem::updatePosition(const QPointF &cursorScenePos) ZoneViewZone *zoneViewZone = 0; for (int i = colliding.size() - 1; i >= 0; i--) { CardZone *temp = qgraphicsitem_cast(colliding.at(i)); - if (!cardZone) + if (!cardZone) { cardZone = temp; - if (!zoneViewZone) + } + if (!zoneViewZone) { zoneViewZone = qobject_cast(temp); + } } CardZone *cursorZone = 0; - if (zoneViewZone) + if (zoneViewZone) { cursorZone = zoneViewZone; - else if (cardZone) + } else if (cardZone) { cursorZone = cardZone; + } // Always update the current zone, even if its null, to cancel the drag // instead of dropping cards into an non-intuitive location. @@ -59,8 +63,9 @@ void CardDragItem::updatePosition(const QPointF &cursorScenePos) QPointF newPos = cursorScenePos - hotSpot; if (newPos != pos()) { - for (int i = 0; i < childDrags.size(); i++) + for (int i = 0; i < childDrags.size(); i++) { childDrags[i]->setPos(newPos + childDrags[i]->getHotSpot()); + } setPos(newPos); } @@ -78,23 +83,27 @@ void CardDragItem::updatePosition(const QPointF &cursorScenePos) // position. TableZone *tableZone = qobject_cast(cursorZone); QPointF closestGridPoint; - if (tableZone) + if (tableZone) { closestGridPoint = tableZone->closestGridPoint(cursorPosInZone); - else + } else { closestGridPoint = cursorPosInZone - hotSpot; + } QPointF newPos = zonePos + closestGridPoint; if (newPos != pos()) { - for (int i = 0; i < childDrags.size(); i++) + for (int i = 0; i < childDrags.size(); i++) { childDrags[i]->setPos(newPos + childDrags[i]->getHotSpot()); + } setPos(newPos); bool newOccupied = false; TableZone *table = qobject_cast(cursorZone); - if (table) - if (table->getCardFromCoords(closestGridPoint)) + if (table) { + if (table->getCardFromCoords(closestGridPoint)) { newOccupied = true; + } + } if (newOccupied != occupied) { occupied = newOccupied; update(); diff --git a/cockatrice/src/game/board/card_item.cpp b/cockatrice/src/game/board/card_item.cpp index 072c1a231..695e94a3a 100644 --- a/cockatrice/src/game/board/card_item.cpp +++ b/cockatrice/src/game/board/card_item.cpp @@ -27,8 +27,9 @@ CardItem::CardItem(Player *_owner, QGraphicsItem *parent, const CardRef &cardRef owner->addCard(this); connect(&SettingsCache::instance().cardCounters(), &CardCounterSettings::colorChanged, this, [this](int counterId) { - if (counters.contains(counterId)) + if (counters.contains(counterId)) { update(); + } }); } @@ -56,8 +57,9 @@ void CardItem::prepareDelete() void CardItem::deleteLater() { prepareDelete(); - if (scene()) + if (scene()) { static_cast(scene())->unregisterAnimationItem(this); + } AbstractCardItem::deleteLater(); } @@ -152,10 +154,11 @@ void CardItem::setAttacking(bool _attacking) void CardItem::setCounter(int _id, int _value) { - if (_value) + if (_value) { counters.insert(_id, _value); - else + } else { counters.remove(_id); + } update(); } @@ -227,8 +230,9 @@ void CardItem::resetState(bool keepAnnotations) attachedCards.clear(); setTapped(false, false); setDoesntUntap(false); - if (scene()) + if (scene()) { static_cast(scene())->unregisterAnimationItem(this); + } update(); } @@ -275,8 +279,9 @@ void CardItem::deleteDragItem() void CardItem::drawArrow(const QColor &arrowColor) { - if (owner->getGame()->getPlayerManager()->isSpectator()) + if (owner->getGame()->getPlayerManager()->isSpectator()) { return; + } auto *game = owner->getGame(); Player *arrowOwner = game->getPlayerManager()->getActiveLocalPlayer(game->getGameState()->getActivePlayer()); @@ -291,10 +296,12 @@ void CardItem::drawArrow(const QColor &arrowColor) for (const auto &item : scene()->selectedItems()) { CardItem *card = qgraphicsitem_cast(item); - if (card == nullptr || card == this) + if (card == nullptr || card == this) { continue; - if (card->getZone() != zone) + } + if (card->getZone() != zone) { continue; + } ArrowDragItem *childArrow = new ArrowDragItem(arrowOwner, card, arrowColor, phase); scene()->addItem(childArrow); @@ -304,8 +311,9 @@ void CardItem::drawArrow(const QColor &arrowColor) void CardItem::drawAttachArrow() { - if (owner->getGame()->getPlayerManager()->isSpectator()) + if (owner->getGame()->getPlayerManager()->isSpectator()) { return; + } auto *arrow = new ArrowAttachItem(this); scene()->addItem(arrow); @@ -313,10 +321,12 @@ void CardItem::drawAttachArrow() for (const auto &item : scene()->selectedItems()) { CardItem *card = qgraphicsitem_cast(item); - if (card == nullptr) + if (card == nullptr) { continue; - if (card->getZone() != zone) + } + if (card->getZone() != zone) { continue; + } ArrowAttachItem *childArrow = new ArrowAttachItem(card); scene()->addItem(childArrow); @@ -328,27 +338,32 @@ void CardItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { if (event->buttons().testFlag(Qt::RightButton)) { if ((event->screenPos() - event->buttonDownScreenPos(Qt::RightButton)).manhattanLength() < - 2 * QApplication::startDragDistance()) + 2 * QApplication::startDragDistance()) { return; + } QColor arrowColor = Qt::red; - if (event->modifiers().testFlag(Qt::ControlModifier)) + if (event->modifiers().testFlag(Qt::ControlModifier)) { arrowColor = Qt::yellow; - else if (event->modifiers().testFlag(Qt::AltModifier)) + } else if (event->modifiers().testFlag(Qt::AltModifier)) { arrowColor = Qt::blue; - else if (event->modifiers().testFlag(Qt::ShiftModifier)) + } else if (event->modifiers().testFlag(Qt::ShiftModifier)) { arrowColor = Qt::green; + } drawArrow(arrowColor); } else if (event->buttons().testFlag(Qt::LeftButton)) { if ((event->screenPos() - event->buttonDownScreenPos(Qt::LeftButton)).manhattanLength() < - 2 * QApplication::startDragDistance()) + 2 * QApplication::startDragDistance()) { return; + } if (const ZoneViewZoneLogic *view = qobject_cast(zone)) { - if (view->getRevealZone() && !view->getWriteableRevealZone()) + if (view->getRevealZone() && !view->getWriteableRevealZone()) { return; - } else if (!owner->getPlayerInfo()->getLocalOrJudge()) + } + } else if (!owner->getPlayerInfo()->getLocalOrJudge()) { return; + } bool forceFaceDown = event->modifiers().testFlag(Qt::ShiftModifier); @@ -360,14 +375,16 @@ void CardItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) int childIndex = 0; for (const auto &item : scene()->selectedItems()) { CardItem *card = static_cast(item); - if ((card == this) || (card->getZone() != zone)) + if ((card == this) || (card->getZone() != zone)) { continue; + } ++childIndex; QPointF childPos; - if (zone->getHasCardAttr()) + if (zone->getHasCardAttr()) { childPos = card->pos() - pos(); - else + } else { childPos = QPointF(childIndex * CardDimensions::WIDTH_HALF_F, 0); + } CardDragItem *drag = new CardDragItem(card, card->getId(), childPos, card->getFaceDown() || forceFaceDown, dragItem); drag->setPos(dragItem->pos() + childPos); @@ -380,13 +397,14 @@ void CardItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) void CardItem::playCard(bool faceDown) { // Do nothing if the card belongs to another player - if (!owner->getPlayerInfo()->getLocalOrJudge()) + if (!owner->getPlayerInfo()->getLocalOrJudge()) { return; + } TableZoneLogic *tz = qobject_cast(zone); - if (tz) + if (tz) { emit tz->toggleTapped(); - else { + } else { if (SettingsCache::instance().getClickPlaysAllSelected()) { faceDown ? zone->getPlayer()->getPlayerActions()->actPlayFacedown() : zone->getPlayer()->getPlayerActions()->actPlay(); @@ -493,8 +511,9 @@ bool CardItem::animationEvent() { int rotation = ROTATION_DEGREES_PER_FRAME; bool animationIncomplete = true; - if (!tapped) + if (!tapped) { rotation *= -1; + } tapAngle += rotation; if (tapped && (tapAngle > 90)) { diff --git a/cockatrice/src/game/deckview/deck_view.cpp b/cockatrice/src/game/deckview/deck_view.cpp index 620dfaa5f..ced02c8db 100644 --- a/cockatrice/src/game/deckview/deck_view.cpp +++ b/cockatrice/src/game/deckview/deck_view.cpp @@ -24,17 +24,21 @@ void DeckViewCardDragItem::updatePosition(const QPointF &cursorScenePos) QList colliding = scene()->items(cursorScenePos); DeckViewCardContainer *cursorZone = 0; - for (int i = colliding.size() - 1; i >= 0; i--) - if ((cursorZone = qgraphicsitem_cast(colliding.at(i)))) + for (int i = colliding.size() - 1; i >= 0; i--) { + if ((cursorZone = qgraphicsitem_cast(colliding.at(i)))) { break; - if (!cursorZone) + } + } + if (!cursorZone) { return; + } currentZone = cursorZone; QPointF newPos = cursorScenePos; if (newPos != pos()) { - for (int i = 0; i < childDrags.size(); i++) + for (int i = 0; i < childDrags.size(); i++) { childDrags[i]->setPos(newPos + childDrags[i]->getHotSpot()); + } setPos(newPos); } } @@ -104,11 +108,13 @@ void DeckViewCard::paint(QPainter *painter, const QStyleOptionGraphicsItem *opti void DeckViewCard::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { if ((event->screenPos() - event->buttonDownScreenPos(Qt::LeftButton)).manhattanLength() < - 2 * QApplication::startDragDistance()) + 2 * QApplication::startDragDistance()) { return; + } - if (static_cast(scene())->getLocked()) + if (static_cast(scene())->getLocked()) { return; + } delete dragItem; dragItem = new DeckViewCardDragItem(this, event->pos()); @@ -120,8 +126,9 @@ void DeckViewCard::mouseMoveEvent(QGraphicsSceneMouseEvent *event) int j = 0; for (int i = 0; i < sel.size(); i++) { auto *c = static_cast(sel.at(i)); - if (c == this) + if (c == this) { continue; + } ++j; auto childPos = QPointF(j * CardDimensions::WIDTH_HALF_F, 0); auto *drag = new DeckViewCardDragItem(c, childPos, dragItem); @@ -133,8 +140,9 @@ void DeckViewCard::mouseMoveEvent(QGraphicsSceneMouseEvent *event) void DeckView::mouseDoubleClickEvent(QMouseEvent *event) { - if (static_cast(scene())->getLocked()) + if (static_cast(scene())->getLocked()) { return; + } if (event->button() == Qt::LeftButton) { QList result; @@ -147,12 +155,13 @@ void DeckView::mouseDoubleClickEvent(QMouseEvent *event) m.set_card_name(c->getName().toStdString()); m.set_start_zone(zone->getName().toStdString()); - if (zone->getName() == DECK_ZONE_MAIN) + if (zone->getName() == DECK_ZONE_MAIN) { m.set_target_zone(DECK_ZONE_SIDE); - else if (zone->getName() == DECK_ZONE_SIDE) + } else if (zone->getName() == DECK_ZONE_SIDE) { m.set_target_zone(DECK_ZONE_MAIN); - else // Trying to move from another zone + } else { // Trying to move from another zone m.set_target_zone(zone->getName().toStdString()); + } result.append(m); } @@ -232,8 +241,9 @@ QList> DeckViewCardContainer::getRowsAndCols() const { QList> result; QList cardTypeList = cardsByType.uniqueKeys(); - for (int i = 0; i < cardTypeList.size(); ++i) + for (int i = 0; i < cardTypeList.size(); ++i) { result.append(QPair(1, cardsByType.count(cardTypeList[i]))); + } return result; } @@ -262,8 +272,9 @@ QSizeF DeckViewCardContainer::calculateBoundingRect(const QList> // Calculate space needed for cards for (int i = 0; i < rowsAndCols.size(); ++i) { totalHeight += CardDimensions::HEIGHT_F * rowsAndCols[i].first + paddingY; - if (CardDimensions::WIDTH_F * rowsAndCols[i].second > totalWidth) + if (CardDimensions::WIDTH_F * rowsAndCols[i].second > totalWidth) { totalWidth = CardDimensions::WIDTH_F * rowsAndCols[i].second; + } } return QSizeF(getCardTypeTextWidth() + totalWidth, totalHeight + separatorY + paddingY); @@ -271,8 +282,9 @@ QSizeF DeckViewCardContainer::calculateBoundingRect(const QList> bool DeckViewCardContainer::sortCardsByName(DeckViewCard *c1, DeckViewCard *c2) { - if (c1 && c2) + if (c1 && c2) { return c1->getName() < c2->getName(); + } return false; } @@ -322,15 +334,17 @@ DeckViewScene::~DeckViewScene() void DeckViewScene::clearContents() { QMapIterator i(cardContainers); - while (i.hasNext()) + while (i.hasNext()) { delete i.next().value(); + } cardContainers.clear(); } void DeckViewScene::setDeck(const DeckList &_deck) { - if (deck) + if (deck) { delete deck; + } deck = new DeckList(_deck.writeToString_Native()); rebuildTree(); @@ -342,8 +356,9 @@ void DeckViewScene::rebuildTree() { clearContents(); - if (!deck) + if (!deck) { return; + } for (auto *currentZone : deck->getZoneNodes()) { DeckViewCardContainer *container = cardContainers.value(currentZone->getName(), 0); @@ -355,8 +370,9 @@ void DeckViewScene::rebuildTree() for (int j = 0; j < currentZone->size(); j++) { auto *currentCard = dynamic_cast(currentZone->at(j)); - if (!currentCard) + if (!currentCard) { continue; + } for (int k = 0; k < currentCard->getNumber(); ++k) { auto *newCard = new DeckViewCard(container, currentCard->toCardRef(), currentZone->getName()); @@ -373,18 +389,21 @@ void DeckViewScene::applySideboardPlan(const QList &plan) const MoveCard_ToZone &m = plan[i]; DeckViewCardContainer *start = cardContainers.value(QString::fromStdString(m.start_zone())); DeckViewCardContainer *target = cardContainers.value(QString::fromStdString(m.target_zone())); - if (!start || !target) + if (!start || !target) { continue; + } DeckViewCard *card = 0; const QList &cardList = start->getCards(); - for (int j = 0; j < cardList.size(); ++j) + for (int j = 0; j < cardList.size(); ++j) { if (cardList[j]->getName() == QString::fromStdString(m.card_name())) { card = cardList[j]; break; } - if (!card) + } + if (!card) { continue; + } start->removeCard(card); target->addCard(card); @@ -405,8 +424,9 @@ void DeckViewScene::rearrangeItems() rowsAndColsList.append(rowsAndCols); cardCountList.append(QList()); - for (int j = 0; j < rowsAndCols.size(); ++j) + for (int j = 0; j < rowsAndCols.size(); ++j) { cardCountList[i].append(rowsAndCols[j].second); + } } qreal totalHeight, totalWidth; @@ -417,23 +437,27 @@ void DeckViewScene::rearrangeItems() for (int i = 0; i < contList.size(); ++i) { QSizeF contSize = contList[i]->calculateBoundingRect(rowsAndColsList[i]); totalHeight += contSize.height() + spacing; - if (contSize.width() > totalWidth) + if (contSize.width() > totalWidth) { totalWidth = contSize.width(); + } } // We're done when the aspect ratio shifts from too high to too low. - if (totalWidth / totalHeight <= optimalAspectRatio) + if (totalWidth / totalHeight <= optimalAspectRatio) { break; + } // Find category with highest column count int maxIndex1 = -1, maxIndex2 = -1, maxCols = 0; - for (int i = 0; i < rowsAndColsList.size(); ++i) - for (int j = 0; j < rowsAndColsList[i].size(); ++j) + for (int i = 0; i < rowsAndColsList.size(); ++i) { + for (int j = 0; j < rowsAndColsList[i].size(); ++j) { if (rowsAndColsList[i][j].second > maxCols) { maxIndex1 = i; maxIndex2 = j; maxCols = rowsAndColsList[i][j].second; } + } + } // Add row to category const int maxRows = rowsAndColsList[maxIndex1][maxIndex2].first; @@ -451,8 +475,9 @@ void DeckViewScene::rearrangeItems() } totalWidth = totalHeight * optimalAspectRatio; - for (int i = 0; i < contList.size(); ++i) + for (int i = 0; i < contList.size(); ++i) { contList[i]->setWidth(totalWidth); + } setSceneRect(QRectF(0, 0, totalWidth, totalHeight)); } @@ -470,7 +495,7 @@ QList DeckViewScene::getSideboardPlan() const while (containerIterator.hasNext()) { DeckViewCardContainer *cont = containerIterator.next().value(); const QList cardList = cont->getCards(); - for (int i = 0; i < cardList.size(); ++i) + for (int i = 0; i < cardList.size(); ++i) { if (cardList[i]->getOriginZone() != cont->getName()) { MoveCard_ToZone m; m.set_card_name(cardList[i]->getName().toStdString()); @@ -478,6 +503,7 @@ QList DeckViewScene::getSideboardPlan() const m.set_target_zone(cont->getName().toStdString()); result.append(m); } + } } return result; } diff --git a/cockatrice/src/game/deckview/deck_view_container.cpp b/cockatrice/src/game/deckview/deck_view_container.cpp index 44b2be6d1..cbd6c2bad 100644 --- a/cockatrice/src/game/deckview/deck_view_container.cpp +++ b/cockatrice/src/game/deckview/deck_view_container.cpp @@ -251,8 +251,9 @@ void DeckViewContainer::unloadDeck() void DeckViewContainer::loadLocalDeck() { DlgLoadDeck dialog(this); - if (!dialog.exec()) + if (!dialog.exec()) { return; + } loadDeckFromFile(dialog.selectedFiles().at(0)); } @@ -364,8 +365,9 @@ void DeckViewContainer::sideboardPlanChanged() { Command_SetSideboardPlan cmd; const QList &newPlan = deckView->getSideboardPlan(); - for (const auto &i : newPlan) + for (const auto &i : newPlan) { cmd.add_move_list()->CopyFrom(i); + } parentGame->getGame()->getGameEventHandler()->sendGameCommand(cmd, playerId); } @@ -404,8 +406,9 @@ void DeckViewContainer::setSideboardLocked(bool locked) { sideboardLockButton->setState(!locked); deckView->setLocked(readyStartButton->getState() || !sideboardLockButton->getState()); - if (locked) + if (locked) { deckView->resetSideboardPlan(); + } } void DeckViewContainer::setDeck(const DeckList &deck) diff --git a/cockatrice/src/game/dialogs/dlg_create_token.cpp b/cockatrice/src/game/dialogs/dlg_create_token.cpp index df264f065..11c24b72e 100644 --- a/cockatrice/src/game/dialogs/dlg_create_token.cpp +++ b/cockatrice/src/game/dialogs/dlg_create_token.cpp @@ -101,8 +101,9 @@ DlgCreateToken::DlgCreateToken(const QStringList &_predefinedTokens, QWidget *pa chooseTokenView->resizeColumnToContents(0); chooseTokenView->setWordWrap(true); - if (!deckHeaderState.isNull()) + if (!deckHeaderState.isNull()) { chooseTokenView->header()->restoreState(deckHeaderState); + } chooseTokenView->header()->setStretchLastSection(false); chooseTokenView->header()->hideSection(1); // Sets @@ -185,8 +186,9 @@ void DlgCreateToken::tokenSelectionChanged(const QModelIndex ¤t, const QMo const QChar cardColor = cardInfo->getColorChar(); colorEdit->setCurrentIndex(colorEdit->findData(cardColor, Qt::UserRole, Qt::MatchFixedString)); ptEdit->setText(cardInfo->getPowTough()); - if (SettingsCache::instance().getAnnotateTokens()) + if (SettingsCache::instance().getAnnotateTokens()) { annotationEdit->setText(cardInfo->getText()); + } } else { nameEdit->setText(""); colorEdit->setCurrentIndex(colorEdit->findData(QString(), Qt::UserRole, Qt::MatchFixedString)); diff --git a/cockatrice/src/game/game_event_handler.cpp b/cockatrice/src/game/game_event_handler.cpp index 42dd49458..82fa2b911 100644 --- a/cockatrice/src/game/game_event_handler.cpp +++ b/cockatrice/src/game/game_event_handler.cpp @@ -36,8 +36,9 @@ GameEventHandler::GameEventHandler(AbstractGame *_game) : QObject(_game), game(_ void GameEventHandler::sendGameCommand(PendingCommand *pend, int playerId) { AbstractClient *client = game->getClientForPlayer(playerId); - if (!client) + if (!client) { return; + } connect(pend, &PendingCommand::finished, this, &GameEventHandler::commandFinished); client->sendCommand(pend); @@ -46,8 +47,9 @@ void GameEventHandler::sendGameCommand(PendingCommand *pend, int playerId) void GameEventHandler::sendGameCommand(const google::protobuf::Message &command, int playerId) { AbstractClient *client = game->getClientForPlayer(playerId); - if (!client) + if (!client) { return; + } PendingCommand *pend = prepareGameCommand(command); connect(pend, &PendingCommand::finished, this, &GameEventHandler::commandFinished); @@ -56,8 +58,9 @@ void GameEventHandler::sendGameCommand(const google::protobuf::Message &command, void GameEventHandler::commandFinished(const Response &response) { - if (response.response_code() == Response::RespChatFlood) + if (response.response_code() == Response::RespChatFlood) { emit gameFlooded(); + } } PendingCommand *GameEventHandler::prepareGameCommand(const ::google::protobuf::Message &cmd) @@ -117,9 +120,11 @@ void GameEventHandler::processGameEventContainer(const GameEventContainer &cont, break; } } else { - if ((game->getGameState()->getClients().size() > 1) && (playerId != -1)) - if (game->getGameState()->getClients().at(playerId) != client) + if ((game->getGameState()->getClients().size() > 1) && (playerId != -1)) { + if (game->getGameState()->getClients().at(playerId) != client) { continue; + } + } switch (eventType) { case GameEvent::GAME_STATE_CHANGED: @@ -284,8 +289,9 @@ void GameEventHandler::eventGameStateChanged(const Event_GameStateChanged &event if (event.game_started() && !game->getGameMetaInfo()->started()) { game->getGameState()->setResuming(!game->getGameState()->isGameStateKnown()); game->getGameMetaInfo()->setStarted(event.game_started()); - if (game->getGameState()->isGameStateKnown()) + if (game->getGameState()->isGameStateKnown()) { emit logGameStart(); + } game->getGameState()->setActivePlayer(event.active_player_id()); game->getGameState()->setCurrentPhase(event.active_phase()); } else if (!event.game_started() && game->getGameMetaInfo()->started()) { @@ -305,8 +311,9 @@ void GameEventHandler::processCardAttachmentsForPlayers(const Event_GameStateCha const ServerInfo_PlayerProperties &prop = playerInfo.properties(); if (!prop.spectator()) { Player *player = game->getPlayerManager()->getPlayers().value(prop.player_id(), 0); - if (!player) + if (!player) { continue; + } player->processCardAttachment(playerInfo); } } @@ -317,8 +324,9 @@ void GameEventHandler::eventPlayerPropertiesChanged(const Event_PlayerProperties const GameEventContext &context) { Player *player = game->getPlayerManager()->getPlayers().value(eventPlayerId, 0); - if (!player) + if (!player) { return; + } const ServerInfo_PlayerProperties &prop = event.player_properties(); emit playerPropertiesChanged(prop, eventPlayerId); @@ -326,8 +334,9 @@ void GameEventHandler::eventPlayerPropertiesChanged(const Event_PlayerProperties switch (contextType) { case GameEventContext::READY_START: { bool ready = prop.ready_start(); - if (player->getPlayerInfo()->getLocal()) + if (player->getPlayerInfo()->getLocal()) { emit localPlayerReadyStateChanged(player->getPlayerInfo()->getId(), ready); + } if (ready) { emit logReadyStart(player); } else { @@ -339,8 +348,9 @@ void GameEventHandler::eventPlayerPropertiesChanged(const Event_PlayerProperties player->setConceded(true); QMapIterator playerIterator(game->getPlayerManager()->getPlayers()); - while (playerIterator.hasNext()) + while (playerIterator.hasNext()) { playerIterator.next().value()->updateZones(); + } emit logConcede(eventPlayerId); @@ -350,8 +360,9 @@ void GameEventHandler::eventPlayerPropertiesChanged(const Event_PlayerProperties player->setConceded(false); QMapIterator playerIterator(game->getPlayerManager()->getPlayers()); - while (playerIterator.hasNext()) + while (playerIterator.hasNext()) { playerIterator.next().value()->updateZones(); + } emit logUnconcede(eventPlayerId); @@ -389,8 +400,9 @@ void GameEventHandler::eventJoin(const Event_Join &event, int /*eventPlayerId*/, QString playerName = QString::fromStdString(playerInfo.user_info().name()); emit addPlayerToAutoCompleteList(playerName); - if (game->getPlayerManager()->getPlayers().contains(playerId)) + if (game->getPlayerManager()->getPlayers().contains(playerId)) { return; + } if (playerInfo.spectator()) { game->getPlayerManager()->addSpectator(playerId, playerInfo); @@ -426,8 +438,9 @@ QString GameEventHandler::getLeaveReason(Event_Leave::LeaveReason reason) void GameEventHandler::eventLeave(const Event_Leave &event, int eventPlayerId, const GameEventContext & /*context*/) { Player *player = game->getPlayerManager()->getPlayers().value(eventPlayerId, 0); - if (!player) + if (!player) { return; + } player->clear(); emit playerLeft(eventPlayerId); @@ -440,8 +453,9 @@ void GameEventHandler::eventLeave(const Event_Leave &event, int eventPlayerId, c // Rearrange all remaining zones so that attachment relationship updates take place QMapIterator playerIterator(game->getPlayerManager()->getPlayers()); - while (playerIterator.hasNext()) + while (playerIterator.hasNext()) { playerIterator.next().value()->updateZones(); + } emitUserEvent(); } @@ -461,8 +475,9 @@ void GameEventHandler::eventReverseTurn(const Event_ReverseTurn &event, const GameEventContext & /*context*/) { Player *player = game->getPlayerManager()->getPlayers().value(eventPlayerId, 0); - if (!player) + if (!player) { return; + } emit logTurnReversed(player, event.reversed()); } @@ -491,8 +506,9 @@ void GameEventHandler::eventSetActivePlayer(const Event_SetActivePlayer &event, { game->getGameState()->setActivePlayer(event.active_player_id()); Player *player = game->getPlayerManager()->getPlayer(event.active_player_id()); - if (!player) + if (!player) { return; + } emit logActivePlayer(player); emitUserEvent(); } diff --git a/cockatrice/src/game/game_meta_info.h b/cockatrice/src/game/game_meta_info.h index b5f5bfe4f..8226af2ae 100644 --- a/cockatrice/src/game/game_meta_info.h +++ b/cockatrice/src/game/game_meta_info.h @@ -87,15 +87,17 @@ public: public slots: void setStarted(bool s) { - if (gameInfo_.started() == s) + if (gameInfo_.started() == s) { return; + } gameInfo_.set_started(s); emit startedChanged(s); } void setSpectatorsOmniscient(bool v) { - if (gameInfo_.spectators_omniscient() == v) + if (gameInfo_.spectators_omniscient() == v) { return; + } gameInfo_.set_spectators_omniscient(v); emit spectatorsOmniscienceChanged(v); } diff --git a/cockatrice/src/game/game_scene.cpp b/cockatrice/src/game/game_scene.cpp index aa6f1e6f1..9141a9d54 100644 --- a/cockatrice/src/game/game_scene.cpp +++ b/cockatrice/src/game/game_scene.cpp @@ -55,8 +55,9 @@ GameScene::~GameScene() */ void GameScene::retranslateUi() { - for (ZoneViewWidget *view : zoneViews) + for (ZoneViewWidget *view : zoneViews) { view->retranslateUi(); + } } QList GameScene::selectedCards() const @@ -209,10 +210,12 @@ QList GameScene::rotatePlayers(const QList &activePlayers, i QList rotated = activePlayers; if (!rotated.isEmpty()) { int totalRotation = firstPlayerIndex + playerRotation; - while (totalRotation < 0) + while (totalRotation < 0) { totalRotation += rotated.size(); - for (int i = 0; i < totalRotation; ++i) + } + for (int i = 0; i < totalRotation; ++i) { rotated.append(rotated.takeFirst()); + } } return rotated; } @@ -252,10 +255,11 @@ QSizeF GameScene::computeSceneSizeAndPlayerLayout(const QList &players for (int j = 0; j < rowsInColumn; ++j) { Player *player = playersIter.next(); - if (col == 0) + if (col == 0) { playersByColumn[col].prepend(player->getGraphicsItem()); - else + } else { playersByColumn[col].append(player->getGraphicsItem()); + } auto *pgItem = player->getGraphicsItem(); thisColumnHeight += pgItem->boundingRect().height() + playerAreaSpacing; @@ -294,8 +298,9 @@ QList GameScene::calculateMinWidthByColumn() const QList minWidthByColumn; for (const auto &col : playersByColumn) { qreal maxWidth = 0; - for (PlayerGraphicsItem *player : col) + for (PlayerGraphicsItem *player : col) { maxWidth = std::max(maxWidth, player->getMinimumWidth()); + } minWidthByColumn.append(maxWidth); } return minWidthByColumn; @@ -356,32 +361,38 @@ void GameScene::updateHover(const QPointF &scenePos) void GameScene::updateHoveredCard(CardItem *newCard) { - if (hoveredCard && (newCard != hoveredCard)) + if (hoveredCard && (newCard != hoveredCard)) { endCardHover(hoveredCard); - if (newCard && (newCard != hoveredCard)) + } + if (newCard && (newCard != hoveredCard)) { beginCardHover(newCard); + } hoveredCard = newCard; } void GameScene::beginCardHover(CardItem *card) { card->setHovered(true); - if (auto *zone = SelectZone::findOwningSelectZone(card)) + if (auto *zone = SelectZone::findOwningSelectZone(card)) { zone->escapeClipForHover(card); + } } void GameScene::endCardHover(CardItem *card) { - if (auto *zone = SelectZone::findOwningSelectZone(card)) + if (auto *zone = SelectZone::findOwningSelectZone(card)) { zone->restoreClipAfterHover(card); + } card->setHovered(false); } CardZone *GameScene::findTopmostZone(const QList &items) { - for (QGraphicsItem *item : items) - if (auto *zone = qgraphicsitem_cast(item)) + for (QGraphicsItem *item : items) { + if (auto *zone = qgraphicsitem_cast(item)) { return zone; + } + } return nullptr; } @@ -392,14 +403,17 @@ CardItem *GameScene::findTopmostCardInZone(const QList &items, for (QGraphicsItem *item : items) { CardItem *card = qgraphicsitem_cast(item); - if (!card) + if (!card) { continue; + } if (card->getAttachedTo()) { - if (card->getAttachedTo()->getZone() != zone->getLogic()) + if (card->getAttachedTo()->getZone() != zone->getLogic()) { continue; - } else if (card->getZone() != zone->getLogic()) + } + } else if (card->getZone() != zone->getLogic()) { continue; + } if (card->getRealZValue() > maxZ) { maxZ = card->getRealZValue(); @@ -438,12 +452,13 @@ void GameScene::toggleZoneView(Player *player, const QString &zoneName, int numb connect(item, &ZoneViewWidget::closePressed, this, &GameScene::removeZoneView); addItem(item); - if (zoneName == ZoneNames::GRAVE) + if (zoneName == ZoneNames::GRAVE) { item->setPos(360, 100); - else if (zoneName == ZoneNames::EXILE) + } else if (zoneName == ZoneNames::EXILE) { item->setPos(380, 120); - else + } else { item->setPos(340, 80); + } } /** @@ -480,8 +495,9 @@ void GameScene::removeZoneView(ZoneViewWidget *item) */ void GameScene::clearViews() { - while (!zoneViews.isEmpty()) + while (!zoneViews.isEmpty()) { zoneViews.first()->close(); + } } /** @@ -489,8 +505,9 @@ void GameScene::clearViews() */ void GameScene::closeMostRecentZoneView() { - if (!zoneViews.isEmpty()) + if (!zoneViews.isEmpty()) { zoneViews.last()->close(); + } } // ---------- View Transforms ---------- @@ -509,10 +526,11 @@ QTransform GameScene::getViewportTransform() const bool GameScene::event(QEvent *event) { - if (event->type() == QEvent::GraphicsSceneMouseMove) + if (event->type() == QEvent::GraphicsSceneMouseMove) { updateHover(static_cast(event)->scenePos()); - else if (event->type() == QEvent::Leave) + } else if (event->type() == QEvent::Leave) { updateHoveredCard(nullptr); + } return QGraphicsScene::event(event); } @@ -522,25 +540,29 @@ void GameScene::timerEvent(QTimerEvent * /*event*/) QMutableSetIterator i(cardsToAnimate); while (i.hasNext()) { i.next(); - if (!i.value()->animationEvent()) + if (!i.value()->animationEvent()) { i.remove(); + } } - if (cardsToAnimate.isEmpty()) + if (cardsToAnimate.isEmpty()) { animationTimer->stop(); + } } void GameScene::registerAnimationItem(AbstractCardItem *card) { cardsToAnimate.insert(static_cast(card)); - if (!animationTimer->isActive()) + if (!animationTimer->isActive()) { animationTimer->start(10, this); + } } void GameScene::unregisterAnimationItem(AbstractCardItem *card) { cardsToAnimate.remove(static_cast(card)); - if (cardsToAnimate.isEmpty()) + if (cardsToAnimate.isEmpty()) { animationTimer->stop(); + } } // ---------- Rubber Band ---------- diff --git a/cockatrice/src/game/game_view.cpp b/cockatrice/src/game/game_view.cpp index ce53828a7..4ba41cffb 100644 --- a/cockatrice/src/game/game_view.cpp +++ b/cockatrice/src/game/game_view.cpp @@ -75,8 +75,9 @@ void GameView::resizeEvent(QResizeEvent *event) QGraphicsView::resizeEvent(event); GameScene *s = dynamic_cast(scene()); - if (s) + if (s) { s->processViewSizeChange(event->size()); + } updateSceneRect(scene()->sceneRect()); updateTotalSelectionCount(event->size()); @@ -89,8 +90,9 @@ void GameView::updateSceneRect(const QRectF &rect) void GameView::startRubberBand(const QPointF &_selectionOrigin) { - if (!rubberBand) + if (!rubberBand) { return; + } selectionOrigin = _selectionOrigin; rubberBand->setGeometry(QRect(mapFromScene(selectionOrigin), QSize(0, 0))); @@ -99,8 +101,9 @@ void GameView::startRubberBand(const QPointF &_selectionOrigin) void GameView::resizeRubberBand(const QPointF &cursorPoint, int selectedCount) { - if (!rubberBand) + if (!rubberBand) { return; + } constexpr int kLabelPaddingInPixels = 4; @@ -145,8 +148,9 @@ void GameView::resizeRubberBand(const QPointF &cursorPoint, int selectedCount) void GameView::stopRubberBand() { - if (!rubberBand) + if (!rubberBand) { return; + } rubberBand->hide(); dragCountLabel->hide(); diff --git a/cockatrice/src/game/phases_toolbar.cpp b/cockatrice/src/game/phases_toolbar.cpp index 2341a1d7f..3361f9d55 100644 --- a/cockatrice/src/game/phases_toolbar.cpp +++ b/cockatrice/src/game/phases_toolbar.cpp @@ -21,8 +21,9 @@ PhaseButton::PhaseButton(const QString &_name, QGraphicsItem *parent, QAction *_ activeAnimationTimer = new QTimer(this); connect(activeAnimationTimer, &QTimer::timeout, this, &PhaseButton::updateAnimation); activeAnimationTimer->setSingleShot(false); - } else + } else { activeAnimationCounter = 9; + } setCacheMode(DeviceCoordinateCache); } @@ -63,8 +64,9 @@ void PhaseButton::setWidth(double _width) void PhaseButton::setActive(bool _active) { - if ((active == _active) || !highlightable) + if ((active == _active) || !highlightable) { return; + } active = _active; activeAnimationTimer->start(25); @@ -72,8 +74,9 @@ void PhaseButton::setActive(bool _active) void PhaseButton::updateAnimation() { - if (!highlightable) + if (!highlightable) { return; + } // the counter ticks up to 10 when active and down to 0 when inactive if (active && activeAnimationCounter < 10) { @@ -99,8 +102,9 @@ void PhaseButton::mouseDoubleClickEvent(QGraphicsSceneMouseEvent * /*event*/) void PhaseButton::triggerDoubleClickAction() { - if (doubleClickAction) + if (doubleClickAction) { doubleClickAction->trigger(); + } } PhasesToolbar::PhasesToolbar(QGraphicsItem *parent) @@ -126,8 +130,9 @@ PhasesToolbar::PhasesToolbar(QGraphicsItem *parent) buttonList << untapButton << upkeepButton << drawButton << main1Button << combatStartButton << combatAttackersButton << combatBlockersButton << combatDamageButton << combatEndButton << main2Button << cleanupButton; - for (auto &i : buttonList) + for (auto &i : buttonList) { connect(i, &PhaseButton::clicked, this, &PhasesToolbar::phaseButtonClicked); + } nextTurnButton = new PhaseButton("nextturn", this, nullptr, false); connect(nextTurnButton, &PhaseButton::clicked, this, &PhasesToolbar::actNextTurn); @@ -144,8 +149,9 @@ QRectF PhasesToolbar::boundingRect() const void PhasesToolbar::retranslateUi() { - for (int i = 0; i < buttonList.size(); ++i) + for (int i = 0; i < buttonList.size(); ++i) { buttonList[i]->setToolTip(getLongPhaseName(i)); + } } QString PhasesToolbar::getLongPhaseName(int phase) const @@ -187,8 +193,9 @@ const double PhasesToolbar::marginSize = 3; void PhasesToolbar::rearrangeButtons() { - for (auto &i : buttonList) + for (auto &i : buttonList) { i->setWidth(symbolSize); + } nextTurnButton->setWidth(symbolSize); double y = marginSize; @@ -226,11 +233,13 @@ void PhasesToolbar::setHeight(double _height) void PhasesToolbar::setActivePhase(int phase) { - if (phase >= buttonList.size()) + if (phase >= buttonList.size()) { return; + } - for (int i = 0; i < buttonList.size(); ++i) + for (int i = 0; i < buttonList.size(); ++i) { buttonList[i]->setActive(i == phase); + } } void PhasesToolbar::triggerPhaseAction(int phase) @@ -243,8 +252,9 @@ void PhasesToolbar::triggerPhaseAction(int phase) void PhasesToolbar::phaseButtonClicked() { auto *button = qobject_cast(sender()); - if (button->getActive()) + if (button->getActive()) { button->triggerDoubleClickAction(); + } Command_SetActivePhase cmd; cmd.set_phase(static_cast(buttonList.indexOf(button))); diff --git a/cockatrice/src/game/player/menu/grave_menu.cpp b/cockatrice/src/game/player/menu/grave_menu.cpp index 2af62c08a..c3a5eb433 100644 --- a/cockatrice/src/game/player/menu/grave_menu.cpp +++ b/cockatrice/src/game/player/menu/grave_menu.cpp @@ -78,8 +78,9 @@ void GraveyardMenu::populateRevealRandomMenuWithActivePlayers() const auto &players = player->getGame()->getPlayerManager()->getPlayers().values(); for (auto *other : players) { - if (other == player) + if (other == player) { continue; + } QAction *a = mRevealRandomGraveyardCard->addAction(other->getPlayerInfo()->getName()); a->setData(other->getPlayerInfo()->getId()); connect(a, &QAction::triggered, this, &GraveyardMenu::onRevealRandomTriggered); diff --git a/cockatrice/src/game/player/menu/hand_menu.cpp b/cockatrice/src/game/player/menu/hand_menu.cpp index d65c136bf..1b1ec27d6 100644 --- a/cockatrice/src/game/player/menu/hand_menu.cpp +++ b/cockatrice/src/game/player/menu/hand_menu.cpp @@ -168,8 +168,9 @@ void HandMenu::populateRevealHandMenuWithActivePlayers() const auto &players = player->getGame()->getPlayerManager()->getPlayers().values(); for (auto *other : players) { - if (other == player) + if (other == player) { continue; + } QAction *a = mRevealHand->addAction(other->getPlayerInfo()->getName()); a->setData(other->getPlayerInfo()->getId()); connect(a, &QAction::triggered, this, &HandMenu::onRevealHandTriggered); @@ -186,8 +187,9 @@ void HandMenu::populateRevealRandomHandCardMenuWithActivePlayers() const auto &players = player->getGame()->getPlayerManager()->getPlayers().values(); for (auto *other : players) { - if (other == player) + if (other == player) { continue; + } QAction *a = mRevealRandomHandCard->addAction(other->getPlayerInfo()->getName()); a->setData(other->getPlayerInfo()->getId()); connect(a, &QAction::triggered, this, &HandMenu::onRevealRandomHandCardTriggered); @@ -197,8 +199,9 @@ void HandMenu::populateRevealRandomHandCardMenuWithActivePlayers() void HandMenu::onRevealHandTriggered() { auto *action = qobject_cast(sender()); - if (!action) + if (!action) { return; + } const int targetId = action->data().toInt(); player->getPlayerActions()->actRevealHand(targetId); @@ -207,8 +210,9 @@ void HandMenu::onRevealHandTriggered() void HandMenu::onRevealRandomHandCardTriggered() { auto *action = qobject_cast(sender()); - if (!action) + if (!action) { return; + } const int targetId = action->data().toInt(); player->getPlayerActions()->actRevealRandomHandCard(targetId); diff --git a/cockatrice/src/game/player/menu/library_menu.cpp b/cockatrice/src/game/player/menu/library_menu.cpp index 1bb647d06..72591575f 100644 --- a/cockatrice/src/game/player/menu/library_menu.cpp +++ b/cockatrice/src/game/player/menu/library_menu.cpp @@ -265,8 +265,9 @@ void LibraryMenu::populateRevealLibraryMenuWithActivePlayers() const auto &players = player->getGame()->getPlayerManager()->getPlayers().values(); for (auto *other : players) { - if (other == player) + if (other == player) { continue; + } QAction *a = mRevealLibrary->addAction(other->getPlayerInfo()->getName()); a->setData(other->getPlayerInfo()->getId()); connect(a, &QAction::triggered, this, &LibraryMenu::onRevealLibraryTriggered); @@ -279,8 +280,9 @@ void LibraryMenu::populateLendLibraryMenuWithActivePlayers() const auto &players = player->getGame()->getPlayerManager()->getPlayers().values(); for (auto *other : players) { - if (other == player) + if (other == player) { continue; + } QAction *a = mLendLibrary->addAction(other->getPlayerInfo()->getName()); a->setData(other->getPlayerInfo()->getId()); connect(a, &QAction::triggered, this, &LibraryMenu::onLendLibraryTriggered); @@ -299,8 +301,9 @@ void LibraryMenu::populateRevealTopCardMenuWithActivePlayers() const auto &players = player->getGame()->getPlayerManager()->getPlayers().values(); for (auto *other : players) { - if (other == player) + if (other == player) { continue; + } QAction *a = mRevealTopCard->addAction(other->getPlayerInfo()->getName()); a->setData(other->getPlayerInfo()->getId()); connect(a, &QAction::triggered, this, &LibraryMenu::onRevealTopCardTriggered); diff --git a/cockatrice/src/game/player/player.cpp b/cockatrice/src/game/player/player.cpp index 8f5067eae..b130bcf75 100644 --- a/cockatrice/src/game/player/player.cpp +++ b/cockatrice/src/game/player/player.cpp @@ -63,8 +63,9 @@ Player::~Player() qCInfo(PlayerLog) << "Player destructor:" << getPlayerInfo()->getName(); QMapIterator i(zones); - while (i.hasNext()) + while (i.hasNext()) { delete i.next().value(); + } zones.clear(); delete playerMenu; diff --git a/cockatrice/src/game/player/player_actions.cpp b/cockatrice/src/game/player/player_actions.cpp index 24da37c82..2be9c90ba 100644 --- a/cockatrice/src/game/player/player_actions.cpp +++ b/cockatrice/src/game/player/player_actions.cpp @@ -85,8 +85,9 @@ void PlayerActions::playCard(CardItem *card, bool faceDown) cardToMove->set_pt(info.getPowTough().toStdString()); } cardToMove->set_tapped(!faceDown && info.getUiAttributes().cipt); - if (tableRow != 3) + if (tableRow != 3) { cmd.set_target_zone(ZoneNames::TABLE); + } cmd.set_x(gridPoint.x()); cmd.set_y(gridPoint.y()); } diff --git a/cockatrice/src/game/player/player_list_widget.cpp b/cockatrice/src/game/player/player_list_widget.cpp index 9506e0729..6b1cf6cc6 100644 --- a/cockatrice/src/game/player/player_list_widget.cpp +++ b/cockatrice/src/game/player/player_list_widget.cpp @@ -43,8 +43,9 @@ PlayerListTWI::PlayerListTWI() : QTreeWidgetItem(Type) bool PlayerListTWI::operator<(const QTreeWidgetItem &other) const { // Sort by spectator/player - if (data(1, Qt::UserRole) != other.data(1, Qt::UserRole)) + if (data(1, Qt::UserRole) != other.data(1, Qt::UserRole)) { return data(1, Qt::UserRole).toBool(); + } // Sort by player ID return data(4, Qt::UserRole + 1).toInt() < other.data(4, Qt::UserRole + 1).toInt(); @@ -106,12 +107,14 @@ void PlayerListWidget::addPlayer(const ServerInfo_PlayerProperties &player) void PlayerListWidget::updatePlayerProperties(const ServerInfo_PlayerProperties &prop, int playerId) { - if (playerId == -1) + if (playerId == -1) { playerId = prop.player_id(); + } QTreeWidgetItem *player = players.value(playerId, 0); - if (!player) + if (!player) { return; + } bool isSpectator = prop.has_spectator() && prop.spectator(); if (prop.has_judge() || prop.has_spectator()) { @@ -126,13 +129,16 @@ void PlayerListWidget::updatePlayerProperties(const ServerInfo_PlayerProperties } if (!isSpectator) { - if (prop.has_conceded()) + if (prop.has_conceded()) { player->setData(2, Qt::UserRole, prop.conceded()); - if (prop.has_ready_start()) + } + if (prop.has_ready_start()) { player->setData(2, Qt::UserRole + 1, prop.ready_start()); - if (prop.has_conceded() || prop.has_ready_start()) + } + if (prop.has_conceded() || prop.has_ready_start()) { player->setIcon(2, gameStarted ? (prop.conceded() ? concededIcon : QIcon()) : (prop.ready_start() ? readyIcon : notReadyIcon)); + } } if (prop.has_user_info()) { player->setData(3, Qt::UserRole, prop.user_info().user_level()); @@ -141,30 +147,35 @@ void PlayerListWidget::updatePlayerProperties(const ServerInfo_PlayerProperties QString::fromStdString(prop.user_info().privlevel()))); player->setText(4, QString::fromStdString(prop.user_info().name())); const QString country = QString::fromStdString(prop.user_info().country()); - if (!country.isEmpty()) + if (!country.isEmpty()) { player->setIcon(4, QIcon(CountryPixmapGenerator::generatePixmap(12, country))); + } player->setData(4, Qt::UserRole, QString::fromStdString(prop.user_info().name())); } - if (prop.has_player_id()) + if (prop.has_player_id()) { player->setData(4, Qt::UserRole + 1, prop.player_id()); + } if (!isSpectator) { if (prop.has_deck_hash()) { player->setText(5, QString::fromStdString(prop.deck_hash())); } - if (prop.has_sideboard_locked()) + if (prop.has_sideboard_locked()) { player->setIcon(5, prop.sideboard_locked() ? lockIcon : QIcon()); + } } - if (prop.has_ping_seconds()) + if (prop.has_ping_seconds()) { player->setIcon(0, QIcon(PingPixmapGenerator::generatePixmap(12, prop.ping_seconds(), 10))); + } } void PlayerListWidget::removePlayer(int playerId) { QTreeWidgetItem *player = players.value(playerId, 0); - if (!player) + if (!player) { return; + } players.remove(playerId); delete takeTopLevelItem(indexOfTopLevelItem(player)); } @@ -193,13 +204,14 @@ void PlayerListWidget::setGameStarted(bool _gameStarted, bool resuming) QTreeWidgetItem *twi = i.next().value(); bool isPlayer = twi->data(1, Qt::UserRole).toBool(); - if (!isPlayer) + if (!isPlayer) { continue; + } if (gameStarted) { - if (resuming) + if (resuming) { twi->setIcon(2, twi->data(2, Qt::UserRole).toBool() ? concededIcon : QIcon()); - else { + } else { twi->setData(2, Qt::UserRole, false); twi->setIcon(2, QIcon()); } @@ -211,8 +223,9 @@ void PlayerListWidget::setGameStarted(bool _gameStarted, bool resuming) void PlayerListWidget::showContextMenu(const QPoint &pos, const QModelIndex &index) { - if (!userContextMenu) + if (!userContextMenu) { return; + } const QString &userName = index.sibling(index.row(), 4).data(Qt::UserRole).toString(); int playerId = index.sibling(index.row(), 4).data(Qt::UserRole + 1).toInt(); diff --git a/cockatrice/src/game/player/player_manager.cpp b/cockatrice/src/game/player/player_manager.cpp index e283d2196..bd50703de 100644 --- a/cockatrice/src/game/player/player_manager.cpp +++ b/cockatrice/src/game/player/player_manager.cpp @@ -21,15 +21,18 @@ bool PlayerManager::isMainPlayerConceded() const Player *PlayerManager::getActiveLocalPlayer(int activePlayer) const { Player *active = players.value(activePlayer, 0); - if (active) - if (active->getPlayerInfo()->getLocal()) + if (active) { + if (active->getPlayerInfo()->getLocal()) { return active; + } + } QMapIterator playerIterator(players); while (playerIterator.hasNext()) { Player *temp = playerIterator.next().value(); - if (temp->getPlayerInfo()->getLocal()) + if (temp->getPlayerInfo()->getLocal()) { return temp; + } } return nullptr; @@ -66,8 +69,9 @@ void PlayerManager::removePlayer(int playerId) Player *PlayerManager::getPlayer(int playerId) const { Player *player = players.value(playerId, 0); - if (!player) + if (!player) { return nullptr; + } return player; } diff --git a/cockatrice/src/game/player/player_target.cpp b/cockatrice/src/game/player/player_target.cpp index a7a5cc5e7..36c9ae953 100644 --- a/cockatrice/src/game/player/player_target.cpp +++ b/cockatrice/src/game/player/player_target.cpp @@ -128,8 +128,9 @@ void PlayerTarget::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*o resetPainterTransform(painter); QString name = QString::fromStdString(info->name()); - if (name.size() > 13) + if (name.size() > 13) { name = name.mid(0, 10) + "..."; + } QFont font; font.setPixelSize(qMax(qRound(translatedNameRect.height() / 1.5), 9)); @@ -144,8 +145,9 @@ void PlayerTarget::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*o painter->setPen(pen); painter->drawRect(boundingRect().adjusted(border / 2, border / 2, -border / 2, -border / 2)); - if (getBeingPointedAt()) + if (getBeingPointedAt()) { painter->fillRect(boundingRect(), QBrush(QColor(255, 0, 0, 100))); + } } AbstractCounter *PlayerTarget::addCounter(int _counterId, const QString &_name, int _value) diff --git a/cockatrice/src/game/zones/card_zone.cpp b/cockatrice/src/game/zones/card_zone.cpp index cd7ae6a56..3457b681e 100644 --- a/cockatrice/src/game/zones/card_zone.cpp +++ b/cockatrice/src/game/zones/card_zone.cpp @@ -25,14 +25,16 @@ void CardZone::onCardAdded(CardItem *addedCard) void CardZone::retranslateUi() { - for (int i = 0; i < getLogic()->getCards().size(); ++i) + for (int i = 0; i < getLogic()->getCards().size(); ++i) { getLogic()->getCards()[i]->retranslateUi(); + } } void CardZone::mouseDoubleClickEvent(QGraphicsSceneMouseEvent * /*event*/) { - if (doubleClickAction) + if (doubleClickAction) { doubleClickAction->trigger(); + } } bool CardZone::showContextMenu(const QPoint &screenPos) @@ -47,12 +49,14 @@ bool CardZone::showContextMenu(const QPoint &screenPos) void CardZone::mousePressEvent(QGraphicsSceneMouseEvent *event) { if (event->button() == Qt::RightButton) { - if (showContextMenu(event->screenPos())) + if (showContextMenu(event->screenPos())) { event->accept(); - else + } else { event->ignore(); - } else + } + } else { event->ignore(); + } } QPointF CardZone::closestGridPoint(const QPointF &point) diff --git a/cockatrice/src/game/zones/hand_zone.cpp b/cockatrice/src/game/zones/hand_zone.cpp index 506a26a80..3d676dbb5 100644 --- a/cockatrice/src/game/zones/hand_zone.cpp +++ b/cockatrice/src/game/zones/hand_zone.cpp @@ -34,9 +34,11 @@ void HandZone::handleDropEvent(const QList &dragItems, QPoint point = dropPoint + scenePos().toPoint(); int x = -1; if (SettingsCache::instance().getHorizontalHand()) { - for (x = 0; x < getLogic()->getCards().size(); x++) - if (point.x() < static_cast(getLogic()->getCards().at(x))->scenePos().x()) + for (x = 0; x < getLogic()->getCards().size(); x++) { + if (point.x() < static_cast(getLogic()->getCards().at(x))->scenePos().x()) { break; + } + } } else { x = calcDropIndexFromY(dropPoint.y()); } @@ -49,18 +51,20 @@ void HandZone::handleDropEvent(const QList &dragItems, cmd.set_x(x); cmd.set_y(-1); - for (int i = 0; i < dragItems.size(); ++i) + for (int i = 0; i < dragItems.size(); ++i) { cmd.mutable_cards_to_move()->add_card()->set_card_id(dragItems[i]->getId()); + } getLogic()->getPlayer()->getPlayerActions()->sendGameCommand(cmd); } QRectF HandZone::boundingRect() const { - if (SettingsCache::instance().getHorizontalHand()) + if (SettingsCache::instance().getHorizontalHand()) { return QRectF(0, 0, width, CardDimensions::HEIGHT_F + 10); - else + } else { return QRectF(0, 0, CardDimensions::WIDTH_F * 1.5, zoneHeight); + } } void HandZone::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*option*/, QWidget * /*widget*/) @@ -90,9 +94,9 @@ void HandZone::reorganizeCards() CardItem *c = getLogic()->getCards().at(i); // If the total width of the cards is smaller than the available width, // the cards do not need to overlap and are displayed in the center of the area. - if (cardWidth * cardCount > totalWidth) + if (cardWidth * cardCount > totalWidth) { c->setPos(xPadding + ((qreal)i) * (totalWidth - cardWidth) / (cardCount - 1), 5); - else { + } else { qreal xPosition = leftJustified ? xPadding + ((qreal)i) * cardWidth : xPadding + ((qreal)i) * cardWidth + (totalWidth - cardCount * cardWidth) / 2; diff --git a/cockatrice/src/game/zones/logic/card_zone_logic.cpp b/cockatrice/src/game/zones/logic/card_zone_logic.cpp index e917e4ad7..9d9b3767f 100644 --- a/cockatrice/src/game/zones/logic/card_zone_logic.cpp +++ b/cockatrice/src/game/zones/logic/card_zone_logic.cpp @@ -55,8 +55,9 @@ void CardZoneLogic::addCard(CardItem *card, const bool reorganize, const int x, emit cardAdded(card); addCardImpl(card, x, y); - if (reorganize) + if (reorganize) { emit reorganizeCards(); + } emit cardCountChanged(); } @@ -66,16 +67,19 @@ CardItem *CardZoneLogic::takeCard(int position, int cardId, bool toNewZone) if (position == -1) { // position == -1 means either that the zone is indexed by card id // or that it doesn't matter which card you take. - for (int i = 0; i < cards.size(); ++i) + for (int i = 0; i < cards.size(); ++i) { if (cards[i]->getId() == cardId) { position = i; break; } - if (position == -1) + } + if (position == -1) { position = 0; + } } - if (position >= cards.size()) + if (position >= cards.size()) { return nullptr; + } for (auto *view : views) { qobject_cast(view->getLogic())->removeCard(position, toNewZone); @@ -142,8 +146,9 @@ void CardZoneLogic::moveAllToZone() cmd.set_target_zone(targetZone.toStdString()); cmd.set_x(targetX); - for (int i = 0; i < cards.size(); ++i) + for (int i = 0; i < cards.size(); ++i) { cmd.mutable_cards_to_move()->add_card()->set_card_id(cards[i]->getId()); + } player->getPlayerActions()->sendGameCommand(cmd); } @@ -175,9 +180,9 @@ void CardZoneLogic::clearContents() QString CardZoneLogic::getTranslatedName(bool theirOwn, GrammaticalCase gc) const { QString ownerName = player->getPlayerInfo()->getName(); - if (name == ZoneNames::HAND) + if (name == ZoneNames::HAND) { return (theirOwn ? tr("their hand", "nominative") : tr("%1's hand", "nominative").arg(ownerName)); - else if (name == ZoneNames::DECK) + } else if (name == ZoneNames::DECK) { switch (gc) { case CaseLookAtZone: return (theirOwn ? tr("their library", "look at zone") @@ -193,11 +198,11 @@ QString CardZoneLogic::getTranslatedName(bool theirOwn, GrammaticalCase gc) cons default: return (theirOwn ? tr("their library", "nominative") : tr("%1's library", "nominative").arg(ownerName)); } - else if (name == ZoneNames::GRAVE) + } else if (name == ZoneNames::GRAVE) { return (theirOwn ? tr("their graveyard", "nominative") : tr("%1's graveyard", "nominative").arg(ownerName)); - else if (name == ZoneNames::EXILE) + } else if (name == ZoneNames::EXILE) { return (theirOwn ? tr("their exile", "nominative") : tr("%1's exile", "nominative").arg(ownerName)); - else if (name == ZoneNames::SIDEBOARD) + } else if (name == ZoneNames::SIDEBOARD) { switch (gc) { case CaseLookAtZone: return (theirOwn ? tr("their sideboard", "look at zone") @@ -208,7 +213,7 @@ QString CardZoneLogic::getTranslatedName(bool theirOwn, GrammaticalCase gc) cons default: break; } - else { + } else { return (theirOwn ? tr("their custom zone '%1'", "nominative").arg(name) : tr("%1's custom zone '%2'", "nominative").arg(ownerName).arg(name)); } diff --git a/cockatrice/src/game/zones/logic/pile_zone_logic.cpp b/cockatrice/src/game/zones/logic/pile_zone_logic.cpp index c5ffd5fd5..d445ad90c 100644 --- a/cockatrice/src/game/zones/logic/pile_zone_logic.cpp +++ b/cockatrice/src/game/zones/logic/pile_zone_logic.cpp @@ -25,8 +25,9 @@ void PileZoneLogic::addCardImpl(CardItem *card, int x, int /*y*/) card->setCardRef({}); card->setId(-1); // If we obscure a previously revealed card, its name has to be forgotten - if (cards.size() > x + 1) + if (cards.size() > x + 1) { cards.at(x + 1)->setCardRef({}); + } } card->setVisible(false); card->resetState(); diff --git a/cockatrice/src/game/zones/logic/table_zone_logic.cpp b/cockatrice/src/game/zones/logic/table_zone_logic.cpp index 42caf2ec8..d01a756a3 100644 --- a/cockatrice/src/game/zones/logic/table_zone_logic.cpp +++ b/cockatrice/src/game/zones/logic/table_zone_logic.cpp @@ -29,7 +29,8 @@ CardItem *TableZoneLogic::takeCard(int position, int cardId, bool toNewZone) { CardItem *result = CardZoneLogic::takeCard(position, cardId); - if (toNewZone) + if (toNewZone) { emit contentSizeChanged(); + } return result; } \ No newline at end of file diff --git a/cockatrice/src/game/zones/pile_zone.cpp b/cockatrice/src/game/zones/pile_zone.cpp index d85b5f4e2..33538ab28 100644 --- a/cockatrice/src/game/zones/pile_zone.cpp +++ b/cockatrice/src/game/zones/pile_zone.cpp @@ -48,9 +48,10 @@ void PileZone::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*optio { painter->drawPath(shape()); - if (!getLogic()->getCards().isEmpty()) + if (!getLogic()->getCards().isEmpty()) { getLogic()->getCards().at(0)->paintPicture(painter, getLogic()->getCards().at(0)->getTranslatedSize(painter), 90); + } painter->translate(CardDimensions::WIDTH_HALF_F, CardDimensions::HEIGHT_HALF_F); painter->rotate(-90); @@ -87,24 +88,28 @@ void PileZone::reorganizeCards() void PileZone::mousePressEvent(QGraphicsSceneMouseEvent *event) { CardZone::mousePressEvent(event); - if (event->isAccepted()) + if (event->isAccepted()) { return; + } if (event->button() == Qt::LeftButton) { setCursor(Qt::ClosedHandCursor); event->accept(); - } else + } else { event->ignore(); + } } void PileZone::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { if ((event->screenPos() - event->buttonDownScreenPos(Qt::LeftButton)).manhattanLength() < - QApplication::startDragDistance()) + QApplication::startDragDistance()) { return; + } - if (getLogic()->getCards().isEmpty()) + if (getLogic()->getCards().isEmpty()) { return; + } bool forceFaceDown = event->modifiers().testFlag(Qt::ShiftModifier); bool bottomCard = event->modifiers().testFlag(Qt::ControlModifier); @@ -123,7 +128,8 @@ void PileZone::mouseReleaseEvent(QGraphicsSceneMouseEvent * /*event*/) void PileZone::hoverEnterEvent(QGraphicsSceneHoverEvent *event) { - if (!getLogic()->getCards().isEmpty()) + if (!getLogic()->getCards().isEmpty()) { getLogic()->getCards()[0]->processHoverEvent(); + } QGraphicsItem::hoverEnterEvent(event); } diff --git a/cockatrice/src/game/zones/select_zone.cpp b/cockatrice/src/game/zones/select_zone.cpp index fd733e01f..e85ec17ae 100644 --- a/cockatrice/src/game/zones/select_zone.cpp +++ b/cockatrice/src/game/zones/select_zone.cpp @@ -69,8 +69,9 @@ SelectZone *SelectZone::findOwningSelectZone(const QGraphicsItem *card) SelectZone::StackLayoutParams SelectZone::buildStackParams(qreal minOffset) const { const auto &cards = getLogic()->getCards(); - if (cards.isEmpty()) + if (cards.isEmpty()) { return {0, boundingRect().height(), 0.0, 0.0, minOffset}; + } const auto cardCount = static_cast(cards.size()); const qreal cardHeight = cards.at(0)->boundingRect().height(); const qreal offset = stackingOffset(cardHeight); @@ -93,8 +94,9 @@ int SelectZone::calcDropIndexFromY(qreal dropY, qreal minOffset) const void SelectZone::restoreStaleEscapedCards() { - if (!cardClipContainer) + if (!cardClipContainer) { return; + } for (auto *card : getLogic()->getCards()) { // A card parented to the zone (instead of the clip container) should // only occur while it is actively hovered. If hover cleanup was @@ -108,10 +110,12 @@ void SelectZone::restoreStaleEscapedCards() void SelectZone::layoutCardsVertically(const StackLayoutParams ¶ms) { const auto &cards = getLogic()->getCards(); - if (cards.isEmpty() || params.cardCount <= 0) + if (cards.isEmpty() || params.cardCount <= 0) { return; - if (params.cardCount > cards.size()) + } + if (params.cardCount > cards.size()) { return; + } constexpr qreal xspace = 5; const qreal cardWidth = cards.at(0)->boundingRect().width(); @@ -163,8 +167,9 @@ void SelectZone::onCardAdded(CardItem *addedCard) void SelectZone::setupClipContainer(std::optional zValue) { - if (cardClipContainer) + if (cardClipContainer) { return; + } setFlag(QGraphicsItem::ItemClipsChildrenToShape, false); @@ -209,15 +214,19 @@ void SelectZone::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { if (event->buttons().testFlag(Qt::LeftButton)) { QPointF pos = event->pos(); - if (pos.x() < 0) + if (pos.x() < 0) { pos.setX(0); + } QRectF br = boundingRect(); - if (pos.x() > br.width()) + if (pos.x() > br.width()) { pos.setX(br.width()); - if (pos.y() < 0) + } + if (pos.y() < 0) { pos.setY(0); - if (pos.y() > br.height()) + } + if (pos.y() > br.height()) { pos.setY(br.height()); + } QRectF selectionRect = QRectF(selectionOrigin, pos).normalized(); for (auto card : getLogic()->getCards()) { @@ -253,8 +262,9 @@ void SelectZone::mousePressEvent(QGraphicsSceneMouseEvent *event) selectionOrigin = event->pos(); static_cast(scene())->startRubberBand(event->scenePos()); event->accept(); - } else + } else { CardZone::mousePressEvent(event); + } } void SelectZone::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) diff --git a/cockatrice/src/game/zones/table_zone.cpp b/cockatrice/src/game/zones/table_zone.cpp index 2a382fafe..5e7db3d09 100644 --- a/cockatrice/src/game/zones/table_zone.cpp +++ b/cockatrice/src/game/zones/table_zone.cpp @@ -108,8 +108,9 @@ void TableZone::paintLandDivider(QPainter *painter) // Place the line 2 grid heights down then back it off just enough to allow // some space between a 3-card stack and the land area. qreal separatorY = MARGIN_TOP + 2 * (CardDimensions::HEIGHT + PADDING_Y) - STACKED_CARD_OFFSET_Y / 2; - if (isInverted()) + if (isInverted()) { separatorY = height - separatorY; + } painter->setPen(QColor(255, 255, 255, 40)); painter->drawLine(QPointF(0, separatorY), QPointF(width, separatorY)); } @@ -157,8 +158,9 @@ void TableZone::reorganizeCards() for (int i = 0; i < getLogic()->getCards().size(); ++i) { QPoint gridPoint = getLogic()->getCards()[i]->getGridPos(); - if (gridPoint.x() == -1) + if (gridPoint.x() == -1) { continue; + } QPointF mapPoint = mapFromGrid(gridPoint); qreal x = mapPoint.x(); @@ -167,8 +169,9 @@ void TableZone::reorganizeCards() int numberAttachedCards = getLogic()->getCards()[i]->getAttachedCards().size(); qreal actualX = x + numberAttachedCards * STACKED_CARD_OFFSET_X; qreal actualY = y; - if (numberAttachedCards) + if (numberAttachedCards) { actualY += 15; + } getLogic()->getCards()[i]->setPos(actualX, actualY); getLogic()->getCards()[i]->setRealZValue(ZValues::tableCardZValue(actualX, actualY)); @@ -227,16 +230,19 @@ void TableZone::resizeToContents() int xMax = 0; // Find rightmost card position, which includes the left margin amount. - for (int i = 0; i < getLogic()->getCards().size(); ++i) - if (getLogic()->getCards()[i]->pos().x() > xMax) + for (int i = 0; i < getLogic()->getCards().size(); ++i) { + if (getLogic()->getCards()[i]->pos().x() > xMax) { xMax = (int)getLogic()->getCards()[i]->pos().x(); + } + } // Minimum width is the rightmost card position plus enough room for // another card with padding, then margin. currentMinimumWidth = xMax + (2 * CardDimensions::WIDTH) + PADDING_X + MARGIN_RIGHT; - if (currentMinimumWidth < MIN_WIDTH) + if (currentMinimumWidth < MIN_WIDTH) { currentMinimumWidth = MIN_WIDTH; + } if (currentMinimumWidth != width) { prepareGeometryChange(); @@ -247,9 +253,11 @@ void TableZone::resizeToContents() CardItem *TableZone::getCardFromGrid(const QPoint &gridPoint) const { - for (int i = 0; i < getLogic()->getCards().size(); i++) - if (getLogic()->getCards().at(i)->getGridPoint() == gridPoint) + for (int i = 0; i < getLogic()->getCards().size(); i++) { + if (getLogic()->getCards().at(i)->getGridPoint() == gridPoint) { return getLogic()->getCards().at(i); + } + } return 0; } @@ -266,8 +274,9 @@ void TableZone::computeCardStackWidths() QMap cardStackCount; for (int i = 0; i < getLogic()->getCards().size(); ++i) { const QPoint &gridPoint = getLogic()->getCards()[i]->getGridPos(); - if (gridPoint.x() == -1) + if (gridPoint.x() == -1) { continue; + } const int key = getCardStackMapKey(gridPoint.x() / 3, gridPoint.y()); cardStackCount.insert(key, cardStackCount.value(key, 0) + 1); @@ -277,16 +286,18 @@ void TableZone::computeCardStackWidths() cardStackWidth.clear(); for (int i = 0; i < getLogic()->getCards().size(); ++i) { const QPoint &gridPoint = getLogic()->getCards()[i]->getGridPos(); - if (gridPoint.x() == -1) + if (gridPoint.x() == -1) { continue; + } const int key = getCardStackMapKey(gridPoint.x() / 3, gridPoint.y()); const int stackCount = cardStackCount.value(key, 0); - if (stackCount == 1) + if (stackCount == 1) { cardStackWidth.insert(key, CardDimensions::WIDTH + getLogic()->getCards()[i]->getAttachedCards().size() * STACKED_CARD_OFFSET_X); - else + } else { cardStackWidth.insert(key, CardDimensions::WIDTH + (stackCount - 1) * STACKED_CARD_OFFSET_X); + } } } @@ -303,15 +314,17 @@ QPointF TableZone::mapFromGrid(QPoint gridPoint) const x += cardStackWidth.value(key, CardDimensions::WIDTH) + PADDING_X; } - if (isInverted()) + if (isInverted()) { gridPoint.setY(TABLEROWS - 1 - gridPoint.y()); + } // Start with margin plus stacked card offset y = MARGIN_TOP + (gridPoint.x() % 3) * STACKED_CARD_OFFSET_Y; // Add in card size and padding for each row - for (int i = 0; i < gridPoint.y(); ++i) + for (int i = 0; i < gridPoint.y(); ++i) { y += CardDimensions::HEIGHT + PADDING_Y; + } return QPointF(x, y); } @@ -330,8 +343,9 @@ QPoint TableZone::mapToGrid(const QPointF &mapPoint) const gridPointY = clampValidTableRow(gridPointY); - if (isInverted()) + if (isInverted()) { gridPointY = TABLEROWS - 1 - gridPointY; + } // Calculating the x-coordinate of the grid space requires adding up the // widths of each card stack along the row. @@ -367,19 +381,23 @@ QPointF TableZone::closestGridPoint(const QPointF &point) { QPoint gridPoint = mapToGrid(point); gridPoint.setX((gridPoint.x() / 3) * 3); - if (getCardFromGrid(gridPoint)) + if (getCardFromGrid(gridPoint)) { gridPoint.setX(gridPoint.x() + 1); - if (getCardFromGrid(gridPoint)) + } + if (getCardFromGrid(gridPoint)) { gridPoint.setX(gridPoint.x() + 1); + } return mapFromGrid(gridPoint); } int TableZone::clampValidTableRow(const int row) { - if (row < 0) + if (row < 0) { return 0; - if (row >= TABLEROWS) + } + if (row >= TABLEROWS) { return TABLEROWS - 1; + } return row; } diff --git a/cockatrice/src/game/zones/view_zone.cpp b/cockatrice/src/game/zones/view_zone.cpp index d2fd1e971..803f80f48 100644 --- a/cockatrice/src/game/zones/view_zone.cpp +++ b/cockatrice/src/game/zones/view_zone.cpp @@ -203,9 +203,9 @@ ZoneViewZone::GridSize ZoneViewZone::positionCardsForDisplay(CardList &cards, Ca QString columnProp = extractor(c); if (i) { // if not the first card - if (columnProp == lastColumnProp) + if (columnProp == lastColumnProp) { row++; // add below current card - else { // if no match then move card to next column + } else { // if no match then move card to next column col++; row = 0; } @@ -233,8 +233,9 @@ ZoneViewZone::GridSize ZoneViewZone::positionCardsForDisplay(CardList &cards, Ca cols = qCeil((double)cardCount / minRows); } - if (cols < 2) + if (cols < 2) { cols = 2; + } qCDebug(ViewZoneLog) << "reorganizeCards: rows=" << rows << "cols=" << cols; diff --git a/cockatrice/src/game/zones/view_zone_widget.cpp b/cockatrice/src/game/zones/view_zone_widget.cpp index 23d7d6a19..5893b8405 100644 --- a/cockatrice/src/game/zones/view_zone_widget.cpp +++ b/cockatrice/src/game/zones/view_zone_widget.cpp @@ -252,8 +252,9 @@ void ZoneViewWidget::retranslateUi() void ZoneViewWidget::stopWindowDrag() { - if (!draggingWindow) + if (!draggingWindow) { return; + } draggingWindow = false; ungrabMouse(); @@ -312,13 +313,15 @@ QGraphicsView *ZoneViewWidget::findDragView(QWidget *eventWidget) const { QWidget *current = eventWidget; while (current) { - if (auto *view = qobject_cast(current)) + if (auto *view = qobject_cast(current)) { return view; + } current = current->parentWidget(); } - if (scene() && !scene()->views().isEmpty()) + if (scene() && !scene()->views().isEmpty()) { return scene()->views().constFirst(); + } return nullptr; } @@ -346,8 +349,9 @@ bool ZoneViewWidget::windowFrameEvent(QEvent *event) } auto *me = dynamic_cast(event); - if (!me) + if (!me) { return QGraphicsWidget::windowFrameEvent(event); + } switch (event->type()) { case QEvent::GraphicsSceneMousePress: @@ -506,8 +510,9 @@ void ZoneViewWidget::resizeToZoneContents(bool forceInitialHeight) zone->setGeometry(QRectF(0, -scrollBar->value(), zoneContainer->size().width(), totalZoneHeight)); - if (layout()) + if (layout()) { layout()->invalidate(); + } } void ZoneViewWidget::handleScrollBarChange(int value) @@ -521,8 +526,9 @@ void ZoneViewWidget::closeEvent(QCloseEvent *event) disconnect(zone, &ZoneViewZone::closed, this, 0); // manually call zone->close in order to remove it from the origZones views zone->close(); - if (shuffleCheckBox.isChecked()) + if (shuffleCheckBox.isChecked()) { player->getPlayerActions()->sendGameCommand(Command_Shuffle()); + } zoneDeleted(); event->accept(); } @@ -536,8 +542,9 @@ void ZoneViewWidget::zoneDeleted() void ZoneViewWidget::initStyleOption(QStyleOption *option) const { QStyleOptionTitleBar *titleBar = qstyleoption_cast(option); - if (titleBar) + if (titleBar) { titleBar->icon = QPixmap("theme:cockatrice"); + } } /** diff --git a/cockatrice/src/game_graphics/board/abstract_graphics_item.cpp b/cockatrice/src/game_graphics/board/abstract_graphics_item.cpp index 05f4a41ab..8da8ab708 100644 --- a/cockatrice/src/game_graphics/board/abstract_graphics_item.cpp +++ b/cockatrice/src/game_graphics/board/abstract_graphics_item.cpp @@ -19,27 +19,29 @@ void AbstractGraphicsItem::paintNumberEllipse(int number, QFontMetrics fm(font); double w = 1.3 * fm.horizontalAdvance(numStr); double h = fm.height() * 1.3; - if (w < h) + if (w < h) { w = h; + } painter->setPen(QColor(255, 255, 255, 0)); painter->setBrush(QBrush(QColor(color))); QRectF textRect; - if (position == -1) + if (position == -1) { textRect = QRectF((boundingRect().width() - w) / 2.0, (boundingRect().height() - h) / 2.0, w, h); - else { + } else { qreal xOffset = 10; qreal yOffset = 20; qreal spacing = 2; - if (position < 2) + if (position < 2) { textRect = QRectF(count == 1 ? ((boundingRect().width() - w) / 2.0) : (position % 2 == 0 ? xOffset : (boundingRect().width() - xOffset - w)), yOffset, w, h); - else + } else { textRect = QRectF(count == 3 ? ((boundingRect().width() - w) / 2.0) : (position % 2 == 0 ? xOffset : (boundingRect().width() - xOffset - w)), yOffset + (spacing + h) * (position / 2), w, h); + } } painter->drawEllipse(textRect); diff --git a/cockatrice/src/interface/card_picture_loader/card_picture_loader.cpp b/cockatrice/src/interface/card_picture_loader/card_picture_loader.cpp index dbd51b973..2cd28c4d3 100644 --- a/cockatrice/src/interface/card_picture_loader/card_picture_loader.cpp +++ b/cockatrice/src/interface/card_picture_loader/card_picture_loader.cpp @@ -230,8 +230,9 @@ bool CardPictureLoader::hasCustomArt() QFileInfo dir(it.next()); #endif - if (it.fileName() == "downloadedPics") + if (it.fileName() == "downloadedPics") { continue; + } QDirIterator subIt(it.filePath(), QDir::Files, QDirIterator::Subdirectories | QDirIterator::FollowSymlinks); if (subIt.hasNext()) { diff --git a/cockatrice/src/interface/card_picture_loader/card_picture_to_load.cpp b/cockatrice/src/interface/card_picture_loader/card_picture_to_load.cpp index d72226aab..f95d8ec8f 100644 --- a/cockatrice/src/interface/card_picture_loader/card_picture_to_load.cpp +++ b/cockatrice/src/interface/card_picture_loader/card_picture_to_load.cpp @@ -63,8 +63,9 @@ static PrintingInfo findPrintingForSet(const ExactCard &card, const QString &set { SetToPrintingsMap setsToPrintings = card.getInfo().getSets(); - if (!setsToPrintings.contains(setName)) + if (!setsToPrintings.contains(setName)) { return PrintingInfo(); + } for (const auto &printing : setsToPrintings[setName]) { if (printing.getUuid() == card.getPrinting().getUuid()) { diff --git a/cockatrice/src/interface/key_signals.cpp b/cockatrice/src/interface/key_signals.cpp index b4a38fad5..a78997cc2 100644 --- a/cockatrice/src/interface/key_signals.cpp +++ b/cockatrice/src/interface/key_signals.cpp @@ -6,29 +6,33 @@ bool KeySignals::eventFilter(QObject * /*object*/, QEvent *event) { QKeyEvent *kevent; - if (event->type() != QEvent::KeyPress) + if (event->type() != QEvent::KeyPress) { return false; + } kevent = static_cast(event); switch (kevent->key()) { case Qt::Key_Return: case Qt::Key_Enter: - if (kevent->modifiers().testFlag(Qt::AltModifier) && kevent->modifiers().testFlag(Qt::ControlModifier)) + if (kevent->modifiers().testFlag(Qt::AltModifier) && kevent->modifiers().testFlag(Qt::ControlModifier)) { emit onCtrlAltEnter(); - else if (kevent->modifiers() & Qt::ControlModifier) + } else if (kevent->modifiers() & Qt::ControlModifier) { emit onCtrlEnter(); - else + } else { emit onEnter(); + } break; case Qt::Key_Right: - if (kevent->modifiers() & Qt::ShiftModifier) + if (kevent->modifiers() & Qt::ShiftModifier) { emit onShiftRight(); + } break; case Qt::Key_Left: - if (kevent->modifiers() & Qt::ShiftModifier) + if (kevent->modifiers() & Qt::ShiftModifier) { emit onShiftLeft(); + } break; case Qt::Key_Delete: @@ -37,33 +41,39 @@ bool KeySignals::eventFilter(QObject * /*object*/, QEvent *event) break; case Qt::Key_Minus: - if (kevent->modifiers().testFlag(Qt::AltModifier) && kevent->modifiers().testFlag(Qt::ControlModifier)) + if (kevent->modifiers().testFlag(Qt::AltModifier) && kevent->modifiers().testFlag(Qt::ControlModifier)) { emit onCtrlAltMinus(); + } break; case Qt::Key_Equal: - if (kevent->modifiers().testFlag(Qt::AltModifier) && kevent->modifiers().testFlag(Qt::ControlModifier)) + if (kevent->modifiers().testFlag(Qt::AltModifier) && kevent->modifiers().testFlag(Qt::ControlModifier)) { emit onCtrlAltEqual(); + } break; case Qt::Key_BracketLeft: - if (kevent->modifiers().testFlag(Qt::AltModifier) && kevent->modifiers().testFlag(Qt::ControlModifier)) + if (kevent->modifiers().testFlag(Qt::AltModifier) && kevent->modifiers().testFlag(Qt::ControlModifier)) { emit onCtrlAltLBracket(); + } break; case Qt::Key_BracketRight: - if (kevent->modifiers().testFlag(Qt::AltModifier) && kevent->modifiers().testFlag(Qt::ControlModifier)) + if (kevent->modifiers().testFlag(Qt::AltModifier) && kevent->modifiers().testFlag(Qt::ControlModifier)) { emit onCtrlAltRBracket(); + } break; case Qt::Key_S: - if (kevent->modifiers() & Qt::ShiftModifier) + if (kevent->modifiers() & Qt::ShiftModifier) { emit onShiftS(); + } break; case Qt::Key_C: - if (kevent->modifiers() & Qt::ControlModifier) + if (kevent->modifiers() & Qt::ControlModifier) { emit onCtrlC(); + } break; default: diff --git a/cockatrice/src/interface/logger.cpp b/cockatrice/src/interface/logger.cpp index d6df065e8..3e00a0b24 100644 --- a/cockatrice/src/interface/logger.cpp +++ b/cockatrice/src/interface/logger.cpp @@ -66,8 +66,9 @@ void Logger::openLogfileSession() void Logger::closeLogfileSession() { - if (!logToFileEnabled) + if (!logToFileEnabled) { return; + } logToFileEnabled = false; fileStream << "Log session closed at " << QDateTime::currentDateTime().toString() << Qt::endl; diff --git a/cockatrice/src/interface/pixel_map_generator.cpp b/cockatrice/src/interface/pixel_map_generator.cpp index 382fff317..d3b0252a6 100644 --- a/cockatrice/src/interface/pixel_map_generator.cpp +++ b/cockatrice/src/interface/pixel_map_generator.cpp @@ -77,8 +77,9 @@ QMap PhasePixmapGenerator::pmCache; QPixmap PhasePixmapGenerator::generatePixmap(int height, QString name) { QString key = name + QString::number(height); - if (pmCache.contains(key)) + if (pmCache.contains(key)) { return pmCache.value(key); + } QPixmap pixmap = tryLoadImage("theme:phases/" + name, QSize(height, height)); @@ -95,19 +96,22 @@ QPixmap CounterPixmapGenerator::generatePixmap(int height, QString name, bool hi name = "general"; } - if (highlight) + if (highlight) { name.append("_highlight"); + } QString key = name + QString::number(height); - if (pmCache.contains(key)) + if (pmCache.contains(key)) { return pmCache.value(key); + } QPixmap pixmap = tryLoadImage("theme:counters/" + name, QSize(height, height)); // fall back to colorless counter if the name can't be found if (pixmap.isNull()) { name = "general"; - if (highlight) + if (highlight) { name.append("_highlight"); + } pixmap = tryLoadImage("theme:counters/" + name, QSize(height, height)); } @@ -118,17 +122,19 @@ QPixmap CounterPixmapGenerator::generatePixmap(int height, QString name, bool hi QPixmap PingPixmapGenerator::generatePixmap(int size, int value, int max) { int key = size * 1000000 + max * 1000 + value; - if (pmCache.contains(key)) + if (pmCache.contains(key)) { return pmCache.value(key); + } QPixmap pixmap(size, size); pixmap.fill(Qt::transparent); QPainter painter(&pixmap); QColor color; - if ((max == -1) || (value == -1)) + if ((max == -1) || (value == -1)) { color = Qt::black; - else + } else { color.setHsv(120 * (1.0 - ((double)value / max)), 255, 255); + } QRadialGradient g(QPointF((double)pixmap.width() / 2, (double)pixmap.height() / 2), qMin(pixmap.width(), pixmap.height()) / 2.0); @@ -145,11 +151,13 @@ QMap PingPixmapGenerator::pmCache; QPixmap CountryPixmapGenerator::generatePixmap(int height, const QString &countryCode) { - if (countryCode.size() != 2) + if (countryCode.size() != 2) { return QPixmap(); + } QString key = countryCode + QString::number(height); - if (pmCache.contains(key)) + if (pmCache.contains(key)) { return pmCache.value(key); + } int width = height * 2; QPixmap pixmap = tryLoadImage("theme:countries/" + countryCode.toLower(), QSize(width, height), true); @@ -352,8 +360,9 @@ QPixmap LockPixmapGenerator::generatePixmap(int height) { int key = height; - if (pmCache.contains(key)) + if (pmCache.contains(key)) { return pmCache.value(key); + } QPixmap pixmap = tryLoadImage("theme:icons/lock", QSize(height, height), true); pmCache.insert(key, pixmap); @@ -365,8 +374,9 @@ QMap LockPixmapGenerator::pmCache; QPixmap DropdownIconPixmapGenerator::generatePixmap(int height, bool expanded) { QString key = QString::number(expanded) + ":" + QString::number(height); - if (pmCache.contains(key)) + if (pmCache.contains(key)) { return pmCache.value(key); + } QString name = expanded ? "dropdown_expanded" : "dropdown_collapsed"; QPixmap pixmap = tryLoadImage("theme:icons/" + name, QSize(height, height), true); diff --git a/cockatrice/src/interface/theme_manager.cpp b/cockatrice/src/interface/theme_manager.cpp index c7f259ec0..58fb62362 100644 --- a/cockatrice/src/interface/theme_manager.cpp +++ b/cockatrice/src/interface/theme_manager.cpp @@ -51,8 +51,9 @@ struct PaletteColorInfo // Iterate through all color roles (excluding NoRole and NColorRoles) for (int r = 0; r < QPalette::NColorRoles; ++r) { auto role = static_cast(r); - if (role == QPalette::NoRole) + if (role == QPalette::NoRole) { continue; + } PaletteColorInfo info; info.group = group; @@ -78,8 +79,9 @@ struct PaletteColorInfo for (int r = 0; r < QPalette::NColorRoles; ++r) { auto role = static_cast(r); - if (role == QPalette::NoRole) + if (role == QPalette::NoRole) { continue; + } QColor color = palette.color(group, role); qInfo().nospace() << qPrintable(QString("%1").arg(roleEnum.valueToKey(role), -20)) << " : " diff --git a/cockatrice/src/interface/widgets/cards/card_group_display_widgets/card_group_display_widget.cpp b/cockatrice/src/interface/widgets/cards/card_group_display_widgets/card_group_display_widget.cpp index fa304816f..5fb0cb343 100644 --- a/cockatrice/src/interface/widgets/cards/card_group_display_widgets/card_group_display_widget.cpp +++ b/cockatrice/src/interface/widgets/cards/card_group_display_widgets/card_group_display_widget.cpp @@ -95,8 +95,9 @@ void CardGroupDisplayWidget::onSelectionChanged(const QItemSelection &selected, for (auto &range : deselected) { for (int row = range.top(); row <= range.bottom(); ++row) { QModelIndex idx = range.model()->index(row, 0, range.parent()); - if (proxyModel) + if (proxyModel) { idx = proxyModel->mapToSource(idx); + } auto it = indexToWidgetMap.find(QPersistentModelIndex(idx)); if (it != indexToWidgetMap.end()) { diff --git a/cockatrice/src/interface/widgets/cards/card_info_display_widget.cpp b/cockatrice/src/interface/widgets/cards/card_info_display_widget.cpp index 4930fbbfd..509a2d92f 100644 --- a/cockatrice/src/interface/widgets/cards/card_info_display_widget.cpp +++ b/cockatrice/src/interface/widgets/cards/card_info_display_widget.cpp @@ -43,11 +43,13 @@ CardInfoDisplayWidget::CardInfoDisplayWidget(const CardRef &cardRef, QWidget *pa void CardInfoDisplayWidget::setCard(const ExactCard &card) { - if (exactCard) + if (exactCard) { disconnect(exactCard.getCardPtr().data(), nullptr, this, nullptr); + } exactCard = card; - if (exactCard) + if (exactCard) { connect(exactCard.getCardPtr().data(), &QObject::destroyed, this, &CardInfoDisplayWidget::clear); + } text->setCard(exactCard); pic->setCard(exactCard); diff --git a/cockatrice/src/interface/widgets/cards/card_info_text_widget.cpp b/cockatrice/src/interface/widgets/cards/card_info_text_widget.cpp index f5f343807..345eb9909 100644 --- a/cockatrice/src/interface/widgets/cards/card_info_text_widget.cpp +++ b/cockatrice/src/interface/widgets/cards/card_info_text_widget.cpp @@ -73,8 +73,9 @@ void CardInfoTextWidget::setCard(const ExactCard &exactCard) QStringList cardProps = card->getProperties(); for (const QString &key : cardProps) { - if (key.contains("-")) + if (key.contains("-")) { continue; + } QString keyText = Mtg::getNicePropertyName(key).toHtmlEscaped() + ":"; text += QString("%1%2").arg(keyText, card->getProperty(key).toHtmlEscaped()); diff --git a/cockatrice/src/interface/widgets/deck_analytics/analytics_panel_widget_factory.cpp b/cockatrice/src/interface/widgets/deck_analytics/analytics_panel_widget_factory.cpp index 7af641689..e807e9d47 100644 --- a/cockatrice/src/interface/widgets/deck_analytics/analytics_panel_widget_factory.cpp +++ b/cockatrice/src/interface/widgets/deck_analytics/analytics_panel_widget_factory.cpp @@ -17,8 +17,9 @@ AbstractAnalyticsPanelWidget * AnalyticsPanelWidgetFactory::create(const QString &type, QWidget *parent, DeckListStatisticsAnalyzer *analyzer) const { auto it = widgets.find(type); - if (it == widgets.end()) + if (it == widgets.end()) { return nullptr; + } auto w = it->creator(parent, analyzer); diff --git a/cockatrice/src/interface/widgets/deck_analytics/analyzer_modules/mana_base/mana_base_config_dialog.cpp b/cockatrice/src/interface/widgets/deck_analytics/analyzer_modules/mana_base/mana_base_config_dialog.cpp index 3317486ea..83e35d57d 100644 --- a/cockatrice/src/interface/widgets/deck_analytics/analyzer_modules/mana_base/mana_base_config_dialog.cpp +++ b/cockatrice/src/interface/widgets/deck_analytics/analyzer_modules/mana_base/mana_base_config_dialog.cpp @@ -28,8 +28,9 @@ ManaBaseConfigDialog::ManaBaseConfigDialog(DeckListStatisticsAnalyzer *analyzer, // select initial filters for (int i = 0; i < filterList->count(); ++i) { - if (config.filters.contains(filterList->item(i)->text())) + if (config.filters.contains(filterList->item(i)->text())) { filterList->item(i)->setSelected(true); + } } buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this); diff --git a/cockatrice/src/interface/widgets/deck_analytics/analyzer_modules/mana_curve/mana_curve_config_dialog.cpp b/cockatrice/src/interface/widgets/deck_analytics/analyzer_modules/mana_curve/mana_curve_config_dialog.cpp index 38199656c..9e9ae98a6 100644 --- a/cockatrice/src/interface/widgets/deck_analytics/analyzer_modules/mana_curve/mana_curve_config_dialog.cpp +++ b/cockatrice/src/interface/widgets/deck_analytics/analyzer_modules/mana_curve/mana_curve_config_dialog.cpp @@ -69,8 +69,9 @@ void ManaCurveConfigDialog::setFromConfig(const ManaCurveConfig &cfg) { groupBy->setCurrentText(cfg.groupBy); // restore filters - for (int i = 0; i < filterList->count(); ++i) + for (int i = 0; i < filterList->count(); ++i) { filterList->item(i)->setSelected(cfg.filters.contains(filterList->item(i)->text())); + } showMain->setChecked(cfg.showMain); showCatRows->setChecked(cfg.showCategoryRows); @@ -81,8 +82,9 @@ void ManaCurveConfigDialog::accept() cfg.groupBy = groupBy->currentText(); cfg.filters.clear(); - for (auto *item : filterList->selectedItems()) + for (auto *item : filterList->selectedItems()) { cfg.filters << item->text(); + } cfg.showMain = showMain->isChecked(); cfg.showCategoryRows = showCatRows->isChecked(); diff --git a/cockatrice/src/interface/widgets/deck_analytics/analyzer_modules/mana_curve/mana_curve_total_widget.cpp b/cockatrice/src/interface/widgets/deck_analytics/analyzer_modules/mana_curve/mana_curve_total_widget.cpp index f059ff873..c04767015 100644 --- a/cockatrice/src/interface/widgets/deck_analytics/analyzer_modules/mana_curve/mana_curve_total_widget.cpp +++ b/cockatrice/src/interface/widgets/deck_analytics/analyzer_modules/mana_curve/mana_curve_total_widget.cpp @@ -51,15 +51,17 @@ void ManaCurveTotalWidget::updateDisplay(const QString &categoryName, for (auto it = cmcIt->cbegin(); it != cmcIt->cend(); ++it) { const QString &category = it.key(); - if (!config.filters.isEmpty() && !config.filters.contains(category)) + if (!config.filters.isEmpty() && !config.filters.contains(category)) { continue; + } const int value = it.value(); QStringList cards; const auto catIt = cardsMap.constFind(category); - if (catIt != cardsMap.cend()) + if (catIt != cardsMap.cend()) { cards = catIt->value(cmc); + } segments.push_back({category, value, cards, GameSpecificColors::MTG::colorHelper(category)}); } diff --git a/cockatrice/src/interface/widgets/deck_analytics/analyzer_modules/mana_curve/mana_curve_widget.cpp b/cockatrice/src/interface/widgets/deck_analytics/analyzer_modules/mana_curve/mana_curve_widget.cpp index e09ecfe87..b182bf954 100644 --- a/cockatrice/src/interface/widgets/deck_analytics/analyzer_modules/mana_curve/mana_curve_widget.cpp +++ b/cockatrice/src/interface/widgets/deck_analytics/analyzer_modules/mana_curve/mana_curve_widget.cpp @@ -69,16 +69,18 @@ static void buildMapsByCategory(const QHash> &categoryC const QString &category = catIt.key(); const auto &countsByCmc = catIt.value(); - for (auto it = countsByCmc.cbegin(); it != countsByCmc.cend(); ++it) + for (auto it = countsByCmc.cbegin(); it != countsByCmc.cend(); ++it) { outCmcMap[it.key()][category] = it.value(); + } } for (auto catIt = categoryCards.cbegin(); catIt != categoryCards.cend(); ++catIt) { const QString &category = catIt.key(); const auto &cardsByCmc = catIt.value(); - for (auto it = cardsByCmc.cbegin(); it != cardsByCmc.cend(); ++it) + for (auto it = cardsByCmc.cbegin(); it != cardsByCmc.cend(); ++it) { outCardsMap[category][it.key()] = it.value(); + } } } @@ -88,8 +90,9 @@ static void findGlobalCmcRange(const QHash> &categoryCo maxCmc = 0; for (const auto &countsByCmc : categoryCounts) { - for (auto it = countsByCmc.cbegin(); it != countsByCmc.cend(); ++it) + for (auto it = countsByCmc.cbegin(); it != countsByCmc.cend(); ++it) { maxCmc = qMax(maxCmc, it.key()); + } } } diff --git a/cockatrice/src/interface/widgets/deck_analytics/analyzer_modules/mana_devotion/mana_devotion_config_dialog.cpp b/cockatrice/src/interface/widgets/deck_analytics/analyzer_modules/mana_devotion/mana_devotion_config_dialog.cpp index 80fd03928..b01c33ba5 100644 --- a/cockatrice/src/interface/widgets/deck_analytics/analyzer_modules/mana_devotion/mana_devotion_config_dialog.cpp +++ b/cockatrice/src/interface/widgets/deck_analytics/analyzer_modules/mana_devotion/mana_devotion_config_dialog.cpp @@ -26,8 +26,9 @@ ManaDevotionConfigDialog::ManaDevotionConfigDialog(DeckListStatisticsAnalyzer *a // select initial filters for (int i = 0; i < filterList->count(); ++i) { - if (config.filters.contains(filterList->item(i)->text())) + if (config.filters.contains(filterList->item(i)->text())) { filterList->item(i)->setSelected(true); + } } buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this); diff --git a/cockatrice/src/interface/widgets/deck_analytics/analyzer_modules/mana_distribution/mana_distribution_config.cpp b/cockatrice/src/interface/widgets/deck_analytics/analyzer_modules/mana_distribution/mana_distribution_config.cpp index f70f32d5b..01af9329c 100644 --- a/cockatrice/src/interface/widgets/deck_analytics/analyzer_modules/mana_distribution/mana_distribution_config.cpp +++ b/cockatrice/src/interface/widgets/deck_analytics/analyzer_modules/mana_distribution/mana_distribution_config.cpp @@ -24,8 +24,9 @@ ManaDistributionConfig ManaDistributionConfig::fromJson(const QJsonObject &o) if (o.contains("filters")) { config.filters.clear(); - for (auto v : o["filters"].toArray()) + for (auto v : o["filters"].toArray()) { config.filters << v.toString(); + } } if (o.contains("showColorRows")) { diff --git a/cockatrice/src/interface/widgets/deck_analytics/analyzer_modules/mana_distribution/mana_distribution_config_dialog.cpp b/cockatrice/src/interface/widgets/deck_analytics/analyzer_modules/mana_distribution/mana_distribution_config_dialog.cpp index 7fe4d94e4..325c70028 100644 --- a/cockatrice/src/interface/widgets/deck_analytics/analyzer_modules/mana_distribution/mana_distribution_config_dialog.cpp +++ b/cockatrice/src/interface/widgets/deck_analytics/analyzer_modules/mana_distribution/mana_distribution_config_dialog.cpp @@ -62,8 +62,9 @@ void ManaDistributionConfigDialog::setFromConfig(const ManaDistributionConfig &c displayType->setCurrentText(cfg.displayType); - for (int i = 0; i < filterList->count(); ++i) + for (int i = 0; i < filterList->count(); ++i) { filterList->item(i)->setSelected(cfg.filters.contains(filterList->item(i)->text())); + } showColorRows->setChecked(cfg.showColorRows); } @@ -74,8 +75,9 @@ void ManaDistributionConfigDialog::accept() // Filters cfg.filters.clear(); - for (auto *item : filterList->selectedItems()) + for (auto *item : filterList->selectedItems()) { cfg.filters << item->text(); + } cfg.showColorRows = showColorRows->isChecked(); diff --git a/cockatrice/src/interface/widgets/deck_analytics/deck_list_statistics_analyzer.cpp b/cockatrice/src/interface/widgets/deck_analytics/deck_list_statistics_analyzer.cpp index 073b6d25c..add13ff21 100644 --- a/cockatrice/src/interface/widgets/deck_analytics/deck_list_statistics_analyzer.cpp +++ b/cockatrice/src/interface/widgets/deck_analytics/deck_list_statistics_analyzer.cpp @@ -191,10 +191,12 @@ double DeckListStatisticsAnalyzer::hypergeometric(int N, int K, int n, int k) } auto choose = [](int n, int r) -> double { - if (r > n) + if (r > n) { return 0.0; - if (r == 0 || r == n) + } + if (r == 0 || r == n) { return 1.0; + } double res = 1.0; for (int i = 1; i <= r; ++i) { res *= (n - r + i); diff --git a/cockatrice/src/interface/widgets/deck_editor/deck_editor_database_display_widget.cpp b/cockatrice/src/interface/widgets/deck_editor/deck_editor_database_display_widget.cpp index 20eef180a..580db67f4 100644 --- a/cockatrice/src/interface/widgets/deck_editor/deck_editor_database_display_widget.cpp +++ b/cockatrice/src/interface/widgets/deck_editor/deck_editor_database_display_widget.cpp @@ -121,9 +121,10 @@ void DeckEditorDatabaseDisplayWidget::updateSearch(const QString &search) { databaseDisplayModel->setStringFilter(search); QModelIndexList sel = databaseView->selectionModel()->selectedRows(); - if (sel.isEmpty() && databaseDisplayModel->rowCount()) + if (sel.isEmpty() && databaseDisplayModel->rowCount()) { databaseView->selectionModel()->setCurrentIndex(databaseDisplayModel->index(0, 0), QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows); + } } void DeckEditorDatabaseDisplayWidget::clearAllDatabaseFilters() diff --git a/cockatrice/src/interface/widgets/deck_editor/deck_editor_deck_dock_widget.cpp b/cockatrice/src/interface/widgets/deck_editor/deck_editor_deck_dock_widget.cpp index f939ae99d..25d9db079 100644 --- a/cockatrice/src/interface/widgets/deck_editor/deck_editor_deck_dock_widget.cpp +++ b/cockatrice/src/interface/widgets/deck_editor/deck_editor_deck_dock_widget.cpp @@ -314,8 +314,9 @@ void DeckEditorDeckDockWidget::initializeFormats() ExactCard DeckEditorDeckDockWidget::getCurrentCard() { QModelIndex current = deckView->selectionModel()->currentIndex(); - if (!current.isValid()) + if (!current.isValid()) { return {}; + } const QString cardName = current.siblingAtColumn(DeckListModelColumns::CARD_NAME).data().toString(); const QString cardProviderID = current.siblingAtColumn(DeckListModelColumns::CARD_PROVIDER_ID).data().toString(); const QModelIndex gparent = current.parent().parent(); @@ -651,10 +652,12 @@ void DeckEditorDeckDockWidget::actSwapSelection() void DeckEditorDeckDockWidget::actDecrementCard(const ExactCard &card, QString zoneName) { - if (!card) + if (!card) { return; - if (card.getInfo().getIsToken()) + } + if (card.getInfo().getIsToken()) { zoneName = DECK_ZONE_TOKENS; + } deckStateManager->decrementCard(card, zoneName); } diff --git a/cockatrice/src/interface/widgets/deck_editor/deck_editor_filter_dock_widget.cpp b/cockatrice/src/interface/widgets/deck_editor/deck_editor_filter_dock_widget.cpp index 8a9a6cdaa..6b18db82e 100644 --- a/cockatrice/src/interface/widgets/deck_editor/deck_editor_filter_dock_widget.cpp +++ b/cockatrice/src/interface/widgets/deck_editor/deck_editor_filter_dock_widget.cpp @@ -89,8 +89,9 @@ void DeckEditorFilterDockWidget::filterViewCustomContextMenu(const QPoint &point QModelIndex idx; idx = filterView->indexAt(point); - if (!idx.isValid()) + if (!idx.isValid()) { return; + } action = menu.addAction(QString("delete")); action->setData(point); @@ -105,8 +106,9 @@ void DeckEditorFilterDockWidget::filterRemove(const QAction *action) point = action->data().toPoint(); idx = filterView->indexAt(point); - if (!idx.isValid()) + if (!idx.isValid()) { return; + } filterModel->removeRow(idx.row(), idx.parent()); } diff --git a/cockatrice/src/interface/widgets/deck_editor/deck_list_style_proxy.cpp b/cockatrice/src/interface/widgets/deck_editor/deck_list_style_proxy.cpp index 14c5faae7..e41529b22 100644 --- a/cockatrice/src/interface/widgets/deck_editor/deck_list_style_proxy.cpp +++ b/cockatrice/src/interface/widgets/deck_editor/deck_list_style_proxy.cpp @@ -8,8 +8,9 @@ QVariant DeckListStyleProxy::data(const QModelIndex &index, int role) const { QModelIndex src = mapToSource(index); - if (!src.isValid()) + if (!src.isValid()) { return {}; + } QVariant value = QIdentityProxyModel::data(index, role); diff --git a/cockatrice/src/interface/widgets/deck_editor/deck_state_manager.cpp b/cockatrice/src/interface/widgets/deck_editor/deck_state_manager.cpp index 8da27b63c..6db8e5623 100644 --- a/cockatrice/src/interface/widgets/deck_editor/deck_state_manager.cpp +++ b/cockatrice/src/interface/widgets/deck_editor/deck_state_manager.cpp @@ -192,8 +192,9 @@ QModelIndex DeckStateManager::addCard(const ExactCard &card, const QString &zone QModelIndex DeckStateManager::decrementCard(const ExactCard &card, const QString &zoneName) { - if (!card) + if (!card) { return {}; + } QString providerId = card.getPrinting().getUuid(); QString collectorNumber = card.getPrinting().getProperty("num"); @@ -241,15 +242,17 @@ static bool doSwapCard(DeckListModel *model, bool DeckStateManager::swapCardAtIndex(const QModelIndex &idx) { - if (!idx.isValid()) + if (!idx.isValid()) { return false; + } QString cardName = idx.siblingAtColumn(DeckListModelColumns::CARD_NAME).data().toString(); QString providerId = idx.siblingAtColumn(DeckListModelColumns::CARD_PROVIDER_ID).data().toString(); QModelIndex gparent = idx.parent().parent(); - if (!gparent.isValid()) + if (!gparent.isValid()) { return false; + } QString zoneName = gparent.siblingAtColumn(DeckListModelColumns::CARD_NAME).data(Qt::EditRole).toString(); QString otherZoneName = zoneName == DECK_ZONE_MAIN ? DECK_ZONE_SIDE : DECK_ZONE_MAIN; diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_connect.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_connect.cpp index 0bb0eb1c9..fdbc90542 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_connect.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_connect.cpp @@ -261,13 +261,7 @@ void DlgConnect::updateDisplayInfo(const QString &saveName) QStringList _data = uci.getServerInfo(saveName); if (_data.isEmpty()) { - _data << "" - << "" - << "" - << "" - << "" - << "" - << ""; + _data << "" << "" << "" << "" << "" << "" << ""; } bool savePasswordStatus = (_data.at(5) == "1"); diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_create_game.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_create_game.cpp index 7f109f600..30364f242 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_create_game.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_create_game.cpp @@ -215,8 +215,9 @@ DlgCreateGame::DlgCreateGame(const ServerInfo_Game &gameInfo, const QMapsetChecked(gameInfo.spectators_omniscient()); QSet types; - for (int i = 0; i < gameInfo.game_types_size(); ++i) + for (int i = 0; i < gameInfo.game_types_size(); ++i) { types.insert(gameInfo.game_types(i)); + } QMapIterator gameTypeIterator(gameTypes); while (gameTypeIterator.hasNext()) { @@ -316,9 +317,9 @@ void DlgCreateGame::checkResponse(const Response &response) { buttonBox->setEnabled(true); - if (response.response_code() == Response::RespOk) + if (response.response_code() == Response::RespOk) { accept(); - else { + } else { QMessageBox::critical(this, tr("Error"), tr("Server error.")); return; } diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_default_tags_editor.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_default_tags_editor.cpp index 349f4ca4c..2d6ee7909 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_default_tags_editor.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_default_tags_editor.cpp @@ -95,8 +95,9 @@ void DlgDefaultTagsEditor::addItem() // Prevent duplicate tags for (int i = 0; i < listWidget->count(); ++i) { QWidget *widget = listWidget->itemWidget(listWidget->item(i)); - if (!widget) + if (!widget) { continue; + } QLineEdit *lineEdit = widget->findChild(); if (lineEdit && lineEdit->text() == newTag) { QMessageBox::warning(this, tr("Duplicate Tag"), tr("This tag already exists.")); @@ -138,8 +139,9 @@ void DlgDefaultTagsEditor::confirmChanges() QStringList updatedList; for (int i = 0; i < listWidget->count(); ++i) { QWidget *widget = listWidget->itemWidget(listWidget->item(i)); - if (!widget) + if (!widget) { continue; + } QLineEdit *lineEdit = widget->findChild(); if (lineEdit) { updatedList.append(lineEdit->text()); diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_edit_tokens.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_edit_tokens.cpp index fe9cd181c..381aa2b11 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_edit_tokens.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_edit_tokens.cpp @@ -149,8 +149,9 @@ void DlgEditTokens::actAddToken() QString name; for (;;) { name = getTextWithMax(this, tr("Add token"), tr("Please enter the name of the token:")); - if (name.isEmpty()) + if (name.isEmpty()) { return; + } if (databaseModel->getDatabase()->query()->getCardInfo(name)) { QMessageBox::critical(this, tr("Error"), tr("The chosen name conflicts with an existing card or token.\nMake sure to enable " @@ -181,18 +182,21 @@ void DlgEditTokens::actRemoveToken() void DlgEditTokens::colorChanged(int colorIndex) { - if (currentCard) + if (currentCard) { currentCard->setColors(QString(colorEdit->itemData(colorIndex).toChar())); + } } void DlgEditTokens::ptChanged(const QString &_pt) { - if (currentCard) + if (currentCard) { currentCard->setPowTough(_pt); + } } void DlgEditTokens::annotationChanged(const QString &_annotation) { - if (currentCard) + if (currentCard) { currentCard->setText(_annotation); + } } diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_edit_user.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_edit_user.cpp index dcfbc91e9..7015f9d47 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_edit_user.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_edit_user.cpp @@ -26,8 +26,9 @@ DlgEditUser::DlgEditUser(QWidget *parent, QString email, QString country, QStrin int i = 1; for (const QString &c : countries) { countryEdit->addItem(QPixmap("theme:countries/" + c.toLower()), c); - if (c == country) + if (c == country) { countryEdit->setCurrentIndex(i); + } ++i; } diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_filter_games.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_filter_games.cpp index 043b7a1cd..8f498cc2c 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_filter_games.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_filter_games.cpp @@ -87,8 +87,9 @@ DlgFilterGames::DlgFilterGames(const QMap &_allGameTypes, if (!allGameTypes.isEmpty()) { gameTypeFilterGroupBox = new QGroupBox(tr("&Game types")); gameTypeFilterGroupBox->setLayout(gameTypeFilterLayout); - } else + } else { gameTypeFilterGroupBox = nullptr; + } auto *maxPlayersFilterMinLabel = new QLabel(tr("at &least:")); maxPlayersFilterMinSpinBox = new QSpinBox; @@ -226,8 +227,9 @@ QSet DlgFilterGames::getGameTypeFilter() const QMapIterator i(gameTypeFilterCheckBoxes); while (i.hasNext()) { i.next(); - if (i.value()->isChecked()) + if (i.value()->isChecked()) { result.insert(i.key()); + } } return result; } diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_manage_sets.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_manage_sets.cpp index 6c46c7faf..c693fb02e 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_manage_sets.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_manage_sets.cpp @@ -217,8 +217,9 @@ void WndSets::saveHeaderState() void WndSets::rebuildMainLayout(int actionToTake) { - if (mainLayout == nullptr) + if (mainLayout == nullptr) { return; + } switch (actionToTake) { case NO_SETS_SELECTED: @@ -382,12 +383,14 @@ void WndSets::actUp() std::sort(rows.begin(), rows.end(), std::less()); QSet newRows; - if (rows.empty()) + if (rows.empty()) { return; + } for (auto i : rows) { - if (i.row() <= 0) + if (i.row() <= 0) { continue; + } int oldRow = displayModel->mapToSource(i).row(); int newRow = i.row() - 1; @@ -405,12 +408,14 @@ void WndSets::actDown() std::sort(rows.begin(), rows.end(), [](const QModelIndex &a, const QModelIndex &b) { return b < a; }); QSet newRows; - if (rows.empty()) + if (rows.empty()) { return; + } for (auto i : rows) { - if (i.row() >= displayModel->rowCount() - 1) + if (i.row() >= displayModel->rowCount() - 1) { continue; + } int oldRow = displayModel->mapToSource(i).row(); int newRow = i.row() + 1; @@ -428,8 +433,9 @@ void WndSets::actTop() QSet newRows; int newRow = 0; - if (rows.empty()) + if (rows.empty()) { return; + } for (int i = 0; i < rows.length(); i++) { int oldRow = displayModel->mapToSource(rows.at(i)).row(); @@ -454,8 +460,9 @@ void WndSets::actBottom() QSet newRows; int newRow = model->rowCount() - 1; - if (rows.empty()) + if (rows.empty()) { return; + } for (int i = 0; i < rows.length(); i++) { int oldRow = displayModel->mapToSource(rows.at(i)).row(); diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_register.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_register.cpp index a3f232d9b..7b84a9a06 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_register.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_register.cpp @@ -311,8 +311,9 @@ DlgRegister::DlgRegister(QWidget *parent) : QDialog(parent) countryEdit->addItem(QPixmap("theme:countries/zw"), "zw"); countryEdit->setCurrentIndex(0); QStringList countries = SettingsCache::instance().getCountries(); - for (const QString &c : countries) + for (const QString &c : countries) { countryEdit->addItem(QPixmap("theme:countries/" + c.toLower()), c); + } realnameLabel = new QLabel(tr("Real name:")); realnameEdit = new QLineEdit(); diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_select_set_for_cards.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_select_set_for_cards.cpp index 5d9e2679c..bc846bf3d 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_select_set_for_cards.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_select_set_for_cards.cpp @@ -237,8 +237,9 @@ QMap DlgSelectSetForCards::getSetsForCards() for (auto cardName : cardNames) { CardInfoPtr infoPtr = CardDatabaseManager::query()->getCardInfo(cardName); - if (!infoPtr) + if (!infoPtr) { continue; + } SetToPrintingsMap setMap = infoPtr->getSets(); for (auto &setName : setMap.keys()) { @@ -359,8 +360,9 @@ QMap DlgSelectSetForCards::getCardsForSets() for (auto cardName : cardNames) { CardInfoPtr infoPtr = CardDatabaseManager::query()->getCardInfo(cardName); - if (!infoPtr) + if (!infoPtr) { continue; + } SetToPrintingsMap setMap = infoPtr->getSets(); for (auto it = setMap.begin(); it != setMap.end(); ++it) { diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_settings.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_settings.cpp index 6238bc80b..d6b5aa213 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_settings.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_settings.cpp @@ -272,8 +272,9 @@ QString GeneralSettingsPage::languageName(const QString &lang) void GeneralSettingsPage::deckPathButtonClicked() { QString path = QFileDialog::getExistingDirectory(this, tr("Choose path"), deckPathEdit->text()); - if (path.isEmpty()) + if (path.isEmpty()) { return; + } deckPathEdit->setText(path); SettingsCache::instance().setDeckPath(path); @@ -282,8 +283,9 @@ void GeneralSettingsPage::deckPathButtonClicked() void GeneralSettingsPage::filtersPathButtonClicked() { QString path = QFileDialog::getExistingDirectory(this, tr("Choose path"), filtersPathEdit->text()); - if (path.isEmpty()) + if (path.isEmpty()) { return; + } filtersPathEdit->setText(path); SettingsCache::instance().setFiltersPath(path); @@ -292,8 +294,9 @@ void GeneralSettingsPage::filtersPathButtonClicked() void GeneralSettingsPage::replaysPathButtonClicked() { QString path = QFileDialog::getExistingDirectory(this, tr("Choose path"), replaysPathEdit->text()); - if (path.isEmpty()) + if (path.isEmpty()) { return; + } replaysPathEdit->setText(path); SettingsCache::instance().setReplaysPath(path); @@ -302,8 +305,9 @@ void GeneralSettingsPage::replaysPathButtonClicked() void GeneralSettingsPage::picsPathButtonClicked() { QString path = QFileDialog::getExistingDirectory(this, tr("Choose path"), picsPathEdit->text()); - if (path.isEmpty()) + if (path.isEmpty()) { return; + } picsPathEdit->setText(path); SettingsCache::instance().setPicsPath(path); @@ -312,8 +316,9 @@ void GeneralSettingsPage::picsPathButtonClicked() void GeneralSettingsPage::cardDatabasePathButtonClicked() { QString path = QFileDialog::getOpenFileName(this, tr("Choose path"), cardDatabasePathEdit->text()); - if (path.isEmpty()) + if (path.isEmpty()) { return; + } cardDatabasePathEdit->setText(path); SettingsCache::instance().setCardDatabasePath(path); @@ -322,8 +327,9 @@ void GeneralSettingsPage::cardDatabasePathButtonClicked() void GeneralSettingsPage::customCardDatabaseButtonClicked() { QString path = QFileDialog::getExistingDirectory(this, tr("Choose path"), customCardDatabasePathEdit->text()); - if (path.isEmpty()) + if (path.isEmpty()) { return; + } customCardDatabasePathEdit->setText(path); SettingsCache::instance().setCustomCardDatabasePath(path); @@ -332,8 +338,9 @@ void GeneralSettingsPage::customCardDatabaseButtonClicked() void GeneralSettingsPage::tokenDatabasePathButtonClicked() { QString path = QFileDialog::getOpenFileName(this, tr("Choose path"), tokenDatabasePathEdit->text()); - if (path.isEmpty()) + if (path.isEmpty()) { return; + } tokenDatabasePathEdit->setText(path); SettingsCache::instance().setTokenDatabasePath(path); @@ -418,8 +425,9 @@ AppearanceSettingsPage::AppearanceSettingsPage() QStringList themeDirs = themeManager->getAvailableThemes().keys(); for (int i = 0; i < themeDirs.size(); i++) { themeBox.addItem(themeDirs[i]); - if (themeDirs[i] == themeName) + if (themeDirs[i] == themeName) { themeBox.setCurrentIndex(i); + } } connect(&themeBox, qOverload(&QComboBox::currentIndexChanged), this, &AppearanceSettingsPage::themeBoxChanged); @@ -560,8 +568,9 @@ AppearanceSettingsPage::AppearanceSettingsPage() auto &cardCounterSettings = SettingsCache::instance().cardCounters(); auto newColor = QColorDialog::getColor(cardCounterSettings.color(index), this); - if (!newColor.isValid()) + if (!newColor.isValid()) { return; + } cardCounterSettings.setColor(index, newColor); }); @@ -643,8 +652,9 @@ AppearanceSettingsPage::AppearanceSettingsPage() void AppearanceSettingsPage::themeBoxChanged(int index) { QStringList themeDirs = themeManager->getAvailableThemes().keys(); - if (index >= 0 && index < themeDirs.count()) + if (index >= 0 && index < themeDirs.count()) { SettingsCache::instance().setThemeName(themeDirs.at(index)); + } } void AppearanceSettingsPage::openThemeLocation() @@ -1395,8 +1405,9 @@ MessagesSettingsPage::MessagesSettingsPage() messageList = new QListWidget; int count = SettingsCache::instance().messages().getCount(); - for (int i = 0; i < count; i++) + for (int i = 0; i < count; i++) { messageList->addItem(SettingsCache::instance().messages().getMessageAt(i)); + } aAdd = new QAction(this); aAdd->setIcon(QPixmap("theme:icons/increment")); @@ -1496,8 +1507,9 @@ void MessagesSettingsPage::updateHighlightPreview() void MessagesSettingsPage::storeSettings() { SettingsCache::instance().messages().setCount(messageList->count()); - for (int i = 0; i < messageList->count(); i++) + for (int i = 0; i < messageList->count(); i++) { SettingsCache::instance().messages().setMessageAt(i, messageList->item(i)->text()); + } emit SettingsCache::instance().messages().messageMacrosChanged(); } @@ -1570,8 +1582,9 @@ SoundSettingsPage::SoundSettingsPage() QStringList themeDirs = soundEngine->getAvailableThemes().keys(); for (int i = 0; i < themeDirs.size(); i++) { themeBox.addItem(themeDirs[i]); - if (themeDirs[i] == themeName) + if (themeDirs[i] == themeName) { themeBox.setCurrentIndex(i); + } } connect(&themeBox, qOverload(&QComboBox::currentIndexChanged), this, &SoundSettingsPage::themeBoxChanged); @@ -1619,8 +1632,9 @@ SoundSettingsPage::SoundSettingsPage() void SoundSettingsPage::themeBoxChanged(int index) { QStringList themeDirs = soundEngine->getAvailableThemes().keys(); - if (index >= 0 && index < themeDirs.count()) + if (index >= 0 && index < themeDirs.count()) { SettingsCache::instance().setSoundThemeName(themeDirs.at(index)); + } } void SoundSettingsPage::masterVolumeChanged(int value) @@ -1857,8 +1871,9 @@ void DlgSettings::createIcons() void DlgSettings::changePage(QListWidgetItem *current, QListWidgetItem *previous) { - if (!current) + if (!current) { current = previous; + } pagesWidget->setCurrentIndex(contentsWidget->row(current)); } diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_update.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_update.cpp index c9adeb270..417dcb3eb 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_update.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_update.cpp @@ -154,8 +154,9 @@ void DlgUpdate::finishedUpdateCheck(bool needToUpdate, bool isCompatible, Releas ")

    " + tr("Do you want to update now?"), QMessageBox::Yes | QMessageBox::No); - if (reply == QMessageBox::Yes) + if (reply == QMessageBox::Yes) { downloadUpdate(release->getName()); + } } else { QMessageBox::information( this, tr("Update Available"), diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_view_log.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_view_log.cpp index 3dd0fedb3..4eb054647 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_view_log.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_view_log.cpp @@ -60,8 +60,9 @@ void DlgViewLog::actCopyToClipboard() void DlgViewLog::loadInitialLogBuffer() { QList logBuffer = Logger::getInstance().getLogBuffer(); - for (const QString &message : logBuffer) + for (const QString &message : logBuffer) { appendLogEntry(message); + } } void DlgViewLog::appendLogEntry(const QString &message) diff --git a/cockatrice/src/interface/widgets/dialogs/tip_of_the_day.cpp b/cockatrice/src/interface/widgets/dialogs/tip_of_the_day.cpp index 94996e975..66170792a 100644 --- a/cockatrice/src/interface/widgets/dialogs/tip_of_the_day.cpp +++ b/cockatrice/src/interface/widgets/dialogs/tip_of_the_day.cpp @@ -73,8 +73,9 @@ TipsOfTheDay::~TipsOfTheDay() QVariant TipsOfTheDay::data(const QModelIndex &index, int /*role*/) const { - if (!index.isValid() || index.row() >= tipList->size() || index.column() >= TIPDDBMODEL_COLUMNS) + if (!index.isValid() || index.row() >= tipList->size() || index.column() >= TIPDDBMODEL_COLUMNS) { return QVariant(); + } TipOfTheDay tip = tipList->at(index.row()); switch (index.column()) { diff --git a/cockatrice/src/interface/widgets/general/background_sources.h b/cockatrice/src/interface/widgets/general/background_sources.h index 15bf1d377..04cafe830 100644 --- a/cockatrice/src/interface/widgets/general/background_sources.h +++ b/cockatrice/src/interface/widgets/general/background_sources.h @@ -40,8 +40,9 @@ public: static QString toId(Type type) { for (const auto &e : all()) { - if (e.type == type) + if (e.type == type) { return e.id; + } } return {}; } @@ -49,8 +50,9 @@ public: static Type fromId(const QString &id) { for (const auto &e : all()) { - if (id == e.id) + if (id == e.id) { return e.type; + } } return Theme; // default } @@ -58,8 +60,9 @@ public: static QString toDisplay(Type type) { for (const auto &e : all()) { - if (e.type == type) + if (e.type == type) { return QObject::tr(e.trKey); + } } return {}; } diff --git a/cockatrice/src/interface/widgets/general/display/charts/bars/bar_chart_widget.cpp b/cockatrice/src/interface/widgets/general/display/charts/bars/bar_chart_widget.cpp index 998808307..d9e108e6a 100644 --- a/cockatrice/src/interface/widgets/general/display/charts/bars/bar_chart_widget.cpp +++ b/cockatrice/src/interface/widgets/general/display/charts/bars/bar_chart_widget.cpp @@ -52,8 +52,9 @@ void BarChartWidget::paintEvent(QPaintEvent *) int barAreaWidth = right - left; int barCount = bars.size(); - if (barCount == 0) + if (barCount == 0) { return; + } int spacing = 6; int barWidth = (barAreaWidth - (barCount - 1) * spacing) / barCount; @@ -91,8 +92,9 @@ void BarChartWidget::paintEvent(QPaintEvent *) for (int j = 0; j < bar.segments.size(); j++) { const auto &seg = bar.segments[j]; int segHeight = (seg.value * barAreaHeight / highest); - if (segHeight < 2 && seg.value > 0) + if (segHeight < 2 && seg.value > 0) { segHeight = 2; + } int topY = yCurrent - segHeight; @@ -189,8 +191,9 @@ void BarChartWidget::mouseMoveEvent(QMouseEvent *e) for (int i = 0; i < segments.size(); i++) { const auto &seg = segments[i]; int segHeight = (seg.value * barAreaHeight / highest); - if (segHeight < 2 && seg.value > 0) + if (segHeight < 2 && seg.value > 0) { segHeight = 2; + } int topY = yCurrent - segHeight; int bottomY = yCurrent; diff --git a/cockatrice/src/interface/widgets/general/display/charts/bars/color_bar.cpp b/cockatrice/src/interface/widgets/general/display/charts/bars/color_bar.cpp index ed91ba03d..12ab5bb3b 100644 --- a/cockatrice/src/interface/widgets/general/display/charts/bars/color_bar.cpp +++ b/cockatrice/src/interface/widgets/general/display/charts/bars/color_bar.cpp @@ -26,16 +26,19 @@ QSize ColorBar::minimumSizeHint() const void ColorBar::paintEvent(QPaintEvent *) { - if (colors.isEmpty()) + if (colors.isEmpty()) { return; + } int total = 0; - for (const auto &pair : colors) + for (const auto &pair : colors) { total += pair.second; + } // Prevent divide-by-zero - if (total == 0) + if (total == 0) { return; + } QPainter p(this); p.setRenderHint(QPainter::Antialiasing, true); @@ -63,8 +66,9 @@ void ColorBar::paintEvent(QPaintEvent *) int segmentWidth = int(ratio * w); // Ensure the segment width is at least 1 to avoid degenerate rectangles - if (segmentWidth < 1) + if (segmentWidth < 1) { segmentWidth = 1; + } QColor base = colorFromName(key); @@ -100,8 +104,9 @@ void ColorBar::leaveEvent(QEvent *) void ColorBar::mouseMoveEvent(QMouseEvent *event) { - if (!isHovered || colors.isEmpty()) + if (!isHovered || colors.isEmpty()) { return; + } #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) int x = int(event->position().x()); @@ -112,18 +117,21 @@ void ColorBar::mouseMoveEvent(QMouseEvent *event) #endif QString text = tooltipForPosition(x); - if (!text.isEmpty()) + if (!text.isEmpty()) { QToolTip::showText(gp, text, this); + } } QString ColorBar::tooltipForPosition(int x) const { int total = 0; - for (const auto &pair : colors) + for (const auto &pair : colors) { total += pair.second; + } - if (total == 0) + if (total == 0) { return {}; + } int pos = 0; @@ -149,12 +157,14 @@ QColor ColorBar::colorFromName(const QString &name) const {"W", QColor(235, 235, 230)}, {"B", QColor(30, 30, 30)}, }; - if (map.contains(name)) + if (map.contains(name)) { return map[name]; + } QColor c(name); - if (!c.isValid()) + if (!c.isValid()) { c = Qt::gray; + } return c; } \ No newline at end of file diff --git a/cockatrice/src/interface/widgets/general/display/charts/bars/segmented_bar_widget.cpp b/cockatrice/src/interface/widgets/general/display/charts/bars/segmented_bar_widget.cpp index e027aabdd..9bad32bda 100644 --- a/cockatrice/src/interface/widgets/general/display/charts/bars/segmented_bar_widget.cpp +++ b/cockatrice/src/interface/widgets/general/display/charts/bars/segmented_bar_widget.cpp @@ -44,8 +44,9 @@ void SegmentedBarWidget::paintEvent(QPaintEvent *) const auto &seg = segments[i]; int segHeight = total > 0 ? (seg.value * barHeight / total) : 0; - if (segHeight < 2) + if (segHeight < 2) { segHeight = 2; + } QRect r(barX, yCurrent - segHeight, barWidth, segHeight); bool isTop = (i == segments.size() - 1); @@ -110,8 +111,9 @@ int SegmentedBarWidget::segmentAt(int y) const int top = currentTop - segHeight; int bottom = currentTop; - if (y >= top && y <= bottom) + if (y >= top && y <= bottom) { return i; + } currentTop -= segHeight; } diff --git a/cockatrice/src/interface/widgets/general/display/charts/pies/color_pie.cpp b/cockatrice/src/interface/widgets/general/display/charts/pies/color_pie.cpp index 84232b36f..b129fbe18 100644 --- a/cockatrice/src/interface/widgets/general/display/charts/pies/color_pie.cpp +++ b/cockatrice/src/interface/widgets/general/display/charts/pies/color_pie.cpp @@ -157,8 +157,9 @@ QString ColorPie::tooltipForPoint(const QPoint &pt) const QPointF v = pt - center; double distance = std::hypot(v.x(), v.y()); - if (distance > size / 2.0) + if (distance > size / 2.0) { return {}; + } double angle = std::atan2(-v.y(), v.x()) * 180.0 / M_PI; if (angle < 0) { diff --git a/cockatrice/src/interface/widgets/general/home_widget.cpp b/cockatrice/src/interface/widgets/general/home_widget.cpp index a87d69119..e1687f997 100644 --- a/cockatrice/src/interface/widgets/general/home_widget.cpp +++ b/cockatrice/src/interface/widgets/general/home_widget.cpp @@ -139,8 +139,9 @@ void HomeWidget::updateRandomCard() } break; } - if (!newCard) + if (!newCard) { return; + } connect(newCard.getCardPtr().data(), &CardInfo::pixmapUpdated, this, &HomeWidget::updateBackgroundProperties); backgroundSourceCard->setCard(newCard); diff --git a/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_overlay_widget.cpp b/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_overlay_widget.cpp index 1508b5243..69334d6f3 100644 --- a/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_overlay_widget.cpp +++ b/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_overlay_widget.cpp @@ -147,8 +147,9 @@ void PrintingSelectorCardOverlayWidget::updateVisibility() */ void PrintingSelectorCardOverlayWidget::updatePinBadgeVisibility() { - if (!pinBadge || !cardInfoPicture) + if (!pinBadge || !cardInfoPicture) { return; + } // Query the persisted preference override to decide whether this printing is pinned. const auto &preferredProviderId = diff --git a/cockatrice/src/interface/widgets/replay/replay_manager.cpp b/cockatrice/src/interface/widgets/replay/replay_manager.cpp index fac3576f2..525b703db 100644 --- a/cockatrice/src/interface/widgets/replay/replay_manager.cpp +++ b/cockatrice/src/interface/widgets/replay/replay_manager.cpp @@ -19,16 +19,19 @@ ReplayManager::ReplayManager(TabGame *parent, GameReplay *_replay) const int eventCount = replay->event_list_size(); for (int i = 0; i < eventCount; ++i) { int j = i + 1; - while ((j < eventCount) && (replay->event_list(j).seconds_elapsed() == lastEventTimestamp)) + while ((j < eventCount) && (replay->event_list(j).seconds_elapsed() == lastEventTimestamp)) { ++j; + } const int numberEventsThisSecond = j - i; - for (int k = 0; k < numberEventsThisSecond; ++k) + for (int k = 0; k < numberEventsThisSecond; ++k) { replayTimeline.append(replay->event_list(i + k).seconds_elapsed() * 1000 + (int)((qreal)k / (qreal)numberEventsThisSecond * 1000)); + } - if (j < eventCount) + if (j < eventCount) { lastEventTimestamp = replay->event_list(j).seconds_elapsed(); + } i += numberEventsThisSecond - 1; } } diff --git a/cockatrice/src/interface/widgets/replay/replay_timeline_widget.cpp b/cockatrice/src/interface/widgets/replay/replay_timeline_widget.cpp index 25ee58b67..508d45666 100644 --- a/cockatrice/src/interface/widgets/replay/replay_timeline_widget.cpp +++ b/cockatrice/src/interface/widgets/replay/replay_timeline_widget.cpp @@ -27,20 +27,23 @@ void ReplayTimelineWidget::setTimeline(const QList &_replayTimeline) for (int i : replayTimeline) { if (i > binEndTime) { histogram.append(binValue); - if (binValue > maxBinValue) + if (binValue > maxBinValue) { maxBinValue = binValue; + } while (i > binEndTime + BIN_LENGTH) { histogram.append(0); binEndTime += BIN_LENGTH; } binValue = 1; binEndTime += BIN_LENGTH; - } else + } else { ++binValue; + } } histogram.append(binValue); - if (!replayTimeline.isEmpty()) + if (!replayTimeline.isEmpty()) { maxTime = replayTimeline.last(); + } update(); } @@ -53,8 +56,9 @@ void ReplayTimelineWidget::paintEvent(QPaintEvent * /* event */) qreal binWidth = (qreal)width() / histogram.size(); QPainterPath path; path.moveTo(0, height() - 1); - for (int i = 0; i < histogram.size(); ++i) + for (int i = 0; i < histogram.size(); ++i) { path.lineTo(qRound(i * binWidth), (height() - 1) * (1.0 - (qreal)histogram[i] / maxBinValue)); + } path.lineTo(width() - 1, height() - 1); path.lineTo(0, height() - 1); painter.fillPath(path, Qt::black); @@ -142,8 +146,9 @@ void ReplayTimelineWidget::replayTimerTimeout() processNewEvents(NORMAL_PLAYBACK); - if (!(currentVisualTime % 1000)) + if (!(currentVisualTime % 1000)) { update(); + } } /// Processes all unprocessed events up to the current time. @@ -156,12 +161,14 @@ void ReplayTimelineWidget::processNewEvents(PlaybackMode playbackMode) // backwards skip => always skip reveal windows // forwards skip => skip reveal windows that don't happen within a big skip of the target - if (playbackMode == BACKWARD_SKIP || currentProcessedTime - replayTimeline[currentEvent] > BIG_SKIP_MS) + if (playbackMode == BACKWARD_SKIP || currentProcessedTime - replayTimeline[currentEvent] > BIG_SKIP_MS) { options |= SKIP_REVEAL_WINDOW; + } // backwards skip => always skip tap animation - if (playbackMode == BACKWARD_SKIP) + if (playbackMode == BACKWARD_SKIP) { options |= SKIP_TAP_ANIMATION; + } emit processNextEvent(options); ++currentEvent; diff --git a/cockatrice/src/interface/widgets/server/chat_view/chat_view.cpp b/cockatrice/src/interface/widgets/server/chat_view/chat_view.cpp index 731f30942..1fe77e278 100644 --- a/cockatrice/src/interface/widgets/server/chat_view/chat_view.cpp +++ b/cockatrice/src/interface/widgets/server/chat_view/chat_view.cpp @@ -88,10 +88,11 @@ void ChatView::refreshBlockColors() for (QTextBlock block = doc->begin(); block.isValid(); block = block.next()) { QTextBlockFormat fmt = block.blockFormat(); - if (even) + if (even) { fmt.setBackground(palette().base()); - else + } else { fmt.setBackground(palette().window()); + } fmt.setForeground(palette().text()); @@ -121,10 +122,11 @@ QTextCursor ChatView::prepareBlock(bool same) cursor.insertHtml("
    "); } else { QTextBlockFormat blockFormat; - if (evenNumber) + if (evenNumber) { blockFormat.setBackground(palette().base()); - else + } else { blockFormat.setBackground(palette().window()); + } evenNumber = !evenNumber; @@ -144,8 +146,9 @@ void ChatView::appendHtml(const QString &html) { bool atBottom = verticalScrollBar()->value() >= verticalScrollBar()->maximum(); prepareBlock().insertHtml(html); - if (atBottom) + if (atBottom) { verticalScrollBar()->setValue(verticalScrollBar()->maximum()); + } } void ChatView::appendHtmlServerMessage(const QString &html, bool optionalIsBold, QString optionalFontColor) @@ -156,12 +159,14 @@ void ChatView::appendHtmlServerMessage(const QString &html, bool optionalIsBold, "" + QDateTime::currentDateTime().toString("[hh:mm:ss] ") + html + ""; - if (optionalIsBold) + if (optionalIsBold) { htmlText = "" + htmlText + ""; + } prepareBlock().insertHtml(htmlText); - if (atBottom) + if (atBottom) { verticalScrollBar()->setValue(verticalScrollBar()->maximum()); + } } void ChatView::appendCardTag(QTextCursor &cursor, const QString &cardName) @@ -180,8 +185,9 @@ void ChatView::appendCardTag(QTextCursor &cursor, const QString &cardName) void ChatView::appendUrlTag(QTextCursor &cursor, QString url) { - if (!url.contains("://")) + if (!url.contains("://")) { url.prepend("https://"); + } QTextCharFormat oldFormat = cursor.charFormat(); QTextCharFormat anchorFormat = oldFormat; @@ -317,8 +323,9 @@ void ChatView::appendMessage(QString message, } } - if (atBottom) + if (atBottom) { verticalScrollBar()->setValue(verticalScrollBar()->maximum()); + } } void ChatView::checkTag(QTextCursor &cursor, QString &message) @@ -327,10 +334,11 @@ void ChatView::checkTag(QTextCursor &cursor, QString &message) message = message.mid(6); int closeTagIndex = message.indexOf("[/card]"); QString cardName = message.left(closeTagIndex); - if (closeTagIndex == -1) + if (closeTagIndex == -1) { message.clear(); - else + } else { message = message.mid(closeTagIndex + 7); + } appendCardTag(cursor, cardName); return; @@ -340,10 +348,11 @@ void ChatView::checkTag(QTextCursor &cursor, QString &message) message = message.mid(2); int closeTagIndex = message.indexOf("]]"); QString cardName = message.left(closeTagIndex); - if (closeTagIndex == -1) + if (closeTagIndex == -1) { message.clear(); - else + } else { message = message.mid(closeTagIndex + 2); + } appendCardTag(cursor, cardName); return; @@ -353,10 +362,11 @@ void ChatView::checkTag(QTextCursor &cursor, QString &message) message = message.mid(5); int closeTagIndex = message.indexOf("[/url]"); QString url = message.left(closeTagIndex); - if (closeTagIndex == -1) + if (closeTagIndex == -1) { message.clear(); - else + } else { message = message.mid(closeTagIndex + 6); + } appendUrlTag(cursor, url); return; @@ -587,8 +597,9 @@ QTextFragment ChatView::getFragmentUnderMouse(const QPoint &pos) const QTextBlock::iterator it; for (it = block.begin(); !(it.atEnd()); ++it) { QTextFragment frag = it.fragment(); - if (frag.contains(cursor.position())) + if (frag.contains(cursor.position())) { return frag; + } } return QTextFragment(); } @@ -604,10 +615,11 @@ void ChatView::mouseMoveEvent(QMouseEvent *event) if (scheme == "card") { hoveredItemType = HoveredCard; emit cardNameHovered(hoveredContent); - } else if (scheme == "user") + } else if (scheme == "user") { hoveredItemType = HoveredUser; - else + } else { hoveredItemType = HoveredUrl; + } viewport()->setCursor(Qt::PointingHandCursor); } else { hoveredItemType = HoveredNothing; @@ -650,8 +662,9 @@ void ChatView::mousePressEvent(QMouseEvent *event) case Qt::LeftButton: { if (event->modifiers() == Qt::ControlModifier) { emit openMessageDialog(userName, true); - } else + } else { emit addMentionTag("@" + userName); + } break; } default: @@ -668,16 +681,18 @@ void ChatView::mousePressEvent(QMouseEvent *event) void ChatView::mouseReleaseEvent(QMouseEvent *event) { - if ((event->button() == Qt::MiddleButton) || (event->button() == Qt::LeftButton)) + if ((event->button() == Qt::MiddleButton) || (event->button() == Qt::LeftButton)) { emit deleteCardInfoPopup(QString("_")); + } QTextBrowser::mouseReleaseEvent(event); } void ChatView::openLink(const QUrl &link) { - if ((link.scheme() == "card") || (link.scheme() == "user")) + if ((link.scheme() == "card") || (link.scheme() == "user")) { return; + } QDesktopServices::openUrl(link); } diff --git a/cockatrice/src/interface/widgets/server/game_selector.cpp b/cockatrice/src/interface/widgets/server/game_selector.cpp index dd29f4fc6..9a41ca6ce 100644 --- a/cockatrice/src/interface/widgets/server/game_selector.cpp +++ b/cockatrice/src/interface/widgets/server/game_selector.cpp @@ -61,14 +61,17 @@ GameSelector::GameSelector(AbstractClient *_client, gameListView->setColumnWidth(3, gameListView->columnWidth(3) * 1.2); // game type width gameListView->setColumnWidth(4, gameListView->columnWidth(4) * 1.4); - if (_room) + if (_room) { gameListView->header()->hideSection(gameListModel->roomColIndex()); + } - if (room) + if (room) { gameTypeMap = gameListModel->getGameTypes().value(room->getRoomId()); + } - if (showFilters && restoresettings) + if (showFilters && restoresettings) { gameListProxyModel->loadFilterParameters(gameTypeMap); + } gameListView->header()->setSectionResizeMode(0, QHeaderView::ResizeToContents); @@ -111,8 +114,9 @@ GameSelector::GameSelector(AbstractClient *_client, buttonLayout->addWidget(clearFilterButton); } buttonLayout->addStretch(); - if (room) + if (room) { buttonLayout->addWidget(createButton); + } buttonLayout->addWidget(joinButton); if (tabSupervisor->getUserInfo()->user_level() & ServerInfo_User::IsJudge) { buttonLayout->addWidget(joinAsJudgeButton); @@ -178,8 +182,9 @@ void GameSelector::actSetFilter() { DlgFilterGames dlg(gameTypeMap, gameListProxyModel, this); - if (!dlg.exec()) + if (!dlg.exec()) { return; + } gameListProxyModel->setGameFilters(dlg.getFilters()); gameListProxyModel->saveFilterParameters(gameTypeMap); @@ -373,8 +378,9 @@ void GameSelector::joinGame(const bool asSpectator, const bool asJudge) void GameSelector::disableButtons() { - if (createButton) + if (createButton) { createButton->setEnabled(false); + } joinButton->setEnabled(false); spectateButton->setEnabled(false); @@ -382,8 +388,9 @@ void GameSelector::disableButtons() void GameSelector::enableButtons() { - if (createButton) + if (createButton) { createButton->setEnabled(true); + } // Enable buttons for the currently selected game enableButtonsForIndex(gameListView->currentIndex()); @@ -391,8 +398,9 @@ void GameSelector::enableButtons() void GameSelector::enableButtonsForIndex(const QModelIndex ¤t) { - if (!current.isValid()) + if (!current.isValid()) { return; + } const ServerInfo_Game &game = gameListModel->getGame(current.data(Qt::UserRole).toInt()); bool overrideRestrictions = !tabSupervisor->getAdminLocked(); @@ -405,8 +413,9 @@ void GameSelector::retranslateUi() { filterButton->setText(tr("&Filter games")); clearFilterButton->setText(tr("C&lear filter")); - if (createButton) + if (createButton) { createButton->setText(tr("C&reate")); + } joinButton->setText(tr("&Join")); joinAsJudgeButton->setText(tr("Join as judge")); spectateButton->setText(tr("J&oin as spectator")); diff --git a/cockatrice/src/interface/widgets/server/game_selector_quick_filter_toolbar.cpp b/cockatrice/src/interface/widgets/server/game_selector_quick_filter_toolbar.cpp index 0e8a0d4c7..d668b1c33 100644 --- a/cockatrice/src/interface/widgets/server/game_selector_quick_filter_toolbar.cpp +++ b/cockatrice/src/interface/widgets/server/game_selector_quick_filter_toolbar.cpp @@ -59,8 +59,9 @@ GameSelectorQuickFilterToolBar::GameSelectorQuickFilterToolBar(QWidget *parent, if (currentTypes.size() == 1) { int typeId = *currentTypes.begin(); int index = filterToFormatComboBox->findData(typeId); - if (index >= 0) + if (index >= 0) { filterToFormatComboBox->setCurrentIndex(index); + } } else { filterToFormatComboBox->setCurrentIndex(0); // "All types" by default } diff --git a/cockatrice/src/interface/widgets/server/games_model.cpp b/cockatrice/src/interface/widgets/server/games_model.cpp index e894ac4fd..1d30aa7ac 100644 --- a/cockatrice/src/interface/widgets/server/games_model.cpp +++ b/cockatrice/src/interface/widgets/server/games_model.cpp @@ -63,14 +63,18 @@ GamesModel::GamesModel(const QMap &_rooms, const QMap= gameList.size()) || (index.column() >= columnCount())) + } + if ((index.row() >= gameList.size()) || (index.column() >= columnCount())) { return QVariant(); + } const ServerInfo_Game &gameentry = gameList[index.row()]; switch (index.column()) { @@ -126,8 +130,9 @@ QVariant GamesModel::data(const QModelIndex &index, int role) const case Qt::DisplayRole: { QStringList result; GameTypeMap gameTypeMap = gameTypes.value(gameentry.room_id()); - for (int i = gameentry.game_types_size() - 1; i >= 0; --i) + for (int i = gameentry.game_types_size() - 1; i >= 0; --i) { result.append(gameTypeMap.value(gameentry.game_types(i))); + } return result.join(", "); } case Qt::TextAlignmentRole: @@ -140,14 +145,18 @@ QVariant GamesModel::data(const QModelIndex &index, int role) const case SORT_ROLE: case Qt::DisplayRole: { QStringList result; - if (gameentry.with_password()) + if (gameentry.with_password()) { result.append(tr("password")); - if (gameentry.only_buddies()) + } + if (gameentry.only_buddies()) { result.append(tr("buddies only")); - if (gameentry.only_registered()) + } + if (gameentry.only_registered()) { result.append(tr("reg. users only")); - if (gameentry.share_decklists_on_load()) + } + if (gameentry.share_decklists_on_load()) { result.append(tr("open decklists")); + } return result.join(", "); } case Qt::DecorationRole: { @@ -205,8 +214,9 @@ QVariant GamesModel::data(const QModelIndex &index, int role) const QVariant GamesModel::headerData(int section, Qt::Orientation /*orientation*/, int role) const { - if ((role != Qt::DisplayRole) && (role != Qt::TextAlignmentRole)) + if ((role != Qt::DisplayRole) && (role != Qt::TextAlignmentRole)) { return QVariant(); + } switch (section) { case ROOM: return tr("Room"); @@ -296,8 +306,9 @@ void GamesProxyModel::setGameFilters(const GameFilterConfigs &_filters) int GamesProxyModel::getNumFilteredGames() const { auto *model = qobject_cast(sourceModel()); - if (!model) + if (!model) { return 0; + } int numFilteredGames = 0; for (int row = 0; row < model->rowCount(); ++row) { @@ -384,8 +395,9 @@ bool GamesProxyModel::filterAcceptsRow(int sourceRow) const static const QDate epochDate = QDateTime::fromSecsSinceEpoch(0, Qt::UTC).date(); #endif auto *model = qobject_cast(sourceModel()); - if (!model) + if (!model) { return false; + } const ServerInfo_Game &game = model->getGame(sourceRow); @@ -403,18 +415,25 @@ bool GamesProxyModel::filterAcceptsRow(int sourceRow) const !userListProxy->isUserBuddy(QString::fromStdString(game.creator_info().name()))) { return false; } - if (filters.hideFullGames && game.player_count() == game.max_players()) + if (filters.hideFullGames && game.player_count() == game.max_players()) { return false; - if (filters.hideGamesThatStarted && game.started()) + } + if (filters.hideGamesThatStarted && game.started()) { return false; - if (!userListProxy->isOwnUserRegistered()) - if (game.only_registered()) + } + if (!userListProxy->isOwnUserRegistered()) { + if (game.only_registered()) { return false; - if (filters.hidePasswordProtectedGames && game.with_password()) + } + } + if (filters.hidePasswordProtectedGames && game.with_password()) { return false; - if (!filters.gameNameFilter.isEmpty()) - if (!QString::fromStdString(game.description()).contains(filters.gameNameFilter, Qt::CaseInsensitive)) + } + if (!filters.gameNameFilter.isEmpty()) { + if (!QString::fromStdString(game.description()).contains(filters.gameNameFilter, Qt::CaseInsensitive)) { return false; + } + } if (!filters.creatorNameFilters.isEmpty()) { bool found = false; for (const auto &createNameFilter : filters.creatorNameFilters) { @@ -428,15 +447,19 @@ bool GamesProxyModel::filterAcceptsRow(int sourceRow) const } QSet gameTypes; - for (int i = 0; i < game.game_types_size(); ++i) + for (int i = 0; i < game.game_types_size(); ++i) { gameTypes.insert(game.game_types(i)); - if (!filters.gameTypeFilter.isEmpty() && gameTypes.intersect(filters.gameTypeFilter).isEmpty()) + } + if (!filters.gameTypeFilter.isEmpty() && gameTypes.intersect(filters.gameTypeFilter).isEmpty()) { return false; + } - if (static_cast(game.max_players()) < filters.maxPlayersFilterMin) + if (static_cast(game.max_players()) < filters.maxPlayersFilterMin) { return false; - if (static_cast(game.max_players()) > filters.maxPlayersFilterMax) + } + if (static_cast(game.max_players()) > filters.maxPlayersFilterMax) { return false; + } if (filters.maxGameAge.isValid()) { QDateTime now = QDateTime::currentDateTimeUtc(); @@ -451,14 +474,18 @@ bool GamesProxyModel::filterAcceptsRow(int sourceRow) const } if (filters.showOnlyIfSpectatorsCanWatch) { - if (!game.spectators_allowed()) + if (!game.spectators_allowed()) { return false; - if (!filters.showSpectatorPasswordProtected && game.spectators_need_password()) + } + if (!filters.showSpectatorPasswordProtected && game.spectators_need_password()) { return false; - if (filters.showOnlyIfSpectatorsCanChat && !game.spectators_can_chat()) + } + if (filters.showOnlyIfSpectatorsCanChat && !game.spectators_can_chat()) { return false; - if (filters.showOnlyIfSpectatorsCanSeeHands && !game.spectators_omniscient()) + } + if (filters.showOnlyIfSpectatorsCanSeeHands && !game.spectators_omniscient()) { return false; + } } return true; } diff --git a/cockatrice/src/interface/widgets/server/handle_public_servers.cpp b/cockatrice/src/interface/widgets/server/handle_public_servers.cpp index f37c957a4..8ebb70e83 100644 --- a/cockatrice/src/interface/widgets/server/handle_public_servers.cpp +++ b/cockatrice/src/interface/widgets/server/handle_public_servers.cpp @@ -37,13 +37,11 @@ void HandlePublicServers::actFinishParsingDownloadedData() QVariantMap jsonMap = jsonResponse.toVariant().toMap(); updateServerINISettings(jsonMap); } else { - qDebug() << "[PUBLIC SERVER HANDLER]" - << "JSON Parsing Error:" << parseError.errorString(); + qDebug() << "[PUBLIC SERVER HANDLER]" << "JSON Parsing Error:" << parseError.errorString(); emit sigPublicServersDownloadedUnsuccessfully(errorCode); } } else { - qDebug() << "[PUBLIC SERVER HANDLER]" - << "Error Downloading Public Servers" << errorCode; + qDebug() << "[PUBLIC SERVER HANDLER]" << "Error Downloading Public Servers" << errorCode; emit sigPublicServersDownloadedUnsuccessfully(errorCode); } diff --git a/cockatrice/src/interface/widgets/server/remote/remote_decklist_tree_widget.cpp b/cockatrice/src/interface/widgets/server/remote/remote_decklist_tree_widget.cpp index 6ca680c3f..a6add3fca 100644 --- a/cockatrice/src/interface/widgets/server/remote/remote_decklist_tree_widget.cpp +++ b/cockatrice/src/interface/widgets/server/remote/remote_decklist_tree_widget.cpp @@ -22,8 +22,9 @@ RemoteDeckList_TreeModel::DirectoryNode::~DirectoryNode() void RemoteDeckList_TreeModel::DirectoryNode::clearTree() { - for (int i = 0; i < size(); ++i) + for (int i = 0; i < size(); ++i) { delete at(i); + } clear(); } @@ -31,31 +32,37 @@ QString RemoteDeckList_TreeModel::DirectoryNode::getPath() const { if (parent) { QString parentPath = parent->getPath(); - if (parentPath.isEmpty()) + if (parentPath.isEmpty()) { return name; - else + } else { return parentPath + "/" + name; - } else + } + } else { return name; + } } RemoteDeckList_TreeModel::DirectoryNode *RemoteDeckList_TreeModel::DirectoryNode::getNodeByPath(QStringList path) { QString pathItem; if (parent) { - if (path.isEmpty()) + if (path.isEmpty()) { return this; + } pathItem = path.takeFirst(); - if (pathItem.isEmpty() && name.isEmpty()) + if (pathItem.isEmpty() && name.isEmpty()) { return this; + } } for (int i = 0; i < size(); ++i) { DirectoryNode *node = dynamic_cast(at(i)); - if (!node) + if (!node) { continue; - if (node->getName() == pathItem) + } + if (node->getName() == pathItem) { return node->getNodeByPath(path); + } } return 0; } @@ -66,12 +73,14 @@ RemoteDeckList_TreeModel::FileNode *RemoteDeckList_TreeModel::DirectoryNode::get DirectoryNode *node = dynamic_cast(at(i)); if (node) { FileNode *result = node->getNodeById(id); - if (result) + if (result) { return result; + } } else { FileNode *file = dynamic_cast(at(i)); - if (file->getId() == id) + if (file->getId() == id) { return file; + } } } return 0; @@ -95,10 +104,11 @@ RemoteDeckList_TreeModel::~RemoteDeckList_TreeModel() int RemoteDeckList_TreeModel::rowCount(const QModelIndex &parent) const { DirectoryNode *node = getNode(parent); - if (node) + if (node) { return node->size(); - else + } else { return 0; + } } int RemoteDeckList_TreeModel::columnCount(const QModelIndex & /*parent*/) const @@ -108,10 +118,12 @@ int RemoteDeckList_TreeModel::columnCount(const QModelIndex & /*parent*/) const QVariant RemoteDeckList_TreeModel::data(const QModelIndex &index, int role) const { - if (!index.isValid()) + if (!index.isValid()) { return QVariant(); - if (index.column() >= 3) + } + if (index.column() >= 3) { return QVariant(); + } Node *temp = static_cast(index.internalPointer()); FileNode *file = dynamic_cast(temp); @@ -157,8 +169,9 @@ QVariant RemoteDeckList_TreeModel::data(const QModelIndex &index, int role) cons QVariant RemoteDeckList_TreeModel::headerData(int section, Qt::Orientation orientation, int role) const { - if (orientation != Qt::Horizontal) + if (orientation != Qt::Horizontal) { return QVariant(); + } switch (role) { case Qt::TextAlignmentRole: return section == 1 ? Qt::AlignRight : Qt::AlignLeft; @@ -181,20 +194,23 @@ QVariant RemoteDeckList_TreeModel::headerData(int section, Qt::Orientation orien QModelIndex RemoteDeckList_TreeModel::index(int row, int column, const QModelIndex &parent) const { - if (!hasIndex(row, column, parent)) + if (!hasIndex(row, column, parent)) { return QModelIndex(); + } DirectoryNode *parentNode = getNode(parent); - if (row >= parentNode->size()) + if (row >= parentNode->size()) { return QModelIndex(); + } return createIndex(row, column, parentNode->at(row)); } QModelIndex RemoteDeckList_TreeModel::parent(const QModelIndex &ind) const { - if (!ind.isValid()) + if (!ind.isValid()) { return QModelIndex(); + } return nodeToIndex(static_cast(ind.internalPointer())->getParent()); } @@ -210,8 +226,9 @@ Qt::ItemFlags RemoteDeckList_TreeModel::flags(const QModelIndex &index) const QModelIndex RemoteDeckList_TreeModel::nodeToIndex(Node *node) const { - if (node == nullptr || node == root) + if (node == nullptr || node == root) { return QModelIndex(); + } return createIndex(node->getParent()->indexOf(node), 0, node); } @@ -233,10 +250,11 @@ void RemoteDeckList_TreeModel::addFolderToTree(const ServerInfo_DeckStorage_Tree const int folderItemsSize = folderInfo.items_size(); for (int i = 0; i < folderItemsSize; ++i) { const ServerInfo_DeckStorage_TreeItem &subItem = folderInfo.items(i); - if (subItem.has_folder()) + if (subItem.has_folder()) { addFolderToTree(subItem, newItem); - else + } else { addFileToTree(subItem, newItem); + } } } diff --git a/cockatrice/src/interface/widgets/server/remote/remote_decklist_tree_widget.h b/cockatrice/src/interface/widgets/server/remote/remote_decklist_tree_widget.h index 8254eb57b..bca46fd47 100644 --- a/cockatrice/src/interface/widgets/server/remote/remote_decklist_tree_widget.h +++ b/cockatrice/src/interface/widgets/server/remote/remote_decklist_tree_widget.h @@ -75,8 +75,9 @@ public: template [[nodiscard]] T getNode(const QModelIndex &index) const { - if (!index.isValid()) + if (!index.isValid()) { return dynamic_cast(root); + } return dynamic_cast(static_cast(index.internalPointer())); } diff --git a/cockatrice/src/interface/widgets/server/remote/remote_replay_list_tree_widget.cpp b/cockatrice/src/interface/widgets/server/remote/remote_replay_list_tree_widget.cpp index 5152880d9..1f034b767 100644 --- a/cockatrice/src/interface/widgets/server/remote/remote_replay_list_tree_widget.cpp +++ b/cockatrice/src/interface/widgets/server/remote/remote_replay_list_tree_widget.cpp @@ -14,14 +14,16 @@ const int RemoteReplayList_TreeModel::numberOfColumns = 6; RemoteReplayList_TreeModel::MatchNode::MatchNode(const ServerInfo_ReplayMatch &_matchInfo) : RemoteReplayList_TreeModel::Node(QString::fromStdString(_matchInfo.game_name())), matchInfo(_matchInfo) { - for (int i = 0; i < matchInfo.replay_list_size(); ++i) + for (int i = 0; i < matchInfo.replay_list_size(); ++i) { append(new ReplayNode(matchInfo.replay_list(i), this)); + } } RemoteReplayList_TreeModel::MatchNode::~MatchNode() { - for (int i = 0; i < size(); ++i) + for (int i = 0; i < size(); ++i) { delete at(i); + } } void RemoteReplayList_TreeModel::MatchNode::updateMatchInfo(const ServerInfo_ReplayMatch &_matchInfo) @@ -45,22 +47,26 @@ RemoteReplayList_TreeModel::~RemoteReplayList_TreeModel() int RemoteReplayList_TreeModel::rowCount(const QModelIndex &parent) const { - if (!parent.isValid()) + if (!parent.isValid()) { return replayMatches.size(); + } auto *matchNode = dynamic_cast(static_cast(parent.internalPointer())); - if (matchNode) + if (matchNode) { return matchNode->size(); - else + } else { return 0; + } } QVariant RemoteReplayList_TreeModel::data(const QModelIndex &index, int role) const { - if (!index.isValid()) + if (!index.isValid()) { return QVariant(); - if (index.column() >= numberOfColumns) + } + if (index.column() >= numberOfColumns) { return QVariant(); + } auto *replayNode = dynamic_cast(static_cast(index.internalPointer())); if (replayNode) { @@ -103,8 +109,9 @@ QVariant RemoteReplayList_TreeModel::data(const QModelIndex &index, int role) co return QString::fromStdString(matchInfo.game_name()); case 2: { QStringList playerList; - for (int i = 0; i < matchInfo.player_names_size(); ++i) + for (int i = 0; i < matchInfo.player_names_size(); ++i) { playerList.append(QString::fromStdString(matchInfo.player_names(i))); + } return playerList.join(", "); } case 4: @@ -131,8 +138,9 @@ QVariant RemoteReplayList_TreeModel::data(const QModelIndex &index, int role) co QVariant RemoteReplayList_TreeModel::headerData(int section, Qt::Orientation orientation, int role) const { - if (orientation != Qt::Horizontal) + if (orientation != Qt::Horizontal) { return QVariant(); + } switch (role) { case Qt::TextAlignmentRole: switch (section) { @@ -167,17 +175,20 @@ QVariant RemoteReplayList_TreeModel::headerData(int section, Qt::Orientation ori QModelIndex RemoteReplayList_TreeModel::index(int row, int column, const QModelIndex &parent) const { - if (!hasIndex(row, column, parent)) + if (!hasIndex(row, column, parent)) { return QModelIndex(); + } auto *matchNode = dynamic_cast(static_cast(parent.internalPointer())); if (matchNode) { - if (row >= matchNode->size()) + if (row >= matchNode->size()) { return QModelIndex(); + } return createIndex(row, column, (void *)matchNode->at(row)); } else { - if (row >= replayMatches.size()) + if (row >= replayMatches.size()) { return QModelIndex(); + } return createIndex(row, column, (void *)replayMatches[row]); } } @@ -185,9 +196,9 @@ QModelIndex RemoteReplayList_TreeModel::index(int row, int column, const QModelI QModelIndex RemoteReplayList_TreeModel::parent(const QModelIndex &ind) const { MatchNode const *matchNode = dynamic_cast(static_cast(ind.internalPointer())); - if (matchNode) + if (matchNode) { return QModelIndex(); - else { + } else { auto *replayNode = dynamic_cast(static_cast(ind.internalPointer())); return createIndex(replayNode->getParent()->indexOf(replayNode), 0, replayNode->getParent()); } @@ -195,45 +206,52 @@ QModelIndex RemoteReplayList_TreeModel::parent(const QModelIndex &ind) const Qt::ItemFlags RemoteReplayList_TreeModel::flags(const QModelIndex &index) const { - if (!index.isValid()) + if (!index.isValid()) { return Qt::NoItemFlags; + } return Qt::ItemIsEnabled | Qt::ItemIsSelectable; } ServerInfo_Replay const *RemoteReplayList_TreeModel::getReplay(const QModelIndex &index) const { - if (!index.isValid()) + if (!index.isValid()) { return 0; + } auto *node = dynamic_cast(static_cast(index.internalPointer())); - if (!node) + if (!node) { return 0; + } return &node->getReplayInfo(); } ServerInfo_ReplayMatch const *RemoteReplayList_TreeModel::getReplayMatch(const QModelIndex &index) const { - if (!index.isValid()) + if (!index.isValid()) { return nullptr; + } auto *node = dynamic_cast(static_cast(index.internalPointer())); - if (!node) + if (!node) { return nullptr; + } return &node->getMatchInfo(); } ServerInfo_ReplayMatch const *RemoteReplayList_TreeModel::getEnclosingReplayMatch(const QModelIndex &index) const { - if (!index.isValid()) + if (!index.isValid()) { return nullptr; + } auto *node = dynamic_cast(static_cast(index.internalPointer())); if (!node) { auto *_node = dynamic_cast(static_cast(index.internalPointer())); - if (!_node) + if (!_node) { return nullptr; + } return &_node->getParent()->getMatchInfo(); } return &node->getMatchInfo(); @@ -244,8 +262,9 @@ ServerInfo_ReplayMatch const *RemoteReplayList_TreeModel::getEnclosingReplayMatc */ void RemoteReplayList_TreeModel::clearAll() { - for (int i = 0; i < replayMatches.size(); ++i) + for (int i = 0; i < replayMatches.size(); ++i) { delete replayMatches[i]; + } replayMatches.clear(); } @@ -275,24 +294,26 @@ void RemoteReplayList_TreeModel::addMatchInfo(const ServerInfo_ReplayMatch &matc void RemoteReplayList_TreeModel::updateMatchInfo(int gameId, const ServerInfo_ReplayMatch &matchInfo) { - for (int i = 0; i < replayMatches.size(); ++i) + for (int i = 0; i < replayMatches.size(); ++i) { if (replayMatches[i]->getMatchInfo().game_id() == gameId) { replayMatches[i]->updateMatchInfo(matchInfo); emit dataChanged(createIndex(i, 0, (void *)replayMatches[i]), createIndex(i, numberOfColumns - 1, (void *)replayMatches[i])); break; } + } } void RemoteReplayList_TreeModel::removeMatchInfo(int gameId) { - for (int i = 0; i < replayMatches.size(); ++i) + for (int i = 0; i < replayMatches.size(); ++i) { if (replayMatches[i]->getMatchInfo().game_id() == gameId) { beginRemoveRows(QModelIndex(), i, i); replayMatches.removeAt(i); endRemoveRows(); break; } + } } void RemoteReplayList_TreeModel::replayListFinished(const Response &r) @@ -302,8 +323,9 @@ void RemoteReplayList_TreeModel::replayListFinished(const Response &r) beginResetModel(); clearAll(); - for (int i = 0; i < resp.match_list_size(); ++i) + for (int i = 0; i < resp.match_list_size(); ++i) { replayMatches.append(new MatchNode(resp.match_list(i))); + } endResetModel(); emit treeRefreshed(); diff --git a/cockatrice/src/interface/widgets/server/user/user_context_menu.cpp b/cockatrice/src/interface/widgets/server/user/user_context_menu.cpp index 7083ac899..195b1cc8d 100644 --- a/cockatrice/src/interface/widgets/server/user/user_context_menu.cpp +++ b/cockatrice/src/interface/widgets/server/user/user_context_menu.cpp @@ -192,13 +192,15 @@ void UserContextMenu::banUserHistory_processResponse(const Response &resp) table->setMinimumSize(table->horizontalHeader()->length() + (table->columnCount() * 5), table->verticalHeader()->length() + (table->rowCount() * 3)); table->show(); - } else + } else { QMessageBox::information(static_cast(parent()), tr("Ban History"), tr("User has never been banned.")); + } - } else + } else { QMessageBox::critical(static_cast(parent()), tr("Ban History"), tr("Failed to collect ban information.")); + } } void UserContextMenu::warnUserHistory_processResponse(const Response &resp) @@ -228,13 +230,15 @@ void UserContextMenu::warnUserHistory_processResponse(const Response &resp) table->setMinimumSize(table->horizontalHeader()->length() + (table->columnCount() * 5), table->verticalHeader()->length() + (table->rowCount() * 3)); table->show(); - } else + } else { QMessageBox::information(static_cast(parent()), tr("Warning History"), tr("User has never been warned.")); + } - } else + } else { QMessageBox::critical(static_cast(parent()), tr("Warning History"), tr("Failed to collect warning information.")); + } } void UserContextMenu::getAdminNotes_processResponse(const Response &resp) @@ -297,8 +301,9 @@ void UserContextMenu::warnUser_dialogFinished() { auto *dlg = static_cast(sender()); - if (dlg->getName().isEmpty() || userListProxy->getOwnUsername().simplified().isEmpty()) + if (dlg->getName().isEmpty() || userListProxy->getOwnUsername().simplified().isEmpty()) { return; + } Command_WarnUser cmd; cmd.set_user_name(dlg->getName().toStdString()); diff --git a/cockatrice/src/interface/widgets/server/user/user_info_box.cpp b/cockatrice/src/interface/widgets/server/user/user_info_box.cpp index 9ae4a42c2..a9955ff3d 100644 --- a/cockatrice/src/interface/widgets/server/user/user_info_box.cpp +++ b/cockatrice/src/interface/widgets/server/user/user_info_box.cpp @@ -123,17 +123,19 @@ void UserInfoBox::updateInfo(const ServerInfo_User &user) userLevelIcon.setPixmap(UserLevelPixmapGenerator::generatePixmap(15, userLevel, user.pawn_colors(), false, QString::fromStdString(user.privlevel()))); QString userLevelText; - if (userLevel.testFlag(ServerInfo_User::IsAdmin)) + if (userLevel.testFlag(ServerInfo_User::IsAdmin)) { userLevelText = tr("Administrator"); - else if (userLevel.testFlag(ServerInfo_User::IsModerator)) + } else if (userLevel.testFlag(ServerInfo_User::IsModerator)) { userLevelText = tr("Moderator"); - else if (userLevel.testFlag(ServerInfo_User::IsRegistered)) + } else if (userLevel.testFlag(ServerInfo_User::IsRegistered)) { userLevelText = tr("Registered user"); - else + } else { userLevelText = tr("Unregistered user"); + } - if (userLevel.testFlag(ServerInfo_User::IsJudge)) + if (userLevel.testFlag(ServerInfo_User::IsJudge)) { userLevelText += " | " + tr("Judge"); + } if (user.has_privlevel() && user.privlevel() != "NONE") { userLevelText += " | " + QString("%1").arg(user.privlevel().c_str()); @@ -152,15 +154,17 @@ void UserInfoBox::updateInfo(const ServerInfo_User &user) QString UserInfoBox::getAgeString(int ageSeconds) { QString accountAgeString = tr("Unknown"); - if (ageSeconds <= 0) + if (ageSeconds <= 0) { return accountAgeString; + } // secsSinceEpoch is in utc auto secsSinceEpoch = QDateTime::currentSecsSinceEpoch() - ageSeconds; // the date is in local time, fromSecsSinceEpoch expects a timestamp from utc and converts it to local time auto date = QDateTime::fromSecsSinceEpoch(secsSinceEpoch).date(); - if (!date.isValid()) + if (!date.isValid()) { return accountAgeString; + } // now can be local time as the date is also local time auto now = QDate::currentDate(); @@ -218,8 +222,9 @@ void UserInfoBox::actEditInternal(const Response &r) QString realName = QString::fromStdString(user.real_name()); DlgEditUser dlg(this, email, country, realName); - if (!dlg.exec()) + if (!dlg.exec()) { return; + } Command_AccountEdit cmd; cmd.set_real_name(dlg.getRealName().toStdString()); @@ -231,8 +236,9 @@ void UserInfoBox::actEditInternal(const Response &r) getTextWithMax(this, tr("Enter Password"), tr("Password verification is required in order to change your email address"), QLineEdit::Password, "", &ok); - if (!ok) + if (!ok) { return; + } cmd.set_password_check(password.toStdString()); cmd.set_email(dlg.getEmail().toStdString()); } // servers that support password hash do not require all fields to be filled anymore @@ -250,8 +256,9 @@ void UserInfoBox::actEditInternal(const Response &r) void UserInfoBox::actPassword() { DlgEditPassword dlg(this); - if (!dlg.exec()) + if (!dlg.exec()) { return; + } auto oldPassword = dlg.getOldPassword(); auto newPassword = dlg.getNewPassword(); @@ -296,8 +303,9 @@ void UserInfoBox::changePassword(const QString &oldPassword, const QString &newP void UserInfoBox::actAvatar() { DlgEditAvatar dlg(this); - if (!dlg.exec()) + if (!dlg.exec()) { return; + } Command_AccountImage cmd; cmd.set_image(dlg.getImage().data(), dlg.getImage().size()); diff --git a/cockatrice/src/interface/widgets/server/user/user_info_connection.cpp b/cockatrice/src/interface/widgets/server/user/user_info_connection.cpp index 069e438a9..919bc2707 100644 --- a/cockatrice/src/interface/widgets/server/user/user_info_connection.cpp +++ b/cockatrice/src/interface/widgets/server/user/user_info_connection.cpp @@ -53,8 +53,9 @@ QStringList UserConnection_Information::getServerInfo(const QString &find) for (int i = 0; i < size; i++) { QString _saveName = servers.getValue(QString("saveName%1").arg(i), "server", "server_details").toString(); - if (find != _saveName) + if (find != _saveName) { continue; + } QString serverName = servers.getValue(QString("server%1").arg(i), "server", "server_details").toString(); QString portNum = servers.getValue(QString("port%1").arg(i), "server", "server_details").toString(); @@ -73,8 +74,9 @@ QStringList UserConnection_Information::getServerInfo(const QString &find) break; } - if (_server.empty()) + if (_server.empty()) { qCWarning(UserInfoConnectionLog) << "There was a problem!"; + } return _server; } diff --git a/cockatrice/src/interface/widgets/server/user/user_list_widget.cpp b/cockatrice/src/interface/widgets/server/user/user_list_widget.cpp index 852743479..11c9b60eb 100644 --- a/cockatrice/src/interface/widgets/server/user/user_list_widget.cpp +++ b/cockatrice/src/interface/widgets/server/user/user_list_widget.cpp @@ -40,8 +40,9 @@ BanDialog::BanDialog(const ServerInfo_User &info, QWidget *parent) : QDialog(par idBanCheckBox->setChecked(true); idBanEdit = new QLineEdit(QString::fromStdString(info.clientid())); idBanEdit->setMaxLength(MAX_NAME_LENGTH); - if (QString::fromStdString(info.clientid()).isEmpty()) + if (QString::fromStdString(info.clientid()).isEmpty()) { idBanCheckBox->setChecked(false); + } QGridLayout *banTypeGrid = new QGridLayout; banTypeGrid->addWidget(nameBanCheckBox, 0, 0); @@ -207,27 +208,30 @@ void BanDialog::okClicked() return; } - if (nameBanCheckBox->isChecked()) + if (nameBanCheckBox->isChecked()) { if (nameBanEdit->text().simplified() == "") { QMessageBox::critical(this, tr("Error"), tr("You must have a value in the name ban when selecting the name ban checkbox.")); return; } + } - if (ipBanCheckBox->isChecked()) + if (ipBanCheckBox->isChecked()) { if (ipBanEdit->text().simplified() == "") { QMessageBox::critical(this, tr("Error"), tr("You must have a value in the ip ban when selecting the ip ban checkbox.")); return; } + } - if (idBanCheckBox->isChecked()) + if (idBanCheckBox->isChecked()) { if (idBanEdit->text().simplified() == "") { QMessageBox::critical( this, tr("Error"), tr("You must have a value in the clientid ban when selecting the clientid ban checkbox.")); return; } + } accept(); } @@ -461,14 +465,15 @@ void UserListWidget::processUserInfo(const ServerInfo_User &user, bool online) { const QString userName = QString::fromStdString(user.name()); UserListTWI *item = users.value(userName); - if (item) + if (item) { item->setUserInfo(user); - else { + } else { item = new UserListTWI(user); users.insert(userName, item); userTree->addTopLevelItem(item); - if (online) + if (online) { ++onlineCount; + } updateCount(); } item->setOnline(online); @@ -480,8 +485,9 @@ bool UserListWidget::deleteUser(const QString &userName) if (twi) { users.remove(userName); userTree->takeTopLevelItem(userTree->indexOfTopLevelItem(twi)); - if (twi->data(0, Qt::UserRole + 1).toBool()) + if (twi->data(0, Qt::UserRole + 1).toBool()) { --onlineCount; + } delete twi; updateCount(); return true; @@ -493,22 +499,25 @@ bool UserListWidget::deleteUser(const QString &userName) void UserListWidget::setUserOnline(const QString &userName, bool online) { UserListTWI *twi = users.value(userName); - if (!twi) + if (!twi) { return; + } twi->setOnline(online); - if (online) + if (online) { ++onlineCount; - else + } else { --onlineCount; + } updateCount(); } void UserListWidget::updateCount() { QString str = titleStr; - if ((type == BuddyList) || (type == IgnoreList)) + if ((type == BuddyList) || (type == IgnoreList)) { str = str.arg(onlineCount); + } setTitle(str.arg(userTree->topLevelItemCount())); } diff --git a/cockatrice/src/interface/widgets/tabs/abstract_tab_deck_editor.cpp b/cockatrice/src/interface/widgets/tabs/abstract_tab_deck_editor.cpp index a739ac83b..66609456e 100644 --- a/cockatrice/src/interface/widgets/tabs/abstract_tab_deck_editor.cpp +++ b/cockatrice/src/interface/widgets/tabs/abstract_tab_deck_editor.cpp @@ -144,10 +144,11 @@ void AbstractTabDeckEditor::addCardHelper(const ExactCard &card, const QString & */ void AbstractTabDeckEditor::actAddCard(const ExactCard &card) { - if (QApplication::keyboardModifiers() & Qt::ControlModifier) + if (QApplication::keyboardModifiers() & Qt::ControlModifier) { actAddCardToSideboard(card); - else + } else { addCardHelper(card, DECK_ZONE_MAIN); + } deckMenu->setSaveStatus(true); } @@ -201,8 +202,9 @@ void AbstractTabDeckEditor::setDeck(const LoadedDeck &_deck) void AbstractTabDeckEditor::actNewDeck() { auto deckOpenLocation = confirmOpen(false); - if (deckOpenLocation == CANCELLED) + if (deckOpenLocation == CANCELLED) { return; + } if (deckOpenLocation == NEW_TAB) { emit openDeckEditor(LoadedDeck()); @@ -227,22 +229,25 @@ void AbstractTabDeckEditor::cleanDeckAndResetModified() AbstractTabDeckEditor::DeckOpenLocation AbstractTabDeckEditor::confirmOpen(const bool openInSameTabIfBlank) { if (SettingsCache::instance().getOpenDeckInNewTab()) { - if (openInSameTabIfBlank && deckStateManager->isBlankNewDeck()) + if (openInSameTabIfBlank && deckStateManager->isBlankNewDeck()) { return SAME_TAB; - else + } else { return NEW_TAB; + } } - if (!deckStateManager->isModified()) + if (!deckStateManager->isModified()) { return SAME_TAB; + } tabSupervisor->setCurrentWidget(this); QMessageBox *msgBox = createSaveConfirmationWindow(); QPushButton *newTabButton = msgBox->addButton(tr("Open in new tab"), QMessageBox::ApplyRole); int ret = msgBox->exec(); - if (msgBox->clickedButton() == newTabButton) + if (msgBox->clickedButton() == newTabButton) { return NEW_TAB; + } switch (ret) { case QMessageBox::Save: @@ -275,12 +280,14 @@ QMessageBox *AbstractTabDeckEditor::createSaveConfirmationWindow() void AbstractTabDeckEditor::actLoadDeck() { auto deckOpenLocation = confirmOpen(); - if (deckOpenLocation == CANCELLED) + if (deckOpenLocation == CANCELLED) { return; + } DlgLoadDeck dialog(this); - if (!dialog.exec()) + if (!dialog.exec()) { return; + } QString fileName = dialog.selectedFiles().at(0); openDeckFromFile(fileName, deckOpenLocation); @@ -293,8 +300,9 @@ void AbstractTabDeckEditor::actLoadDeck() void AbstractTabDeckEditor::actOpenRecent(const QString &fileName) { auto deckOpenLocation = confirmOpen(); - if (deckOpenLocation == CANCELLED) + if (deckOpenLocation == CANCELLED) { return; + } openDeckFromFile(fileName, deckOpenLocation); } @@ -347,8 +355,9 @@ bool AbstractTabDeckEditor::actSaveDeck() return true; } - if (loadedDeck.lastLoadInfo.fileName.isEmpty()) + if (loadedDeck.lastLoadInfo.fileName.isEmpty()) { return actSaveDeckAs(); + } if (DeckLoader::saveToFile(loadedDeck)) { deckStateManager->setModified(false); @@ -376,8 +385,9 @@ bool AbstractTabDeckEditor::actSaveDeckAs() dialog.setNameFilters(DeckLoader::FILE_NAME_FILTERS); dialog.selectFile(deckList.getName().trimmed()); - if (!dialog.exec()) + if (!dialog.exec()) { return false; + } QString fileName = dialog.selectedFiles().at(0); DeckFileFormat::Format fmt = DeckFileFormat::getFormatFromName(fileName); @@ -403,10 +413,11 @@ bool AbstractTabDeckEditor::actSaveDeckAs() */ void AbstractTabDeckEditor::saveDeckRemoteFinished(const Response &response) { - if (response.response_code() != Response::RespOk) + if (response.response_code() != Response::RespOk) { QMessageBox::critical(this, tr("Error"), tr("The deck could not be saved.")); - else + } else { deckStateManager->setModified(false); + } } /** @@ -416,12 +427,14 @@ void AbstractTabDeckEditor::saveDeckRemoteFinished(const Response &response) void AbstractTabDeckEditor::actLoadDeckFromClipboard() { auto deckOpenLocation = confirmOpen(); - if (deckOpenLocation == CANCELLED) + if (deckOpenLocation == CANCELLED) { return; + } DlgLoadDeckFromClipboard dlg(this); - if (!dlg.exec()) + if (!dlg.exec()) { return; + } if (deckOpenLocation == NEW_TAB) { emit openDeckEditor({.deckList = dlg.getDeckList()}); @@ -441,8 +454,9 @@ void AbstractTabDeckEditor::editDeckInClipboard(bool annotated) { LoadedDeck loadedDeck = deckStateManager->toLoadedDeck(); DlgEditDeckInClipboard dlg(loadedDeck.deckList, annotated, this); - if (!dlg.exec()) + if (!dlg.exec()) { return; + } setDeck({dlg.getDeckList(), loadedDeck.lastLoadInfo}); deckStateManager->setModified(true); @@ -500,12 +514,14 @@ void AbstractTabDeckEditor::actPrintDeck() void AbstractTabDeckEditor::actLoadDeckFromWebsite() { auto deckOpenLocation = confirmOpen(); - if (deckOpenLocation == CANCELLED) + if (deckOpenLocation == CANCELLED) { return; + } DlgLoadDeckFromWebsite dlg(this); - if (!dlg.exec()) + if (!dlg.exec()) { return; + } if (deckOpenLocation == NEW_TAB) { emit openDeckEditor({.deckList = dlg.getDeck()}); @@ -588,10 +604,11 @@ bool AbstractTabDeckEditor::confirmClose() if (deckStateManager->isModified()) { tabSupervisor->setCurrentWidget(this); int ret = createSaveConfirmationWindow()->exec(); - if (ret == QMessageBox::Save) + if (ret == QMessageBox::Save) { return actSaveDeck(); - else if (ret == QMessageBox::Cancel) + } else if (ret == QMessageBox::Cancel) { return false; + } } return true; } @@ -599,7 +616,8 @@ bool AbstractTabDeckEditor::confirmClose() /** @brief Handles close requests from outside (tab manager). */ bool AbstractTabDeckEditor::closeRequest() { - if (!confirmClose()) + if (!confirmClose()) { return false; + } return close(); } diff --git a/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/archidekt_formats.h b/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/archidekt_formats.h index ac1b66e14..5b5c16302 100644 --- a/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/archidekt_formats.h +++ b/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/archidekt_formats.h @@ -98,55 +98,79 @@ inline static DeckFormat apiNameToFormat(const QString &name) { const QString n = name.trimmed(); - if (n.compare("Standard", Qt::CaseInsensitive) == 0) + if (n.compare("Standard", Qt::CaseInsensitive) == 0) { return DeckFormat::Standard; - if (n.compare("Modern", Qt::CaseInsensitive) == 0) + } + if (n.compare("Modern", Qt::CaseInsensitive) == 0) { return DeckFormat::Modern; - if (n.compare("Commander", Qt::CaseInsensitive) == 0) + } + if (n.compare("Commander", Qt::CaseInsensitive) == 0) { return DeckFormat::Commander; - if (n.compare("Legacy", Qt::CaseInsensitive) == 0) + } + if (n.compare("Legacy", Qt::CaseInsensitive) == 0) { return DeckFormat::Legacy; - if (n.compare("Vintage", Qt::CaseInsensitive) == 0) + } + if (n.compare("Vintage", Qt::CaseInsensitive) == 0) { return DeckFormat::Vintage; - if (n.compare("Pauper", Qt::CaseInsensitive) == 0) + } + if (n.compare("Pauper", Qt::CaseInsensitive) == 0) { return DeckFormat::Pauper; - if (n.compare("Custom", Qt::CaseInsensitive) == 0) + } + if (n.compare("Custom", Qt::CaseInsensitive) == 0) { return DeckFormat::Custom; - if (n.compare("Frontier", Qt::CaseInsensitive) == 0) + } + if (n.compare("Frontier", Qt::CaseInsensitive) == 0) { return DeckFormat::Frontier; - if (n.compare("Future Std", Qt::CaseInsensitive) == 0) + } + if (n.compare("Future Std", Qt::CaseInsensitive) == 0) { return DeckFormat::FutureStandard; - if (n.compare("Penny Dreadful", Qt::CaseInsensitive) == 0) + } + if (n.compare("Penny Dreadful", Qt::CaseInsensitive) == 0) { return DeckFormat::PennyDreadful; - if (n.compare("1v1 Commander", Qt::CaseInsensitive) == 0) + } + if (n.compare("1v1 Commander", Qt::CaseInsensitive) == 0) { return DeckFormat::Commander1v1; - if (n.compare("Dual Commander", Qt::CaseInsensitive) == 0) + } + if (n.compare("Dual Commander", Qt::CaseInsensitive) == 0) { return DeckFormat::DualCommander; - if (n.compare("Brawl", Qt::CaseInsensitive) == 0) + } + if (n.compare("Brawl", Qt::CaseInsensitive) == 0) { return DeckFormat::Brawl; + } - if (n.compare("Alchemy", Qt::CaseInsensitive) == 0) + if (n.compare("Alchemy", Qt::CaseInsensitive) == 0) { return DeckFormat::Alchemy; - if (n.compare("Historic", Qt::CaseInsensitive) == 0) + } + if (n.compare("Historic", Qt::CaseInsensitive) == 0) { return DeckFormat::Historic; - if (n.compare("Gladiator", Qt::CaseInsensitive) == 0) + } + if (n.compare("Gladiator", Qt::CaseInsensitive) == 0) { return DeckFormat::Gladiator; - if (n.compare("Oathbreaker", Qt::CaseInsensitive) == 0) + } + if (n.compare("Oathbreaker", Qt::CaseInsensitive) == 0) { return DeckFormat::Oathbreaker; - if (n.compare("Old School", Qt::CaseInsensitive) == 0) + } + if (n.compare("Old School", Qt::CaseInsensitive) == 0) { return DeckFormat::OldSchool; - if (n.compare("Pauper Commander", Qt::CaseInsensitive) == 0) + } + if (n.compare("Pauper Commander", Qt::CaseInsensitive) == 0) { return DeckFormat::PauperCommander; - if (n.compare("Pioneer", Qt::CaseInsensitive) == 0) + } + if (n.compare("Pioneer", Qt::CaseInsensitive) == 0) { return DeckFormat::Pioneer; - if (n.compare("PreDH", Qt::CaseInsensitive) == 0) + } + if (n.compare("PreDH", Qt::CaseInsensitive) == 0) { return DeckFormat::PreDH; - if (n.compare("Premodern", Qt::CaseInsensitive) == 0) + } + if (n.compare("Premodern", Qt::CaseInsensitive) == 0) { return DeckFormat::Premodern; - if (n.compare("Standard Brawl", Qt::CaseInsensitive) == 0) + } + if (n.compare("Standard Brawl", Qt::CaseInsensitive) == 0) { return DeckFormat::StandardBrawl; - if (n.compare("Timeless", Qt::CaseInsensitive) == 0) + } + if (n.compare("Timeless", Qt::CaseInsensitive) == 0) { return DeckFormat::Timeless; + } return DeckFormat::Unknown; } diff --git a/cockatrice/src/interface/widgets/tabs/api/archidekt/display/archidekt_api_response_deck_entry_display_widget.cpp b/cockatrice/src/interface/widgets/tabs/api/archidekt/display/archidekt_api_response_deck_entry_display_widget.cpp index c26220869..70156df79 100644 --- a/cockatrice/src/interface/widgets/tabs/api/archidekt/display/archidekt_api_response_deck_entry_display_widget.cpp +++ b/cockatrice/src/interface/widgets/tabs/api/archidekt/display/archidekt_api_response_deck_entry_display_widget.cpp @@ -20,21 +20,27 @@ static QString timeAgo(const QString ×tamp) { QDateTime dt = QDateTime::fromString(timestamp, Qt::ISODate); - if (!dt.isValid()) + if (!dt.isValid()) { return timestamp; // fallback if parsing fails + } qint64 secs = dt.secsTo(QDateTime::currentDateTimeUtc()); - if (secs < 60) + if (secs < 60) { return QString("%1 seconds ago").arg(secs); - if (secs < 3600) + } + if (secs < 3600) { return QString("%1 minutes ago").arg(secs / 60); - if (secs < 86400) + } + if (secs < 86400) { return QString("%1 hours ago").arg(secs / 3600); - if (secs < 30 * 86400) + } + if (secs < 30 * 86400) { return QString("%1 days ago").arg(secs / 86400); - if (secs < 365 * 86400) + } + if (secs < 365 * 86400) { return QString("%1 months ago").arg(secs / (30 * 86400)); + } return QString("%1 years ago").arg(secs / (365 * 86400)); } diff --git a/cockatrice/src/interface/widgets/tabs/api/archidekt/tab_archidekt.cpp b/cockatrice/src/interface/widgets/tabs/api/archidekt/tab_archidekt.cpp index 352d55c79..9cac74d50 100644 --- a/cockatrice/src/interface/widgets/tabs/api/archidekt/tab_archidekt.cpp +++ b/cockatrice/src/interface/widgets/tabs/api/archidekt/tab_archidekt.cpp @@ -93,10 +93,11 @@ void TabArchidekt::initializeUi() colorLayout->addWidget(manaSymbol); connect(manaSymbol, &ManaSymbolWidget::colorToggled, this, [this](QChar c, bool active) { - if (active) + if (active) { activeColors.insert(c); - else + } else { activeColors.remove(c); + } doSearch(); }); } @@ -298,16 +299,18 @@ void TabArchidekt::setupFilterWidgets() searchModel->updateSearchResults(text); QString pattern = ".*" + QRegularExpression::escape(text) + ".*"; proxyModel->setFilterRegularExpression(QRegularExpression(pattern, QRegularExpression::CaseInsensitiveOption)); - if (!text.isEmpty()) + if (!text.isEmpty()) { completer->complete(); + } }); connect(commandersField, &QLineEdit::textChanged, this, [=](const QString &text) { searchModel->updateSearchResults(text); QString pattern = ".*" + QRegularExpression::escape(text) + ".*"; proxyModel->setFilterRegularExpression(QRegularExpression(pattern, QRegularExpression::CaseInsensitiveOption)); - if (!text.isEmpty()) + if (!text.isEmpty()) { completer->complete(); + } }); // Assemble secondary toolbar @@ -492,12 +495,13 @@ QString TabArchidekt::buildSearchUrl() QString logic = "GTE"; QString selected = minDeckSizeLogicCombo->currentText(); - if (selected == "≥") + if (selected == "≥") { logic = "GTE"; - else if (selected == "≤") + } else if (selected == "≤") { logic = "LTE"; - else + } else { logic = ""; + } if (!logic.isEmpty()) { query.addQueryItem("sizeLogic", logic); diff --git a/cockatrice/src/interface/widgets/tabs/tab_deck_editor.cpp b/cockatrice/src/interface/widgets/tabs/tab_deck_editor.cpp index 59ee6bdeb..77dfddb4a 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_deck_editor.cpp +++ b/cockatrice/src/interface/widgets/tabs/tab_deck_editor.cpp @@ -81,8 +81,9 @@ void TabDeckEditor::createMenus() QString TabDeckEditor::getTabText() const { QString result = tr("Deck: %1").arg(deckStateManager->getSimpleDeckName()); - if (deckStateManager->isModified()) + if (deckStateManager->isModified()) { result.prepend("* "); + } return result; } @@ -137,9 +138,9 @@ void TabDeckEditor::loadLayout() LayoutsSettings &layouts = SettingsCache::instance().layouts(); auto layoutState = layouts.getDeckEditorLayoutState(); - if (layoutState.isNull()) + if (layoutState.isNull()) { restartLayout(); - else { + } else { restoreState(layoutState); restoreGeometry(layouts.getDeckEditorGeometry()); } diff --git a/cockatrice/src/interface/widgets/tabs/tab_deck_storage.cpp b/cockatrice/src/interface/widgets/tabs/tab_deck_storage.cpp index 26e3f2ecf..bdf7901f1 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_deck_storage.cpp +++ b/cockatrice/src/interface/widgets/tabs/tab_deck_storage.cpp @@ -181,8 +181,9 @@ void TabDeckStorage::retranslateUi() QString TabDeckStorage::getTargetPath() const { RemoteDeckList_TreeModel::Node *curRight = serverDirView->getCurrentItem(); - if (curRight == nullptr) + if (curRight == nullptr) { return {}; + } auto *dir = dynamic_cast(curRight); if (dir == nullptr) { dir = dynamic_cast(curRight->getParent()); @@ -237,13 +238,15 @@ void TabDeckStorage::actOpenLocalDeck() { QModelIndexList curLefts = localDirView->selectionModel()->selectedRows(); for (const auto &curLeft : curLefts) { - if (localDirModel->isDir(curLeft)) + if (localDirModel->isDir(curLeft)) { continue; + } QString filePath = localDirModel->filePath(curLeft); std::optional deckOpt = DeckLoader::loadFromFile(filePath, DeckFileFormat::Cockatrice, true); - if (!deckOpt) + if (!deckOpt) { continue; + } emit openDeckEditor(deckOpt.value()); } @@ -320,10 +323,12 @@ void TabDeckStorage::uploadDeck(const QString &filePath, const QString &targetPa QString deckName = getTextWithMax(this, tr("Enter deck name"), tr("This decklist does not have a name.\nPlease enter a name:"), QLineEdit::Normal, deckFileInfo.completeBaseName(), &ok); - if (!ok) + if (!ok) { return; - if (deckName.isEmpty()) + } + if (deckName.isEmpty()) { deckName = tr("Unnamed deck"); + } deck.setName(deckName); } else { deck.setName(deck.getName().left(MAX_NAME_LENGTH)); @@ -372,8 +377,9 @@ void TabDeckStorage::actNewLocalFolder() bool ok; QString folderName = QInputDialog::getText(this, tr("New folder"), tr("Name of new folder:"), QLineEdit::Normal, "", &ok); - if (!ok || folderName.isEmpty()) + if (!ok || folderName.isEmpty()) { return; + } localDirModel->mkdir(dirIndex, folderName); } @@ -387,8 +393,9 @@ void TabDeckStorage::actDeleteLocalDeck() } if (QMessageBox::warning(this, tr("Delete local file"), tr("Are you sure you want to delete the selected files?"), - QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes) + QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes) { return; + } for (const auto &curLeft : curLefts) { if (curLeft.isValid()) { @@ -414,8 +421,9 @@ void TabDeckStorage::actOpenRemoteDeck() { for (const auto &curRight : serverDirView->getCurrentSelection()) { RemoteDeckList_TreeModel::FileNode *node = dynamic_cast(curRight); - if (!node) + if (!node) { continue; + } Command_DeckDownload cmd; cmd.set_deck_id(node->getId()); @@ -428,15 +436,17 @@ void TabDeckStorage::actOpenRemoteDeck() void TabDeckStorage::openRemoteDeckFinished(const Response &r, const CommandContainer &commandContainer) { - if (r.response_code() != Response::RespOk) + if (r.response_code() != Response::RespOk) { return; + } const Response_DeckDownload &resp = r.GetExtension(Response_DeckDownload::ext); const Command_DeckDownload &cmd = commandContainer.session_command(0).GetExtension(Command_DeckDownload::ext); std::optional deckOpt = DeckLoader::loadFromRemote(QString::fromStdString(resp.deck()), cmd.deck_id()); - if (!deckOpt) + if (!deckOpt) { return; + } emit openDeckEditor(deckOpt.value()); } @@ -488,8 +498,9 @@ void TabDeckStorage::downloadFinished(const Response &r, const CommandContainer & /*commandContainer*/, const QVariant &extraData) { - if (r.response_code() != Response::RespOk) + if (r.response_code() != Response::RespOk) { return; + } const Response_DeckDownload &resp = r.GetExtension(Response_DeckDownload::ext); QString filePath = extraData.toString(); @@ -504,12 +515,14 @@ void TabDeckStorage::actNewFolder() QString targetPath = getTargetPath(); int max_length = MAX_NAME_LENGTH - targetPath.length() - 1; // generated length would be path + / + name - if (max_length < 1) // can't create path that's short enough + if (max_length < 1) { // can't create path that's short enough return; + } QString folderName = getTextWithMax(this, tr("New folder"), tr("Name of new folder:"), max_length); - if (folderName.isEmpty()) + if (folderName.isEmpty()) { return; + } // '/' isn't a valid filename character on *nix so we're choosing to replace it with a different arbitrary // character. @@ -527,8 +540,9 @@ void TabDeckStorage::actNewFolder() void TabDeckStorage::newFolderFinished(const Response &response, const CommandContainer &commandContainer) { - if (response.response_code() != Response::RespOk) + if (response.response_code() != Response::RespOk) { return; + } const Command_DeckNewDir &cmd = commandContainer.session_command(0).GetExtension(Command_DeckNewDir::ext); serverDirView->addFolderToTree(QString::fromStdString(cmd.dir_name()), @@ -562,8 +576,9 @@ void TabDeckStorage::deleteRemoteDeck(const RemoteDeckList_TreeModel::Node *curR PendingCommand *pend; if (const auto *dir = dynamic_cast(curRight)) { QString targetPath = dir->getPath(); - if (targetPath.isEmpty()) + if (targetPath.isEmpty()) { return; + } if (targetPath.length() > MAX_NAME_LENGTH) { qCritical() << "target path to delete is too long" << targetPath; return; @@ -585,22 +600,26 @@ void TabDeckStorage::deleteRemoteDeck(const RemoteDeckList_TreeModel::Node *curR void TabDeckStorage::deleteDeckFinished(const Response &response, const CommandContainer &commandContainer) { - if (response.response_code() != Response::RespOk) + if (response.response_code() != Response::RespOk) { return; + } const Command_DeckDel &cmd = commandContainer.session_command(0).GetExtension(Command_DeckDel::ext); RemoteDeckList_TreeModel::Node *toDelete = serverDirView->getNodeById(cmd.deck_id()); - if (toDelete) + if (toDelete) { serverDirView->removeNode(toDelete); + } } void TabDeckStorage::deleteFolderFinished(const Response &response, const CommandContainer &commandContainer) { - if (response.response_code() != Response::RespOk) + if (response.response_code() != Response::RespOk) { return; + } const Command_DeckDelDir &cmd = commandContainer.session_command(0).GetExtension(Command_DeckDelDir::ext); RemoteDeckList_TreeModel::Node *toDelete = serverDirView->getNodeByPath(QString::fromStdString(cmd.path())); - if (toDelete) + if (toDelete) { serverDirView->removeNode(toDelete); + } } diff --git a/cockatrice/src/interface/widgets/tabs/tab_game.cpp b/cockatrice/src/interface/widgets/tabs/tab_game.cpp index 161829b35..90756dad2 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_game.cpp +++ b/cockatrice/src/interface/widgets/tabs/tab_game.cpp @@ -125,8 +125,9 @@ TabGame::TabGame(TabSupervisor *_tabSupervisor, refreshShortcuts(); // append game to rooms game list for others to see - for (int i = game->getGameMetaInfo()->gameTypesSize() - 1; i >= 0; i--) + for (int i = game->getGameMetaInfo()->gameTypesSize() - 1; i >= 0; i--) { gameTypes.append(game->getGameMetaInfo()->findRoomGameType(i)); + } QTimer::singleShot(0, this, &TabGame::loadLayout); } @@ -282,12 +283,14 @@ void TabGame::retranslateUi() updatePlayerListDockTitle(); cardInfoDock->setWindowTitle(tr("Card Info") + (cardInfoDock->isWindow() ? tabText : QString())); messageLayoutDock->setWindowTitle(tr("Messages") + (messageLayoutDock->isWindow() ? tabText : QString())); - if (replayDock) + if (replayDock) { replayDock->setWindowTitle(tr("Replay Timeline") + (replayDock->isWindow() ? tabText : QString())); + } if (phasesMenu) { - for (int i = 0; i < phaseActions.size(); ++i) + for (int i = 0; i < phaseActions.size(); ++i) { phaseActions[i]->setText(phasesToolbar->getLongPhaseName(i)); + } phasesMenu->setTitle(tr("&Phases")); } @@ -313,8 +316,9 @@ void TabGame::retranslateUi() if (aRotateViewCCW) { aRotateViewCCW->setText(tr("Rotate View Co&unterclockwise")); } - if (aGameInfo) + if (aGameInfo) { aGameInfo->setText(tr("Game &information")); + } if (aConcede) { if (game->getPlayerManager()->isMainPlayerConceded()) { aConcede->setText(tr("Un&concede")); @@ -361,11 +365,13 @@ void TabGame::retranslateUi() QMapIterator i(game->getPlayerManager()->getPlayers()); - while (i.hasNext()) + while (i.hasNext()) { i.next().value()->getGraphicsItem()->retranslateUi(); + } QMapIterator j(deckViewContainers); - while (j.hasNext()) + while (j.hasNext()) { j.next().value()->playerDeckView->retranslateUi(); + } scene->retranslateUi(); } @@ -484,18 +490,21 @@ void TabGame::actGameInfo() void TabGame::actConcede() { Player *player = game->getPlayerManager()->getActiveLocalPlayer(game->getGameState()->getActivePlayer()); - if (player == nullptr) + if (player == nullptr) { return; + } if (!player->getConceded()) { if (QMessageBox::question(this, tr("Concede"), tr("Are you sure you want to concede this game?"), - QMessageBox::Yes | QMessageBox::No, QMessageBox::No) != QMessageBox::Yes) + QMessageBox::Yes | QMessageBox::No, QMessageBox::No) != QMessageBox::Yes) { return; + } emit game->getPlayerManager()->activeLocalPlayerConceded(); } else { if (QMessageBox::question(this, tr("Unconcede"), tr("You have already conceded. Do you want to return to this game?"), - QMessageBox::Yes | QMessageBox::No, QMessageBox::No) != QMessageBox::Yes) + QMessageBox::Yes | QMessageBox::No, QMessageBox::No) != QMessageBox::Yes) { return; + } emit game->getPlayerManager()->activeLocalPlayerUnconceded(); } } @@ -511,20 +520,23 @@ bool TabGame::leaveGame() if (!game->getPlayerManager()->isSpectator()) { tabSupervisor->setCurrentWidget(this); if (QMessageBox::question(this, tr("Leave game"), tr("Are you sure you want to leave this game?"), - QMessageBox::Yes | QMessageBox::No, QMessageBox::No) != QMessageBox::Yes) + QMessageBox::Yes | QMessageBox::No, QMessageBox::No) != QMessageBox::Yes) { return false; + } } - if (!replayDock) + if (!replayDock) { emit gameLeft(); + } } return true; } void TabGame::actSay() { - if (completer->popup()->isVisible()) + if (completer->popup()->isVisible()) { return; + } if (sayEdit->text().startsWith("/card ")) { cardInfoFrameWidget->setCard(sayEdit->text().mid(6)); @@ -569,8 +581,9 @@ void TabGame::actPhaseAction() void TabGame::actNextPhase() { int phase = game->getGameState()->getCurrentPhase(); - if (++phase >= phasesToolbar->phaseCount()) + if (++phase >= phasesToolbar->phaseCount()) { phase = 0; + } emit phaseChanged(phase); } @@ -596,8 +609,9 @@ void TabGame::actRemoveLocalArrows() QMapIterator playerIterator(game->getPlayerManager()->getPlayers()); while (playerIterator.hasNext()) { Player *player = playerIterator.next().value(); - if (!player->getPlayerInfo()->getLocal()) + if (!player->getPlayerInfo()->getLocal()) { continue; + } QMapIterator arrowIterator(player->getArrows()); while (arrowIterator.hasNext()) { ArrowItem *a = arrowIterator.next().value(); @@ -807,8 +821,9 @@ void TabGame::startGame(bool _resuming) if (!_resuming) { QMapIterator playerIterator(game->getPlayerManager()->getPlayers()); - while (playerIterator.hasNext()) + while (playerIterator.hasNext()) { playerIterator.next().value()->setGameStarted(); + } } playerListWidget->setGameStarted(true, game->getGameState()->isResuming()); @@ -851,8 +866,9 @@ void TabGame::closeGame() Player *TabGame::setActivePlayer(int id) { Player *player = game->getPlayerManager()->getPlayer(id); - if (!player) + if (!player) { return nullptr; + } playerListWidget->setActivePlayer(id); QMapIterator i(game->getPlayerManager()->getPlayers()); @@ -894,26 +910,31 @@ QString TabGame::getTabText() const QString gameTypeInfo; if (!gameTypes.empty()) { gameTypeInfo = gameTypes.at(0); - if (gameTypes.size() > 1) + if (gameTypes.size() > 1) { gameTypeInfo.append("..."); + } } QString gameDesc(game->getGameMetaInfo()->description()); QString gameId(QString::number(game->getGameMetaInfo()->gameId())); QString tabText; - if (replayDock) + if (replayDock) { tabText.append(tr("Replay") + " "); - if (!gameTypeInfo.isEmpty()) - tabText.append(gameTypeInfo + " "); - if (!gameDesc.isEmpty()) { - if (gameDesc.length() >= 15) - tabText.append("| " + gameDesc.left(15) + "... "); - else - tabText.append("| " + gameDesc + " "); } - if (!tabText.isEmpty()) + if (!gameTypeInfo.isEmpty()) { + tabText.append(gameTypeInfo + " "); + } + if (!gameDesc.isEmpty()) { + if (gameDesc.length() >= 15) { + tabText.append("| " + gameDesc.left(15) + "... "); + } else { + tabText.append("| " + gameDesc + " "); + } + } + if (!tabText.isEmpty()) { tabText.append("| "); + } tabText.append("#" + gameId); return tabText; @@ -1127,9 +1148,10 @@ void TabGame::actResetLayout() void TabGame::createPlayAreaWidget(bool bReplay) { phasesToolbar = new PhasesToolbar; - if (!bReplay) + if (!bReplay) { connect(phasesToolbar, &PhasesToolbar::sendGameCommand, game->getGameEventHandler(), qOverload(&GameEventHandler::sendGameCommand)); + } scene = new GameScene(phasesToolbar, this); connect(game->getPlayerManager(), &PlayerManager::playerConceded, scene, &GameScene::rearrange); connect(game->getPlayerManager(), &PlayerManager::playerCountChanged, scene, &GameScene::rearrange); diff --git a/cockatrice/src/interface/widgets/tabs/tab_logs.cpp b/cockatrice/src/interface/widgets/tabs/tab_logs.cpp index e4f699160..9a030e7d9 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_logs.cpp +++ b/cockatrice/src/interface/widgets/tabs/tab_logs.cpp @@ -83,18 +83,22 @@ void TabLog::getClicked() privateChat->setChecked(true); } - if (maximumResults->value() == 0) + if (maximumResults->value() == 0) { maximumResults->setValue(1000); + } int dateRange = 0; - if (lastHour->isChecked()) + if (lastHour->isChecked()) { dateRange = 1; + } - if (today->isChecked()) + if (today->isChecked()) { dateRange = 24; + } - if (pastDays->isChecked()) + if (pastDays->isChecked()) { dateRange = pastXDays->value() * 24; + } Command_ViewLogHistory cmd; cmd.set_user_name(findUsername->text().toStdString()); diff --git a/cockatrice/src/interface/widgets/tabs/tab_message.cpp b/cockatrice/src/interface/widgets/tabs/tab_message.cpp index bd0457990..d77cb0391 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_message.cpp +++ b/cockatrice/src/interface/widgets/tabs/tab_message.cpp @@ -72,8 +72,9 @@ void TabMessage::retranslateUi() void TabMessage::tabActivated() { - if (!sayEdit->hasFocus()) + if (!sayEdit->hasFocus()) { sayEdit->setFocus(); + } } QString TabMessage::getUserName() const @@ -94,8 +95,9 @@ void TabMessage::closeEvent(QCloseEvent *event) void TabMessage::sendMessage() { - if (sayEdit->text().isEmpty() || !userOnline) + if (sayEdit->text().isEmpty() || !userOnline) { return; + } Command_Message cmd; cmd.set_user_name(otherUserInfo->name()); @@ -110,9 +112,10 @@ void TabMessage::sendMessage() void TabMessage::messageSent(const Response &response) { - if (response.response_code() == Response::RespInIgnoreList) + if (response.response_code() == Response::RespInIgnoreList) { chatView->appendMessage(tr( "This user is ignoring you, they cannot see your messages in main chat and you cannot join their games.")); + } } void TabMessage::processUserMessageEvent(const Event_UserMessage &event) @@ -120,12 +123,15 @@ void TabMessage::processUserMessageEvent(const Event_UserMessage &event) auto userInfo = event.sender_name() == otherUserInfo->name() ? otherUserInfo : ownUserInfo; chatView->appendMessage(QString::fromStdString(event.message()), {}, *userInfo, true); - if (tabSupervisor->currentIndex() != tabSupervisor->indexOf(this)) + if (tabSupervisor->currentIndex() != tabSupervisor->indexOf(this)) { soundEngine->playSound("private_message"); - if (SettingsCache::instance().getShowMessagePopup() && shouldShowSystemPopup(event)) + } + if (SettingsCache::instance().getShowMessagePopup() && shouldShowSystemPopup(event)) { showSystemPopup(event); - if (QString::fromStdString(event.sender_name()).toLower().simplified() == "servatrice") + } + if (QString::fromStdString(event.sender_name()).toLower().simplified() == "servatrice") { sayEdit->setDisabled(true); + } emit userEvent(); } diff --git a/cockatrice/src/interface/widgets/tabs/tab_replays.cpp b/cockatrice/src/interface/widgets/tabs/tab_replays.cpp index 570677ada..af52c038f 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_replays.cpp +++ b/cockatrice/src/interface/widgets/tabs/tab_replays.cpp @@ -256,13 +256,15 @@ void TabReplays::actOpenLocalReplay() { QModelIndexList curLefts = localDirView->selectionModel()->selectedRows(); for (const auto &curLeft : curLefts) { - if (localDirModel->isDir(curLeft)) + if (localDirModel->isDir(curLeft)) { continue; + } QString filePath = localDirModel->filePath(curLeft); QFile f(filePath); - if (!f.open(QIODevice::ReadOnly)) + if (!f.open(QIODevice::ReadOnly)) { continue; + } QByteArray _data = f.readAll(); f.close(); @@ -319,8 +321,9 @@ void TabReplays::actNewLocalFolder() bool ok; QString folderName = QInputDialog::getText(this, tr("New folder"), tr("Name of new folder:"), QLineEdit::Normal, "", &ok); - if (!ok || folderName.isEmpty()) + if (!ok || folderName.isEmpty()) { return; + } localDirModel->mkdir(dirIndex, folderName); } @@ -378,8 +381,9 @@ void TabReplays::actOpenRemoteReplay() void TabReplays::openRemoteReplayFinished(const Response &r) { - if (r.response_code() != Response::RespOk) + if (r.response_code() != Response::RespOk) { return; + } const Response_ReplayDownload &resp = r.GetExtension(Response_ReplayDownload::ext); GameReplay *replay = new GameReplay; @@ -438,8 +442,9 @@ void TabReplays::downloadFinished(const Response &r, const CommandContainer & /* commandContainer */, const QVariant &extraData) { - if (r.response_code() != Response::RespOk) + if (r.response_code() != Response::RespOk) { return; + } const Response_ReplayDownload &resp = r.GetExtension(Response_ReplayDownload::ext); QString filePath = extraData.toString(); @@ -475,8 +480,9 @@ void TabReplays::actKeepRemoteReplay() void TabReplays::keepRemoteReplayFinished(const Response &r, const CommandContainer &commandContainer) { - if (r.response_code() != Response::RespOk) + if (r.response_code() != Response::RespOk) { return; + } const Command_ReplayModifyMatch &cmd = commandContainer.session_command(0).GetExtension(Command_ReplayModifyMatch::ext); @@ -513,8 +519,9 @@ void TabReplays::actDeleteRemoteReplay() void TabReplays::deleteRemoteReplayFinished(const Response &r, const CommandContainer &commandContainer) { - if (r.response_code() != Response::RespOk) + if (r.response_code() != Response::RespOk) { return; + } const Command_ReplayDeleteMatch &cmd = commandContainer.session_command(0).GetExtension(Command_ReplayDeleteMatch::ext); diff --git a/cockatrice/src/interface/widgets/tabs/tab_room.cpp b/cockatrice/src/interface/widgets/tabs/tab_room.cpp index 92e38662b..424742e9b 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_room.cpp +++ b/cockatrice/src/interface/widgets/tabs/tab_room.cpp @@ -41,9 +41,10 @@ TabRoom::TabRoom(TabSupervisor *_tabSupervisor, ownUser(_ownUser), userListProxy(_tabSupervisor->getUserListManager()) { const int gameTypeListSize = info.gametype_list_size(); - for (int i = 0; i < gameTypeListSize; ++i) + for (int i = 0; i < gameTypeListSize; ++i) { gameTypes.insert(info.gametype_list(i).game_type_id(), QString::fromStdString(info.gametype_list(i).description())); + } QMap tempMap; tempMap.insert(info.room_id(), gameTypes); @@ -117,8 +118,9 @@ TabRoom::TabRoom(TabSupervisor *_tabSupervisor, userList->sortItems(); const int gameListSize = info.game_list_size(); - for (int i = 0; i < gameListSize; ++i) + for (int i = 0; i < gameListSize; ++i) { gameSelector->processGameInfo(info.game_list(i)); + } completer = new QCompleter(autocompleteUserList, sayEdit); completer->setCaseSensitivity(Qt::CaseInsensitive); @@ -182,8 +184,9 @@ void TabRoom::closeEvent(QCloseEvent *event) void TabRoom::tabActivated() { - if (!sayEdit->hasFocus()) + if (!sayEdit->hasFocus()) { sayEdit->setFocus(); + } } QString TabRoom::sanitizeHtml(QString dirty) const @@ -211,8 +214,9 @@ void TabRoom::sendMessage() void TabRoom::sayFinished(const Response &response) { - if (response.response_code() == Response::RespChatFlood) + if (response.response_code() == Response::RespChatFlood) { chatView->appendMessage(tr("You are flooding the chat. Please wait a couple of seconds.")); + } } void TabRoom::actClearChat() @@ -258,8 +262,9 @@ void TabRoom::processRoomEvent(const RoomEvent &event) void TabRoom::processListGamesEvent(const Event_ListGames &event) { const int gameListSize = event.game_list_size(); - for (int i = 0; i < gameListSize; ++i) + for (int i = 0; i < gameListSize; ++i) { gameSelector->processGameInfo(event.game_list(i)); + } } void TabRoom::processJoinRoomEvent(const Event_JoinRoom &event) @@ -284,26 +289,30 @@ void TabRoom::processRoomSayEvent(const Event_RoomSay &event) QString senderName = QString::fromStdString(event.name()); QString message = QString::fromStdString(event.message()); - if (userListProxy->isUserIgnored(senderName)) + if (userListProxy->isUserIgnored(senderName)) { return; + } UserListTWI *twi = userList->getUsers().value(senderName); ServerInfo_User userInfo = {}; if (twi) { userInfo = twi->getUserInfo(); if (SettingsCache::instance().getIgnoreUnregisteredUsers() && - !UserLevelFlags(userInfo.user_level()).testFlag(ServerInfo_User::IsRegistered)) + !UserLevelFlags(userInfo.user_level()).testFlag(ServerInfo_User::IsRegistered)) { return; + } } - if (event.message_type() == Event_RoomSay::ChatHistory && !SettingsCache::instance().getRoomHistory()) + if (event.message_type() == Event_RoomSay::ChatHistory && !SettingsCache::instance().getRoomHistory()) { return; + } - if (event.message_type() == Event_RoomSay::ChatHistory) + if (event.message_type() == Event_RoomSay::ChatHistory) { message = "[" + QString(QDateTime::fromMSecsSinceEpoch(event.time_of()).toLocalTime().toString("d MMM yyyy HH:mm:ss")) + "] " + message; + } chatView->appendMessage(message, event.message_type(), userInfo, true); emit userEvent(false); diff --git a/cockatrice/src/interface/widgets/tabs/tab_server.cpp b/cockatrice/src/interface/widgets/tabs/tab_server.cpp index aa52b4b1a..2fce5c1fa 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_server.cpp +++ b/cockatrice/src/interface/widgets/tabs/tab_server.cpp @@ -69,27 +69,35 @@ void RoomSelector::processListRoomsEvent(const Event_ListRooms &event) for (int j = 0; j < roomList->topLevelItemCount(); ++j) { QTreeWidgetItem *twi = roomList->topLevelItem(j); if (twi->data(0, Qt::UserRole).toInt() == room.room_id()) { - if (room.has_name()) + if (room.has_name()) { twi->setData(0, Qt::DisplayRole, QString::fromStdString(room.name())); - if (room.has_description()) + } + if (room.has_description()) { twi->setData(1, Qt::DisplayRole, QString::fromStdString(room.description())); - if (room.has_permissionlevel()) + } + if (room.has_permissionlevel()) { twi->setData(2, Qt::DisplayRole, getRoomPermissionDisplay(room)); - if (room.has_player_count()) + } + if (room.has_player_count()) { twi->setData(3, Qt::DisplayRole, room.player_count()); - if (room.has_game_count()) + } + if (room.has_game_count()) { twi->setData(4, Qt::DisplayRole, room.game_count()); + } return; } } QTreeWidgetItem *twi = new QTreeWidgetItem; twi->setData(0, Qt::UserRole, room.room_id()); - if (room.has_name()) + if (room.has_name()) { twi->setData(0, Qt::DisplayRole, QString::fromStdString(room.name())); - if (room.has_description()) + } + if (room.has_description()) { twi->setData(1, Qt::DisplayRole, QString::fromStdString(room.description())); - if (room.has_permissionlevel()) + } + if (room.has_permissionlevel()) { twi->setData(2, Qt::DisplayRole, getRoomPermissionDisplay(room)); + } twi->setData(3, Qt::DisplayRole, room.player_count()); twi->setData(4, Qt::DisplayRole, room.game_count()); twi->setTextAlignment(2, Qt::AlignRight); @@ -97,9 +105,11 @@ void RoomSelector::processListRoomsEvent(const Event_ListRooms &event) twi->setTextAlignment(4, Qt::AlignRight); roomList->addTopLevelItem(twi); - if (room.has_auto_join()) - if (room.auto_join()) + if (room.has_auto_join()) { + if (room.auto_join()) { emit joinRoomRequest(room.room_id(), false); + } + } } } @@ -113,10 +123,12 @@ QString RoomSelector::getRoomPermissionDisplay(const ServerInfo_Room &room) */ QString roomPermissionDisplay = QString::fromStdString(room.privilegelevel()).toLower(); - if (QString::fromStdString(room.permissionlevel()).toLower() != "none") + if (QString::fromStdString(room.permissionlevel()).toLower() != "none") { roomPermissionDisplay = QString::fromStdString(room.permissionlevel()).toLower(); - if (roomPermissionDisplay == "") // catch all for misconfigured .ini room definitions + } + if (roomPermissionDisplay == "") { // catch all for misconfigured .ini room definitions roomPermissionDisplay = "none"; + } return roomPermissionDisplay; } @@ -124,8 +136,9 @@ QString RoomSelector::getRoomPermissionDisplay(const ServerInfo_Room &room) void RoomSelector::joinClicked() { QTreeWidgetItem *twi = roomList->currentItem(); - if (!twi) + if (!twi) { return; + } int id = twi->data(0, Qt::UserRole).toInt(); @@ -185,8 +198,9 @@ void TabServer::joinRoom(int id, bool setCurrent) return; } - if (setCurrent) + if (setCurrent) { tabSupervisor->setCurrentWidget((QWidget *)room); + } } void TabServer::joinRoomFinished(const Response &r, diff --git a/cockatrice/src/interface/widgets/tabs/tab_supervisor.cpp b/cockatrice/src/interface/widgets/tabs/tab_supervisor.cpp index b10d615ff..3566d6939 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_supervisor.cpp +++ b/cockatrice/src/interface/widgets/tabs/tab_supervisor.cpp @@ -86,18 +86,22 @@ void CloseButton::paintEvent(QPaintEvent * /*event*/) QStyleOption opt; opt.initFrom(this); opt.state |= QStyle::State_AutoRaise; - if (isEnabled() && underMouse() && !isChecked() && !isDown()) + if (isEnabled() && underMouse() && !isChecked() && !isDown()) { opt.state |= QStyle::State_Raised; - if (isChecked()) + } + if (isChecked()) { opt.state |= QStyle::State_On; - if (isDown()) + } + if (isDown()) { opt.state |= QStyle::State_Sunken; + } if (const auto *tb = qobject_cast(parent())) { int index = tb->currentIndex(); auto position = (QTabBar::ButtonPosition)style()->styleHint(QStyle::SH_TabBar_CloseButtonPosition, nullptr, tb); - if (tb->tabButton(index, position) == this) + if (tb->tabButton(index, position) == this) { opt.state |= QStyle::State_Selected; + } } style()->drawPrimitive(QStyle::PE_IndicatorTabClose, &opt, &p, this); @@ -228,20 +232,25 @@ void TabSupervisor::retranslateUi() tabs.append(tabAccount); tabs.append(tabLog); QMapIterator roomIterator(roomTabs); - while (roomIterator.hasNext()) + while (roomIterator.hasNext()) { tabs.append(roomIterator.next().value()); + } QMapIterator gameIterator(gameTabs); - while (gameIterator.hasNext()) + while (gameIterator.hasNext()) { tabs.append(gameIterator.next().value()); + } QListIterator replayIterator(replayTabs); - while (replayIterator.hasNext()) + while (replayIterator.hasNext()) { tabs.append(replayIterator.next()); + } QListIterator deckEditorIterator(deckEditorTabs); - while (deckEditorIterator.hasNext()) + while (deckEditorIterator.hasNext()) { tabs.append(deckEditorIterator.next()); + } QMapIterator messageIterator(messageTabs); - while (messageIterator.hasNext()) + while (messageIterator.hasNext()) { tabs.append(messageIterator.next().value()); + } for (auto &tab : tabs) { if (tab) { @@ -448,9 +457,10 @@ void TabSupervisor::startLocal(const QList &_clients) isLocalGame = true; userInfo = new ServerInfo_User; localClients = _clients; - for (int i = 0; i < localClients.size(); ++i) + for (int i = 0; i < localClients.size(); ++i) { connect(localClients[i], &AbstractClient::gameEventContainerReceived, this, &TabSupervisor::processGameEventContainer); + } connect(localClients.first(), &AbstractClient::gameJoinedEventReceived, this, &TabSupervisor::localGameJoined); } @@ -459,8 +469,9 @@ void TabSupervisor::startLocal(const QList &_clients) */ void TabSupervisor::stop() { - if ((!client) && localClients.isEmpty()) + if ((!client) && localClients.isEmpty()) { return; + } resetTabsMenu(); @@ -694,10 +705,12 @@ void TabSupervisor::openTabLog() void TabSupervisor::updatePingTime(int value, int max) { - if (!tabServer) + if (!tabServer) { return; - if (tabServer->getContentsChanged()) + } + if (tabServer->getContentsChanged()) { return; + } setTabIcon(indexOf(tabServer), QIcon(PingPixmapGenerator::generatePixmap(15, value, max))); } @@ -706,12 +719,14 @@ void TabSupervisor::gameJoined(const Event_GameJoined &event) { QMap roomGameTypes; TabRoom *room = roomTabs.value(event.game_info().room_id()); - if (room) + if (room) { roomGameTypes = room->getGameTypes(); - else - for (int i = 0; i < event.game_types_size(); ++i) + } else { + for (int i = 0; i < event.game_types_size(); ++i) { roomGameTypes.insert(event.game_types(i).game_type_id(), QString::fromStdString(event.game_types(i).description())); + } + } auto *tab = new TabGame(this, QList() << client, event, roomGameTypes); connect(tab, &TabGame::gameClosing, this, &TabSupervisor::gameLeft); @@ -740,14 +755,16 @@ void TabSupervisor::localGameJoined(const Event_GameJoined &event) void TabSupervisor::gameLeft(TabGame *tab) { - if (tab == currentWidget()) + if (tab == currentWidget()) { emit setMenu(); + } gameTabs.remove(tab->getGame()->getGameMetaInfo()->gameId()); removeTab(indexOf(tab)); - if (!localClients.isEmpty()) + if (!localClients.isEmpty()) { stop(); + } } void TabSupervisor::addRoomTab(const ServerInfo_Room &info, bool setCurrent) @@ -758,14 +775,16 @@ void TabSupervisor::addRoomTab(const ServerInfo_Room &info, bool setCurrent) connect(tab, &TabRoom::openMessageDialog, this, &TabSupervisor::addMessageTab); myAddTab(tab); roomTabs.insert(info.room_id(), tab); - if (setCurrent) + if (setCurrent) { setCurrentWidget(tab); + } } void TabSupervisor::roomLeft(TabRoom *tab) { - if (tab == currentWidget()) + if (tab == currentWidget()) { emit setMenu(); + } roomTabs.remove(tab->getRoomId()); removeTab(indexOf(tab)); @@ -793,16 +812,18 @@ void TabSupervisor::openReplay(GameReplay *replay) void TabSupervisor::replayLeft(TabGame *tab) { - if (tab == currentWidget()) + if (tab == currentWidget()) { emit setMenu(); + } replayTabs.removeOne(tab); } TabMessage *TabSupervisor::addMessageTab(const QString &receiverName, bool focus) { - if (receiverName == QString::fromStdString(userInfo->name())) + if (receiverName == QString::fromStdString(userInfo->name())) { return nullptr; + } ServerInfo_User otherUser; if (auto user = userListManager->getOnlineUser(receiverName)) { @@ -814,8 +835,9 @@ TabMessage *TabSupervisor::addMessageTab(const QString &receiverName, bool focus TabMessage *tab; tab = messageTabs.value(QString::fromStdString(otherUser.name())); if (tab) { - if (focus) + if (focus) { setCurrentWidget(tab); + } return tab; } @@ -824,8 +846,9 @@ TabMessage *TabSupervisor::addMessageTab(const QString &receiverName, bool focus connect(tab, &TabMessage::maximizeClient, this, &TabSupervisor::maximizeMainWindow); myAddTab(tab); messageTabs.insert(receiverName, tab); - if (focus) + if (focus) { setCurrentWidget(tab); + } return tab; } @@ -836,8 +859,9 @@ void TabSupervisor::maximizeMainWindow() void TabSupervisor::talkLeft(TabMessage *tab) { - if (tab == currentWidget()) + if (tab == currentWidget()) { emit setMenu(); + } messageTabs.remove(tab->getUserName()); removeTab(indexOf(tab)); @@ -934,8 +958,9 @@ TabEdhRec *TabSupervisor::addEdhrecTab(const CardInfoPtr &cardToQuery, bool isCo void TabSupervisor::deckEditorClosed(AbstractTabDeckEditor *tab) { - if (tab == currentWidget()) + if (tab == currentWidget()) { emit setMenu(); + } deckEditorTabs.removeOne(tab); removeTab(indexOf(tab)); @@ -948,8 +973,9 @@ void TabSupervisor::tabUserEvent(bool globalEvent) tab->setContentsChanged(true); setTabIcon(indexOf(tab), QPixmap("theme:icons/tab_changed")); } - if (globalEvent && SettingsCache::instance().getNotificationsEnabled()) + if (globalEvent && SettingsCache::instance().getNotificationsEnabled()) { QApplication::alert(this); + } } void TabSupervisor::updateTabText(Tab *tab, const QString &newTabText) @@ -962,39 +988,44 @@ void TabSupervisor::updateTabText(Tab *tab, const QString &newTabText) void TabSupervisor::processRoomEvent(const RoomEvent &event) { TabRoom *tab = roomTabs.value(event.room_id(), 0); - if (tab) + if (tab) { tab->processRoomEvent(event); + } } void TabSupervisor::processGameEventContainer(const GameEventContainer &cont) { TabGame *tab = gameTabs.value(cont.game_id()); - if (tab) + if (tab) { tab->getGame()->getGameEventHandler()->processGameEventContainer(cont, qobject_cast(sender()), {}); - else + } else { qCInfo(TabSupervisorLog) << "gameEvent: invalid gameId" << cont.game_id(); + } } void TabSupervisor::processUserMessageEvent(const Event_UserMessage &event) { QString senderName = QString::fromStdString(event.sender_name()); TabMessage *tab = messageTabs.value(senderName); - if (!tab) + if (!tab) { tab = messageTabs.value(QString::fromStdString(event.receiver_name())); + } if (!tab) { const ServerInfo_User *onlineUserInfo = userListManager->getOnlineUser(senderName); if (onlineUserInfo) { auto userLevel = UserLevelFlags(onlineUserInfo->user_level()); if (SettingsCache::instance().getIgnoreUnregisteredUserMessages() && - !userLevel.testFlag(ServerInfo_User::IsRegistered)) + !userLevel.testFlag(ServerInfo_User::IsRegistered)) { // Flags are additive, so reg/mod/admin are all IsRegistered return; + } } tab = addMessageTab(QString::fromStdString(event.sender_name()), false); } - if (!tab) + if (!tab) { return; + } tab->processUserMessageEvent(event); } @@ -1012,8 +1043,9 @@ void TabSupervisor::actShowPopup(const QString &message) void TabSupervisor::processUserLeft(const QString &userName) { TabMessage *tab = messageTabs.value(userName); - if (tab) + if (tab) { tab->processUserLeft(); + } } void TabSupervisor::processUserJoined(const ServerInfo_User &userInfoJoined) @@ -1037,8 +1069,9 @@ void TabSupervisor::processUserJoined(const ServerInfo_User &userInfoJoined) } TabMessage *tab = messageTabs.value(userName); - if (tab) + if (tab) { tab->processUserJoined(userInfoJoined); + } } void TabSupervisor::updateCurrent(int index) @@ -1051,8 +1084,9 @@ void TabSupervisor::updateCurrent(int index) } emit setMenu(static_cast(widget(index))->getTabMenus()); tab->tabActivated(); - } else + } else { emit setMenu(); + } } /** @@ -1062,8 +1096,9 @@ void TabSupervisor::updateCurrent(int index) */ bool TabSupervisor::getAdminLocked() const { - if (!tabAdmin) + if (!tabAdmin) { return true; + } return tabAdmin->getLocked(); } @@ -1087,12 +1122,13 @@ void TabSupervisor::processNotifyUserEvent(const Event_NotifyUser &event) tr("You have been promoted. Please log out and back in for changes to take effect.")); break; case Event_NotifyUser::WARNING: { - if (!QString::fromStdString(event.warning_reason()).simplified().isEmpty()) + if (!QString::fromStdString(event.warning_reason()).simplified().isEmpty()) { QMessageBox::warning(this, tr("Warned"), tr("You have received a warning due to %1.\nPlease refrain from engaging in this " "activity or further actions may be taken against you. If you have any " "questions, please private message a moderator.") .arg(QString::fromStdString(event.warning_reason()).simplified())); + } break; } case Event_NotifyUser::CUSTOM: { diff --git a/cockatrice/src/interface/widgets/tabs/visual_deck_editor/tab_deck_editor_visual.cpp b/cockatrice/src/interface/widgets/tabs/visual_deck_editor/tab_deck_editor_visual.cpp index d03ac483b..081766cdf 100644 --- a/cockatrice/src/interface/widgets/tabs/visual_deck_editor/tab_deck_editor_visual.cpp +++ b/cockatrice/src/interface/widgets/tabs/visual_deck_editor/tab_deck_editor_visual.cpp @@ -116,8 +116,9 @@ void TabDeckEditorVisual::createMenus() QString TabDeckEditorVisual::getTabText() const { QString result = tr("Visual Deck: %1").arg(deckStateManager->getSimpleDeckName()); - if (deckStateManager->isModified()) + if (deckStateManager->isModified()) { result.prepend("* "); + } return result; } diff --git a/cockatrice/src/interface/widgets/utility/custom_line_edit.cpp b/cockatrice/src/interface/widgets/utility/custom_line_edit.cpp index c137b4f35..05f56c275 100644 --- a/cockatrice/src/interface/widgets/utility/custom_line_edit.cpp +++ b/cockatrice/src/interface/widgets/utility/custom_line_edit.cpp @@ -24,14 +24,18 @@ bool LineEditUnfocusable::isUnfocusShortcut(QKeyEvent *event) QString modifier; QString keyNoMod; - if (event->modifiers() & Qt::ShiftModifier) + if (event->modifiers() & Qt::ShiftModifier) { modifier += "Shift+"; - if (event->modifiers() & Qt::ControlModifier) + } + if (event->modifiers() & Qt::ControlModifier) { modifier += "Ctrl+"; - if (event->modifiers() & Qt::AltModifier) + } + if (event->modifiers() & Qt::AltModifier) { modifier += "Alt+"; - if (event->modifiers() & Qt::MetaModifier) + } + if (event->modifiers() & Qt::MetaModifier) { modifier += "Meta+"; + } keyNoMod = QKeySequence(event->key()).toString(); @@ -39,8 +43,9 @@ bool LineEditUnfocusable::isUnfocusShortcut(QKeyEvent *event) QList unfocusShortcut = SettingsCache::instance().shortcuts().getShortcut("Player/unfocusTextBox"); for (const auto &unfocusKey : unfocusShortcut) { - if (key.matches(unfocusKey) == QKeySequence::ExactMatch) + if (key.matches(unfocusKey) == QKeySequence::ExactMatch) { return true; + } } return false; } @@ -79,10 +84,12 @@ void SearchLineEdit::keyPressEvent(QKeyEvent *event) static const QVector forwardWhenEmpty = {Qt::Key_Home, Qt::Key_End}; Qt::Key key = static_cast(event->key()); if (treeView) { - if (forwardToTreeView.contains(key)) + if (forwardToTreeView.contains(key)) { QCoreApplication::sendEvent(treeView, event); - if (text().isEmpty() && forwardWhenEmpty.contains(key)) + } + if (text().isEmpty() && forwardWhenEmpty.contains(key)) { QCoreApplication::sendEvent(treeView, event); + } } LineEditUnfocusable::keyPressEvent(event); } \ No newline at end of file diff --git a/cockatrice/src/interface/widgets/utility/line_edit_completer.cpp b/cockatrice/src/interface/widgets/utility/line_edit_completer.cpp index 389e69d57..13f475a61 100644 --- a/cockatrice/src/interface/widgets/utility/line_edit_completer.cpp +++ b/cockatrice/src/interface/widgets/utility/line_edit_completer.cpp @@ -46,8 +46,9 @@ void LineEditCompleter::keyPressEvent(QKeyEvent *event) int lastIndexof = qMax(0, textValue.lastIndexOf(" ")); QString finalString = textValue.left(lastIndexof); // Add a space if there's a word - if (finalString != "") + if (finalString != "") { finalString += " "; + } setText(finalString); return; } @@ -121,12 +122,14 @@ void LineEditCompleter::setCompleter(QCompleter *completer) void LineEditCompleter::setCompletionList(QStringList completionList) { - if (!c || c->popup()->isVisible()) + if (!c || c->popup()->isVisible()) { return; + } QStringListModel *model; model = (QStringListModel *)(c->model()); - if (model == NULL) + if (model == NULL) { model = new QStringListModel(); + } model->setStringList(completionList); } diff --git a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_filter_save_load_widget.cpp b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_filter_save_load_widget.cpp index 44b275afd..7ee57b1e9 100644 --- a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_filter_save_load_widget.cpp +++ b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_filter_save_load_widget.cpp @@ -57,8 +57,9 @@ void VisualDatabaseDisplayFilterSaveLoadWidget::retranslateUi() void VisualDatabaseDisplayFilterSaveLoadWidget::saveFilter() { QString filename = filenameInput->text().trimmed(); - if (filename.isEmpty()) + if (filename.isEmpty()) { return; + } QString filePath = SettingsCache::instance().getFiltersPath() + QDir::separator() + filename + ".json"; @@ -88,19 +89,22 @@ void VisualDatabaseDisplayFilterSaveLoadWidget::loadFilter(const QString &filena QString filePath = SettingsCache::instance().getFiltersPath() + QDir::separator() + filename; QFile file(filePath); - if (!file.open(QIODevice::ReadOnly)) + if (!file.open(QIODevice::ReadOnly)) { return; + } QByteArray jsonData = file.readAll(); file.close(); QJsonDocument doc = QJsonDocument::fromJson(jsonData); - if (!doc.isObject()) + if (!doc.isObject()) { return; + } QJsonObject root = doc.object(); - if (!root.contains("filters") || !root["filters"].isArray()) + if (!root.contains("filters") || !root["filters"].isArray()) { return; + } QJsonArray filtersArray = root["filters"].toArray(); diff --git a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_name_filter_widget.cpp b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_name_filter_widget.cpp index 2751ee971..fd03e17e6 100644 --- a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_name_filter_widget.cpp +++ b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_name_filter_widget.cpp @@ -64,8 +64,9 @@ void VisualDatabaseDisplayNameFilterWidget::actLoadFromDeck() { DeckListModel *deckListModel = deckEditor->deckStateManager->getModel(); - if (!deckListModel) + if (!deckListModel) { return; + } QList cardNames = deckListModel->getCardNames(); for (auto cardName : cardNames) { @@ -78,8 +79,9 @@ void VisualDatabaseDisplayNameFilterWidget::actLoadFromDeck() void VisualDatabaseDisplayNameFilterWidget::actLoadFromClipboard() { DlgLoadDeckFromClipboard dlg(this); - if (!dlg.exec()) + if (!dlg.exec()) { return; + } QStringList cardsInClipboard = dlg.getDeckList().getCardList(); for (QString cardName : cardsInClipboard) { @@ -91,8 +93,9 @@ void VisualDatabaseDisplayNameFilterWidget::actLoadFromClipboard() void VisualDatabaseDisplayNameFilterWidget::createNameFilter(const QString &name) { - if (activeFilters.contains(name)) + if (activeFilters.contains(name)) { return; + } // Create a button for the filter auto *button = new QPushButton(name, flowWidget); diff --git a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.cpp b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.cpp index f9a783a3c..027092990 100644 --- a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.cpp +++ b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.cpp @@ -240,9 +240,10 @@ void VisualDatabaseDisplayWidget::updateSearch(const QString &search) const { databaseDisplayModel->setStringFilter(search); QModelIndexList sel = databaseView->selectionModel()->selectedRows(); - if (sel.isEmpty() && databaseDisplayModel->rowCount()) + if (sel.isEmpty() && databaseDisplayModel->rowCount()) { databaseView->selectionModel()->setCurrentIndex(databaseDisplayModel->index(0, 0), QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows); + } } bool VisualDatabaseDisplayWidget::isVisualDisplayMode() const diff --git a/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_sample_hand_widget.cpp b/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_sample_hand_widget.cpp index cc35372b0..8417ffa34 100644 --- a/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_sample_hand_widget.cpp +++ b/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_sample_hand_widget.cpp @@ -112,13 +112,15 @@ static QList cardNodesToExactCards(QList no QList VisualDeckEditorSampleHandWidget::getRandomCards(int amountToGet) { QList randomCards; - if (!deckListModel) + if (!deckListModel) { return randomCards; + } QList mainDeckCards = cardNodesToExactCards(deckListModel->getCardNodesForZone(DECK_ZONE_MAIN)); - if (mainDeckCards.isEmpty()) + if (mainDeckCards.isEmpty()) { return randomCards; + } // Shuffle the deck std::random_device rd; diff --git a/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.cpp b/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.cpp index 19a99d3e9..971498af1 100644 --- a/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.cpp +++ b/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.cpp @@ -78,8 +78,9 @@ void VisualDeckEditorWidget::initializeSearchBarAndCompleter() searchBar = new QLineEdit(searchContainer); searchContainer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); connect(searchBar, &QLineEdit::returnPressed, this, [=, this]() { - if (!searchBar->hasFocus()) + if (!searchBar->hasFocus()) { return; + } ExactCard card = CardDatabaseManager::query()->getCard({searchBar->text()}); if (card) { diff --git a/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_tag_filter_widget.cpp b/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_tag_filter_widget.cpp index 28fd7a5ca..c4c8d18a8 100644 --- a/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_tag_filter_widget.cpp +++ b/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_tag_filter_widget.cpp @@ -126,8 +126,9 @@ void VisualDeckStorageTagFilterWidget::addTagIfNotPresent(const QString &tag) void VisualDeckStorageTagFilterWidget::sortTags() { auto *flowWidget = findChild(); - if (!flowWidget) + if (!flowWidget) { return; + } // Get all tag widgets QList tagWidgets = findChildren(); diff --git a/cockatrice/src/interface/window_main.cpp b/cockatrice/src/interface/window_main.cpp index bd7a5904e..69d3260bc 100644 --- a/cockatrice/src/interface/window_main.cpp +++ b/cockatrice/src/interface/window_main.cpp @@ -88,11 +88,13 @@ inline Q_LOGGING_CATEGORY(MainWindowLog, "main_window"); */ void MainWindow::updateTabMenu(const QList &newMenuList) { - for (auto &tabMenu : tabMenus) + for (auto &tabMenu : tabMenus) { menuBar()->removeAction(tabMenu->menuAction()); + } tabMenus = newMenuList; - for (auto &tabMenu : tabMenus) + for (auto &tabMenu : tabMenus) { menuBar()->insertMenu(helpMenu->menuAction(), tabMenu); + } } void MainWindow::statusChanged(ClientStatus _status) @@ -177,13 +179,15 @@ void MainWindow::actWatchReplay() QFileDialog dlg(this, tr("Load replay")); dlg.setDirectory(SettingsCache::instance().getReplaysPath()); dlg.setNameFilters(QStringList() << QObject::tr("Cockatrice replays (*.cor)")); - if (!dlg.exec()) + if (!dlg.exec()) { return; + } QString fileName = dlg.selectedFiles().at(0); QFile file(fileName); - if (!file.open(QIODevice::ReadOnly)) + if (!file.open(QIODevice::ReadOnly)) { return; + } QByteArray buf = file.readAll(); file.close(); @@ -208,10 +212,11 @@ void MainWindow::localGameEnded() void MainWindow::actFullScreen(bool checked) { - if (checked) + if (checked) { setWindowState(windowState() | Qt::WindowFullScreen); - else + } else { setWindowState(windowState() & ~Qt::WindowFullScreen); + } } void MainWindow::actSettings() @@ -691,8 +696,9 @@ void MainWindow::closeEvent(QCloseEvent *event) { // workaround Qt bug where closeEvent gets called twice static bool bClosingDown = false; - if (bClosingDown) + if (bClosingDown) { return; + } bClosingDown = true; if (!tabSupervisor->close()) { @@ -709,9 +715,9 @@ void MainWindow::closeEvent(QCloseEvent *event) void MainWindow::changeEvent(QEvent *event) { - if (event->type() == QEvent::LanguageChange) + if (event->type() == QEvent::LanguageChange) { retranslateUi(); - else if (event->type() == QEvent::ActivationChange) { + } else if (event->type() == QEvent::ActivationChange) { if (isActiveWindow() && !bHasActivated) { bHasActivated = true; if (!connectTo.isEmpty()) { @@ -1069,8 +1075,9 @@ int MainWindow::getNextCustomSetPrefix(QDir dataDir) QStringList::const_iterator filesIterator; for (filesIterator = files.constBegin(); filesIterator != files.constEnd(); ++filesIterator) { int fileIndex = (*filesIterator).split(".").at(0).toInt(); - if (fileIndex > maxIndex) + if (fileIndex > maxIndex) { maxIndex = fileIndex; + } } return maxIndex + 1; diff --git a/cockatrice/src/main.cpp b/cockatrice/src/main.cpp index 7092a3fd7..ad68d4be9 100644 --- a/cockatrice/src/main.cpp +++ b/cockatrice/src/main.cpp @@ -158,9 +158,11 @@ QString const generateClientID() { QString macList; for (const QNetworkInterface &networkInterface : QNetworkInterface::allInterfaces()) { - if (networkInterface.hardwareAddress() != "") - if (networkInterface.hardwareAddress() != "00:00:00:00:00:00:00:E0") + if (networkInterface.hardwareAddress() != "") { + if (networkInterface.hardwareAddress() != "00:00:00:00:00:00:00:E0") { macList += networkInterface.hardwareAddress() + "."; + } + } } QString strClientID = QCryptographicHash::hash(macList.toUtf8(), QCryptographicHash::Sha1).toHex().right(15); return strClientID; diff --git a/libcockatrice_card/libcockatrice/card/database/card_database.cpp b/libcockatrice_card/libcockatrice/card/database/card_database.cpp index 13dece626..951381aa4 100644 --- a/libcockatrice_card/libcockatrice/card/database/card_database.cpp +++ b/libcockatrice_card/libcockatrice/card/database/card_database.cpp @@ -103,9 +103,11 @@ void CardDatabase::addCard(CardInfoPtr card) // If a card already exists, just add the new set property. if (auto existing = cards.value(name)) { - for (const auto &printings : card->getSets()) - for (const auto &printing : printings) + for (const auto &printings : card->getSets()) { + for (const auto &printing : printings) { existing->addToSet(printing.getSet(), printing); + } + } return; } @@ -123,14 +125,17 @@ void CardDatabase::removeCard(CardInfoPtr card) return; } - for (auto *cardRelation : card->getRelatedCards()) + for (auto *cardRelation : card->getRelatedCards()) { cardRelation->deleteLater(); + } - for (auto *cardRelation : card->getReverseRelatedCards()) + for (auto *cardRelation : card->getReverseRelatedCards()) { cardRelation->deleteLater(); + } - for (auto *cardRelation : card->getReverseRelatedCards2Me()) + for (auto *cardRelation : card->getReverseRelatedCards2Me()) { cardRelation->deleteLater(); + } QMutexLocker locker(removeCardMutex); cards.remove(card->getName()); diff --git a/libcockatrice_card/libcockatrice/card/database/card_database_loader.cpp b/libcockatrice_card/libcockatrice/card/database/card_database_loader.cpp index 716477a59..76abf87ce 100644 --- a/libcockatrice_card/libcockatrice/card/database/card_database_loader.cpp +++ b/libcockatrice_card/libcockatrice/card/database/card_database_loader.cpp @@ -125,8 +125,9 @@ QStringList CardDatabaseLoader::collectCustomDatabasePaths() const QDirIterator::Subdirectories | QDirIterator::FollowSymlinks); QStringList paths; - while (it.hasNext()) + while (it.hasNext()) { paths << it.next(); + } paths.sort(); return paths; } diff --git a/libcockatrice_card/libcockatrice/card/database/card_database_querier.cpp b/libcockatrice_card/libcockatrice/card/database/card_database_querier.cpp index 021e8d12d..174943333 100644 --- a/libcockatrice_card/libcockatrice/card/database/card_database_querier.cpp +++ b/libcockatrice_card/libcockatrice/card/database/card_database_querier.cpp @@ -36,8 +36,9 @@ QList CardDatabaseQuerier::getCardInfos(const QStringList &cardName QList cardInfos; for (const QString &cardName : cardNames) { CardInfoPtr ptr = db->cards.value(cardName); - if (ptr) + if (ptr) { cardInfos.append(ptr); + } } return cardInfos; @@ -50,10 +51,12 @@ CardInfoPtr CardDatabaseQuerier::getCardBySimpleName(const QString &cardName) co CardInfoPtr CardDatabaseQuerier::lookupCardByName(const QString &name) const { - if (auto info = getCardInfo(name)) + if (auto info = getCardInfo(name)) { return info; - if (auto info = getCardBySimpleName(name)) + } + if (auto info = getCardBySimpleName(name)) { return info; + } return getCardBySimpleName(CardInfo::simplifyName(name)); } @@ -71,8 +74,9 @@ QList CardDatabaseQuerier::getCards(const QList &cardRefs) c QList cards; for (const auto &cardRef : cardRefs) { ExactCard card = getCard(cardRef); - if (card) + if (card) { cards.append(card); + } } return cards; @@ -119,8 +123,9 @@ ExactCard CardDatabaseQuerier::guessCard(const CardRef &cardRef) const ExactCard CardDatabaseQuerier::getRandomCard() const { - if (db->cards.isEmpty()) + if (db->cards.isEmpty()) { return {}; + } const auto keys = db->cards.keys(); int randomIndex = QRandomGenerator::global()->bounded(keys.size()); diff --git a/libcockatrice_card/libcockatrice/card/database/parser/cockatrice_xml_4.cpp b/libcockatrice_card/libcockatrice/card/database/parser/cockatrice_xml_4.cpp index cc0220526..96a5ac104 100644 --- a/libcockatrice_card/libcockatrice/card/database/parser/cockatrice_xml_4.cpp +++ b/libcockatrice_card/libcockatrice/card/database/parser/cockatrice_xml_4.cpp @@ -306,8 +306,9 @@ void CockatriceXml4Parser::loadCardsFromXml(QXmlStreamReader &xml) PrintingInfo printingInfo(set); for (QXmlStreamAttribute attr : attrs) { QString attrName = attr.name().toString(); - if (attrName == "picURL") + if (attrName == "picURL") { attrName = "picurl"; + } printingInfo.setProperty(attrName, attr.value().toString()); } diff --git a/libcockatrice_card/libcockatrice/card/format/format_legality_rules.h b/libcockatrice_card/libcockatrice/card/format/format_legality_rules.h index 16f2359ab..8778ab17e 100644 --- a/libcockatrice_card/libcockatrice/card/format/format_legality_rules.h +++ b/libcockatrice_card/libcockatrice/card/format/format_legality_rules.h @@ -51,16 +51,21 @@ enum class CardMatchType // convert string to enum inline CardMatchType matchTypeFromString(const QString &str) { - if (str == "equals") + if (str == "equals") { return CardMatchType::Equals; - if (str == "notEquals") + } + if (str == "notEquals") { return CardMatchType::NotEquals; - if (str == "contains") + } + if (str == "contains") { return CardMatchType::Contains; - if (str == "notContains") + } + if (str == "notContains") { return CardMatchType::NotContains; - if (str == "regex") + } + if (str == "regex") { return CardMatchType::Regex; + } return CardMatchType::Equals; // fallback default } diff --git a/libcockatrice_card/libcockatrice/card/game_specific_terms.h b/libcockatrice_card/libcockatrice/card/game_specific_terms.h index 2931365ad..3616745be 100644 --- a/libcockatrice_card/libcockatrice/card/game_specific_terms.h +++ b/libcockatrice_card/libcockatrice/card/game_specific_terms.h @@ -31,26 +31,36 @@ QString const ColorIdentity("coloridentity"); inline static const QString getNicePropertyName(QString key) { - if (key == CardType) + if (key == CardType) { return QCoreApplication::translate("Mtg", "Card Type"); - if (key == ConvertedManaCost) + } + if (key == ConvertedManaCost) { return QCoreApplication::translate("Mtg", "Mana Value"); - if (key == Colors) + } + if (key == Colors) { return QCoreApplication::translate("Mtg", "Color(s)"); - if (key == Loyalty) + } + if (key == Loyalty) { return QCoreApplication::translate("Mtg", "Loyalty"); - if (key == MainCardType) + } + if (key == MainCardType) { return QCoreApplication::translate("Mtg", "Main Card Type"); - if (key == ManaCost) + } + if (key == ManaCost) { return QCoreApplication::translate("Mtg", "Mana Cost"); - if (key == PowTough) + } + if (key == PowTough) { return QCoreApplication::translate("Mtg", "P/T"); - if (key == Side) + } + if (key == Side) { return QCoreApplication::translate("Mtg", "Side"); - if (key == Layout) + } + if (key == Layout) { return QCoreApplication::translate("Mtg", "Layout"); - if (key == ColorIdentity) + } + if (key == ColorIdentity) { return QCoreApplication::translate("Mtg", "Color Identity"); + } return key; } } // namespace Mtg diff --git a/libcockatrice_card/libcockatrice/card/set/card_set.cpp b/libcockatrice_card/libcockatrice/card/set/card_set.cpp index 20d0aced8..6eea220bb 100644 --- a/libcockatrice_card/libcockatrice/card/set/card_set.cpp +++ b/libcockatrice_card/libcockatrice/card/set/card_set.cpp @@ -33,28 +33,9 @@ QString CardSet::getCorrectedShortName() const { // For Windows machines. QSet invalidFileNames; - invalidFileNames << "CON" - << "PRN" - << "AUX" - << "NUL" - << "COM1" - << "COM2" - << "COM3" - << "COM4" - << "COM5" - << "COM6" - << "COM7" - << "COM8" - << "COM9" - << "LPT1" - << "LPT2" - << "LPT3" - << "LPT4" - << "LPT5" - << "LPT6" - << "LPT7" - << "LPT8" - << "LPT9"; + invalidFileNames << "CON" << "PRN" << "AUX" << "NUL" << "COM1" << "COM2" << "COM3" << "COM4" << "COM5" << "COM6" + << "COM7" << "COM8" << "COM9" << "LPT1" << "LPT2" << "LPT3" << "LPT4" << "LPT5" << "LPT6" << "LPT7" + << "LPT8" << "LPT9"; return invalidFileNames.contains(shortName) ? shortName + "_" : shortName; } diff --git a/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.cpp b/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.cpp index e3e7b41c0..d41713302 100644 --- a/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.cpp +++ b/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.cpp @@ -143,12 +143,14 @@ bool DeckList::loadFromXml(QXmlStreamReader *xml) while (!xml->atEnd()) { xml->readNext(); if (xml->isStartElement()) { - if (xml->name().toString() != "cockatrice_deck") + if (xml->name().toString() != "cockatrice_deck") { return false; + } while (!xml->atEnd()) { xml->readNext(); - if (!readElement(xml)) + if (!readElement(xml)) { break; + } } } } @@ -291,8 +293,9 @@ bool DeckList::loadFromStream_Plain(QTextStream &in, for (; index < max_line; ++index) { // check if line is a card match = reCardLine.match(inputs.at(index)); - if (!match.hasMatch()) + if (!match.hasMatch()) { continue; + } QString cardName = match.captured().simplified(); bool sideboard = false; @@ -305,8 +308,9 @@ bool DeckList::loadFromStream_Plain(QTextStream &in, cardName = match.captured(1); } } else { - if (index == sBStart) + if (index == sBStart) { continue; + } sideboard = index > sBStart; } diff --git a/libcockatrice_deck_list/libcockatrice/deck_list/deck_list_history_manager.cpp b/libcockatrice_deck_list/libcockatrice/deck_list/deck_list_history_manager.cpp index 83c9cc0bb..acf4707ab 100644 --- a/libcockatrice_deck_list/libcockatrice/deck_list/deck_list_history_manager.cpp +++ b/libcockatrice_deck_list/libcockatrice/deck_list/deck_list_history_manager.cpp @@ -16,8 +16,9 @@ void DeckListHistoryManager::clear() void DeckListHistoryManager::undo(DeckList *deck) { - if (undoStack.isEmpty()) + if (undoStack.isEmpty()) { return; + } // Peek at the memento we are going to restore const DeckListMemento &mementoToRestore = undoStack.top(); @@ -35,8 +36,9 @@ void DeckListHistoryManager::undo(DeckList *deck) void DeckListHistoryManager::redo(DeckList *deck) { - if (redoStack.isEmpty()) + if (redoStack.isEmpty()) { return; + } // Peek at the memento we are going to restore const DeckListMemento &mementoToRestore = redoStack.top(); diff --git a/libcockatrice_deck_list/libcockatrice/deck_list/deck_list_node_tree.cpp b/libcockatrice_deck_list/libcockatrice/deck_list/deck_list_node_tree.cpp index 644e0851a..196416cde 100644 --- a/libcockatrice_deck_list/libcockatrice/deck_list/deck_list_node_tree.cpp +++ b/libcockatrice_deck_list/libcockatrice/deck_list/deck_list_node_tree.cpp @@ -58,8 +58,9 @@ QList DecklistNodeTree::getZoneNodes(const QSet zones; for (auto *node : *root) { InnerDecklistNode *currentZone = dynamic_cast(node); - if (!currentZone) + if (!currentZone) { continue; + } if (!restrictToZones.isEmpty() && !restrictToZones.contains(currentZone->getName())) { continue; } diff --git a/libcockatrice_deck_list/libcockatrice/deck_list/sideboard_plan.cpp b/libcockatrice_deck_list/libcockatrice/deck_list/sideboard_plan.cpp index d991ec98e..a76fed619 100644 --- a/libcockatrice_deck_list/libcockatrice/deck_list/sideboard_plan.cpp +++ b/libcockatrice_deck_list/libcockatrice/deck_list/sideboard_plan.cpp @@ -18,28 +18,30 @@ bool SideboardPlan::readElement(QXmlStreamReader *xml) xml->readNext(); const QString childName = xml->name().toString(); if (xml->isStartElement()) { - if (childName == "name") + if (childName == "name") { name = xml->readElementText(); - else if (childName == "move_card_to_zone") { + } else if (childName == "move_card_to_zone") { MoveCard_ToZone m; while (!xml->atEnd()) { xml->readNext(); const QString childName2 = xml->name().toString(); if (xml->isStartElement()) { - if (childName2 == "card_name") + if (childName2 == "card_name") { m.set_card_name(xml->readElementText().toStdString()); - else if (childName2 == "start_zone") + } else if (childName2 == "start_zone") { m.set_start_zone(xml->readElementText().toStdString()); - else if (childName2 == "target_zone") + } else if (childName2 == "target_zone") { m.set_target_zone(xml->readElementText().toStdString()); + } } else if (xml->isEndElement() && (childName2 == "move_card_to_zone")) { moveList.append(m); break; } } } - } else if (xml->isEndElement() && (childName == "sideboard_plan")) + } else if (xml->isEndElement() && (childName == "sideboard_plan")) { return true; + } } return false; } diff --git a/libcockatrice_deck_list/libcockatrice/deck_list/tree/abstract_deck_list_card_node.cpp b/libcockatrice_deck_list/libcockatrice/deck_list/tree/abstract_deck_list_card_node.cpp index b8a497c20..705dfae4c 100644 --- a/libcockatrice_deck_list/libcockatrice/deck_list/tree/abstract_deck_list_card_node.cpp +++ b/libcockatrice_deck_list/libcockatrice/deck_list/tree/abstract_deck_list_card_node.cpp @@ -38,8 +38,9 @@ bool AbstractDecklistCardNode::readElement(QXmlStreamReader *xml) { while (!xml->atEnd()) { xml->readNext(); - if (xml->isEndElement() && xml->name().toString() == "card") + if (xml->isEndElement() && xml->name().toString() == "card") { return false; + } } return true; } diff --git a/libcockatrice_deck_list/libcockatrice/deck_list/tree/inner_deck_list_node.cpp b/libcockatrice_deck_list/libcockatrice/deck_list/tree/inner_deck_list_node.cpp index eca58963a..602ea6aec 100644 --- a/libcockatrice_deck_list/libcockatrice/deck_list/tree/inner_deck_list_node.cpp +++ b/libcockatrice_deck_list/libcockatrice/deck_list/tree/inner_deck_list_node.cpp @@ -48,8 +48,9 @@ QString InnerDecklistNode::getVisibleName() const void InnerDecklistNode::clearTree() { - for (int i = 0; i < size(); i++) + for (int i = 0; i < size(); i++) { delete at(i); + } clear(); } @@ -154,8 +155,9 @@ bool InnerDecklistNode::readElement(QXmlStreamReader *xml) xml->attributes().value("collectorNumber").toString(), xml->attributes().value("uuid").toString()); newCard->readElement(xml); } - } else if (xml->isEndElement() && (childName == "zone")) + } else if (xml->isEndElement() && (childName == "zone")) { return false; + } } return true; } @@ -164,8 +166,9 @@ void InnerDecklistNode::writeElement(QXmlStreamWriter *xml) { xml->writeStartElement("zone"); xml->writeAttribute("name", name); - for (int i = 0; i < size(); i++) + for (int i = 0; i < size(); i++) { at(i)->writeElement(xml); + } xml->writeEndElement(); // zone } diff --git a/libcockatrice_network/libcockatrice/network/client/abstract/abstract_client.cpp b/libcockatrice_network/libcockatrice/network/client/abstract/abstract_client.cpp index 11458768d..916f4351b 100644 --- a/libcockatrice_network/libcockatrice/network/client/abstract/abstract_client.cpp +++ b/libcockatrice_network/libcockatrice/network/client/abstract/abstract_client.cpp @@ -66,8 +66,9 @@ void AbstractClient::processProtocolItem(const ServerMessage &item) const int cmdId = response.cmd_id(); PendingCommand *pend = pendingCommands.value(cmdId, 0); - if (!pend) + if (!pend) { return; + } pendingCommands.remove(cmdId); pend->processResponse(response); diff --git a/libcockatrice_network/libcockatrice/network/client/remote/remote_client.cpp b/libcockatrice_network/libcockatrice/network/client/remote/remote_client.cpp index 3e3ec889d..0ef211b94 100644 --- a/libcockatrice_network/libcockatrice/network/client/remote/remote_client.cpp +++ b/libcockatrice_network/libcockatrice/network/client/remote/remote_client.cpp @@ -213,8 +213,9 @@ Command_Login RemoteClient::generateCommandLogin() if (!clientFeatures.isEmpty()) { QMap::iterator i; - for (i = clientFeatures.begin(); i != clientFeatures.end(); ++i) + for (i = clientFeatures.begin(); i != clientFeatures.end(); ++i) { cmdLogin.add_clientfeatures(i.key().toStdString().c_str()); + } } return cmdLogin; @@ -284,8 +285,9 @@ void RemoteClient::loginResponse(const Response &response) QString possibleMissingFeatures; if (resp.missing_features_size() > 0) { - for (int i = 0; i < resp.missing_features_size(); ++i) + for (int i = 0; i < resp.missing_features_size(); ++i) { possibleMissingFeatures.append("," + QString::fromStdString(resp.missing_features(i))); + } } if (response.response_code() == Response::RespOk) { @@ -293,13 +295,15 @@ void RemoteClient::loginResponse(const Response &response) emit userInfoChanged(resp.user_info()); QList buddyList; - for (int i = resp.buddy_list_size() - 1; i >= 0; --i) + for (int i = resp.buddy_list_size() - 1; i >= 0; --i) { buddyList.append(resp.buddy_list(i)); + } emit buddyListReceived(buddyList); QList ignoreList; - for (int i = resp.ignore_list_size() - 1; i >= 0; --i) + for (int i = resp.ignore_list_size() - 1; i >= 0; --i) { ignoreList.append(resp.ignore_list(i)); + } emit ignoreListReceived(ignoreList); if (newMissingFeatureFound(possibleMissingFeatures) && resp.missing_features_size() > 0 && @@ -311,8 +315,9 @@ void RemoteClient::loginResponse(const Response &response) } else if (response.response_code() != Response::RespNotConnected) { QList missingFeatures; if (resp.missing_features_size() > 0) { - for (int i = 0; i < resp.missing_features_size(); ++i) + for (int i = 0; i < resp.missing_features_size(); ++i) { missingFeatures << QString::fromStdString(resp.missing_features(i)); + } } emit loginError(response.response_code(), QString::fromStdString(resp.denied_reason_str()), static_cast(resp.denied_end_time()), missingFeatures); @@ -383,11 +388,13 @@ void RemoteClient::readData() inputBuffer.remove(0, 4); messageInProgress = true; } - } else + } else { return; + } } - if (inputBuffer.size() < messageLength) + if (inputBuffer.size() < messageLength) { return; + } ServerMessage newServerMessage; bool ok = newServerMessage.ParseFromArray(inputBuffer.data(), messageLength); @@ -403,8 +410,9 @@ void RemoteClient::readData() qCDebug(RemoteClientLog) << "parsing error!"; } - if (getStatus() == StatusDisconnecting) // use thread-safe getter + if (getStatus() == StatusDisconnecting) { // use thread-safe getter doDisconnectFromServer(); + } } while (!inputBuffer.isEmpty()); } @@ -537,8 +545,9 @@ void RemoteClient::doDisconnectFromServer() pendingCommands.clear(); setStatus(StatusDisconnected); - if (websocket->isValid()) + if (websocket->isValid()) { websocket->close(); + } socket->close(); } @@ -615,8 +624,9 @@ bool RemoteClient::newMissingFeatureFound(const QString &_serversMissingFeatures QStringList serversMissingFeaturesList = _serversMissingFeatures.split(","); for (const QString &feature : serversMissingFeaturesList) { if (!feature.isEmpty()) { - if (!networkSettingsProvider->getKnownMissingFeatures().contains(feature)) + if (!networkSettingsProvider->getKnownMissingFeatures().contains(feature)) { return true; + } } } return newMissingFeature; @@ -628,8 +638,9 @@ void RemoteClient::clearNewClientFeatures() QStringList existingKnownMissingFeatures = networkSettingsProvider->getKnownMissingFeatures().split(","); for (const QString &existingKnownFeature : existingKnownMissingFeatures) { if (!existingKnownFeature.isEmpty()) { - if (!clientFeatures.contains(existingKnownFeature)) + if (!clientFeatures.contains(existingKnownFeature)) { newKnownMissingFeatures.append("," + existingKnownFeature); + } } } networkSettingsProvider->setKnownMissingFeatures(newKnownMissingFeatures); @@ -667,10 +678,12 @@ void RemoteClient::requestForgotPasswordResponse(const Response &response) if (response.response_code() == Response::RespOk) { if (resp.challenge_email()) { emit sigPromptForForgotPasswordChallenge(); - } else + } else { emit sigPromptForForgotPasswordReset(); - } else + } + } else { emit sigForgotPasswordError(); + } doDisconnectFromServer(); } @@ -698,8 +711,9 @@ void RemoteClient::submitForgotPasswordResetResponse(const Response &response) { if (response.response_code() == Response::RespOk) { emit sigForgotPasswordSuccess(); - } else + } else { emit sigForgotPasswordError(); + } doDisconnectFromServer(); } @@ -732,8 +746,9 @@ void RemoteClient::submitForgotPasswordChallengeResponse(const Response &respons { if (response.response_code() == Response::RespOk) { emit sigPromptForForgotPasswordReset(); - } else + } else { emit sigForgotPasswordError(); + } doDisconnectFromServer(); } diff --git a/libcockatrice_network/libcockatrice/network/server/remote/game/server_abstract_player.cpp b/libcockatrice_network/libcockatrice/network/server/remote/game/server_abstract_player.cpp index 1b1135ead..36ab75675 100644 --- a/libcockatrice_network/libcockatrice/network/server/remote/game/server_abstract_player.cpp +++ b/libcockatrice_network/libcockatrice/network/server/remote/game/server_abstract_player.cpp @@ -391,8 +391,9 @@ void Server_AbstractPlayer::processMoveCard(GameEventStorage &ges, for (auto *player : game->getPlayers().values()) { QList arrowsToDelete; for (Server_Arrow *arrow : player->getArrows()) { - if ((arrow->getStartCard() == card) || (arrow->getTargetItem() == card)) + if ((arrow->getStartCard() == card) || (arrow->getTargetItem() == card)) { arrowsToDelete.append(arrow->getId()); + } } for (int j : arrowsToDelete) { player->deleteArrow(j); @@ -1472,8 +1473,9 @@ Server_AbstractPlayer::cmdRevealCards(const Command_RevealCards &cmd, ResponseCo if (cmd.has_player_id()) { Server_AbstractPlayer *otherPlayer = game->getPlayer(cmd.player_id()); - if (!otherPlayer) + if (!otherPlayer) { return Response::RespNameNotFound; + } } Server_CardZone *zone = zones.value(nameFromStdString(cmd.zone_name())); if (!zone) { diff --git a/libcockatrice_network/libcockatrice/network/server/remote/game/server_arrow.cpp b/libcockatrice_network/libcockatrice/network/server/remote/game/server_arrow.cpp index f6787baa2..2ad38b977 100644 --- a/libcockatrice_network/libcockatrice/network/server/remote/game/server_arrow.cpp +++ b/libcockatrice_network/libcockatrice/network/server/remote/game/server_arrow.cpp @@ -30,6 +30,7 @@ void Server_Arrow::getInfo(ServerInfo_Arrow *info) info->set_target_player_id(targetCard->getZone()->getPlayer()->getPlayerId()); info->set_target_zone(targetCard->getZone()->getName().toStdString()); info->set_target_card_id(targetCard->getId()); - } else + } else { info->set_target_player_id(static_cast(targetItem)->getPlayerId()); + } } diff --git a/libcockatrice_network/libcockatrice/network/server/remote/game/server_card.cpp b/libcockatrice_network/libcockatrice/network/server/remote/game/server_card.cpp index 86ff2f008..e3d53ace8 100644 --- a/libcockatrice_network/libcockatrice/network/server/remote/game/server_card.cpp +++ b/libcockatrice_network/libcockatrice/network/server/remote/game/server_card.cpp @@ -36,11 +36,13 @@ Server_Card::Server_Card(const CardRef &cardRef, int _id, int _coord_x, int _coo Server_Card::~Server_Card() { // setParentCard(0) leads to the item being removed from our list, so we can't iterate properly - while (!attachedCards.isEmpty()) + while (!attachedCards.isEmpty()) { attachedCards.first()->setParentCard(0); + } - if (parentCard) + if (parentCard) { parentCard->removeAttachedCard(this); + } if (stashedCard) { stashedCard->deleteLater(); @@ -62,16 +64,18 @@ void Server_Card::resetState(bool keepAnnotations) QString Server_Card::setAttribute(CardAttribute attribute, const QString &avalue, bool allCards) { - if (attribute == AttrTapped && avalue != "1" && allCards && doesntUntap) + if (attribute == AttrTapped && avalue != "1" && allCards && doesntUntap) { return QVariant(tapped).toString(); + } return setAttribute(attribute, avalue); } QString Server_Card::setAttribute(CardAttribute attribute, const QString &avalue, Event_SetCardAttr *event) { - if (event) + if (event) { event->set_attribute(attribute); + } switch (attribute) { case AttrTapped: { @@ -89,8 +93,9 @@ QString Server_Card::setAttribute(CardAttribute attribute, const QString &avalue break; case AttrPT: setPT(avalue); - if (event) + if (event) { event->set_attr_value(getPT().toStdString()); + } return getPT(); case AttrAnnotation: setAnnotation(avalue); @@ -99,17 +104,19 @@ QString Server_Card::setAttribute(CardAttribute attribute, const QString &avalue setDoesntUntap(avalue == "1"); break; } - if (event) + if (event) { event->set_attr_value(avalue.toStdString()); + } return avalue; } void Server_Card::setCounter(int _id, int value, Event_SetCardCounter *event) { - if (value) + if (value) { counters.insert(_id, value); - else + } else { counters.remove(_id); + } if (event) { event->set_counter_id(_id); @@ -119,11 +126,13 @@ void Server_Card::setCounter(int _id, int value, Event_SetCardCounter *event) void Server_Card::setParentCard(Server_Card *_parentCard) { - if (parentCard) + if (parentCard) { parentCard->removeAttachedCard(this); + } parentCard = _parentCard; - if (parentCard) + if (parentCard) { parentCard->addAttachedCard(this); + } } void Server_Card::getInfo(ServerInfo_Card *info) diff --git a/libcockatrice_network/libcockatrice/network/server/remote/game/server_cardzone.cpp b/libcockatrice_network/libcockatrice/network/server/remote/game/server_cardzone.cpp index f2a35e548..1db4f9c4c 100644 --- a/libcockatrice_network/libcockatrice/network/server/remote/game/server_cardzone.cpp +++ b/libcockatrice_network/libcockatrice/network/server/remote/game/server_cardzone.cpp @@ -47,19 +47,23 @@ void Server_CardZone::shuffle(int start, int end) cardsBeingLookedAt = 0; // Size 0 or 1 decks are sorted - if (cards.size() < 2) + if (cards.size() < 2) { return; + } // Negative numbers signify positions starting at the end of the // zone convert these to actual indexes. - if (end < 0) + if (end < 0) { end += cards.size(); + } - if (start < 0) + if (start < 0) { start += cards.size(); + } - if (start < 0 || end < 0 || start >= cards.size() || end >= cards.size()) + if (start < 0 || end < 0 || start >= cards.size() || end >= cards.size()) { return; + } for (int i = end; i > start; i--) { int j = rng->rand(start, i); @@ -70,40 +74,47 @@ void Server_CardZone::shuffle(int start, int end) void Server_CardZone::removeCardFromCoordMap(Server_Card *card, int oldX, int oldY) { - if (oldX < 0) + if (oldX < 0) { return; + } const int baseX = (oldX / 3) * 3; QMap &coordMap = coordinateMap[oldY]; - if (coordMap.contains(baseX) && coordMap.contains(baseX + 1) && coordMap.contains(baseX + 2)) + if (coordMap.contains(baseX) && coordMap.contains(baseX + 1) && coordMap.contains(baseX + 2)) { // If the removal of this card has opened up a previously full pile... freePilesMap[oldY].insert(coordMap.value(baseX)->getName(), baseX); + } coordMap.remove(oldX); if (!(coordMap.contains(baseX) && coordMap.value(baseX)->getName() == card->getName()) && !(coordMap.contains(baseX + 1) && coordMap.value(baseX + 1)->getName() == card->getName()) && - !(coordMap.contains(baseX + 2) && coordMap.value(baseX + 2)->getName() == card->getName())) + !(coordMap.contains(baseX + 2) && coordMap.value(baseX + 2)->getName() == card->getName())) { // If this card was the last one with this name... freePilesMap[oldY].remove(card->getName(), baseX); + } if (!coordMap.contains(baseX) && !coordMap.contains(baseX + 1) && !coordMap.contains(baseX + 2)) { // If the removal of this card has freed a whole pile, i.e. it was the last card in it... - if (baseX < freeSpaceMap[oldY]) + if (baseX < freeSpaceMap[oldY]) { freeSpaceMap[oldY] = baseX; + } } } void Server_CardZone::insertCardIntoCoordMap(Server_Card *card, int x, int y) { - if (x < 0) + if (x < 0) { return; + } coordinateMap[y].insert(x, card); if (!(x % 3)) { - if (!card->getFaceDown() && !freePilesMap[y].contains(card->getName(), x) && card->getAttachedCards().isEmpty()) + if (!card->getFaceDown() && !freePilesMap[y].contains(card->getName(), x) && + card->getAttachedCards().isEmpty()) { freePilesMap[y].insert(card->getName(), x); + } if (freeSpaceMap[y] == x) { int nextFreeX = x; do { @@ -146,8 +157,9 @@ Server_Card *Server_CardZone::getCard(int id, int *position, bool remove) for (int i = 0; i < cards.size(); ++i) { Server_Card *tmp = cards[i]; if (tmp->getId() == id) { - if (position) + if (position) { *position = i; + } if (remove) { cards.removeAt(i); tmp->setZone(nullptr); @@ -157,11 +169,13 @@ Server_Card *Server_CardZone::getCard(int id, int *position, bool remove) } return nullptr; } else { - if ((id >= cards.size()) || (id < 0)) + if ((id >= cards.size()) || (id < 0)) { return nullptr; + } Server_Card *tmp = cards[id]; - if (position) + if (position) { *position = id; + } if (remove) { cards.removeAt(id); tmp->setZone(nullptr); @@ -184,32 +198,35 @@ int Server_CardZone::getFreeGridColumn(int x, int y, const QString &cardName, bo if (coordMap.contains(x) && (coordMap[x]->getFaceDown() || !coordMap[x]->getAttachedCards().isEmpty())) { // don't pile up on: 1. facedown cards 2. cards with attached cards - } else if (!coordMap.contains(x)) + } else if (!coordMap.contains(x)) { return x; - else if (!coordMap.contains(x + 1)) + } else if (!coordMap.contains(x + 1)) { return x + 1; - else + } else { return x + 2; + } } } else if (x >= 0) { int resultX = 0; x = (x / 3) * 3; - if (!coordMap.contains(x)) + if (!coordMap.contains(x)) { resultX = x; - else if (!coordMap.value(x)->getAttachedCards().isEmpty()) { + } else if (!coordMap.value(x)->getAttachedCards().isEmpty()) { resultX = x; x = -1; - } else if (!coordMap.contains(x + 1)) + } else if (!coordMap.contains(x + 1)) { resultX = x + 1; - else if (!coordMap.contains(x + 2)) + } else if (!coordMap.contains(x + 2)) { resultX = x + 2; - else { + } else { resultX = x; x = -1; } - if (x < 0) - while (coordMap.contains(resultX)) + if (x < 0) { + while (coordMap.contains(resultX)) { resultX += 3; + } + } return resultX; } @@ -219,16 +236,18 @@ int Server_CardZone::getFreeGridColumn(int x, int y, const QString &cardName, bo bool Server_CardZone::isColumnStacked(int x, int y) const { - if (!has_coords) + if (!has_coords) { return false; + } return coordinateMap[y].contains((x / 3) * 3 + 1); } bool Server_CardZone::isColumnEmpty(int x, int y) const { - if (!has_coords) + if (!has_coords) { return true; + } return !coordinateMap[y].contains((x / 3) * 3); } @@ -243,12 +262,14 @@ void Server_CardZone::moveCardInRow(GameEventStorage &ges, Server_Card *card, in void Server_CardZone::fixFreeSpaces(GameEventStorage &ges) { - if (!has_coords) + if (!has_coords) { return; + } QSet> placesToLook; - for (auto &card : cards) + for (auto &card : cards) { placesToLook.insert(QPair((card->getX() / 3) * 3, card->getY())); + } QSetIterator> placeIterator(placesToLook); while (placeIterator.hasNext()) { @@ -257,26 +278,30 @@ void Server_CardZone::fixFreeSpaces(GameEventStorage &ges) int y = foo.second; if (!coordinateMap[y].contains(baseX)) { - if (coordinateMap[y].contains(baseX + 1)) + if (coordinateMap[y].contains(baseX + 1)) { moveCardInRow(ges, coordinateMap[y].value(baseX + 1), baseX, y); - else if (coordinateMap[y].contains(baseX + 2)) { + } else if (coordinateMap[y].contains(baseX + 2)) { moveCardInRow(ges, coordinateMap[y].value(baseX + 2), baseX, y); continue; - } else + } else { continue; + } } - if (!coordinateMap[y].contains(baseX + 1) && coordinateMap[y].contains(baseX + 2)) + if (!coordinateMap[y].contains(baseX + 1) && coordinateMap[y].contains(baseX + 2)) { moveCardInRow(ges, coordinateMap[y].value(baseX + 2), baseX + 1, y); + } } } void Server_CardZone::updateCardCoordinates(Server_Card *card, int oldX, int oldY) { - if (!has_coords) + if (!has_coords) { return; + } - if (oldX != -1) + if (oldX != -1) { removeCardFromCoordMap(card, oldX, oldY); + } insertCardIntoCoordMap(card, card->getX(), card->getY()); } @@ -299,8 +324,9 @@ void Server_CardZone::insertCard(Server_Card *card, int x, int y) void Server_CardZone::clear() { - for (auto card : cards) + for (auto card : cards) { delete card; + } cards.clear(); coordinateMap.clear(); freePilesMap.clear(); @@ -329,7 +355,8 @@ void Server_CardZone::getInfo(ServerInfo_Zone *info, Server_AbstractParticipant const bool zonesOthersCanSee = type == ServerInfo_Zone::PublicZone; if ((selfPlayerAsking && zonesSelfCanSee) || (otherPlayerAsking && zonesOthersCanSee)) { QListIterator cardIterator(cards); - while (cardIterator.hasNext()) + while (cardIterator.hasNext()) { cardIterator.next()->getInfo(info->add_card_list()); + } } } diff --git a/libcockatrice_network/libcockatrice/network/server/remote/game/server_game.cpp b/libcockatrice_network/libcockatrice/network/server/remote/game/server_game.cpp index 28d06c6be..f5a4889d0 100644 --- a/libcockatrice_network/libcockatrice/network/server/remote/game/server_game.cpp +++ b/libcockatrice_network/libcockatrice/network/server/remote/game/server_game.cpp @@ -147,8 +147,9 @@ void Server_Game::storeGameInformation() const QStringList &allGameTypes = room->getGameTypes(); QStringList _gameTypes; - for (int i = gameInfo.game_types_size() - 1; i >= 0; --i) + for (int i = gameInfo.game_types_size() - 1; i >= 0; --i) { _gameTypes.append(allGameTypes[gameInfo.game_types(i)]); + } for (const auto &playerName : allPlayersEver) { replayMatchInfo->add_player_names(playerName.toStdString()); @@ -166,8 +167,9 @@ void Server_Game::storeGameInformation() server->clientsLock.lockForRead(); for (auto userName : allPlayersEver + allSpectatorsEver) { Server_AbstractUserInterface *userHandler = server->findUser(userName); - if (userHandler && server->getStoreReplaysEnabled()) + if (userHandler && server->getStoreReplaysEnabled()) { userHandler->sendProtocolItem(*sessionEvent); + } } server->clientsLock.unlock(); delete sessionEvent; @@ -189,8 +191,9 @@ void Server_Game::pingClockTimeout() bool allPlayersInactive = true; int playerCount = 0; for (auto *participant : participants) { - if (participant == nullptr) + if (participant == nullptr) { continue; + } if (!participant->isSpectator()) { ++playerCount; @@ -253,8 +256,9 @@ int Server_Game::getSpectatorCount() const int result = 0; for (Server_AbstractParticipant *participant : participants.values()) { - if (participant->isSpectator()) + if (participant->isSpectator()) { ++result; + } } return result; } @@ -269,8 +273,9 @@ void Server_Game::createGameStateChangedEvent(Event_GameStateChanged *event, event->set_game_started(true); event->set_active_player_id(0); event->set_active_phase(0); - } else + } else { event->set_game_started(false); + } for (Server_AbstractParticipant *participant : participants.values()) { participant->getInfo(event->add_player_list(), recipient, omniscient, withUserInfo); @@ -367,8 +372,9 @@ void Server_Game::doStartGameIfReady(bool forceStartGame) delete replayCont; startTimeOfThisGame = secondsElapsed; - } else + } else { firstGameStarted = true; + } sendGameStateToPlayers(); @@ -396,11 +402,13 @@ void Server_Game::stopGameIfFinished() int playing = 0; auto players = getPlayers(); for (auto *player : players.values()) { - if (!player->getConceded()) + if (!player->getConceded()) { ++playing; + } } - if (playing > 1) + if (playing > 1) { return; + } gameStarted = false; @@ -428,32 +436,40 @@ Response::ResponseCode Server_Game::checkJoin(ServerInfo_User *user, { Server_DatabaseInterface *databaseInterface = room->getServer()->getDatabaseInterface(); for (auto *participant : participants.values()) { - if (participant->getUserInfo()->name() == user->name()) + if (participant->getUserInfo()->name() == user->name()) { return Response::RespContextError; + } } if (asJudge && !(user->user_level() & ServerInfo_User::IsJudge)) { return Response::RespUserLevelTooLow; } if (!(overrideRestrictions && (user->user_level() & ServerInfo_User::IsModerator))) { - if ((_password != password) && !(spectator && !spectatorsNeedPassword)) + if ((_password != password) && !(spectator && !spectatorsNeedPassword)) { return Response::RespWrongPassword; - if (!(user->user_level() & ServerInfo_User::IsRegistered) && onlyRegistered) + } + if (!(user->user_level() & ServerInfo_User::IsRegistered) && onlyRegistered) { return Response::RespUserLevelTooLow; - if (onlyBuddies && (user->name() != creatorInfo->name())) + } + if (onlyBuddies && (user->name() != creatorInfo->name())) { if (!databaseInterface->isInBuddyList(QString::fromStdString(creatorInfo->name()), - QString::fromStdString(user->name()))) + QString::fromStdString(user->name()))) { return Response::RespOnlyBuddies; + } + } if (databaseInterface->isInIgnoreList(QString::fromStdString(creatorInfo->name()), - QString::fromStdString(user->name()))) + QString::fromStdString(user->name()))) { return Response::RespInIgnoreList; + } if (spectator) { - if (!spectatorsAllowed) + if (!spectatorsAllowed) { return Response::RespSpectatorsNotAllowed; + } } } - if (!spectator && (gameStarted || (getPlayerCount() >= getMaxPlayers()))) + if (!spectator && (gameStarted || (getPlayerCount() >= getMaxPlayers()))) { return Response::RespGameFull; + } return Response::RespOk; } @@ -463,8 +479,9 @@ bool Server_Game::containsUser(const QString &userName) const QMutexLocker locker(&gameMutex); for (auto *participant : participants.values()) { - if (participant->getUserInfo()->name() == userName.toStdString()) + if (participant->getUserInfo()->name() == userName.toStdString()) { return true; + } } return false; } @@ -516,8 +533,9 @@ void Server_Game::addPlayer(Server_AbstractUserInterface *userInterface, emit gameInfoChanged(gameInfo); } - if ((newParticipant->getUserInfo()->user_level() & ServerInfo_User::IsRegistered) && !spectator) + if ((newParticipant->getUserInfo()->user_level() & ServerInfo_User::IsRegistered) && !spectator) { room->getServer()->addPersistentPlayer(playerName, room->getId(), gameId, newParticipant->getPlayerId()); + } userInterface->playerAddedToGame(gameId, room->getId(), newParticipant->getPlayerId()); @@ -564,8 +582,9 @@ void Server_Game::removeParticipant(Server_AbstractParticipant *participant, Eve } if (!spectator) { stopGameIfFinished(); - if (gameStarted && playerActive) + if (gameStarted && playerActive) { nextTurn(); + } } ServerInfo_Game gameInfo; @@ -588,15 +607,18 @@ void Server_Game::removeArrowsRelatedToPlayer(GameEventStorage &ges, Server_Abst for (auto *arrow : anyPlayer->getArrows().values()) { auto *targetCard = qobject_cast(arrow->getTargetItem()); if (targetCard) { - if (targetCard->getZone() != nullptr && targetCard->getZone()->getPlayer() == player) + if (targetCard->getZone() != nullptr && targetCard->getZone()->getPlayer() == player) { toDelete.append(arrow); + } } else if (arrow->getTargetItem() == player) { toDelete.append(arrow); } // Don't use else here! It has to happen regardless of whether targetCard == 0. - if (arrow->getStartCard()->getZone() != nullptr && arrow->getStartCard()->getZone()->getPlayer() == player) + if (arrow->getStartCard()->getZone() != nullptr && + arrow->getStartCard()->getZone()->getPlayer() == player) { toDelete.append(arrow); + } } for (auto *arrow : toDelete) { Event_DeleteArrow event; @@ -635,8 +657,9 @@ bool Server_Game::kickParticipant(int playerId) QMutexLocker locker(&gameMutex); auto *participant = participants.value(playerId); - if (!participant) + if (!participant) { return false; + } GameEventContainer *gec = prepareGameEvent(Event_Kicked(), -1); participant->sendGameEvent(*gec); @@ -769,8 +792,9 @@ void Server_Game::sendGameEventContainer(GameEventContainer *cont, const bool playerPrivate = (participant->getPlayerId() == privatePlayerId) || participant->isJudge() || (participant->isSpectator() && spectatorsSeeEverything); if ((recipients.testFlag(GameEventStorageItem::SendToPrivate) && playerPrivate) || - (recipients.testFlag(GameEventStorageItem::SendToOthers) && !playerPrivate)) + (recipients.testFlag(GameEventStorageItem::SendToOthers) && !playerPrivate)) { participant->sendGameEvent(*cont); + } } if (recipients.testFlag(GameEventStorageItem::SendToPrivate)) { cont->set_seconds_elapsed(secondsElapsed - startTimeOfThisGame); @@ -786,11 +810,13 @@ Server_Game::prepareGameEvent(const ::google::protobuf::Message &gameEvent, int { auto *cont = new GameEventContainer; cont->set_game_id(gameId); - if (context) + if (context) { cont->mutable_context()->CopyFrom(*context); + } GameEvent *event = cont->add_event_list(); - if (playerId != -1) + if (playerId != -1) { event->set_player_id(playerId); + } event->GetReflection() ->MutableMessage(event, gameEvent.GetDescriptor()->FindExtensionByName("ext")) ->CopyFrom(gameEvent); diff --git a/libcockatrice_network/libcockatrice/network/server/remote/server.cpp b/libcockatrice_network/libcockatrice/network/server/remote/server.cpp index a5a74c54c..904637797 100644 --- a/libcockatrice_network/libcockatrice/network/server/remote/server.cpp +++ b/libcockatrice_network/libcockatrice/network/server/remote/server.cpp @@ -56,8 +56,9 @@ void Server::prepareDestroy() { roomsLock.lockForWrite(); QMapIterator roomIterator(rooms); - while (roomIterator.hasNext()) + while (roomIterator.hasNext()) { delete roomIterator.next().value(); + } rooms.clear(); roomsLock.unlock(); } @@ -86,22 +87,25 @@ AuthenticationResult Server::loginUser(Server_ProtocolHandler *session, bool hasClientId = false; if (clientid.isEmpty()) { // client id is empty, either out dated client or client has been modified - if (getClientIDRequiredEnabled()) + if (getClientIDRequiredEnabled()) { return ClientIdRequired; + } } else { hasClientId = true; } - if (name.size() > 35) + if (name.size() > 35) { name = name.left(35); + } Server_DatabaseInterface *databaseInterface = getDatabaseInterface(); AuthenticationResult authState = databaseInterface->checkUserPassword(session, name, password, clientid, reasonStr, secondsLeft, passwordNeedsHash); if (authState == NotLoggedIn || authState == UserIsBanned || authState == UsernameInvalid || - authState == UserIsInactive) + authState == UserIsInactive) { return authState; + } ServerInfo_User data = databaseInterface->getUserData(name, true); data.set_address(session->getAddress().toStdString()); @@ -140,8 +144,9 @@ AuthenticationResult Server::loginUser(Server_ProtocolHandler *session, QString tempName = name; int i = 0; while (users.contains(tempName) || databaseInterface->activeUserExists(tempName) || - databaseInterface->userSessionExists(tempName)) + databaseInterface->userSessionExists(tempName)) { tempName = name + "_" + QString::number(++i); + } name = tempName; data.set_name(name.toStdString()); } @@ -163,9 +168,11 @@ AuthenticationResult Server::loginUser(Server_ProtocolHandler *session, Event_UserJoined event; event.mutable_user_info()->CopyFrom(session->copyUserInfo(false)); SessionEvent *se = Server_ProtocolHandler::prepareSessionEvent(event); - for (auto &client : clients) - if (client->getAcceptsUserListChanges()) + for (auto &client : clients) { + if (client->getAcceptsUserListChanges()) { client->sendProtocolItem(*se); + } + } delete se; event.mutable_user_info()->CopyFrom(session->copyUserInfo(true, true, true)); @@ -206,19 +213,22 @@ Server_AbstractUserInterface *Server::findUser(const QString &userName) const // Call this only with clientsLock set. Server_AbstractUserInterface *userHandler = users.value(userName); - if (userHandler) + if (userHandler) { return userHandler; - else + } else { return externalUsers.value(userName); + } } void Server::addClient(Server_ProtocolHandler *client) { - if (client->getConnectionType() == "tcp") + if (client->getConnectionType() == "tcp") { tcpUserCount++; + } - if (client->getConnectionType() == "websocket") + if (client->getConnectionType() == "websocket") { webSocketUserCount++; + } QWriteLocker locker(&clientsLock); clients << client; @@ -232,11 +242,13 @@ void Server::removeClient(Server_ProtocolHandler *client) return; } - if (client->getConnectionType() == "tcp") + if (client->getConnectionType() == "tcp") { tcpUserCount--; + } - if (client->getConnectionType() == "websocket") + if (client->getConnectionType() == "websocket") { webSocketUserCount--; + } QWriteLocker locker(&clientsLock); clients.removeAt(clientIndex); @@ -245,9 +257,11 @@ void Server::removeClient(Server_ProtocolHandler *client) Event_UserLeft event; event.set_name(data->name()); SessionEvent *se = Server_ProtocolHandler::prepareSessionEvent(event); - for (auto &_client : clients) - if (_client->getAcceptsUserListChanges()) + for (auto &_client : clients) { + if (_client->getAcceptsUserListChanges()) { _client->sendProtocolItem(*se); + } + } sendIsl_SessionEvent(*se); delete se; @@ -274,8 +288,9 @@ QList Server::getOnlineModeratorList() const // TODO: this line should be updated in the event there is any type of new user level created if (data && - (data->user_level() & ServerInfo_User::IsModerator || data->user_level() & ServerInfo_User::IsAdmin)) + (data->user_level() & ServerInfo_User::IsModerator || data->user_level() & ServerInfo_User::IsAdmin)) { results << QString::fromStdString(data->name()).simplified(); + } } return results; } @@ -293,9 +308,11 @@ void Server::externalUserJoined(const ServerInfo_User &userInfo) event.mutable_user_info()->CopyFrom(userInfo); SessionEvent *se = Server_ProtocolHandler::prepareSessionEvent(event); - for (auto &client : clients) - if (client->getAcceptsUserListChanges()) + for (auto &client : clients) { + if (client->getAcceptsUserListChanges()) { client->sendProtocolItem(*se); + } + } delete se; clientsLock.unlock(); @@ -319,18 +336,21 @@ void Server::externalUserLeft(const QString &userName) while (userGamesIterator.hasNext()) { userGamesIterator.next(); Server_Room *room = rooms.value(userGamesIterator.value().first); - if (!room) + if (!room) { continue; + } QReadLocker roomGamesLocker(&room->gamesLock); Server_Game *game = room->getGames().value(userGamesIterator.key()); - if (!game) + if (!game) { continue; + } QMutexLocker gameLocker(&game->gameMutex); auto *participant = game->getParticipants().value(userGamesIterator.value().second); - if (!participant) + if (!participant) { continue; + } participant->disconnectClient(); } @@ -343,9 +363,11 @@ void Server::externalUserLeft(const QString &userName) SessionEvent *se = Server_ProtocolHandler::prepareSessionEvent(event); clientsLock.lockForRead(); - for (auto &client : clients) - if (client->getAcceptsUserListChanges()) + for (auto &client : clients) { + if (client->getAcceptsUserListChanges()) { client->sendProtocolItem(*se); + } + } clientsLock.unlock(); delete se; } @@ -492,8 +514,9 @@ void Server::externalGameCommandContainerReceived(const CommandContainer &cont, Response::ResponseCode resp = participant->processGameCommand(sc, responseContainer, ges); - if (resp != Response::RespOk) + if (resp != Response::RespOk) { finalResponseCode = resp; + } } ges.sendToGame(game); @@ -547,13 +570,16 @@ void Server::broadcastRoomUpdate(const ServerInfo_Room &roomInfo, bool sendToIsl SessionEvent *se = Server_ProtocolHandler::prepareSessionEvent(event); clientsLock.lockForRead(); - for (auto &client : clients) - if (client->getAcceptsRoomListChanges()) + for (auto &client : clients) { + if (client->getAcceptsRoomListChanges()) { client->sendProtocolItem(*se); + } + } clientsLock.unlock(); - if (sendToIsl) + if (sendToIsl) { sendIsl_SessionEvent(*se); + } delete se; } @@ -591,8 +617,9 @@ void Server::sendIsl_Response(const Response &item, int serverId, qint64 session { IslMessage msg; msg.set_message_type(IslMessage::RESPONSE); - if (sessionId != -1) + if (sessionId != -1) { msg.set_session_id(static_cast(sessionId)); + } msg.mutable_response()->CopyFrom(item); emit sigSendIslMessage(msg, serverId); @@ -602,8 +629,9 @@ void Server::sendIsl_SessionEvent(const SessionEvent &item, int serverId, qint64 { IslMessage msg; msg.set_message_type(IslMessage::SESSION_EVENT); - if (sessionId != -1) + if (sessionId != -1) { msg.set_session_id(static_cast(sessionId)); + } msg.mutable_session_event()->CopyFrom(item); emit sigSendIslMessage(msg, serverId); @@ -613,8 +641,9 @@ void Server::sendIsl_GameEventContainer(const GameEventContainer &item, int serv { IslMessage msg; msg.set_message_type(IslMessage::GAME_EVENT_CONTAINER); - if (sessionId != -1) + if (sessionId != -1) { msg.set_session_id(static_cast(sessionId)); + } msg.mutable_game_event_container()->CopyFrom(item); emit sigSendIslMessage(msg, serverId); @@ -624,8 +653,9 @@ void Server::sendIsl_RoomEvent(const RoomEvent &item, int serverId, qint64 sessi { IslMessage msg; msg.set_message_type(IslMessage::ROOM_EVENT); - if (sessionId != -1) + if (sessionId != -1) { msg.set_session_id(static_cast(sessionId)); + } msg.mutable_room_event()->CopyFrom(item); emit sigSendIslMessage(msg, serverId); diff --git a/libcockatrice_network/libcockatrice/network/server/remote/server_abstractuserinterface.cpp b/libcockatrice_network/libcockatrice/network/server/remote/server_abstractuserinterface.cpp index f9b61ab48..641be1eed 100644 --- a/libcockatrice_network/libcockatrice/network/server/remote/server_abstractuserinterface.cpp +++ b/libcockatrice_network/libcockatrice/network/server/remote/server_abstractuserinterface.cpp @@ -45,25 +45,28 @@ void Server_AbstractUserInterface::sendResponseContainer(const ResponseContainer { const QList> &preResponseQueue = responseContainer.getPreResponseQueue(); - for (int i = 0; i < preResponseQueue.size(); ++i) + for (int i = 0; i < preResponseQueue.size(); ++i) { sendProtocolItemByType(preResponseQueue[i].first, *preResponseQueue[i].second); + } if (responseCode != Response::RespNothing) { Response response; response.set_cmd_id(responseContainer.getCmdId()); response.set_response_code(responseCode); ::google::protobuf::Message *responseExtension = responseContainer.getResponseExtension(); - if (responseExtension) + if (responseExtension) { response.GetReflection() ->MutableMessage(&response, responseExtension->GetDescriptor()->FindExtensionByName("ext")) ->CopyFrom(*responseExtension); + } sendProtocolItem(response); } const QList> &postResponseQueue = responseContainer.getPostResponseQueue(); - for (int i = 0; i < postResponseQueue.size(); ++i) + for (int i = 0; i < postResponseQueue.size(); ++i) { sendProtocolItemByType(postResponseQueue[i].first, *postResponseQueue[i].second); + } } void Server_AbstractUserInterface::playerRemovedFromGame(Server_Game *game) @@ -92,18 +95,21 @@ void Server_AbstractUserInterface::joinPersistentGames(ResponseContainer &rc) const PlayerReference &pr = gamesToJoin.at(i); Server_Room *room = server->getRooms().value(pr.getRoomId()); - if (!room) + if (!room) { continue; + } QReadLocker roomGamesLocker(&room->gamesLock); Server_Game *game = room->getGames().value(pr.getGameId()); - if (!game) + if (!game) { continue; + } QMutexLocker gameLocker(&game->gameMutex); auto *participant = game->getParticipants().value(pr.getPlayerId()); - if (!participant) + if (!participant) { continue; + } participant->setUserInterface(this); playerAddedToGame(game->getGameId(), room->getId(), participant->getPlayerId()); diff --git a/libcockatrice_network/libcockatrice/network/server/remote/server_protocolhandler.cpp b/libcockatrice_network/libcockatrice/network/server/remote/server_protocolhandler.cpp index bfd8d113c..27ebaf228 100644 --- a/libcockatrice_network/libcockatrice/network/server/remote/server_protocolhandler.cpp +++ b/libcockatrice_network/libcockatrice/network/server/remote/server_protocolhandler.cpp @@ -48,8 +48,9 @@ Server_ProtocolHandler::~Server_ProtocolHandler() // The thread must not hold any server locks when calling this (e.g. clientsLock, roomsLock). void Server_ProtocolHandler::prepareDestroy() { - if (deleted) + if (deleted) { return; + } deleted = true; for (auto *room : rooms.values()) { @@ -64,8 +65,9 @@ void Server_ProtocolHandler::prepareDestroy() gameIterator.next(); Server_Room *room = server->getRooms().value(gameIterator.value().first); - if (!room) + if (!room) { continue; + } room->gamesLock.lockForRead(); Server_Game *game = room->getGames().value(gameIterator.key()); if (!game) { @@ -167,8 +169,9 @@ Response::ResponseCode Server_ProtocolHandler::processSessionCommandContainer(co default: resp = processExtendedSessionCommand(num, sc, rc); } - if (resp != Response::RespOk) + if (resp != Response::RespOk) { finalResponseCode = resp; + } } return finalResponseCode; } @@ -176,13 +179,15 @@ Response::ResponseCode Server_ProtocolHandler::processSessionCommandContainer(co Response::ResponseCode Server_ProtocolHandler::processRoomCommandContainer(const CommandContainer &cont, ResponseContainer &rc) { - if (authState == NotLoggedIn) + if (authState == NotLoggedIn) { return Response::RespLoginNeeded; + } QReadLocker locker(&server->roomsLock); Server_Room *room = rooms.value(cont.room_id(), 0); - if (!room) + if (!room) { return Response::RespNotInRoom; + } resetIdleTimer(); @@ -206,8 +211,9 @@ Response::ResponseCode Server_ProtocolHandler::processRoomCommandContainer(const resp = cmdJoinGame(sc.GetExtension(Command_JoinGame::ext), room, rc); break; } - if (resp != Response::RespOk) + if (resp != Response::RespOk) { finalResponseCode = resp; + } } return finalResponseCode; } @@ -232,18 +238,21 @@ Response::ResponseCode Server_ProtocolHandler::processGameCommandContainer(const // allows a user to sideboard without receiving flooding message << GameCommand::MOVE_CARD; - if (authState == NotLoggedIn) + if (authState == NotLoggedIn) { return Response::RespLoginNeeded; + } QMap> gameMap = getGames(); - if (!gameMap.contains(cont.game_id())) + if (!gameMap.contains(cont.game_id())) { return Response::RespNotInRoom; + } const QPair roomIdAndPlayerId = gameMap.value(cont.game_id()); QReadLocker roomsLocker(&server->roomsLock); Server_Room *room = server->getRooms().value(roomIdAndPlayerId.first); - if (!room) + if (!room) { return Response::RespNotInRoom; + } QReadLocker roomGamesLocker(&room->gamesLock); Server_Game *game = room->getGames().value(cont.game_id()); @@ -258,8 +267,9 @@ Response::ResponseCode Server_ProtocolHandler::processGameCommandContainer(const QMutexLocker gameLocker(&game->gameMutex); auto *participant = game->getParticipants().value(roomIdAndPlayerId.second); - if (!participant) + if (!participant) { return Response::RespNotInRoom; + } resetIdleTimer(); @@ -274,11 +284,13 @@ Response::ResponseCode Server_ProtocolHandler::processGameCommandContainer(const if (commandCountingInterval > 0) { int totalCount = 0; - if (commandCountOverTime.isEmpty()) + if (commandCountOverTime.isEmpty()) { commandCountOverTime.prepend(0); + } - if (!antifloodCommandsWhiteList.contains((GameCommand::GameCommandType)getPbExtension(sc))) + if (!antifloodCommandsWhiteList.contains((GameCommand::GameCommandType)getPbExtension(sc))) { ++commandCountOverTime[0]; + } for (int count : commandCountOverTime) { totalCount += count; @@ -291,8 +303,9 @@ Response::ResponseCode Server_ProtocolHandler::processGameCommandContainer(const Response::ResponseCode resp = participant->processGameCommand(sc, rc, ges); - if (resp != Response::RespOk) + if (resp != Response::RespOk) { finalResponseCode = resp; + } } ges.sendToGame(game); @@ -302,10 +315,12 @@ Response::ResponseCode Server_ProtocolHandler::processGameCommandContainer(const Response::ResponseCode Server_ProtocolHandler::processModeratorCommandContainer(const CommandContainer &cont, ResponseContainer &rc) { - if (!userInfo) + if (!userInfo) { return Response::RespLoginNeeded; - if (!(userInfo->user_level() & ServerInfo_User::IsModerator)) + } + if (!(userInfo->user_level() & ServerInfo_User::IsModerator)) { return Response::RespLoginNeeded; + } resetIdleTimer(); @@ -317,8 +332,9 @@ Response::ResponseCode Server_ProtocolHandler::processModeratorCommandContainer( logDebugMessage(getSafeDebugString(sc)); resp = processExtendedModeratorCommand(num, sc, rc); - if (resp != Response::RespOk) + if (resp != Response::RespOk) { finalResponseCode = resp; + } } return finalResponseCode; } @@ -326,10 +342,12 @@ Response::ResponseCode Server_ProtocolHandler::processModeratorCommandContainer( Response::ResponseCode Server_ProtocolHandler::processAdminCommandContainer(const CommandContainer &cont, ResponseContainer &rc) { - if (!userInfo) + if (!userInfo) { return Response::RespLoginNeeded; - if (!(userInfo->user_level() & ServerInfo_User::IsAdmin)) + } + if (!(userInfo->user_level() & ServerInfo_User::IsAdmin)) { return Response::RespLoginNeeded; + } resetIdleTimer(); @@ -341,8 +359,9 @@ Response::ResponseCode Server_ProtocolHandler::processAdminCommandContainer(cons logDebugMessage(getSafeDebugString(sc)); resp = processExtendedAdminCommand(num, sc, rc); - if (resp != Response::RespOk) + if (resp != Response::RespOk) { finalResponseCode = resp; + } } return finalResponseCode; } @@ -350,29 +369,32 @@ Response::ResponseCode Server_ProtocolHandler::processAdminCommandContainer(cons void Server_ProtocolHandler::processCommandContainer(const CommandContainer &cont) { // Command processing must be disabled after prepareDestroy() has been called. - if (deleted) + if (deleted) { return; + } lastDataReceived = timeRunning; ResponseContainer responseContainer(cont.has_cmd_id() ? cont.cmd_id() : -1); Response::ResponseCode finalResponseCode; - if (cont.game_command_size()) + if (cont.game_command_size()) { finalResponseCode = processGameCommandContainer(cont, responseContainer); - else if (cont.room_command_size()) + } else if (cont.room_command_size()) { finalResponseCode = processRoomCommandContainer(cont, responseContainer); - else if (cont.session_command_size()) + } else if (cont.session_command_size()) { finalResponseCode = processSessionCommandContainer(cont, responseContainer); - else if (cont.moderator_command_size()) + } else if (cont.moderator_command_size()) { finalResponseCode = processModeratorCommandContainer(cont, responseContainer); - else if (cont.admin_command_size()) + } else if (cont.admin_command_size()) { finalResponseCode = processAdminCommandContainer(cont, responseContainer); - else + } else { finalResponseCode = Response::RespInvalidCommand; + } - if ((finalResponseCode != Response::RespNothing)) + if ((finalResponseCode != Response::RespNothing)) { sendResponseContainer(responseContainer, finalResponseCode); + } } void Server_ProtocolHandler::pingClockTimeout() @@ -386,11 +408,13 @@ void Server_ProtocolHandler::pingClockTimeout() if (interval > 0) { if (pingclockinterval > 0) { messageSizeOverTime.prepend(0); - if (messageSizeOverTime.size() > (msgcountinterval / pingclockinterval)) + if (messageSizeOverTime.size() > (msgcountinterval / pingclockinterval)) { messageSizeOverTime.removeLast(); + } messageCountOverTime.prepend(0); - if (messageCountOverTime.size() > (msgcountinterval / pingclockinterval)) + if (messageCountOverTime.size() > (msgcountinterval / pingclockinterval)) { messageCountOverTime.removeLast(); + } } } @@ -398,13 +422,15 @@ void Server_ProtocolHandler::pingClockTimeout() if (interval > 0) { if (pingclockinterval > 0) { commandCountOverTime.prepend(0); - if (commandCountOverTime.size() > (cmdcountinterval / pingclockinterval)) + if (commandCountOverTime.size() > (cmdcountinterval / pingclockinterval)) { commandCountOverTime.removeLast(); + } } } - if (timeRunning - lastDataReceived > server->getMaxPlayerInactivityTime()) + if (timeRunning - lastDataReceived > server->getMaxPlayerInactivityTime()) { prepareDestroy(); + } // PrivLevel users, Moderators, and Admins are not subject to the server idle timeout policy const bool hasPrivLevel = userInfo && QString::fromStdString(userInfo->privlevel()).toLower() != "none"; @@ -444,8 +470,9 @@ Response::ResponseCode Server_ProtocolHandler::cmdLogin(const Command_Login &cmd QString password; bool needsHash = false; if (cmd.has_password()) { - if (cmd.password().length() > MAX_NAME_LENGTH) + if (cmd.password().length() > MAX_NAME_LENGTH) { return Response::RespWrongPassword; + } password = QString::fromStdString(cmd.password()); needsHash = true; } else if (cmd.hashed_password().length() > MAX_NAME_LENGTH) { @@ -493,8 +520,9 @@ Response::ResponseCode Server_ProtocolHandler::cmdLogin(const Command_Login &cmd case UserIsBanned: { auto *re = new Response_Login; re->set_denied_reason_str(reasonStr.toStdString()); - if (banSecondsLeft != 0) + if (banSecondsLeft != 0) { re->set_denied_end_time(QDateTime::currentDateTime().addSecs(banSecondsLeft).toSecsSinceEpoch()); + } rc.setResponseExtension(re); return Response::RespUserIsBanned; } @@ -539,19 +567,22 @@ Response::ResponseCode Server_ProtocolHandler::cmdLogin(const Command_Login &cmd if (authState == PasswordRight) { QMapIterator buddyIterator(databaseInterface->getBuddyList(userName)); - while (buddyIterator.hasNext()) + while (buddyIterator.hasNext()) { re->add_buddy_list()->CopyFrom(buddyIterator.next().value()); + } QMapIterator ignoreIterator(databaseInterface->getIgnoreList(userName)); - while (ignoreIterator.hasNext()) + while (ignoreIterator.hasNext()) { re->add_ignore_list()->CopyFrom(ignoreIterator.next().value()); + } } // return to client any missing features the server has that the client does not if (!missingClientFeatures.isEmpty()) { QMap::iterator i; - for (i = missingClientFeatures.begin(); i != missingClientFeatures.end(); ++i) + for (i = missingClientFeatures.begin(); i != missingClientFeatures.end(); ++i) { re->add_missing_features(i.key().toStdString().c_str()); + } } joinPersistentGames(rc); @@ -562,8 +593,9 @@ Response::ResponseCode Server_ProtocolHandler::cmdLogin(const Command_Login &cmd Response::ResponseCode Server_ProtocolHandler::cmdMessage(const Command_Message &cmd, ResponseContainer &rc) { - if (authState == NotLoggedIn) + if (authState == NotLoggedIn) { return Response::RespLoginNeeded; + } QReadLocker locker(&server->clientsLock); @@ -599,8 +631,9 @@ Response::ResponseCode Server_ProtocolHandler::cmdMessage(const Command_Message Response::ResponseCode Server_ProtocolHandler::cmdGetGamesOfUser(const Command_GetGamesOfUser &cmd, ResponseContainer &rc) { - if (authState == NotLoggedIn) + if (authState == NotLoggedIn) { return Response::RespLoginNeeded; + } // Do not show games to someone on the ignore list of that user, except for mods QString target_user = nameFromStdString(cmd.user_name()); @@ -624,8 +657,9 @@ Response::ResponseCode Server_ProtocolHandler::cmdGetGamesOfUser(const Command_G room->gamesLock.lockForRead(); room->getInfo(*re->add_room_list(), false, true); QListIterator gameIterator(room->getGamesOfUser(nameFromStdString(cmd.user_name()))); - while (gameIterator.hasNext()) + while (gameIterator.hasNext()) { re->add_game_list()->CopyFrom(gameIterator.next()); + } room->gamesLock.unlock(); } server->roomsLock.unlock(); @@ -636,14 +670,15 @@ Response::ResponseCode Server_ProtocolHandler::cmdGetGamesOfUser(const Command_G Response::ResponseCode Server_ProtocolHandler::cmdGetUserInfo(const Command_GetUserInfo &cmd, ResponseContainer &rc) { - if (authState == NotLoggedIn) + if (authState == NotLoggedIn) { return Response::RespLoginNeeded; + } QString userName = nameFromStdString(cmd.user_name()); auto *re = new Response_GetUserInfo; - if (userName.isEmpty()) + if (userName.isEmpty()) { re->mutable_user_info()->CopyFrom(*userInfo); - else { + } else { QReadLocker locker(&server->clientsLock); @@ -662,13 +697,15 @@ Response::ResponseCode Server_ProtocolHandler::cmdGetUserInfo(const Command_GetU Response::ResponseCode Server_ProtocolHandler::cmdListRooms(const Command_ListRooms & /*cmd*/, ResponseContainer &rc) { - if (authState == NotLoggedIn) + if (authState == NotLoggedIn) { return Response::RespLoginNeeded; + } Event_ListRooms event; QMapIterator roomIterator(server->getRooms()); - while (roomIterator.hasNext()) + while (roomIterator.hasNext()) { roomIterator.next().value()->getInfo(*event.add_room_list(), false); + } rc.enqueuePreResponseItem(ServerMessage::SESSION_EVENT, prepareSessionEvent(event)); acceptsRoomListChanges = true; @@ -677,20 +714,25 @@ Response::ResponseCode Server_ProtocolHandler::cmdListRooms(const Command_ListRo Response::ResponseCode Server_ProtocolHandler::cmdJoinRoom(const Command_JoinRoom &cmd, ResponseContainer &rc) { - if (authState == NotLoggedIn) + if (authState == NotLoggedIn) { return Response::RespLoginNeeded; + } - if (rooms.contains(cmd.room_id())) + if (rooms.contains(cmd.room_id())) { return Response::RespContextError; + } QReadLocker serverLocker(&server->roomsLock); Server_Room *room = server->getRooms().value(cmd.room_id(), 0); - if (!room) + if (!room) { return Response::RespNameNotFound; + } - if (!(userInfo->user_level() & ServerInfo_User::IsModerator)) - if (!(room->userMayJoin(*userInfo))) + if (!(userInfo->user_level() & ServerInfo_User::IsModerator)) { + if (!(room->userMayJoin(*userInfo))) { return Response::RespUserLevelTooLow; + } + } room->addClient(this); rooms.insert(room->getId(), room); @@ -722,17 +764,20 @@ Response::ResponseCode Server_ProtocolHandler::cmdJoinRoom(const Command_JoinRoo Response::ResponseCode Server_ProtocolHandler::cmdListUsers(const Command_ListUsers & /*cmd*/, ResponseContainer &rc) { - if (authState == NotLoggedIn) + if (authState == NotLoggedIn) { return Response::RespLoginNeeded; + } auto *re = new Response_ListUsers; server->clientsLock.lockForRead(); QMapIterator userIterator = server->getUsers(); - while (userIterator.hasNext()) + while (userIterator.hasNext()) { re->add_user_list()->CopyFrom(userIterator.next().value()->copyUserInfo(false)); + } QMapIterator extIterator = server->getExternalUsers(); - while (extIterator.hasNext()) + while (extIterator.hasNext()) { re->add_user_list()->CopyFrom(extIterator.next().value()->copyUserInfo(false)); + } acceptsUserListChanges = true; server->clientsLock.unlock(); @@ -799,10 +844,12 @@ Server_ProtocolHandler::cmdRoomSay(const Command_RoomSay &cmd, Server_Room *room Response::ResponseCode Server_ProtocolHandler::cmdCreateGame(const Command_CreateGame &cmd, Server_Room *room, ResponseContainer &rc) { - if (authState == NotLoggedIn) + if (authState == NotLoggedIn) { return Response::RespLoginNeeded; - if (cmd.password().length() > MAX_NAME_LENGTH) + } + if (cmd.password().length() > MAX_NAME_LENGTH) { return Response::RespContextError; + } auto level = userInfo->user_level(); bool isJudge = level & ServerInfo_User::IsJudge; @@ -852,8 +899,9 @@ Server_ProtocolHandler::cmdCreateGame(const Command_CreateGame &cmd, Server_Room Response::ResponseCode Server_ProtocolHandler::cmdJoinGame(const Command_JoinGame &cmd, Server_Room *room, ResponseContainer &rc) { - if (authState == NotLoggedIn) + if (authState == NotLoggedIn) { return Response::RespLoginNeeded; + } return room->processJoinGameCommand(cmd, rc, this); } diff --git a/libcockatrice_network/libcockatrice/network/server/remote/server_response_containers.cpp b/libcockatrice_network/libcockatrice/network/server/remote/server_response_containers.cpp index 9b07bdb91..22fb199fb 100644 --- a/libcockatrice_network/libcockatrice/network/server/remote/server_response_containers.cpp +++ b/libcockatrice_network/libcockatrice/network/server/remote/server_response_containers.cpp @@ -25,8 +25,9 @@ GameEventStorage::GameEventStorage() : gameEventContext(0), privatePlayerId(0) GameEventStorage::~GameEventStorage() { delete gameEventContext; - for (int i = 0; i < gameEventList.size(); ++i) + for (int i = 0; i < gameEventList.size(); ++i) { delete gameEventList[i]; + } } void GameEventStorage::setGameEventContext(const ::google::protobuf::Message &_gameEventContext) @@ -44,14 +45,16 @@ void GameEventStorage::enqueueGameEvent(const ::google::protobuf::Message &event int _privatePlayerId) { gameEventList.append(new GameEventStorageItem(event, playerId, recipients)); - if (_privatePlayerId != -1) + if (_privatePlayerId != -1) { privatePlayerId = _privatePlayerId; + } } void GameEventStorage::sendToGame(Server_Game *game) { - if (gameEventList.isEmpty()) + if (gameEventList.isEmpty()) { return; + } auto *contPrivate = new GameEventContainer; auto *contOthers = new GameEventContainer; @@ -68,10 +71,12 @@ void GameEventStorage::sendToGame(Server_Game *game) for (const auto &i : gameEventList) { const GameEvent &event = i->getGameEvent(); const GameEventStorageItem::EventRecipients recipients = i->getRecipients(); - if (recipients.testFlag(GameEventStorageItem::SendToPrivate)) + if (recipients.testFlag(GameEventStorageItem::SendToPrivate)) { contPrivate->add_event_list()->CopyFrom(event); - if (recipients.testFlag(GameEventStorageItem::SendToOthers)) + } + if (recipients.testFlag(GameEventStorageItem::SendToOthers)) { contOthers->add_event_list()->CopyFrom(event); + } } if (gameEventContext) { contPrivate->mutable_context()->CopyFrom(*gameEventContext); @@ -88,8 +93,10 @@ ResponseContainer::ResponseContainer(int _cmdId) : cmdId(_cmdId), responseExtens ResponseContainer::~ResponseContainer() { delete responseExtension; - for (int i = 0; i < preResponseQueue.size(); ++i) + for (int i = 0; i < preResponseQueue.size(); ++i) { delete preResponseQueue[i].second; - for (int i = 0; i < postResponseQueue.size(); ++i) + } + for (int i = 0; i < postResponseQueue.size(); ++i) { delete postResponseQueue[i].second; + } } diff --git a/libcockatrice_network/libcockatrice/network/server/remote/server_room.cpp b/libcockatrice_network/libcockatrice/network/server/remote/server_room.cpp index bfa8912b1..1bd928e09 100644 --- a/libcockatrice_network/libcockatrice/network/server/remote/server_room.cpp +++ b/libcockatrice_network/libcockatrice/network/server/remote/server_room.cpp @@ -42,8 +42,9 @@ Server_Room::~Server_Room() gamesLock.lockForWrite(); const QList gameList = games.values(); - for (int i = 0; i < gameList.size(); ++i) + for (int i = 0; i < gameList.size(); ++i) { delete gameList[i]; + } games.clear(); gamesLock.unlock(); @@ -55,19 +56,23 @@ Server_Room::~Server_Room() bool Server_Room::userMayJoin(const ServerInfo_User &userInfo) { - if (permissionLevel.toLower() == "administrator" || permissionLevel.toLower() == "moderator") + if (permissionLevel.toLower() == "administrator" || permissionLevel.toLower() == "moderator") { return false; + } - if (permissionLevel.toLower() == "registered" && !(userInfo.user_level() & ServerInfo_User::IsRegistered)) + if (permissionLevel.toLower() == "registered" && !(userInfo.user_level() & ServerInfo_User::IsRegistered)) { return false; + } if (privilegeLevel.toLower() != "none") { if (privilegeLevel.toLower() == "privileged") { - if (privilegeLevel.toLower() == "none") + if (privilegeLevel.toLower() == "none") { return false; + } } else { - if (privilegeLevel.toLower() != QString::fromStdString(userInfo.privlevel()).toLower()) + if (privilegeLevel.toLower() != QString::fromStdString(userInfo.privlevel()).toLower()) { return false; + } } } return true; @@ -92,12 +97,14 @@ Server_Room::getInfo(ServerInfo_Room &result, bool complete, bool showGameTypes, result.set_game_count(games.size() + externalGames.size()); if (complete) { QMapIterator gameIterator(games); - while (gameIterator.hasNext()) + while (gameIterator.hasNext()) { gameIterator.next().value()->getInfo(*result.add_game_list()); + } if (includeExternalData) { QMapIterator externalGameIterator(externalGames); - while (externalGameIterator.hasNext()) + while (externalGameIterator.hasNext()) { result.add_game_list()->CopyFrom(externalGameIterator.next().value()); + } } } gamesLock.unlock(); @@ -106,22 +113,25 @@ Server_Room::getInfo(ServerInfo_Room &result, bool complete, bool showGameTypes, result.set_player_count(users.size() + externalUsers.size()); if (complete) { QMapIterator userIterator(users); - while (userIterator.hasNext()) + while (userIterator.hasNext()) { result.add_user_list()->CopyFrom(userIterator.next().value()->copyUserInfo(false)); + } if (includeExternalData) { QMapIterator externalUserIterator(externalUsers); - while (externalUserIterator.hasNext()) + while (externalUserIterator.hasNext()) { result.add_user_list()->CopyFrom(externalUserIterator.next().value().copyUserInfo(false)); + } } } usersLock.unlock(); - if (complete || showGameTypes) + if (complete || showGameTypes) { for (int i = 0; i < gameTypes.size(); ++i) { ServerInfo_GameType *gameTypeInfo = result.add_gametype_list(); gameTypeInfo->set_game_type_id(i); gameTypeInfo->set_description(gameTypes[i].toStdString()); } + } return result; } @@ -208,8 +218,9 @@ void Server_Room::removeExternalUser(const QString &_name) roomInfo.set_room_id(id); usersLock.lockForWrite(); - if (externalUsers.contains(_name)) + if (externalUsers.contains(_name)) { externalUsers.remove(_name); + } roomInfo.set_player_count(users.size() + externalUsers.size()); usersLock.unlock(); @@ -227,10 +238,11 @@ void Server_Room::updateExternalGameList(const ServerInfo_Game &gameInfo) roomInfo.set_room_id(id); gamesLock.lockForWrite(); - if (!gameInfo.has_player_count() && externalGames.contains(gameInfo.game_id())) + if (!gameInfo.has_player_count() && externalGames.contains(gameInfo.game_id())) { externalGames.remove(gameInfo.game_id()); - else + } else { externalGames.insert(gameInfo.game_id(), gameInfo); + } roomInfo.set_game_count(games.size() + externalGames.size()); gamesLock.unlock(); @@ -242,8 +254,9 @@ Response::ResponseCode Server_Room::processJoinGameCommand(const Command_JoinGam ResponseContainer &rc, Server_AbstractUserInterface *userInterface) { - if (cmd.password().length() > MAX_NAME_LENGTH) + if (cmd.password().length() > MAX_NAME_LENGTH) { return Response::RespWrongPassword; + } // This function is called from the Server thread and from the S_PH thread. // server->roomsMutex is always locked. @@ -271,8 +284,9 @@ Response::ResponseCode Server_Room::processJoinGameCommand(const Command_JoinGam Response::ResponseCode result = game->checkJoin(userInterface->getUserInfo(), QString::fromStdString(cmd.password()), cmd.spectator(), cmd.override_restrictions(), cmd.join_as_judge()); - if (result == Response::RespOk) + if (result == Response::RespOk) { game->addPlayer(userInterface, rc, cmd.spectator(), cmd.join_as_judge()); + } return result; } @@ -329,13 +343,15 @@ void Server_Room::sendRoomEvent(RoomEvent *event, bool sendToIsl) usersLock.lockForRead(); { QMapIterator userIterator(users); - while (userIterator.hasNext()) + while (userIterator.hasNext()) { userIterator.next().value()->sendProtocolItem(*event); + } } usersLock.unlock(); - if (sendToIsl) + if (sendToIsl) { static_cast(parent())->sendIsl_RoomEvent(*event); + } delete event; } @@ -405,9 +421,11 @@ int Server_Room::getGamesCreatedByUser(const QString &userName) const QMapIterator gamesIterator(games); int result = 0; - while (gamesIterator.hasNext()) - if (gamesIterator.next().value()->getCreatorInfo()->name() == userName.toStdString()) + while (gamesIterator.hasNext()) { + if (gamesIterator.next().value()->getCreatorInfo()->name() == userName.toStdString()) { ++result; + } + } return result; } diff --git a/libcockatrice_network/libcockatrice/network/server/remote/serverinfo_user_container.cpp b/libcockatrice_network/libcockatrice/network/server/remote/serverinfo_user_container.cpp index 77ff38906..24e734a4e 100644 --- a/libcockatrice_network/libcockatrice/network/server/remote/serverinfo_user_container.cpp +++ b/libcockatrice_network/libcockatrice/network/server/remote/serverinfo_user_container.cpp @@ -13,10 +13,11 @@ ServerInfo_User_Container::ServerInfo_User_Container(const ServerInfo_User &_use ServerInfo_User_Container::ServerInfo_User_Container(const ServerInfo_User_Container &other) { - if (other.userInfo) + if (other.userInfo) { userInfo = new ServerInfo_User(*other.userInfo); - else + } else { userInfo = nullptr; + } } ServerInfo_User_Container::~ServerInfo_User_Container() @@ -45,8 +46,9 @@ ServerInfo_User &ServerInfo_User_Container::copyUserInfo(ServerInfo_User &result result.clear_id(); result.clear_email(); } - if (!complete) + if (!complete) { result.clear_avatar_bmp(); + } } return result; } diff --git a/libcockatrice_protocol/libcockatrice/protocol/debug_pb_message.cpp b/libcockatrice_protocol/libcockatrice/protocol/debug_pb_message.cpp index 718487c18..c419a68d4 100644 --- a/libcockatrice_protocol/libcockatrice/protocol/debug_pb_message.cpp +++ b/libcockatrice_protocol/libcockatrice/protocol/debug_pb_message.cpp @@ -58,8 +58,9 @@ void SafePrinter::applySafePrinter(const ::google::protobuf::Message &message, case ::google::protobuf::FieldDescriptor::CPPTYPE_STRING: if (field->name().find("password") != std::string::npos) { // name contains password auto *safePrinter = new SafePrinter(); - if (!printer.RegisterFieldValuePrinter(field, safePrinter)) + if (!printer.RegisterFieldValuePrinter(field, safePrinter)) { delete safePrinter; // in case safePrinter has not been taken ownership of + } } break; case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE: diff --git a/libcockatrice_protocol/libcockatrice/protocol/featureset.cpp b/libcockatrice_protocol/libcockatrice/protocol/featureset.cpp index 1b08c4040..3e687ef56 100644 --- a/libcockatrice_protocol/libcockatrice/protocol/featureset.cpp +++ b/libcockatrice_protocol/libcockatrice/protocol/featureset.cpp @@ -33,14 +33,16 @@ void FeatureSet::initalizeFeatureList(QMap &_featureList) void FeatureSet::enableRequiredFeature(QMap &_featureList, const QString &featureName) { - if (_featureList.contains(featureName)) + if (_featureList.contains(featureName)) { _featureList.insert(featureName, true); + } } void FeatureSet::disableRequiredFeature(QMap &_featureList, const QString &featureName) { - if (_featureList.contains(featureName)) + if (_featureList.contains(featureName)) { _featureList.insert(featureName, false); + } } QMap diff --git a/libcockatrice_protocol/libcockatrice/protocol/get_pb_extension.cpp b/libcockatrice_protocol/libcockatrice/protocol/get_pb_extension.cpp index d6235858a..a693ea5a7 100644 --- a/libcockatrice_protocol/libcockatrice/protocol/get_pb_extension.cpp +++ b/libcockatrice_protocol/libcockatrice/protocol/get_pb_extension.cpp @@ -7,8 +7,10 @@ int getPbExtension(const ::google::protobuf::Message &message) { std::vector fieldList; message.GetReflection()->ListFields(message, &fieldList); - for (unsigned int j = 0; j < fieldList.size(); ++j) - if (fieldList[j]->is_extension()) + for (unsigned int j = 0; j < fieldList.size(); ++j) { + if (fieldList[j]->is_extension()) { return fieldList[j]->number(); + } + } return -1; } diff --git a/libcockatrice_rng/libcockatrice/rng/rng_abstract.cpp b/libcockatrice_rng/libcockatrice/rng/rng_abstract.cpp index 63072b988..82404d351 100644 --- a/libcockatrice_rng/libcockatrice/rng/rng_abstract.cpp +++ b/libcockatrice_rng/libcockatrice/rng/rng_abstract.cpp @@ -8,10 +8,11 @@ QVector RNG_Abstract::makeNumbersVector(int n, int min, int max) QVector result(bins); for (int i = 0; i < n; ++i) { int number = rand(min, max); - if ((number < min) || (number > max)) + if ((number < min) || (number > max)) { qDebug() << "rand(" << min << "," << max << ") returned " << number; - else + } else { result[number - min]++; + } } return result; } @@ -19,12 +20,14 @@ QVector RNG_Abstract::makeNumbersVector(int n, int min, int max) double RNG_Abstract::testRandom(const QVector &numbers) const { int n = 0; - for (int i = 0; i < numbers.size(); ++i) + for (int i = 0; i < numbers.size(); ++i) { n += numbers[i]; + } double expected = (double)n / (double)numbers.size(); double chisq = 0; - for (int i = 0; i < numbers.size(); ++i) + for (int i = 0; i < numbers.size(); ++i) { chisq += ((double)numbers[i] - expected) * ((double)numbers[i] - expected) / expected; + } return chisq; } diff --git a/libcockatrice_rng/libcockatrice/rng/rng_sfmt.cpp b/libcockatrice_rng/libcockatrice/rng/rng_sfmt.cpp index 5a6d8c862..5b38deb3f 100644 --- a/libcockatrice_rng/libcockatrice/rng/rng_sfmt.cpp +++ b/libcockatrice_rng/libcockatrice/rng/rng_sfmt.cpp @@ -40,8 +40,9 @@ unsigned int RNG_SFMT::rand(int min, int max) } // For complete fairness and equal timing, this should be a roll, but let's skip it anyway - if (min == max) + if (min == max) { return max; + } // This is actually not used in Cockatrice: // Someone wants rand() % -foo, so we should compute -rand(0, +foo) diff --git a/libcockatrice_settings/libcockatrice/settings/servers_settings.cpp b/libcockatrice_settings/libcockatrice/settings/servers_settings.cpp index 0140182be..d9b98e036 100644 --- a/libcockatrice_settings/libcockatrice/settings/servers_settings.cpp +++ b/libcockatrice_settings/libcockatrice/settings/servers_settings.cpp @@ -58,9 +58,11 @@ int ServersSettings::getPrevioushostindex(const QString &saveName) const { int size = getValue("totalServers", "server", "server_details").toInt(); - for (int i = 0; i <= size; ++i) - if (saveName == getValue(QString("saveName%1").arg(i), "server", "server_details").toString()) + for (int i = 0; i <= size; ++i) { + if (saveName == getValue(QString("saveName%1").arg(i), "server", "server_details").toString()) { return i; + } + } return -1; } @@ -92,8 +94,9 @@ QString ServersSettings::getPassword() { int index = getPrevioushostindex(getPrevioushostName()); - if (getSavePassword()) + if (getSavePassword()) { return getValue(QString("password%1").arg(index), "server", "server_details").toString(); + } return QString(); } @@ -168,8 +171,9 @@ void ServersSettings::addNewServer(const QString &saveName, bool savePassword, const QString &site) { - if (updateExistingServer(saveName, serv, port, username, password, savePassword, site)) + if (updateExistingServer(saveName, serv, port, username, password, savePassword, site)) { return; + } int index = getValue("totalServers", "server", "server_details").toInt() + 1; diff --git a/libcockatrice_utility/libcockatrice/utility/color.h b/libcockatrice_utility/libcockatrice/utility/color.h index f02df3a0e..31bcb3734 100644 --- a/libcockatrice_utility/libcockatrice/utility/color.h +++ b/libcockatrice_utility/libcockatrice/utility/color.h @@ -45,11 +45,13 @@ inline QColor colorHelper(const QString &name) {"Land", QColor(110, 80, 50)}, }; - if (colorMap.contains(name)) + if (colorMap.contains(name)) { return colorMap[name]; + } - if (name.length() == 1 && colorMap.contains(name.toUpper())) + if (name.length() == 1 && colorMap.contains(name.toUpper())) { return colorMap[name.toUpper()]; + } uint h = qHash(name); int r = 100 + (h % 120); diff --git a/libcockatrice_utility/libcockatrice/utility/expression.cpp b/libcockatrice_utility/libcockatrice/utility/expression.cpp index 42073670c..718b0fe18 100644 --- a/libcockatrice_utility/libcockatrice/utility/expression.cpp +++ b/libcockatrice_utility/libcockatrice/utility/expression.cpp @@ -54,8 +54,9 @@ double Expression::eval(const peg::Ast &ast) return stod(std::string(ast.token)); } else if (ast.name == "FUNCTION") { QString name = QString::fromStdString(std::string(nodes[0]->token)); - if (!fns.contains(name)) + if (!fns.contains(name)) { return 0; + } return fns[name](eval(*nodes[1])); } else if (ast.name == "VARIABLE") { return value; diff --git a/libcockatrice_utility/libcockatrice/utility/levenshtein.cpp b/libcockatrice_utility/libcockatrice/utility/levenshtein.cpp index cfb972f91..f39d325fb 100644 --- a/libcockatrice_utility/libcockatrice/utility/levenshtein.cpp +++ b/libcockatrice_utility/libcockatrice/utility/levenshtein.cpp @@ -9,10 +9,12 @@ int levenshteinDistance(const QString &s1, const QString &s2) int len2 = s2.size(); std::vector> dp(len1 + 1, std::vector(len2 + 1)); - for (int i = 0; i <= len1; i++) + for (int i = 0; i <= len1; i++) { dp[i][0] = i; - for (int j = 0; j <= len2; j++) + } + for (int j = 0; j <= len2; j++) { dp[0][j] = j; + } for (int i = 1; i <= len1; i++) { for (int j = 1; j <= len2; j++) { diff --git a/libcockatrice_utility/libcockatrice/utility/qt_utils.h b/libcockatrice_utility/libcockatrice/utility/qt_utils.h index 606947143..334e56027 100644 --- a/libcockatrice_utility/libcockatrice/utility/qt_utils.h +++ b/libcockatrice_utility/libcockatrice/utility/qt_utils.h @@ -18,14 +18,17 @@ template T *findParentOfType(const QObject *obj) static inline void clearLayoutRec(QLayout *l) { - if (!l) + if (!l) { return; + } QLayoutItem *it; while ((it = l->takeAt(0)) != nullptr) { - if (QWidget *w = it->widget()) + if (QWidget *w = it->widget()) { w->deleteLater(); - if (QLayout *sub = it->layout()) + } + if (QLayout *sub = it->layout()) { clearLayoutRec(sub); + } delete it; } } diff --git a/oracle/src/oracleimporter.cpp b/oracle/src/oracleimporter.cpp index 578afd98d..05a3a7ca3 100644 --- a/oracle/src/oracleimporter.cpp +++ b/oracle/src/oracleimporter.cpp @@ -124,10 +124,11 @@ static void sortAndReduceColors(QString &colors) // reduce QChar lastChar = '\0'; for (int i = 0; i < colors.size(); ++i) { - if (colors.at(i) == lastChar) + if (colors.at(i) == lastChar) { colors.remove(i, 1); - else + } else { lastChar = colors.at(i); + } } } @@ -191,12 +192,13 @@ CardInfoPtr OracleImporter::addCard(QString name, // table row int tableRow = 1; QString mainCardType = properties.value("maintype").toString(); - if (mainCardType == "Land") + if (mainCardType == "Land") { tableRow = 0; - else if (mainCardType == "Sorcery" || mainCardType == "Instant") + } else if (mainCardType == "Sorcery" || mainCardType == "Instant") { tableRow = 3; - else if (mainCardType == "Creature") + } else if (mainCardType == "Creature") { tableRow = 2; + } // card side QString side = properties.value("side").toString() == "b" ? "back" : "front"; @@ -282,8 +284,9 @@ int OracleImporter::importCardsFromSet(const CardSetPtr ¤tSet, const QList QString mtgjsonProperty = i.key(); QString xmlPropertyName = i.value(); QString propertyValue = getStringPropertyFromMap(card, mtgjsonProperty); - if (!propertyValue.isEmpty()) + if (!propertyValue.isEmpty()) { properties.insert(xmlPropertyName, propertyValue); + } } // per-set properties @@ -292,8 +295,9 @@ int OracleImporter::importCardsFromSet(const CardSetPtr ¤tSet, const QList QString mtgjsonProperty = i.key(); QString xmlPropertyName = i.value(); QString propertyValue = getStringPropertyFromMap(card, mtgjsonProperty); - if (!propertyValue.isEmpty()) + if (!propertyValue.isEmpty()) { printingInfo.setProperty(xmlPropertyName, propertyValue); + } } // handle flavorNames specially due to double-faced cards @@ -544,8 +548,9 @@ int OracleImporter::startImport() CardSetPtr newSet = CardSet::newInstance(noOpController, curSetToParse.getShortName(), curSetToParse.getLongName(), curSetToParse.getSetType(), curSetToParse.getReleaseDate(), curSetToParse.getPriority()); - if (!sets.contains(newSet->getShortName())) + if (!sets.contains(newSet->getShortName())) { sets.insert(newSet->getShortName(), newSet); + } int numCardsInSet = importCardsFromSet(newSet, curSetToParse.getCards()); diff --git a/servatrice/src/isl_interface.cpp b/servatrice/src/isl_interface.cpp index 692a0fdba..b0ee201bf 100644 --- a/servatrice/src/isl_interface.cpp +++ b/servatrice/src/isl_interface.cpp @@ -76,8 +76,9 @@ IslInterface::~IslInterface() QMapIterator roomUsers(room->getExternalUsers()); while (roomUsers.hasNext()) { roomUsers.next(); - if (roomUsers.value().getUserInfo()->server_id() == serverId) + if (roomUsers.value().getUserInfo()->server_id() == serverId) { emit externalRoomUserLeft(room->getId(), roomUsers.key()); + } } room->usersLock.unlock(); } @@ -87,8 +88,9 @@ IslInterface::~IslInterface() QMapIterator extUsers(server->getExternalUsers()); while (extUsers.hasNext()) { extUsers.next(); - if (extUsers.value()->getUserInfo()->server_id() == serverId) + if (extUsers.value()->getUserInfo()->server_id() == serverId) { emit externalUserLeft(extUsers.key()); + } } server->clientsLock.unlock(); } @@ -101,11 +103,12 @@ void IslInterface::initServer() QList serverList = server->getServerList(); int listIndex = -1; - for (int i = 0; i < serverList.size(); ++i) + for (int i = 0; i < serverList.size(); ++i) { if (serverList[i].address == socket->peerAddress()) { listIndex = i; break; } + } if (listIndex == -1) { logger->logMessage( QString("[ISL] address %1 unknown, terminating connection").arg(socket->peerAddress().toString())); @@ -125,9 +128,9 @@ void IslInterface::initServer() return; } - if (serverList[listIndex].cert == socket->peerCertificate()) + if (serverList[listIndex].cert == socket->peerCertificate()) { logger->logMessage(QString("[ISL] Peer authenticated as " + serverList[listIndex].hostname)); - else { + } else { logger->logMessage(QString("[ISL] Authentication failed, terminating connection")); deleteLater(); return; @@ -139,8 +142,9 @@ void IslInterface::initServer() server->clientsLock.lockForRead(); QMapIterator userIterator(server->getUsers()); - while (userIterator.hasNext()) + while (userIterator.hasNext()) { event.add_user_list()->CopyFrom(userIterator.next().value()->copyUserInfo(true, true)); + } server->clientsLock.unlock(); server->roomsLock.lockForRead(); @@ -217,8 +221,9 @@ void IslInterface::initClient() void IslInterface::flushOutputBuffer() { QMutexLocker locker(&outputBufferMutex); - if (outputBuffer.isEmpty()) + if (outputBuffer.isEmpty()) { return; + } server->incTxBytes(outputBuffer.size()); socket->write(outputBuffer); socket->flush(); @@ -240,11 +245,13 @@ void IslInterface::readClient() ((quint32)(unsigned char)inputBuffer[3]); inputBuffer.remove(0, 4); messageInProgress = true; - } else + } else { return; + } } - if (inputBuffer.size() < messageLength) + if (inputBuffer.size() < messageLength) { return; + } IslMessage newMessage; bool ok = newMessage.ParseFromArray(inputBuffer.data(), messageLength); diff --git a/servatrice/src/main.cpp b/servatrice/src/main.cpp index b1294a04c..9e7fe38d9 100644 --- a/servatrice/src/main.cpp +++ b/servatrice/src/main.cpp @@ -69,19 +69,22 @@ void testRNG() for (int i = 0; i <= maxMax - min; ++i) { std::cerr << (min + i); for (auto &number : numbers) { - if (i < number.size()) + if (i < number.size()) { std::cerr << "\t" << number[i]; - else + } else { std::cerr << "\t"; + } } std::cerr << std::endl; } std::cerr << std::endl << "Chi^2 ="; - for (double j : chisq) + for (double j : chisq) { std::cerr << "\t" << QString::number(j, 'f', 3).toStdString(); + } std::cerr << std::endl << "k ="; - for (int j = 0; j < chisq.size(); ++j) + for (int j = 0; j < chisq.size(); ++j) { std::cerr << "\t" << (j - min + minMax); + } std::cerr << std::endl << std::endl; } @@ -90,8 +93,9 @@ void testHash() const int n = 5000; std::cerr << "Benchmarking password hash function (n =" << n << ")..." << std::endl; QDateTime startTime = QDateTime::currentDateTime(); - for (int i = 0; i < n; ++i) + for (int i = 0; i < n; ++i) { PasswordHasher::computeHash("aaaaaa", "aaaaaaaaaaaaaaaa"); + } QDateTime endTime = QDateTime::currentDateTime(); std::cerr << startTime.secsTo(endTime) << "secs" << std::endl; } @@ -157,10 +161,11 @@ int main(int argc, char *argv[]) QMetaObject::invokeMethod(logger, "startLog", Qt::BlockingQueuedConnection, Q_ARG(QString, settingsCache->value("server/logfile", QString("server.log")).toString())); - if (logToConsole) + if (logToConsole) { qInstallMessageHandler(myMessageOutput); - else + } else { qInstallMessageHandler(myMessageOutput2); + } signalhandler = new SignalHandler(); diff --git a/servatrice/src/servatrice.cpp b/servatrice/src/servatrice.cpp index 410bf4ed9..aa50e068a 100644 --- a/servatrice/src/servatrice.cpp +++ b/servatrice/src/servatrice.cpp @@ -318,8 +318,9 @@ bool Servatrice::initServer() query2->bindValue(":id_room", query->value(0).toInt()); servatriceDatabaseInterface->execSqlQuery(query2); QStringList gameTypes; - while (query2->next()) + while (query2->next()) { gameTypes.append(query2->value(0).toString()); + } addRoom(new Server_Room(query->value(0).toInt(), query->value(7).toInt(), query->value(1).toString(), query->value(2).toString(), query->value(3).toString().toLower(), query->value(4).toString().toLower(), static_cast(query->value(5).toInt()), @@ -362,21 +363,25 @@ bool Servatrice::initServer() qDebug() << "Connecting to ISL network."; qDebug() << "Loading certificate..."; QFile certFile(getISLNetworkSSLCertFile()); - if (!certFile.open(QIODevice::ReadOnly)) + if (!certFile.open(QIODevice::ReadOnly)) { throw QString("Error opening certificate file: %1").arg(getISLNetworkSSLCertFile()); + } QSslCertificate cert(&certFile); const QDateTime currentTime = QDateTime::currentDateTime(); - if (currentTime < cert.effectiveDate() || currentTime > cert.expiryDate() || cert.isBlacklisted()) + if (currentTime < cert.effectiveDate() || currentTime > cert.expiryDate() || cert.isBlacklisted()) { throw QString("Invalid certificate."); + } qDebug() << "Loading private key..."; QFile keyFile(getISLNetworkSSLKeyFile()); - if (!keyFile.open(QIODevice::ReadOnly)) + if (!keyFile.open(QIODevice::ReadOnly)) { throw QString("Error opening private key file: %1").arg(getISLNetworkSSLKeyFile()); + } QSslKey key(&keyFile, QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey); - if (key.isNull()) + if (key.isNull()) { throw QString("Invalid private key."); + } QMutableListIterator serverIterator(serverList); while (serverIterator.hasNext()) { @@ -401,10 +406,11 @@ bool Servatrice::initServer() qDebug() << "Starting ISL server on port" << getISLNetworkPort(); islServer = new Servatrice_IslServer(this, cert, key, this); - if (islServer->listen(QHostAddress::Any, static_cast(getISLNetworkPort()))) + if (islServer->listen(QHostAddress::Any, static_cast(getISLNetworkPort()))) { qDebug() << "ISL server listening."; - else + } else { throw QString("islServer->listen()"); + } } } catch (QString &error) { qDebug() << "ERROR --" << error; @@ -429,9 +435,9 @@ bool Servatrice::initServer() gameServer->setMaxPendingConnections(1000); QHostAddress tcpHost = getServerTCPHost(); qDebug() << "Starting server on host" << tcpHost.toString() << "port" << getServerTCPPort(); - if (gameServer->listen(tcpHost, static_cast(getServerTCPPort()))) + if (gameServer->listen(tcpHost, static_cast(getServerTCPPort()))) { qDebug() << "Server listening."; - else { + } else { qDebug() << "gameServer->listen(): Error:" << gameServer->errorString(); return false; } @@ -445,9 +451,9 @@ bool Servatrice::initServer() QHostAddress webSocketHost = getServerWebSocketHost(); qDebug() << "Starting websocket server on host" << webSocketHost.toString() << "port" << getServerWebSocketPort(); - if (websocketGameServer->listen(webSocketHost, static_cast(getServerWebSocketPort()))) + if (websocketGameServer->listen(webSocketHost, static_cast(getServerWebSocketPort()))) { qDebug() << "Websocket server listening."; - else { + } else { qDebug() << "websocketGameServer->listen(): Error:" << websocketGameServer->errorString(); return false; } @@ -455,11 +461,12 @@ bool Servatrice::initServer() if (getIdleClientTimeout() > 0) { qDebug() << "Idle client timeout value:" << getIdleClientTimeout(); - if (getIdleClientTimeout() < 300) + if (getIdleClientTimeout() < 300) { qDebug() << "WARNING: It is not recommended to set the IdleClientTimeout value very low. Doing so will " "cause clients to very quickly be disconnected. Many players when connected may be searching " "for card details outside the client in the middle of matches or possibly drafting outside the " "client and short time out values will remove these players."; + } } setRequiredFeatures(getRequiredFeatures()); @@ -511,9 +518,11 @@ int Servatrice::getUsersWithAddress(const QHostAddress &address) const { int result = 0; QReadLocker locker(&clientsLock); - for (auto client : clients) - if (static_cast(client)->getPeerAddress() == address) + for (auto client : clients) { + if (static_cast(client)->getPeerAddress() == address) { ++result; + } + } return result; } @@ -522,21 +531,24 @@ QList Servatrice::getUsersWithAddressAsList(con { QList result; QReadLocker locker(&clientsLock); - for (auto client : clients) - if (static_cast(client)->getPeerAddress() == address) + for (auto client : clients) { + if (static_cast(client)->getPeerAddress() == address) { result.append(static_cast(client)); + } + } return result; } void Servatrice::updateLoginMessage() { - if (!servatriceDatabaseInterface->checkSql()) + if (!servatriceDatabaseInterface->checkSql()) { return; + } QSqlQuery *query = servatriceDatabaseInterface->prepareQuery( "select message from {prefix}_servermessages where id_server = :id_server order by timest desc limit 1"); query->bindValue(":id_server", serverId); - if (servatriceDatabaseInterface->execSqlQuery(query)) + if (servatriceDatabaseInterface->execSqlQuery(query)) { if (query->next()) { const QString newLoginMessage = query->value(0).toString(); @@ -548,10 +560,12 @@ void Servatrice::updateLoginMessage() event.set_message(newLoginMessage.toStdString()); SessionEvent *se = Server_ProtocolHandler::prepareSessionEvent(event); QMapIterator usersIterator(users); - while (usersIterator.hasNext()) + while (usersIterator.hasNext()) { usersIterator.next().value()->sendProtocolItem(*se); + } delete se; } + } } void Servatrice::setRequiredFeatures(const QString &featureList) @@ -560,18 +574,20 @@ void Servatrice::setRequiredFeatures(const QString &featureList) serverRequiredFeatureList.clear(); features.initalizeFeatureList(serverRequiredFeatureList); QStringList listReqFeatures = featureList.split(",", Qt::SkipEmptyParts); - if (!listReqFeatures.isEmpty()) + if (!listReqFeatures.isEmpty()) { for (const QString &reqFeature : listReqFeatures) { features.enableRequiredFeature(serverRequiredFeatureList, reqFeature); } + } qDebug() << "Set required client features to:" << serverRequiredFeatureList; } void Servatrice::statusUpdate() { - if (!servatriceDatabaseInterface->checkSql()) + if (!servatriceDatabaseInterface->checkSql()) { return; + } const int uc = getUsersCount(); // for correct mutex locking order @@ -611,8 +627,9 @@ void Servatrice::statusUpdate() auto servDbSelQuery = servatriceDatabaseInterface->prepareQuery("select a.name, b.email, b.token from " "{prefix}_activation_emails a left join " "{prefix}_users b on a.name = b.name"); - if (!servatriceDatabaseInterface->execSqlQuery(servDbSelQuery)) + if (!servatriceDatabaseInterface->execSqlQuery(servDbSelQuery)) { return; + } auto *queryDelete = servatriceDatabaseInterface->prepareQuery("delete from {prefix}_activation_emails where name = :name"); @@ -633,8 +650,9 @@ void Servatrice::statusUpdate() auto *forgotPwQuery = servatriceDatabaseInterface->prepareQuery( "select a.name, b.email, b.token from {prefix}_forgot_password a left join {prefix}_users b on a.name " "= b.name where a.emailed = 0"); - if (!servatriceDatabaseInterface->execSqlQuery(forgotPwQuery)) + if (!servatriceDatabaseInterface->execSqlQuery(forgotPwQuery)) { return; + } QSqlQuery *queryDelete = servatriceDatabaseInterface->prepareQuery( "update {prefix}_forgot_password set emailed = 1 where name = :name"); @@ -686,8 +704,9 @@ void Servatrice::shutdownTimeout() { // Show every time counter cut in half & every minute for last 5 minutes if (shutdownMinutes <= 5 || shutdownMinutes == nextShutdownMessageMinutes) { - if (shutdownMinutes == nextShutdownMessageMinutes) + if (shutdownMinutes == nextShutdownMessageMinutes) { nextShutdownMessageMinutes = shutdownMinutes / 2; + } SessionEvent *se; if (shutdownMinutes) { @@ -702,8 +721,9 @@ void Servatrice::shutdownTimeout() } clientsLock.lockForRead(); - for (auto &client : clients) + for (auto &client : clients) { client->sendProtocolItem(*se); + } clientsLock.unlock(); delete se; @@ -759,12 +779,14 @@ void Servatrice::doSendIslMessage(const IslMessage &msg, int _serverId) if (_serverId == -1) { QMapIterator islIterator(islInterfaces); - while (islIterator.hasNext()) + while (islIterator.hasNext()) { islIterator.next().value()->transmitMessage(msg); + } } else { IslInterface *interface = islInterfaces.value(_serverId); - if (interface) + if (interface) { interface->transmitMessage(msg); + } } } @@ -968,10 +990,11 @@ bool Servatrice::permitCreateGameAsJudge() const QHostAddress Servatrice::getServerTCPHost() const { QString host = settingsCache->value("server/host", "any").toString(); - if (host == "any") + if (host == "any") { return QHostAddress::Any; - else + } else { return QHostAddress(host); + } } int Servatrice::getServerTCPPort() const @@ -987,10 +1010,11 @@ int Servatrice::getNumberOfWebSocketPools() const QHostAddress Servatrice::getServerWebSocketHost() const { QString host = settingsCache->value("server/websocket_host", "any").toString(); - if (host == "any") + if (host == "any") { return QHostAddress::Any; - else + } else { return QHostAddress(host); + } } int Servatrice::getServerWebSocketPort() const diff --git a/servatrice/src/servatrice_database_interface.cpp b/servatrice/src/servatrice_database_interface.cpp index bce3542e8..73643825e 100644 --- a/servatrice/src/servatrice_database_interface.cpp +++ b/servatrice/src/servatrice_database_interface.cpp @@ -55,8 +55,9 @@ bool Servatrice_DatabaseInterface::initDatabase(const QString &type, bool Servatrice_DatabaseInterface::openDatabase() { - if (sqlDatabase.isOpen()) + if (sqlDatabase.isOpen()) { sqlDatabase.close(); + } const QString poolStr = instanceId == -1 ? QString("main") : QString("pool %1").arg(instanceId); qCDebug(DatabaseInterfaceLog).noquote() << poolStr << "Opening database..."; @@ -139,8 +140,9 @@ QSqlQuery *Servatrice_DatabaseInterface::prepareQuery(const QString &queryText) bool Servatrice_DatabaseInterface::execSqlQuery(QSqlQuery *query) { - if (query->exec()) + if (query->exec()) { return true; + } const QString poolStr = instanceId == -1 ? QString("main") : QString("pool %1").arg(instanceId); qCCritical(DatabaseInterfaceLog) << poolStr << "Error executing query:" << query->lastError().text(); sqlDatabase.close(); @@ -151,8 +153,9 @@ bool Servatrice_DatabaseInterface::execSqlQuery(QSqlQuery *query) bool Servatrice_DatabaseInterface::usernameIsValid(const QString &user, QString &error) { int minNameLength = settingsCache->value("users/minnamelength", 6).toInt(); - if (minNameLength < 1) + if (minNameLength < 1) { minNameLength = 1; + } int maxNameLength = settingsCache->value("users/maxnamelength", 12).toInt(); bool allowLowercase = settingsCache->value("users/allowlowercase", true).toBool(); bool allowUppercase = settingsCache->value("users/allowuppercase", true).toBool(); @@ -184,29 +187,36 @@ bool Servatrice_DatabaseInterface::usernameIsValid(const QString &user, QString .arg(disallowedWordsStr) .arg(disallowedRegExpStr); - if (user.length() < minNameLength || user.length() > maxNameLength) + if (user.length() < minNameLength || user.length() > maxNameLength) { return false; + } - if (!allowPunctuationPrefix && allowedPunctuation.contains(user.at(0))) + if (!allowPunctuationPrefix && allowedPunctuation.contains(user.at(0))) { return false; + } for (const QString &word : disallowedWords) { - if (user.contains(word, Qt::CaseInsensitive)) + if (user.contains(word, Qt::CaseInsensitive)) { return false; + } } for (const QRegularExpression ®Exp : settingsCache->disallowedRegExp) { - if (regExp.match(user).hasMatch()) + if (regExp.match(user).hasMatch()) { return false; + } } QString regEx("\\A["); - if (allowLowercase) + if (allowLowercase) { regEx.append("a-z"); - if (allowUppercase) + } + if (allowUppercase) { regEx.append("A-Z"); - if (allowNumerics) + } + if (allowNumerics) { regEx.append("0-9"); + } regEx.append(QRegularExpression::escape(allowedPunctuation)); regEx.append("]+\\z"); @@ -222,8 +232,9 @@ bool Servatrice_DatabaseInterface::registerUser(const QString &userName, const QString &country, bool active) { - if (!checkSql()) + if (!checkSql()) { return false; + } QString passwordSha512; if (passwordNeedsHash) { @@ -259,8 +270,9 @@ bool Servatrice_DatabaseInterface::registerUser(const QString &userName, bool Servatrice_DatabaseInterface::activateUser(const QString &userName, const QString &token) { - if (!checkSql()) + if (!checkSql()) { return false; + } QSqlQuery *activateQuery = prepareQuery("select name from {prefix}_users where active=0 and name=:username and token=:token"); @@ -306,20 +318,24 @@ AuthenticationResult Servatrice_DatabaseInterface::checkUserPassword(Server_Prot return UnknownUser; case Servatrice::AuthenticationPassword: { QString configPassword = settingsCache->value("authentication/password").toString(); - if (configPassword == password) + if (configPassword == password) { return PasswordRight; + } return NotLoggedIn; } case Servatrice::AuthenticationSql: { - if (!checkSql()) + if (!checkSql()) { return UnknownUser; + } - if (!usernameIsValid(user, reasonStr)) + if (!usernameIsValid(user, reasonStr)) { return UsernameInvalid; + } - if (checkUserIsBanned(handler->getAddress(), user, clientId, reasonStr, banSecondsLeft)) + if (checkUserIsBanned(handler->getAddress(), user, clientId, reasonStr, banSecondsLeft)) { return UserIsBanned; + } QSqlQuery *passwordQuery = prepareQuery("select password_sha512, active from {prefix}_users where name = :name"); @@ -364,8 +380,9 @@ bool Servatrice_DatabaseInterface::checkUserIsBanned(const QString &ipAddress, QString &banReason, int &banSecondsRemaining) { - if (server->getAuthenticationMethod() != Servatrice::AuthenticationSql) + if (server->getAuthenticationMethod() != Servatrice::AuthenticationSql) { return false; + } if (!checkSql()) { qCWarning(DatabaseInterfaceLog) << "Failed to check if user is banned. Database invalid."; @@ -381,8 +398,9 @@ bool Servatrice_DatabaseInterface::checkUserIsIdBanned(const QString &clientId, QString &banReason, int &banSecondsRemaining) { - if (clientId.isEmpty()) + if (clientId.isEmpty()) { return false; + } QSqlQuery *idBanQuery = prepareQuery("select" @@ -487,8 +505,9 @@ bool Servatrice_DatabaseInterface::activeUserExists(const QString &user) QSqlQuery *query = prepareQuery("select 1 from {prefix}_users where name = :name and active = 1"); query->bindValue(":name", user); - if (!execSqlQuery(query)) + if (!execSqlQuery(query)) { return false; + } return query->next(); } return false; @@ -501,8 +520,9 @@ bool Servatrice_DatabaseInterface::userExists(const QString &user) QSqlQuery *query = prepareQuery("select 1 from {prefix}_users where name = :name"); query->bindValue(":name", user); - if (!execSqlQuery(query)) + if (!execSqlQuery(query)) { return false; + } return query->next(); } return false; @@ -535,10 +555,12 @@ int Servatrice_DatabaseInterface::getUserIdInDB(const QString &name) if (server->getAuthenticationMethod() == Servatrice::AuthenticationSql) { QSqlQuery *query = prepareQuery("select id from {prefix}_users where name = :name and active = 1"); query->bindValue(":name", name); - if (!execSqlQuery(query)) + if (!execSqlQuery(query)) { return -1; - if (!query->next()) + } + if (!query->next()) { return -1; + } return query->value(0).toInt(); } return -1; @@ -546,11 +568,13 @@ int Servatrice_DatabaseInterface::getUserIdInDB(const QString &name) bool Servatrice_DatabaseInterface::isInBuddyList(const QString &whoseList, const QString &who) { - if (server->getAuthenticationMethod() == Servatrice::AuthenticationNone) + if (server->getAuthenticationMethod() == Servatrice::AuthenticationNone) { return false; + } - if (!checkSql()) + if (!checkSql()) { return false; + } int id1 = getUserIdInDB(whoseList); int id2 = getUserIdInDB(who); @@ -559,18 +583,21 @@ bool Servatrice_DatabaseInterface::isInBuddyList(const QString &whoseList, const prepareQuery("select 1 from {prefix}_buddylist where id_user1 = :id_user1 and id_user2 = :id_user2"); query->bindValue(":id_user1", id1); query->bindValue(":id_user2", id2); - if (!execSqlQuery(query)) + if (!execSqlQuery(query)) { return false; + } return query->next(); } bool Servatrice_DatabaseInterface::isInIgnoreList(const QString &whoseList, const QString &who) { - if (server->getAuthenticationMethod() == Servatrice::AuthenticationNone) + if (server->getAuthenticationMethod() == Servatrice::AuthenticationNone) { return false; + } - if (!checkSql()) + if (!checkSql()) { return false; + } int id1 = getUserIdInDB(whoseList); int id2 = getUserIdInDB(who); @@ -579,8 +606,9 @@ bool Servatrice_DatabaseInterface::isInIgnoreList(const QString &whoseList, cons prepareQuery("select 1 from {prefix}_ignorelist where id_user1 = :id_user1 and id_user2 = :id_user2"); query->bindValue(":id_user1", id1); query->bindValue(":id_user2", id2); - if (!execSqlQuery(query)) + if (!execSqlQuery(query)) { return false; + } return query->next(); } @@ -588,29 +616,34 @@ ServerInfo_User Servatrice_DatabaseInterface::evalUserQueryResult(const QSqlQuer { ServerInfo_User result; - if (withId) + if (withId) { result.set_id(query->value(0).toInt()); + } result.set_name(query->value(1).toString().toStdString()); const int is_admin = query->value(2).toInt(); int userLevel = ServerInfo_User::IsUser | ServerInfo_User::IsRegistered; - if (is_admin & 1) + if (is_admin & 1) { userLevel |= ServerInfo_User::IsAdmin | ServerInfo_User::IsModerator; - else if (is_admin & 2) + } else if (is_admin & 2) { userLevel |= ServerInfo_User::IsModerator; + } - if (is_admin & 4) + if (is_admin & 4) { userLevel |= ServerInfo_User::IsJudge; + } result.set_user_level(userLevel); const QString country = query->value(3).toString(); - if (!country.isEmpty()) + if (!country.isEmpty()) { result.set_country(country.toStdString()); + } const QString privlevel = query->value(4).toString(); - if (!privlevel.isEmpty()) + if (!privlevel.isEmpty()) { result.set_privlevel(privlevel.toStdString()); + } const auto &pawn_left_override = query->value(5).toString(); const auto &pawn_right_override = query->value(6).toString(); @@ -623,12 +656,14 @@ ServerInfo_User Servatrice_DatabaseInterface::evalUserQueryResult(const QSqlQuer if (complete) { const QString realName = query->value(7).toString(); - if (!realName.isEmpty()) + if (!realName.isEmpty()) { result.set_real_name(realName.toStdString()); + } const QByteArray avatarBmp = query->value(8).toByteArray(); - if (avatarBmp.size()) + if (avatarBmp.size()) { result.set_avatar_bmp(avatarBmp.data(), avatarBmp.size()); + } const QDateTime regDate = query->value(9).toDateTime(); if (!regDate.toString(Qt::ISODate).isEmpty()) { @@ -638,12 +673,14 @@ ServerInfo_User Servatrice_DatabaseInterface::evalUserQueryResult(const QSqlQuer } const QString email = query->value(10).toString(); - if (!email.isEmpty()) + if (!email.isEmpty()) { result.set_email(email.toStdString()); + } const QString clientid = query->value(11).toString(); - if (!clientid.isEmpty()) + if (!clientid.isEmpty()) { result.set_clientid(clientid.toStdString()); + } } return result; } @@ -655,23 +692,27 @@ ServerInfo_User Servatrice_DatabaseInterface::getUserData(const QString &name, b result.set_user_level(ServerInfo_User::IsUser); if (server->getAuthenticationMethod() == Servatrice::AuthenticationSql) { - if (!checkSql()) + if (!checkSql()) { return result; + } QSqlQuery *query = prepareQuery("select id, name, admin, country, privlevel, leftPawnColorOverride, " "rightPawnColorOverride, realname, avatar_bmp, registrationDate, " "email, clientid from {prefix}_users where " "name = :name and active = 1"); query->bindValue(":name", name); - if (!execSqlQuery(query)) + if (!execSqlQuery(query)) { return result; + } - if (query->next()) + if (query->next()) { return evalUserQueryResult(query, true, withId); - else + } else { return result; - } else + } + } else { return result; + } } void Servatrice_DatabaseInterface::clearSessionTables() @@ -715,11 +756,13 @@ qint64 Servatrice_DatabaseInterface::startSession(const QString &userName, const QString &clientId, const QString &connectionType) { - if (server->getAuthenticationMethod() == Servatrice::AuthenticationNone) + if (server->getAuthenticationMethod() == Servatrice::AuthenticationNone) { return -1; + } - if (!checkSql()) + if (!checkSql()) { return -1; + } QSqlQuery *query = prepareQuery("insert into {prefix}_sessions (user_name, id_server, ip_address, start_time, " "clientid, connection_type) values(:user_name, :id_server, :ip_address, NOW(), " @@ -729,18 +772,21 @@ qint64 Servatrice_DatabaseInterface::startSession(const QString &userName, query->bindValue(":ip_address", address); query->bindValue(":client_id", clientId); query->bindValue(":connection_type", connectionType); - if (execSqlQuery(query)) + if (execSqlQuery(query)) { return query->lastInsertId().toInt(); + } return -1; } void Servatrice_DatabaseInterface::endSession(qint64 sessionId) { - if (server->getAuthenticationMethod() == Servatrice::AuthenticationNone) + if (server->getAuthenticationMethod() == Servatrice::AuthenticationNone) { return; + } - if (!checkSql()) + if (!checkSql()) { return; + } auto *query = prepareQuery("update {prefix}_sessions set end_time=NOW() where id = :id_session"); query->bindValue(":id_session", sessionId); @@ -759,8 +805,9 @@ QMap Servatrice_DatabaseInterface::getBuddyList(const "left join {prefix}_buddylist b on a.id = b.id_user2 left join {prefix}_users " "c on b.id_user1 = c.id where c.name = :name"); query->bindValue(":name", name); - if (!execSqlQuery(query)) + if (!execSqlQuery(query)) { return result; + } while (query->next()) { const ServerInfo_User &temp = evalUserQueryResult(query, false); @@ -782,8 +829,9 @@ QMap Servatrice_DatabaseInterface::getIgnoreList(const "left join {prefix}_ignorelist b on a.id = b.id_user2 left join {prefix}_users " "c on b.id_user1 = c.id where c.name = :name"); query->bindValue(":name", name); - if (!execSqlQuery(query)) + if (!execSqlQuery(query)) { return result; + } while (query->next()) { ServerInfo_User temp = evalUserQueryResult(query, false); @@ -795,11 +843,13 @@ QMap Servatrice_DatabaseInterface::getIgnoreList(const int Servatrice_DatabaseInterface::getNextGameId() { - if (!sqlDatabase.isValid()) + if (!sqlDatabase.isValid()) { return server->getNextLocalGameId(); + } - if (!checkSql()) + if (!checkSql()) { return -1; + } QSqlQuery *query = prepareQuery("insert into {prefix}_games (time_started) values (now())"); @@ -812,8 +862,9 @@ int Servatrice_DatabaseInterface::getNextGameId() int Servatrice_DatabaseInterface::getNextReplayId() { - if (!checkSql()) + if (!checkSql()) { return -1; + } QSqlQuery *query = prepareQuery("insert into {prefix}_replays (id_game) values (NULL)"); @@ -831,11 +882,13 @@ void Servatrice_DatabaseInterface::storeGameInformation(const QString &roomName, const QSet &allSpectatorsEver, const QList &replayList) { - if (!checkSql()) + if (!checkSql()) { return; + } - if (!settingsCache->value("game/store_replays", 1).toBool()) + if (!settingsCache->value("game/store_replays", 1).toBool()) { return; + } QVariantList gameIds1, playerNames, gameIds2, userIds, replayNames; QSetIterator playerIterator(allPlayersEver); @@ -848,8 +901,9 @@ void Servatrice_DatabaseInterface::storeGameInformation(const QString &roomName, QSetIterator allUsersIterator(allUsersInGame); while (allUsersIterator.hasNext()) { int id = getUserIdInDB(allUsersIterator.next()); - if (id == -1) + if (id == -1) { continue; + } gameIds2.append(gameInfo.game_id()); userIds.append(id); replayNames.append(QString::fromStdString(gameInfo.description())); @@ -888,8 +942,9 @@ void Servatrice_DatabaseInterface::storeGameInformation(const QString &roomName, query->bindValue(":password", gameInfo.with_password() ? 1 : 0); query->bindValue(":game_types", roomGameTypes.isEmpty() ? QString("") : roomGameTypes.join(", ")); query->bindValue(":player_count", gameInfo.max_players()); - if (!execSqlQuery(query)) + if (!execSqlQuery(query)) { return; + } } { QSqlQuery *query = @@ -926,8 +981,9 @@ DeckList *Servatrice_DatabaseInterface::getDeckFromDatabase(int deckId, int user query->bindValue(":id", deckId); query->bindValue(":id_user", userId); execSqlQuery(query); - if (!query->next()) + if (!query->next()) { throw Response::RespNameNotFound; + } DeckList *deck = new DeckList; deck->loadFromString_Native(query->value(0).toString()); @@ -946,23 +1002,27 @@ void Servatrice_DatabaseInterface::logMessage(const int senderId, QString targetTypeString; switch (targetType) { case MessageTargetRoom: - if (!settingsCache->value("logging/log_user_msg_room", 0).toBool()) + if (!settingsCache->value("logging/log_user_msg_room", 0).toBool()) { return; + } targetTypeString = "room"; break; case MessageTargetGame: - if (!settingsCache->value("logging/log_user_msg_game", 0).toBool()) + if (!settingsCache->value("logging/log_user_msg_game", 0).toBool()) { return; + } targetTypeString = "game"; break; case MessageTargetChat: - if (!settingsCache->value("logging/log_user_msg_chat", 0).toBool()) + if (!settingsCache->value("logging/log_user_msg_chat", 0).toBool()) { return; + } targetTypeString = "chat"; break; case MessageTargetIslRoom: - if (!settingsCache->value("logging/log_user_msg_isl", 0).toBool()) + if (!settingsCache->value("logging/log_user_msg_isl", 0).toBool()) { return; + } targetTypeString = "room"; break; default: @@ -995,8 +1055,9 @@ bool Servatrice_DatabaseInterface::changeUserPassword(const QString &user, "passwordLastChangedDate = NOW() where name = :name"); passwordQuery->bindValue(":password", passwordSha512); passwordQuery->bindValue(":name", user); - if (execSqlQuery(passwordQuery)) + if (execSqlQuery(passwordQuery)) { return true; + } return false; } @@ -1007,15 +1068,18 @@ bool Servatrice_DatabaseInterface::changeUserPassword(const QString &user, const QString &newPassword, bool newPasswordNeedsHash) { - if (server->getAuthenticationMethod() != Servatrice::AuthenticationSql) + if (server->getAuthenticationMethod() != Servatrice::AuthenticationSql) { return false; + } - if (!checkSql()) + if (!checkSql()) { return false; + } QString error; - if (!usernameIsValid(user, error)) + if (!usernameIsValid(user, error)) { return false; + } QSqlQuery *passwordQuery = prepareQuery("select password_sha512 from {prefix}_users where name = :name"); passwordQuery->bindValue(":name", user); @@ -1025,8 +1089,9 @@ bool Servatrice_DatabaseInterface::changeUserPassword(const QString &user, return false; } - if (!passwordQuery->next()) + if (!passwordQuery->next()) { return false; + } const QString correctPasswordSha512 = passwordQuery->value(0).toString(); QString oldPasswordSha512 = oldPassword; @@ -1034,8 +1099,9 @@ bool Servatrice_DatabaseInterface::changeUserPassword(const QString &user, QString salt = correctPasswordSha512.left(16); oldPasswordSha512 = PasswordHasher::computeHash(oldPassword, salt); } - if (correctPasswordSha512 != oldPasswordSha512) + if (correctPasswordSha512 != oldPasswordSha512) { return false; + } return changeUserPassword(user, newPassword, newPasswordNeedsHash); } @@ -1044,23 +1110,28 @@ int Servatrice_DatabaseInterface::getActiveUserCount(QString connectionType) { int userCount = 0; - if (!checkSql()) + if (!checkSql()) { return userCount; + } QString text = "select count(*) from {prefix}_sessions where id_server = :serverid AND end_time is NULL"; - if (!connectionType.isEmpty()) + if (!connectionType.isEmpty()) { text += " AND connection_type = :connection_type"; + } QSqlQuery *query = prepareQuery(text); query->bindValue(":serverid", server->getServerID()); - if (!connectionType.isEmpty()) + if (!connectionType.isEmpty()) { query->bindValue(":connection_type", connectionType); + } - if (!execSqlQuery(query)) + if (!execSqlQuery(query)) { return userCount; + } - if (query->next()) + if (query->next()) { userCount = query->value(0).toInt(); + } return userCount; } @@ -1068,8 +1139,9 @@ int Servatrice_DatabaseInterface::getActiveUserCount(QString connectionType) void Servatrice_DatabaseInterface::updateUsersClientID(const QString &userName, const QString &userClientID) { - if (!checkSql()) + if (!checkSql()) { return; + } QSqlQuery *query = prepareQuery("update {prefix}_users set clientid = :clientid where name = :username"); query->bindValue(":clientid", userClientID); @@ -1080,8 +1152,9 @@ void Servatrice_DatabaseInterface::updateUsersClientID(const QString &userName, void Servatrice_DatabaseInterface::updateUsersLastLoginData(const QString &userName, const QString &clientVersion) { - if (!checkSql()) + if (!checkSql()) { return; + } int usersID = 0; @@ -1100,8 +1173,9 @@ void Servatrice_DatabaseInterface::updateUsersLastLoginData(const QString &userN int userCount = 0; query = prepareQuery("select count(id) from {prefix}_user_analytics where id = :user_id"); query->bindValue(":user_id", usersID); - if (!execSqlQuery(query)) + if (!execSqlQuery(query)) { return; + } if (query->next()) { userCount = query->value(0).toInt(); @@ -1128,8 +1202,9 @@ QList Servatrice_DatabaseInterface::getUserBanHistory(const QStr QList results; ServerInfo_Ban banDetails; - if (!checkSql()) + if (!checkSql()) { return results; + } QSqlQuery *query = prepareQuery("SELECT A.id_admin, A.time_from, A.minutes, A.reason, A.visible_reason, B.name AS name_admin FROM " @@ -1159,8 +1234,9 @@ bool Servatrice_DatabaseInterface::addWarning(const QString userName, const QString warningReason, const QString clientID) { - if (!checkSql()) + if (!checkSql()) { return false; + } int userID = getUserIdInDB(userName); QSqlQuery *query = @@ -1184,8 +1260,9 @@ QList Servatrice_DatabaseInterface::getUserWarnHistory(const QList results; ServerInfo_Warning warnDetails; - if (!checkSql()) + if (!checkSql()) { return results; + } int userID = getUserIdInDB(userName); QSqlQuery *query = @@ -1223,8 +1300,9 @@ QList Servatrice_DatabaseInterface::getMessageLogHistory QList results; ServerInfo_ChatMessage chatMessage; - if (!checkSql()) + if (!checkSql()) { return results; + } if (user.isEmpty() && ipaddress.isEmpty() && gameid.isEmpty() && gamename.isEmpty()) { // To ensure quick results and minimal lag, require an indexed field @@ -1233,48 +1311,58 @@ QList Servatrice_DatabaseInterface::getMessageLogHistory // BUILD QUERY STRING BASED ON PASSED IN VALUES QString queryString = "SELECT * FROM {prefix}_log WHERE `sender_ip` IS NOT NULL"; - if (!user.isEmpty()) + if (!user.isEmpty()) { queryString.append(" AND (`sender_name` = :user_name OR `target_name` = :user_name)"); + } - if (!ipaddress.isEmpty()) + if (!ipaddress.isEmpty()) { queryString.append(" AND `sender_ip` = :ip_to_find"); + } - if (!gameid.isEmpty()) + if (!gameid.isEmpty()) { queryString.append(" AND (`target_id` = :game_id AND `target_type` = 'game')"); + } - if (!gamename.isEmpty()) + if (!gamename.isEmpty()) { queryString.append(" AND (`target_name` = :game_name AND `target_type` = 'game')"); + } - if (!message.isEmpty()) + if (!message.isEmpty()) { queryString.append(" AND `log_message` LIKE :log_message"); + } if (chat || game || room) { queryString.append(" AND ("); - if (chat) + if (chat) { queryString.append("`target_type` = 'chat'"); + } if (game) { - if (chat) + if (chat) { queryString.append(" OR `target_type` = 'game'"); - else + } else { queryString.append("`target_type` = 'game'"); + } } if (room) { - if (game || chat) + if (game || chat) { queryString.append(" OR `target_type` = 'room'"); - else + } else { queryString.append("`target_type` = 'room'"); + } } queryString.append(")"); } - if (range) + if (range) { queryString.append(" AND log_time >= DATE_SUB(now(), INTERVAL :range_time HOUR)"); + } - if (maxresults) + if (maxresults) { queryString.append(" LIMIT :limit_size"); + } QSqlQuery *query = prepareQuery(queryString); if (!user.isEmpty()) { @@ -1321,8 +1409,9 @@ QList Servatrice_DatabaseInterface::getMessageLogHistory int Servatrice_DatabaseInterface::checkNumberOfUserAccounts(const QString &email) { - if (!checkSql()) + if (!checkSql()) { return 0; + } QSqlQuery *query = prepareQuery("SELECT count(email) FROM {prefix}_users WHERE email = :user_email"); query->bindValue(":user_email", email); @@ -1333,75 +1422,88 @@ int Servatrice_DatabaseInterface::checkNumberOfUserAccounts(const QString &email return 0; } - if (query->next()) + if (query->next()) { return query->value(0).toInt(); + } return 0; } bool Servatrice_DatabaseInterface::addForgotPassword(const QString &user) { - if (!checkSql()) + if (!checkSql()) { return false; + } - if (!updateUserToken(PasswordHasher::generateActivationToken(), user)) + if (!updateUserToken(PasswordHasher::generateActivationToken(), user)) { return false; + } QSqlQuery *query = prepareQuery("insert into {prefix}_forgot_password (name,requestDate) values (:username,NOW())"); query->bindValue(":username", user); - if (execSqlQuery(query)) + if (execSqlQuery(query)) { return true; + } return false; } bool Servatrice_DatabaseInterface::removeForgotPassword(const QString &user) { - if (!checkSql()) + if (!checkSql()) { return false; + } QSqlQuery *query = prepareQuery("delete from {prefix}_forgot_password where name = :username"); query->bindValue(":username", user); - if (execSqlQuery(query)) + if (execSqlQuery(query)) { return true; + } return false; } bool Servatrice_DatabaseInterface::doesForgotPasswordExist(const QString &user) { - if (!checkSql()) + if (!checkSql()) { return false; + } QSqlQuery *query = prepareQuery("select count(name) from {prefix}_forgot_password where name = :user_name AND " "requestDate > (now() - interval :minutes minute)"); query->bindValue(":user_name", user); query->bindValue(":minutes", QString::number(server->getForgotPasswordTokenLife())); - if (!execSqlQuery(query)) + if (!execSqlQuery(query)) { return false; + } - if (query->next()) - if (query->value("count(name)").toInt() > 0) + if (query->next()) { + if (query->value("count(name)").toInt() > 0) { return true; + } + } return false; } bool Servatrice_DatabaseInterface::updateUserToken(const QString &token, const QString &user) { - if (!checkSql()) + if (!checkSql()) { return false; + } - if (token.isEmpty() || user.isEmpty()) + if (token.isEmpty() || user.isEmpty()) { return false; + } QSqlQuery *query = prepareQuery("update {prefix}_users set token = :token where name = :user_name"); query->bindValue(":user_name", user); query->bindValue(":token", token); - if (execSqlQuery(query)) + if (execSqlQuery(query)) { return true; + } return false; } @@ -1411,22 +1513,27 @@ bool Servatrice_DatabaseInterface::validateTableColumnStringData(const QString & const QString &_user, const QString &_datatocheck) { - if (!checkSql()) + if (!checkSql()) { return false; + } - if (table.isEmpty() || column.isEmpty() || _user.isEmpty() || _datatocheck.isEmpty()) + if (table.isEmpty() || column.isEmpty() || _user.isEmpty() || _datatocheck.isEmpty()) { return false; + } QString formatedQuery = QString("select %1 from %2 where name = :user_name").arg(column).arg(table); QSqlQuery *query = prepareQuery(formatedQuery); query->bindValue(":user_name", _user); - if (!execSqlQuery(query)) + if (!execSqlQuery(query)) { return false; + } - if (query->next()) - if (query->value(column).toString().toLower() == _datatocheck.toLower()) + if (query->next()) { + if (query->value(column).toString().toLower() == _datatocheck.toLower()) { return true; + } + } return false; } @@ -1438,14 +1545,17 @@ void Servatrice_DatabaseInterface::addAuditRecord(const QString &user, const QString &details, const bool &results = false) { - if (!checkSql()) + if (!checkSql()) { return; + } - if (!server->getEnableAudit()) + if (!server->getEnableAudit()) { return; + } - if (user.isEmpty() || ipaddress.isEmpty() || clientid.isEmpty() || action.isEmpty()) + if (user.isEmpty() || ipaddress.isEmpty() || clientid.isEmpty() || action.isEmpty()) { return; + } QSqlQuery *query = prepareQuery("insert into {prefix}_audit " "(id_server,name,ip_address,clientid,incidentDate,action,results,details) values " diff --git a/servatrice/src/server_logger.cpp b/servatrice/src/server_logger.cpp index de0befacb..620780052 100644 --- a/servatrice/src/server_logger.cpp +++ b/servatrice/src/server_logger.cpp @@ -39,20 +39,23 @@ void ServerLogger::startLog(const QString &logFileName) logFile = 0; return; } - } else + } else { logFile = 0; + } connect(this, SIGNAL(sigFlushBuffer()), this, SLOT(flushBuffer()), Qt::QueuedConnection); } void ServerLogger::logMessage(const QString &message, void *caller) { - if (!logFile) + if (!logFile) { return; + } QString callerString; - if (caller) + if (caller) { callerString = QString::number((qulonglong)caller, 16) + " "; + } // filter out all log entries based on values in configuration file bool shouldWeWriteLog = settingsCache->value("server/writelog", 1).toBool(); @@ -60,8 +63,9 @@ void ServerLogger::logMessage(const QString &message, void *caller) QStringList listlogFilters = logFilters.split(",", Qt::SkipEmptyParts); bool shouldWeSkipLine = false; - if (!shouldWeWriteLog) + if (!shouldWeWriteLog) { return; + } if (!logFilters.trimmed().isEmpty()) { shouldWeSkipLine = true; @@ -73,8 +77,9 @@ void ServerLogger::logMessage(const QString &message, void *caller) } } - if (shouldWeSkipLine) + if (shouldWeSkipLine) { return; + } bufferMutex.lock(); buffer.append(QDateTime::currentDateTime().toString() + " " + callerString + message); @@ -84,8 +89,9 @@ void ServerLogger::logMessage(const QString &message, void *caller) void ServerLogger::flushBuffer() { - if (flushRunning) + if (flushRunning) { return; + } flushRunning = true; QTextStream stream(logFile); @@ -103,15 +109,17 @@ void ServerLogger::flushBuffer() stream << message << "\n"; stream.flush(); - if (logToConsole) + if (logToConsole) { std::cout << message.toStdString() << std::endl; + } } } void ServerLogger::rotateLogs() { - if (!logFile) + if (!logFile) { return; + } flushBuffer(); diff --git a/servatrice/src/serversocketinterface.cpp b/servatrice/src/serversocketinterface.cpp index 41e61ddec..5549074c5 100644 --- a/servatrice/src/serversocketinterface.cpp +++ b/servatrice/src/serversocketinterface.cpp @@ -117,8 +117,9 @@ bool AbstractServerSocketInterface::initSession() // allow unlimited number of connections from the trusted sources QString trustedSources = settingsCache->value("security/trusted_sources", "127.0.0.1,::1").toString(); - if (trustedSources.contains(getAddress(), Qt::CaseInsensitive)) + if (trustedSources.contains(getAddress(), Qt::CaseInsensitive)) { return true; + } int maxUsers = servatrice->getMaxUsersPerAddress(); if ((maxUsers > 0) && (servatrice->getUsersWithAddress(getPeerAddress()) > maxUsers)) { @@ -270,35 +271,44 @@ AbstractServerSocketInterface::processExtendedAdminCommand(int cmdType, const Ad Response::ResponseCode AbstractServerSocketInterface::cmdAddToList(const Command_AddToList &cmd, ResponseContainer &rc) { - if (authState != PasswordRight) + if (authState != PasswordRight) { return Response::RespFunctionNotAllowed; + } QString list = nameFromStdString(cmd.list()); QString user = nameFromStdString(cmd.user_name()); - if ((list != "buddy") && (list != "ignore")) + if ((list != "buddy") && (list != "ignore")) { return Response::RespContextError; + } - if (list == "buddy") - if (databaseInterface->isInBuddyList(QString::fromStdString(userInfo->name()), user)) + if (list == "buddy") { + if (databaseInterface->isInBuddyList(QString::fromStdString(userInfo->name()), user)) { return Response::RespContextError; - if (list == "ignore") - if (databaseInterface->isInIgnoreList(QString::fromStdString(userInfo->name()), user)) + } + } + if (list == "ignore") { + if (databaseInterface->isInIgnoreList(QString::fromStdString(userInfo->name()), user)) { return Response::RespContextError; + } + } int id1 = userInfo->id(); int id2 = sqlInterface->getUserIdInDB(user); - if (id2 < 0) + if (id2 < 0) { return Response::RespNameNotFound; - if (id1 == id2) + } + if (id1 == id2) { return Response::RespContextError; + } QSqlQuery *query = sqlInterface->prepareQuery("insert into {prefix}_" + list + "list (id_user1, id_user2) values(:id1, :id2)"); query->bindValue(":id1", id1); query->bindValue(":id2", id2); - if (!sqlInterface->execSqlQuery(query)) + if (!sqlInterface->execSqlQuery(query)) { return Response::RespInternalError; + } Event_AddToList event; event.set_list_name(cmd.list()); @@ -311,33 +321,41 @@ Response::ResponseCode AbstractServerSocketInterface::cmdAddToList(const Command Response::ResponseCode AbstractServerSocketInterface::cmdRemoveFromList(const Command_RemoveFromList &cmd, ResponseContainer &rc) { - if (authState != PasswordRight) + if (authState != PasswordRight) { return Response::RespFunctionNotAllowed; + } QString list = nameFromStdString(cmd.list()); QString user = nameFromStdString(cmd.user_name()); - if ((list != "buddy") && (list != "ignore")) + if ((list != "buddy") && (list != "ignore")) { return Response::RespContextError; + } - if (list == "buddy") - if (!databaseInterface->isInBuddyList(QString::fromStdString(userInfo->name()), user)) + if (list == "buddy") { + if (!databaseInterface->isInBuddyList(QString::fromStdString(userInfo->name()), user)) { return Response::RespContextError; - if (list == "ignore") - if (!databaseInterface->isInIgnoreList(QString::fromStdString(userInfo->name()), user)) + } + } + if (list == "ignore") { + if (!databaseInterface->isInIgnoreList(QString::fromStdString(userInfo->name()), user)) { return Response::RespContextError; + } + } int id1 = userInfo->id(); int id2 = sqlInterface->getUserIdInDB(user); - if (id2 < 0) + if (id2 < 0) { return Response::RespNameNotFound; + } QSqlQuery *query = sqlInterface->prepareQuery("delete from {prefix}_" + list + "list where id_user1 = :id1 and id_user2 = :id2"); query->bindValue(":id1", id1); query->bindValue(":id2", id2); - if (!sqlInterface->execSqlQuery(query)) + if (!sqlInterface->execSqlQuery(query)) { return Response::RespInternalError; + } Event_RemoveFromList event; event.set_list_name(cmd.list()); @@ -349,25 +367,30 @@ Response::ResponseCode AbstractServerSocketInterface::cmdRemoveFromList(const Co int AbstractServerSocketInterface::getDeckPathId(int basePathId, QStringList path) { - if (path.isEmpty()) + if (path.isEmpty()) { return 0; - if (path[0].isEmpty()) + } + if (path[0].isEmpty()) { return 0; + } QSqlQuery *query = sqlInterface->prepareQuery("select id from {prefix}_decklist_folders where id_parent = " ":id_parent and name = :name and id_user = :id_user"); query->bindValue(":id_parent", basePathId); query->bindValue(":name", path.takeFirst()); query->bindValue(":id_user", userInfo->id()); - if (!sqlInterface->execSqlQuery(query)) + if (!sqlInterface->execSqlQuery(query)) { return -1; - if (!query->next()) + } + if (!query->next()) { return -1; + } int id = query->value(0).toInt(); - if (path.isEmpty()) + if (path.isEmpty()) { return id; - else + } else { return getDeckPathId(id, path); + } } int AbstractServerSocketInterface::getDeckPathId(const QString &path) @@ -381,28 +404,32 @@ bool AbstractServerSocketInterface::deckListHelper(int folderId, ServerInfo_Deck "select id, name from {prefix}_decklist_folders where id_parent = :id_parent and id_user = :id_user"); query->bindValue(":id_parent", folderId); query->bindValue(":id_user", userInfo->id()); - if (!sqlInterface->execSqlQuery(query)) + if (!sqlInterface->execSqlQuery(query)) { return false; + } QMap results; - while (query->next()) + while (query->next()) { results[query->value(0).toInt()] = query->value(1).toString(); + } for (int key : results.keys()) { ServerInfo_DeckStorage_TreeItem *newItem = folder->add_items(); newItem->set_id(key); newItem->set_name(results.value(key).toStdString()); - if (!deckListHelper(newItem->id(), newItem->mutable_folder())) + if (!deckListHelper(newItem->id(), newItem->mutable_folder())) { return false; + } } query = sqlInterface->prepareQuery("select id, name, upload_time from {prefix}_decklist_files where id_folder = " ":id_folder and id_user = :id_user"); query->bindValue(":id_folder", folderId); query->bindValue(":id_user", userInfo->id()); - if (!sqlInterface->execSqlQuery(query)) + if (!sqlInterface->execSqlQuery(query)) { return false; + } while (query->next()) { ServerInfo_DeckStorage_TreeItem *newItem = folder->add_items(); @@ -422,16 +449,18 @@ bool AbstractServerSocketInterface::deckListHelper(int folderId, ServerInfo_Deck Response::ResponseCode AbstractServerSocketInterface::cmdDeckList(const Command_DeckList & /*cmd*/, ResponseContainer &rc) { - if (authState != PasswordRight) + if (authState != PasswordRight) { return Response::RespFunctionNotAllowed; + } sqlInterface->checkSql(); Response_DeckList *re = new Response_DeckList; ServerInfo_DeckStorage_Folder *root = re->mutable_root(); - if (!deckListHelper(0, root)) + if (!deckListHelper(0, root)) { return Response::RespContextError; + } rc.setResponseExtension(re); return Response::RespOk; @@ -440,27 +469,31 @@ Response::ResponseCode AbstractServerSocketInterface::cmdDeckList(const Command_ Response::ResponseCode AbstractServerSocketInterface::cmdDeckNewDir(const Command_DeckNewDir &cmd, ResponseContainer & /*rc*/) { - if (authState != PasswordRight) + if (authState != PasswordRight) { return Response::RespFunctionNotAllowed; + } sqlInterface->checkSql(); QString path = nameFromStdString(cmd.path()); int folderId = getDeckPathId(path); - if (folderId == -1) + if (folderId == -1) { return Response::RespNameNotFound; + } QString name = nameFromStdString(cmd.dir_name()); - if (path.length() + name.length() + 1 > MAX_NAME_LENGTH) + if (path.length() + name.length() + 1 > MAX_NAME_LENGTH) { return Response::RespContextError; // do not allow creation of paths that would be too long to delete + } QSqlQuery *query = sqlInterface->prepareQuery( "insert into {prefix}_decklist_folders (id_parent, id_user, name) values(:id_parent, :id_user, :name)"); query->bindValue(":id_parent", folderId); query->bindValue(":id_user", userInfo->id()); query->bindValue(":name", name); - if (!sqlInterface->execSqlQuery(query)) + if (!sqlInterface->execSqlQuery(query)) { return Response::RespContextError; + } return Response::RespOk; } @@ -471,8 +504,9 @@ void AbstractServerSocketInterface::deckDelDirHelper(int basePathId) sqlInterface->prepareQuery("select id from {prefix}_decklist_folders where id_parent = :id_parent"); query->bindValue(":id_parent", basePathId); sqlInterface->execSqlQuery(query); - while (query->next()) + while (query->next()) { deckDelDirHelper(query->value(0).toInt()); + } query = sqlInterface->prepareQuery("delete from {prefix}_decklist_files where id_folder = :id_folder"); query->bindValue(":id_folder", basePathId); @@ -487,8 +521,9 @@ void AbstractServerSocketInterface::sendServerMessage(const QString userName, co { AbstractServerSocketInterface *user = static_cast(server->getUsers().value(userName)); - if (!user) + if (!user) { return; + } Event_UserMessage event; event.set_sender_name("Servatrice"); @@ -502,22 +537,25 @@ void AbstractServerSocketInterface::sendServerMessage(const QString userName, co Response::ResponseCode AbstractServerSocketInterface::cmdDeckDelDir(const Command_DeckDelDir &cmd, ResponseContainer & /*rc*/) { - if (authState != PasswordRight) + if (authState != PasswordRight) { return Response::RespFunctionNotAllowed; + } sqlInterface->checkSql(); int basePathId = getDeckPathId(nameFromStdString(cmd.path())); - if ((basePathId == -1) || (basePathId == 0)) + if ((basePathId == -1) || (basePathId == 0)) { return Response::RespNameNotFound; + } deckDelDirHelper(basePathId); return Response::RespOk; } Response::ResponseCode AbstractServerSocketInterface::cmdDeckDel(const Command_DeckDel &cmd, ResponseContainer & /*rc*/) { - if (authState != PasswordRight) + if (authState != PasswordRight) { return Response::RespFunctionNotAllowed; + } sqlInterface->checkSql(); QSqlQuery *query = @@ -525,8 +563,9 @@ Response::ResponseCode AbstractServerSocketInterface::cmdDeckDel(const Command_D query->bindValue(":id", cmd.deck_id()); query->bindValue(":id_user", userInfo->id()); sqlInterface->execSqlQuery(query); - if (!query->next()) + if (!query->next()) { return Response::RespNameNotFound; + } query = sqlInterface->prepareQuery("delete from {prefix}_decklist_files where id = :id"); query->bindValue(":id", cmd.deck_id()); @@ -538,27 +577,32 @@ Response::ResponseCode AbstractServerSocketInterface::cmdDeckDel(const Command_D Response::ResponseCode AbstractServerSocketInterface::cmdDeckUpload(const Command_DeckUpload &cmd, ResponseContainer &rc) { - if (authState != PasswordRight) + if (authState != PasswordRight) { return Response::RespFunctionNotAllowed; + } - if (!cmd.has_deck_list()) + if (!cmd.has_deck_list()) { return Response::RespInvalidData; + } sqlInterface->checkSql(); QString deckStr = fileFromStdString(cmd.deck_list()); DeckList deck; - if (!deck.loadFromString_Native(deckStr)) + if (!deck.loadFromString_Native(deckStr)) { return Response::RespContextError; + } QString deckName = deck.getName(); - if (deckName.isEmpty()) + if (deckName.isEmpty()) { deckName = "Unnamed deck"; + } if (cmd.has_path()) { int folderId = getDeckPathId(nameFromStdString(cmd.path())); - if (folderId == -1) + if (folderId == -1) { return Response::RespNameNotFound; + } QSqlQuery *query = sqlInterface->prepareQuery("insert into {prefix}_decklist_files (id_folder, id_user, name, upload_time, " @@ -585,8 +629,9 @@ Response::ResponseCode AbstractServerSocketInterface::cmdDeckUpload(const Comman query->bindValue(":content", deckStr); sqlInterface->execSqlQuery(query); - if (query->numRowsAffected() == 0) + if (query->numRowsAffected() == 0) { return Response::RespNameNotFound; + } Response_DeckUpload *re = new Response_DeckUpload; ServerInfo_DeckStorage_TreeItem *fileInfo = re->mutable_new_file(); @@ -594,8 +639,9 @@ Response::ResponseCode AbstractServerSocketInterface::cmdDeckUpload(const Comman fileInfo->set_name(deckName.toStdString()); fileInfo->mutable_file()->set_creation_time(QDateTime::currentDateTime().toSecsSinceEpoch()); rc.setResponseExtension(re); - } else + } else { return Response::RespInvalidData; + } return Response::RespOk; } @@ -603,8 +649,9 @@ Response::ResponseCode AbstractServerSocketInterface::cmdDeckUpload(const Comman Response::ResponseCode AbstractServerSocketInterface::cmdDeckDownload(const Command_DeckDownload &cmd, ResponseContainer &rc) { - if (authState != PasswordRight) + if (authState != PasswordRight) { return Response::RespFunctionNotAllowed; + } DeckList *deck; try { @@ -624,8 +671,9 @@ Response::ResponseCode AbstractServerSocketInterface::cmdDeckDownload(const Comm Response::ResponseCode AbstractServerSocketInterface::cmdReplayList(const Command_ReplayList & /*cmd*/, ResponseContainer &rc) { - if (authState != PasswordRight) + if (authState != PasswordRight) { return Response::RespFunctionNotAllowed; + } Response_ReplayList *re = new Response_ReplayList; @@ -654,8 +702,9 @@ Response::ResponseCode AbstractServerSocketInterface::cmdReplayList(const Comman sqlInterface->prepareQuery("select player_name from {prefix}_games_players where id_game = :id_game"); query2->bindValue(":id_game", gameId); sqlInterface->execSqlQuery(query2); - while (query2->next()) + while (query2->next()) { matchInfo->add_player_names(query2->value(0).toString().toStdString()); + } } { QSqlQuery *query3 = @@ -678,8 +727,9 @@ Response::ResponseCode AbstractServerSocketInterface::cmdReplayList(const Comman Response::ResponseCode AbstractServerSocketInterface::cmdReplayDownload(const Command_ReplayDownload &cmd, ResponseContainer &rc) { - if (authState != PasswordRight) + if (authState != PasswordRight) { return Response::RespFunctionNotAllowed; + } { QSqlQuery *query = @@ -687,18 +737,22 @@ Response::ResponseCode AbstractServerSocketInterface::cmdReplayDownload(const Co "a.id_game = b.id_game where b.id = :id_replay and a.id_player = :id_player"); query->bindValue(":id_replay", cmd.replay_id()); query->bindValue(":id_player", userInfo->id()); - if (!sqlInterface->execSqlQuery(query)) + if (!sqlInterface->execSqlQuery(query)) { return Response::RespInternalError; - if (!query->next()) + } + if (!query->next()) { return Response::RespAccessDenied; + } } QSqlQuery *query = sqlInterface->prepareQuery("select replay from {prefix}_replays where id = :id_replay"); query->bindValue(":id_replay", cmd.replay_id()); - if (!sqlInterface->execSqlQuery(query)) + if (!sqlInterface->execSqlQuery(query)) { return Response::RespInternalError; - if (!query->next()) + } + if (!query->next()) { return Response::RespNameNotFound; + } QByteArray data = query->value(0).toByteArray(); @@ -712,11 +766,13 @@ Response::ResponseCode AbstractServerSocketInterface::cmdReplayDownload(const Co Response::ResponseCode AbstractServerSocketInterface::cmdReplayModifyMatch(const Command_ReplayModifyMatch &cmd, ResponseContainer & /*rc*/) { - if (authState != PasswordRight) + if (authState != PasswordRight) { return Response::RespFunctionNotAllowed; + } - if (!sqlInterface->checkSql()) + if (!sqlInterface->checkSql()) { return Response::RespInternalError; + } QSqlQuery *query = sqlInterface->prepareQuery("update {prefix}_replays_access set do_not_hide=:do_not_hide where " "id_player = :id_player and id_game = :id_game"); @@ -724,27 +780,31 @@ Response::ResponseCode AbstractServerSocketInterface::cmdReplayModifyMatch(const query->bindValue(":id_game", cmd.game_id()); query->bindValue(":do_not_hide", cmd.do_not_hide()); - if (!sqlInterface->execSqlQuery(query)) + if (!sqlInterface->execSqlQuery(query)) { return Response::RespInternalError; + } return query->numRowsAffected() > 0 ? Response::RespOk : Response::RespNameNotFound; } Response::ResponseCode AbstractServerSocketInterface::cmdReplayDeleteMatch(const Command_ReplayDeleteMatch &cmd, ResponseContainer & /*rc*/) { - if (authState != PasswordRight) + if (authState != PasswordRight) { return Response::RespFunctionNotAllowed; + } - if (!sqlInterface->checkSql()) + if (!sqlInterface->checkSql()) { return Response::RespInternalError; + } QSqlQuery *query = sqlInterface->prepareQuery( "delete from {prefix}_replays_access where id_player = :id_player and id_game = :id_game"); query->bindValue(":id_player", userInfo->id()); query->bindValue(":id_game", cmd.game_id()); - if (!sqlInterface->execSqlQuery(query)) + if (!sqlInterface->execSqlQuery(query)) { return Response::RespInternalError; + } return query->numRowsAffected() > 0 ? Response::RespOk : Response::RespNameNotFound; } @@ -764,8 +824,9 @@ QString AbstractServerSocketInterface::createHashForReplay(int gameId) sqlInterface->prepareQuery("select replay from {prefix}_replays where id_game = :id_game limit 3"); query->bindValue(":id_game", gameId); - if (!sqlInterface->execSqlQuery(query)) + if (!sqlInterface->execSqlQuery(query)) { return ""; + } QByteArray replaysBytes; while (query->next()) { @@ -783,8 +844,9 @@ QString AbstractServerSocketInterface::createHashForReplay(int gameId) Response::ResponseCode AbstractServerSocketInterface::cmdReplayGetCode(const Command_ReplayGetCode &cmd, ResponseContainer &rc) { - if (authState != PasswordRight) + if (authState != PasswordRight) { return Response::RespFunctionNotAllowed; + } // Check that user has access to replay match { @@ -792,10 +854,12 @@ Response::ResponseCode AbstractServerSocketInterface::cmdReplayGetCode(const Com "select 1 from {prefix}_replays_access where id_game = :id_game and id_player = :id_player"); query->bindValue(":id_game", cmd.game_id()); query->bindValue(":id_player", userInfo->id()); - if (!sqlInterface->execSqlQuery(query)) + if (!sqlInterface->execSqlQuery(query)) { return Response::RespInternalError; - if (!query->next()) + } + if (!query->next()) { return Response::RespAccessDenied; + } } QString hash = createHashForReplay(cmd.game_id()); @@ -894,12 +958,15 @@ Response::ResponseCode AbstractServerSocketInterface::cmdGetLogHistory(const Com bool roomType = false; for (int i = 0; i != cmd.log_location_size(); ++i) { - if (nameFromStdString(cmd.log_location(i)).simplified() == "room") + if (nameFromStdString(cmd.log_location(i)).simplified() == "room") { roomType = true; - if (nameFromStdString(cmd.log_location(i)).simplified() == "game") + } + if (nameFromStdString(cmd.log_location(i)).simplified() == "game") { gameType = true; - if (nameFromStdString(cmd.log_location(i)).simplified() == "chat") + } + if (nameFromStdString(cmd.log_location(i)).simplified() == "chat") { chatType = true; + } } int dateRange = cmd.date_range(); @@ -910,8 +977,9 @@ Response::ResponseCode AbstractServerSocketInterface::cmdGetLogHistory(const Com if (servatrice->getEnableLogQuery()) { QListIterator messageIterator(sqlInterface->getMessageLogHistory( userName, ipAddress, gameName, gameID, message, chatType, gameType, roomType, dateRange, maximumResults)); - while (messageIterator.hasNext()) + while (messageIterator.hasNext()) { re->add_log_message()->CopyFrom(messageIterator.next()); + } } else { ServerInfo_ChatMessage chatMessage; @@ -949,8 +1017,9 @@ Response::ResponseCode AbstractServerSocketInterface::cmdGetLogHistory(const Com messageList << chatMessage; QListIterator messageIterator(messageList); - while (messageIterator.hasNext()) + while (messageIterator.hasNext()) { re->add_log_message()->CopyFrom(messageIterator.next()); + } } rc.setResponseExtension(re); @@ -965,8 +1034,9 @@ Response::ResponseCode AbstractServerSocketInterface::cmdGetBanHistory(const Com Response_BanHistory *re = new Response_BanHistory; QListIterator banIterator(sqlInterface->getUserBanHistory(userName)); - while (banIterator.hasNext()) + while (banIterator.hasNext()) { re->add_ban_list()->CopyFrom(banIterator.next()); + } rc.setResponseExtension(re); return Response::RespOk; } @@ -995,8 +1065,9 @@ Response::ResponseCode AbstractServerSocketInterface::cmdGetWarnHistory(const Co Response_WarnHistory *re = new Response_WarnHistory; QListIterator warnIterator(sqlInterface->getUserWarnHistory(userName)); - while (warnIterator.hasNext()) + while (warnIterator.hasNext()) { re->add_warn_list()->CopyFrom(warnIterator.next()); + } rc.setResponseExtension(re); return Response::RespOk; } @@ -1056,16 +1127,18 @@ Response::ResponseCode AbstractServerSocketInterface::cmdWarnUser(const Command_ Response::ResponseCode AbstractServerSocketInterface::cmdBanFromServer(const Command_BanFromServer &cmd, ResponseContainer & /*rc*/) { - if (!sqlInterface->checkSql()) + if (!sqlInterface->checkSql()) { return Response::RespInternalError; + } QString userName = nameFromStdString(cmd.user_name()).simplified(); QString address = nameFromStdString(cmd.address()).simplified(); QString clientId = nameFromStdString(cmd.clientid()).simplified(); QString visibleReason = textFromStdString(cmd.visible_reason()); - if (userName.isEmpty() && address.isEmpty() && clientId.isEmpty()) + if (userName.isEmpty() && address.isEmpty() && clientId.isEmpty()) { return Response::RespOk; + } int amountRemove = cmd.remove_messages(); if (amountRemove != 0) { @@ -1073,8 +1146,9 @@ Response::ResponseCode AbstractServerSocketInterface::cmdBanFromServer(const Com } QString trustedSources = settingsCache->value("server/trusted_sources", "127.0.0.1,::1").toString(); int minutes = cmd.minutes(); - if (trustedSources.contains(address, Qt::CaseInsensitive)) + if (trustedSources.contains(address, Qt::CaseInsensitive)) { address = ""; + } QSqlQuery *query = sqlInterface->prepareQuery( "insert into {prefix}_bans (user_name, ip_address, id_admin, time_from, minutes, reason, visible_reason, " @@ -1095,8 +1169,9 @@ Response::ResponseCode AbstractServerSocketInterface::cmdBanFromServer(const Com if (!userName.isEmpty()) { AbstractServerSocketInterface *user = static_cast(server->getUsers().value(userName)); - if (user && !userList.contains(user)) + if (user && !userList.contains(user)) { userList.append(user); + } } if (userName.isEmpty() && address.isEmpty() && (!clientId.isEmpty())) { @@ -1111,8 +1186,9 @@ Response::ResponseCode AbstractServerSocketInterface::cmdBanFromServer(const Com userName = clientIdQuery->value(0).toString(); AbstractServerSocketInterface *user = static_cast(server->getUsers().value(userName)); - if (user && !userList.contains(user)) + if (user && !userList.contains(user)) { userList.append(user); + } } } } @@ -1121,10 +1197,12 @@ Response::ResponseCode AbstractServerSocketInterface::cmdBanFromServer(const Com if (!userList.isEmpty()) { Event_ConnectionClosed event; event.set_reason(Event_ConnectionClosed::BANNED); - if (cmd.has_visible_reason()) + if (cmd.has_visible_reason()) { event.set_reason_str(visibleReason.toStdString()); - if (minutes) + } + if (minutes) { event.set_end_time(QDateTime::currentDateTime().addSecs(60 * minutes).toSecsSinceEpoch()); + } for (int i = 0; i < userList.size(); ++i) { SessionEvent *se = userList[i]->prepareSessionEvent(event); userList[i]->sendProtocolItem(*se); @@ -1136,12 +1214,15 @@ Response::ResponseCode AbstractServerSocketInterface::cmdBanFromServer(const Com for (QString &moderator : moderatorList) { QString notificationMessage = QString::fromStdString(userInfo->name()).simplified() + " has placed a ban with the following information"; - if (!userName.isEmpty()) + if (!userName.isEmpty()) { notificationMessage.append("\n Username: " + userName); - if (!address.isEmpty()) + } + if (!address.isEmpty()) { notificationMessage.append("\n IP Address: " + address); - if (!clientId.isEmpty()) + } + if (!clientId.isEmpty()) { notificationMessage.append("\n Client ID: " + clientId); + } notificationMessage.append("\n Length: " + QString::number(minutes) + " minute(s)"); notificationMessage.append("\n Internal Reason: " + textFromStdString(cmd.reason())); @@ -1161,9 +1242,10 @@ Response::ResponseCode AbstractServerSocketInterface::cmdRegisterAccount(const C bool registrationEnabled = settingsCache->value("registration/enabled", false).toBool(); if (!registrationEnabled) { - if (servatrice->getEnableRegistrationAudit()) + if (servatrice->getEnableRegistrationAudit()) { sqlInterface->addAuditRecord(userName.simplified(), this->getAddress(), clientId.simplified(), "REGISTER_ACCOUNT", "Server functionality disabled", false); + } return Response::RespRegistrationDisabled; } @@ -1196,9 +1278,10 @@ Response::ResponseCode AbstractServerSocketInterface::cmdRegisterAccount(const C // If a blacklist exists, ensure the email address domain is NOT in the blacklist if (!emailBlackListFilters.isEmpty() && emailBlackListFilters.contains(emailDomain, Qt::CaseInsensitive)) { - if (servatrice->getEnableRegistrationAudit()) + if (servatrice->getEnableRegistrationAudit()) { sqlInterface->addAuditRecord(userName.simplified(), this->getAddress(), clientId.simplified(), "REGISTER_ACCOUNT", "Email used is blacklisted", false); + } return Response::RespEmailBlackListed; } @@ -1206,9 +1289,10 @@ Response::ResponseCode AbstractServerSocketInterface::cmdRegisterAccount(const C //! \todo Move this method outside of the db interface QString errorString; if (!sqlInterface->usernameIsValid(userName, errorString)) { - if (servatrice->getEnableRegistrationAudit()) + if (servatrice->getEnableRegistrationAudit()) { sqlInterface->addAuditRecord(userName.simplified(), this->getAddress(), clientId.simplified(), "REGISTER_ACCOUNT", "Username is invalid", false); + } Response_Register *re = new Response_Register; re->set_denied_reason_str(errorString.toStdString()); @@ -1217,17 +1301,19 @@ Response::ResponseCode AbstractServerSocketInterface::cmdRegisterAccount(const C } if (userName.toLower().simplified() == "servatrice") { - if (servatrice->getEnableRegistrationAudit()) + if (servatrice->getEnableRegistrationAudit()) { sqlInterface->addAuditRecord(userName.simplified(), this->getAddress(), clientId.simplified(), "REGISTER_ACCOUNT", "Username is invalid", false); + } return Response::RespUsernameInvalid; } if (sqlInterface->userExists(userName)) { - if (servatrice->getEnableRegistrationAudit()) + if (servatrice->getEnableRegistrationAudit()) { sqlInterface->addAuditRecord(userName.simplified(), this->getAddress(), clientId.simplified(), "REGISTER_ACCOUNT", "Username already exists", false); + } return Response::RespUserAlreadyExists; } @@ -1235,10 +1321,11 @@ Response::ResponseCode AbstractServerSocketInterface::cmdRegisterAccount(const C const auto parsedEmailAddress = EmailParser::getParsedEmailAddress(parsedEmailParts); if (servatrice->getMaxAccountsPerEmail() > 0 && sqlInterface->checkNumberOfUserAccounts(parsedEmailAddress) >= servatrice->getMaxAccountsPerEmail()) { - if (servatrice->getEnableRegistrationAudit()) + if (servatrice->getEnableRegistrationAudit()) { sqlInterface->addAuditRecord(userName.simplified(), this->getAddress(), clientId.simplified(), "REGISTER_ACCOUNT", "Too many usernames registered with this email address", false); + } return Response::RespTooManyRequests; } @@ -1246,23 +1333,26 @@ Response::ResponseCode AbstractServerSocketInterface::cmdRegisterAccount(const C QString banReason; int banSecondsRemaining; if (sqlInterface->checkUserIsBanned(this->getAddress(), userName, clientId, banReason, banSecondsRemaining)) { - if (servatrice->getEnableRegistrationAudit()) + if (servatrice->getEnableRegistrationAudit()) { sqlInterface->addAuditRecord(userName.simplified(), this->getAddress(), clientId.simplified(), "REGISTER_ACCOUNT", "User is banned", false); + } Response_Register *re = new Response_Register; re->set_denied_reason_str(banReason.toStdString()); - if (banSecondsRemaining != 0) + if (banSecondsRemaining != 0) { re->set_denied_end_time(QDateTime::currentDateTime().addSecs(banSecondsRemaining).toSecsSinceEpoch()); + } rc.setResponseExtension(re); return Response::RespUserIsBanned; } if (tooManyRegistrationAttempts(this->getAddress())) { - if (servatrice->getEnableRegistrationAudit()) + if (servatrice->getEnableRegistrationAudit()) { sqlInterface->addAuditRecord(userName.simplified(), this->getAddress(), clientId.simplified(), "REGISTER_ACCOUNT", "Too many registration attempts from this ip address", false); + } return Response::RespTooManyRequests; } @@ -1272,8 +1362,9 @@ Response::ResponseCode AbstractServerSocketInterface::cmdRegisterAccount(const C QString password; bool passwordNeedsHash = false; if (cmd.has_password()) { - if (cmd.password().length() > MAX_NAME_LENGTH) + if (cmd.password().length() > MAX_NAME_LENGTH) { return Response::RespRegistrationFailed; + } password = QString::fromStdString(cmd.password()); passwordNeedsHash = true; if (!isPasswordLongEnough(password.length())) { @@ -1299,26 +1390,30 @@ Response::ResponseCode AbstractServerSocketInterface::cmdRegisterAccount(const C QSqlQuery *query = sqlInterface->prepareQuery("insert into {prefix}_activation_emails (name) values(:name)"); query->bindValue(":name", userName); - if (!sqlInterface->execSqlQuery(query)) + if (!sqlInterface->execSqlQuery(query)) { return Response::RespRegistrationFailed; + } - if (servatrice->getEnableRegistrationAudit()) + if (servatrice->getEnableRegistrationAudit()) { sqlInterface->addAuditRecord(userName.simplified(), this->getAddress(), clientId.simplified(), "REGISTER_ACCOUNT", "", true); + } return Response::RespRegistrationAcceptedNeedsActivation; } else { - if (servatrice->getEnableRegistrationAudit()) + if (servatrice->getEnableRegistrationAudit()) { sqlInterface->addAuditRecord(userName.simplified(), this->getAddress(), clientId.simplified(), "REGISTER_ACCOUNT", "", true); + } return Response::RespRegistrationAccepted; } } else { - if (servatrice->getEnableRegistrationAudit()) + if (servatrice->getEnableRegistrationAudit()) { sqlInterface->addAuditRecord(userName.simplified(), this->getAddress(), clientId.simplified(), "REGISTER_ACCOUNT", "Unknown reason for failure", false); + } return Response::RespRegistrationFailed; } @@ -1338,24 +1433,27 @@ Response::ResponseCode AbstractServerSocketInterface::cmdActivateAccount(const C QString token = nameFromStdString(cmd.token()); QString clientId = nameFromStdString(cmd.clientid()); - if (clientId.isEmpty()) + if (clientId.isEmpty()) { clientId = "UNKNOWN"; + } if (sqlInterface->activateUser(userName, token)) { qCDebug(AbstractServerSocketInterfaceLog) << "Accepted activation for user" << userName; - if (servatrice->getEnableRegistrationAudit()) + if (servatrice->getEnableRegistrationAudit()) { sqlInterface->addAuditRecord(userName.simplified(), this->getAddress(), clientId.simplified(), "ACTIVATE_ACCOUNT", "", true); + } return Response::RespActivationAccepted; } else { qCDebug(AbstractServerSocketInterfaceLog) << "Failed activation for user" << userName; - if (servatrice->getEnableRegistrationAudit()) + if (servatrice->getEnableRegistrationAudit()) { sqlInterface->addAuditRecord(userName.simplified(), this->getAddress(), clientId.simplified(), "ACTIVATE_ACCOUNT", "Failed to activate account, incorrect activation token", false); + } return Response::RespActivationFailed; } @@ -1364,8 +1462,9 @@ Response::ResponseCode AbstractServerSocketInterface::cmdActivateAccount(const C Response::ResponseCode AbstractServerSocketInterface::cmdAccountEdit(const Command_AccountEdit &cmd, ResponseContainer & /* rc */) { - if (authState != PasswordRight) + if (authState != PasswordRight) { return Response::RespFunctionNotAllowed; + } QString realName = nameFromStdString(cmd.real_name()); const auto parsedEmailAddress = EmailParser::getParsedEmailAddress(nameFromStdString(cmd.email())); @@ -1374,8 +1473,9 @@ Response::ResponseCode AbstractServerSocketInterface::cmdAccountEdit(const Comma bool checkedPassword = false; QString userName = QString::fromStdString(userInfo->name()); if (cmd.has_password_check()) { - if (cmd.password_check().length() > MAX_NAME_LENGTH) + if (cmd.password_check().length() > MAX_NAME_LENGTH) { return Response::RespWrongPassword; + } QString password = QString::fromStdString(cmd.password_check()); QString clientId = QString::fromStdString(userInfo->clientid()); QString reasonStr{}; @@ -1406,8 +1506,9 @@ Response::ResponseCode AbstractServerSocketInterface::cmdAccountEdit(const Comma queryList << "country=:country"; } - if (queryList.isEmpty()) + if (queryList.isEmpty()) { return Response::RespOk; + } QString queryText = QString("update {prefix}_users set %1 where name=:userName").arg(queryList.join(", ")); QSqlQuery *query = sqlInterface->prepareQuery(queryText); @@ -1425,8 +1526,9 @@ Response::ResponseCode AbstractServerSocketInterface::cmdAccountEdit(const Comma } query->bindValue(":userName", userName); - if (!sqlInterface->execSqlQuery(query)) + if (!sqlInterface->execSqlQuery(query)) { return Response::RespInternalError; + } if (cmd.has_real_name()) { userInfo->set_real_name(realName.toStdString()); @@ -1444,8 +1546,9 @@ Response::ResponseCode AbstractServerSocketInterface::cmdAccountEdit(const Comma Response::ResponseCode AbstractServerSocketInterface::cmdAccountImage(const Command_AccountImage &cmd, ResponseContainer & /* rc */) { - if (authState != PasswordRight) + if (authState != PasswordRight) { return Response::RespFunctionNotAllowed; + } size_t length = qMin(cmd.image().length(), (size_t)MAX_FILE_LENGTH); QByteArray image(cmd.image().c_str(), length); @@ -1454,8 +1557,9 @@ Response::ResponseCode AbstractServerSocketInterface::cmdAccountImage(const Comm QSqlQuery *query = sqlInterface->prepareQuery("update {prefix}_users set avatar_bmp=:image where id=:id"); query->bindValue(":image", image); query->bindValue(":id", id); - if (!sqlInterface->execSqlQuery(query)) + if (!sqlInterface->execSqlQuery(query)) { return Response::RespInternalError; + } userInfo->set_avatar_bmp(cmd.image().c_str(), length); return Response::RespOk; @@ -1464,21 +1568,25 @@ Response::ResponseCode AbstractServerSocketInterface::cmdAccountImage(const Comm Response::ResponseCode AbstractServerSocketInterface::cmdAccountPassword(const Command_AccountPassword &cmd, ResponseContainer & /* rc */) { - if (authState != PasswordRight) + if (authState != PasswordRight) { return Response::RespFunctionNotAllowed; + } - if (cmd.old_password().length() > MAX_NAME_LENGTH) + if (cmd.old_password().length() > MAX_NAME_LENGTH) { return Response::RespWrongPassword; + } QString oldPassword = QString::fromStdString(cmd.old_password()); QString newPassword; bool newPasswordNeedsHash = false; if (cmd.has_new_password()) { - if (cmd.new_password().length() > MAX_NAME_LENGTH) + if (cmd.new_password().length() > MAX_NAME_LENGTH) { return Response::RespContextError; + } newPassword = QString::fromStdString(cmd.new_password()); newPasswordNeedsHash = true; - if (!isPasswordLongEnough(newPassword.length())) + if (!isPasswordLongEnough(newPassword.length())) { return Response::RespPasswordTooShort; + } } else if (cmd.hashed_new_password().length() > MAX_NAME_LENGTH) { return Response::RespContextError; } else { @@ -1486,8 +1594,9 @@ Response::ResponseCode AbstractServerSocketInterface::cmdAccountPassword(const C } QString userName = QString::fromStdString(userInfo->name()); - if (!databaseInterface->changeUserPassword(userName, oldPassword, true, newPassword, newPasswordNeedsHash)) + if (!databaseInterface->changeUserPassword(userName, oldPassword, true, newPassword, newPasswordNeedsHash)) { return Response::RespWrongPassword; + } return Response::RespOk; } @@ -1501,9 +1610,10 @@ Response::ResponseCode AbstractServerSocketInterface::cmdForgotPasswordRequest(c qCDebug(AbstractServerSocketInterfaceLog) << "Received reset password request from user:" << userName; if (!servatrice->getEnableForgotPassword()) { - if (servatrice->getEnableForgotPasswordAudit()) + if (servatrice->getEnableForgotPasswordAudit()) { sqlInterface->addAuditRecord(userName.simplified(), this->getAddress(), clientId.simplified(), "PASSWORD_RESET_REQUEST", "Server functionality disabled", false); + } return Response::RespFunctionNotAllowed; } @@ -1516,9 +1626,10 @@ Response::ResponseCode AbstractServerSocketInterface::cmdForgotPasswordRequest(c } if (!sqlInterface->userExists(userName)) { - if (servatrice->getEnableForgotPasswordAudit()) + if (servatrice->getEnableForgotPasswordAudit()) { sqlInterface->addAuditRecord(userName.simplified(), this->getAddress(), clientId.simplified(), "PASSWORD_RESET_REQUEST", "User does not exist", false); + } return Response::RespFunctionNotAllowed; } @@ -1533,9 +1644,10 @@ Response::ResponseCode AbstractServerSocketInterface::continuePasswordRequest(co { if (sqlInterface->doesForgotPasswordExist(userName)) { - if (servatrice->getEnableForgotPasswordAudit()) + if (servatrice->getEnableForgotPasswordAudit()) { sqlInterface->addAuditRecord(userName.simplified(), this->getAddress(), clientId.simplified(), "PASSWORD_RESET_REQUEST", "Request already exists", true); + } Response_ForgotPasswordRequest *re = new Response_ForgotPasswordRequest; re->set_challenge_email(false); @@ -1546,9 +1658,10 @@ Response::ResponseCode AbstractServerSocketInterface::continuePasswordRequest(co QString banReason; int banTimeRemaining; if (sqlInterface->checkUserIsBanned(this->getAddress(), userName, clientId, banReason, banTimeRemaining)) { - if (servatrice->getEnableForgotPasswordAudit()) + if (servatrice->getEnableForgotPasswordAudit()) { sqlInterface->addAuditRecord(userName.simplified(), this->getAddress(), clientId.simplified(), "PASSWORD_RESET_REQUEST", "User is banned", false); + } return Response::RespFunctionNotAllowed; } @@ -1583,18 +1696,20 @@ Response::ResponseCode AbstractServerSocketInterface::cmdForgotPasswordReset(con qCDebug(AbstractServerSocketInterfaceLog) << "Received reset password reset from user:" << userName; if (!sqlInterface->doesForgotPasswordExist(userName)) { - if (servatrice->getEnableForgotPasswordAudit()) + if (servatrice->getEnableForgotPasswordAudit()) { sqlInterface->addAuditRecord(userName.simplified(), this->getAddress(), clientId.simplified(), "PASSWORD_RESET", "Request does not exist for user", false); + } return Response::RespFunctionNotAllowed; } if (!sqlInterface->validateTableColumnStringData("{prefix}_users", "token", userName, nameFromStdString(cmd.token()))) { - if (servatrice->getEnableForgotPasswordAudit()) + if (servatrice->getEnableForgotPasswordAudit()) { sqlInterface->addAuditRecord(userName.simplified(), this->getAddress(), userName.simplified(), "PASSWORD_RESET", "Failed token validation", false); + } return Response::RespFunctionNotAllowed; } @@ -1602,8 +1717,9 @@ Response::ResponseCode AbstractServerSocketInterface::cmdForgotPasswordReset(con QString password; bool passwordNeedsHash = false; if (cmd.has_new_password()) { - if (cmd.new_password().length() > MAX_NAME_LENGTH) + if (cmd.new_password().length() > MAX_NAME_LENGTH) { return Response::RespContextError; + } password = QString::fromStdString(cmd.new_password()); passwordNeedsHash = true; } else if (cmd.hashed_new_password().length() > MAX_NAME_LENGTH) { @@ -1613,9 +1729,10 @@ Response::ResponseCode AbstractServerSocketInterface::cmdForgotPasswordReset(con } if (sqlInterface->changeUserPassword(nameFromStdString(cmd.user_name()), password, passwordNeedsHash)) { - if (servatrice->getEnableForgotPasswordAudit()) + if (servatrice->getEnableForgotPasswordAudit()) { sqlInterface->addAuditRecord(userName.simplified(), this->getAddress(), clientId.simplified(), "PASSWORD_RESET", "", true); + } sqlInterface->removeForgotPassword(nameFromStdString(cmd.user_name())); return Response::RespOk; @@ -1961,8 +2078,9 @@ void TcpServerSocketInterface::initSessionDeprecated() void TcpServerSocketInterface::flushOutputQueue() { QMutexLocker locker(&outputQueueMutex); - if (outputQueue.isEmpty()) + if (outputQueue.isEmpty()) { return; + } int totalBytes = 0; while (!outputQueue.isEmpty()) { @@ -2011,11 +2129,13 @@ void TcpServerSocketInterface::readClient() ((quint32)(unsigned char)inputBuffer[3]); inputBuffer.remove(0, 4); messageInProgress = true; - } else + } else { return; + } } - if (inputBuffer.size() < messageLength || messageLength < 0) + if (inputBuffer.size() < messageLength || messageLength < 0) { return; + } CommandContainer newCommandContainer; bool ok; @@ -2048,12 +2168,13 @@ void TcpServerSocketInterface::readClient() if (ok) { // dirty hack to make v13 client display the correct error message - if (handshakeStarted) + if (handshakeStarted) { processCommandContainer(newCommandContainer); - else if (!newCommandContainer.has_cmd_id()) { + } else if (!newCommandContainer.has_cmd_id()) { handshakeStarted = true; - if (!initTcpSession()) + if (!initTcpSession()) { prepareDestroy(); + } } // end of hack } else { @@ -2065,8 +2186,9 @@ void TcpServerSocketInterface::readClient() bool TcpServerSocketInterface::initTcpSession() { - if (!initSession()) + if (!initSession()) { return false; + } // limit the number of websocket users based on configuration settings bool enforceUserLimit = settingsCache->value("security/enable_max_user_limit", false).toBool(); @@ -2138,14 +2260,16 @@ void WebsocketServerSocketInterface::initConnection(void *_socket) QString("Incoming websocket connection: %1 (%2)").arg(address.toString()).arg(socket->peerAddress().toString()), this); - if (!initWebsocketSession()) + if (!initWebsocketSession()) { prepareDestroy(); + } } bool WebsocketServerSocketInterface::initWebsocketSession() { - if (!initSession()) + if (!initSession()) { return false; + } // limit the number of websocket users based on configuration settings bool enforceUserLimit = settingsCache->value("security/enable_max_user_limit", false).toBool(); @@ -2172,8 +2296,9 @@ bool WebsocketServerSocketInterface::initWebsocketSession() void WebsocketServerSocketInterface::flushOutputQueue() { QMutexLocker locker(&outputQueueMutex); - if (outputQueue.isEmpty()) + if (outputQueue.isEmpty()) { return; + } qint64 totalBytes = 0; while (!outputQueue.isEmpty()) { diff --git a/servatrice/src/settingscache.cpp b/servatrice/src/settingscache.cpp index f6dcd5fc8..f6c862904 100644 --- a/servatrice/src/settingscache.cpp +++ b/servatrice/src/settingscache.cpp @@ -30,14 +30,16 @@ QString SettingsCache::guessConfigurationPath() // application directory path guessFileName = QCoreApplication::applicationDirPath() + "/" + fileName; - if (QFile::exists(guessFileName)) + if (QFile::exists(guessFileName)) { return guessFileName; + } #ifdef Q_OS_UNIX // /etc guessFileName = "/etc/servatrice/" + fileName; - if (QFile::exists(guessFileName)) + if (QFile::exists(guessFileName)) { return guessFileName; + } #endif guessFileName = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + "/" + fileName; diff --git a/servatrice/src/signalhandler.cpp b/servatrice/src/signalhandler.cpp index f7cb207a9..b4513979f 100644 --- a/servatrice/src/signalhandler.cpp +++ b/servatrice/src/signalhandler.cpp @@ -86,10 +86,11 @@ void SignalHandler::sigSegvHandler(int sig) fprintf(stderr, "Error: signal %d:\n", sig); backtrace_symbols_fd(array, size, STDERR_FILENO); - if (sig == SIGSEGV) + if (sig == SIGSEGV) { logger->logMessage("CRASH: SIGSEGV"); - else if (sig == SIGABRT) + } else if (sig == SIGABRT) { logger->logMessage("CRASH: SIGABRT"); + } logger->deleteLater(); loggerThread->wait(); diff --git a/servatrice/src/smtpclient.cpp b/servatrice/src/smtpclient.cpp index ee7214904..3ec333413 100644 --- a/servatrice/src/smtpclient.cpp +++ b/servatrice/src/smtpclient.cpp @@ -125,11 +125,13 @@ bool SmtpClient::enqueueForgotPasswordTokenMail(const QString &nickname, const Q void SmtpClient::sendAllEmails() { // still connected from the previous round - if (smtp->socket()->state() == QAbstractSocket::ConnectedState) + if (smtp->socket()->state() == QAbstractSocket::ConnectedState) { return; + } - if (smtp->pendingMessages() == 0) + if (smtp->pendingMessages() == 0) { return; + } QString connectionType = settingsCache->value("smtp/connection", "tcp").toString(); QString host = settingsCache->value("smtp/host", "localhost").toString(); @@ -143,8 +145,9 @@ void SmtpClient::sendAllEmails() // Connect if (connectionType == "ssl") { - if (acceptAllCerts) + if (acceptAllCerts) { smtp->sslSocket()->setPeerVerifyMode(QSslSocket::QueryPeer); + } smtp->connectToSecureHost(host, port); } else { smtp->connectToHost(host, port); From 20cd7ce73daac54e6b8f85e8ecaba80e799c9940 Mon Sep 17 00:00:00 2001 From: ebbit1q Date: Sat, 16 May 2026 19:39:34 +0200 Subject: [PATCH 10/51] fix arch compiling (#6895) --- .../network/server/remote/server_player_reference.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcockatrice_network/libcockatrice/network/server/remote/server_player_reference.h b/libcockatrice_network/libcockatrice/network/server/remote/server_player_reference.h index 07b2d3d2b..b478a4244 100644 --- a/libcockatrice_network/libcockatrice/network/server/remote/server_player_reference.h +++ b/libcockatrice_network/libcockatrice/network/server/remote/server_player_reference.h @@ -24,7 +24,7 @@ public: { return playerId; } - bool operator==(const PlayerReference &other) + bool operator==(const PlayerReference &other) const { return ((roomId == other.roomId) && (gameId == other.gameId) && (playerId == other.playerId)); } From f8ce5c2e39600e7501a020b066d11b0e62dbf56e Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Sat, 16 May 2026 20:15:10 +0200 Subject: [PATCH 11/51] [PictureLoader] Allow saving downloaded images to local storage and not just the QNetworkManager cache (#6620) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [PictureLoader] Allow saving downloaded images to local storage and not just the QNetworkManager cache. Took 1 hour 11 minutes Took 4 seconds Took 25 seconds * Give people options from a dropdown. Took 1 hour 6 minutes Took 3 seconds * Simplify directory removal code. Took 5 minutes Took 8 seconds * Merge pull request #8 * Create new category for new settings * Split off storage settings Took 47 minutes Took 4 seconds * Allow toggling between caching methods. Took 1 hour 30 minutes Took 9 seconds * Adjust settings dialog. Took 5 minutes Took 59 seconds Took 22 seconds Took 6 seconds * tr() strings Took 1 minute Took 6 seconds * Readjust layout, default naming scheme. Took 5 minutes * Add stretch. Took 9 minutes * Make scrollable. Took 2 minutes * Add icon. Took 7 minutes * Change naming to be uniform. Took 3 minutes Took 3 seconds --------- Co-authored-by: Lukas Brübach Co-authored-by: RickyRister <42636155+RickyRister@users.noreply.github.com> --- cockatrice/cockatrice.qrc | 1 + cockatrice/resources/config/storage.svg | 799 ++++++++++++++++++ .../src/client/settings/cache_settings.cpp | 27 + .../src/client/settings/cache_settings.h | 17 + .../card_picture_loader.cpp | 96 ++- .../card_picture_loader/card_picture_loader.h | 1 + .../card_picture_loader_cache_method.h | 31 + .../card_picture_loader_local.cpp | 23 +- .../card_picture_loader_local_schemes.h | 109 +++ .../card_picture_loader_worker.cpp | 38 +- .../widgets/dialogs/dlg_settings.cpp | 333 ++++++-- .../interface/widgets/dialogs/dlg_settings.h | 39 +- 12 files changed, 1382 insertions(+), 132 deletions(-) create mode 100644 cockatrice/resources/config/storage.svg create mode 100644 cockatrice/src/interface/card_picture_loader/card_picture_loader_cache_method.h create mode 100644 cockatrice/src/interface/card_picture_loader/card_picture_loader_local_schemes.h diff --git a/cockatrice/cockatrice.qrc b/cockatrice/cockatrice.qrc index 37fb145f0..00f9f0284 100644 --- a/cockatrice/cockatrice.qrc +++ b/cockatrice/cockatrice.qrc @@ -69,6 +69,7 @@ resources/config/interface.svg resources/config/messages.svg resources/config/deckeditor.svg + resources/config/storage.svg resources/config/shorcuts.svg resources/config/sound.svg resources/config/debug.ini diff --git a/cockatrice/resources/config/storage.svg b/cockatrice/resources/config/storage.svg new file mode 100644 index 000000000..de85228dc --- /dev/null +++ b/cockatrice/resources/config/storage.svg @@ -0,0 +1,799 @@ + + + +image/svg+xml diff --git a/cockatrice/src/client/settings/cache_settings.cpp b/cockatrice/src/client/settings/cache_settings.cpp index 779522b72..64416e5ee 100644 --- a/cockatrice/src/client/settings/cache_settings.cpp +++ b/cockatrice/src/client/settings/cache_settings.cpp @@ -1,5 +1,7 @@ #include "cache_settings.h" +#include "../../interface/card_picture_loader/card_picture_loader_cache_method.h" +#include "../../interface/card_picture_loader/card_picture_loader_local_schemes.h" #include "../network/update/client/release_channel.h" #include "card_counter_settings.h" #include "version_string.h" @@ -278,6 +280,16 @@ SettingsCache::SettingsCache() networkCacheSize = settings->value("personal/networkCacheSize", NETWORK_CACHE_SIZE_DEFAULT).toInt(); redirectCacheTtl = settings->value("personal/redirectCacheTtl", NETWORK_REDIRECT_CACHE_TTL_DEFAULT).toInt(); + cardPictureLoaderCacheMethod = + settings + ->value("personal/cardPictureLoaderCacheMethod", + static_cast(CardPictureLoaderCacheMethod::CacheMethod::NETWORK_CACHE)) + .toInt(); + localCardImageStorageNamingScheme = + settings + ->value("personal/localCardImageStorageNamingScheme", + static_cast(CardPictureLoaderLocalSchemes::NamingScheme::Set_Folder_Name_Set_Collector)) + .toInt(); picDownload = settings->value("personal/picturedownload", true).toBool(); showStatusBar = settings->value("personal/showStatusBar", false).toBool(); @@ -1112,6 +1124,13 @@ void SettingsCache::setPixmapCacheSize(const int _pixmapCacheSize) emit pixmapCacheSizeChanged(pixmapCacheSize); } +void SettingsCache::setCardImageCacheMethod(const CardPictureLoaderCacheMethod::CacheMethod _cardImageCachingMethod) +{ + cardPictureLoaderCacheMethod = static_cast(_cardImageCachingMethod); + settings->setValue("personal/cardPictureLoaderCacheMethod", cardPictureLoaderCacheMethod); + emit cardPictureLoaderCacheMethodChanged(cardPictureLoaderCacheMethod); +} + void SettingsCache::setNetworkCacheSizeInMB(const int _networkCacheSize) { networkCacheSize = _networkCacheSize; @@ -1126,6 +1145,14 @@ void SettingsCache::setNetworkRedirectCacheTtl(const int _redirectCacheTtl) emit redirectCacheTtlChanged(redirectCacheTtl); } +void SettingsCache::setLocalCardImageStorageNamingScheme( + const CardPictureLoaderLocalSchemes::NamingScheme _localCardImageStorageNamingScheme) +{ + localCardImageStorageNamingScheme = static_cast(_localCardImageStorageNamingScheme); + settings->setValue("personal/localCardImageStorageNamingScheme", localCardImageStorageNamingScheme); + emit localCardImageStorageNamingSchemeChanged(localCardImageStorageNamingScheme); +} + void SettingsCache::setClientID(const QString &_clientID) { clientID = _clientID; diff --git a/cockatrice/src/client/settings/cache_settings.h b/cockatrice/src/client/settings/cache_settings.h index 0cd5ceb68..90aa8eedb 100644 --- a/cockatrice/src/client/settings/cache_settings.h +++ b/cockatrice/src/client/settings/cache_settings.h @@ -7,6 +7,8 @@ #ifndef SETTINGSCACHE_H #define SETTINGSCACHE_H +#include "../../interface/card_picture_loader/card_picture_loader_cache_method.h" +#include "../../interface/card_picture_loader/card_picture_loader_local_schemes.h" #include "shortcuts_settings.h" #include @@ -184,6 +186,8 @@ signals: void pixmapCacheSizeChanged(int newSizeInMBs); void networkCacheSizeChanged(int newSizeInMBs); void redirectCacheTtlChanged(int newTtl); + void cardPictureLoaderCacheMethodChanged(int cardPictureLoaderCacheMethod); + void localCardImageStorageNamingSchemeChanged(int localCardImageStorageNamingScheme); void masterVolumeChanged(int value); void chatMentionCompleterChanged(); void downloadSpoilerTimeIndexChanged(); @@ -303,6 +307,8 @@ private: int pixmapCacheSize; int networkCacheSize; int redirectCacheTtl; + int cardPictureLoaderCacheMethod; + int localCardImageStorageNamingScheme; bool scaleCards; int verticalCardOverlapPercent; bool showMessagePopups; @@ -786,6 +792,10 @@ public: { return pixmapCacheSize; } + [[nodiscard]] CardPictureLoaderCacheMethod::CacheMethod getCardPictureLoaderCacheMethod() const + { + return static_cast(cardPictureLoaderCacheMethod); + } [[nodiscard]] int getNetworkCacheSizeInMB() const { return networkCacheSize; @@ -794,6 +804,10 @@ public: { return redirectCacheTtl; } + [[nodiscard]] CardPictureLoaderLocalSchemes::NamingScheme getLocalCardImageStorageNamingScheme() const + { + return static_cast(localCardImageStorageNamingScheme); + } [[nodiscard]] bool getScaleCards() const { return scaleCards; @@ -1098,8 +1112,11 @@ public slots: void setIgnoreUnregisteredUsers(QT_STATE_CHANGED_T _ignoreUnregisteredUsers); void setIgnoreUnregisteredUserMessages(QT_STATE_CHANGED_T _ignoreUnregisteredUserMessages); void setPixmapCacheSize(const int _pixmapCacheSize); + void setCardImageCacheMethod(CardPictureLoaderCacheMethod::CacheMethod _cardImageCachingMethod); void setNetworkCacheSizeInMB(const int _networkCacheSize); void setNetworkRedirectCacheTtl(const int _redirectCacheTtl); + void setLocalCardImageStorageNamingScheme( + const CardPictureLoaderLocalSchemes::NamingScheme _localCardImageStorageNamingScheme); void setCardScaling(const QT_STATE_CHANGED_T _scaleCards); void setStackCardOverlapPercent(const int _verticalCardOverlapPercent); void setShowMessagePopups(const QT_STATE_CHANGED_T _showMessagePopups); diff --git a/cockatrice/src/interface/card_picture_loader/card_picture_loader.cpp b/cockatrice/src/interface/card_picture_loader/card_picture_loader.cpp index 2cd28c4d3..bd427a6c8 100644 --- a/cockatrice/src/interface/card_picture_loader/card_picture_loader.cpp +++ b/cockatrice/src/interface/card_picture_loader/card_picture_loader.cpp @@ -150,9 +150,10 @@ void CardPictureLoader::getPixmap(QPixmap &pixmap, const ExactCard &card, QSize void CardPictureLoader::imageLoaded(const ExactCard &card, const QImage &image) { + QPixmap finalPixmap; + if (image.isNull()) { qCDebug(CardPictureLoaderLog) << "Caching NULL pixmap for" << card.getName(); - QPixmapCache::insert(card.getPixmapCacheKey(), QPixmap()); } else { if (card.getInfo().getUiAttributes().upsideDownArt) { #if (QT_VERSION >= QT_VERSION_CHECK(6, 9, 0)) @@ -160,12 +161,19 @@ void CardPictureLoader::imageLoaded(const ExactCard &card, const QImage &image) #else QImage mirrorImage = image.mirrored(true, true); #endif - QPixmapCache::insert(card.getPixmapCacheKey(), QPixmap::fromImage(mirrorImage)); + finalPixmap = QPixmap::fromImage(mirrorImage); } else { - QPixmapCache::insert(card.getPixmapCacheKey(), QPixmap::fromImage(image)); + finalPixmap = QPixmap::fromImage(image); } } + QPixmapCache::insert(card.getPixmapCacheKey(), finalPixmap); + + if (SettingsCache::instance().getCardPictureLoaderCacheMethod() == + CardPictureLoaderCacheMethod::CacheMethod::FILESYSTEM_CACHE) { + saveCardImageToLocalStorage(card, finalPixmap); + } + // imageLoaded should only be reached if the exactCard isn't already in cache. // (plus there's a deduplication mechanism in CardPictureLoaderWorker) // It should be safe to connect the CardInfo here without worrying about redundant connections. @@ -175,6 +183,88 @@ void CardPictureLoader::imageLoaded(const ExactCard &card, const QImage &image) card.emitPixmapUpdated(); } +void CardPictureLoader::saveCardImageToLocalStorage(const ExactCard &card, const QPixmap &pixmap) +{ + if (pixmap.isNull() || !card) { + return; + } + + const QString picsRoot = SettingsCache::instance().getPicsPath(); + CardPictureLoaderLocalSchemes::NamingScheme scheme = + SettingsCache::instance().getLocalCardImageStorageNamingScheme(); + + QString pattern; + + for (const auto &s : CardPictureLoaderLocalSchemes::exportSchemes()) { + if (s.id == scheme) { + pattern = s.pattern; + break; + } + } + + if (picsRoot.isEmpty() || pattern.isEmpty()) { + return; + } + + // Base directory: /downloadedPics + QDir baseDir(picsRoot); + if (!baseDir.exists("downloadedPics")) { + baseDir.mkpath("downloadedPics"); + } + baseDir.cd("downloadedPics"); + + // Collect card metadata + const QString cardName = card.getInfo().getCorrectedName(); + + QString setName; + QString collectorNumber; + QString uuid; + + PrintingInfo printing = card.getPrinting(); + if (printing.getSet()) { + setName = printing.getSet()->getCorrectedShortName(); + collectorNumber = printing.getProperty("num"); + uuid = printing.getUuid(); + } + + // Build path from scheme + QString relativePath = + CardPictureLoaderLocalSchemes::expandPattern(pattern, cardName, setName, collectorNumber, uuid); + + if (relativePath.isEmpty()) { + return; + } + + // append extension + relativePath += ".png"; + + // Normalize slashes + relativePath = QDir::cleanPath(relativePath); + + QFileInfo outInfo(baseDir.filePath(relativePath)); + + // Do not overwrite existing files + if (outInfo.exists()) { + return; + } + + QDir outDir = outInfo.dir(); + + // Ensure directory exists + if (!outDir.exists()) { + if (!baseDir.mkpath(outDir.path())) { + qCWarning(CardPictureLoaderLog) << "Failed to create directory for downloaded card image:" << outDir.path(); + return; + } + } + + // Save image + QImage image = pixmap.toImage(); + if (!image.save(outInfo.absoluteFilePath(), "PNG")) { + qCWarning(CardPictureLoaderLog) << "Failed to save card image to" << outInfo.absoluteFilePath(); + } +} + void CardPictureLoader::clearPixmapCache() { QPixmapCache::clear(); diff --git a/cockatrice/src/interface/card_picture_loader/card_picture_loader.h b/cockatrice/src/interface/card_picture_loader/card_picture_loader.h index 4000fd99a..0c114ae92 100644 --- a/cockatrice/src/interface/card_picture_loader/card_picture_loader.h +++ b/cockatrice/src/interface/card_picture_loader/card_picture_loader.h @@ -117,6 +117,7 @@ public slots: * @param image Loaded QImage. */ void imageLoaded(const ExactCard &card, const QImage &image); + void saveCardImageToLocalStorage(const ExactCard &card, const QPixmap &pixmap); private slots: /** diff --git a/cockatrice/src/interface/card_picture_loader/card_picture_loader_cache_method.h b/cockatrice/src/interface/card_picture_loader/card_picture_loader_cache_method.h new file mode 100644 index 000000000..54977e249 --- /dev/null +++ b/cockatrice/src/interface/card_picture_loader/card_picture_loader_cache_method.h @@ -0,0 +1,31 @@ +#ifndef COCKATRICE_CARD_PICTURE_LOADER_CACHE_METHOD_H +#define COCKATRICE_CARD_PICTURE_LOADER_CACHE_METHOD_H +#include +#include +#include + +namespace CardPictureLoaderCacheMethod +{ +enum class CacheMethod +{ + NETWORK_CACHE, + FILESYSTEM_CACHE +}; + +struct CacheMethodInfo +{ + CacheMethod id; + QString displayName; +}; + +static inline const QList methods() +{ + static QList all = { + {CacheMethod::NETWORK_CACHE, QCoreApplication::translate("CardPictureLoaderCacheMethod", "Network Cache")}, + {CacheMethod::FILESYSTEM_CACHE, QCoreApplication::translate("CardPictureLoaderCacheMethod", "Filesystem")}, + }; + return all; +} +} // namespace CardPictureLoaderCacheMethod + +#endif // COCKATRICE_CARD_PICTURE_LOADER_CACHE_METHOD_H diff --git a/cockatrice/src/interface/card_picture_loader/card_picture_loader_local.cpp b/cockatrice/src/interface/card_picture_loader/card_picture_loader_local.cpp index dd00e6e1d..bb10d1c42 100644 --- a/cockatrice/src/interface/card_picture_loader/card_picture_loader_local.cpp +++ b/cockatrice/src/interface/card_picture_loader/card_picture_loader_local.cpp @@ -1,6 +1,7 @@ #include "card_picture_loader_local.h" #include "../../client/settings/cache_settings.h" +#include "card_picture_loader_local_schemes.h" #include "card_picture_to_load.h" #include @@ -77,26 +78,8 @@ QImage CardPictureLoaderLocal::tryLoadCardImageFromDisk(const QString &setName, imgReader.setDecideFormatFromContent(true); // Most-to-least specific, these will fall through in order. - QStringList nameVariants; - - // cardName_providerId - if (!providerId.isEmpty()) { - nameVariants << QString("%1-%2").arg(correctedCardName, providerId) - << QString("%1_%2").arg(correctedCardName, providerId); - } - // cardName_setName_collectorNumber & setName-collectorNumber-cardName - if (!setName.isEmpty() && !collectorNumber.isEmpty()) { - nameVariants << QString("%1_%2_%3").arg(correctedCardName, setName, collectorNumber) - << QString("%1-%2-%3").arg(setName, collectorNumber, correctedCardName); - } - // cardName_setName - if (!setName.isEmpty()) { - nameVariants << QString("%1_%2").arg(correctedCardName, setName) - << QString("%1-%2").arg(setName, correctedCardName); - } - - // cardName - nameVariants << correctedCardName; + QStringList nameVariants = + CardPictureLoaderLocalSchemes::generateImportVariants(correctedCardName, setName, collectorNumber, providerId); for (const QString &nameVariant : nameVariants) { if (nameVariant.isEmpty()) { diff --git a/cockatrice/src/interface/card_picture_loader/card_picture_loader_local_schemes.h b/cockatrice/src/interface/card_picture_loader/card_picture_loader_local_schemes.h new file mode 100644 index 000000000..cad7d2d5f --- /dev/null +++ b/cockatrice/src/interface/card_picture_loader/card_picture_loader_local_schemes.h @@ -0,0 +1,109 @@ +#ifndef COCKATRICE_CARD_PICTURE_LOADER_LOCAL_SCHEMES_H +#define COCKATRICE_CARD_PICTURE_LOADER_LOCAL_SCHEMES_H + +#include +#include +#include +#include + +namespace CardPictureLoaderLocalSchemes +{ + +enum class NamingScheme +{ + NameOnly, + Name_Set, + Name_Set_Collector, + Set_Collector_Name, + Name_ProviderId, + Set_Folder_Name_ProviderId, + Set_Folder_Name_Set_Collector +}; + +struct NamingSchemeInfo +{ + NamingScheme id; + QString displayName; + QString pattern; +}; + +inline const QList &importSchemes() +{ + static QList list = { + {NamingScheme::Name_ProviderId, "Card Name + Provider ID", "{name}_{providerId}"}, + {NamingScheme::Name_Set_Collector, "Card Name + Set + Collector", "{name}_{set}_{collector}"}, + {NamingScheme::Set_Collector_Name, "Set + Collector + Card Name", "{set}_{collector}_{name}"}, + {NamingScheme::Name_Set, "Card Name + Set", "{name}_{set}"}, + {NamingScheme::NameOnly, "Card Name", "{name}"}, + }; + return list; +} + +inline const QList &exportSchemes() +{ + static QList list = { + {NamingScheme::Set_Folder_Name_ProviderId, "Set Folder / Name + Provider ID", "{set}/{name}_{providerId}"}, + {NamingScheme::Set_Folder_Name_Set_Collector, "Set Folder / Name + Set Name + Collector", + "{set}/{name}_{set}_{collector}"}, + {NamingScheme::Name_ProviderId, "Card Name + Provider ID", "{name}_{providerId}"}, + {NamingScheme::Name_Set_Collector, "Card Name + Set + Collector", "{name}_{set}_{collector}"}, + {NamingScheme::Set_Collector_Name, "Set + Collector + Card Name", "{set}_{collector}_{name}"}, + }; + return list; +} + +inline QString expandPattern(const QString &pattern, + const QString &name, + const QString &set, + const QString &collector, + const QString &providerId) +{ + QString result = pattern; + + auto replaceIfPresent = [&](const QString &token, const QString &value) -> bool { + if (!result.contains(token)) + return true; + + if (value.isEmpty()) + return false; + + result.replace(token, value); + return true; + }; + + if (!replaceIfPresent("{name}", name)) + return {}; + if (!replaceIfPresent("{set}", set)) + return {}; + if (!replaceIfPresent("{collector}", collector)) + return {}; + if (!replaceIfPresent("{providerId}", providerId)) + return {}; + + return result; +} + +inline QStringList +generateImportVariants(const QString &name, const QString &set, const QString &collector, const QString &providerId) +{ + QStringList variants; + const QStringList separators = {"_", "-"}; + + for (const auto &scheme : importSchemes()) { + for (const QString &sep : separators) { + + QString pattern = scheme.pattern; + pattern.replace("_", sep); + + QString v = expandPattern(pattern, name, set, collector, providerId); + if (!v.isEmpty()) + variants << v; + } + } + + return variants; +} + +} // namespace CardPictureLoaderLocalSchemes + +#endif // COCKATRICE_CARD_PICTURE_LOADER_LOCAL_SCHEMES_H \ No newline at end of file diff --git a/cockatrice/src/interface/card_picture_loader/card_picture_loader_worker.cpp b/cockatrice/src/interface/card_picture_loader/card_picture_loader_worker.cpp index a246d74f2..a0f000139 100644 --- a/cockatrice/src/interface/card_picture_loader/card_picture_loader_worker.cpp +++ b/cockatrice/src/interface/card_picture_loader/card_picture_loader_worker.cpp @@ -26,10 +26,14 @@ CardPictureLoaderWorker::CardPictureLoaderWorker() cache->setCacheDirectory(SettingsCache::instance().getNetworkCachePath()); cache->setMaximumCacheSize(1024L * 1024L * static_cast(SettingsCache::instance().getNetworkCacheSizeInMB())); - // Note: the settings is in MB, but QNetworkDiskCache uses bytes - connect(&SettingsCache::instance(), &SettingsCache::networkCacheSizeChanged, this, - [this](int newSizeInMB) { cache->setMaximumCacheSize(1024L * 1024L * static_cast(newSizeInMB)); }); + + connect(&SettingsCache::instance(), &SettingsCache::networkCacheSizeChanged, cache, [this](int newSizeInMB) { + if (cache) + cache->setMaximumCacheSize(1024L * 1024L * static_cast(newSizeInMB)); + }); + networkManager->setCache(cache); + // Use a ManualRedirectPolicy since we keep track of redirects in picDownloadFinished // We can't use NoLessSafeRedirectPolicy because it is not applied with AlwaysCache networkManager->setRedirectPolicy(QNetworkRequest::ManualRedirectPolicy); @@ -65,14 +69,19 @@ void CardPictureLoaderWorker::queueRequest(const QUrl &url, CardPictureLoaderWor QUrl cachedRedirect = getCachedRedirect(url); if (!cachedRedirect.isEmpty()) { queueRequest(cachedRedirect, worker); - } else if (cache->metaData(url).isValid()) { - // If we hit a cached url, we get to make the request for free, since it won't contribute towards the rate-limit - makeRequest(url, worker); - } else { - requestLoadQueue.append(qMakePair(url, worker)); - emit imageRequestQueued(url, worker->cardToDownload.getCard(), worker->cardToDownload.getSetName()); - processQueuedRequests(); + return; } + if (SettingsCache::instance().getCardPictureLoaderCacheMethod() == + CardPictureLoaderCacheMethod::CacheMethod::NETWORK_CACHE && + cache->metaData(url).isValid()) { + // If we hit a cached url, we get to make the request for free, since it won't contribute towards the + // rate-limit + makeRequest(url, worker); + return; + } + requestLoadQueue.append(qMakePair(url, worker)); + emit imageRequestQueued(url, worker->cardToDownload.getCard(), worker->cardToDownload.getSetName()); + processQueuedRequests(); } QNetworkReply *CardPictureLoaderWorker::makeRequest(const QUrl &url, CardPictureLoaderWorkerWork *worker) @@ -87,9 +96,12 @@ QNetworkReply *CardPictureLoaderWorker::makeRequest(const QUrl &url, CardPicture QNetworkRequest req(url); req.setHeader(QNetworkRequest::UserAgentHeader, QString("Cockatrice %1").arg(VERSION_STRING)); req.setRawHeader("Accept", "image/avif,image/webp,image/apng,image/,/*;q=0.8"); - if (!picDownload) { - req.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysCache); - } + + bool useNetworkCache = !picDownload && SettingsCache::instance().getCardPictureLoaderCacheMethod() == + CardPictureLoaderCacheMethod::CacheMethod::NETWORK_CACHE; + + req.setAttribute(QNetworkRequest::CacheLoadControlAttribute, + useNetworkCache ? QNetworkRequest::AlwaysCache : QNetworkRequest::AlwaysNetwork); QNetworkReply *reply = networkManager->get(req); diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_settings.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_settings.cpp index d6b5aa213..7da0a9207 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_settings.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_settings.cpp @@ -1013,8 +1013,6 @@ DeckEditorSettingsPage::DeckEditorSettingsPage() urlLinkLabel.setTextInteractionFlags(Qt::LinksAccessibleByMouse); urlLinkLabel.setOpenExternalLinks(true); - connect(&clearDownloadedPicsButton, &QPushButton::clicked, this, - &DeckEditorSettingsPage::clearDownloadedPicsButtonClicked); connect(&resetDownloadURLs, &QPushButton::clicked, this, &DeckEditorSettingsPage::resetDownloadedURLsButtonClicked); auto *lpGeneralGrid = new QGridLayout; @@ -1066,49 +1064,11 @@ DeckEditorSettingsPage::DeckEditorSettingsPage() urlListLayout->addWidget(urlToolBar); urlListLayout->addWidget(urlList); - // pixmap cache - pixmapCacheEdit.setMinimum(PIXMAPCACHE_SIZE_MIN); - // 2047 is the max value to avoid overflowing of QPixmapCache::setCacheLimit(int size) - pixmapCacheEdit.setMaximum(PIXMAPCACHE_SIZE_MAX); - pixmapCacheEdit.setSingleStep(64); - pixmapCacheEdit.setValue(SettingsCache::instance().getPixmapCacheSize()); - pixmapCacheEdit.setSuffix(" MB"); - - networkCacheEdit.setMinimum(NETWORK_CACHE_SIZE_MIN); - networkCacheEdit.setMaximum(NETWORK_CACHE_SIZE_MAX); - networkCacheEdit.setSingleStep(1); - networkCacheEdit.setValue(SettingsCache::instance().getNetworkCacheSizeInMB()); - networkCacheEdit.setSuffix(" MB"); - - networkRedirectCacheTtlEdit.setMinimum(NETWORK_REDIRECT_CACHE_TTL_MIN); - networkRedirectCacheTtlEdit.setMaximum(NETWORK_REDIRECT_CACHE_TTL_MAX); - networkRedirectCacheTtlEdit.setSingleStep(1); - networkRedirectCacheTtlEdit.setValue(SettingsCache::instance().getRedirectCacheTtl()); - - auto networkCacheLayout = new QHBoxLayout; - networkCacheLayout->addStretch(); - networkCacheLayout->addWidget(&networkCacheLabel); - networkCacheLayout->addWidget(&networkCacheEdit); - - auto networkRedirectCacheLayout = new QHBoxLayout; - networkRedirectCacheLayout->addStretch(); - networkRedirectCacheLayout->addWidget(&networkRedirectCacheTtlLabel); - networkRedirectCacheLayout->addWidget(&networkRedirectCacheTtlEdit); - - auto pixmapCacheLayout = new QHBoxLayout; - pixmapCacheLayout->addStretch(); - pixmapCacheLayout->addWidget(&pixmapCacheLabel); - pixmapCacheLayout->addWidget(&pixmapCacheEdit); - // Top Layout lpGeneralGrid->addWidget(&picDownloadCheckBox, 0, 0); lpGeneralGrid->addWidget(&resetDownloadURLs, 0, 1); lpGeneralGrid->addLayout(urlListLayout, 1, 0, 1, 2); - lpGeneralGrid->addLayout(networkCacheLayout, 2, 1); - lpGeneralGrid->addLayout(networkRedirectCacheLayout, 3, 0); - lpGeneralGrid->addLayout(pixmapCacheLayout, 3, 1); - lpGeneralGrid->addWidget(&urlLinkLabel, 5, 0); - lpGeneralGrid->addWidget(&clearDownloadedPicsButton, 5, 1); + lpGeneralGrid->addWidget(&urlLinkLabel, 4, 0); // Spoiler Layout lpSpoilerGrid->addWidget(&mcDownloadSpoilersCheckBox, 0, 0); @@ -1123,12 +1083,6 @@ DeckEditorSettingsPage::DeckEditorSettingsPage() connect(&mcDownloadSpoilersCheckBox, &QCheckBox::toggled, &SettingsCache::instance(), &SettingsCache::setDownloadSpoilerStatus); connect(&mcDownloadSpoilersCheckBox, &QCheckBox::toggled, this, &DeckEditorSettingsPage::setSpoilersEnabled); - connect(&pixmapCacheEdit, qOverload(&QSpinBox::valueChanged), &SettingsCache::instance(), - &SettingsCache::setPixmapCacheSize); - connect(&networkCacheEdit, qOverload(&QSpinBox::valueChanged), &SettingsCache::instance(), - &SettingsCache::setNetworkCacheSizeInMB); - connect(&networkRedirectCacheTtlEdit, qOverload(&QSpinBox::valueChanged), &SettingsCache::instance(), - &SettingsCache::setNetworkRedirectCacheTtl); mpGeneralGroupBox = new QGroupBox; mpGeneralGroupBox->setLayout(lpGeneralGrid); @@ -1154,46 +1108,6 @@ void DeckEditorSettingsPage::resetDownloadedURLsButtonClicked() QMessageBox::information(this, tr("Success"), tr("Download URLs have been reset.")); } -void DeckEditorSettingsPage::clearDownloadedPicsButtonClicked() -{ - CardPictureLoader::clearNetworkCache(); - - // These are not used anymore, but we don't delete them automatically, so - // we should do it here lest we leave pictures hanging around on users' - // machines. - QString picsPath = SettingsCache::instance().getPicsPath() + "/downloadedPics/"; - QStringList dirs = QDir(picsPath).entryList(QDir::AllDirs | QDir::NoDotAndDotDot); - bool outerSuccessRemove = true; - for (const auto &dir : dirs) { - QString currentPath = picsPath + dir + "/"; - QStringList files = QDir(currentPath).entryList(QDir::Files); - bool innerSuccessRemove = true; - for (int j = 0; j < files.length(); j++) { - if (!QDir(currentPath).remove(files.at(j))) { - qInfo() << "Failed to remove " + currentPath.toUtf8() + files.at(j).toUtf8(); - outerSuccessRemove = false; - innerSuccessRemove = false; - } - qInfo() << "Removed " << currentPath << files.at(j); - } - - if (innerSuccessRemove) { - bool success = QDir(picsPath).rmdir(dir); - if (!success) { - qInfo() << "Failed to remove inner directory" << picsPath; - } else { - qInfo() << "Removed" << currentPath; - } - } - } - if (outerSuccessRemove) { - QMessageBox::information(this, tr("Success"), tr("Downloaded card pictures have been reset.")); - QDir(SettingsCache::instance().getPicsPath()).rmdir("downloadedPics"); - } else { - QMessageBox::critical(this, tr("Error"), tr("One or more downloaded card pictures could not be cleared.")); - } -} - void DeckEditorSettingsPage::actAddURL() { bool ok; @@ -1312,18 +1226,246 @@ void DeckEditorSettingsPage::retranslateUi() tr("Do not close settings until manual update is complete")); picDownloadCheckBox.setText(tr("Download card pictures on the fly")); urlLinkLabel.setText(QString("%2").arg(WIKI_CUSTOM_PIC_URL).arg(tr("How to add a custom URL"))); - clearDownloadedPicsButton.setText(tr("Delete Downloaded Images")); resetDownloadURLs.setText(tr("Reset Download URLs")); + updateNowButton->setText(tr("Update Spoilers")); + aAdd->setText(tr("Add New URL")); + aEdit->setText(tr("Edit URL")); + aRemove->setText(tr("Remove URL")); +} + +StorageSettingsPage::StorageSettingsPage() +{ + auto *lpNetworkCacheGrid = new QGridLayout; + auto *lpImageBackupGrid = new QGridLayout; + auto *lpPixmapCacheGrid = new QGridLayout; + + networkCacheExplainerLabel.setWordWrap(true); + imageBackupExplainerLabel.setWordWrap(true); + pixmapCacheExplainerLabel.setWordWrap(true); + + connect(&clearDownloadedPicsButton, &QPushButton::clicked, this, + &StorageSettingsPage::clearDownloadedPicsButtonClicked); + + connect(&clearPixmapCacheButton, &QPushButton::clicked, this, &StorageSettingsPage::clearPixmapCacheButtonClicked); + + // pixmap cache + pixmapCacheEdit.setMinimum(PIXMAPCACHE_SIZE_MIN); + // 2047 is the max value to avoid overflowing of QPixmapCache::setCacheLimit(int size) + pixmapCacheEdit.setMaximum(PIXMAPCACHE_SIZE_MAX); + pixmapCacheEdit.setSingleStep(64); + pixmapCacheEdit.setValue(SettingsCache::instance().getPixmapCacheSize()); + pixmapCacheEdit.setSuffix(" MB"); + + // Caching method + + cardPictureLoaderCacheMethodComboBox = new QComboBox; + for (auto method : CardPictureLoaderCacheMethod::methods()) { + cardPictureLoaderCacheMethodComboBox->addItem(method.displayName, static_cast(method.id)); + } + + int currentCacheMethod = static_cast(SettingsCache::instance().getCardPictureLoaderCacheMethod()); + + int currentIndex = cardPictureLoaderCacheMethodComboBox->findData(currentCacheMethod); + if (currentIndex >= 0) { + cardPictureLoaderCacheMethodComboBox->setCurrentIndex(currentIndex); + } + + connect(cardPictureLoaderCacheMethodComboBox, qOverload(&QComboBox::currentIndexChanged), this, + [this](int index) { + auto cacheMethod = static_cast( + cardPictureLoaderCacheMethodComboBox->itemData(index).toInt()); + + bool useNetworkCache = (cacheMethod == CardPictureLoaderCacheMethod::CacheMethod::NETWORK_CACHE); + + if (useNetworkCache) { + clearImageBackupsButtonClicked(); + } else { + clearDownloadedPicsButtonClicked(); + } + + mpNetworkCacheGroupBox->setEnabled(useNetworkCache); + mpImageBackupGroupBox->setEnabled(!useNetworkCache); + + SettingsCache::instance().setCardImageCacheMethod(cacheMethod); + }); + + // Network Cache + + networkCacheEdit.setMinimum(NETWORK_CACHE_SIZE_MIN); + networkCacheEdit.setMaximum(NETWORK_CACHE_SIZE_MAX); + networkCacheEdit.setSingleStep(1); + networkCacheEdit.setValue(SettingsCache::instance().getNetworkCacheSizeInMB()); + networkCacheEdit.setSuffix(" MB"); + + networkRedirectCacheTtlEdit.setMinimum(NETWORK_REDIRECT_CACHE_TTL_MIN); + networkRedirectCacheTtlEdit.setMaximum(NETWORK_REDIRECT_CACHE_TTL_MAX); + networkRedirectCacheTtlEdit.setSingleStep(1); + networkRedirectCacheTtlEdit.setValue(SettingsCache::instance().getRedirectCacheTtl()); + + // Image Backup + localCardImageStorageNamingSchemeComboBox = new QComboBox; + for (const auto &scheme : CardPictureLoaderLocalSchemes::exportSchemes()) { + localCardImageStorageNamingSchemeComboBox->addItem(scheme.displayName, static_cast(scheme.id)); + } + + int current = static_cast(SettingsCache::instance().getLocalCardImageStorageNamingScheme()); + + int index = localCardImageStorageNamingSchemeComboBox->findData(current); + if (index >= 0) { + localCardImageStorageNamingSchemeComboBox->setCurrentIndex(index); + } + + connect(localCardImageStorageNamingSchemeComboBox, qOverload(&QComboBox::currentIndexChanged), this, + [this](int index) { + auto scheme = static_cast( + localCardImageStorageNamingSchemeComboBox->itemData(index).toInt()); + SettingsCache::instance().setLocalCardImageStorageNamingScheme(scheme); + }); + + connect(&clearBackupsButton, &QPushButton::clicked, this, &StorageSettingsPage::clearImageBackupsButtonClicked); + + auto cacheMethodLayout = new QHBoxLayout; + cacheMethodLayout->addWidget(&cardPictureLoaderCacheMethodLabel); + cacheMethodLayout->addWidget(cardPictureLoaderCacheMethodComboBox); + + auto networkCacheLayout = new QHBoxLayout; + networkCacheLayout->addWidget(&clearDownloadedPicsButton); + networkCacheLayout->addStretch(); + networkCacheLayout->addWidget(&networkCacheLabel); + networkCacheLayout->addWidget(&networkCacheEdit); + + auto networkRedirectCacheLayout = new QHBoxLayout; + networkRedirectCacheLayout->addStretch(); + networkRedirectCacheLayout->addWidget(&networkRedirectCacheTtlLabel); + networkRedirectCacheLayout->addWidget(&networkRedirectCacheTtlEdit); + + auto pixmapCacheLayout = new QHBoxLayout; + pixmapCacheLayout->addWidget(&clearPixmapCacheButton); + pixmapCacheLayout->addStretch(); + pixmapCacheLayout->addWidget(&pixmapCacheLabel); + pixmapCacheLayout->addWidget(&pixmapCacheEdit); + + lpNetworkCacheGrid->addWidget(&networkCacheExplainerLabel, 0, 0); + lpNetworkCacheGrid->addLayout(networkCacheLayout, 1, 0); + lpNetworkCacheGrid->addLayout(networkRedirectCacheLayout, 2, 0); + + // Image Backup Layout + lpImageBackupGrid->addWidget(&imageBackupExplainerLabel, 0, 0, 1, 2); + lpImageBackupGrid->addWidget(&localCardImageStorageNamingSchemeLabel, 1, 0); + lpImageBackupGrid->addWidget(localCardImageStorageNamingSchemeComboBox, 1, 1); + lpImageBackupGrid->addWidget(&clearBackupsButton, 2, 0); + + lpPixmapCacheGrid->addWidget(&pixmapCacheExplainerLabel, 0, 0); + lpPixmapCacheGrid->addLayout(pixmapCacheLayout, 1, 0); + + connect(&pixmapCacheEdit, qOverload(&QSpinBox::valueChanged), &SettingsCache::instance(), + &SettingsCache::setPixmapCacheSize); + connect(&networkCacheEdit, qOverload(&QSpinBox::valueChanged), &SettingsCache::instance(), + &SettingsCache::setNetworkCacheSizeInMB); + connect(&networkRedirectCacheTtlEdit, qOverload(&QSpinBox::valueChanged), &SettingsCache::instance(), + &SettingsCache::setNetworkRedirectCacheTtl); + + mpCacheMethodGroupBox = new QGroupBox; + mpCacheMethodGroupBox->setLayout(cacheMethodLayout); + + mpNetworkCacheGroupBox = new QGroupBox; + mpNetworkCacheGroupBox->setLayout(lpNetworkCacheGrid); + + mpImageBackupGroupBox = new QGroupBox; + mpImageBackupGroupBox->setLayout(lpImageBackupGrid); + + mpPixmapCacheGroupBox = new QGroupBox; + mpPixmapCacheGroupBox->setLayout(lpPixmapCacheGrid); + + auto *lpMainLayout = new QVBoxLayout; + + lpMainLayout->addWidget(mpCacheMethodGroupBox); + lpMainLayout->addWidget(mpNetworkCacheGroupBox); + lpMainLayout->addWidget(mpImageBackupGroupBox); + lpMainLayout->addWidget(mpPixmapCacheGroupBox); + lpMainLayout->addStretch(); + + setLayout(lpMainLayout); + + bool useNetworkCache = SettingsCache::instance().getCardPictureLoaderCacheMethod() == + CardPictureLoaderCacheMethod::CacheMethod::NETWORK_CACHE; + + mpNetworkCacheGroupBox->setEnabled(useNetworkCache); + mpImageBackupGroupBox->setEnabled(!useNetworkCache); + + connect(&SettingsCache::instance(), &SettingsCache::langChanged, this, &StorageSettingsPage::retranslateUi); + retranslateUi(); +} + +void StorageSettingsPage::clearDownloadedPicsButtonClicked() +{ + CardPictureLoader::clearNetworkCache(); + CardPictureLoader::clearPixmapCache(); + QMessageBox::information(this, tr("Success"), tr("Cached card pictures have been reset.")); +} + +void StorageSettingsPage::clearImageBackupsButtonClicked() +{ + QString picsPath = SettingsCache::instance().getPicsPath() + "/downloadedPics"; + + QDir dir(picsPath); + bool success = dir.removeRecursively(); + + CardPictureLoader::clearPixmapCache(); + + if (success) { + QMessageBox::information(this, tr("Success"), tr("Downloaded card pictures have been reset.")); + } else { + QMessageBox::critical(this, tr("Error"), tr("One or more downloaded card pictures could not be cleared.")); + } +} + +void StorageSettingsPage::clearPixmapCacheButtonClicked() +{ + CardPictureLoader::clearPixmapCache(); + QMessageBox::information(this, tr("Success"), tr("In-memory (currently loaded) card pictures have been reset.")); +} + +void StorageSettingsPage::retranslateUi() +{ + cardPictureLoaderCacheMethodLabel.setText(tr("Card Picture Loader Caching Method:")); + + networkCacheExplainerLabel.setText( + tr("The network cache is the preferred way of storing images. Downloaded images " + "are stored here until the size of the cache exceeds the configured size. Cockatrice automatically monitors " + "this cache and deletes the least recently seen card images to ensure the cache does not exceed the " + "configured size.")); + imageBackupExplainerLabel.setText( + tr("Writing card images directly to a folder on your hard drive is another way " + "of storing images. This does not change how Cockatrice accesses or downloads " + "images. Cockatrice will NOT automatically monitor and clear this folder, so if you enable this option, it " + "is up to you to ensure sufficient available space. It should also be noted that if a provider outage " + "causes you to download the wrong picture (i.e. wrong printing) you will be stuck with it until you " + "manually delete the file, as opposed to using the network cache, which automatically rotates and thus " + "correct errors after a while.")); + pixmapCacheExplainerLabel.setText( + tr("This is the in-memory picture cache used by the application at runtime. It determines how much memory " + "(RAM) Cockatrice can use before it has to fetch card images from the hard disk again. Increasing this will " + "allow more card images to be displayed at once but shouldn't be necessary. Clearing this will make " + "Cockatrice reload all images from the network cache or the disk.")); + + clearDownloadedPicsButton.setText(tr("Delete Cached Images")); + clearBackupsButton.setText(tr("Delete Saved Images")); + clearPixmapCacheButton.setText(tr("Clear In-Memory Images")); + + mpCacheMethodGroupBox->setTitle(tr("Card Picture Loader Cache Method")); + mpNetworkCacheGroupBox->setTitle(tr("Network Cache")); + mpImageBackupGroupBox->setTitle(tr("Filesystem")); + mpPixmapCacheGroupBox->setTitle(tr("In-Memory Picture Cache")); + networkCacheLabel.setText(tr("Network Cache Size:")); networkCacheEdit.setToolTip(tr("On-disk cache for downloaded pictures")); networkRedirectCacheTtlLabel.setText(tr("Redirect Cache TTL:")); networkRedirectCacheTtlEdit.setToolTip(tr("How long cached redirects for urls are valid for.")); pixmapCacheLabel.setText(tr("Picture Cache Size:")); pixmapCacheEdit.setToolTip(tr("In-memory cache for pictures not currently on screen")); - updateNowButton->setText(tr("Update Spoilers")); - aAdd->setText(tr("Add New URL")); - aEdit->setText(tr("Edit URL")); - aRemove->setText(tr("Remove URL")); + localCardImageStorageNamingSchemeLabel.setText(tr("Naming scheme:")); + networkRedirectCacheTtlEdit.setSuffix(" " + tr("Day(s)")); } @@ -1803,6 +1945,7 @@ DlgSettings::DlgSettings(QWidget *parent) : QDialog(parent) pagesWidget->addWidget(makeScrollable(new AppearanceSettingsPage)); pagesWidget->addWidget(makeScrollable(new UserInterfaceSettingsPage)); pagesWidget->addWidget(new DeckEditorSettingsPage); + pagesWidget->addWidget(makeScrollable(new StorageSettingsPage)); pagesWidget->addWidget(new MessagesSettingsPage); pagesWidget->addWidget(new SoundSettingsPage); pagesWidget->addWidget(new ShortcutSettingsPage); @@ -1851,6 +1994,11 @@ void DlgSettings::createIcons() deckEditorButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); deckEditorButton->setIcon(QPixmap("theme:config/deckeditor")); + storageButton = new QListWidgetItem(contentsWidget); + storageButton->setTextAlignment(Qt::AlignHCenter); + storageButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + storageButton->setIcon(QPixmap("theme:config/storage")); + messagesButton = new QListWidgetItem(contentsWidget); messagesButton->setTextAlignment(Qt::AlignHCenter); messagesButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); @@ -1975,6 +2123,7 @@ void DlgSettings::retranslateUi() generalButton->setText(tr("General")); appearanceButton->setText(tr("Appearance")); userInterfaceButton->setText(tr("User Interface")); + storageButton->setText(tr("Storage")); deckEditorButton->setText(tr("Card Sources")); messagesButton->setText(tr("Chat")); soundButton->setText(tr("Sound")); diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_settings.h b/cockatrice/src/interface/widgets/dialogs/dlg_settings.h index b655a30bc..42268e997 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_settings.h +++ b/cockatrice/src/interface/widgets/dialogs/dlg_settings.h @@ -213,11 +213,9 @@ private slots: void actAddURL(); void actRemoveURL(); void actEditURL(); - void clearDownloadedPicsButtonClicked(); void resetDownloadedURLsButtonClicked(); private: - QPushButton clearDownloadedPicsButton; QPushButton resetDownloadURLs; QLabel urlLinkLabel; QCheckBox picDownloadCheckBox; @@ -227,18 +225,51 @@ private: QLabel msDownloadSpoilersLabel; QGroupBox *mpGeneralGroupBox; QGroupBox *mpSpoilerGroupBox; + QLineEdit *mpSpoilerSavePathLineEdit; QLabel mcSpoilerSaveLabel; QLabel lastUpdatedLabel; QLabel infoOnSpoilersLabel; QPushButton *mpSpoilerPathButton; QPushButton *updateNowButton; +}; + +class StorageSettingsPage : public AbstractSettingsPage +{ + Q_OBJECT +public: + StorageSettingsPage(); + void retranslateUi() override; + +private slots: + void clearDownloadedPicsButtonClicked(); + void clearImageBackupsButtonClicked(); + void clearPixmapCacheButtonClicked(); + +private: + QPushButton clearDownloadedPicsButton; + QPushButton clearBackupsButton; + QPushButton clearPixmapCacheButton; + + QGroupBox *mpCacheMethodGroupBox; + QGroupBox *mpNetworkCacheGroupBox; + QGroupBox *mpImageBackupGroupBox; + QGroupBox *mpPixmapCacheGroupBox; + + QLabel networkCacheExplainerLabel; + QLabel imageBackupExplainerLabel; + QLabel pixmapCacheExplainerLabel; + + QLabel cardPictureLoaderCacheMethodLabel; + QComboBox *cardPictureLoaderCacheMethodComboBox; QLabel networkCacheLabel; QSpinBox networkCacheEdit; QLabel networkRedirectCacheTtlLabel; QSpinBox networkRedirectCacheTtlEdit; QSpinBox pixmapCacheEdit; QLabel pixmapCacheLabel; + QLabel localCardImageStorageNamingSchemeLabel; + QComboBox *localCardImageStorageNamingSchemeComboBox; }; class MessagesSettingsPage : public AbstractSettingsPage @@ -353,8 +384,8 @@ private slots: private: QListWidget *contentsWidget; QStackedWidget *pagesWidget; - QListWidgetItem *generalButton, *appearanceButton, *userInterfaceButton, *deckEditorButton, *messagesButton, - *soundButton, *shortcutsButton; + QListWidgetItem *generalButton, *appearanceButton, *userInterfaceButton, *deckEditorButton, *storageButton, + *messagesButton, *soundButton, *shortcutsButton; void createIcons(); void retranslateUi(); From 989a5be23b948fe2fafbd126838f30cf2712c87b Mon Sep 17 00:00:00 2001 From: tooomm Date: Sat, 16 May 2026 20:26:37 +0200 Subject: [PATCH 12/51] Enable `RemoveSemicolon` & update format.sh (#6896) * Update .clang-format * Add libs that got added in the meantime * Use libcockatrice_* --- .clang-format | 20 +++++++++----------- format.sh | 8 +------- 2 files changed, 10 insertions(+), 18 deletions(-) diff --git a/.clang-format b/.clang-format index 4be096155..1db97481a 100644 --- a/.clang-format +++ b/.clang-format @@ -3,7 +3,9 @@ AccessModifierOffset: -4 ColumnLimit: 120 --- Language: Cpp -BreakBeforeBraces: Custom +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortFunctionsOnASingleLine: None +BinPackParameters: false BraceWrapping: AfterClass: true AfterControlStatement: false @@ -18,18 +20,14 @@ BraceWrapping: SplitEmptyFunction: true SplitEmptyRecord: true SplitEmptyNamespace: true -AllowShortFunctionsOnASingleLine: None -BinPackParameters: false -AllowAllParametersOfDeclarationOnNextLine: false -IndentCaseLabels: true -PointerAlignment: Right -SortIncludes: true +BreakBeforeBraces: Custom IncludeBlocks: Regroup -StatementAttributeLikeMacros: [emit] -# requires clang-format 15 +IndentCaseLabels: true InsertBraces: true -# requires clang-format 16 -# RemoveSemicolon: true +PointerAlignment: Right +RemoveSemicolon: true +SortIncludes: true +StatementAttributeLikeMacros: [emit] --- Language: Proto AllowShortFunctionsOnASingleLine: None diff --git a/format.sh b/format.sh index f8c183dfc..c43f537f5 100755 --- a/format.sh +++ b/format.sh @@ -14,13 +14,7 @@ cd "${BASH_SOURCE%/*}/" || exit 2 # could not find path, this could happen with # defaults include=("cockatrice/src" \ -"libcockatrice_card" \ -"libcockatrice_deck_list" \ -"libcockatrice_network" \ -"libcockatrice_protocol" \ -"libcockatrice_rng" \ -"libcockatrice_settings" \ -"libcockatrice_utility" \ +libcockatrice_* \ "oracle/src" \ "servatrice/src" \ "tests") From 117ea543c59de1ae142d71598e5ea3c64a2db572 Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Sun, 17 May 2026 10:08:00 +0200 Subject: [PATCH 13/51] [App/Theme] Palette Editor (#6877) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [App/Theme] Palette Editor Took 1 minute Took 1 hour 47 minutes Took 6 seconds Took 3 minutes Took 5 minutes Took 3 minutes * Add oracle, add palette files and configs. Took 10 minutes * Fix a stupid include mistake, thanks IDE Took 3 minutes Took 20 seconds * Includes. Took 4 minutes * Fix ampersand not displaying correctly. Took 14 minutes * Longer variable names. Took 10 minutes Took 5 seconds * Change ampersand everywhere Took 23 seconds * Doxygen properly. Took 1 minute * Remove namespace, fold I/O into structs. Took 12 minutes * Remove namespace, fold I/O into structs. Took 33 seconds * Alphabetize. Took 35 seconds * Lint. Took 49 seconds * Add a combo box to quick switch settings. Took 19 minutes --------- Co-authored-by: Lukas Brübach --- cockatrice/CMakeLists.txt | 6 + .../interface/palette_editor/color_button.cpp | 72 ++++ .../interface/palette_editor/color_button.h | 30 ++ .../palette_editor/palette_editor_dialog.cpp | 326 +++++++++++++++ .../palette_editor/palette_editor_dialog.h | 68 ++++ .../palette_editor/palette_generator.cpp | 200 +++++++++ .../palette_editor/palette_generator.h | 16 + .../palette_editor/palette_grid_widget.cpp | 179 +++++++++ .../palette_editor/palette_grid_widget.h | 38 ++ .../palette_editor/quick_setup_panel.cpp | 99 +++++ .../palette_editor/quick_setup_panel.h | 94 +++++ cockatrice/src/interface/theme_config.cpp | 267 ++++++++++++ cockatrice/src/interface/theme_config.h | 37 ++ cockatrice/src/interface/theme_manager.cpp | 380 +++++++----------- cockatrice/src/interface/theme_manager.h | 25 +- .../widgets/dialogs/dlg_settings.cpp | 53 ++- .../interface/widgets/dialogs/dlg_settings.h | 4 + .../themes/Default/palette-default-dark.toml | 63 +++ cockatrice/themes/Default/theme.cfg | 5 + .../themes/Fusion/palette-default-dark.toml | 69 ++++ .../themes/Fusion/palette-default-light.toml | 69 ++++ cockatrice/themes/Fusion/theme.cfg | 5 + oracle/CMakeLists.txt | 1 + 23 files changed, 1874 insertions(+), 232 deletions(-) create mode 100644 cockatrice/src/interface/palette_editor/color_button.cpp create mode 100644 cockatrice/src/interface/palette_editor/color_button.h create mode 100644 cockatrice/src/interface/palette_editor/palette_editor_dialog.cpp create mode 100644 cockatrice/src/interface/palette_editor/palette_editor_dialog.h create mode 100644 cockatrice/src/interface/palette_editor/palette_generator.cpp create mode 100644 cockatrice/src/interface/palette_editor/palette_generator.h create mode 100644 cockatrice/src/interface/palette_editor/palette_grid_widget.cpp create mode 100644 cockatrice/src/interface/palette_editor/palette_grid_widget.h create mode 100644 cockatrice/src/interface/palette_editor/quick_setup_panel.cpp create mode 100644 cockatrice/src/interface/palette_editor/quick_setup_panel.h create mode 100644 cockatrice/src/interface/theme_config.cpp create mode 100644 cockatrice/src/interface/theme_config.h create mode 100644 cockatrice/themes/Default/palette-default-dark.toml create mode 100644 cockatrice/themes/Default/theme.cfg create mode 100644 cockatrice/themes/Fusion/palette-default-dark.toml create mode 100644 cockatrice/themes/Fusion/palette-default-light.toml create mode 100644 cockatrice/themes/Fusion/theme.cfg diff --git a/cockatrice/CMakeLists.txt b/cockatrice/CMakeLists.txt index 1017f1247..a4e357f60 100644 --- a/cockatrice/CMakeLists.txt +++ b/cockatrice/CMakeLists.txt @@ -130,7 +130,13 @@ set(cockatrice_SOURCES src/interface/layouts/overlap_layout.cpp src/interface/widgets/utility/line_edit_completer.cpp src/interface/pixel_map_generator.cpp + src/interface/theme_config.cpp src/interface/theme_manager.cpp + src/interface/palette_editor/color_button.cpp + src/interface/palette_editor/palette_generator.cpp + src/interface/palette_editor/quick_setup_panel.cpp + src/interface/palette_editor/palette_grid_widget.cpp + src/interface/palette_editor/palette_editor_dialog.cpp src/interface/widgets/cards/additional_info/color_identity_widget.cpp src/interface/widgets/cards/additional_info/mana_cost_widget.cpp src/interface/widgets/cards/additional_info/mana_symbol_widget.cpp diff --git a/cockatrice/src/interface/palette_editor/color_button.cpp b/cockatrice/src/interface/palette_editor/color_button.cpp new file mode 100644 index 000000000..e1a490d20 --- /dev/null +++ b/cockatrice/src/interface/palette_editor/color_button.cpp @@ -0,0 +1,72 @@ +#include "color_button.h" + +#include +#include + +ColorButton::ColorButton(QWidget *parent) : QToolButton(parent) +{ + setFixedSize(52, 24); + setCursor(Qt::PointingHandCursor); + setToolTip(tr("Click to pick a color")); + connect(this, &QToolButton::clicked, this, &ColorButton::pickColor); +} + +void ColorButton::setColor(const QColor &c) +{ + if (color == c) { + return; + } + color = c; + updateSwatch(); + emit colorChanged(c); +} + +void ColorButton::pickColor() +{ + QColor chosen = QColorDialog::getColor(color, this, tr("Pick colour"), QColorDialog::ShowAlphaChannel); + if (chosen.isValid()) { + setColor(chosen); + } +} + +void ColorButton::updateSwatch() +{ + QPixmap pixmap(size() * devicePixelRatioF()); + pixmap.setDevicePixelRatio(devicePixelRatioF()); + pixmap.fill(Qt::transparent); + QPainter painter(&pixmap); + painter.setRenderHint(QPainter::Antialiasing); + + // Checkerboard for alpha + const int cellSize = 4; + for (int y = 0; y < height(); y += cellSize) { + for (int x = 0; x < width(); x += cellSize) { + painter.fillRect(x, y, cellSize, cellSize, + ((x / cellSize + y / cellSize) % 2) ? QColor(180, 180, 180) : Qt::white); + } + } + + // Color fill + painter.setPen(Qt::NoPen); + painter.setBrush(color); + painter.drawRoundedRect(QRectF(0.5, 0.5, width() - 1, height() - 1), 3, 3); + + // Border + QColor border = palette().color(QPalette::Shadow); + border.setAlpha(180); + painter.setPen(QPen(border, 1)); + painter.setBrush(Qt::NoBrush); + painter.drawRoundedRect(QRectF(0.5, 0.5, width() - 1, height() - 1), 3, 3); + + // Hex label — black or white for contrast + int luma = 0.299 * color.red() + 0.587 * color.green() + 0.114 * color.blue(); + painter.setPen((luma > 128 && color.alpha() > 80) ? QColor(0, 0, 0, 180) : QColor(255, 255, 255, 200)); + QFont f = font(); + f.setPixelSize(8); + painter.setFont(f); + painter.drawText(rect(), Qt::AlignCenter, color.name().toUpper()); + + setIcon(QIcon(pixmap)); + setIconSize(size()); + setText({}); +} \ No newline at end of file diff --git a/cockatrice/src/interface/palette_editor/color_button.h b/cockatrice/src/interface/palette_editor/color_button.h new file mode 100644 index 000000000..4b139ef68 --- /dev/null +++ b/cockatrice/src/interface/palette_editor/color_button.h @@ -0,0 +1,30 @@ +#ifndef COCKATRICE_COLOR_BUTTON_H +#define COCKATRICE_COLOR_BUTTON_H + +#include +#include + +class ColorButton : public QToolButton +{ + Q_OBJECT +public: + explicit ColorButton(QWidget *parent = nullptr); + + QColor getColor() const + { + return color; + } + void setColor(const QColor &c); + +signals: + void colorChanged(const QColor &color); + +private slots: + void pickColor(); + +private: + void updateSwatch(); + QColor color; +}; + +#endif // COCKATRICE_COLOR_BUTTON_H \ No newline at end of file diff --git a/cockatrice/src/interface/palette_editor/palette_editor_dialog.cpp b/cockatrice/src/interface/palette_editor/palette_editor_dialog.cpp new file mode 100644 index 000000000..1b9be1dd4 --- /dev/null +++ b/cockatrice/src/interface/palette_editor/palette_editor_dialog.cpp @@ -0,0 +1,326 @@ +#include "palette_editor_dialog.h" + +#include "../theme_manager.h" +#include "palette_generator.h" +#include "palette_grid_widget.h" +#include "quick_setup_panel.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +PaletteEditorDialog::PaletteEditorDialog(const QString &_themeDirPath, const QString &_themeName, QWidget *parent) + : QDialog(parent), themeDirPath(_themeDirPath), themeName(_themeName) +{ + setMinimumSize(740, 220); + setupUi(); + + // Load both scheme configs upfront so switching is instant + loadSchemes(); + + loadedScheme = themeManager->isDarkMode(themeDirPath) ? "Dark" : "Light"; + + schemeComboBox->blockSignals(true); + schemeComboBox->setCurrentText(loadedScheme); + schemeComboBox->blockSignals(false); + + paletteGrid->loadPalette(workingConfig[loadedScheme]); + seedAccentFromScheme(loadedScheme); + + retranslateUi(); +} + +void PaletteEditorDialog::setupUi() +{ + auto *root = new QVBoxLayout(this); + root->setSpacing(0); + root->setContentsMargins(0, 0, 0, 0); + + // Header + header = new QWidget; + header->setAutoFillBackground(true); + { + QPalette hp = header->palette(); + hp.setColor(QPalette::Window, qApp->palette().color(QPalette::Window).darker(108)); + header->setPalette(hp); + } + auto *headerLayout = new QHBoxLayout(header); + headerLayout->setContentsMargins(12, 8, 12, 8); + + titleLabel = new QLabel(this); + titleLabel->setTextFormat(Qt::RichText); + + editingLabel = new QLabel(this); + + schemeComboBox = new QComboBox; + schemeComboBox->addItems({"Light", "Dark"}); + schemeComboBox->setFixedWidth(90); + + headerLayout->addWidget(titleLabel); + headerLayout->addStretch(); + headerLayout->addWidget(editingLabel); + headerLayout->addWidget(schemeComboBox); + root->addWidget(header); + + auto makeSeparator = [&]() { + auto *sep = new QFrame; + sep->setFrameShape(QFrame::HLine); + sep->setFrameShadow(QFrame::Plain); + sep->setFixedHeight(1); + return sep; + }; + + root->addWidget(makeSeparator()); + + // Quick Setup panel + quickSetupPanel = new QuickSetupPanel; + quickSetupPanel->setAutoFillBackground(true); + + QPalette sp = quickSetupPanel->palette(); + sp.setColor(QPalette::Window, qApp->palette().color(QPalette::Window).darker(102)); + quickSetupPanel->setPalette(sp); + + root->addWidget(quickSetupPanel); + root->addWidget(makeSeparator()); + + // Toggle button — acts as a section header for the advanced area + paletteGridToggleButton = new QPushButton(this); + paletteGridToggleButton->setCheckable(true); + paletteGridToggleButton->setChecked(false); + paletteGridToggleButton->setFlat(true); + paletteGridToggleButton->setStyleSheet("QPushButton { text-align: left; padding: 5px 12px; font-weight: bold; }" + "QPushButton:checked { }"); + root->addWidget(paletteGridToggleButton); + + // Separator + grid start hidden; revealed by the toggle + paletteGridSeparator = makeSeparator(); + paletteGridSeparator->setVisible(false); + root->addWidget(paletteGridSeparator); + + paletteGrid = new PaletteGridWidget; + paletteGrid->setVisible(false); + root->addWidget(paletteGrid, 1); + + // Footer + root->addWidget(makeSeparator()); + footer = new QWidget; + footer->setAutoFillBackground(true); + { + QPalette fp = footer->palette(); + fp.setColor(QPalette::Window, qApp->palette().color(QPalette::Window).darker(104)); + footer->setPalette(fp); + } + auto *footerLayout = new QHBoxLayout(footer); + footerLayout->setContentsMargins(12, 8, 12, 8); + + revertButton = new QPushButton(this); + + buttonBox = new QDialogButtonBox; + resetBtn = buttonBox->addButton(tr("Reset"), QDialogButtonBox::ResetRole); + applyBtn = buttonBox->addButton(tr("Apply"), QDialogButtonBox::ApplyRole); + saveBtn = buttonBox->addButton(tr("Save && Apply"), QDialogButtonBox::AcceptRole); + closeBtn = buttonBox->addButton(QDialogButtonBox::Close); + + footerLayout->addWidget(revertButton); + footerLayout->addStretch(); + footerLayout->addWidget(buttonBox); + root->addWidget(footer); + + // Connections + connect(schemeComboBox, &QComboBox::currentTextChanged, this, &PaletteEditorDialog::onSchemeChanged); + connect(quickSetupPanel, &QuickSetupPanel::generateRequested, this, &PaletteEditorDialog::onGenerateFromAccent); + connect(revertButton, &QPushButton::clicked, this, &PaletteEditorDialog::onRevertToDefault); + connect(resetBtn, &QPushButton::clicked, this, &PaletteEditorDialog::onReset); + connect(applyBtn, &QPushButton::clicked, this, &PaletteEditorDialog::onApply); + connect(saveBtn, &QPushButton::clicked, this, &PaletteEditorDialog::onSave); + connect(closeBtn, &QPushButton::clicked, this, &QDialog::reject); + + connect(paletteGridToggleButton, &QPushButton::toggled, this, [this](bool open) { + paletteGridToggleButton->setText(open ? tr("▼ Edit Palette") : tr("▶ Edit Palette")); + paletteGridSeparator->setVisible(open); + paletteGrid->setVisible(open); + + if (open) { + setMinimumHeight(680); + resize(width(), 680); + } else { + setMinimumHeight(220); + adjustSize(); // shrinks to fit just the visible content + } + }); +} + +void PaletteEditorDialog::retranslateUi() +{ + setWindowTitle(tr("Palette Editor — %1").arg(themeName)); + titleLabel->setText(tr("Palette Editor  ·  %1").arg(themeName)); + + // Revert button only makes sense when the theme ships default palette files + const bool hasDefault = PaletteConfig::fromDefault(themeDirPath, "Light").hasPalette() || + PaletteConfig::fromDefault(themeDirPath, "Dark").hasPalette(); + revertButton->setEnabled(hasDefault); + if (!hasDefault) { + revertButton->setToolTip(tr("This theme ships no default palette files")); + } else { + revertButton->setToolTip(tr("Replace current colours with the theme author's defaults")); + } + + schemeComboBox->setToolTip(tr("Switch between the light and dark palette files")); + editingLabel->setText(tr("Editing:")); + paletteGridToggleButton->setText(tr("▶ Edit Palette")); + paletteGridToggleButton->setToolTip(tr("Show or hide the per-role colour grid for manual tweaks")); + revertButton->setText(tr("↺ Revert to theme default")); + + resetBtn->setText(tr("Reset")); + applyBtn->setText(tr("Apply")); + saveBtn->setText(tr("Save && Apply")); + resetBtn->setToolTip(tr("Discard unsaved edits and restore the last saved palette")); + applyBtn->setToolTip(tr("Preview this palette without saving to disk")); + saveBtn->setToolTip(tr("Write palette-%1.toml and reload the theme").arg(loadedScheme.toLower())); + + if (themeDirPath.isEmpty()) { + saveBtn->setEnabled(false); + saveBtn->setToolTip(tr("Cannot save: this theme has no directory on disk")); + } +} + +void PaletteEditorDialog::loadSchemes() +{ + const QStringList schemes = {"Light", "Dark"}; + for (const QString &scheme : schemes) { + PaletteConfig cfg = PaletteConfig::fromScheme(themeDirPath, scheme); + + if (!cfg.hasPalette()) { + cfg = PaletteConfig::fromDefault(themeDirPath, scheme); + } + + if (!cfg.hasPalette()) { + const QPalette appPal = qApp->palette(); + for (auto group : {QPalette::Active, QPalette::Disabled, QPalette::Inactive}) { + for (int i = 0; i < QPalette::NColorRoles; ++i) { + auto role = static_cast(i); + if (role != QPalette::NoRole) { + cfg.colors[group][role] = appPal.color(group, role); + } + } + } + } + savedConfig[scheme] = cfg; + workingConfig[scheme] = cfg; + } +} + +void PaletteEditorDialog::seedAccentFromScheme(const QString &scheme) +{ + QColor seed = workingConfig.value(scheme).colors.value(QPalette::Active).value(QPalette::Highlight); + if (seed.isValid()) { + quickSetupPanel->setAccentColor(seed); + } +} + +void PaletteEditorDialog::onSchemeChanged(const QString &scheme) +{ + // Snapshot unsaved edits for the scheme we're leaving + if (!loadedScheme.isEmpty()) { + workingConfig[loadedScheme] = paletteGrid->currentPaletteConfig(); + } + + loadedScheme = scheme; + paletteGrid->loadPalette(workingConfig.value(scheme)); + seedAccentFromScheme(scheme); + onApply(); +} + +void PaletteEditorDialog::onGenerateFromAccent(const QColor &accent, int intensity) +{ + PaletteConfig cfg = PaletteGenerator::fromAccent(accent, intensity, loadedScheme); + workingConfig[loadedScheme] = cfg; + paletteGrid->loadPalette(cfg); +} + +void PaletteEditorDialog::onApply() +{ + themeManager->previewPalette(paletteGrid->currentPaletteConfig(), loadedScheme); +} + +void PaletteEditorDialog::onSave() +{ + if (loadedScheme.isEmpty()) { + return; + } + + PaletteConfig cfg = paletteGrid->currentPaletteConfig(); + + if (!ThemeManager::savePaletteConfig(themeDirPath, loadedScheme, cfg)) { + QMessageBox::warning(this, tr("Save failed"), + tr("Could not write %1 to:\n%2").arg(PaletteConfig::fileName(loadedScheme), themeDirPath)); + return; + } + + ThemeConfig globalCfg = ThemeConfig::fromThemeDir(themeDirPath); + globalCfg.colorScheme = loadedScheme; + globalCfg.save(themeDirPath); + + savedConfig[loadedScheme] = cfg; + workingConfig[loadedScheme] = cfg; + themeManager->reloadCurrentTheme(); + accept(); +} + +void PaletteEditorDialog::onReset() +{ + workingConfig[loadedScheme] = savedConfig[loadedScheme]; + paletteGrid->loadPalette(savedConfig[loadedScheme]); +} + +void PaletteEditorDialog::onRevertToDefault() +{ + PaletteConfig def = PaletteConfig::fromDefault(themeDirPath, loadedScheme); + if (!def.hasPalette()) { + QMessageBox::information(this, tr("No default found"), + tr("No default palette file found for the \"%1\" scheme.").arg(loadedScheme)); + return; + } + workingConfig[loadedScheme] = def; + paletteGrid->loadPalette(def); +} + +void PaletteEditorDialog::changeEvent(QEvent *e) +{ + if (e->type() == QEvent::PaletteChange) { + QTimer::singleShot(0, this, &PaletteEditorDialog::refreshChromePalettes); + } + + QDialog::changeEvent(e); +} + +void PaletteEditorDialog::refreshChromePalettes() +{ + const QPalette base = qApp->palette(); + + if (header) { + QPalette hp = header->palette(); + hp.setColor(QPalette::Window, base.color(QPalette::Window).darker(108)); + header->setPalette(hp); + header->update(); + } + if (footer) { + QPalette fp = footer->palette(); + fp.setColor(QPalette::Window, base.color(QPalette::Window).darker(104)); + footer->setPalette(fp); + footer->update(); + } + if (quickSetupPanel) { + QPalette sp = quickSetupPanel->palette(); + sp.setColor(QPalette::Window, base.color(QPalette::Window).darker(102)); + quickSetupPanel->setPalette(sp); + quickSetupPanel->update(); + } +} diff --git a/cockatrice/src/interface/palette_editor/palette_editor_dialog.h b/cockatrice/src/interface/palette_editor/palette_editor_dialog.h new file mode 100644 index 000000000..cec4c1700 --- /dev/null +++ b/cockatrice/src/interface/palette_editor/palette_editor_dialog.h @@ -0,0 +1,68 @@ +#ifndef COCKATRICE_PALETTE_EDITOR_DIALOG_H +#define COCKATRICE_PALETTE_EDITOR_DIALOG_H + +#include "../theme_config.h" + +#include +#include +#include + +class QLabel; +class QComboBox; +class QDialogButtonBox; +class QPushButton; +class PaletteGridWidget; +class QuickSetupPanel; + +class PaletteEditorDialog : public QDialog +{ + Q_OBJECT +public: + explicit PaletteEditorDialog(const QString &themeDirPath, const QString &themeName, QWidget *parent = nullptr); + void loadSchemes(); + +private slots: + void onSave(); + void onApply(); + void onReset(); + void onRevertToDefault(); + void onSchemeChanged(const QString &scheme); + void onGenerateFromAccent(const QColor &accent, int intensity); + +private: + void setupUi(); + void retranslateUi(); + void refreshChromePalettes(); + void loadScheme(const QString &scheme); // snapshot current, switch, load + void seedAccentFromScheme(const QString &scheme); + + // Sub-widgets + QWidget *header; + QLabel *titleLabel; + QLabel *editingLabel; + QuickSetupPanel *quickSetupPanel = nullptr; + PaletteGridWidget *paletteGrid = nullptr; + QPushButton *paletteGridToggleButton = nullptr; + QFrame *paletteGridSeparator = nullptr; + QWidget *footer; + QComboBox *schemeComboBox = nullptr; + QDialogButtonBox *buttonBox = nullptr; + QPushButton *resetBtn = nullptr; + QPushButton *applyBtn = nullptr; + QPushButton *saveBtn = nullptr; + QPushButton *closeBtn = nullptr; + QPushButton *revertButton = nullptr; + + // State + QString themeDirPath; + QString themeName; + QString loadedScheme; + + QMap workingConfig; + QMap savedConfig; + +protected: + void changeEvent(QEvent *e) override; +}; + +#endif // COCKATRICE_PALETTE_EDITOR_DIALOG_H \ No newline at end of file diff --git a/cockatrice/src/interface/palette_editor/palette_generator.cpp b/cockatrice/src/interface/palette_editor/palette_generator.cpp new file mode 100644 index 000000000..d30dd14f1 --- /dev/null +++ b/cockatrice/src/interface/palette_editor/palette_generator.cpp @@ -0,0 +1,200 @@ +#include "palette_generator.h" + +#include + +// ════════════════════════════════════════════════════════════════════════════ +// PaletteGenerator::fromAccent +// +// Three intensity bands: +// 0–30 Subtle — Highlight / links / BrightText take on the hue; +// backgrounds stay neutral grey. +// 30–70 Accented — Button, ToolTipBase, AlternateBase, shading tint in; +// backgrounds get a faint hue wash. +// 70–100 Chromatic— Window and Base pick up real saturation; the whole +// application reads as that colour, text stays readable. +// +// Key principles: +// • Quadratic saturation curve: low end feels truly subtle, top is vivid. +// • Each role has its own saturation ceiling; buttons always pop above window. +// • Base stays near-white / near-black regardless of intensity for legibility. +// • Button text contrast is computed from the real button color, not assumed. +// • Tooltip blends from classic yellow to hue-tinted above intensity ~25. +// • 3D shading ladder (Light→Shadow) carries the same hue for coherence. +// • Disabled: text → mid-gray, backgrounds → match Window. +// • Inactive Highlight fades to a near-bg tone so it doesn't compete. +// ════════════════════════════════════════════════════════════════════════════ + +namespace PaletteGenerator +{ + +PaletteConfig fromAccent(const QColor &accent, int intensity, const QString &scheme) +{ + PaletteConfig cfg; + const bool dark = scheme.compare("Dark", Qt::CaseInsensitive) == 0; + const double t = intensity / 100.0; // 0.0 – 1.0 + + int h = accent.hslHue(); + const bool achromatic = (h < 0); + if (achromatic) { + h = 0; + } + + // Saturation budgets + // Quadratic ease-in means the subtle end is genuinely subtle and the + // full end is bold without being garish. + auto sat = [&](double maxSat) -> int { + if (achromatic) { + return 0; + } + return qRound(maxSat * t * t); + }; + + const int satWindow = sat(dark ? 80.0 : 90.0); + const int satBase = sat(dark ? 25.0 : 20.0); // text areas stay near-white/black + const int satAlt = sat(dark ? 90.0 : 100.0); + const int satButton = sat(dark ? 120.0 : 130.0); // buttons pop above the bg + const int satTooltip = sat(dark ? 90.0 : 80.0); + const int satHighlight = achromatic ? 0 : qRound(accent.hslSaturation() * (0.45 + 0.55 * t)); + const int satShadeHi = sat(dark ? 60.0 : 50.0); // Light / Midlight + const int satShadeLo = sat(dark ? 90.0 : 70.0); // Mid / Dark + + // Per-role lightness + // Nudge lightness slightly as saturation rises to compensate for the + // Helmholtz-Kohlrausch effect (saturated colors look lighter/heavier). + const int winL = dark ? (28 + qRound(t * 8)) : (242 - qRound(t * 6)); + const int baseL = dark ? (43 + qRound(t * 6)) : 252; + const int altL = dark ? (36 + qRound(t * 9)) : (234 - qRound(t * 5)); + const int btnL = dark ? (56 + qRound(t * 10)) : (230 - qRound(t * 10)); + const int tipL = dark ? (52 + qRound(t * 8)) : (248 - qRound(t * 6)); + + // Highlight color + QColor hl; + if (achromatic) { + hl = dark ? QColor(105, 105, 105) : QColor(95, 95, 95); + } else if (dark) { + int L = qBound(105, accent.lightness() + qRound(45.0 * (1.0 - t)), 215); + hl = QColor::fromHsl(h, qMin(255, satHighlight), L); + } else { + int L = qBound(50, accent.lightness() - qRound(25.0 * t), 180); + hl = QColor::fromHsl(h, qMin(255, satHighlight), L); + } + const double hlLuma = 0.299 * hl.red() + 0.587 * hl.green() + 0.114 * hl.blue(); + const QColor hlText = (hlLuma > 135) ? Qt::black : Qt::white; + + // Local helpers + using CR = QPalette::ColorRole; + using CG = QPalette::ColorGroup; + + auto hsl = [&](int lightness, int s) -> QColor { + return QColor::fromHsl(h, qBound(0, s, 255), qBound(0, lightness, 255)); + }; + + auto textOn = [](const QColor &bg) -> QColor { + double luma = 0.299 * bg.red() + 0.587 * bg.green() + 0.114 * bg.blue(); + return (luma > 135) ? Qt::black : Qt::white; + }; + + auto set3 = [&](CR role, QColor active, QColor disabled, QColor inactive) { + cfg.colors[CG::Active][role] = active; + cfg.colors[CG::Disabled][role] = disabled; + cfg.colors[CG::Inactive][role] = inactive; + }; + + auto setAll = [&](CR role, QColor c) { set3(role, c, c, c); }; + + // Tooltip: blend classic yellow → hue-tinted above t≈0.20 + QColor bg_tip; + if (achromatic || t < 0.20) { + bg_tip = QColor(255, 255, 220); + } else { + QColor tinted = hsl(tipL, satTooltip); + double blend = qMin(1.0, (t - 0.20) / 0.55); + QColor yellow(255, 255, 220); + bg_tip = QColor(qRound(yellow.red() * (1.0 - blend) + tinted.red() * blend), + qRound(yellow.green() * (1.0 - blend) + tinted.green() * blend), + qRound(yellow.blue() * (1.0 - blend) + tinted.blue() * blend)); + } + + // Backgrounds + const QColor bg_win = hsl(winL, satWindow); + const QColor bg_base = hsl(baseL, satBase); + const QColor bg_alt = hsl(altL, satAlt); + const QColor bg_btn = hsl(btnL, satButton); + + set3(CR::Window, bg_win, bg_win, bg_win); + set3(CR::Base, bg_base, bg_win, bg_base); + set3(CR::AlternateBase, bg_alt, bg_alt, bg_alt); + set3(CR::Button, bg_btn, bg_win, bg_btn); + set3(CR::ToolTipBase, bg_tip, bg_tip, bg_tip); + + // Foreground text + const QColor winText = dark ? Qt::white : Qt::black; + const QColor disText = dark ? QColor(157, 157, 157) : QColor(120, 120, 120); + const QColor disBtnText = dark ? QColor(120, 120, 120) : QColor(150, 150, 150); + + set3(CR::WindowText, winText, disText, winText); + set3(CR::Text, winText, disText, winText); + set3(CR::ButtonText, textOn(bg_btn), disBtnText, textOn(bg_btn)); + setAll(CR::ToolTipText, textOn(bg_tip)); + + const QColor phAlpha = dark ? QColor(255, 255, 255, 110) : QColor(0, 0, 0, 110); + const QColor phDis = dark ? QColor(255, 255, 255, 70) : QColor(0, 0, 0, 70); + set3(CR::PlaceholderText, phAlpha, phDis, phAlpha); + + // Highlight / selection + const QColor inactiveHl = hsl(winL + (dark ? 14 : -10), satWindow); + cfg.colors[CG::Active][CR::Highlight] = hl; + cfg.colors[CG::Disabled][CR::Highlight] = inactiveHl; + cfg.colors[CG::Inactive][CR::Highlight] = inactiveHl; + cfg.colors[CG::Active][CR::HighlightedText] = hlText; + cfg.colors[CG::Disabled][CR::HighlightedText] = disText; + cfg.colors[CG::Inactive][CR::HighlightedText] = dark ? Qt::white : Qt::black; + + // BrightText + QColor bright; + if (achromatic) { + bright = dark ? Qt::white : Qt::black; + } else if (dark) { + bright = QColor::fromHsl(h, qMin(255, satHighlight + 25), qMin(235, hl.lightness() + 50)); + } else { + bright = Qt::white; + } + setAll(CR::BrightText, bright); + + // Links + QColor link, linkV; + if (achromatic) { + link = dark ? QColor(100, 200, 255) : QColor(0, 0, 210); + linkV = dark ? QColor(200, 100, 255) : QColor(128, 0, 180); + } else if (dark) { + link = QColor::fromHsl(h, qMin(255, satHighlight), qMin(230, hl.lightness() + 75)); + linkV = QColor::fromHsl((h + 30) % 360, qMin(255, satHighlight), qMin(215, hl.lightness() + 55)); + } else { + link = QColor::fromHsl(h, qMin(255, satHighlight), qMax(40, hl.lightness() - 75)); + linkV = QColor::fromHsl((h + 30) % 360, qMin(255, satHighlight), qMax(30, hl.lightness() - 95)); + } + set3(CR::Link, link, dark ? QColor(48, 140, 198) : QColor(0, 0, 255), link); + set3(CR::LinkVisited, linkV, dark ? QColor(180, 80, 255) : QColor(255, 0, 255), linkV); + + // 3D / frame shading + if (dark) { + setAll(CR::Light, hsl(115, qMin(255, satShadeHi))); + setAll(CR::Midlight, hsl(82, qMin(255, satShadeHi))); + setAll(CR::Mid, hsl(37, satShadeLo)); + setAll(CR::Dark, hsl(22, satShadeLo)); + setAll(CR::Shadow, Qt::black); + } else { + setAll(CR::Light, Qt::white); + setAll(CR::Midlight, hsl(226, qMin(255, satShadeHi))); + setAll(CR::Mid, hsl(158, satShadeLo)); + setAll(CR::Dark, hsl(148, satShadeLo)); + // Shadow stays neutral — tinting it makes the UI look bruised + cfg.colors[CG::Active][CR::Shadow] = QColor(105, 105, 105); + cfg.colors[CG::Disabled][CR::Shadow] = Qt::black; + cfg.colors[CG::Inactive][CR::Shadow] = QColor(105, 105, 105); + } + + return cfg; +} + +} // namespace PaletteGenerator \ No newline at end of file diff --git a/cockatrice/src/interface/palette_editor/palette_generator.h b/cockatrice/src/interface/palette_editor/palette_generator.h new file mode 100644 index 000000000..0cec9b5c3 --- /dev/null +++ b/cockatrice/src/interface/palette_editor/palette_generator.h @@ -0,0 +1,16 @@ +#ifndef COCKATRICE_PALETTE_GENERATOR_H +#define COCKATRICE_PALETTE_GENERATOR_H + +#include "../theme_config.h" + +#include +#include + +// All QPalette roles are derived from a single accent color and an +// intensity value (0-100). See the .cpp for the full band breakdown. +namespace PaletteGenerator +{ +PaletteConfig fromAccent(const QColor &accent, int intensity, const QString &scheme); +} // namespace PaletteGenerator + +#endif // COCKATRICE_PALETTE_GENERATOR_H \ No newline at end of file diff --git a/cockatrice/src/interface/palette_editor/palette_grid_widget.cpp b/cockatrice/src/interface/palette_editor/palette_grid_widget.cpp new file mode 100644 index 000000000..e4ac5a16f --- /dev/null +++ b/cockatrice/src/interface/palette_editor/palette_grid_widget.cpp @@ -0,0 +1,179 @@ +#include "palette_grid_widget.h" + +#include +#include +#include +#include +#include +#include +#include + +static QList allRoles() +{ + QList roles; + for (int i = 0; i < QPalette::NColorRoles; ++i) { + auto r = static_cast(i); + if (r != QPalette::NoRole) { + roles << r; + } + } + return roles; +} + +static const QList ALL_GROUPS = {QPalette::Active, QPalette::Disabled, QPalette::Inactive}; + +static const QMap ROLE_DESCRIPTIONS = { + {QPalette::Window, QT_TR_NOOP("Main window / dialog background")}, + {QPalette::WindowText, QT_TR_NOOP("Text drawn on Window")}, + {QPalette::Base, QT_TR_NOOP("Background for text input widgets")}, + {QPalette::Text, QT_TR_NOOP("Text in input widgets")}, + {QPalette::Button, QT_TR_NOOP("Button background")}, + {QPalette::ButtonText, QT_TR_NOOP("Button label text")}, + {QPalette::BrightText, QT_TR_NOOP("High-contrast text (e.g. checked items)")}, + {QPalette::Highlight, QT_TR_NOOP("Selection / focus highlight")}, + {QPalette::HighlightedText, QT_TR_NOOP("Text on top of Highlight")}, + {QPalette::Link, QT_TR_NOOP("Unvisited hyperlink")}, + {QPalette::LinkVisited, QT_TR_NOOP("Visited hyperlink")}, + {QPalette::AlternateBase, QT_TR_NOOP("Alternating row background in views")}, + {QPalette::ToolTipBase, QT_TR_NOOP("Tooltip background")}, + {QPalette::ToolTipText, QT_TR_NOOP("Tooltip text")}, + {QPalette::PlaceholderText, QT_TR_NOOP("Placeholder / hint text in inputs")}, + {QPalette::Light, QT_TR_NOOP("Lighter than Button (3-D highlight)")}, + {QPalette::Midlight, QT_TR_NOOP("Between Button and Light")}, + {QPalette::Mid, QT_TR_NOOP("Between Button and Dark")}, + {QPalette::Dark, QT_TR_NOOP("Darker than Button (3-D shadow)")}, + {QPalette::Shadow, QT_TR_NOOP("Very dark shadow colour")}, +}; + +PaletteGridWidget::PaletteGridWidget(QWidget *parent) : QWidget(parent) +{ + scroll = new QScrollArea(this); + scroll->setWidgetResizable(true); + scroll->setFrameShape(QFrame::NoFrame); + + gridHost = new QWidget; + buildGrid(gridHost); + refreshChromePalettes(); + scroll->setWidget(gridHost); + + layout = new QVBoxLayout(this); + layout->setContentsMargins(0, 0, 0, 0); + layout->addWidget(scroll); +} + +void PaletteGridWidget::buildGrid(QWidget *host) +{ + QMetaEnum roleEnum = QMetaEnum::fromType(); + + auto *grid = new QGridLayout(host); + grid->setSpacing(3); + grid->setContentsMargins(12, 8, 12, 8); + grid->setColumnStretch(0, 1); + grid->setColumnStretch(1, 0); + grid->setColumnStretch(2, 0); + grid->setColumnStretch(3, 0); + + // Column headers + const QStringList groupHeaders = {tr("Active"), tr("Disabled"), tr("Inactive")}; + const QStringList groupTips = { + tr("Normal interactive state"), + tr("Widget is disabled / not interactive"), + tr("Window is in background / unfocused"), + }; + for (int col = 0; col < 3; ++col) { + auto *label = new QLabel(groupHeaders[col], host); + label->setAlignment(Qt::AlignCenter); + label->setToolTip(groupTips[col]); + QFont f = label->font(); + f.setBold(true); + label->setFont(f); + label->setAutoFillBackground(true); + label->setContentsMargins(4, 4, 4, 4); + grid->addWidget(label, 0, col + 1); + headerLabels.push_back(label); + } + + // Role rows + const auto roles = allRoles(); + for (int row = 0; row < roles.size(); ++row) { + auto role = roles[row]; + const char *name = roleEnum.valueToKey(role); + + // Alternating row shade + if (row % 2 == 0) { + for (int col = 0; col < 4; ++col) { + auto *shade = new QWidget(host); + shade->setAutoFillBackground(true); + grid->addWidget(shade, row + 1, col); + rowShadeWidgets.push_back(shade); + } + } + + auto *label = new QLabel(QString(name), host); + label->setToolTip(ROLE_DESCRIPTIONS.value(role, {})); + label->setContentsMargins(4, 2, 8, 2); + grid->addWidget(label, row + 1, 0); + + for (int col = 0; col < 3; ++col) { + auto group = ALL_GROUPS[col]; + auto *btn = new ColorButton(host); + colorButtons[group][role] = btn; + grid->addWidget(btn, row + 1, col + 1, Qt::AlignHCenter | Qt::AlignVCenter); + } + } +} + +void PaletteGridWidget::changeEvent(QEvent *e) +{ + if (e->type() == QEvent::PaletteChange) { + QTimer::singleShot(0, this, &PaletteGridWidget::refreshChromePalettes); + } + + QWidget::changeEvent(e); +} + +void PaletteGridWidget::refreshChromePalettes() +{ + const QPalette base = qApp->palette(); + const QColor alt = base.color(QPalette::AlternateBase); + + // Header labels + for (auto *label : headerLabels) { + QPalette lp = label->palette(); + lp.setColor(QPalette::Window, alt); + label->setPalette(lp); + label->update(); + } + + // Alternating row backgrounds + for (auto *shade : rowShadeWidgets) { + QPalette sp = shade->palette(); + sp.setColor(QPalette::Window, alt); + shade->setPalette(sp); + shade->update(); + } +} + +void PaletteGridWidget::loadPalette(const PaletteConfig &cfg) +{ + for (auto group : ALL_GROUPS) { + for (auto role : allRoles()) { + QColor color = cfg.colors.value(group).value(role); + if (!color.isValid()) { + color = qApp->palette().color(group, role); + } + colorButtons[group][role]->setColor(color); + } + } +} + +PaletteConfig PaletteGridWidget::currentPaletteConfig() const +{ + PaletteConfig cfg; + for (auto group : ALL_GROUPS) { + for (auto role : allRoles()) { + cfg.colors[group][role] = colorButtons[group][role]->getColor(); + } + } + return cfg; +} \ No newline at end of file diff --git a/cockatrice/src/interface/palette_editor/palette_grid_widget.h b/cockatrice/src/interface/palette_editor/palette_grid_widget.h new file mode 100644 index 000000000..1d85f1ac8 --- /dev/null +++ b/cockatrice/src/interface/palette_editor/palette_grid_widget.h @@ -0,0 +1,38 @@ +#ifndef COCKATRICE_PALETTE_GRID_WIDGET_H +#define COCKATRICE_PALETTE_GRID_WIDGET_H + +#include "../theme_config.h" +#include "color_button.h" + +#include +#include +#include +#include + +class QLabel; +class QScrollArea; +// Scrollable grid of ColorButtons — one per (ColorGroup × ColorRole) cell. +// Owns the load/read round-trip for PaletteConfig but has no file I/O itself. +class PaletteGridWidget : public QWidget +{ + Q_OBJECT +public: + explicit PaletteGridWidget(QWidget *parent = nullptr); + + void loadPalette(const PaletteConfig &cfg); + PaletteConfig currentPaletteConfig() const; + +private: + void buildGrid(QWidget *host); + void changeEvent(QEvent *e); + void refreshChromePalettes(); + + QMap> colorButtons; + QScrollArea *scroll; + QWidget *gridHost; + QVBoxLayout *layout; + QVector headerLabels; + QVector rowShadeWidgets; +}; + +#endif // COCKATRICE_PALETTE_GRID_WIDGET_H \ No newline at end of file diff --git a/cockatrice/src/interface/palette_editor/quick_setup_panel.cpp b/cockatrice/src/interface/palette_editor/quick_setup_panel.cpp new file mode 100644 index 000000000..fe3af9b52 --- /dev/null +++ b/cockatrice/src/interface/palette_editor/quick_setup_panel.cpp @@ -0,0 +1,99 @@ +#include "quick_setup_panel.h" + +#include +#include +#include +#include +#include + +QuickSetupPanel::QuickSetupPanel(QWidget *parent) : QWidget(parent) +{ + layout = new QHBoxLayout(this); + layout->setContentsMargins(12, 8, 12, 8); + layout->setSpacing(10); + + heading = new QLabel(this); + heading->setTextFormat(Qt::RichText); + + accentLabel = new QLabel(this); + accentButton = new ColorButton(this); + accentButton->setColor(QColor(20, 140, 60)); + + intensityLabel = new QLabel(this); + + labelLow = new QLabel(this); + labelHigh = new QLabel(this); + QFont small = labelLow->font(); + small.setPointSizeF(small.pointSizeF() * 0.82); + labelLow->setFont(small); + labelHigh->setFont(small); + QPalette dimmed = labelLow->palette(); + dimmed.setColor(QPalette::WindowText, qApp->palette().color(QPalette::Mid)); + labelLow->setPalette(dimmed); + labelHigh->setPalette(dimmed); + + intensitySlider = new QSlider(Qt::Horizontal, this); + intensitySlider->setRange(0, 100); + intensitySlider->setValue(70); + intensitySlider->setFixedWidth(160); + + intensityPercentageLabel = new QLabel(this); + intensityPercentageLabel->setFixedWidth(34); + intensityPercentageLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter); + + generateButton = new QPushButton(this); + + layout->addWidget(heading); + layout->addSpacing(6); + layout->addWidget(accentLabel); + layout->addWidget(accentButton); + layout->addSpacing(12); + layout->addWidget(intensityLabel); + layout->addWidget(labelLow); + layout->addWidget(intensitySlider); + layout->addWidget(labelHigh); + layout->addWidget(intensityPercentageLabel); + layout->addStretch(); + layout->addWidget(generateButton); + + connect(intensitySlider, &QSlider::valueChanged, this, + [this](int v) { intensityPercentageLabel->setText(tr("%1%").arg(v)); }); + connect(generateButton, &QPushButton::clicked, this, + [this] { emit generateRequested(accentButton->getColor(), intensitySlider->value()); }); + retranslateUi(); +} + +void QuickSetupPanel::retranslateUi() +{ + heading->setText(tr("Quick Setup")); + heading->setToolTip(tr("Generate all palette roles automatically from a single accent colour")); + accentLabel->setText(tr("Accent:")); + accentButton->setToolTip(tr("Primary hue. Used directly for highlights and links.\n" + "At high intensity it also tints buttons and backgrounds.")); + intensityLabel->setText(tr("Intensity:")); + labelLow->setText(tr("Subtle")); + labelHigh->setText(tr("Full colour")); + intensitySlider->setToolTip(tr("0–30 Subtle tint — only highlights and links change hue\n" + "30–70 Accented — buttons, tooltips, and borders join in\n" + "70–100 Full colour — backgrounds, everything")); + intensityPercentageLabel->setText(tr("70%")); + + generateButton->setText(tr("Generate ↓")); + generateButton->setToolTip(tr("Derive all palette roles from the accent colour above.\n" + "Fine-tune individual colours in the grid afterwards.")); +} + +QColor QuickSetupPanel::accentColor() const +{ + return accentButton->getColor(); +} + +int QuickSetupPanel::intensity() const +{ + return intensitySlider->value(); +} + +void QuickSetupPanel::setAccentColor(const QColor &c) +{ + accentButton->setColor(c); +} \ No newline at end of file diff --git a/cockatrice/src/interface/palette_editor/quick_setup_panel.h b/cockatrice/src/interface/palette_editor/quick_setup_panel.h new file mode 100644 index 000000000..dddd0aaa3 --- /dev/null +++ b/cockatrice/src/interface/palette_editor/quick_setup_panel.h @@ -0,0 +1,94 @@ +#ifndef COCKATRICE_QUICK_SETUP_PANEL_H +#define COCKATRICE_QUICK_SETUP_PANEL_H + +#include "color_button.h" + +#include + +class QPushButton; +class QHBoxLayout; +class QLabel; +class QSlider; + +/** + * @class QuickSetupPanel + * @brief Provides a compact "Quick Setup" interface for generating theme palettes. + * + * The panel contains: + * - an accent color picker, + * - an intensity slider, + * - and a generate button. + * + * When the user clicks the generate button, the panel emits + * generateRequested() with the currently selected accent color + * and intensity value. + * + * Typically used together with PaletteGenerator::fromAccent() + * to quickly generate color schemes from a chosen accent color. + */ +class QuickSetupPanel : public QWidget +{ + Q_OBJECT + +public: + /** + * @brief Constructs the quick setup panel. + * + * @param parent Optional parent widget. + */ + explicit QuickSetupPanel(QWidget *parent = nullptr); + + /** + * @brief Retranslates all user-visible strings. + * + * Intended to be called when the application language changes. + */ + void retranslateUi(); + + /** + * @brief Returns the currently selected accent color. + * + * @return The selected accent color. + */ + QColor accentColor() const; + + /** + * @brief Returns the current intensity slider value. + * + * @return The selected intensity value. + */ + int intensity() const; + + /** + * @brief Updates the displayed accent color. + * + * Used by the parent dialog when switching schemes to keep + * the color swatch synchronized with the active palette. + * + * @param c The new accent color. + */ + void setAccentColor(const QColor &c); + +signals: + /** + * @brief Emitted when the user requests palette generation. + * + * @param accent The selected accent color. + * @param intensity The selected intensity value. + */ + void generateRequested(QColor accent, int intensity); + +private: + QHBoxLayout *layout; + QLabel *heading; + QLabel *accentLabel; + ColorButton *accentButton; + QLabel *intensityLabel; + QLabel *labelLow; + QLabel *labelHigh; + QSlider *intensitySlider; + QLabel *intensityPercentageLabel; + QPushButton *generateButton; +}; + +#endif // COCKATRICE_QUICK_SETUP_PANEL_H \ No newline at end of file diff --git a/cockatrice/src/interface/theme_config.cpp b/cockatrice/src/interface/theme_config.cpp new file mode 100644 index 000000000..b79c91265 --- /dev/null +++ b/cockatrice/src/interface/theme_config.cpp @@ -0,0 +1,267 @@ +#include "theme_config.h" + +#include +#include +#include +#include + +bool ThemeConfig::isEmpty() const +{ + return colorScheme.isEmpty() && styleName.isEmpty(); +} + +QString ThemeConfig::toIni() const +{ + QString out; + out += "[Appearance]\n"; + out += QString("ColorScheme = %1\n").arg(colorScheme.isEmpty() ? "System" : colorScheme); + out += "\n[Style]\n"; + out += QString("Name = %1\n").arg(styleName.isEmpty() ? "Default" : styleName); + return out; +} + +ThemeConfig ThemeConfig::fromThemeDir(const QString &themeDirPath) +{ + ThemeConfig cfg; + + if (themeDirPath.isEmpty()) { + return cfg; + } + + QFile f(QDir(themeDirPath).absoluteFilePath("theme.cfg")); + if (!f.open(QIODevice::ReadOnly | QIODevice::Text)) { + return cfg; + } + + QString currentSection; + + QTextStream in(&f); + + while (!in.atEnd()) { + QString line = in.readLine().trimmed(); + + if (line.isEmpty() || line.startsWith('#') || line.startsWith(';')) { + continue; + } + + if (line.startsWith('[') && line.endsWith(']')) { + currentSection = line.mid(1, line.length() - 2).trimmed(); + continue; + } + + int eq = line.indexOf('='); + if (eq < 0) { + continue; + } + + QString key = line.left(eq).trimmed(); + QString value = line.mid(eq + 1).trimmed(); + + if (currentSection.compare("Appearance", Qt::CaseInsensitive) == 0) { + if (key.compare("ColorScheme", Qt::CaseInsensitive) == 0) { + cfg.colorScheme = value; + } + } else if (currentSection.compare("Style", Qt::CaseInsensitive) == 0) { + if (key.compare("Name", Qt::CaseInsensitive) == 0) { + cfg.styleName = value; + } + } + } + + return cfg; +} + +bool ThemeConfig::save(const QString &themeDirPath) const +{ + if (themeDirPath.isEmpty()) { + return false; + } + + QDir dir(themeDirPath); + + if (!dir.exists()) { + dir.mkpath("."); + } + + QFile f(dir.absoluteFilePath("theme.cfg")); + if (!f.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) { + return false; + } + + QTextStream out(&f); + out << toIni(); + + return true; +} + +bool PaletteConfig::hasPalette() const +{ + return !colors.isEmpty(); +} + +QString PaletteConfig::toToml() const +{ + QMetaEnum roleEnum = QMetaEnum::fromType(); + + QString out; + + static const QList> groups = { + {QPalette::Active, "Palette"}, + {QPalette::Disabled, "Palette.Disabled"}, + {QPalette::Inactive, "Palette.Inactive"}, + }; + + for (const auto &[group, sectionName] : groups) { + if (!colors.contains(group)) { + continue; + } + + out += QString("[%1]\n").arg(sectionName); + + const auto &roleMap = colors[group]; + + for (auto it = roleMap.cbegin(); it != roleMap.cend(); ++it) { + const char *roleName = roleEnum.valueToKey(it.key()); + + if (!roleName) { + continue; + } + + out += QString("%1 = %2\n").arg(QString(roleName), -20).arg(it.value().name(QColor::HexArgb)); + } + + out += "\n"; + } + + return out; +} + +QString PaletteConfig::fileName(const QString &colorScheme) +{ + return colorScheme.compare("Dark", Qt::CaseInsensitive) == 0 ? "palette-dark.toml" : "palette-light.toml"; +} + +PaletteConfig PaletteConfig::fromFile(const QString &filePath) +{ + PaletteConfig cfg; + + QFile f(filePath); + + if (!f.open(QIODevice::ReadOnly | QIODevice::Text)) { + return cfg; + } + + QMetaEnum roleEnum = QMetaEnum::fromType(); + + QString currentSection; + QPalette::ColorGroup currentGroup = QPalette::Active; + + QTextStream in(&f); + + while (!in.atEnd()) { + QString line = in.readLine().trimmed(); + + if (line.isEmpty() || line.startsWith('#') || line.startsWith(';')) { + continue; + } + + if (line.startsWith('[') && line.endsWith(']')) { + currentSection = line.mid(1, line.length() - 2).trimmed(); + + if (currentSection.startsWith("Palette", Qt::CaseInsensitive)) { + int dot = currentSection.indexOf('.'); + + QString groupStr = (dot >= 0) ? currentSection.mid(dot + 1) : "Active"; + + if (groupStr.compare("Disabled", Qt::CaseInsensitive) == 0) { + currentGroup = QPalette::Disabled; + } else if (groupStr.compare("Inactive", Qt::CaseInsensitive) == 0) { + currentGroup = QPalette::Inactive; + } else { + currentGroup = QPalette::Active; + } + } + + continue; + } + + int eq = line.indexOf('='); + + if (eq < 0) { + continue; + } + + QString key = line.left(eq).trimmed(); + QString value = line.mid(eq + 1).trimmed(); + + // Strip inline comments if preceded by whitespace + for (int i = 1; i < value.size(); ++i) { + if (value[i] == '#' && value[i - 1].isSpace()) { + value = value.left(i).trimmed(); + break; + } + } + + if (!currentSection.startsWith("Palette", Qt::CaseInsensitive)) { + continue; + } + + if (key.startsWith("QPalette::")) { + key = key.mid(10); + } + + int roleInt = roleEnum.keyToValue(key.toUtf8().constData()); + + if (roleInt < 0) { + continue; + } + + QColor color(value); + + if (color.isValid()) { + cfg.colors[currentGroup][static_cast(roleInt)] = color; + } + } + + return cfg; +} + +PaletteConfig PaletteConfig::fromScheme(const QString &themeDirPath, const QString &colorScheme) +{ + if (themeDirPath.isEmpty()) { + return {}; + } + + return fromFile(QDir(themeDirPath).absoluteFilePath(fileName(colorScheme))); +} + +PaletteConfig PaletteConfig::fromDefault(const QString &themeDirPath, const QString &colorScheme) +{ + if (themeDirPath.isEmpty()) { + return {}; + } + + QDir dir(themeDirPath); + + bool wantDark = colorScheme.compare("Dark", Qt::CaseInsensitive) == 0; + + PaletteConfig cfg = + fromFile(dir.absoluteFilePath(wantDark ? "palette-default-dark.toml" : "palette-default-light.toml")); + + if (!cfg.hasPalette()) { + cfg = fromFile(dir.absoluteFilePath(wantDark ? "palette-default-light.toml" : "palette-default-dark.toml")); + } + + return cfg; +} + +QPalette PaletteConfig::apply(QPalette base) const +{ + for (auto git = colors.cbegin(); git != colors.cend(); ++git) { + for (auto rit = git.value().cbegin(); rit != git.value().cend(); ++rit) { + base.setColor(git.key(), rit.key(), rit.value()); + } + } + + return base; +} \ No newline at end of file diff --git a/cockatrice/src/interface/theme_config.h b/cockatrice/src/interface/theme_config.h new file mode 100644 index 000000000..07bf55b7a --- /dev/null +++ b/cockatrice/src/interface/theme_config.h @@ -0,0 +1,37 @@ +#ifndef COCKATRICE_THEME_CONFIG_H +#define COCKATRICE_THEME_CONFIG_H + +#include +#include +#include +#include + +struct ThemeConfig +{ + QString colorScheme; + QString styleName; + + bool isEmpty() const; + QString toIni() const; + + static ThemeConfig fromThemeDir(const QString &themeDirPath); + bool save(const QString &themeDirPath) const; +}; + +struct PaletteConfig +{ + QMap> colors; + + bool hasPalette() const; + QString toToml() const; + + static QString fileName(const QString &colorScheme); + + static PaletteConfig fromFile(const QString &filePath); + static PaletteConfig fromScheme(const QString &themeDirPath, const QString &colorScheme); + static PaletteConfig fromDefault(const QString &themeDirPath, const QString &colorScheme); + + QPalette apply(QPalette base) const; +}; + +#endif // COCKATRICE_THEME_CONFIG_H \ No newline at end of file diff --git a/cockatrice/src/interface/theme_manager.cpp b/cockatrice/src/interface/theme_manager.cpp index 58fb62362..abdc02eef 100644 --- a/cockatrice/src/interface/theme_manager.cpp +++ b/cockatrice/src/interface/theme_manager.cpp @@ -19,9 +19,7 @@ #include #define NONE_THEME_NAME "Default" -#define FUSION_THEME_NAME "Fusion (System Default)" -#define FUSION_THEME_NAME_LIGHT "Fusion (Light)" -#define FUSION_THEME_NAME_DARK "Fusion (Dark)" +#define FUSION_THEME_NAME "Fusion" #define STYLE_CSS_NAME "style.css" #define HANDZONE_BG_NAME "handzone" #define PLAYERZONE_BG_NAME "playerzone" @@ -115,37 +113,28 @@ void ThemeManager::ensureThemeDirectoryExists() } } -bool ThemeManager::isDarkMode() +bool ThemeManager::isDarkMode(const QString &themeDirPath) { - auto themeName = SettingsCache::instance().getThemeName(); - // Explicit Dark Mode - if (themeName == FUSION_THEME_NAME_LIGHT || themeName.endsWith("(Light)")) { + ThemeConfig themeConfig = ThemeConfig::fromThemeDir(themeDirPath); + if (themeConfig.colorScheme.compare("Dark", Qt::CaseInsensitive) == 0) { + return true; + } else if (themeConfig.colorScheme.compare("Light", Qt::CaseInsensitive) == 0) { return false; - } - // Explicit Light Mode - if (themeName == FUSION_THEME_NAME_DARK || themeName.endsWith("(Dark)")) { - return true; - } - - // Auto detection on compatible Qt versions -#if (QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)) - if (QGuiApplication::styleHints()->colorScheme() == Qt::ColorScheme::Dark && - (themeName == NONE_THEME_NAME || themeName == FUSION_THEME_NAME || themeName.endsWith("(System Default)"))) { - return true; } else { - return false; - } +#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0) + bool osDark = (QGuiApplication::styleHints()->colorScheme() == Qt::ColorScheme::Dark); +#else + bool osDark = false; #endif - // Default to light mode - return false; + return osDark; + } } bool ThemeManager::isBuiltInTheme() { const auto themeName = SettingsCache::instance().getThemeName(); - return themeName == NONE_THEME_NAME || themeName == FUSION_THEME_NAME || themeName == FUSION_THEME_NAME_LIGHT || - themeName == FUSION_THEME_NAME_DARK; + return themeName == NONE_THEME_NAME || themeName == FUSION_THEME_NAME; } QStringMap &ThemeManager::getAvailableThemes() @@ -153,15 +142,13 @@ QStringMap &ThemeManager::getAvailableThemes() QDir dir; availableThemes.clear(); - // add default value - availableThemes.insert(NONE_THEME_NAME, QString()); - // load themes from user profile dir dir.setPath(SettingsCache::instance().getThemesPath()); - availableThemes.insert(FUSION_THEME_NAME, dir.filePath("Fusion (System Default)")); - availableThemes.insert(FUSION_THEME_NAME_LIGHT, dir.filePath("Fusion (Light)")); - availableThemes.insert(FUSION_THEME_NAME_DARK, dir.filePath("Fusion (Dark)")); + // add default value + availableThemes.insert(NONE_THEME_NAME, dir.absoluteFilePath("Default")); + + availableThemes.insert(FUSION_THEME_NAME, dir.absoluteFilePath("Fusion")); for (QString themeName : dir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot, QDir::Name)) { if (!availableThemes.contains(themeName)) { @@ -217,192 +204,112 @@ QBrush ThemeManager::loadExtraBrush(QString fileName, QBrush &fallbackBrush) return brush; } -static inline QPalette createDarkGreenFusionPalette() +ThemeConfig ThemeManager::loadGlobalConfig(const QString &themeDirPath) { - QPalette p = QStyleFactory::create("Fusion")->standardPalette(); - - // ---------- Core backgrounds ---------- - p.setColor(QPalette::Window, QColor(30, 30, 30)); // #ff1e1e1e - p.setColor(QPalette::Base, QColor(45, 45, 45)); // #ff2d2d2d - p.setColor(QPalette::AlternateBase, QColor(53, 53, 53)); // #ff353535 - p.setColor(QPalette::Button, QColor(60, 60, 60)); // #ff3c3c3c - p.setColor(QPalette::ToolTipBase, QColor(60, 60, 60)); // #ff3c3c3c - - // ---------- Core text ---------- - p.setColor(QPalette::WindowText, Qt::white); // #ffffffff - p.setColor(QPalette::Text, Qt::white); // #ffffffff - p.setColor(QPalette::ButtonText, Qt::white); // #ffffffff - p.setColor(QPalette::ToolTipText, QColor(212, 212, 212)); // #ffd4d4d4 - p.setColor(QPalette::PlaceholderText, QColor(255, 255, 255, 128)); // #80ffffff - - // ---------- Selection / focus ---------- - const QColor highlight(20, 140, 60); // #ff148c3c - p.setColor(QPalette::Highlight, highlight); - p.setColor(QPalette::HighlightedText, Qt::white); // #ffffffff - - // ---------- Links ---------- - p.setColor(QPalette::Link, QColor(0, 246, 82)); // #ff00f652 - p.setColor(QPalette::LinkVisited, QColor(0, 211, 70)); // #ff00d346 - - // ---------- Accent (Qt 6) ---------- -#if (QT_VERSION >= QT_VERSION_CHECK(6, 6, 0)) - p.setColor(QPalette::Accent, QColor(0, 211, 70)); // #ff00d346 -#endif - - // ---------- Bright text ---------- - p.setColor(QPalette::BrightText, QColor(0, 246, 82)); // #ff00f652 - - // ---------- 3D / frame shading ---------- - p.setColor(QPalette::Light, QColor(120, 120, 120)); // #ff787878 - p.setColor(QPalette::Midlight, QColor(90, 90, 90)); // #ff5a5a5a - p.setColor(QPalette::Mid, QColor(40, 40, 40)); // #ff282828 - p.setColor(QPalette::Dark, QColor(30, 30, 30)); // #ff1e1e1e - p.setColor(QPalette::Shadow, Qt::black); // #ff000000 - - // ---------- Disabled state ---------- - const QColor disabledText(157, 157, 157); // #ff9d9d9d - p.setColor(QPalette::Disabled, QPalette::WindowText, disabledText); - p.setColor(QPalette::Disabled, QPalette::Text, disabledText); - p.setColor(QPalette::Disabled, QPalette::ButtonText, disabledText); - p.setColor(QPalette::Disabled, QPalette::Base, QColor(30, 30, 30)); - p.setColor(QPalette::Disabled, QPalette::Window, QColor(30, 30, 30)); - p.setColor(QPalette::Disabled, QPalette::Link, QColor(48, 140, 198)); // #ff308cc6 - p.setColor(QPalette::Disabled, QPalette::LinkVisited, QColor(255, 0, 255)); // #ffff00ff - p.setColor(QPalette::Disabled, QPalette::ToolTipBase, QColor(255, 255, 220)); - p.setColor(QPalette::Disabled, QPalette::ToolTipText, Qt::black); - -#if (QT_VERSION >= QT_VERSION_CHECK(6, 6, 0)) - p.setColor(QPalette::Disabled, QPalette::Accent, disabledText); -#endif - - // ---------- Inactive state ---------- - p.setColor(QPalette::Inactive, QPalette::Highlight, QColor(30, 30, 30)); - p.setColor(QPalette::Inactive, QPalette::HighlightedText, Qt::white); - -#if (QT_VERSION >= QT_VERSION_CHECK(6, 6, 0)) - p.setColor(QPalette::Inactive, QPalette::Accent, QColor(30, 30, 30)); -#endif - - return p; + return ThemeConfig::fromThemeDir(themeDirPath); } -static inline QPalette createLightGreenFusionPalette() +bool ThemeManager::saveGlobalConfig(const QString &themeDirPath, const ThemeConfig &cfg) { - QPalette p = QStyleFactory::create("Fusion")->standardPalette(); - - // ---------- Core backgrounds ---------- - p.setColor(QPalette::Window, QColor(240, 240, 240)); // #fff0f0f0 - p.setColor(QPalette::Base, Qt::white); // #ffffffff - p.setColor(QPalette::AlternateBase, QColor(233, 231, 227)); // #ffe9e7e3 - p.setColor(QPalette::Button, QColor(240, 240, 240)); // #fff0f0f0 - p.setColor(QPalette::ToolTipBase, QColor(255, 255, 220)); // #ffffffdc - - // ---------- Core text ---------- - p.setColor(QPalette::WindowText, Qt::black); // #ff000000 - p.setColor(QPalette::Text, Qt::black); // #ff000000 - p.setColor(QPalette::ButtonText, Qt::black); // #ff000000 - p.setColor(QPalette::ToolTipText, Qt::black); // #ff000000 - p.setColor(QPalette::PlaceholderText, QColor(0, 0, 0, 128)); // #80000000 - - // ---------- Selection / focus ---------- - const QColor highlight(20, 140, 60); // #ff148c3c - p.setColor(QPalette::Highlight, highlight); - p.setColor(QPalette::HighlightedText, Qt::white); // #ffffffff - - // ---------- Links ---------- - p.setColor(QPalette::Link, QColor(13, 95, 40)); // #ff0d5f28 - p.setColor(QPalette::LinkVisited, QColor(8, 64, 27)); // #ff08401b - - // ---------- Accent (Qt 6) ---------- -#if (QT_VERSION >= QT_VERSION_CHECK(6, 6, 0)) - p.setColor(QPalette::Accent, QColor(16, 117, 50)); // #ff107532 -#endif - - // ---------- Bright text ---------- - p.setColor(QPalette::BrightText, Qt::white); // #ffffffff - - // ---------- 3D / frame shading ---------- - p.setColor(QPalette::Light, Qt::white); // #ffffffff - p.setColor(QPalette::Midlight, QColor(227, 227, 227)); // #ffe3e3e3 - p.setColor(QPalette::Mid, QColor(160, 160, 160)); // #ffa0a0a0 - p.setColor(QPalette::Dark, QColor(160, 160, 160)); // #ffa0a0a0 - p.setColor(QPalette::Shadow, QColor(105, 105, 105)); // #ff696969 - - // ---------- Disabled state ---------- - const QColor disabledText(120, 120, 120); // #ff787878 - p.setColor(QPalette::Disabled, QPalette::WindowText, disabledText); - p.setColor(QPalette::Disabled, QPalette::Text, disabledText); - p.setColor(QPalette::Disabled, QPalette::ButtonText, disabledText); - p.setColor(QPalette::Disabled, QPalette::Base, QColor(240, 240, 240)); - p.setColor(QPalette::Disabled, QPalette::Window, QColor(240, 240, 240)); - p.setColor(QPalette::Disabled, QPalette::Midlight, QColor(247, 247, 247)); - p.setColor(QPalette::Disabled, QPalette::AlternateBase, QColor(247, 247, 247)); - p.setColor(QPalette::Disabled, QPalette::Shadow, Qt::black); - p.setColor(QPalette::Disabled, QPalette::Link, QColor(0, 0, 255)); - p.setColor(QPalette::Disabled, QPalette::LinkVisited, QColor(255, 0, 255)); - -#if (QT_VERSION >= QT_VERSION_CHECK(6, 6, 0)) - p.setColor(QPalette::Disabled, QPalette::Accent, disabledText); -#endif - - // ---------- Inactive state ---------- - p.setColor(QPalette::Inactive, QPalette::Highlight, QColor(240, 240, 240)); - p.setColor(QPalette::Inactive, QPalette::HighlightedText, Qt::black); - -#if (QT_VERSION >= QT_VERSION_CHECK(6, 6, 0)) - p.setColor(QPalette::Inactive, QPalette::Accent, QColor(240, 240, 240)); -#endif - - return p; + return cfg.save(themeDirPath); } -void ThemeManager::themeChangedSlot() +PaletteConfig ThemeManager::loadPaletteConfig(const QString &themeDirPath, const QString &colorScheme) { - QString themeName = SettingsCache::instance().getThemeName(); - qCInfo(ThemeManagerLog) << "Theme changed:" << themeName; + if (themeDirPath.isEmpty()) { + return {}; + } + return PaletteConfig::fromScheme(themeDirPath, colorScheme); +} - QString dirPath = getAvailableThemes().value(themeName); - QDir dir = dirPath; - - // css - if (!dirPath.isEmpty() && dir.exists(STYLE_CSS_NAME)) { - qApp->setStyleSheet("file:///" + dir.absoluteFilePath(STYLE_CSS_NAME)); - } else { - qApp->setStyleSheet(""); +bool ThemeManager::savePaletteConfig(const QString &themeDirPath, const QString &colorScheme, const PaletteConfig &cfg) +{ + if (themeDirPath.isEmpty()) { + return false; } - QStyle *newStyle = nullptr; - QPalette newPalette; + QDir dir(themeDirPath); + if (!dir.exists()) { + dir.mkpath("."); + } - if (themeName == FUSION_THEME_NAME) { - newStyle = QStyleFactory::create("Fusion"); + QFile f(dir.absoluteFilePath(PaletteConfig::fileName(colorScheme))); + if (!f.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) { + return false; + } -#if (QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)) - // Start from Fusion's own palette so dark mode is handled correctly, - // then apply any tweaks on top of it. - newPalette = newStyle->standardPalette(); - if (QGuiApplication::styleHints()->colorScheme() == Qt::ColorScheme::Dark) { - newPalette.setColor(QPalette::AlternateBase, QColor(53, 53, 53)); + QTextStream(&f) << cfg.toToml(); + return true; +} + +void ThemeManager::setColorScheme(const QString &scheme) +{ + const QString dirPath = getAvailableThemes().value(SettingsCache::instance().getThemeName()); + ThemeConfig cfg = ThemeConfig::fromThemeDir(dirPath); + + cfg.colorScheme = scheme; + + cfg.save(dirPath); + reloadCurrentTheme(); +} + +void ThemeManager::reloadCurrentTheme() +{ + themeChangedSlot(); +} + +void ThemeManager::previewPalette(const PaletteConfig &cfg, const QString &scheme) +{ + const QString themeName = SettingsCache::instance().getThemeName(); + const QString dirPath = getAvailableThemes().value(themeName); + const ThemeConfig themeCfg = ThemeConfig::fromThemeDir(dirPath); + applyStyleAndPalette(themeName, themeCfg, cfg, scheme); +} + +void ThemeManager::applyStyleAndPalette(const QString &themeName, + const ThemeConfig &themeCfg, + const PaletteConfig &palCfg, + const QString &activeScheme) +{ + QString styleName = themeCfg.styleName; + if (styleName.isEmpty() || styleName.compare("Default", Qt::CaseInsensitive) == 0) { + if (themeName == FUSION_THEME_NAME) { + styleName = "Fusion"; + } else { + styleName = defaultStyleName; } -#else - newPalette = qApp->palette(); -#endif - } else if (themeName == FUSION_THEME_NAME_LIGHT) { - newStyle = QStyleFactory::create("Fusion"); - newPalette = createLightGreenFusionPalette(); - } else if (themeName == FUSION_THEME_NAME_DARK) { - newStyle = QStyleFactory::create("Fusion"); - newPalette = createDarkGreenFusionPalette(); - } else { - newStyle = QStyleFactory::create(defaultStyleName); - // Use the style's default palette. - newPalette = newStyle->standardPalette(); } - // Apply palette FIRST. - qApp->setPalette(newPalette); - // Then apply style. - qApp->setStyle(newStyle); + QStyle *style = QStyleFactory::create(styleName); + if (!style) { + style = QStyleFactory::create(defaultStyleName); + } + + // Base palette + QPalette base; + if (styleName.compare("Fusion", Qt::CaseInsensitive) == 0) { + base = style->standardPalette(); +#if (QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)) + if (activeScheme == "Dark") { + base.setColor(QPalette::AlternateBase, QColor(53, 53, 53)); + } +#endif + } else { + base = qApp->palette(); + } + + // Overlay custom palette colours + if (palCfg.hasPalette()) { + base = palCfg.apply(base); + } + + // Palette BEFORE style — setStyle() triggers a synchronous repolish of all + // widgets immediately. If the palette isn't set yet at that point, every + // widget gets polished against the stale colours, requiring a second apply + // to fully resolve. Setting palette first means setStyle's repolish cascade + // already sees the correct colours. + qApp->setPalette(base); + qApp->setStyle(style); // Force every widget to re-polish and repaint immediately rather than // waiting for natural expose events, which produces a patchwork of old @@ -412,34 +319,57 @@ void ThemeManager::themeChangedSlot() // palette (WA_SetPalette not set). Calling it unconditionally would clobber // intentional per-widget palette customisations across the whole app. for (QWidget *widget : qApp->allWidgets()) { - if (widget->isVisible()) { - newStyle->unpolish(widget); - newStyle->polish(widget); - - widget->update(); - } + style->unpolish(widget); + style->polish(widget); + widget->update(); } +} - if (dirPath.isEmpty()) { - // set default values - QDir::setSearchPaths("theme", DEFAULT_RESOURCE_PATHS); - brushes[Role::Hand] = HANDZONE_BG_DEFAULT; - brushes[Role::Table] = TABLEZONE_BG_DEFAULT; - brushes[Role::Player] = PLAYERZONE_BG_DEFAULT; - brushes[Role::Stack] = STACKZONE_BG_DEFAULT; +void ThemeManager::themeChangedSlot() +{ + QString themeName = SettingsCache::instance().getThemeName(); + QString dirPath = getAvailableThemes().value(themeName); + currentThemePath = dirPath; + QDir dir(dirPath); + + // CSS + if (!dirPath.isEmpty() && dir.exists(STYLE_CSS_NAME)) { + qApp->setStyleSheet("file:///" + dir.absoluteFilePath(STYLE_CSS_NAME)); } else { - // resources - QStringList resources; - resources << dir.absolutePath() << DEFAULT_RESOURCE_PATHS; - QDir::setSearchPaths("theme", resources); - - // zones bg - dir.cd("zones"); - brushes[Role::Hand] = loadBrush(HANDZONE_BG_NAME, HANDZONE_BG_DEFAULT); - brushes[Role::Table] = loadBrush(TABLEZONE_BG_NAME, TABLEZONE_BG_DEFAULT); - brushes[Role::Player] = loadBrush(PLAYERZONE_BG_NAME, PLAYERZONE_BG_DEFAULT); - brushes[Role::Stack] = loadBrush(STACKZONE_BG_NAME, STACKZONE_BG_DEFAULT); + qApp->setStyleSheet(""); } + + // load theme.cfg for style + scheme preference + ThemeConfig themeCfg = ThemeConfig::fromThemeDir(dirPath); + + // Resolve active scheme: + // theme.cfg says Dark/Light → use that + // theme.cfg says System or is absent → follow the OS + QString activeScheme = isDarkMode(dirPath) ? "Dark" : "Light"; + + // ── Load palette: custom first, then theme default ──────────────────── + PaletteConfig palette = PaletteConfig::fromScheme(dirPath, activeScheme); + if (!palette.hasPalette()) { + palette = PaletteConfig::fromDefault(dirPath, activeScheme); + } + + applyStyleAndPalette(themeName, themeCfg, palette, activeScheme); + + QStringList resources; + if (!dirPath.isEmpty()) { + resources << dir.absolutePath(); + } + resources << DEFAULT_RESOURCE_PATHS; + + QDir::setSearchPaths("theme", resources); + + brushes[Role::Hand] = loadBrush(HANDZONE_BG_NAME, HANDZONE_BG_DEFAULT); + + brushes[Role::Table] = loadBrush(TABLEZONE_BG_NAME, TABLEZONE_BG_DEFAULT); + + brushes[Role::Player] = loadBrush(PLAYERZONE_BG_NAME, PLAYERZONE_BG_DEFAULT); + + brushes[Role::Stack] = loadBrush(STACKZONE_BG_NAME, STACKZONE_BG_DEFAULT); for (auto &brushCache : brushesCache) { brushCache.clear(); } diff --git a/cockatrice/src/interface/theme_manager.h b/cockatrice/src/interface/theme_manager.h index 416923128..4b1fd2026 100644 --- a/cockatrice/src/interface/theme_manager.h +++ b/cockatrice/src/interface/theme_manager.h @@ -7,6 +7,8 @@ #ifndef THEMEMANAGER_H #define THEMEMANAGER_H +#include "theme_config.h" + #include #include #include @@ -41,6 +43,7 @@ public: private: QString defaultStyleName; + QString currentThemePath; std::array brushes; QStringMap availableThemes; /* @@ -52,11 +55,31 @@ protected: void ensureThemeDirectoryExists(); QBrush loadBrush(QString fileName, QColor fallbackColor); QBrush loadExtraBrush(QString fileName, QBrush &fallbackBrush); + void applyStyleAndPalette(const QString &themeName, + const ThemeConfig &themeCfg, + const PaletteConfig &palCfg, + const QString &activeScheme); public: bool isBuiltInTheme(); - bool isDarkMode(); + bool isDarkMode(const QString &themeDirPath); QStringMap &getAvailableThemes(); + // Returns the path to the currently active theme directory (empty = default) + QString getCurrentThemePath() const + { + return currentThemePath; + } + // Load the global theme settings (style + color scheme preference) + static ThemeConfig loadGlobalConfig(const QString &themeDirPath); + static bool saveGlobalConfig(const QString &themeDirPath, const ThemeConfig &cfg); + + // Load/save per-scheme palette colors + static PaletteConfig loadPaletteConfig(const QString &themeDirPath, const QString &colorScheme); + static bool savePaletteConfig(const QString &themeDirPath, const QString &colorScheme, const PaletteConfig &cfg); + void setColorScheme(const QString &scheme); + + void reloadCurrentTheme(); + void previewPalette(const PaletteConfig &cfg, const QString &scheme); QBrush &getBgBrush(Role zone); QBrush getExtraBgBrush(Role zone, int zoneId = 0); diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_settings.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_settings.cpp index 7da0a9207..4323ed724 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_settings.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_settings.cpp @@ -2,6 +2,7 @@ #include "../../../client/settings/cache_settings.h" #include "../../../client/settings/shortcut_treeview.h" +#include "../../palette_editor/palette_editor_dialog.h" #include "../client/network/update/card_spoiler/spoiler_background_updater.h" #include "../client/network/update/client/release_channel.h" #include "../client/sound_engine.h" @@ -433,6 +434,35 @@ AppearanceSettingsPage::AppearanceSettingsPage() connect(&themeBox, qOverload(&QComboBox::currentIndexChanged), this, &AppearanceSettingsPage::themeBoxChanged); connect(&openThemeButton, &QPushButton::clicked, this, &AppearanceSettingsPage::openThemeLocation); + schemeCombo.addItem(tr("Light"), QStringLiteral("Light")); + schemeCombo.addItem(tr("Dark"), QStringLiteral("Dark")); +#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0) + schemeCombo.addItem(tr("System"), QStringLiteral("System")); +#endif + + // Seed from whatever the current theme already has saved + const QString dirPath = themeManager->getAvailableThemes().value(SettingsCache::instance().getThemeName()); + const ThemeConfig cfg = ThemeConfig::fromThemeDir(dirPath); + const QString current = cfg.colorScheme; + const int seedIdx = schemeCombo.findData(current); + schemeCombo.setCurrentIndex(seedIdx >= 0 ? seedIdx : 0); + + connect(&schemeCombo, &QComboBox::currentIndexChanged, this, + [this] { themeManager->setColorScheme(schemeCombo.currentData().toString()); }); + + connect(themeManager, &ThemeManager::themeChanged, this, [this, dirPath] { + const QString newDir = themeManager->getAvailableThemes().value(SettingsCache::instance().getThemeName()); + const ThemeConfig cfg = ThemeConfig::fromThemeDir(newDir); + const QString current = cfg.colorScheme; + + schemeCombo.blockSignals(true); + const int idx = schemeCombo.findData(current); + schemeCombo.setCurrentIndex(idx >= 0 ? idx : 0); + schemeCombo.blockSignals(false); + }); + + connect(&editPaletteButton, &QPushButton::clicked, this, &AppearanceSettingsPage::editPalette); + for (const auto &entry : BackgroundSources::all()) { homeTabBackgroundSourceBox.addItem(QObject::tr(entry.trKey), QVariant::fromValue(entry.type)); } @@ -466,12 +496,15 @@ AppearanceSettingsPage::AppearanceSettingsPage() themeGrid->addWidget(&themeLabel, 0, 0); themeGrid->addWidget(&themeBox, 0, 1); themeGrid->addWidget(&openThemeButton, 1, 1); - themeGrid->addWidget(&homeTabBackgroundSourceLabel, 2, 0); - themeGrid->addWidget(&homeTabBackgroundSourceBox, 2, 1); - themeGrid->addWidget(&homeTabBackgroundShuffleFrequencyLabel, 3, 0); - themeGrid->addWidget(&homeTabBackgroundShuffleFrequencySpinBox, 3, 1); - themeGrid->addWidget(&homeTabDisplayCardNameLabel, 4, 0); - themeGrid->addWidget(&homeTabDisplayCardNameCheckBox, 4, 1); + themeGrid->addWidget(&schemeComboLabel, 2, 0); + themeGrid->addWidget(&schemeCombo, 2, 1); + themeGrid->addWidget(&editPaletteButton, 3, 1); + themeGrid->addWidget(&homeTabBackgroundSourceLabel, 4, 0); + themeGrid->addWidget(&homeTabBackgroundSourceBox, 4, 1); + themeGrid->addWidget(&homeTabBackgroundShuffleFrequencyLabel, 5, 0); + themeGrid->addWidget(&homeTabBackgroundShuffleFrequencySpinBox, 5, 1); + themeGrid->addWidget(&homeTabDisplayCardNameLabel, 6, 0); + themeGrid->addWidget(&homeTabDisplayCardNameCheckBox, 6, 1); themeGroupBox = new QGroupBox; themeGroupBox->setLayout(themeGrid); @@ -670,6 +703,12 @@ void AppearanceSettingsPage::openThemeLocation() } } +void AppearanceSettingsPage::editPalette() +{ + PaletteEditorDialog dlg(themeManager->getCurrentThemePath(), SettingsCache::instance().getThemeName(), this); + dlg.exec(); +} + void AppearanceSettingsPage::updateHomeTabSettingsVisibility() { bool visible = @@ -734,6 +773,8 @@ void AppearanceSettingsPage::retranslateUi() themeGroupBox->setTitle(tr("Theme settings")); themeLabel.setText(tr("Current theme:")); openThemeButton.setText(tr("Open themes folder")); + schemeComboLabel.setText(tr("Active theme palette")); + editPaletteButton.setText(tr("Edit theme palette")); homeTabBackgroundSourceLabel.setText(tr("Home tab background source:")); homeTabBackgroundShuffleFrequencyLabel.setText(tr("Home tab background shuffle frequency:")); homeTabBackgroundShuffleFrequencySpinBox.setSpecialValueText(tr("Disabled")); diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_settings.h b/cockatrice/src/interface/widgets/dialogs/dlg_settings.h index 42268e997..86266347f 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_settings.h +++ b/cockatrice/src/interface/widgets/dialogs/dlg_settings.h @@ -103,6 +103,7 @@ class AppearanceSettingsPage : public AbstractSettingsPage private slots: void themeBoxChanged(int index); void openThemeLocation(); + void editPalette(); void updateHomeTabSettingsVisibility(); void showShortcutsChanged(QT_STATE_CHANGED_T enabled); void overrideAllCardArtWithPersonalPreferenceToggled(QT_STATE_CHANGED_T enabled); @@ -114,6 +115,9 @@ private: QLabel themeLabel; QComboBox themeBox; QPushButton openThemeButton; + QLabel schemeComboLabel; + QComboBox schemeCombo; + QPushButton editPaletteButton; QLabel homeTabBackgroundSourceLabel; QComboBox homeTabBackgroundSourceBox; QLabel homeTabBackgroundShuffleFrequencyLabel; diff --git a/cockatrice/themes/Default/palette-default-dark.toml b/cockatrice/themes/Default/palette-default-dark.toml new file mode 100644 index 000000000..3ee174a2f --- /dev/null +++ b/cockatrice/themes/Default/palette-default-dark.toml @@ -0,0 +1,63 @@ +[Palette] +WindowText = #ffffffff +Button = #ff383838 +Light = #ff737373 +Midlight = #ff525252 +Dark = #ff161616 +Mid = #ff252525 +Text = #ffffffff +BrightText = #ffb4dd8b +ButtonText = #ffffffff +Base = #ff2b2b2b +Window = #ff1c1c1c +Shadow = #ff000000 +HighlightedText = #ff000000 +Link = #ffcde4b6 +LinkVisited = #ff99d999 +AlternateBase = #ff242424 +ToolTipBase = #ffffffdc +ToolTipText = #ff000000 +PlaceholderText = #6effffff + +[Palette.Disabled] +WindowText = #ff9d9d9d +Button = #ff1c1c1c +Light = #ff737373 +Midlight = #ff525252 +Dark = #ff161616 +Mid = #ff252525 +Text = #ff9d9d9d +BrightText = #ffb4dd8b +ButtonText = #ff787878 +Base = #ff1c1c1c +Window = #ff1c1c1c +Shadow = #ff000000 +HighlightedText = #ff9d9d9d +Link = #ff308cc6 +LinkVisited = #ffb450ff +AlternateBase = #ff242424 +ToolTipBase = #ffffffdc +ToolTipText = #ff000000 +PlaceholderText = #46ffffff + +[Palette.Inactive] +WindowText = #ffffffff +Button = #ff383838 +Light = #ff737373 +Midlight = #ff525252 +Dark = #ff161616 +Mid = #ff252525 +Text = #ffffffff +BrightText = #ffb4dd8b +ButtonText = #ffffffff +Base = #ff2b2b2b +Window = #ff1c1c1c +Shadow = #ff000000 +HighlightedText = #ffffffff +Link = #ffcde4b6 +LinkVisited = #ff99d999 +AlternateBase = #ff242424 +ToolTipBase = #ffffffdc +ToolTipText = #ff000000 +PlaceholderText = #6effffff + diff --git a/cockatrice/themes/Default/theme.cfg b/cockatrice/themes/Default/theme.cfg new file mode 100644 index 000000000..d2016a238 --- /dev/null +++ b/cockatrice/themes/Default/theme.cfg @@ -0,0 +1,5 @@ +[Appearance] +ColorScheme = Light + +[Style] +Name = Default diff --git a/cockatrice/themes/Fusion/palette-default-dark.toml b/cockatrice/themes/Fusion/palette-default-dark.toml new file mode 100644 index 000000000..c1d83a4cd --- /dev/null +++ b/cockatrice/themes/Fusion/palette-default-dark.toml @@ -0,0 +1,69 @@ +[Palette] +WindowText = #ffffffff +Button = #ff3c3c3c +Light = #ff787878 +Midlight = #ff5a5a5a +Dark = #ff1e1e1e +Mid = #ff282828 +Text = #ffffffff +BrightText = #ff00f652 +ButtonText = #ffffffff +Base = #ff2d2d2d +Window = #ff1e1e1e +Shadow = #ff000000 +Highlight = #ff148c3c +HighlightedText = #ffffffff +Link = #ff00f652 +LinkVisited = #ff00d346 +AlternateBase = #ff353535 +ToolTipBase = #ff3c3c3c +ToolTipText = #ffd4d4d4 +PlaceholderText = #80ffffff +Accent = #ff00d346 + +[Palette.Disabled] +WindowText = #ff9d9d9d +Button = #ff3c3c3c +Light = #ff787878 +Midlight = #ff5a5a5a +Dark = #ff1e1e1e +Mid = #ff282828 +Text = #ff9d9d9d +BrightText = #ff00f652 +ButtonText = #ff9d9d9d +Base = #ff1e1e1e +Window = #ff1e1e1e +Shadow = #ff000000 +Highlight = #ff148c3c +HighlightedText = #ffffffff +Link = #ff308cc6 +LinkVisited = #ffff00ff +AlternateBase = #ff353535 +ToolTipBase = #ffffffdc +ToolTipText = #ff000000 +PlaceholderText = #80ffffff +Accent = #ff9d9d9d + +[Palette.Inactive] +WindowText = #ffffffff +Button = #ff3c3c3c +Light = #ff787878 +Midlight = #ff5a5a5a +Dark = #ff1e1e1e +Mid = #ff282828 +Text = #ffffffff +BrightText = #ff00f652 +ButtonText = #ffffffff +Base = #ff2d2d2d +Window = #ff1e1e1e +Shadow = #ff000000 +Highlight = #ff1e1e1e +HighlightedText = #ffffffff +Link = #ff00f652 +LinkVisited = #ff00d346 +AlternateBase = #ff353535 +ToolTipBase = #ff3c3c3c +ToolTipText = #ffd4d4d4 +PlaceholderText = #80ffffff +Accent = #ff1e1e1e + diff --git a/cockatrice/themes/Fusion/palette-default-light.toml b/cockatrice/themes/Fusion/palette-default-light.toml new file mode 100644 index 000000000..86c41be78 --- /dev/null +++ b/cockatrice/themes/Fusion/palette-default-light.toml @@ -0,0 +1,69 @@ +[Palette] +WindowText = #ff000000 +Button = #fff0f0f0 +Light = #ffffffff +Midlight = #ffe3e3e3 +Dark = #ffa0a0a0 +Mid = #ffa0a0a0 +Text = #ff000000 +BrightText = #ffffffff +ButtonText = #ff000000 +Base = #ffffffff +Window = #fff0f0f0 +Shadow = #ff696969 +Highlight = #ff148c3c +HighlightedText = #ffffffff +Link = #ff0d5f28 +LinkVisited = #ff08401b +AlternateBase = #ffe9e7e3 +ToolTipBase = #ffffffdc +ToolTipText = #ff000000 +PlaceholderText = #80000000 +Accent = #ff107532 + +[Palette.Disabled] +WindowText = #ff787878 +Button = #fff0f0f0 +Light = #ffffffff +Midlight = #fff7f7f7 +Dark = #ffa0a0a0 +Mid = #ffa0a0a0 +Text = #ff787878 +BrightText = #ffffffff +ButtonText = #ff787878 +Base = #fff0f0f0 +Window = #fff0f0f0 +Shadow = #ff000000 +Highlight = #ff148c3c +HighlightedText = #ffffffff +Link = #ff0000ff +LinkVisited = #ffff00ff +AlternateBase = #fff7f7f7 +ToolTipBase = #ffffffdc +ToolTipText = #ff000000 +PlaceholderText = #80000000 +Accent = #ff787878 + +[Palette.Inactive] +WindowText = #ff000000 +Button = #fff0f0f0 +Light = #ffffffff +Midlight = #ffe3e3e3 +Dark = #ffa0a0a0 +Mid = #ffa0a0a0 +Text = #ff000000 +BrightText = #ffffffff +ButtonText = #ff000000 +Base = #ffffffff +Window = #fff0f0f0 +Shadow = #ff696969 +Highlight = #fff0f0f0 +HighlightedText = #ff000000 +Link = #ff0d5f28 +LinkVisited = #ff08401b +AlternateBase = #ffe9e7e3 +ToolTipBase = #ffffffdc +ToolTipText = #ff000000 +PlaceholderText = #80000000 +Accent = #fff0f0f0 + diff --git a/cockatrice/themes/Fusion/theme.cfg b/cockatrice/themes/Fusion/theme.cfg new file mode 100644 index 000000000..9b38e505e --- /dev/null +++ b/cockatrice/themes/Fusion/theme.cfg @@ -0,0 +1,5 @@ +[Appearance] +ColorScheme = Dark + +[Style] +Name = Fusion diff --git a/oracle/CMakeLists.txt b/oracle/CMakeLists.txt index 3bb4de5df..a51982625 100644 --- a/oracle/CMakeLists.txt +++ b/oracle/CMakeLists.txt @@ -28,6 +28,7 @@ set(oracle_SOURCES ../cockatrice/src/client/settings/card_counter_settings.cpp ../cockatrice/src/client/settings/shortcuts_settings.cpp ../cockatrice/src/client/network/update/client/release_channel.cpp + ../cockatrice/src/interface/theme_config.cpp ../cockatrice/src/interface/theme_manager.cpp ../cockatrice/src/interface/widgets/quick_settings/settings_button_widget.cpp ../cockatrice/src/interface/widgets/quick_settings/settings_popup_widget.cpp From 059eeebe89011f3d45660745bd6b38e6c14ed561 Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Sun, 17 May 2026 10:12:34 +0200 Subject: [PATCH 14/51] [Settings] Fix typo for schemeComboLabel (#6897) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Took 6 minutes Co-authored-by: Lukas Brübach --- cockatrice/src/interface/widgets/dialogs/dlg_settings.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_settings.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_settings.cpp index 4323ed724..d9f0c0fe4 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_settings.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_settings.cpp @@ -773,7 +773,7 @@ void AppearanceSettingsPage::retranslateUi() themeGroupBox->setTitle(tr("Theme settings")); themeLabel.setText(tr("Current theme:")); openThemeButton.setText(tr("Open themes folder")); - schemeComboLabel.setText(tr("Active theme palette")); + schemeComboLabel.setText(tr("Active theme palette:")); editPaletteButton.setText(tr("Edit theme palette")); homeTabBackgroundSourceLabel.setText(tr("Home tab background source:")); homeTabBackgroundShuffleFrequencyLabel.setText(tr("Home tab background shuffle frequency:")); From 6ac340026f4e363ab0f8b1feacbb34296d782782 Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Sun, 17 May 2026 16:15:15 +0200 Subject: [PATCH 15/51] Update CMakeLists.txt (#6898) --- cockatrice/themes/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cockatrice/themes/CMakeLists.txt b/cockatrice/themes/CMakeLists.txt index 3e07c54dd..577977551 100644 --- a/cockatrice/themes/CMakeLists.txt +++ b/cockatrice/themes/CMakeLists.txt @@ -2,7 +2,7 @@ # # add themes subfolders -set(defthemes Fabric Leather Plasma VelvetMarble) +set(defthemes Default Fabric Fusion Leather Plasma VelvetMarble) if(UNIX) if(APPLE) From bb1a5b33a113fb5e5af825310ae6fa1f7c3c2304 Mon Sep 17 00:00:00 2001 From: SlightlyCircuitous <71394296+SlightlyCircuitous@users.noreply.github.com> Date: Sun, 17 May 2026 13:48:48 -0400 Subject: [PATCH 16/51] Add generic colorless mana symbol (#6873) * Add generic colorless mana symbol * Add generic colorless mana symbol --- cockatrice/cockatrice.qrc | 1 + cockatrice/resources/icons/mana/C.svg | 72 +++++++++++++++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 cockatrice/resources/icons/mana/C.svg diff --git a/cockatrice/cockatrice.qrc b/cockatrice/cockatrice.qrc index 00f9f0284..9c34929b7 100644 --- a/cockatrice/cockatrice.qrc +++ b/cockatrice/cockatrice.qrc @@ -55,6 +55,7 @@ resources/icons/view.svg resources/icons/mana/B.svg + resources/icons/mana/C.svg resources/icons/mana/G.svg resources/icons/mana/R.svg resources/icons/mana/U.svg diff --git a/cockatrice/resources/icons/mana/C.svg b/cockatrice/resources/icons/mana/C.svg new file mode 100644 index 000000000..eb09fb872 --- /dev/null +++ b/cockatrice/resources/icons/mana/C.svg @@ -0,0 +1,72 @@ + + + + + + + + + + + + + From cba9ce2b2b0704fc9e2c508ea523eb2b42570660 Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Mon, 18 May 2026 06:36:18 +0200 Subject: [PATCH 17/51] [Game/Zones] Simple move refactor to differentiate between logic and graphics for zones (#6903) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [Game/Zones] Simple move refactor to differentiate between logic and graphics for zones Took 21 minutes * Clean up game/zones/logic folder. Took 6 minutes * Adjust tests. Took 3 minutes --------- Co-authored-by: Lukas Brübach --- cockatrice/CMakeLists.txt | 28 +++++++++---------- cockatrice/src/game/board/arrow_item.cpp | 2 +- cockatrice/src/game/board/card_drag_item.cpp | 6 ++-- cockatrice/src/game/board/card_item.cpp | 6 ++-- cockatrice/src/game/board/card_item.h | 2 +- cockatrice/src/game/game_scene.cpp | 6 ++-- cockatrice/src/game/game_scene.h | 2 +- cockatrice/src/game/hand_counter.cpp | 2 +- cockatrice/src/game/log/message_log_widget.h | 2 +- cockatrice/src/game/player/menu/card_menu.cpp | 2 +- cockatrice/src/game/player/menu/hand_menu.cpp | 2 +- .../src/game/player/menu/player_menu.cpp | 6 ++-- cockatrice/src/game/player/player.cpp | 8 +++--- cockatrice/src/game/player/player.h | 8 +++--- cockatrice/src/game/player/player_actions.cpp | 6 ++-- .../src/game/player/player_event_handler.cpp | 2 +- .../src/game/player/player_graphics_item.cpp | 8 +++--- .../zones/{logic => }/card_zone_algorithms.h | 0 .../zones/{logic => }/card_zone_logic.cpp | 8 +++--- .../game/zones/{logic => }/card_zone_logic.h | 4 +-- .../zones/{logic => }/hand_zone_logic.cpp | 2 +- .../game/zones/{logic => }/hand_zone_logic.h | 0 .../zones/{logic => }/pile_zone_logic.cpp | 2 +- .../game/zones/{logic => }/pile_zone_logic.h | 0 .../zones/{logic => }/stack_zone_logic.cpp | 2 +- .../game/zones/{logic => }/stack_zone_logic.h | 0 .../zones/{logic => }/table_zone_logic.cpp | 2 +- .../game/zones/{logic => }/table_zone_logic.h | 0 .../zones/{logic => }/view_zone_logic.cpp | 4 +-- .../game/zones/{logic => }/view_zone_logic.h | 0 .../zones/card_zone.cpp | 2 +- .../{game => game_graphics}/zones/card_zone.h | 6 ++-- .../zones/hand_zone.cpp | 8 +++--- .../{game => game_graphics}/zones/hand_zone.h | 2 +- .../zones/pile_zone.cpp | 10 +++---- .../{game => game_graphics}/zones/pile_zone.h | 2 +- .../zones/select_zone.cpp | 4 +-- .../zones/select_zone.h | 0 .../zones/stack_zone.cpp | 12 ++++---- .../zones/stack_zone.h | 2 +- .../zones/table_zone.cpp | 14 +++++----- .../zones/table_zone.h | 4 +-- .../zones/view_zone.cpp | 10 +++---- .../{game => game_graphics}/zones/view_zone.h | 2 +- .../zones/view_zone_widget.cpp | 10 +++---- .../zones/view_zone_widget.h | 2 +- tests/card_zone_algorithms/CMakeLists.txt | 2 +- 47 files changed, 107 insertions(+), 107 deletions(-) rename cockatrice/src/game/zones/{logic => }/card_zone_algorithms.h (100%) rename cockatrice/src/game/zones/{logic => }/card_zone_logic.cpp (98%) rename cockatrice/src/game/zones/{logic => }/card_zone_logic.h (97%) rename cockatrice/src/game/zones/{logic => }/hand_zone_logic.cpp (94%) rename cockatrice/src/game/zones/{logic => }/hand_zone_logic.h (100%) rename cockatrice/src/game/zones/{logic => }/pile_zone_logic.cpp (96%) rename cockatrice/src/game/zones/{logic => }/pile_zone_logic.h (100%) rename cockatrice/src/game/zones/{logic => }/stack_zone_logic.cpp (94%) rename cockatrice/src/game/zones/{logic => }/stack_zone_logic.h (100%) rename cockatrice/src/game/zones/{logic => }/table_zone_logic.cpp (96%) rename cockatrice/src/game/zones/{logic => }/table_zone_logic.h (100%) rename cockatrice/src/game/zones/{logic => }/view_zone_logic.cpp (98%) rename cockatrice/src/game/zones/{logic => }/view_zone_logic.h (100%) rename cockatrice/src/{game => game_graphics}/zones/card_zone.cpp (97%) rename cockatrice/src/{game => game_graphics}/zones/card_zone.h (92%) rename cockatrice/src/{game => game_graphics}/zones/hand_zone.cpp (96%) rename cockatrice/src/{game => game_graphics}/zones/hand_zone.h (95%) rename cockatrice/src/{game => game_graphics}/zones/pile_zone.cpp (95%) rename cockatrice/src/{game => game_graphics}/zones/pile_zone.h (96%) rename cockatrice/src/{game => game_graphics}/zones/select_zone.cpp (99%) rename cockatrice/src/{game => game_graphics}/zones/select_zone.h (100%) rename cockatrice/src/{game => game_graphics}/zones/stack_zone.cpp (91%) rename cockatrice/src/{game => game_graphics}/zones/stack_zone.h (94%) rename cockatrice/src/{game => game_graphics}/zones/table_zone.cpp (97%) rename cockatrice/src/{game => game_graphics}/zones/table_zone.h (98%) rename cockatrice/src/{game => game_graphics}/zones/view_zone.cpp (98%) rename cockatrice/src/{game => game_graphics}/zones/view_zone.h (98%) rename cockatrice/src/{game => game_graphics}/zones/view_zone_widget.cpp (99%) rename cockatrice/src/{game => game_graphics}/zones/view_zone_widget.h (98%) diff --git a/cockatrice/CMakeLists.txt b/cockatrice/CMakeLists.txt index a4e357f60..ab47aff80 100644 --- a/cockatrice/CMakeLists.txt +++ b/cockatrice/CMakeLists.txt @@ -104,20 +104,20 @@ set(cockatrice_SOURCES src/game/player/player_manager.cpp src/game/player/player_target.cpp src/game/replay.cpp - src/game/zones/card_zone.cpp - src/game/zones/hand_zone.cpp - src/game/zones/logic/card_zone_logic.cpp - src/game/zones/logic/hand_zone_logic.cpp - src/game/zones/logic/pile_zone_logic.cpp - src/game/zones/logic/stack_zone_logic.cpp - src/game/zones/logic/table_zone_logic.cpp - src/game/zones/logic/view_zone_logic.cpp - src/game/zones/pile_zone.cpp - src/game/zones/select_zone.cpp - src/game/zones/stack_zone.cpp - src/game/zones/table_zone.cpp - src/game/zones/view_zone.cpp - src/game/zones/view_zone_widget.cpp + src/game/zones/card_zone_logic.cpp + src/game/zones/hand_zone_logic.cpp + src/game/zones/pile_zone_logic.cpp + src/game/zones/stack_zone_logic.cpp + src/game/zones/table_zone_logic.cpp + src/game/zones/view_zone_logic.cpp + src/game_graphics/zones/card_zone.cpp + src/game_graphics/zones/hand_zone.cpp + src/game_graphics/zones/pile_zone.cpp + src/game_graphics/zones/select_zone.cpp + src/game_graphics/zones/stack_zone.cpp + src/game_graphics/zones/table_zone.cpp + src/game_graphics/zones/view_zone.cpp + src/game_graphics/zones/view_zone_widget.cpp src/game_graphics/board/abstract_graphics_item.cpp src/interface/card_picture_loader/card_picture_loader.cpp src/interface/card_picture_loader/card_picture_loader_local.cpp diff --git a/cockatrice/src/game/board/arrow_item.cpp b/cockatrice/src/game/board/arrow_item.cpp index 53d8ea33e..498a3dfab 100644 --- a/cockatrice/src/game/board/arrow_item.cpp +++ b/cockatrice/src/game/board/arrow_item.cpp @@ -2,11 +2,11 @@ #include "arrow_item.h" #include "../../client/settings/cache_settings.h" +#include "../../game_graphics/zones/card_zone.h" #include "../player/player.h" #include "../player/player_actions.h" #include "../player/player_target.h" #include "../z_values.h" -#include "../zones/card_zone.h" #include "card_item.h" #include diff --git a/cockatrice/src/game/board/card_drag_item.cpp b/cockatrice/src/game/board/card_drag_item.cpp index 49467c5c9..39fb9a390 100644 --- a/cockatrice/src/game/board/card_drag_item.cpp +++ b/cockatrice/src/game/board/card_drag_item.cpp @@ -1,9 +1,9 @@ #include "card_drag_item.h" +#include "../../game_graphics/zones/card_zone.h" +#include "../../game_graphics/zones/table_zone.h" +#include "../../game_graphics/zones/view_zone.h" #include "../game_scene.h" -#include "../zones/card_zone.h" -#include "../zones/table_zone.h" -#include "../zones/view_zone.h" #include "card_item.h" #include diff --git a/cockatrice/src/game/board/card_item.cpp b/cockatrice/src/game/board/card_item.cpp index 695e94a3a..d85937894 100644 --- a/cockatrice/src/game/board/card_item.cpp +++ b/cockatrice/src/game/board/card_item.cpp @@ -1,14 +1,14 @@ #include "card_item.h" #include "../../client/settings/cache_settings.h" +#include "../../game_graphics/zones/table_zone.h" +#include "../../game_graphics/zones/view_zone.h" #include "../../interface/widgets/tabs/tab_game.h" #include "../game_scene.h" #include "../phase.h" #include "../player/player.h" #include "../player/player_actions.h" -#include "../zones/logic/view_zone_logic.h" -#include "../zones/table_zone.h" -#include "../zones/view_zone.h" +#include "../zones/view_zone_logic.h" #include "arrow_item.h" #include "card_drag_item.h" diff --git a/cockatrice/src/game/board/card_item.h b/cockatrice/src/game/board/card_item.h index 9799b5067..c0dd03d3d 100644 --- a/cockatrice/src/game/board/card_item.h +++ b/cockatrice/src/game/board/card_item.h @@ -7,7 +7,7 @@ #ifndef CARDITEM_H #define CARDITEM_H -#include "../zones/logic/card_zone_logic.h" +#include "../zones/card_zone_logic.h" #include "abstract_card_item.h" #include diff --git a/cockatrice/src/game/game_scene.cpp b/cockatrice/src/game/game_scene.cpp index 9141a9d54..b5026ad33 100644 --- a/cockatrice/src/game/game_scene.cpp +++ b/cockatrice/src/game/game_scene.cpp @@ -1,13 +1,13 @@ #include "game_scene.h" #include "../client/settings/cache_settings.h" +#include "../game_graphics/zones/select_zone.h" +#include "../game_graphics/zones/view_zone.h" +#include "../game_graphics/zones/view_zone_widget.h" #include "board/card_item.h" #include "phases_toolbar.h" #include "player/player.h" #include "player/player_graphics_item.h" -#include "zones/select_zone.h" -#include "zones/view_zone.h" -#include "zones/view_zone_widget.h" #include #include diff --git a/cockatrice/src/game/game_scene.h b/cockatrice/src/game/game_scene.h index 6d491297c..0cb332ad0 100644 --- a/cockatrice/src/game/game_scene.h +++ b/cockatrice/src/game/game_scene.h @@ -1,7 +1,7 @@ #ifndef GAMESCENE_H #define GAMESCENE_H -#include "zones/logic/card_zone_logic.h" +#include "zones/card_zone_logic.h" #include #include diff --git a/cockatrice/src/game/hand_counter.cpp b/cockatrice/src/game/hand_counter.cpp index 35989ff38..a853ae2de 100644 --- a/cockatrice/src/game/hand_counter.cpp +++ b/cockatrice/src/game/hand_counter.cpp @@ -1,6 +1,6 @@ #include "hand_counter.h" -#include "zones/card_zone.h" +#include "../game_graphics/zones/card_zone.h" #include #include diff --git a/cockatrice/src/game/log/message_log_widget.h b/cockatrice/src/game/log/message_log_widget.h index 369debd33..78f830e53 100644 --- a/cockatrice/src/game/log/message_log_widget.h +++ b/cockatrice/src/game/log/message_log_widget.h @@ -8,7 +8,7 @@ #define MESSAGELOGWIDGET_H #include "../../interface/widgets/server/chat_view/chat_view.h" -#include "../zones/logic/card_zone_logic.h" +#include "../zones/card_zone_logic.h" class AbstractGame; class CardItem; diff --git a/cockatrice/src/game/player/menu/card_menu.cpp b/cockatrice/src/game/player/menu/card_menu.cpp index 54403e237..9ece326cc 100644 --- a/cockatrice/src/game/player/menu/card_menu.cpp +++ b/cockatrice/src/game/player/menu/card_menu.cpp @@ -3,7 +3,7 @@ #include "../../../client/settings/card_counter_settings.h" #include "../../../interface/widgets/tabs/tab_game.h" #include "../../board/card_item.h" -#include "../../zones/logic/view_zone_logic.h" +#include "../../zones/view_zone_logic.h" #include "../card_menu_action_type.h" #include "../player.h" #include "../player_actions.h" diff --git a/cockatrice/src/game/player/menu/hand_menu.cpp b/cockatrice/src/game/player/menu/hand_menu.cpp index 1b1ec27d6..156bf2aa9 100644 --- a/cockatrice/src/game/player/menu/hand_menu.cpp +++ b/cockatrice/src/game/player/menu/hand_menu.cpp @@ -2,8 +2,8 @@ #include "../../../client/settings/cache_settings.h" #include "../../../client/settings/shortcuts_settings.h" +#include "../../../game_graphics/zones/hand_zone.h" #include "../../abstract_game.h" -#include "../../zones/hand_zone.h" #include "../player.h" #include "../player_actions.h" diff --git a/cockatrice/src/game/player/menu/player_menu.cpp b/cockatrice/src/game/player/menu/player_menu.cpp index 0dc381e28..8a0e4af8b 100644 --- a/cockatrice/src/game/player/menu/player_menu.cpp +++ b/cockatrice/src/game/player/menu/player_menu.cpp @@ -1,10 +1,10 @@ #include "player_menu.h" +#include "../../../game_graphics/zones/hand_zone.h" +#include "../../../game_graphics/zones/pile_zone.h" +#include "../../../game_graphics/zones/table_zone.h" #include "../../../interface/widgets/tabs/tab_game.h" #include "../../board/card_item.h" -#include "../../zones/hand_zone.h" -#include "../../zones/pile_zone.h" -#include "../../zones/table_zone.h" #include "card_menu.h" #include "hand_menu.h" diff --git a/cockatrice/src/game/player/player.cpp b/cockatrice/src/game/player/player.cpp index b130bcf75..b1814a587 100644 --- a/cockatrice/src/game/player/player.cpp +++ b/cockatrice/src/game/player/player.cpp @@ -1,5 +1,9 @@ #include "player.h" +#include "../../game_graphics/zones/hand_zone.h" +#include "../../game_graphics/zones/pile_zone.h" +#include "../../game_graphics/zones/stack_zone.h" +#include "../../game_graphics/zones/table_zone.h" #include "../../interface/theme_manager.h" #include "../../interface/widgets/tabs/tab_game.h" #include "../board/arrow_item.h" @@ -7,10 +11,6 @@ #include "../board/card_list.h" #include "../board/counter_general.h" #include "../game_scene.h" -#include "../zones/hand_zone.h" -#include "../zones/pile_zone.h" -#include "../zones/stack_zone.h" -#include "../zones/table_zone.h" #include "player_actions.h" #include "player_target.h" diff --git a/cockatrice/src/game/player/player.h b/cockatrice/src/game/player/player.h index 1e7bc928d..f9ab10207 100644 --- a/cockatrice/src/game/player/player.h +++ b/cockatrice/src/game/player/player.h @@ -10,10 +10,10 @@ #include "../../game_graphics/board/abstract_graphics_item.h" #include "../../interface/widgets/menus/tearoff_menu.h" #include "../interface/deck_loader/loaded_deck.h" -#include "../zones/logic/hand_zone_logic.h" -#include "../zones/logic/pile_zone_logic.h" -#include "../zones/logic/stack_zone_logic.h" -#include "../zones/logic/table_zone_logic.h" +#include "../zones/hand_zone_logic.h" +#include "../zones/pile_zone_logic.h" +#include "../zones/stack_zone_logic.h" +#include "../zones/table_zone_logic.h" #include "menu/player_menu.h" #include "player_area.h" #include "player_event_handler.h" diff --git a/cockatrice/src/game/player/player_actions.cpp b/cockatrice/src/game/player/player_actions.cpp index 2be9c90ba..c36cdaa1a 100644 --- a/cockatrice/src/game/player/player_actions.cpp +++ b/cockatrice/src/game/player/player_actions.cpp @@ -1,14 +1,14 @@ #include "player_actions.h" +#include "../../game_graphics/zones/hand_zone.h" +#include "../../game_graphics/zones/table_zone.h" #include "../../interface/widgets/tabs/tab_game.h" #include "../../interface/widgets/utility/get_text_with_max.h" #include "../board/card_item.h" #include "../client/settings/card_counter_settings.h" #include "../dialogs/dlg_move_top_cards_until.h" #include "../dialogs/dlg_roll_dice.h" -#include "../zones/hand_zone.h" -#include "../zones/logic/view_zone_logic.h" -#include "../zones/table_zone.h" +#include "../zones/view_zone_logic.h" #include "card_menu_action_type.h" #include diff --git a/cockatrice/src/game/player/player_event_handler.cpp b/cockatrice/src/game/player/player_event_handler.cpp index dc1e2393c..afc32208d 100644 --- a/cockatrice/src/game/player/player_event_handler.cpp +++ b/cockatrice/src/game/player/player_event_handler.cpp @@ -1,10 +1,10 @@ #include "player_event_handler.h" +#include "../../game_graphics/zones/view_zone.h" #include "../../interface/widgets/tabs/tab_game.h" #include "../board/arrow_item.h" #include "../board/card_item.h" #include "../board/card_list.h" -#include "../zones/view_zone.h" #include "player.h" #include "player_actions.h" diff --git a/cockatrice/src/game/player/player_graphics_item.cpp b/cockatrice/src/game/player/player_graphics_item.cpp index bcc4b7f72..a4f515274 100644 --- a/cockatrice/src/game/player/player_graphics_item.cpp +++ b/cockatrice/src/game/player/player_graphics_item.cpp @@ -1,12 +1,12 @@ #include "player_graphics_item.h" +#include "../../game_graphics/zones/hand_zone.h" +#include "../../game_graphics/zones/pile_zone.h" +#include "../../game_graphics/zones/stack_zone.h" +#include "../../game_graphics/zones/table_zone.h" #include "../../interface/widgets/tabs/tab_game.h" #include "../board/abstract_card_item.h" #include "../hand_counter.h" -#include "../zones/hand_zone.h" -#include "../zones/pile_zone.h" -#include "../zones/stack_zone.h" -#include "../zones/table_zone.h" PlayerGraphicsItem::PlayerGraphicsItem(Player *_player) : player(_player) { diff --git a/cockatrice/src/game/zones/logic/card_zone_algorithms.h b/cockatrice/src/game/zones/card_zone_algorithms.h similarity index 100% rename from cockatrice/src/game/zones/logic/card_zone_algorithms.h rename to cockatrice/src/game/zones/card_zone_algorithms.h diff --git a/cockatrice/src/game/zones/logic/card_zone_logic.cpp b/cockatrice/src/game/zones/card_zone_logic.cpp similarity index 98% rename from cockatrice/src/game/zones/logic/card_zone_logic.cpp rename to cockatrice/src/game/zones/card_zone_logic.cpp index 9d9b3767f..411aa19a9 100644 --- a/cockatrice/src/game/zones/logic/card_zone_logic.cpp +++ b/cockatrice/src/game/zones/card_zone_logic.cpp @@ -1,9 +1,9 @@ #include "card_zone_logic.h" -#include "../../board/card_item.h" -#include "../../player/player.h" -#include "../../player/player_actions.h" -#include "../view_zone.h" +#include "../../game_graphics/zones/view_zone.h" +#include "../board/card_item.h" +#include "../player/player.h" +#include "../player/player_actions.h" #include "view_zone_logic.h" #include diff --git a/cockatrice/src/game/zones/logic/card_zone_logic.h b/cockatrice/src/game/zones/card_zone_logic.h similarity index 97% rename from cockatrice/src/game/zones/logic/card_zone_logic.h rename to cockatrice/src/game/zones/card_zone_logic.h index 1aa46effd..af770b104 100644 --- a/cockatrice/src/game/zones/logic/card_zone_logic.h +++ b/cockatrice/src/game/zones/card_zone_logic.h @@ -7,8 +7,8 @@ #ifndef COCKATRICE_CARD_ZONE_LOGIC_H #define COCKATRICE_CARD_ZONE_LOGIC_H -#include "../../../client/translation.h" -#include "../../board/card_list.h" +#include "../../client/translation.h" +#include "../board/card_list.h" #include #include diff --git a/cockatrice/src/game/zones/logic/hand_zone_logic.cpp b/cockatrice/src/game/zones/hand_zone_logic.cpp similarity index 94% rename from cockatrice/src/game/zones/logic/hand_zone_logic.cpp rename to cockatrice/src/game/zones/hand_zone_logic.cpp index efa85d649..2dca1c6f7 100644 --- a/cockatrice/src/game/zones/logic/hand_zone_logic.cpp +++ b/cockatrice/src/game/zones/hand_zone_logic.cpp @@ -1,6 +1,6 @@ #include "hand_zone_logic.h" -#include "../../board/card_item.h" +#include "../board/card_item.h" #include "card_zone_algorithms.h" HandZoneLogic::HandZoneLogic(Player *_player, diff --git a/cockatrice/src/game/zones/logic/hand_zone_logic.h b/cockatrice/src/game/zones/hand_zone_logic.h similarity index 100% rename from cockatrice/src/game/zones/logic/hand_zone_logic.h rename to cockatrice/src/game/zones/hand_zone_logic.h diff --git a/cockatrice/src/game/zones/logic/pile_zone_logic.cpp b/cockatrice/src/game/zones/pile_zone_logic.cpp similarity index 96% rename from cockatrice/src/game/zones/logic/pile_zone_logic.cpp rename to cockatrice/src/game/zones/pile_zone_logic.cpp index d445ad90c..440b8df81 100644 --- a/cockatrice/src/game/zones/logic/pile_zone_logic.cpp +++ b/cockatrice/src/game/zones/pile_zone_logic.cpp @@ -1,6 +1,6 @@ #include "pile_zone_logic.h" -#include "../../board/card_item.h" +#include "../board/card_item.h" PileZoneLogic::PileZoneLogic(Player *_player, const QString &_name, diff --git a/cockatrice/src/game/zones/logic/pile_zone_logic.h b/cockatrice/src/game/zones/pile_zone_logic.h similarity index 100% rename from cockatrice/src/game/zones/logic/pile_zone_logic.h rename to cockatrice/src/game/zones/pile_zone_logic.h diff --git a/cockatrice/src/game/zones/logic/stack_zone_logic.cpp b/cockatrice/src/game/zones/stack_zone_logic.cpp similarity index 94% rename from cockatrice/src/game/zones/logic/stack_zone_logic.cpp rename to cockatrice/src/game/zones/stack_zone_logic.cpp index 6f3cb6e99..7208a259d 100644 --- a/cockatrice/src/game/zones/logic/stack_zone_logic.cpp +++ b/cockatrice/src/game/zones/stack_zone_logic.cpp @@ -1,6 +1,6 @@ #include "stack_zone_logic.h" -#include "../../board/card_item.h" +#include "../board/card_item.h" #include "card_zone_algorithms.h" StackZoneLogic::StackZoneLogic(Player *_player, diff --git a/cockatrice/src/game/zones/logic/stack_zone_logic.h b/cockatrice/src/game/zones/stack_zone_logic.h similarity index 100% rename from cockatrice/src/game/zones/logic/stack_zone_logic.h rename to cockatrice/src/game/zones/stack_zone_logic.h diff --git a/cockatrice/src/game/zones/logic/table_zone_logic.cpp b/cockatrice/src/game/zones/table_zone_logic.cpp similarity index 96% rename from cockatrice/src/game/zones/logic/table_zone_logic.cpp rename to cockatrice/src/game/zones/table_zone_logic.cpp index d01a756a3..e6c9b8101 100644 --- a/cockatrice/src/game/zones/logic/table_zone_logic.cpp +++ b/cockatrice/src/game/zones/table_zone_logic.cpp @@ -1,6 +1,6 @@ #include "table_zone_logic.h" -#include "../../board/card_item.h" +#include "../board/card_item.h" TableZoneLogic::TableZoneLogic(Player *_player, const QString &_name, diff --git a/cockatrice/src/game/zones/logic/table_zone_logic.h b/cockatrice/src/game/zones/table_zone_logic.h similarity index 100% rename from cockatrice/src/game/zones/logic/table_zone_logic.h rename to cockatrice/src/game/zones/table_zone_logic.h diff --git a/cockatrice/src/game/zones/logic/view_zone_logic.cpp b/cockatrice/src/game/zones/view_zone_logic.cpp similarity index 98% rename from cockatrice/src/game/zones/logic/view_zone_logic.cpp rename to cockatrice/src/game/zones/view_zone_logic.cpp index 5a4db3163..d025fc841 100644 --- a/cockatrice/src/game/zones/logic/view_zone_logic.cpp +++ b/cockatrice/src/game/zones/view_zone_logic.cpp @@ -1,7 +1,7 @@ #include "view_zone_logic.h" -#include "../../../client/settings/cache_settings.h" -#include "../../board/card_item.h" +#include "../../client/settings/cache_settings.h" +#include "../board/card_item.h" /** * @param _player the player that the cards are revealed to. diff --git a/cockatrice/src/game/zones/logic/view_zone_logic.h b/cockatrice/src/game/zones/view_zone_logic.h similarity index 100% rename from cockatrice/src/game/zones/logic/view_zone_logic.h rename to cockatrice/src/game/zones/view_zone_logic.h diff --git a/cockatrice/src/game/zones/card_zone.cpp b/cockatrice/src/game_graphics/zones/card_zone.cpp similarity index 97% rename from cockatrice/src/game/zones/card_zone.cpp rename to cockatrice/src/game_graphics/zones/card_zone.cpp index 3457b681e..6ba8abe42 100644 --- a/cockatrice/src/game/zones/card_zone.cpp +++ b/cockatrice/src/game_graphics/zones/card_zone.cpp @@ -1,6 +1,6 @@ #include "card_zone.h" -#include "../board/card_item.h" +#include "../../game/board/card_item.h" #include "view_zone.h" #include diff --git a/cockatrice/src/game/zones/card_zone.h b/cockatrice/src/game_graphics/zones/card_zone.h similarity index 92% rename from cockatrice/src/game/zones/card_zone.h rename to cockatrice/src/game_graphics/zones/card_zone.h index 5df48f7fb..80226de3c 100644 --- a/cockatrice/src/game/zones/card_zone.h +++ b/cockatrice/src/game_graphics/zones/card_zone.h @@ -7,9 +7,9 @@ #ifndef CARDZONE_H #define CARDZONE_H -#include "../../game_graphics/board/abstract_graphics_item.h" -#include "../../game_graphics/board/graphics_item_type.h" -#include "logic/card_zone_logic.h" +#include "../../game/zones/card_zone_logic.h" +#include "../board/abstract_graphics_item.h" +#include "../board/graphics_item_type.h" #include #include diff --git a/cockatrice/src/game/zones/hand_zone.cpp b/cockatrice/src/game_graphics/zones/hand_zone.cpp similarity index 96% rename from cockatrice/src/game/zones/hand_zone.cpp rename to cockatrice/src/game_graphics/zones/hand_zone.cpp index 3d676dbb5..8bae6ed0a 100644 --- a/cockatrice/src/game/zones/hand_zone.cpp +++ b/cockatrice/src/game_graphics/zones/hand_zone.cpp @@ -1,11 +1,11 @@ #include "hand_zone.h" #include "../../client/settings/cache_settings.h" +#include "../../game/board/card_drag_item.h" +#include "../../game/board/card_item.h" +#include "../../game/player/player.h" +#include "../../game/player/player_actions.h" #include "../../interface/theme_manager.h" -#include "../board/card_drag_item.h" -#include "../board/card_item.h" -#include "../player/player.h" -#include "../player/player_actions.h" #include #include diff --git a/cockatrice/src/game/zones/hand_zone.h b/cockatrice/src/game_graphics/zones/hand_zone.h similarity index 95% rename from cockatrice/src/game/zones/hand_zone.h rename to cockatrice/src/game_graphics/zones/hand_zone.h index 586302308..c3f3f252b 100644 --- a/cockatrice/src/game/zones/hand_zone.h +++ b/cockatrice/src/game_graphics/zones/hand_zone.h @@ -7,7 +7,7 @@ #ifndef HANDZONE_H #define HANDZONE_H -#include "logic/hand_zone_logic.h" +#include "../../game/zones/hand_zone_logic.h" #include "select_zone.h" class HandZone : public SelectZone diff --git a/cockatrice/src/game/zones/pile_zone.cpp b/cockatrice/src/game_graphics/zones/pile_zone.cpp similarity index 95% rename from cockatrice/src/game/zones/pile_zone.cpp rename to cockatrice/src/game_graphics/zones/pile_zone.cpp index 33538ab28..cbc312d0c 100644 --- a/cockatrice/src/game/zones/pile_zone.cpp +++ b/cockatrice/src/game_graphics/zones/pile_zone.cpp @@ -1,10 +1,10 @@ #include "pile_zone.h" -#include "../board/card_drag_item.h" -#include "../board/card_item.h" -#include "../player/player.h" -#include "../player/player_actions.h" -#include "logic/pile_zone_logic.h" +#include "../../game/board/card_drag_item.h" +#include "../../game/board/card_item.h" +#include "../../game/player/player.h" +#include "../../game/player/player_actions.h" +#include "../../game/zones/pile_zone_logic.h" #include "view_zone.h" #include diff --git a/cockatrice/src/game/zones/pile_zone.h b/cockatrice/src/game_graphics/zones/pile_zone.h similarity index 96% rename from cockatrice/src/game/zones/pile_zone.h rename to cockatrice/src/game_graphics/zones/pile_zone.h index 5bfc50880..8cf04676d 100644 --- a/cockatrice/src/game/zones/pile_zone.h +++ b/cockatrice/src/game_graphics/zones/pile_zone.h @@ -7,8 +7,8 @@ #ifndef PILEZONE_H #define PILEZONE_H +#include "../../game/zones/pile_zone_logic.h" #include "card_zone.h" -#include "logic/pile_zone_logic.h" /** * A CardZone where the cards are in a single pile instead of being laid out. diff --git a/cockatrice/src/game/zones/select_zone.cpp b/cockatrice/src/game_graphics/zones/select_zone.cpp similarity index 99% rename from cockatrice/src/game/zones/select_zone.cpp rename to cockatrice/src/game_graphics/zones/select_zone.cpp index e85ec17ae..d43753603 100644 --- a/cockatrice/src/game/zones/select_zone.cpp +++ b/cockatrice/src/game_graphics/zones/select_zone.cpp @@ -1,8 +1,8 @@ #include "select_zone.h" #include "../../client/settings/cache_settings.h" -#include "../board/card_item.h" -#include "../game_scene.h" +#include "../../game/board/card_item.h" +#include "../../game/game_scene.h" #include #include diff --git a/cockatrice/src/game/zones/select_zone.h b/cockatrice/src/game_graphics/zones/select_zone.h similarity index 100% rename from cockatrice/src/game/zones/select_zone.h rename to cockatrice/src/game_graphics/zones/select_zone.h diff --git a/cockatrice/src/game/zones/stack_zone.cpp b/cockatrice/src/game_graphics/zones/stack_zone.cpp similarity index 91% rename from cockatrice/src/game/zones/stack_zone.cpp rename to cockatrice/src/game_graphics/zones/stack_zone.cpp index c0da0bfd2..b4c00e04e 100644 --- a/cockatrice/src/game/zones/stack_zone.cpp +++ b/cockatrice/src/game_graphics/zones/stack_zone.cpp @@ -1,12 +1,12 @@ #include "stack_zone.h" +#include "../../game/board/card_drag_item.h" +#include "../../game/board/card_item.h" +#include "../../game/card_dimensions.h" +#include "../../game/player/player.h" +#include "../../game/player/player_actions.h" +#include "../../game/zones/stack_zone_logic.h" #include "../../interface/theme_manager.h" -#include "../board/card_drag_item.h" -#include "../board/card_item.h" -#include "../card_dimensions.h" -#include "../player/player.h" -#include "../player/player_actions.h" -#include "logic/stack_zone_logic.h" #include #include diff --git a/cockatrice/src/game/zones/stack_zone.h b/cockatrice/src/game_graphics/zones/stack_zone.h similarity index 94% rename from cockatrice/src/game/zones/stack_zone.h rename to cockatrice/src/game_graphics/zones/stack_zone.h index 8f5bed09d..ed13ae1f9 100644 --- a/cockatrice/src/game/zones/stack_zone.h +++ b/cockatrice/src/game_graphics/zones/stack_zone.h @@ -7,7 +7,7 @@ #ifndef STACKZONE_H #define STACKZONE_H -#include "logic/stack_zone_logic.h" +#include "../../game/zones/stack_zone_logic.h" #include "select_zone.h" class StackZone : public SelectZone diff --git a/cockatrice/src/game/zones/table_zone.cpp b/cockatrice/src/game_graphics/zones/table_zone.cpp similarity index 97% rename from cockatrice/src/game/zones/table_zone.cpp rename to cockatrice/src/game_graphics/zones/table_zone.cpp index 5e7db3d09..d428a8a33 100644 --- a/cockatrice/src/game/zones/table_zone.cpp +++ b/cockatrice/src/game_graphics/zones/table_zone.cpp @@ -1,14 +1,14 @@ #include "table_zone.h" #include "../../client/settings/cache_settings.h" +#include "../../game/board/arrow_item.h" +#include "../../game/board/card_drag_item.h" +#include "../../game/board/card_item.h" +#include "../../game/player/player.h" +#include "../../game/player/player_actions.h" +#include "../../game/z_values.h" +#include "../../game/zones/table_zone_logic.h" #include "../../interface/theme_manager.h" -#include "../board/arrow_item.h" -#include "../board/card_drag_item.h" -#include "../board/card_item.h" -#include "../player/player.h" -#include "../player/player_actions.h" -#include "../z_values.h" -#include "logic/table_zone_logic.h" #include #include diff --git a/cockatrice/src/game/zones/table_zone.h b/cockatrice/src/game_graphics/zones/table_zone.h similarity index 98% rename from cockatrice/src/game/zones/table_zone.h rename to cockatrice/src/game_graphics/zones/table_zone.h index 7a53a9eb4..b5e941782 100644 --- a/cockatrice/src/game/zones/table_zone.h +++ b/cockatrice/src/game_graphics/zones/table_zone.h @@ -7,8 +7,8 @@ #ifndef TABLEZONE_H #define TABLEZONE_H -#include "../board/abstract_card_item.h" -#include "logic/table_zone_logic.h" +#include "../../game/board/abstract_card_item.h" +#include "../../game/zones/table_zone_logic.h" #include "select_zone.h" /* diff --git a/cockatrice/src/game/zones/view_zone.cpp b/cockatrice/src/game_graphics/zones/view_zone.cpp similarity index 98% rename from cockatrice/src/game/zones/view_zone.cpp rename to cockatrice/src/game_graphics/zones/view_zone.cpp index 803f80f48..185c1cc6e 100644 --- a/cockatrice/src/game/zones/view_zone.cpp +++ b/cockatrice/src/game_graphics/zones/view_zone.cpp @@ -1,10 +1,10 @@ #include "view_zone.h" -#include "../board/card_drag_item.h" -#include "../board/card_item.h" -#include "../player/player.h" -#include "../player/player_actions.h" -#include "logic/view_zone_logic.h" +#include "../../game/board/card_drag_item.h" +#include "../../game/board/card_item.h" +#include "../../game/player/player.h" +#include "../../game/player/player_actions.h" +#include "../../game/zones/view_zone_logic.h" #include #include diff --git a/cockatrice/src/game/zones/view_zone.h b/cockatrice/src/game_graphics/zones/view_zone.h similarity index 98% rename from cockatrice/src/game/zones/view_zone.h rename to cockatrice/src/game_graphics/zones/view_zone.h index 81279c72e..65e4846d0 100644 --- a/cockatrice/src/game/zones/view_zone.h +++ b/cockatrice/src/game_graphics/zones/view_zone.h @@ -7,7 +7,7 @@ #ifndef ZONEVIEWERZONE_H #define ZONEVIEWERZONE_H -#include "logic/view_zone_logic.h" +#include "../../game/zones/view_zone_logic.h" #include "select_zone.h" #include diff --git a/cockatrice/src/game/zones/view_zone_widget.cpp b/cockatrice/src/game_graphics/zones/view_zone_widget.cpp similarity index 99% rename from cockatrice/src/game/zones/view_zone_widget.cpp rename to cockatrice/src/game_graphics/zones/view_zone_widget.cpp index 5893b8405..a0e63bea0 100644 --- a/cockatrice/src/game/zones/view_zone_widget.cpp +++ b/cockatrice/src/game_graphics/zones/view_zone_widget.cpp @@ -2,12 +2,12 @@ #include "../../client/settings/cache_settings.h" #include "../../filters/syntax_help.h" +#include "../../game/board/card_item.h" +#include "../../game/game_scene.h" +#include "../../game/player/player.h" +#include "../../game/player/player_actions.h" +#include "../../game/z_values.h" #include "../../interface/pixel_map_generator.h" -#include "../board/card_item.h" -#include "../game_scene.h" -#include "../player/player.h" -#include "../player/player_actions.h" -#include "../z_values.h" #include "view_zone.h" #include diff --git a/cockatrice/src/game/zones/view_zone_widget.h b/cockatrice/src/game_graphics/zones/view_zone_widget.h similarity index 98% rename from cockatrice/src/game/zones/view_zone_widget.h rename to cockatrice/src/game_graphics/zones/view_zone_widget.h index 1246192b8..f5c29cf7d 100644 --- a/cockatrice/src/game/zones/view_zone_widget.h +++ b/cockatrice/src/game_graphics/zones/view_zone_widget.h @@ -6,7 +6,7 @@ #ifndef ZONEVIEWWIDGET_H #define ZONEVIEWWIDGET_H -#include "logic/card_zone_logic.h" +#include "../../game/zones/card_zone_logic.h" #include #include diff --git a/tests/card_zone_algorithms/CMakeLists.txt b/tests/card_zone_algorithms/CMakeLists.txt index 889e92eaa..e03d8f77d 100644 --- a/tests/card_zone_algorithms/CMakeLists.txt +++ b/tests/card_zone_algorithms/CMakeLists.txt @@ -1,6 +1,6 @@ add_executable(card_zone_algorithms_test card_zone_algorithms_test.cpp) -target_include_directories(card_zone_algorithms_test PRIVATE ${CMAKE_SOURCE_DIR}/cockatrice/src/game/zones/logic) +target_include_directories(card_zone_algorithms_test PRIVATE ${CMAKE_SOURCE_DIR}/cockatrice/src/game/zones) target_link_libraries( card_zone_algorithms_test From 021a9f8383bb6d97846bc7a4b7175ac65484a463 Mon Sep 17 00:00:00 2001 From: RickyRister <42636155+RickyRister@users.noreply.github.com> Date: Mon, 18 May 2026 01:59:02 -0700 Subject: [PATCH 18/51] [DlgSettings] Refactor: split SettingsPage into separate files (#6899) --- cockatrice/CMakeLists.txt | 8 + cockatrice/resources/config/qtlogging.ini | 2 + .../widgets/dialogs/dlg_settings.cpp | 1954 +---------------- .../interface/widgets/dialogs/dlg_settings.h | 359 +-- .../settings_page/abstract_settings_page.h | 16 + .../appearance_settings_page.cpp | 415 ++++ .../settings_page/appearance_settings_page.h | 75 + .../deck_editor_settings_page.cpp | 241 ++ .../settings_page/deck_editor_settings_page.h | 51 + .../settings_page/general_settings_page.cpp | 373 ++++ .../settings_page/general_settings_page.h | 71 + .../settings_page/messages_settings_page.cpp | 252 +++ .../settings_page/messages_settings_page.h | 58 + .../settings_page/shortcut_settings_page.cpp | 128 ++ .../settings_page/shortcut_settings_page.h | 45 + .../settings_page/sound_settings_page.cpp | 86 + .../settings_page/sound_settings_page.h | 35 + .../settings_page/storage_settings_page.cpp | 244 ++ .../settings_page/storage_settings_page.h | 50 + .../user_interface_settings_page.cpp | 234 ++ .../user_interface_settings_page.h | 54 + 21 files changed, 2452 insertions(+), 2299 deletions(-) create mode 100644 cockatrice/src/interface/widgets/settings_page/abstract_settings_page.h create mode 100644 cockatrice/src/interface/widgets/settings_page/appearance_settings_page.cpp create mode 100644 cockatrice/src/interface/widgets/settings_page/appearance_settings_page.h create mode 100644 cockatrice/src/interface/widgets/settings_page/deck_editor_settings_page.cpp create mode 100644 cockatrice/src/interface/widgets/settings_page/deck_editor_settings_page.h create mode 100644 cockatrice/src/interface/widgets/settings_page/general_settings_page.cpp create mode 100644 cockatrice/src/interface/widgets/settings_page/general_settings_page.h create mode 100644 cockatrice/src/interface/widgets/settings_page/messages_settings_page.cpp create mode 100644 cockatrice/src/interface/widgets/settings_page/messages_settings_page.h create mode 100644 cockatrice/src/interface/widgets/settings_page/shortcut_settings_page.cpp create mode 100644 cockatrice/src/interface/widgets/settings_page/shortcut_settings_page.h create mode 100644 cockatrice/src/interface/widgets/settings_page/sound_settings_page.cpp create mode 100644 cockatrice/src/interface/widgets/settings_page/sound_settings_page.h create mode 100644 cockatrice/src/interface/widgets/settings_page/storage_settings_page.cpp create mode 100644 cockatrice/src/interface/widgets/settings_page/storage_settings_page.h create mode 100644 cockatrice/src/interface/widgets/settings_page/user_interface_settings_page.cpp create mode 100644 cockatrice/src/interface/widgets/settings_page/user_interface_settings_page.h diff --git a/cockatrice/CMakeLists.txt b/cockatrice/CMakeLists.txt index ab47aff80..69b052a36 100644 --- a/cockatrice/CMakeLists.txt +++ b/cockatrice/CMakeLists.txt @@ -235,6 +235,14 @@ set(cockatrice_SOURCES src/interface/widgets/server/user/user_info_connection.cpp src/interface/widgets/server/user/user_list_manager.cpp src/interface/widgets/server/user/user_list_widget.cpp + src/interface/widgets/settings_page/appearance_settings_page.cpp + src/interface/widgets/settings_page/deck_editor_settings_page.cpp + src/interface/widgets/settings_page/general_settings_page.cpp + src/interface/widgets/settings_page/messages_settings_page.cpp + src/interface/widgets/settings_page/shortcut_settings_page.cpp + src/interface/widgets/settings_page/sound_settings_page.cpp + src/interface/widgets/settings_page/storage_settings_page.cpp + src/interface/widgets/settings_page/user_interface_settings_page.cpp src/interface/widgets/utility/custom_line_edit.cpp src/interface/widgets/utility/get_text_with_max.cpp src/interface/widgets/utility/sequence_edit.cpp diff --git a/cockatrice/resources/config/qtlogging.ini b/cockatrice/resources/config/qtlogging.ini index 20aa206ce..7ac0d9ca4 100644 --- a/cockatrice/resources/config/qtlogging.ini +++ b/cockatrice/resources/config/qtlogging.ini @@ -28,6 +28,8 @@ #dlg_tip_of_the_day = true #dlg_update = true +#general_settings_page = true + #settings_cache = true #servers_settings = true #shortcuts_settings = true diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_settings.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_settings.cpp index d9f0c0fe4..3f133c5b6 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_settings.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_settings.cpp @@ -1,1957 +1,29 @@ #include "dlg_settings.h" #include "../../../client/settings/cache_settings.h" -#include "../../../client/settings/shortcut_treeview.h" -#include "../../palette_editor/palette_editor_dialog.h" -#include "../client/network/update/card_spoiler/spoiler_background_updater.h" -#include "../client/network/update/client/release_channel.h" -#include "../client/sound_engine.h" -#include "../interface/card_picture_loader/card_picture_loader.h" -#include "../interface/theme_manager.h" -#include "../interface/widgets/general/background_sources.h" -#include "../interface/widgets/tabs/tab_supervisor.h" -#include "../interface/widgets/utility/custom_line_edit.h" -#include "../interface/widgets/utility/get_text_with_max.h" -#include "../interface/widgets/utility/sequence_edit.h" #include "../main.h" -#include "override_printing_warning.h" +#include "../settings_page/appearance_settings_page.h" +#include "../settings_page/deck_editor_settings_page.h" +#include "../settings_page/general_settings_page.h" +#include "../settings_page/messages_settings_page.h" +#include "../settings_page/shortcut_settings_page.h" +#include "../settings_page/sound_settings_page.h" +#include "../settings_page/storage_settings_page.h" +#include "../settings_page/user_interface_settings_page.h" +#include "libcockatrice/card/database/card_database_loader.h" +#include "libcockatrice/card/database/card_database_manager.h" -#include <../../client/settings/card_counter_settings.h> -#include -#include -#include -#include -#include #include -#include -#include -#include -#include #include -#include -#include -#include -#include -#include -#include -#include +#include +#include #include #include -#include #include #include #include -#include -#include #include -#include -#include -#include -#include -#include - -#define WIKI_CUSTOM_PIC_URL "https://github.com/Cockatrice/Cockatrice/wiki/Custom-Picture-Download-URLs" -#define WIKI_CUSTOM_SHORTCUTS "https://github.com/Cockatrice/Cockatrice/wiki/Custom-Keyboard-Shortcuts" -#define WIKI_TRANSLATION_FAQ "https://github.com/Cockatrice/Cockatrice/wiki/Translation-FAQ" - -enum startupCardUpdateCheckBehaviorIndex -{ - startupCardUpdateCheckBehaviorIndexNone, - startupCardUpdateCheckBehaviorIndexPrompt, - startupCardUpdateCheckBehaviorIndexAlways -}; - -GeneralSettingsPage::GeneralSettingsPage() -{ - QStringList languageCodes = findQmFiles(); - for (const QString &code : languageCodes) { - QString langName = languageName(code); - languageBox.addItem(langName, code); - } - - QString setLanguage = QCoreApplication::translate("i18n", DEFAULT_LANG_NAME); - int index = languageBox.findText(setLanguage, Qt::MatchExactly); - if (index == -1) { - qWarning() << "could not find language" << setLanguage; - } else { - languageBox.setCurrentIndex(index); - } - - // updates - SettingsCache &settings = SettingsCache::instance(); - startupUpdateCheckCheckBox.setChecked(settings.getCheckUpdatesOnStartup()); - - startupCardUpdateCheckBehaviorSelector.addItem(""); // these will be set in retranslateUI - startupCardUpdateCheckBehaviorSelector.addItem(""); - startupCardUpdateCheckBehaviorSelector.addItem(""); - if (SettingsCache::instance().getStartupCardUpdateCheckPromptForUpdate()) { - startupCardUpdateCheckBehaviorSelector.setCurrentIndex(startupCardUpdateCheckBehaviorIndexPrompt); - } else if (SettingsCache::instance().getStartupCardUpdateCheckAlwaysUpdate()) { - startupCardUpdateCheckBehaviorSelector.setCurrentIndex(startupCardUpdateCheckBehaviorIndexAlways); - } else { - startupCardUpdateCheckBehaviorSelector.setCurrentIndex(startupCardUpdateCheckBehaviorIndexNone); - } - - cardUpdateCheckIntervalSpinBox.setMinimum(1); - cardUpdateCheckIntervalSpinBox.setMaximum(30); - cardUpdateCheckIntervalSpinBox.setValue(settings.getCardUpdateCheckInterval()); - updateNotificationCheckBox.setChecked(settings.getNotifyAboutUpdates()); - newVersionOracleCheckBox.setChecked(settings.getNotifyAboutNewVersion()); - - showTipsOnStartup.setChecked(settings.getShowTipsOnStartup()); - - advertiseTranslationPageLabel.setTextInteractionFlags(Qt::LinksAccessibleByMouse); - advertiseTranslationPageLabel.setOpenExternalLinks(true); - - connect(&languageBox, qOverload(&QComboBox::currentIndexChanged), this, - &GeneralSettingsPage::languageBoxChanged); - connect(&startupUpdateCheckCheckBox, &QCheckBox::QT_STATE_CHANGED, &settings, - &SettingsCache::setCheckUpdatesOnStartup); - connect(&startupCardUpdateCheckBehaviorSelector, QOverload::of(&QComboBox::currentIndexChanged), this, - [](int index) { - SettingsCache::instance().setStartupCardUpdateCheckPromptForUpdate( - index == startupCardUpdateCheckBehaviorIndexPrompt); - SettingsCache::instance().setStartupCardUpdateCheckAlwaysUpdate( - index == startupCardUpdateCheckBehaviorIndexAlways); - }); - connect(&cardUpdateCheckIntervalSpinBox, qOverload(&QSpinBox::valueChanged), &settings, - &SettingsCache::setCardUpdateCheckInterval); - connect(&updateNotificationCheckBox, &QCheckBox::QT_STATE_CHANGED, &settings, &SettingsCache::setNotifyAboutUpdate); - connect(&newVersionOracleCheckBox, &QCheckBox::QT_STATE_CHANGED, &settings, - &SettingsCache::setNotifyAboutNewVersion); - connect(&showTipsOnStartup, &QCheckBox::clicked, &settings, &SettingsCache::setShowTipsOnStartup); - - auto *personalGrid = new QGridLayout; - personalGrid->addWidget(&languageLabel, 0, 0); - personalGrid->addWidget(&languageBox, 0, 1); - personalGrid->addWidget(&advertiseTranslationPageLabel, 1, 1, Qt::AlignRight); - personalGrid->addWidget(&updateReleaseChannelLabel, 2, 0); - personalGrid->addWidget(&updateReleaseChannelBox, 2, 1); - personalGrid->addWidget(&startupUpdateCheckCheckBox, 4, 0, 1, 2); - personalGrid->addWidget(&startupCardUpdateCheckBehaviorLabel, 5, 0); - personalGrid->addWidget(&startupCardUpdateCheckBehaviorSelector, 5, 1); - personalGrid->addWidget(&cardUpdateCheckIntervalLabel, 6, 0); - personalGrid->addWidget(&cardUpdateCheckIntervalSpinBox, 6, 1); - personalGrid->addWidget(&lastCardUpdateCheckDateLabel, 7, 1); - personalGrid->addWidget(&updateNotificationCheckBox, 8, 0, 1, 2); - personalGrid->addWidget(&newVersionOracleCheckBox, 9, 0, 1, 2); - personalGrid->addWidget(&showTipsOnStartup, 10, 0, 1, 2); - - personalGroupBox = new QGroupBox; - personalGroupBox->setLayout(personalGrid); - - deckPathEdit = new QLineEdit(settings.getDeckPath()); - deckPathEdit->setReadOnly(true); - auto *deckPathButton = new QPushButton("..."); - connect(deckPathButton, &QPushButton::clicked, this, &GeneralSettingsPage::deckPathButtonClicked); - - filtersPathEdit = new QLineEdit(settings.getFiltersPath()); - filtersPathEdit->setReadOnly(true); - auto *filtersPathButton = new QPushButton("..."); - connect(filtersPathButton, &QPushButton::clicked, this, &GeneralSettingsPage::filtersPathButtonClicked); - - replaysPathEdit = new QLineEdit(settings.getReplaysPath()); - replaysPathEdit->setReadOnly(true); - auto *replaysPathButton = new QPushButton("..."); - connect(replaysPathButton, &QPushButton::clicked, this, &GeneralSettingsPage::replaysPathButtonClicked); - - picsPathEdit = new QLineEdit(settings.getPicsPath()); - picsPathEdit->setReadOnly(true); - auto *picsPathButton = new QPushButton("..."); - connect(picsPathButton, &QPushButton::clicked, this, &GeneralSettingsPage::picsPathButtonClicked); - - cardDatabasePathEdit = new QLineEdit(settings.getCardDatabasePath()); - cardDatabasePathEdit->setReadOnly(true); - auto *cardDatabasePathButton = new QPushButton("..."); - connect(cardDatabasePathButton, &QPushButton::clicked, this, &GeneralSettingsPage::cardDatabasePathButtonClicked); - - customCardDatabasePathEdit = new QLineEdit(settings.getCustomCardDatabasePath()); - customCardDatabasePathEdit->setReadOnly(true); - auto *customCardDatabasePathButton = new QPushButton("..."); - connect(customCardDatabasePathButton, &QPushButton::clicked, this, - &GeneralSettingsPage::customCardDatabaseButtonClicked); - - tokenDatabasePathEdit = new QLineEdit(settings.getTokenDatabasePath()); - tokenDatabasePathEdit->setReadOnly(true); - auto *tokenDatabasePathButton = new QPushButton("..."); - connect(tokenDatabasePathButton, &QPushButton::clicked, this, &GeneralSettingsPage::tokenDatabasePathButtonClicked); - - // Required init here to avoid crashing on Portable builds - resetAllPathsButton = new QPushButton; - - bool isPortable = settings.getIsPortableBuild(); - if (isPortable) { - deckPathEdit->setEnabled(false); - filtersPathEdit->setEnabled(false); - replaysPathEdit->setEnabled(false); - picsPathEdit->setEnabled(false); - cardDatabasePathEdit->setEnabled(false); - customCardDatabasePathEdit->setEnabled(false); - tokenDatabasePathEdit->setEnabled(false); - - deckPathButton->setVisible(false); - replaysPathButton->setVisible(false); - picsPathButton->setVisible(false); - cardDatabasePathButton->setVisible(false); - customCardDatabasePathButton->setVisible(false); - tokenDatabasePathButton->setVisible(false); - } else { - connect(resetAllPathsButton, &QPushButton::clicked, this, &GeneralSettingsPage::resetAllPathsClicked); - allPathsResetLabel = new QLabel(tr("All paths have been reset")); - allPathsResetLabel->setVisible(false); - } - - auto *pathsGrid = new QGridLayout; - pathsGrid->addWidget(&deckPathLabel, 0, 0); - pathsGrid->addWidget(deckPathEdit, 0, 1); - pathsGrid->addWidget(deckPathButton, 0, 2); - pathsGrid->addWidget(&filtersPathLabel, 1, 0); - pathsGrid->addWidget(filtersPathEdit, 1, 1); - pathsGrid->addWidget(filtersPathButton, 1, 2); - pathsGrid->addWidget(&replaysPathLabel, 2, 0); - pathsGrid->addWidget(replaysPathEdit, 2, 1); - pathsGrid->addWidget(replaysPathButton, 2, 2); - pathsGrid->addWidget(&picsPathLabel, 3, 0); - pathsGrid->addWidget(picsPathEdit, 3, 1); - pathsGrid->addWidget(picsPathButton, 3, 2); - pathsGrid->addWidget(&cardDatabasePathLabel, 4, 0); - pathsGrid->addWidget(cardDatabasePathEdit, 4, 1); - pathsGrid->addWidget(cardDatabasePathButton, 4, 2); - pathsGrid->addWidget(&customCardDatabasePathLabel, 5, 0); - pathsGrid->addWidget(customCardDatabasePathEdit, 5, 1); - pathsGrid->addWidget(customCardDatabasePathButton, 5, 2); - pathsGrid->addWidget(&tokenDatabasePathLabel, 6, 0); - pathsGrid->addWidget(tokenDatabasePathEdit, 6, 1); - pathsGrid->addWidget(tokenDatabasePathButton, 6, 2); - if (!isPortable) { - pathsGrid->addWidget(resetAllPathsButton, 7, 0); - pathsGrid->addWidget(allPathsResetLabel, 7, 1); - } - pathsGroupBox = new QGroupBox; - pathsGroupBox->setLayout(pathsGrid); - - auto *mainLayout = new QVBoxLayout; - mainLayout->addWidget(personalGroupBox); - mainLayout->addWidget(pathsGroupBox); - mainLayout->addStretch(); - - GeneralSettingsPage::retranslateUi(); - - // connect the ReleaseChannel combo box only after the entries are inserted in retranslateUi - connect(&updateReleaseChannelBox, qOverload(&QComboBox::currentIndexChanged), &settings, - &SettingsCache::setUpdateReleaseChannelIndex); - updateReleaseChannelBox.setCurrentIndex(settings.getUpdateReleaseChannelIndex()); - - setLayout(mainLayout); - - connect(&SettingsCache::instance(), &SettingsCache::langChanged, this, &GeneralSettingsPage::retranslateUi); - retranslateUi(); -} - -QStringList GeneralSettingsPage::findQmFiles() -{ - QDir dir(translationPath); - QStringList fileNames = dir.entryList(QStringList(translationPrefix + "_*.qm"), QDir::Files, QDir::Name); - fileNames.replaceInStrings(QRegularExpression(translationPrefix + "_(.*)\\.qm"), "\\1"); - return fileNames; -} - -QString GeneralSettingsPage::languageName(const QString &lang) -{ - QTranslator qTranslator; - - QString appNameHint = translationPrefix + "_" + lang; - bool appTranslationLoaded = qTranslator.load(appNameHint, translationPath); - if (!appTranslationLoaded) { - qCWarning(DlgSettingsLog) << "Unable to load" << translationPrefix << "translation" << appNameHint << "at" - << translationPath; - } - - return qTranslator.translate("i18n", DEFAULT_LANG_NAME); -} - -void GeneralSettingsPage::deckPathButtonClicked() -{ - QString path = QFileDialog::getExistingDirectory(this, tr("Choose path"), deckPathEdit->text()); - if (path.isEmpty()) { - return; - } - - deckPathEdit->setText(path); - SettingsCache::instance().setDeckPath(path); -} - -void GeneralSettingsPage::filtersPathButtonClicked() -{ - QString path = QFileDialog::getExistingDirectory(this, tr("Choose path"), filtersPathEdit->text()); - if (path.isEmpty()) { - return; - } - - filtersPathEdit->setText(path); - SettingsCache::instance().setFiltersPath(path); -} - -void GeneralSettingsPage::replaysPathButtonClicked() -{ - QString path = QFileDialog::getExistingDirectory(this, tr("Choose path"), replaysPathEdit->text()); - if (path.isEmpty()) { - return; - } - - replaysPathEdit->setText(path); - SettingsCache::instance().setReplaysPath(path); -} - -void GeneralSettingsPage::picsPathButtonClicked() -{ - QString path = QFileDialog::getExistingDirectory(this, tr("Choose path"), picsPathEdit->text()); - if (path.isEmpty()) { - return; - } - - picsPathEdit->setText(path); - SettingsCache::instance().setPicsPath(path); -} - -void GeneralSettingsPage::cardDatabasePathButtonClicked() -{ - QString path = QFileDialog::getOpenFileName(this, tr("Choose path"), cardDatabasePathEdit->text()); - if (path.isEmpty()) { - return; - } - - cardDatabasePathEdit->setText(path); - SettingsCache::instance().setCardDatabasePath(path); -} - -void GeneralSettingsPage::customCardDatabaseButtonClicked() -{ - QString path = QFileDialog::getExistingDirectory(this, tr("Choose path"), customCardDatabasePathEdit->text()); - if (path.isEmpty()) { - return; - } - - customCardDatabasePathEdit->setText(path); - SettingsCache::instance().setCustomCardDatabasePath(path); -} - -void GeneralSettingsPage::tokenDatabasePathButtonClicked() -{ - QString path = QFileDialog::getOpenFileName(this, tr("Choose path"), tokenDatabasePathEdit->text()); - if (path.isEmpty()) { - return; - } - - tokenDatabasePathEdit->setText(path); - SettingsCache::instance().setTokenDatabasePath(path); -} - -void GeneralSettingsPage::resetAllPathsClicked() -{ - SettingsCache &settings = SettingsCache::instance(); - settings.resetPaths(); - deckPathEdit->setText(settings.getDeckPath()); - replaysPathEdit->setText(settings.getReplaysPath()); - picsPathEdit->setText(settings.getPicsPath()); - cardDatabasePathEdit->setText(settings.getCardDatabasePath()); - customCardDatabasePathEdit->setText(settings.getCustomCardDatabasePath()); - tokenDatabasePathEdit->setText(settings.getTokenDatabasePath()); - allPathsResetLabel->setVisible(true); -} - -void GeneralSettingsPage::languageBoxChanged(int index) -{ - SettingsCache::instance().setLang(languageBox.itemData(index).toString()); -} - -void GeneralSettingsPage::retranslateUi() -{ - personalGroupBox->setTitle(tr("Personal settings")); - languageLabel.setText(tr("Language:")); - - if (SettingsCache::instance().getIsPortableBuild()) { - pathsGroupBox->setTitle(tr("Paths (editing disabled in portable mode)")); - } else { - pathsGroupBox->setTitle(tr("Paths")); - } - advertiseTranslationPageLabel.setText( - QString("%2").arg(WIKI_TRANSLATION_FAQ).arg(tr("How to help with translations"))); - deckPathLabel.setText(tr("Decks directory:")); - filtersPathLabel.setText(tr("Filters directory:")); - replaysPathLabel.setText(tr("Replays directory:")); - picsPathLabel.setText(tr("Pictures directory:")); - cardDatabasePathLabel.setText(tr("Card database:")); - customCardDatabasePathLabel.setText(tr("Custom database directory:")); - tokenDatabasePathLabel.setText(tr("Token database:")); - updateReleaseChannelLabel.setText(tr("Update channel")); - startupUpdateCheckCheckBox.setText(tr("Check for client updates on startup")); - startupCardUpdateCheckBehaviorLabel.setText(tr("Check for card database updates on startup")); - startupCardUpdateCheckBehaviorSelector.setItemText(startupCardUpdateCheckBehaviorIndexNone, tr("Don't check")); - startupCardUpdateCheckBehaviorSelector.setItemText(startupCardUpdateCheckBehaviorIndexPrompt, - tr("Prompt for update")); - startupCardUpdateCheckBehaviorSelector.setItemText(startupCardUpdateCheckBehaviorIndexAlways, - tr("Always update in the background")); - cardUpdateCheckIntervalLabel.setText(tr("Check for card database updates every")); - cardUpdateCheckIntervalSpinBox.setSuffix(tr(" days")); - updateNotificationCheckBox.setText(tr("Notify if a feature supported by the server is missing in my client")); - newVersionOracleCheckBox.setText(tr("Automatically run Oracle when running a new version of Cockatrice")); - showTipsOnStartup.setText(tr("Show tips on startup")); - resetAllPathsButton->setText(tr("Reset all paths")); - - const auto &settings = SettingsCache::instance(); - - QDate lastCheckDate = settings.getLastCardUpdateCheck(); - int daysAgo = lastCheckDate.daysTo(QDate::currentDate()); - - lastCardUpdateCheckDateLabel.setText( - tr("Last update check on %1 (%2 days ago)").arg(lastCheckDate.toString()).arg(daysAgo)); - - // We can't change the strings after they're put into the QComboBox, so this is our workaround - int oldIndex = updateReleaseChannelBox.currentIndex(); - updateReleaseChannelBox.clear(); - for (ReleaseChannel *chan : settings.getUpdateReleaseChannels()) { - updateReleaseChannelBox.addItem(tr(chan->getName().toUtf8())); - } - updateReleaseChannelBox.setCurrentIndex(oldIndex); -} - -AppearanceSettingsPage::AppearanceSettingsPage() -{ - SettingsCache &settings = SettingsCache::instance(); - - // Theme settings - QString themeName = SettingsCache::instance().getThemeName(); - - QStringList themeDirs = themeManager->getAvailableThemes().keys(); - for (int i = 0; i < themeDirs.size(); i++) { - themeBox.addItem(themeDirs[i]); - if (themeDirs[i] == themeName) { - themeBox.setCurrentIndex(i); - } - } - - connect(&themeBox, qOverload(&QComboBox::currentIndexChanged), this, &AppearanceSettingsPage::themeBoxChanged); - connect(&openThemeButton, &QPushButton::clicked, this, &AppearanceSettingsPage::openThemeLocation); - - schemeCombo.addItem(tr("Light"), QStringLiteral("Light")); - schemeCombo.addItem(tr("Dark"), QStringLiteral("Dark")); -#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0) - schemeCombo.addItem(tr("System"), QStringLiteral("System")); -#endif - - // Seed from whatever the current theme already has saved - const QString dirPath = themeManager->getAvailableThemes().value(SettingsCache::instance().getThemeName()); - const ThemeConfig cfg = ThemeConfig::fromThemeDir(dirPath); - const QString current = cfg.colorScheme; - const int seedIdx = schemeCombo.findData(current); - schemeCombo.setCurrentIndex(seedIdx >= 0 ? seedIdx : 0); - - connect(&schemeCombo, &QComboBox::currentIndexChanged, this, - [this] { themeManager->setColorScheme(schemeCombo.currentData().toString()); }); - - connect(themeManager, &ThemeManager::themeChanged, this, [this, dirPath] { - const QString newDir = themeManager->getAvailableThemes().value(SettingsCache::instance().getThemeName()); - const ThemeConfig cfg = ThemeConfig::fromThemeDir(newDir); - const QString current = cfg.colorScheme; - - schemeCombo.blockSignals(true); - const int idx = schemeCombo.findData(current); - schemeCombo.setCurrentIndex(idx >= 0 ? idx : 0); - schemeCombo.blockSignals(false); - }); - - connect(&editPaletteButton, &QPushButton::clicked, this, &AppearanceSettingsPage::editPalette); - - for (const auto &entry : BackgroundSources::all()) { - homeTabBackgroundSourceBox.addItem(QObject::tr(entry.trKey), QVariant::fromValue(entry.type)); - } - - QString homeTabBackgroundSource = SettingsCache::instance().getHomeTabBackgroundSource(); - int homeTabBackgroundSourceId = - homeTabBackgroundSourceBox.findData(BackgroundSources::fromId(homeTabBackgroundSource)); - if (homeTabBackgroundSourceId != -1) { - homeTabBackgroundSourceBox.setCurrentIndex(homeTabBackgroundSourceId); - } - - connect(&homeTabBackgroundSourceBox, QOverload::of(&QComboBox::currentIndexChanged), this, [this]() { - auto type = homeTabBackgroundSourceBox.currentData().value(); - SettingsCache::instance().setHomeTabBackgroundSource(BackgroundSources::toId(type)); - updateHomeTabSettingsVisibility(); - }); - - homeTabBackgroundShuffleFrequencySpinBox.setRange(0, 3600); - homeTabBackgroundShuffleFrequencySpinBox.setSuffix(tr(" seconds")); - homeTabBackgroundShuffleFrequencySpinBox.setValue(SettingsCache::instance().getHomeTabBackgroundShuffleFrequency()); - connect(&homeTabBackgroundShuffleFrequencySpinBox, qOverload(&QSpinBox::valueChanged), - &SettingsCache::instance(), &SettingsCache::setHomeTabBackgroundShuffleFrequency); - - homeTabDisplayCardNameCheckBox.setChecked(settings.getHomeTabDisplayCardName()); - connect(&homeTabDisplayCardNameCheckBox, &QCheckBox::QT_STATE_CHANGED, &settings, - &SettingsCache::setHomeTabDisplayCardName); - - updateHomeTabSettingsVisibility(); - - auto *themeGrid = new QGridLayout; - themeGrid->addWidget(&themeLabel, 0, 0); - themeGrid->addWidget(&themeBox, 0, 1); - themeGrid->addWidget(&openThemeButton, 1, 1); - themeGrid->addWidget(&schemeComboLabel, 2, 0); - themeGrid->addWidget(&schemeCombo, 2, 1); - themeGrid->addWidget(&editPaletteButton, 3, 1); - themeGrid->addWidget(&homeTabBackgroundSourceLabel, 4, 0); - themeGrid->addWidget(&homeTabBackgroundSourceBox, 4, 1); - themeGrid->addWidget(&homeTabBackgroundShuffleFrequencyLabel, 5, 0); - themeGrid->addWidget(&homeTabBackgroundShuffleFrequencySpinBox, 5, 1); - themeGrid->addWidget(&homeTabDisplayCardNameLabel, 6, 0); - themeGrid->addWidget(&homeTabDisplayCardNameCheckBox, 6, 1); - - themeGroupBox = new QGroupBox; - themeGroupBox->setLayout(themeGrid); - - // Menu settings - showShortcutsCheckBox.setChecked(settings.getShowShortcuts()); - connect(&showShortcutsCheckBox, &QCheckBox::QT_STATE_CHANGED, this, &AppearanceSettingsPage::showShortcutsChanged); - - showGameSelectorFilterToolbarCheckBox.setChecked(settings.getShowGameSelectorFilterToolbar()); - connect(&showGameSelectorFilterToolbarCheckBox, &QCheckBox::QT_STATE_CHANGED, &settings, - &SettingsCache::setShowGameSelectorFilterToolbar); - - auto *menuGrid = new QGridLayout; - menuGrid->addWidget(&showShortcutsCheckBox, 0, 0); - menuGrid->addWidget(&showGameSelectorFilterToolbarCheckBox, 1, 0); - - menuGroupBox = new QGroupBox; - menuGroupBox->setLayout(menuGrid); - - // Card rendering - displayCardNamesCheckBox.setChecked(settings.getDisplayCardNames()); - connect(&displayCardNamesCheckBox, &QCheckBox::QT_STATE_CHANGED, &settings, &SettingsCache::setDisplayCardNames); - - autoRotateSidewaysLayoutCardsCheckBox.setChecked(settings.getAutoRotateSidewaysLayoutCards()); - connect(&autoRotateSidewaysLayoutCardsCheckBox, &QCheckBox::QT_STATE_CHANGED, &settings, - &SettingsCache::setAutoRotateSidewaysLayoutCards); - - overrideAllCardArtWithPersonalPreferenceCheckBox.setChecked(settings.getOverrideAllCardArtWithPersonalPreference()); - connect(&overrideAllCardArtWithPersonalPreferenceCheckBox, &QCheckBox::QT_STATE_CHANGED, this, - &AppearanceSettingsPage::overrideAllCardArtWithPersonalPreferenceToggled); - - bumpSetsWithCardsInDeckToTopCheckBox.setChecked(settings.getBumpSetsWithCardsInDeckToTop()); - connect(&bumpSetsWithCardsInDeckToTopCheckBox, &QCheckBox::QT_STATE_CHANGED, &settings, - &SettingsCache::setBumpSetsWithCardsInDeckToTop); - - cardScalingCheckBox.setChecked(settings.getScaleCards()); - connect(&cardScalingCheckBox, &QCheckBox::QT_STATE_CHANGED, &settings, &SettingsCache::setCardScaling); - - roundCardCornersCheckBox.setChecked(settings.getRoundCardCorners()); - connect(&roundCardCornersCheckBox, &QAbstractButton::toggled, &settings, &SettingsCache::setRoundCardCorners); - - verticalCardOverlapPercentBox.setValue(settings.getStackCardOverlapPercent()); - verticalCardOverlapPercentBox.setRange(0, 80); - connect(&verticalCardOverlapPercentBox, qOverload(&QSpinBox::valueChanged), &settings, - &SettingsCache::setStackCardOverlapPercent); - - cardViewInitialRowsMaxBox.setRange(1, 999); - cardViewInitialRowsMaxBox.setValue(SettingsCache::instance().getCardViewInitialRowsMax()); - connect(&cardViewInitialRowsMaxBox, qOverload(&QSpinBox::valueChanged), this, - &AppearanceSettingsPage::cardViewInitialRowsMaxChanged); - - cardViewExpandedRowsMaxBox.setRange(1, 999); - cardViewExpandedRowsMaxBox.setValue(SettingsCache::instance().getCardViewExpandedRowsMax()); - connect(&cardViewExpandedRowsMaxBox, qOverload(&QSpinBox::valueChanged), this, - &AppearanceSettingsPage::cardViewExpandedRowsMaxChanged); - - auto *cardsGrid = new QGridLayout; - cardsGrid->addWidget(&displayCardNamesCheckBox, 0, 0, 1, 2); - cardsGrid->addWidget(&autoRotateSidewaysLayoutCardsCheckBox, 1, 0, 1, 2); - cardsGrid->addWidget(&cardScalingCheckBox, 2, 0, 1, 2); - cardsGrid->addWidget(&roundCardCornersCheckBox, 3, 0, 1, 2); - cardsGrid->addWidget(&overrideAllCardArtWithPersonalPreferenceCheckBox, 4, 0, 1, 2); - cardsGrid->addWidget(&bumpSetsWithCardsInDeckToTopCheckBox, 5, 0, 1, 2); - cardsGrid->addWidget(&verticalCardOverlapPercentLabel, 6, 0, 1, 1); - cardsGrid->addWidget(&verticalCardOverlapPercentBox, 6, 1, 1, 1); - cardsGrid->addWidget(&cardViewInitialRowsMaxLabel, 7, 0); - cardsGrid->addWidget(&cardViewInitialRowsMaxBox, 7, 1); - cardsGrid->addWidget(&cardViewExpandedRowsMaxLabel, 8, 0); - cardsGrid->addWidget(&cardViewExpandedRowsMaxBox, 8, 1); - - cardsGroupBox = new QGroupBox; - cardsGroupBox->setLayout(cardsGrid); - - // Card counter colors - - auto *cardCounterColorsLayout = new QGridLayout; - cardCounterColorsLayout->setColumnStretch(1, 1); - cardCounterColorsLayout->setColumnStretch(3, 1); - cardCounterColorsLayout->setColumnStretch(5, 1); - - auto &cardCounterSettings = SettingsCache::instance().cardCounters(); - for (int index = 0; index < 6; ++index) { - auto *pushButton = new QPushButton; - pushButton->setStyleSheet(QString("background-color: %1").arg(cardCounterSettings.color(index).name())); - - connect(&SettingsCache::instance().cardCounters(), &CardCounterSettings::colorChanged, pushButton, - [index, pushButton](int changedIndex, const QColor &color) { - if (index == changedIndex) { - pushButton->setStyleSheet(QString("background-color: %1").arg(color.name())); - } - }); - - connect(pushButton, &QPushButton::clicked, this, [index, this]() { - auto &cardCounterSettings = SettingsCache::instance().cardCounters(); - - auto newColor = QColorDialog::getColor(cardCounterSettings.color(index), this); - if (!newColor.isValid()) { - return; - } - - cardCounterSettings.setColor(index, newColor); - }); - - auto *colorName = new QLabel; - cardCounterNames.append(colorName); - - int row = index / 3; - int column = 2 * (index % 3); - - cardCounterColorsLayout->addWidget(pushButton, row, column); - cardCounterColorsLayout->addWidget(colorName, row, column + 1); - } - - auto *cardCountersLayout = new QVBoxLayout; - cardCountersLayout->addLayout(cardCounterColorsLayout, 1); - - cardCountersGroupBox = new QGroupBox; - cardCountersGroupBox->setLayout(cardCountersLayout); - - // Hand layout - horizontalHandCheckBox.setChecked(settings.getHorizontalHand()); - connect(&horizontalHandCheckBox, &QCheckBox::QT_STATE_CHANGED, &settings, &SettingsCache::setHorizontalHand); - - leftJustifiedHandCheckBox.setChecked(settings.getLeftJustified()); - connect(&leftJustifiedHandCheckBox, &QCheckBox::QT_STATE_CHANGED, &settings, &SettingsCache::setLeftJustified); - - auto *handGrid = new QGridLayout; - handGrid->addWidget(&horizontalHandCheckBox, 0, 0, 1, 2); - handGrid->addWidget(&leftJustifiedHandCheckBox, 1, 0, 1, 2); - - handGroupBox = new QGroupBox; - handGroupBox->setLayout(handGrid); - - // table grid layout - invertVerticalCoordinateCheckBox.setChecked(settings.getInvertVerticalCoordinate()); - connect(&invertVerticalCoordinateCheckBox, &QCheckBox::QT_STATE_CHANGED, &settings, - &SettingsCache::setInvertVerticalCoordinate); - - minPlayersForMultiColumnLayoutEdit.setMinimum(2); - minPlayersForMultiColumnLayoutEdit.setValue(settings.getMinPlayersForMultiColumnLayout()); - connect(&minPlayersForMultiColumnLayoutEdit, qOverload(&QSpinBox::valueChanged), &settings, - &SettingsCache::setMinPlayersForMultiColumnLayout); - minPlayersForMultiColumnLayoutLabel.setBuddy(&minPlayersForMultiColumnLayoutEdit); - - connect(&maxFontSizeForCardsEdit, qOverload(&QSpinBox::valueChanged), &settings, - &SettingsCache::setMaxFontSize); - maxFontSizeForCardsEdit.setValue(settings.getMaxFontSize()); - maxFontSizeForCardsLabel.setBuddy(&maxFontSizeForCardsEdit); - maxFontSizeForCardsEdit.setMinimum(9); - maxFontSizeForCardsEdit.setMaximum(100); - - auto *tableGrid = new QGridLayout; - tableGrid->addWidget(&invertVerticalCoordinateCheckBox, 0, 0, 1, 2); - tableGrid->addWidget(&minPlayersForMultiColumnLayoutLabel, 1, 0, 1, 1); - tableGrid->addWidget(&minPlayersForMultiColumnLayoutEdit, 1, 1, 1, 1); - tableGrid->addWidget(&maxFontSizeForCardsLabel, 2, 0, 1, 1); - tableGrid->addWidget(&maxFontSizeForCardsEdit, 2, 1, 1, 1); - - tableGroupBox = new QGroupBox; - tableGroupBox->setLayout(tableGrid); - - // putting it all together - auto *mainLayout = new QVBoxLayout; - mainLayout->addWidget(themeGroupBox); - mainLayout->addWidget(menuGroupBox); - mainLayout->addWidget(cardsGroupBox); - mainLayout->addWidget(cardCountersGroupBox); - mainLayout->addWidget(handGroupBox); - mainLayout->addWidget(tableGroupBox); - mainLayout->addStretch(); - - setLayout(mainLayout); - - connect(&SettingsCache::instance(), &SettingsCache::langChanged, this, &AppearanceSettingsPage::retranslateUi); - retranslateUi(); -} - -void AppearanceSettingsPage::themeBoxChanged(int index) -{ - QStringList themeDirs = themeManager->getAvailableThemes().keys(); - if (index >= 0 && index < themeDirs.count()) { - SettingsCache::instance().setThemeName(themeDirs.at(index)); - } -} - -void AppearanceSettingsPage::openThemeLocation() -{ - QString dir = SettingsCache::instance().getThemesPath(); - QDir dirDir = dir; - dirDir.cdUp(); - // open if dir exists, create if parent dir does exist - if (dirDir.exists() && dirDir.mkpath(dir)) { - QDesktopServices::openUrl(QUrl::fromLocalFile(dir)); - } else { - QMessageBox::critical(this, tr("Error"), tr("Could not create themes directory at '%1'.").arg(dir)); - } -} - -void AppearanceSettingsPage::editPalette() -{ - PaletteEditorDialog dlg(themeManager->getCurrentThemePath(), SettingsCache::instance().getThemeName(), this); - dlg.exec(); -} - -void AppearanceSettingsPage::updateHomeTabSettingsVisibility() -{ - bool visible = - SettingsCache::instance().getHomeTabBackgroundSource() != BackgroundSources::toId(BackgroundSources::Theme); - - homeTabBackgroundShuffleFrequencyLabel.setVisible(visible); - homeTabBackgroundShuffleFrequencySpinBox.setVisible(visible); - homeTabDisplayCardNameLabel.setVisible(visible); - homeTabDisplayCardNameCheckBox.setVisible(visible); -} - -void AppearanceSettingsPage::showShortcutsChanged(QT_STATE_CHANGED_T value) -{ - SettingsCache::instance().setShowShortcuts(value); - qApp->setAttribute(Qt::AA_DontShowShortcutsInContextMenus, value == 0); // 0 = unchecked -} - -void AppearanceSettingsPage::overrideAllCardArtWithPersonalPreferenceToggled(QT_STATE_CHANGED_T value) -{ - bool enable = static_cast(value); - - bool accepted = OverridePrintingWarning::execMessageBox(this, enable); - - if (!accepted) { - // If user cancels, revert the checkbox/state back - QTimer::singleShot(0, this, [this, enable]() { - overrideAllCardArtWithPersonalPreferenceCheckBox.blockSignals(true); - overrideAllCardArtWithPersonalPreferenceCheckBox.setChecked(!enable); - overrideAllCardArtWithPersonalPreferenceCheckBox.blockSignals(false); - }); - } -} - -/** - * Updates the settings for cardViewInitialRowsMax. - * Forces expanded rows max to always be >= initial rows max - * @param value The new value - */ -void AppearanceSettingsPage::cardViewInitialRowsMaxChanged(int value) -{ - SettingsCache::instance().setCardViewInitialRowsMax(value); - if (cardViewExpandedRowsMaxBox.value() < value) { - cardViewExpandedRowsMaxBox.setValue(value); - } -} - -/** - * Updates the settings for cardViewExpandedRowsMax. - * Forces initial rows max to always be <= expanded rows max - * @param value The new value - */ -void AppearanceSettingsPage::cardViewExpandedRowsMaxChanged(int value) -{ - SettingsCache::instance().setCardViewExpandedRowsMax(value); - if (cardViewInitialRowsMaxBox.value() > value) { - cardViewInitialRowsMaxBox.setValue(value); - } -} - -void AppearanceSettingsPage::retranslateUi() -{ - themeGroupBox->setTitle(tr("Theme settings")); - themeLabel.setText(tr("Current theme:")); - openThemeButton.setText(tr("Open themes folder")); - schemeComboLabel.setText(tr("Active theme palette:")); - editPaletteButton.setText(tr("Edit theme palette")); - homeTabBackgroundSourceLabel.setText(tr("Home tab background source:")); - homeTabBackgroundShuffleFrequencyLabel.setText(tr("Home tab background shuffle frequency:")); - homeTabBackgroundShuffleFrequencySpinBox.setSpecialValueText(tr("Disabled")); - homeTabDisplayCardNameLabel.setText(tr("Display card name of background in bottom right:")); - - menuGroupBox->setTitle(tr("Menu settings")); - showShortcutsCheckBox.setText(tr("Show keyboard shortcuts in right-click menus")); - showGameSelectorFilterToolbarCheckBox.setText(tr("Show game filter toolbar above list in room tab")); - - cardsGroupBox->setTitle(tr("Card rendering")); - displayCardNamesCheckBox.setText(tr("Display card names on cards having a picture")); - autoRotateSidewaysLayoutCardsCheckBox.setText(tr("Auto-Rotate cards with sideways layout")); - overrideAllCardArtWithPersonalPreferenceCheckBox.setText( - tr("Override all card art with personal set preference (Pre-ProviderID change behavior)")); - bumpSetsWithCardsInDeckToTopCheckBox.setText( - tr("Bump sets that the deck contains cards from to the top in the printing selector")); - cardScalingCheckBox.setText(tr("Scale cards on mouse over")); - roundCardCornersCheckBox.setText(tr("Use rounded card corners")); - verticalCardOverlapPercentLabel.setText( - tr("Minimum overlap percentage of cards on the stack and in vertical hand")); - cardViewInitialRowsMaxLabel.setText(tr("Maximum initial height for card view window:")); - cardViewInitialRowsMaxBox.setSuffix(tr(" rows")); - cardViewExpandedRowsMaxLabel.setText(tr("Maximum expanded height for card view window:")); - cardViewExpandedRowsMaxBox.setSuffix(tr(" rows")); - - cardCountersGroupBox->setTitle(tr("Card counters")); - - auto &cardCounterSettings = SettingsCache::instance().cardCounters(); - for (int index = 0; index < cardCounterNames.size(); ++index) { - cardCounterNames[index]->setText(tr("Counter %1").arg(cardCounterSettings.displayName(index))); - } - - handGroupBox->setTitle(tr("Hand layout")); - horizontalHandCheckBox.setText(tr("Display hand horizontally (wastes space)")); - leftJustifiedHandCheckBox.setText(tr("Enable left justification")); - - tableGroupBox->setTitle(tr("Table grid layout")); - invertVerticalCoordinateCheckBox.setText(tr("Invert vertical coordinate")); - minPlayersForMultiColumnLayoutLabel.setText(tr("Minimum player count for multi-column layout:")); - maxFontSizeForCardsLabel.setText(tr("Maximum font size for information displayed on cards:")); -} - -enum visualDeckStoragePromptForConversionIndex -{ - visualDeckStoragePromptForConversionIndexNone, - visualDeckStoragePromptForConversionIndexPrompt, - visualDeckStoragePromptForConversionIndexAlways -}; - -UserInterfaceSettingsPage::UserInterfaceSettingsPage() -{ - // general settings and notification settings - notificationsEnabledCheckBox.setChecked(SettingsCache::instance().getNotificationsEnabled()); - connect(¬ificationsEnabledCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(), - &SettingsCache::setNotificationsEnabled); - connect(¬ificationsEnabledCheckBox, &QCheckBox::QT_STATE_CHANGED, this, - &UserInterfaceSettingsPage::setNotificationEnabled); - - specNotificationsEnabledCheckBox.setChecked(SettingsCache::instance().getSpectatorNotificationsEnabled()); - specNotificationsEnabledCheckBox.setEnabled(SettingsCache::instance().getNotificationsEnabled()); - connect(&specNotificationsEnabledCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(), - &SettingsCache::setSpectatorNotificationsEnabled); - - buddyConnectNotificationsEnabledCheckBox.setChecked( - SettingsCache::instance().getBuddyConnectNotificationsEnabled()); - buddyConnectNotificationsEnabledCheckBox.setEnabled(SettingsCache::instance().getNotificationsEnabled()); - connect(&buddyConnectNotificationsEnabledCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(), - &SettingsCache::setBuddyConnectNotificationsEnabled); - - doubleClickToPlayCheckBox.setChecked(SettingsCache::instance().getDoubleClickToPlay()); - connect(&doubleClickToPlayCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(), - &SettingsCache::setDoubleClickToPlay); - - clickPlaysAllSelectedCheckBox.setChecked(SettingsCache::instance().getClickPlaysAllSelected()); - connect(&clickPlaysAllSelectedCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(), - &SettingsCache::setClickPlaysAllSelected); - - playToStackCheckBox.setChecked(SettingsCache::instance().getPlayToStack()); - connect(&playToStackCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(), - &SettingsCache::setPlayToStack); - - doNotDeleteArrowsInSubPhasesCheckBox.setChecked(SettingsCache::instance().getDoNotDeleteArrowsInSubPhases()); - connect(&doNotDeleteArrowsInSubPhasesCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(), - &SettingsCache::setDoNotDeleteArrowsInSubPhases); - - closeEmptyCardViewCheckBox.setChecked(SettingsCache::instance().getCloseEmptyCardView()); - connect(&closeEmptyCardViewCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(), - &SettingsCache::setCloseEmptyCardView); - - focusCardViewSearchBarCheckBox.setChecked(SettingsCache::instance().getFocusCardViewSearchBar()); - connect(&focusCardViewSearchBarCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(), - &SettingsCache::setFocusCardViewSearchBar); - - annotateTokensCheckBox.setChecked(SettingsCache::instance().getAnnotateTokens()); - connect(&annotateTokensCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(), - &SettingsCache::setAnnotateTokens); - - showDragSelectionCountCheckBox.setChecked(SettingsCache::instance().getShowDragSelectionCount()); - connect(&showDragSelectionCountCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(), - &SettingsCache::setShowDragSelectionCount); - - showTotalSelectionCountCheckBox.setChecked(SettingsCache::instance().getShowTotalSelectionCount()); - connect(&showTotalSelectionCountCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(), - &SettingsCache::setShowTotalSelectionCount); - - useTearOffMenusCheckBox.setChecked(SettingsCache::instance().getUseTearOffMenus()); - connect(&useTearOffMenusCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(), - [](const QT_STATE_CHANGED_T state) { SettingsCache::instance().setUseTearOffMenus(state == Qt::Checked); }); - - auto *generalGrid = new QGridLayout; - generalGrid->addWidget(&doubleClickToPlayCheckBox, 0, 0); - generalGrid->addWidget(&clickPlaysAllSelectedCheckBox, 1, 0); - generalGrid->addWidget(&playToStackCheckBox, 2, 0); - generalGrid->addWidget(&doNotDeleteArrowsInSubPhasesCheckBox, 3, 0); - generalGrid->addWidget(&closeEmptyCardViewCheckBox, 4, 0); - generalGrid->addWidget(&focusCardViewSearchBarCheckBox, 5, 0); - generalGrid->addWidget(&annotateTokensCheckBox, 6, 0); - generalGrid->addWidget(&showDragSelectionCountCheckBox, 7, 0); - generalGrid->addWidget(&showTotalSelectionCountCheckBox, 8, 0); - generalGrid->addWidget(&useTearOffMenusCheckBox, 9, 0); - - generalGroupBox = new QGroupBox; - generalGroupBox->setLayout(generalGrid); - - auto *notificationsGrid = new QGridLayout; - notificationsGrid->addWidget(¬ificationsEnabledCheckBox, 0, 0); - notificationsGrid->addWidget(&specNotificationsEnabledCheckBox, 1, 0); - notificationsGrid->addWidget(&buddyConnectNotificationsEnabledCheckBox, 2, 0); - - notificationsGroupBox = new QGroupBox; - notificationsGroupBox->setLayout(notificationsGrid); - - // animation settings - tapAnimationCheckBox.setChecked(SettingsCache::instance().getTapAnimation()); - connect(&tapAnimationCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(), - &SettingsCache::setTapAnimation); - - auto *animationGrid = new QGridLayout; - animationGrid->addWidget(&tapAnimationCheckBox, 0, 0); - - animationGroupBox = new QGroupBox; - animationGroupBox->setLayout(animationGrid); - - // deck editor settings - openDeckInNewTabCheckBox.setChecked(SettingsCache::instance().getOpenDeckInNewTab()); - connect(&openDeckInNewTabCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(), - &SettingsCache::setOpenDeckInNewTab); - - visualDeckStorageInGameCheckBox.setChecked(SettingsCache::instance().getVisualDeckStorageInGame()); - connect(&visualDeckStorageInGameCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(), - &SettingsCache::setVisualDeckStorageInGame); - - visualDeckStorageSelectionAnimationCheckBox.setChecked( - SettingsCache::instance().getVisualDeckStorageSelectionAnimation()); - connect(&visualDeckStorageSelectionAnimationCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(), - &SettingsCache::setVisualDeckStorageSelectionAnimation); - - visualDeckStoragePromptForConversionSelector.addItem(""); // these will be set in retranslateUI - visualDeckStoragePromptForConversionSelector.addItem(""); - visualDeckStoragePromptForConversionSelector.addItem(""); - if (SettingsCache::instance().getVisualDeckStoragePromptForConversion()) { - visualDeckStoragePromptForConversionSelector.setCurrentIndex(visualDeckStoragePromptForConversionIndexPrompt); - } else if (SettingsCache::instance().getVisualDeckStorageAlwaysConvert()) { - visualDeckStoragePromptForConversionSelector.setCurrentIndex(visualDeckStoragePromptForConversionIndexAlways); - } else { - visualDeckStoragePromptForConversionSelector.setCurrentIndex(visualDeckStoragePromptForConversionIndexNone); - } - connect(&visualDeckStoragePromptForConversionSelector, QOverload::of(&QComboBox::currentIndexChanged), this, - [](int index) { - SettingsCache::instance().setVisualDeckStoragePromptForConversion( - index == visualDeckStoragePromptForConversionIndexPrompt); - SettingsCache::instance().setVisualDeckStorageAlwaysConvert( - index == visualDeckStoragePromptForConversionIndexAlways); - }); - - defaultDeckEditorTypeSelector.addItem(""); // these will be set in retranslateUI - defaultDeckEditorTypeSelector.addItem(""); - defaultDeckEditorTypeSelector.setCurrentIndex(SettingsCache::instance().getDefaultDeckEditorType()); - connect(&defaultDeckEditorTypeSelector, QOverload::of(&QComboBox::currentIndexChanged), - &SettingsCache::instance(), &SettingsCache::setDefaultDeckEditorType); - - auto *deckEditorGrid = new QGridLayout; - deckEditorGrid->addWidget(&openDeckInNewTabCheckBox, 0, 0); - deckEditorGrid->addWidget(&visualDeckStorageInGameCheckBox, 1, 0); - deckEditorGrid->addWidget(&visualDeckStorageSelectionAnimationCheckBox, 2, 0); - deckEditorGrid->addWidget(&visualDeckStoragePromptForConversionLabel, 3, 0); - deckEditorGrid->addWidget(&visualDeckStoragePromptForConversionSelector, 3, 1); - deckEditorGrid->addWidget(&defaultDeckEditorTypeLabel, 4, 0); - deckEditorGrid->addWidget(&defaultDeckEditorTypeSelector, 4, 1); - - deckEditorGroupBox = new QGroupBox; - deckEditorGroupBox->setLayout(deckEditorGrid); - - // replay settings - rewindBufferingMsBox.setRange(0, 9999); - rewindBufferingMsBox.setValue(SettingsCache::instance().getRewindBufferingMs()); - connect(&rewindBufferingMsBox, qOverload(&QSpinBox::valueChanged), &SettingsCache::instance(), - &SettingsCache::setRewindBufferingMs); - - auto *replayGrid = new QGridLayout; - replayGrid->addWidget(&rewindBufferingMsLabel, 0, 0, 1, 1); - replayGrid->addWidget(&rewindBufferingMsBox, 0, 1, 1, 1); - - replayGroupBox = new QGroupBox; - replayGroupBox->setLayout(replayGrid); - - // putting it all together - auto *mainLayout = new QVBoxLayout; - mainLayout->addWidget(generalGroupBox); - mainLayout->addWidget(notificationsGroupBox); - mainLayout->addWidget(animationGroupBox); - mainLayout->addWidget(deckEditorGroupBox); - mainLayout->addWidget(replayGroupBox); - mainLayout->addStretch(); - - setLayout(mainLayout); - - connect(&SettingsCache::instance(), &SettingsCache::langChanged, this, &UserInterfaceSettingsPage::retranslateUi); - retranslateUi(); -} - -void UserInterfaceSettingsPage::setNotificationEnabled(QT_STATE_CHANGED_T i) -{ - specNotificationsEnabledCheckBox.setEnabled(i != 0); - buddyConnectNotificationsEnabledCheckBox.setEnabled(i != 0); - if (i == 0) { - specNotificationsEnabledCheckBox.setChecked(false); - buddyConnectNotificationsEnabledCheckBox.setChecked(false); - } -} - -void UserInterfaceSettingsPage::retranslateUi() -{ - generalGroupBox->setTitle(tr("General interface settings")); - doubleClickToPlayCheckBox.setText(tr("&Double-click cards to play them (instead of single-click)")); - clickPlaysAllSelectedCheckBox.setText(tr("&Clicking plays all selected cards (instead of just the clicked card)")); - playToStackCheckBox.setText(tr("&Play all nonlands onto the stack (not the battlefield) by default")); - doNotDeleteArrowsInSubPhasesCheckBox.setText(tr("Do not delete &arrows inside of subphases")); - closeEmptyCardViewCheckBox.setText(tr("Close card view window when last card is removed")); - focusCardViewSearchBarCheckBox.setText(tr("Auto focus search bar when card view window is opened")); - annotateTokensCheckBox.setText(tr("Annotate card text on tokens")); - showDragSelectionCountCheckBox.setText(tr("Show selection counter during drag selection")); - showTotalSelectionCountCheckBox.setText(tr("Show total selection counter")); - useTearOffMenusCheckBox.setText(tr("Use tear-off menus, allowing right click menus to persist on screen")); - notificationsGroupBox->setTitle(tr("Notifications settings")); - notificationsEnabledCheckBox.setText(tr("Enable notifications in taskbar")); - specNotificationsEnabledCheckBox.setText(tr("Notify in the taskbar for game events while you are spectating")); - buddyConnectNotificationsEnabledCheckBox.setText(tr("Notify in the taskbar when users in your buddy list connect")); - animationGroupBox->setTitle(tr("Animation settings")); - tapAnimationCheckBox.setText(tr("&Tap/untap animation")); - deckEditorGroupBox->setTitle(tr("Deck editor/storage settings")); - openDeckInNewTabCheckBox.setText(tr("Open deck in new tab by default")); - visualDeckStorageInGameCheckBox.setText(tr("Use visual deck storage in game lobby")); - visualDeckStorageSelectionAnimationCheckBox.setText(tr("Use selection animation for Visual Deck Storage")); - visualDeckStoragePromptForConversionLabel.setText( - tr("When adding a tag in the visual deck storage to a .txt deck:")); - visualDeckStoragePromptForConversionSelector.setItemText(visualDeckStoragePromptForConversionIndexNone, - tr("do nothing")); - visualDeckStoragePromptForConversionSelector.setItemText(visualDeckStoragePromptForConversionIndexPrompt, - tr("ask to convert to .cod")); - visualDeckStoragePromptForConversionSelector.setItemText(visualDeckStoragePromptForConversionIndexAlways, - tr("always convert to .cod")); - defaultDeckEditorTypeLabel.setText(tr("Default deck editor type")); - defaultDeckEditorTypeSelector.setItemText(TabSupervisor::ClassicDeckEditor, tr("Classic Deck Editor")); - defaultDeckEditorTypeSelector.setItemText(TabSupervisor::VisualDeckEditor, tr("Visual Deck Editor")); - replayGroupBox->setTitle(tr("Replay settings")); - rewindBufferingMsLabel.setText(tr("Buffer time for backwards skip via shortcut:")); - rewindBufferingMsBox.setSuffix(" ms"); -} - -DeckEditorSettingsPage::DeckEditorSettingsPage() -{ - picDownloadCheckBox.setChecked(SettingsCache::instance().getPicDownload()); - connect(&picDownloadCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(), - &SettingsCache::setPicDownload); - - urlLinkLabel.setTextInteractionFlags(Qt::LinksAccessibleByMouse); - urlLinkLabel.setOpenExternalLinks(true); - - connect(&resetDownloadURLs, &QPushButton::clicked, this, &DeckEditorSettingsPage::resetDownloadedURLsButtonClicked); - - auto *lpGeneralGrid = new QGridLayout; - auto *lpSpoilerGrid = new QGridLayout; - - mcDownloadSpoilersCheckBox.setChecked(SettingsCache::instance().getDownloadSpoilersStatus()); - - mpSpoilerSavePathLineEdit = new QLineEdit(SettingsCache::instance().getSpoilerCardDatabasePath()); - mpSpoilerSavePathLineEdit->setReadOnly(true); - mpSpoilerPathButton = new QPushButton("..."); - connect(mpSpoilerPathButton, &QPushButton::clicked, this, &DeckEditorSettingsPage::spoilerPathButtonClicked); - - updateNowButton = new QPushButton; - updateNowButton->setFixedWidth(150); - connect(updateNowButton, &QPushButton::clicked, this, &DeckEditorSettingsPage::updateSpoilers); - - // Update the GUI depending on if the box is ticked or not - setSpoilersEnabled(mcDownloadSpoilersCheckBox.isChecked()); - - urlList = new QListWidget; - urlList->setSelectionMode(QAbstractItemView::SingleSelection); - urlList->setAlternatingRowColors(true); - urlList->setDragEnabled(true); - urlList->setDragDropMode(QAbstractItemView::InternalMove); - connect(urlList->model(), &QAbstractItemModel::rowsMoved, this, &DeckEditorSettingsPage::urlListChanged); - - urlList->addItems(SettingsCache::instance().downloads().getAllURLs()); - - aAdd = new QAction(this); - aAdd->setIcon(QPixmap("theme:icons/increment")); - connect(aAdd, &QAction::triggered, this, &DeckEditorSettingsPage::actAddURL); - - aEdit = new QAction(this); - aEdit->setIcon(QPixmap("theme:icons/pencil")); - connect(aEdit, &QAction::triggered, this, &DeckEditorSettingsPage::actEditURL); - - aRemove = new QAction(this); - aRemove->setIcon(QPixmap("theme:icons/decrement")); - connect(aRemove, &QAction::triggered, this, &DeckEditorSettingsPage::actRemoveURL); - - auto *urlToolBar = new QToolBar; - urlToolBar->setOrientation(Qt::Vertical); - urlToolBar->addAction(aAdd); - urlToolBar->addAction(aRemove); - urlToolBar->addAction(aEdit); - urlToolBar->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding); - - auto *urlListLayout = new QHBoxLayout; - urlListLayout->addWidget(urlToolBar); - urlListLayout->addWidget(urlList); - - // Top Layout - lpGeneralGrid->addWidget(&picDownloadCheckBox, 0, 0); - lpGeneralGrid->addWidget(&resetDownloadURLs, 0, 1); - lpGeneralGrid->addLayout(urlListLayout, 1, 0, 1, 2); - lpGeneralGrid->addWidget(&urlLinkLabel, 4, 0); - - // Spoiler Layout - lpSpoilerGrid->addWidget(&mcDownloadSpoilersCheckBox, 0, 0); - lpSpoilerGrid->addWidget(&mcSpoilerSaveLabel, 1, 0); - lpSpoilerGrid->addWidget(mpSpoilerSavePathLineEdit, 1, 1); - lpSpoilerGrid->addWidget(mpSpoilerPathButton, 1, 2); - lpSpoilerGrid->addWidget(&lastUpdatedLabel, 2, 0); - lpSpoilerGrid->addWidget(updateNowButton, 2, 1); - lpSpoilerGrid->addWidget(&infoOnSpoilersLabel, 3, 0, 1, 3, Qt::AlignTop); - - // On a change to the checkbox, hide/un-hide the other fields - connect(&mcDownloadSpoilersCheckBox, &QCheckBox::toggled, &SettingsCache::instance(), - &SettingsCache::setDownloadSpoilerStatus); - connect(&mcDownloadSpoilersCheckBox, &QCheckBox::toggled, this, &DeckEditorSettingsPage::setSpoilersEnabled); - - mpGeneralGroupBox = new QGroupBox; - mpGeneralGroupBox->setLayout(lpGeneralGrid); - - mpSpoilerGroupBox = new QGroupBox; - mpSpoilerGroupBox->setLayout(lpSpoilerGrid); - - auto *lpMainLayout = new QVBoxLayout; - lpMainLayout->addWidget(mpGeneralGroupBox); - lpMainLayout->addWidget(mpSpoilerGroupBox); - - setLayout(lpMainLayout); - - connect(&SettingsCache::instance(), &SettingsCache::langChanged, this, &DeckEditorSettingsPage::retranslateUi); - retranslateUi(); -} - -void DeckEditorSettingsPage::resetDownloadedURLsButtonClicked() -{ - SettingsCache::instance().downloads().resetToDefaultURLs(); - urlList->clear(); - urlList->addItems(SettingsCache::instance().downloads().getAllURLs()); - QMessageBox::information(this, tr("Success"), tr("Download URLs have been reset.")); -} - -void DeckEditorSettingsPage::actAddURL() -{ - bool ok; - QString msg = QInputDialog::getText(this, tr("Add URL"), tr("URL:"), QLineEdit::Normal, QString(), &ok); - if (ok) { - urlList->addItem(msg); - storeSettings(); - } -} - -void DeckEditorSettingsPage::actRemoveURL() -{ - if (urlList->currentItem() != nullptr) { - delete urlList->takeItem(urlList->currentRow()); - storeSettings(); - } -} - -void DeckEditorSettingsPage::actEditURL() -{ - if (urlList->currentItem()) { - QString oldText = urlList->currentItem()->text(); - bool ok; - QString msg = QInputDialog::getText(this, tr("Edit URL"), tr("URL:"), QLineEdit::Normal, oldText, &ok); - if (ok) { - urlList->currentItem()->setText(msg); - storeSettings(); - } - } -} - -void DeckEditorSettingsPage::storeSettings() -{ - qInfo() << "URL Priority Reset"; - - QStringList downloadUrls; - for (int i = 0; i < urlList->count(); i++) { - qInfo() << "Priority" << i << ":" << urlList->item(i)->text(); - downloadUrls << urlList->item(i)->text(); - } - SettingsCache::instance().downloads().setDownloadUrls(downloadUrls); -} - -void DeckEditorSettingsPage::urlListChanged(const QModelIndex &, int, int, const QModelIndex &, int) -{ - storeSettings(); -} - -void DeckEditorSettingsPage::updateSpoilers() -{ - // Disable the button so the user can only press it once at a time - updateNowButton->setDisabled(true); - updateNowButton->setText(tr("Updating...")); - - // Create a new SBU that will act as if the client was just reloaded - auto *sbu = new SpoilerBackgroundUpdater(); - connect(sbu, &SpoilerBackgroundUpdater::spoilerCheckerDone, this, &DeckEditorSettingsPage::unlockSettings); - connect(sbu, &SpoilerBackgroundUpdater::spoilersUpdatedSuccessfully, this, &DeckEditorSettingsPage::unlockSettings); -} - -void DeckEditorSettingsPage::unlockSettings() -{ - updateNowButton->setDisabled(false); - updateNowButton->setText(tr("Update Spoilers")); -} - -QString DeckEditorSettingsPage::getLastUpdateTime() -{ - QString fileName = SettingsCache::instance().getSpoilerCardDatabasePath(); - QFileInfo fi(fileName); - QDir fileDir(fi.path()); - QFile file(fileName); - - if (file.exists()) { - return fi.lastModified().toString("MMM d, hh:mm"); - } - - return QString(); -} - -void DeckEditorSettingsPage::spoilerPathButtonClicked() -{ - QString lsPath = QFileDialog::getExistingDirectory(this, tr("Choose path"), mpSpoilerSavePathLineEdit->text()); - if (lsPath.isEmpty()) { - return; - } - - mpSpoilerSavePathLineEdit->setText(lsPath + "/spoiler.xml"); - SettingsCache::instance().setSpoilerDatabasePath(lsPath + "/spoiler.xml"); -} - -void DeckEditorSettingsPage::setSpoilersEnabled(bool anInput) -{ - msDownloadSpoilersLabel.setEnabled(anInput); - mcSpoilerSaveLabel.setEnabled(anInput); - mpSpoilerSavePathLineEdit->setEnabled(anInput); - mpSpoilerPathButton->setEnabled(anInput); - lastUpdatedLabel.setEnabled(anInput); - updateNowButton->setEnabled(anInput); - infoOnSpoilersLabel.setEnabled(anInput); - - if (!anInput) { - SpoilerBackgroundUpdater::deleteSpoilerFile(); - } -} - -void DeckEditorSettingsPage::retranslateUi() -{ - mpGeneralGroupBox->setTitle(tr("URL Download Priority")); - mpSpoilerGroupBox->setTitle(tr("Spoilers")); - mcDownloadSpoilersCheckBox.setText(tr("Download Spoilers Automatically")); - mcSpoilerSaveLabel.setText(tr("Spoiler Location:")); - lastUpdatedLabel.setText(tr("Last Change") + ": " + getLastUpdateTime()); - infoOnSpoilersLabel.setText(tr("Spoilers download automatically on launch") + "\n" + - tr("Press the button to manually update without relaunching") + "\n\n" + - tr("Do not close settings until manual update is complete")); - picDownloadCheckBox.setText(tr("Download card pictures on the fly")); - urlLinkLabel.setText(QString("%2").arg(WIKI_CUSTOM_PIC_URL).arg(tr("How to add a custom URL"))); - resetDownloadURLs.setText(tr("Reset Download URLs")); - updateNowButton->setText(tr("Update Spoilers")); - aAdd->setText(tr("Add New URL")); - aEdit->setText(tr("Edit URL")); - aRemove->setText(tr("Remove URL")); -} - -StorageSettingsPage::StorageSettingsPage() -{ - auto *lpNetworkCacheGrid = new QGridLayout; - auto *lpImageBackupGrid = new QGridLayout; - auto *lpPixmapCacheGrid = new QGridLayout; - - networkCacheExplainerLabel.setWordWrap(true); - imageBackupExplainerLabel.setWordWrap(true); - pixmapCacheExplainerLabel.setWordWrap(true); - - connect(&clearDownloadedPicsButton, &QPushButton::clicked, this, - &StorageSettingsPage::clearDownloadedPicsButtonClicked); - - connect(&clearPixmapCacheButton, &QPushButton::clicked, this, &StorageSettingsPage::clearPixmapCacheButtonClicked); - - // pixmap cache - pixmapCacheEdit.setMinimum(PIXMAPCACHE_SIZE_MIN); - // 2047 is the max value to avoid overflowing of QPixmapCache::setCacheLimit(int size) - pixmapCacheEdit.setMaximum(PIXMAPCACHE_SIZE_MAX); - pixmapCacheEdit.setSingleStep(64); - pixmapCacheEdit.setValue(SettingsCache::instance().getPixmapCacheSize()); - pixmapCacheEdit.setSuffix(" MB"); - - // Caching method - - cardPictureLoaderCacheMethodComboBox = new QComboBox; - for (auto method : CardPictureLoaderCacheMethod::methods()) { - cardPictureLoaderCacheMethodComboBox->addItem(method.displayName, static_cast(method.id)); - } - - int currentCacheMethod = static_cast(SettingsCache::instance().getCardPictureLoaderCacheMethod()); - - int currentIndex = cardPictureLoaderCacheMethodComboBox->findData(currentCacheMethod); - if (currentIndex >= 0) { - cardPictureLoaderCacheMethodComboBox->setCurrentIndex(currentIndex); - } - - connect(cardPictureLoaderCacheMethodComboBox, qOverload(&QComboBox::currentIndexChanged), this, - [this](int index) { - auto cacheMethod = static_cast( - cardPictureLoaderCacheMethodComboBox->itemData(index).toInt()); - - bool useNetworkCache = (cacheMethod == CardPictureLoaderCacheMethod::CacheMethod::NETWORK_CACHE); - - if (useNetworkCache) { - clearImageBackupsButtonClicked(); - } else { - clearDownloadedPicsButtonClicked(); - } - - mpNetworkCacheGroupBox->setEnabled(useNetworkCache); - mpImageBackupGroupBox->setEnabled(!useNetworkCache); - - SettingsCache::instance().setCardImageCacheMethod(cacheMethod); - }); - - // Network Cache - - networkCacheEdit.setMinimum(NETWORK_CACHE_SIZE_MIN); - networkCacheEdit.setMaximum(NETWORK_CACHE_SIZE_MAX); - networkCacheEdit.setSingleStep(1); - networkCacheEdit.setValue(SettingsCache::instance().getNetworkCacheSizeInMB()); - networkCacheEdit.setSuffix(" MB"); - - networkRedirectCacheTtlEdit.setMinimum(NETWORK_REDIRECT_CACHE_TTL_MIN); - networkRedirectCacheTtlEdit.setMaximum(NETWORK_REDIRECT_CACHE_TTL_MAX); - networkRedirectCacheTtlEdit.setSingleStep(1); - networkRedirectCacheTtlEdit.setValue(SettingsCache::instance().getRedirectCacheTtl()); - - // Image Backup - localCardImageStorageNamingSchemeComboBox = new QComboBox; - for (const auto &scheme : CardPictureLoaderLocalSchemes::exportSchemes()) { - localCardImageStorageNamingSchemeComboBox->addItem(scheme.displayName, static_cast(scheme.id)); - } - - int current = static_cast(SettingsCache::instance().getLocalCardImageStorageNamingScheme()); - - int index = localCardImageStorageNamingSchemeComboBox->findData(current); - if (index >= 0) { - localCardImageStorageNamingSchemeComboBox->setCurrentIndex(index); - } - - connect(localCardImageStorageNamingSchemeComboBox, qOverload(&QComboBox::currentIndexChanged), this, - [this](int index) { - auto scheme = static_cast( - localCardImageStorageNamingSchemeComboBox->itemData(index).toInt()); - SettingsCache::instance().setLocalCardImageStorageNamingScheme(scheme); - }); - - connect(&clearBackupsButton, &QPushButton::clicked, this, &StorageSettingsPage::clearImageBackupsButtonClicked); - - auto cacheMethodLayout = new QHBoxLayout; - cacheMethodLayout->addWidget(&cardPictureLoaderCacheMethodLabel); - cacheMethodLayout->addWidget(cardPictureLoaderCacheMethodComboBox); - - auto networkCacheLayout = new QHBoxLayout; - networkCacheLayout->addWidget(&clearDownloadedPicsButton); - networkCacheLayout->addStretch(); - networkCacheLayout->addWidget(&networkCacheLabel); - networkCacheLayout->addWidget(&networkCacheEdit); - - auto networkRedirectCacheLayout = new QHBoxLayout; - networkRedirectCacheLayout->addStretch(); - networkRedirectCacheLayout->addWidget(&networkRedirectCacheTtlLabel); - networkRedirectCacheLayout->addWidget(&networkRedirectCacheTtlEdit); - - auto pixmapCacheLayout = new QHBoxLayout; - pixmapCacheLayout->addWidget(&clearPixmapCacheButton); - pixmapCacheLayout->addStretch(); - pixmapCacheLayout->addWidget(&pixmapCacheLabel); - pixmapCacheLayout->addWidget(&pixmapCacheEdit); - - lpNetworkCacheGrid->addWidget(&networkCacheExplainerLabel, 0, 0); - lpNetworkCacheGrid->addLayout(networkCacheLayout, 1, 0); - lpNetworkCacheGrid->addLayout(networkRedirectCacheLayout, 2, 0); - - // Image Backup Layout - lpImageBackupGrid->addWidget(&imageBackupExplainerLabel, 0, 0, 1, 2); - lpImageBackupGrid->addWidget(&localCardImageStorageNamingSchemeLabel, 1, 0); - lpImageBackupGrid->addWidget(localCardImageStorageNamingSchemeComboBox, 1, 1); - lpImageBackupGrid->addWidget(&clearBackupsButton, 2, 0); - - lpPixmapCacheGrid->addWidget(&pixmapCacheExplainerLabel, 0, 0); - lpPixmapCacheGrid->addLayout(pixmapCacheLayout, 1, 0); - - connect(&pixmapCacheEdit, qOverload(&QSpinBox::valueChanged), &SettingsCache::instance(), - &SettingsCache::setPixmapCacheSize); - connect(&networkCacheEdit, qOverload(&QSpinBox::valueChanged), &SettingsCache::instance(), - &SettingsCache::setNetworkCacheSizeInMB); - connect(&networkRedirectCacheTtlEdit, qOverload(&QSpinBox::valueChanged), &SettingsCache::instance(), - &SettingsCache::setNetworkRedirectCacheTtl); - - mpCacheMethodGroupBox = new QGroupBox; - mpCacheMethodGroupBox->setLayout(cacheMethodLayout); - - mpNetworkCacheGroupBox = new QGroupBox; - mpNetworkCacheGroupBox->setLayout(lpNetworkCacheGrid); - - mpImageBackupGroupBox = new QGroupBox; - mpImageBackupGroupBox->setLayout(lpImageBackupGrid); - - mpPixmapCacheGroupBox = new QGroupBox; - mpPixmapCacheGroupBox->setLayout(lpPixmapCacheGrid); - - auto *lpMainLayout = new QVBoxLayout; - - lpMainLayout->addWidget(mpCacheMethodGroupBox); - lpMainLayout->addWidget(mpNetworkCacheGroupBox); - lpMainLayout->addWidget(mpImageBackupGroupBox); - lpMainLayout->addWidget(mpPixmapCacheGroupBox); - lpMainLayout->addStretch(); - - setLayout(lpMainLayout); - - bool useNetworkCache = SettingsCache::instance().getCardPictureLoaderCacheMethod() == - CardPictureLoaderCacheMethod::CacheMethod::NETWORK_CACHE; - - mpNetworkCacheGroupBox->setEnabled(useNetworkCache); - mpImageBackupGroupBox->setEnabled(!useNetworkCache); - - connect(&SettingsCache::instance(), &SettingsCache::langChanged, this, &StorageSettingsPage::retranslateUi); - retranslateUi(); -} - -void StorageSettingsPage::clearDownloadedPicsButtonClicked() -{ - CardPictureLoader::clearNetworkCache(); - CardPictureLoader::clearPixmapCache(); - QMessageBox::information(this, tr("Success"), tr("Cached card pictures have been reset.")); -} - -void StorageSettingsPage::clearImageBackupsButtonClicked() -{ - QString picsPath = SettingsCache::instance().getPicsPath() + "/downloadedPics"; - - QDir dir(picsPath); - bool success = dir.removeRecursively(); - - CardPictureLoader::clearPixmapCache(); - - if (success) { - QMessageBox::information(this, tr("Success"), tr("Downloaded card pictures have been reset.")); - } else { - QMessageBox::critical(this, tr("Error"), tr("One or more downloaded card pictures could not be cleared.")); - } -} - -void StorageSettingsPage::clearPixmapCacheButtonClicked() -{ - CardPictureLoader::clearPixmapCache(); - QMessageBox::information(this, tr("Success"), tr("In-memory (currently loaded) card pictures have been reset.")); -} - -void StorageSettingsPage::retranslateUi() -{ - cardPictureLoaderCacheMethodLabel.setText(tr("Card Picture Loader Caching Method:")); - - networkCacheExplainerLabel.setText( - tr("The network cache is the preferred way of storing images. Downloaded images " - "are stored here until the size of the cache exceeds the configured size. Cockatrice automatically monitors " - "this cache and deletes the least recently seen card images to ensure the cache does not exceed the " - "configured size.")); - imageBackupExplainerLabel.setText( - tr("Writing card images directly to a folder on your hard drive is another way " - "of storing images. This does not change how Cockatrice accesses or downloads " - "images. Cockatrice will NOT automatically monitor and clear this folder, so if you enable this option, it " - "is up to you to ensure sufficient available space. It should also be noted that if a provider outage " - "causes you to download the wrong picture (i.e. wrong printing) you will be stuck with it until you " - "manually delete the file, as opposed to using the network cache, which automatically rotates and thus " - "correct errors after a while.")); - pixmapCacheExplainerLabel.setText( - tr("This is the in-memory picture cache used by the application at runtime. It determines how much memory " - "(RAM) Cockatrice can use before it has to fetch card images from the hard disk again. Increasing this will " - "allow more card images to be displayed at once but shouldn't be necessary. Clearing this will make " - "Cockatrice reload all images from the network cache or the disk.")); - - clearDownloadedPicsButton.setText(tr("Delete Cached Images")); - clearBackupsButton.setText(tr("Delete Saved Images")); - clearPixmapCacheButton.setText(tr("Clear In-Memory Images")); - - mpCacheMethodGroupBox->setTitle(tr("Card Picture Loader Cache Method")); - mpNetworkCacheGroupBox->setTitle(tr("Network Cache")); - mpImageBackupGroupBox->setTitle(tr("Filesystem")); - mpPixmapCacheGroupBox->setTitle(tr("In-Memory Picture Cache")); - - networkCacheLabel.setText(tr("Network Cache Size:")); - networkCacheEdit.setToolTip(tr("On-disk cache for downloaded pictures")); - networkRedirectCacheTtlLabel.setText(tr("Redirect Cache TTL:")); - networkRedirectCacheTtlEdit.setToolTip(tr("How long cached redirects for urls are valid for.")); - pixmapCacheLabel.setText(tr("Picture Cache Size:")); - pixmapCacheEdit.setToolTip(tr("In-memory cache for pictures not currently on screen")); - localCardImageStorageNamingSchemeLabel.setText(tr("Naming scheme:")); - - networkRedirectCacheTtlEdit.setSuffix(" " + tr("Day(s)")); -} - -MessagesSettingsPage::MessagesSettingsPage() -{ - chatMentionCheckBox.setChecked(SettingsCache::instance().getChatMention()); - connect(&chatMentionCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(), - &SettingsCache::setChatMention); - - chatMentionCompleterCheckbox.setChecked(SettingsCache::instance().getChatMentionCompleter()); - connect(&chatMentionCompleterCheckbox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(), - &SettingsCache::setChatMentionCompleter); - - explainMessagesLabel.setTextInteractionFlags(Qt::LinksAccessibleByMouse); - explainMessagesLabel.setOpenExternalLinks(true); - - ignoreUnregUsersMainChat.setChecked(SettingsCache::instance().getIgnoreUnregisteredUsers()); - ignoreUnregUserMessages.setChecked(SettingsCache::instance().getIgnoreUnregisteredUserMessages()); - connect(&ignoreUnregUsersMainChat, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(), - &SettingsCache::setIgnoreUnregisteredUsers); - connect(&ignoreUnregUserMessages, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(), - &SettingsCache::setIgnoreUnregisteredUserMessages); - - invertMentionForeground.setChecked(SettingsCache::instance().getChatMentionForeground()); - connect(&invertMentionForeground, &QCheckBox::QT_STATE_CHANGED, this, &MessagesSettingsPage::updateTextColor); - - invertHighlightForeground.setChecked(SettingsCache::instance().getChatHighlightForeground()); - connect(&invertHighlightForeground, &QCheckBox::QT_STATE_CHANGED, this, - &MessagesSettingsPage::updateTextHighlightColor); - - mentionColor = new QLineEdit(); - mentionColor->setText(SettingsCache::instance().getChatMentionColor()); - updateMentionPreview(); - connect(mentionColor, &QLineEdit::textChanged, this, &MessagesSettingsPage::updateColor); - - messagePopups.setChecked(SettingsCache::instance().getShowMessagePopup()); - connect(&messagePopups, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(), - &SettingsCache::setShowMessagePopups); - - mentionPopups.setChecked(SettingsCache::instance().getShowMentionPopup()); - connect(&mentionPopups, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(), - &SettingsCache::setShowMentionPopups); - - roomHistory.setChecked(SettingsCache::instance().getRoomHistory()); - connect(&roomHistory, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(), &SettingsCache::setRoomHistory); - - customAlertString = new QLineEdit(); - customAlertString->setText(SettingsCache::instance().getHighlightWords()); - connect(customAlertString, &QLineEdit::textChanged, &SettingsCache::instance(), &SettingsCache::setHighlightWords); - - auto *chatGrid = new QGridLayout; - chatGrid->addWidget(&chatMentionCheckBox, 0, 0); - chatGrid->addWidget(&invertMentionForeground, 0, 1); - chatGrid->addWidget(mentionColor, 0, 2); - chatGrid->addWidget(&chatMentionCompleterCheckbox, 1, 0); - chatGrid->addWidget(&ignoreUnregUsersMainChat, 2, 0); - chatGrid->addWidget(&hexLabel, 1, 2); - chatGrid->addWidget(&ignoreUnregUserMessages, 3, 0); - chatGrid->addWidget(&messagePopups, 4, 0); - chatGrid->addWidget(&mentionPopups, 5, 0); - chatGrid->addWidget(&roomHistory, 6, 0); - chatGroupBox = new QGroupBox; - chatGroupBox->setLayout(chatGrid); - - highlightColor = new QLineEdit(); - highlightColor->setText(SettingsCache::instance().getChatHighlightColor()); - updateHighlightPreview(); - connect(highlightColor, &QLineEdit::textChanged, this, &MessagesSettingsPage::updateHighlightColor); - - auto *highlightNotice = new QGridLayout; - highlightNotice->addWidget(highlightColor, 0, 2); - highlightNotice->addWidget(&invertHighlightForeground, 0, 1); - highlightNotice->addWidget(&hexHighlightLabel, 1, 2); - highlightNotice->addWidget(customAlertString, 0, 0); - highlightNotice->addWidget(&customAlertStringLabel, 1, 0); - highlightGroupBox = new QGroupBox; - highlightGroupBox->setLayout(highlightNotice); - - messageList = new QListWidget; - - int count = SettingsCache::instance().messages().getCount(); - for (int i = 0; i < count; i++) { - messageList->addItem(SettingsCache::instance().messages().getMessageAt(i)); - } - - aAdd = new QAction(this); - aAdd->setIcon(QPixmap("theme:icons/increment")); - connect(aAdd, &QAction::triggered, this, &MessagesSettingsPage::actAdd); - - aEdit = new QAction(this); - aEdit->setIcon(QPixmap("theme:icons/pencil")); - connect(aEdit, &QAction::triggered, this, &MessagesSettingsPage::actEdit); - - aRemove = new QAction(this); - aRemove->setIcon(QPixmap("theme:icons/decrement")); - connect(aRemove, &QAction::triggered, this, &MessagesSettingsPage::actRemove); - - auto *messageToolBar = new QToolBar; - messageToolBar->setOrientation(Qt::Vertical); - messageToolBar->addAction(aAdd); - messageToolBar->addAction(aRemove); - messageToolBar->addAction(aEdit); - messageToolBar->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding); - - auto *messageListLayout = new QHBoxLayout; - messageListLayout->addWidget(messageToolBar); - messageListLayout->addWidget(messageList); - - auto *messagesLayout = new QVBoxLayout; // combines the explainer label with the actual messages widget pieces - messagesLayout->addLayout(messageListLayout); - messagesLayout->addWidget(&explainMessagesLabel); - - messageGroupBox = new QGroupBox; // draws a box around the above layout and allows it to be titled - messageGroupBox->setLayout(messagesLayout); - - auto *mainLayout = new QVBoxLayout; // combines the messages groupbox with the rest of the menu - mainLayout->addWidget(messageGroupBox); - mainLayout->addWidget(chatGroupBox); - mainLayout->addWidget(highlightGroupBox); - - setLayout(mainLayout); - - connect(&SettingsCache::instance(), &SettingsCache::langChanged, this, &MessagesSettingsPage::retranslateUi); - retranslateUi(); -} - -void MessagesSettingsPage::updateColor(const QString &value) -{ -#if (QT_VERSION >= QT_VERSION_CHECK(6, 4, 0)) - QColor colorToSet = QColor::fromString("#" + value); -#else - QColor colorToSet; - colorToSet.setNamedColor("#" + value); -#endif - if (colorToSet.isValid()) { - SettingsCache::instance().setChatMentionColor(value); - updateMentionPreview(); - } -} - -void MessagesSettingsPage::updateHighlightColor(const QString &value) -{ -#if (QT_VERSION >= QT_VERSION_CHECK(6, 4, 0)) - QColor colorToSet = QColor::fromString("#" + value); -#else - QColor colorToSet; - colorToSet.setNamedColor("#" + value); -#endif - if (colorToSet.isValid()) { - SettingsCache::instance().setChatHighlightColor(value); - updateHighlightPreview(); - } -} - -void MessagesSettingsPage::updateTextColor(QT_STATE_CHANGED_T value) -{ - SettingsCache::instance().setChatMentionForeground(value); - updateMentionPreview(); -} - -void MessagesSettingsPage::updateTextHighlightColor(QT_STATE_CHANGED_T value) -{ - SettingsCache::instance().setChatHighlightForeground(value); - updateHighlightPreview(); -} - -void MessagesSettingsPage::updateMentionPreview() -{ - mentionColor->setStyleSheet( - "QLineEdit{background:#" + SettingsCache::instance().getChatMentionColor() + - ";color: " + (SettingsCache::instance().getChatMentionForeground() ? "white" : "black") + ";}"); -} - -void MessagesSettingsPage::updateHighlightPreview() -{ - highlightColor->setStyleSheet( - "QLineEdit{background:#" + SettingsCache::instance().getChatHighlightColor() + - ";color: " + (SettingsCache::instance().getChatHighlightForeground() ? "white" : "black") + ";}"); -} - -void MessagesSettingsPage::storeSettings() -{ - SettingsCache::instance().messages().setCount(messageList->count()); - for (int i = 0; i < messageList->count(); i++) { - SettingsCache::instance().messages().setMessageAt(i, messageList->item(i)->text()); - } - emit SettingsCache::instance().messages().messageMacrosChanged(); -} - -void MessagesSettingsPage::actAdd() -{ - bool ok; - QString msg = - getTextWithMax(this, tr("Add message"), tr("Message:"), QLineEdit::Normal, QString(), &ok, MAX_TEXT_LENGTH); - if (ok) { - messageList->addItem(msg); - storeSettings(); - } -} - -void MessagesSettingsPage::actEdit() -{ - if (messageList->currentItem()) { - QString oldText = messageList->currentItem()->text(); - bool ok; - QString msg = - getTextWithMax(this, tr("Edit message"), tr("Message:"), QLineEdit::Normal, oldText, &ok, MAX_TEXT_LENGTH); - if (ok) { - messageList->currentItem()->setText(msg); - storeSettings(); - } - } -} - -void MessagesSettingsPage::actRemove() -{ - if (messageList->currentItem() != nullptr) { - delete messageList->takeItem(messageList->currentRow()); - storeSettings(); - } -} - -void MessagesSettingsPage::retranslateUi() -{ - chatGroupBox->setTitle(tr("Chat settings")); - highlightGroupBox->setTitle(tr("Custom alert words")); - chatMentionCheckBox.setText(tr("Enable chat mentions")); - chatMentionCompleterCheckbox.setText(tr("Enable mention completer")); - messageGroupBox->setTitle(tr("In-game message macros")); - explainMessagesLabel.setText( - QString("%2").arg(WIKI_CUSTOM_SHORTCUTS).arg(tr("How to use in-game message macros"))); - ignoreUnregUsersMainChat.setText(tr("Ignore chat room messages sent by unregistered users")); - ignoreUnregUserMessages.setText(tr("Ignore private messages sent by unregistered users")); - invertMentionForeground.setText(tr("Invert text color")); - invertHighlightForeground.setText(tr("Invert text color")); - messagePopups.setText(tr("Enable desktop notifications for private messages")); - mentionPopups.setText(tr("Enable desktop notification for mentions")); - roomHistory.setText(tr("Enable room message history on join")); - hexLabel.setText(tr("(Color is hexadecimal)")); - hexHighlightLabel.setText(tr("(Color is hexadecimal)")); - customAlertStringLabel.setText(tr("Separate words with a space, alphanumeric characters only")); - customAlertString->setPlaceholderText(tr("Word1 Word2 Word3")); - aAdd->setText(tr("Add New Message")); - aEdit->setText(tr("Edit Message")); - aRemove->setText(tr("Remove Message")); -} - -SoundSettingsPage::SoundSettingsPage() -{ - soundEnabledCheckBox.setChecked(SettingsCache::instance().getSoundEnabled()); - connect(&soundEnabledCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(), - &SettingsCache::setSoundEnabled); - - QString themeName = SettingsCache::instance().getSoundThemeName(); - - QStringList themeDirs = soundEngine->getAvailableThemes().keys(); - for (int i = 0; i < themeDirs.size(); i++) { - themeBox.addItem(themeDirs[i]); - if (themeDirs[i] == themeName) { - themeBox.setCurrentIndex(i); - } - } - - connect(&themeBox, qOverload(&QComboBox::currentIndexChanged), this, &SoundSettingsPage::themeBoxChanged); - connect(&soundTestButton, &QPushButton::clicked, soundEngine, &SoundEngine::testSound); - - masterVolumeSlider = new QSlider(Qt::Horizontal); - masterVolumeSlider->setMinimum(0); - masterVolumeSlider->setMaximum(100); - masterVolumeSlider->setValue(SettingsCache::instance().getMasterVolume()); - masterVolumeSlider->setToolTip(QString::number(SettingsCache::instance().getMasterVolume())); - connect(&SettingsCache::instance(), &SettingsCache::masterVolumeChanged, this, - &SoundSettingsPage::masterVolumeChanged); - connect(masterVolumeSlider, &QSlider::sliderReleased, soundEngine, &SoundEngine::testSound); - connect(masterVolumeSlider, &QSlider::valueChanged, &SettingsCache::instance(), &SettingsCache::setMasterVolume); - - masterVolumeSpinBox = new QSpinBox(); - masterVolumeSpinBox->setMinimum(0); - masterVolumeSpinBox->setMaximum(100); - masterVolumeSpinBox->setValue(SettingsCache::instance().getMasterVolume()); - connect(masterVolumeSlider, &QSlider::valueChanged, masterVolumeSpinBox, &QSpinBox::setValue); - connect(masterVolumeSpinBox, qOverload(&QSpinBox::valueChanged), masterVolumeSlider, &QSlider::setValue); - - auto *soundGrid = new QGridLayout; - soundGrid->addWidget(&soundEnabledCheckBox, 0, 0, 1, 3); - soundGrid->addWidget(&masterVolumeLabel, 1, 0); - soundGrid->addWidget(masterVolumeSlider, 1, 1); - soundGrid->addWidget(masterVolumeSpinBox, 1, 2); - soundGrid->addWidget(&themeLabel, 2, 0); - soundGrid->addWidget(&themeBox, 2, 1); - soundGrid->addWidget(&soundTestButton, 3, 1); - - soundGroupBox = new QGroupBox; - soundGroupBox->setLayout(soundGrid); - - auto *mainLayout = new QVBoxLayout; - mainLayout->addWidget(soundGroupBox); - mainLayout->addStretch(); - - setLayout(mainLayout); - - connect(&SettingsCache::instance(), &SettingsCache::langChanged, this, &SoundSettingsPage::retranslateUi); - retranslateUi(); -} - -void SoundSettingsPage::themeBoxChanged(int index) -{ - QStringList themeDirs = soundEngine->getAvailableThemes().keys(); - if (index >= 0 && index < themeDirs.count()) { - SettingsCache::instance().setSoundThemeName(themeDirs.at(index)); - } -} - -void SoundSettingsPage::masterVolumeChanged(int value) -{ - masterVolumeSlider->setToolTip(QString::number(value)); -} - -void SoundSettingsPage::retranslateUi() -{ - soundEnabledCheckBox.setText(tr("Enable &sounds")); - themeLabel.setText(tr("Current sounds theme:")); - soundTestButton.setText(tr("Test system sound engine")); - soundGroupBox->setTitle(tr("Sound settings")); - masterVolumeLabel.setText(tr("Master volume")); -} - -ShortcutSettingsPage::ShortcutSettingsPage() -{ - // search bar - searchEdit = new SearchLineEdit; - searchEdit->setObjectName("searchEdit"); - searchEdit->setClearButtonEnabled(true); - - setFocusProxy(searchEdit); - setFocusPolicy(Qt::ClickFocus); - - // table - shortcutsTable = new ShortcutTreeView(this); - - shortcutsTable->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - shortcutsTable->setEditTriggers(QAbstractItemView::NoEditTriggers); - shortcutsTable->setColumnWidth(0, width() / 3 * 2); - searchEdit->setTreeView(shortcutsTable); - - connect(searchEdit, &SearchLineEdit::textChanged, shortcutsTable, &ShortcutTreeView::updateSearchString); - - // edit widget - currentActionGroupLabel = new QLabel(this); - currentActionGroupName = new QLabel(this); - currentActionLabel = new QLabel(this); - currentActionName = new QLabel(this); - currentShortcutLabel = new QLabel(this); - editTextBox = new SequenceEdit("", this); - shortcutsTable->installEventFilter(editTextBox); - - // buttons - faqLabel = new QLabel(this); - faqLabel->setTextInteractionFlags(Qt::LinksAccessibleByMouse); - faqLabel->setOpenExternalLinks(true); - - btnResetAll = new QPushButton(this); - btnClearAll = new QPushButton(this); - - btnResetAll->setIcon(QPixmap("theme:icons/update")); - btnClearAll->setIcon(QPixmap("theme:icons/clearsearch")); - - // layout - auto *_editLayout = new QGridLayout; - _editLayout->addWidget(currentActionGroupLabel, 0, 0); - _editLayout->addWidget(currentActionGroupName, 0, 1); - _editLayout->addWidget(currentActionLabel, 1, 0); - _editLayout->addWidget(currentActionName, 1, 1); - _editLayout->addWidget(currentShortcutLabel, 2, 0); - _editLayout->addWidget(editTextBox, 2, 1); - - editShortcutGroupBox = new QGroupBox; - editShortcutGroupBox->setLayout(_editLayout); - - auto *_buttonsLayout = new QHBoxLayout; - _buttonsLayout->addWidget(faqLabel); - _buttonsLayout->addWidget(btnResetAll); - _buttonsLayout->addWidget(btnClearAll); - - auto *_mainLayout = new QVBoxLayout; - _mainLayout->addWidget(searchEdit); - _mainLayout->addWidget(shortcutsTable); - _mainLayout->addWidget(editShortcutGroupBox); - _mainLayout->addLayout(_buttonsLayout); - - setLayout(_mainLayout); - - connect(btnResetAll, &QPushButton::clicked, this, &ShortcutSettingsPage::resetShortcuts); - connect(btnClearAll, &QPushButton::clicked, this, &ShortcutSettingsPage::clearShortcuts); - - connect(shortcutsTable, &ShortcutTreeView::currentItemChanged, this, &ShortcutSettingsPage::currentItemChanged); - - connect(&SettingsCache::instance(), &SettingsCache::langChanged, this, &ShortcutSettingsPage::retranslateUi); - retranslateUi(); -} - -void ShortcutSettingsPage::currentItemChanged(const QString &key) -{ - if (key.isEmpty()) { - currentActionGroupName->setText(""); - currentActionName->setText(""); - editTextBox->setShortcutName(""); - } else { - QString group = SettingsCache::instance().shortcuts().getShortcut(key).getGroupName(); - QString action = SettingsCache::instance().shortcuts().getShortcut(key).getName(); - currentActionGroupName->setText(group); - currentActionName->setText(action); - editTextBox->setShortcutName(key); - } -} - -void ShortcutSettingsPage::resetShortcuts() -{ - if (QMessageBox::question(this, tr("Restore all default shortcuts"), - tr("Do you really want to restore all default shortcuts?")) == QMessageBox::Yes) { - SettingsCache::instance().shortcuts().resetAllShortcuts(); - } -} - -void ShortcutSettingsPage::clearShortcuts() -{ - if (QMessageBox::question(this, tr("Clear all default shortcuts"), - tr("Do you really want to clear all shortcuts?")) == QMessageBox::Yes) { - SettingsCache::instance().shortcuts().clearAllShortcuts(); - } -} - -void ShortcutSettingsPage::retranslateUi() -{ - shortcutsTable->retranslateUi(); - - currentActionGroupLabel->setText(tr("Section:")); - currentActionLabel->setText(tr("Action:")); - currentShortcutLabel->setText(tr("Shortcut:")); - editTextBox->retranslateUi(); - faqLabel->setText(QString("%2").arg(WIKI_CUSTOM_SHORTCUTS).arg(tr("How to set custom shortcuts"))); - btnResetAll->setText(tr("Restore all default shortcuts")); - btnClearAll->setText(tr("Clear all shortcuts")); - searchEdit->setPlaceholderText(tr("Search by shortcut name")); -} +#include static QScrollArea *makeScrollable(QWidget *widget) { diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_settings.h b/cockatrice/src/interface/widgets/dialogs/dlg_settings.h index 86266347f..f228bde92 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_settings.h +++ b/cockatrice/src/interface/widgets/dialogs/dlg_settings.h @@ -7,372 +7,15 @@ #ifndef DLG_SETTINGS_H #define DLG_SETTINGS_H -#include #include #include -#include -#include #include -#include -#include -#include inline Q_LOGGING_CATEGORY(DlgSettingsLog, "dlg_settings"); -class ShortcutTreeView; -class SearchLineEdit; -class QTreeView; -class QStandardItemModel; -class CardDatabase; -class QCloseEvent; -class QGridLayout; -class QHBoxLayout; -class QLineEdit; class QListWidget; -class QListWidgetItem; -class QRadioButton; -class QSlider; class QStackedWidget; -class QVBoxLayout; -class SequenceEdit; - -class AbstractSettingsPage : public QWidget -{ -public: - virtual void retranslateUi() = 0; -}; - -class GeneralSettingsPage : public AbstractSettingsPage -{ - Q_OBJECT -public: - GeneralSettingsPage(); - void retranslateUi() override; - -private slots: - void deckPathButtonClicked(); - void filtersPathButtonClicked(); - void replaysPathButtonClicked(); - void picsPathButtonClicked(); - void cardDatabasePathButtonClicked(); - void customCardDatabaseButtonClicked(); - void tokenDatabasePathButtonClicked(); - void resetAllPathsClicked(); - void languageBoxChanged(int index); - -private: - QStringList findQmFiles(); - QString languageName(const QString &lang); - QLineEdit *deckPathEdit; - QLineEdit *filtersPathEdit; - QLineEdit *replaysPathEdit; - QLineEdit *picsPathEdit; - QLineEdit *cardDatabasePathEdit; - QLineEdit *customCardDatabasePathEdit; - QLineEdit *tokenDatabasePathEdit; - QPushButton *resetAllPathsButton; - QLabel *allPathsResetLabel; - QGroupBox *personalGroupBox; - QGroupBox *pathsGroupBox; - QComboBox languageBox; - QCheckBox startupUpdateCheckCheckBox; - QLabel startupCardUpdateCheckBehaviorLabel; - QComboBox startupCardUpdateCheckBehaviorSelector; - QLabel cardUpdateCheckIntervalLabel; - QSpinBox cardUpdateCheckIntervalSpinBox; - QLabel lastCardUpdateCheckDateLabel; - QCheckBox updateNotificationCheckBox; - QCheckBox newVersionOracleCheckBox; - QComboBox updateReleaseChannelBox; - QLabel languageLabel; - QLabel deckPathLabel; - QLabel filtersPathLabel; - QLabel replaysPathLabel; - QLabel picsPathLabel; - QLabel cardDatabasePathLabel; - QLabel customCardDatabasePathLabel; - QLabel tokenDatabasePathLabel; - QLabel updateReleaseChannelLabel; - QLabel advertiseTranslationPageLabel; - QCheckBox showTipsOnStartup; -}; - -class AppearanceSettingsPage : public AbstractSettingsPage -{ - Q_OBJECT -private slots: - void themeBoxChanged(int index); - void openThemeLocation(); - void editPalette(); - void updateHomeTabSettingsVisibility(); - void showShortcutsChanged(QT_STATE_CHANGED_T enabled); - void overrideAllCardArtWithPersonalPreferenceToggled(QT_STATE_CHANGED_T enabled); - - void cardViewInitialRowsMaxChanged(int value); - void cardViewExpandedRowsMaxChanged(int value); - -private: - QLabel themeLabel; - QComboBox themeBox; - QPushButton openThemeButton; - QLabel schemeComboLabel; - QComboBox schemeCombo; - QPushButton editPaletteButton; - QLabel homeTabBackgroundSourceLabel; - QComboBox homeTabBackgroundSourceBox; - QLabel homeTabBackgroundShuffleFrequencyLabel; - QSpinBox homeTabBackgroundShuffleFrequencySpinBox; - QLabel homeTabDisplayCardNameLabel; - QCheckBox homeTabDisplayCardNameCheckBox; - QLabel minPlayersForMultiColumnLayoutLabel; - QLabel maxFontSizeForCardsLabel; - QCheckBox showShortcutsCheckBox; - QCheckBox showGameSelectorFilterToolbarCheckBox; - QCheckBox displayCardNamesCheckBox; - QCheckBox autoRotateSidewaysLayoutCardsCheckBox; - QCheckBox overrideAllCardArtWithPersonalPreferenceCheckBox; - QCheckBox bumpSetsWithCardsInDeckToTopCheckBox; - QCheckBox cardScalingCheckBox; - QCheckBox roundCardCornersCheckBox; - QLabel verticalCardOverlapPercentLabel; - QSpinBox verticalCardOverlapPercentBox; - QLabel cardViewInitialRowsMaxLabel; - QSpinBox cardViewInitialRowsMaxBox; - QLabel cardViewExpandedRowsMaxLabel; - QSpinBox cardViewExpandedRowsMaxBox; - QCheckBox horizontalHandCheckBox; - QCheckBox leftJustifiedHandCheckBox; - QCheckBox invertVerticalCoordinateCheckBox; - QGroupBox *themeGroupBox; - QGroupBox *menuGroupBox; - QGroupBox *cardsGroupBox; - QGroupBox *handGroupBox; - QGroupBox *tableGroupBox; - QGroupBox *cardCountersGroupBox; - QList cardCounterNames; - QSpinBox minPlayersForMultiColumnLayoutEdit; - QSpinBox maxFontSizeForCardsEdit; - -public: - AppearanceSettingsPage(); - void retranslateUi() override; -}; - -class UserInterfaceSettingsPage : public AbstractSettingsPage -{ - Q_OBJECT -private slots: - void setNotificationEnabled(QT_STATE_CHANGED_T); - -private: - QCheckBox notificationsEnabledCheckBox; - QCheckBox specNotificationsEnabledCheckBox; - QCheckBox buddyConnectNotificationsEnabledCheckBox; - QCheckBox doubleClickToPlayCheckBox; - QCheckBox clickPlaysAllSelectedCheckBox; - QCheckBox playToStackCheckBox; - QCheckBox doNotDeleteArrowsInSubPhasesCheckBox; - QCheckBox closeEmptyCardViewCheckBox; - QCheckBox focusCardViewSearchBarCheckBox; - QCheckBox annotateTokensCheckBox; - QCheckBox showDragSelectionCountCheckBox; - QCheckBox showTotalSelectionCountCheckBox; - QCheckBox useTearOffMenusCheckBox; - QCheckBox tapAnimationCheckBox; - QCheckBox openDeckInNewTabCheckBox; - QLabel visualDeckStoragePromptForConversionLabel; - QComboBox visualDeckStoragePromptForConversionSelector; - QCheckBox visualDeckStorageInGameCheckBox; - QCheckBox visualDeckStorageSelectionAnimationCheckBox; - QLabel defaultDeckEditorTypeLabel; - QComboBox defaultDeckEditorTypeSelector; - QLabel rewindBufferingMsLabel; - QSpinBox rewindBufferingMsBox; - QGroupBox *generalGroupBox; - QGroupBox *notificationsGroupBox; - QGroupBox *animationGroupBox; - QGroupBox *deckEditorGroupBox; - QGroupBox *replayGroupBox; - -public: - UserInterfaceSettingsPage(); - void retranslateUi() override; -}; - -class DeckEditorSettingsPage : public AbstractSettingsPage -{ - Q_OBJECT -public: - DeckEditorSettingsPage(); - void retranslateUi() override; - QString getLastUpdateTime(); - -private slots: - void storeSettings(); - void urlListChanged(const QModelIndex &, int, int, const QModelIndex &, int); - void setSpoilersEnabled(bool); - void spoilerPathButtonClicked(); - void updateSpoilers(); - void unlockSettings(); - void actAddURL(); - void actRemoveURL(); - void actEditURL(); - void resetDownloadedURLsButtonClicked(); - -private: - QPushButton resetDownloadURLs; - QLabel urlLinkLabel; - QCheckBox picDownloadCheckBox; - QListWidget *urlList; - QAction *aAdd, *aEdit, *aRemove; - QCheckBox mcDownloadSpoilersCheckBox; - QLabel msDownloadSpoilersLabel; - QGroupBox *mpGeneralGroupBox; - QGroupBox *mpSpoilerGroupBox; - - QLineEdit *mpSpoilerSavePathLineEdit; - QLabel mcSpoilerSaveLabel; - QLabel lastUpdatedLabel; - QLabel infoOnSpoilersLabel; - QPushButton *mpSpoilerPathButton; - QPushButton *updateNowButton; -}; - -class StorageSettingsPage : public AbstractSettingsPage -{ - Q_OBJECT -public: - StorageSettingsPage(); - void retranslateUi() override; - -private slots: - void clearDownloadedPicsButtonClicked(); - void clearImageBackupsButtonClicked(); - void clearPixmapCacheButtonClicked(); - -private: - QPushButton clearDownloadedPicsButton; - QPushButton clearBackupsButton; - QPushButton clearPixmapCacheButton; - - QGroupBox *mpCacheMethodGroupBox; - QGroupBox *mpNetworkCacheGroupBox; - QGroupBox *mpImageBackupGroupBox; - QGroupBox *mpPixmapCacheGroupBox; - - QLabel networkCacheExplainerLabel; - QLabel imageBackupExplainerLabel; - QLabel pixmapCacheExplainerLabel; - - QLabel cardPictureLoaderCacheMethodLabel; - QComboBox *cardPictureLoaderCacheMethodComboBox; - QLabel networkCacheLabel; - QSpinBox networkCacheEdit; - QLabel networkRedirectCacheTtlLabel; - QSpinBox networkRedirectCacheTtlEdit; - QSpinBox pixmapCacheEdit; - QLabel pixmapCacheLabel; - QLabel localCardImageStorageNamingSchemeLabel; - QComboBox *localCardImageStorageNamingSchemeComboBox; -}; - -class MessagesSettingsPage : public AbstractSettingsPage -{ - Q_OBJECT -public: - MessagesSettingsPage(); - void retranslateUi() override; - -private slots: - void actAdd(); - void actEdit(); - void actRemove(); - void updateColor(const QString &value); - void updateHighlightColor(const QString &value); - void updateTextColor(QT_STATE_CHANGED_T value); - void updateTextHighlightColor(QT_STATE_CHANGED_T value); - -private: - QListWidget *messageList; - QAction *aAdd; - QAction *aEdit; - QAction *aRemove; - QCheckBox chatMentionCheckBox; - QCheckBox chatMentionCompleterCheckbox; - QCheckBox invertMentionForeground; - QCheckBox invertHighlightForeground; - QCheckBox ignoreUnregUsersMainChat; - QCheckBox ignoreUnregUserMessages; - QCheckBox messagePopups; - QCheckBox mentionPopups; - QCheckBox roomHistory; - QGroupBox *chatGroupBox; - QGroupBox *highlightGroupBox; - QGroupBox *messageGroupBox; - QLineEdit *mentionColor; - QLineEdit *highlightColor; - QLineEdit *customAlertString; - QLabel hexLabel; - QLabel hexHighlightLabel; - QLabel customAlertStringLabel; - QLabel explainMessagesLabel; - - void storeSettings(); - void updateMentionPreview(); - void updateHighlightPreview(); -}; - -class SoundSettingsPage : public AbstractSettingsPage -{ - Q_OBJECT -public: - SoundSettingsPage(); - void retranslateUi() override; - -private: - QLabel themeLabel; - QComboBox themeBox; - QGroupBox *soundGroupBox; - QPushButton soundTestButton; - QCheckBox soundEnabledCheckBox; - QLabel masterVolumeLabel; - QSlider *masterVolumeSlider; - QSpinBox *masterVolumeSpinBox; - -private slots: - void masterVolumeChanged(int value); - void themeBoxChanged(int index); -}; - -class ShortcutSettingsPage : public AbstractSettingsPage -{ - Q_OBJECT -public: - ShortcutSettingsPage(); - void retranslateUi() override; - -private: - SearchLineEdit *searchEdit; - ShortcutTreeView *shortcutsTable; - QVBoxLayout *mainLayout; - QHBoxLayout *buttonsLayout; - QGroupBox *editShortcutGroupBox; - QGridLayout *editLayout; - QLabel *currentActionGroupLabel; - QLabel *currentActionGroupName; - QLabel *currentActionLabel; - QLabel *currentActionName; - QLabel *currentShortcutLabel; - SequenceEdit *editTextBox; - QLabel *faqLabel; - QPushButton *btnResetAll; - QPushButton *btnClearAll; - -private slots: - void resetShortcuts(); - void clearShortcuts(); - void currentItemChanged(const QString &key); -}; +class QListWidgetItem; class DlgSettings : public QDialog { diff --git a/cockatrice/src/interface/widgets/settings_page/abstract_settings_page.h b/cockatrice/src/interface/widgets/settings_page/abstract_settings_page.h new file mode 100644 index 000000000..4cbf2d71a --- /dev/null +++ b/cockatrice/src/interface/widgets/settings_page/abstract_settings_page.h @@ -0,0 +1,16 @@ +#ifndef COCKATRICE_ABSTRACT_SETTINGS_PAGE_H +#define COCKATRICE_ABSTRACT_SETTINGS_PAGE_H + +#include + +#define WIKI_CUSTOM_PIC_URL "https://github.com/Cockatrice/Cockatrice/wiki/Custom-Picture-Download-URLs" +#define WIKI_CUSTOM_SHORTCUTS "https://github.com/Cockatrice/Cockatrice/wiki/Custom-Keyboard-Shortcuts" +#define WIKI_TRANSLATION_FAQ "https://github.com/Cockatrice/Cockatrice/wiki/Translation-FAQ" + +class AbstractSettingsPage : public QWidget +{ +public: + virtual void retranslateUi() = 0; +}; + +#endif // COCKATRICE_ABSTRACT_SETTINGS_PAGE_H diff --git a/cockatrice/src/interface/widgets/settings_page/appearance_settings_page.cpp b/cockatrice/src/interface/widgets/settings_page/appearance_settings_page.cpp new file mode 100644 index 000000000..f6740f472 --- /dev/null +++ b/cockatrice/src/interface/widgets/settings_page/appearance_settings_page.cpp @@ -0,0 +1,415 @@ +#include "appearance_settings_page.h" + +#include "../../../client/settings/cache_settings.h" +#include "../../client/settings/card_counter_settings.h" +#include "../../palette_editor/palette_editor_dialog.h" +#include "../dialogs/override_printing_warning.h" +#include "../interface/theme_manager.h" +#include "../interface/widgets/general/background_sources.h" + +#include +#include +#include +#include +#include + +AppearanceSettingsPage::AppearanceSettingsPage() +{ + SettingsCache &settings = SettingsCache::instance(); + + // Theme settings + QString themeName = SettingsCache::instance().getThemeName(); + + QStringList themeDirs = themeManager->getAvailableThemes().keys(); + for (int i = 0; i < themeDirs.size(); i++) { + themeBox.addItem(themeDirs[i]); + if (themeDirs[i] == themeName) { + themeBox.setCurrentIndex(i); + } + } + + connect(&themeBox, qOverload(&QComboBox::currentIndexChanged), this, &AppearanceSettingsPage::themeBoxChanged); + connect(&openThemeButton, &QPushButton::clicked, this, &AppearanceSettingsPage::openThemeLocation); + + schemeCombo.addItem(tr("Light"), QStringLiteral("Light")); + schemeCombo.addItem(tr("Dark"), QStringLiteral("Dark")); +#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0) + schemeCombo.addItem(tr("System"), QStringLiteral("System")); +#endif + + // Seed from whatever the current theme already has saved + const QString dirPath = themeManager->getAvailableThemes().value(SettingsCache::instance().getThemeName()); + const ThemeConfig cfg = ThemeConfig::fromThemeDir(dirPath); + const QString current = cfg.colorScheme; + const int seedIdx = schemeCombo.findData(current); + schemeCombo.setCurrentIndex(seedIdx >= 0 ? seedIdx : 0); + + connect(&schemeCombo, &QComboBox::currentIndexChanged, this, + [this] { themeManager->setColorScheme(schemeCombo.currentData().toString()); }); + + connect(themeManager, &ThemeManager::themeChanged, this, [this, dirPath] { + const QString newDir = themeManager->getAvailableThemes().value(SettingsCache::instance().getThemeName()); + const ThemeConfig cfg = ThemeConfig::fromThemeDir(newDir); + const QString current = cfg.colorScheme; + + schemeCombo.blockSignals(true); + const int idx = schemeCombo.findData(current); + schemeCombo.setCurrentIndex(idx >= 0 ? idx : 0); + schemeCombo.blockSignals(false); + }); + + connect(&editPaletteButton, &QPushButton::clicked, this, &AppearanceSettingsPage::editPalette); + + for (const auto &entry : BackgroundSources::all()) { + homeTabBackgroundSourceBox.addItem(QObject::tr(entry.trKey), QVariant::fromValue(entry.type)); + } + + QString homeTabBackgroundSource = SettingsCache::instance().getHomeTabBackgroundSource(); + int homeTabBackgroundSourceId = + homeTabBackgroundSourceBox.findData(BackgroundSources::fromId(homeTabBackgroundSource)); + if (homeTabBackgroundSourceId != -1) { + homeTabBackgroundSourceBox.setCurrentIndex(homeTabBackgroundSourceId); + } + + connect(&homeTabBackgroundSourceBox, QOverload::of(&QComboBox::currentIndexChanged), this, [this]() { + auto type = homeTabBackgroundSourceBox.currentData().value(); + SettingsCache::instance().setHomeTabBackgroundSource(BackgroundSources::toId(type)); + updateHomeTabSettingsVisibility(); + }); + + homeTabBackgroundShuffleFrequencySpinBox.setRange(0, 3600); + homeTabBackgroundShuffleFrequencySpinBox.setSuffix(tr(" seconds")); + homeTabBackgroundShuffleFrequencySpinBox.setValue(SettingsCache::instance().getHomeTabBackgroundShuffleFrequency()); + connect(&homeTabBackgroundShuffleFrequencySpinBox, qOverload(&QSpinBox::valueChanged), + &SettingsCache::instance(), &SettingsCache::setHomeTabBackgroundShuffleFrequency); + + homeTabDisplayCardNameCheckBox.setChecked(settings.getHomeTabDisplayCardName()); + connect(&homeTabDisplayCardNameCheckBox, &QCheckBox::QT_STATE_CHANGED, &settings, + &SettingsCache::setHomeTabDisplayCardName); + + updateHomeTabSettingsVisibility(); + + auto *themeGrid = new QGridLayout; + themeGrid->addWidget(&themeLabel, 0, 0); + themeGrid->addWidget(&themeBox, 0, 1); + themeGrid->addWidget(&openThemeButton, 1, 1); + themeGrid->addWidget(&schemeComboLabel, 2, 0); + themeGrid->addWidget(&schemeCombo, 2, 1); + themeGrid->addWidget(&editPaletteButton, 3, 1); + themeGrid->addWidget(&homeTabBackgroundSourceLabel, 4, 0); + themeGrid->addWidget(&homeTabBackgroundSourceBox, 4, 1); + themeGrid->addWidget(&homeTabBackgroundShuffleFrequencyLabel, 5, 0); + themeGrid->addWidget(&homeTabBackgroundShuffleFrequencySpinBox, 5, 1); + themeGrid->addWidget(&homeTabDisplayCardNameLabel, 6, 0); + themeGrid->addWidget(&homeTabDisplayCardNameCheckBox, 6, 1); + + themeGroupBox = new QGroupBox; + themeGroupBox->setLayout(themeGrid); + + // Menu settings + showShortcutsCheckBox.setChecked(settings.getShowShortcuts()); + connect(&showShortcutsCheckBox, &QCheckBox::QT_STATE_CHANGED, this, &AppearanceSettingsPage::showShortcutsChanged); + + showGameSelectorFilterToolbarCheckBox.setChecked(settings.getShowGameSelectorFilterToolbar()); + connect(&showGameSelectorFilterToolbarCheckBox, &QCheckBox::QT_STATE_CHANGED, &settings, + &SettingsCache::setShowGameSelectorFilterToolbar); + + auto *menuGrid = new QGridLayout; + menuGrid->addWidget(&showShortcutsCheckBox, 0, 0); + menuGrid->addWidget(&showGameSelectorFilterToolbarCheckBox, 1, 0); + + menuGroupBox = new QGroupBox; + menuGroupBox->setLayout(menuGrid); + + // Card rendering + displayCardNamesCheckBox.setChecked(settings.getDisplayCardNames()); + connect(&displayCardNamesCheckBox, &QCheckBox::QT_STATE_CHANGED, &settings, &SettingsCache::setDisplayCardNames); + + autoRotateSidewaysLayoutCardsCheckBox.setChecked(settings.getAutoRotateSidewaysLayoutCards()); + connect(&autoRotateSidewaysLayoutCardsCheckBox, &QCheckBox::QT_STATE_CHANGED, &settings, + &SettingsCache::setAutoRotateSidewaysLayoutCards); + + overrideAllCardArtWithPersonalPreferenceCheckBox.setChecked(settings.getOverrideAllCardArtWithPersonalPreference()); + connect(&overrideAllCardArtWithPersonalPreferenceCheckBox, &QCheckBox::QT_STATE_CHANGED, this, + &AppearanceSettingsPage::overrideAllCardArtWithPersonalPreferenceToggled); + + bumpSetsWithCardsInDeckToTopCheckBox.setChecked(settings.getBumpSetsWithCardsInDeckToTop()); + connect(&bumpSetsWithCardsInDeckToTopCheckBox, &QCheckBox::QT_STATE_CHANGED, &settings, + &SettingsCache::setBumpSetsWithCardsInDeckToTop); + + cardScalingCheckBox.setChecked(settings.getScaleCards()); + connect(&cardScalingCheckBox, &QCheckBox::QT_STATE_CHANGED, &settings, &SettingsCache::setCardScaling); + + roundCardCornersCheckBox.setChecked(settings.getRoundCardCorners()); + connect(&roundCardCornersCheckBox, &QAbstractButton::toggled, &settings, &SettingsCache::setRoundCardCorners); + + verticalCardOverlapPercentBox.setValue(settings.getStackCardOverlapPercent()); + verticalCardOverlapPercentBox.setRange(0, 80); + connect(&verticalCardOverlapPercentBox, qOverload(&QSpinBox::valueChanged), &settings, + &SettingsCache::setStackCardOverlapPercent); + + cardViewInitialRowsMaxBox.setRange(1, 999); + cardViewInitialRowsMaxBox.setValue(SettingsCache::instance().getCardViewInitialRowsMax()); + connect(&cardViewInitialRowsMaxBox, qOverload(&QSpinBox::valueChanged), this, + &AppearanceSettingsPage::cardViewInitialRowsMaxChanged); + + cardViewExpandedRowsMaxBox.setRange(1, 999); + cardViewExpandedRowsMaxBox.setValue(SettingsCache::instance().getCardViewExpandedRowsMax()); + connect(&cardViewExpandedRowsMaxBox, qOverload(&QSpinBox::valueChanged), this, + &AppearanceSettingsPage::cardViewExpandedRowsMaxChanged); + + auto *cardsGrid = new QGridLayout; + cardsGrid->addWidget(&displayCardNamesCheckBox, 0, 0, 1, 2); + cardsGrid->addWidget(&autoRotateSidewaysLayoutCardsCheckBox, 1, 0, 1, 2); + cardsGrid->addWidget(&cardScalingCheckBox, 2, 0, 1, 2); + cardsGrid->addWidget(&roundCardCornersCheckBox, 3, 0, 1, 2); + cardsGrid->addWidget(&overrideAllCardArtWithPersonalPreferenceCheckBox, 4, 0, 1, 2); + cardsGrid->addWidget(&bumpSetsWithCardsInDeckToTopCheckBox, 5, 0, 1, 2); + cardsGrid->addWidget(&verticalCardOverlapPercentLabel, 6, 0, 1, 1); + cardsGrid->addWidget(&verticalCardOverlapPercentBox, 6, 1, 1, 1); + cardsGrid->addWidget(&cardViewInitialRowsMaxLabel, 7, 0); + cardsGrid->addWidget(&cardViewInitialRowsMaxBox, 7, 1); + cardsGrid->addWidget(&cardViewExpandedRowsMaxLabel, 8, 0); + cardsGrid->addWidget(&cardViewExpandedRowsMaxBox, 8, 1); + + cardsGroupBox = new QGroupBox; + cardsGroupBox->setLayout(cardsGrid); + + // Card counter colors + + auto *cardCounterColorsLayout = new QGridLayout; + cardCounterColorsLayout->setColumnStretch(1, 1); + cardCounterColorsLayout->setColumnStretch(3, 1); + cardCounterColorsLayout->setColumnStretch(5, 1); + + auto &cardCounterSettings = SettingsCache::instance().cardCounters(); + for (int index = 0; index < 6; ++index) { + auto *pushButton = new QPushButton; + pushButton->setStyleSheet(QString("background-color: %1").arg(cardCounterSettings.color(index).name())); + + connect(&SettingsCache::instance().cardCounters(), &CardCounterSettings::colorChanged, pushButton, + [index, pushButton](int changedIndex, const QColor &color) { + if (index == changedIndex) { + pushButton->setStyleSheet(QString("background-color: %1").arg(color.name())); + } + }); + + connect(pushButton, &QPushButton::clicked, this, [index, this]() { + auto &cardCounterSettings = SettingsCache::instance().cardCounters(); + + auto newColor = QColorDialog::getColor(cardCounterSettings.color(index), this); + if (!newColor.isValid()) { + return; + } + + cardCounterSettings.setColor(index, newColor); + }); + + auto *colorName = new QLabel; + cardCounterNames.append(colorName); + + int row = index / 3; + int column = 2 * (index % 3); + + cardCounterColorsLayout->addWidget(pushButton, row, column); + cardCounterColorsLayout->addWidget(colorName, row, column + 1); + } + + auto *cardCountersLayout = new QVBoxLayout; + cardCountersLayout->addLayout(cardCounterColorsLayout, 1); + + cardCountersGroupBox = new QGroupBox; + cardCountersGroupBox->setLayout(cardCountersLayout); + + // Hand layout + horizontalHandCheckBox.setChecked(settings.getHorizontalHand()); + connect(&horizontalHandCheckBox, &QCheckBox::QT_STATE_CHANGED, &settings, &SettingsCache::setHorizontalHand); + + leftJustifiedHandCheckBox.setChecked(settings.getLeftJustified()); + connect(&leftJustifiedHandCheckBox, &QCheckBox::QT_STATE_CHANGED, &settings, &SettingsCache::setLeftJustified); + + auto *handGrid = new QGridLayout; + handGrid->addWidget(&horizontalHandCheckBox, 0, 0, 1, 2); + handGrid->addWidget(&leftJustifiedHandCheckBox, 1, 0, 1, 2); + + handGroupBox = new QGroupBox; + handGroupBox->setLayout(handGrid); + + // table grid layout + invertVerticalCoordinateCheckBox.setChecked(settings.getInvertVerticalCoordinate()); + connect(&invertVerticalCoordinateCheckBox, &QCheckBox::QT_STATE_CHANGED, &settings, + &SettingsCache::setInvertVerticalCoordinate); + + minPlayersForMultiColumnLayoutEdit.setMinimum(2); + minPlayersForMultiColumnLayoutEdit.setValue(settings.getMinPlayersForMultiColumnLayout()); + connect(&minPlayersForMultiColumnLayoutEdit, qOverload(&QSpinBox::valueChanged), &settings, + &SettingsCache::setMinPlayersForMultiColumnLayout); + minPlayersForMultiColumnLayoutLabel.setBuddy(&minPlayersForMultiColumnLayoutEdit); + + connect(&maxFontSizeForCardsEdit, qOverload(&QSpinBox::valueChanged), &settings, + &SettingsCache::setMaxFontSize); + maxFontSizeForCardsEdit.setValue(settings.getMaxFontSize()); + maxFontSizeForCardsLabel.setBuddy(&maxFontSizeForCardsEdit); + maxFontSizeForCardsEdit.setMinimum(9); + maxFontSizeForCardsEdit.setMaximum(100); + + auto *tableGrid = new QGridLayout; + tableGrid->addWidget(&invertVerticalCoordinateCheckBox, 0, 0, 1, 2); + tableGrid->addWidget(&minPlayersForMultiColumnLayoutLabel, 1, 0, 1, 1); + tableGrid->addWidget(&minPlayersForMultiColumnLayoutEdit, 1, 1, 1, 1); + tableGrid->addWidget(&maxFontSizeForCardsLabel, 2, 0, 1, 1); + tableGrid->addWidget(&maxFontSizeForCardsEdit, 2, 1, 1, 1); + + tableGroupBox = new QGroupBox; + tableGroupBox->setLayout(tableGrid); + + // putting it all together + auto *mainLayout = new QVBoxLayout; + mainLayout->addWidget(themeGroupBox); + mainLayout->addWidget(menuGroupBox); + mainLayout->addWidget(cardsGroupBox); + mainLayout->addWidget(cardCountersGroupBox); + mainLayout->addWidget(handGroupBox); + mainLayout->addWidget(tableGroupBox); + mainLayout->addStretch(); + + setLayout(mainLayout); + + connect(&SettingsCache::instance(), &SettingsCache::langChanged, this, &AppearanceSettingsPage::retranslateUi); + retranslateUi(); +} + +void AppearanceSettingsPage::themeBoxChanged(int index) +{ + QStringList themeDirs = themeManager->getAvailableThemes().keys(); + if (index >= 0 && index < themeDirs.count()) { + SettingsCache::instance().setThemeName(themeDirs.at(index)); + } +} + +void AppearanceSettingsPage::openThemeLocation() +{ + QString dir = SettingsCache::instance().getThemesPath(); + QDir dirDir = dir; + dirDir.cdUp(); + // open if dir exists, create if parent dir does exist + if (dirDir.exists() && dirDir.mkpath(dir)) { + QDesktopServices::openUrl(QUrl::fromLocalFile(dir)); + } else { + QMessageBox::critical(this, tr("Error"), tr("Could not create themes directory at '%1'.").arg(dir)); + } +} + +void AppearanceSettingsPage::editPalette() +{ + PaletteEditorDialog dlg(themeManager->getCurrentThemePath(), SettingsCache::instance().getThemeName(), this); + dlg.exec(); +} + +void AppearanceSettingsPage::updateHomeTabSettingsVisibility() +{ + bool visible = + SettingsCache::instance().getHomeTabBackgroundSource() != BackgroundSources::toId(BackgroundSources::Theme); + + homeTabBackgroundShuffleFrequencyLabel.setVisible(visible); + homeTabBackgroundShuffleFrequencySpinBox.setVisible(visible); + homeTabDisplayCardNameLabel.setVisible(visible); + homeTabDisplayCardNameCheckBox.setVisible(visible); +} + +void AppearanceSettingsPage::showShortcutsChanged(QT_STATE_CHANGED_T value) +{ + SettingsCache::instance().setShowShortcuts(value); + qApp->setAttribute(Qt::AA_DontShowShortcutsInContextMenus, value == 0); // 0 = unchecked +} + +void AppearanceSettingsPage::overrideAllCardArtWithPersonalPreferenceToggled(QT_STATE_CHANGED_T value) +{ + bool enable = static_cast(value); + + bool accepted = OverridePrintingWarning::execMessageBox(this, enable); + + if (!accepted) { + // If user cancels, revert the checkbox/state back + QTimer::singleShot(0, this, [this, enable]() { + overrideAllCardArtWithPersonalPreferenceCheckBox.blockSignals(true); + overrideAllCardArtWithPersonalPreferenceCheckBox.setChecked(!enable); + overrideAllCardArtWithPersonalPreferenceCheckBox.blockSignals(false); + }); + } +} + +/** + * Updates the settings for cardViewInitialRowsMax. + * Forces expanded rows max to always be >= initial rows max + * @param value The new value + */ +void AppearanceSettingsPage::cardViewInitialRowsMaxChanged(int value) +{ + SettingsCache::instance().setCardViewInitialRowsMax(value); + if (cardViewExpandedRowsMaxBox.value() < value) { + cardViewExpandedRowsMaxBox.setValue(value); + } +} + +/** + * Updates the settings for cardViewExpandedRowsMax. + * Forces initial rows max to always be <= expanded rows max + * @param value The new value + */ +void AppearanceSettingsPage::cardViewExpandedRowsMaxChanged(int value) +{ + SettingsCache::instance().setCardViewExpandedRowsMax(value); + if (cardViewInitialRowsMaxBox.value() > value) { + cardViewInitialRowsMaxBox.setValue(value); + } +} + +void AppearanceSettingsPage::retranslateUi() +{ + themeGroupBox->setTitle(tr("Theme settings")); + themeLabel.setText(tr("Current theme:")); + openThemeButton.setText(tr("Open themes folder")); + schemeComboLabel.setText(tr("Active theme palette:")); + editPaletteButton.setText(tr("Edit theme palette")); + homeTabBackgroundSourceLabel.setText(tr("Home tab background source:")); + homeTabBackgroundShuffleFrequencyLabel.setText(tr("Home tab background shuffle frequency:")); + homeTabBackgroundShuffleFrequencySpinBox.setSpecialValueText(tr("Disabled")); + homeTabDisplayCardNameLabel.setText(tr("Display card name of background in bottom right:")); + + menuGroupBox->setTitle(tr("Menu settings")); + showShortcutsCheckBox.setText(tr("Show keyboard shortcuts in right-click menus")); + showGameSelectorFilterToolbarCheckBox.setText(tr("Show game filter toolbar above list in room tab")); + + cardsGroupBox->setTitle(tr("Card rendering")); + displayCardNamesCheckBox.setText(tr("Display card names on cards having a picture")); + autoRotateSidewaysLayoutCardsCheckBox.setText(tr("Auto-Rotate cards with sideways layout")); + overrideAllCardArtWithPersonalPreferenceCheckBox.setText( + tr("Override all card art with personal set preference (Pre-ProviderID change behavior)")); + bumpSetsWithCardsInDeckToTopCheckBox.setText( + tr("Bump sets that the deck contains cards from to the top in the printing selector")); + cardScalingCheckBox.setText(tr("Scale cards on mouse over")); + roundCardCornersCheckBox.setText(tr("Use rounded card corners")); + verticalCardOverlapPercentLabel.setText( + tr("Minimum overlap percentage of cards on the stack and in vertical hand")); + cardViewInitialRowsMaxLabel.setText(tr("Maximum initial height for card view window:")); + cardViewInitialRowsMaxBox.setSuffix(tr(" rows")); + cardViewExpandedRowsMaxLabel.setText(tr("Maximum expanded height for card view window:")); + cardViewExpandedRowsMaxBox.setSuffix(tr(" rows")); + + cardCountersGroupBox->setTitle(tr("Card counters")); + + auto &cardCounterSettings = SettingsCache::instance().cardCounters(); + for (int index = 0; index < cardCounterNames.size(); ++index) { + cardCounterNames[index]->setText(tr("Counter %1").arg(cardCounterSettings.displayName(index))); + } + + handGroupBox->setTitle(tr("Hand layout")); + horizontalHandCheckBox.setText(tr("Display hand horizontally (wastes space)")); + leftJustifiedHandCheckBox.setText(tr("Enable left justification")); + + tableGroupBox->setTitle(tr("Table grid layout")); + invertVerticalCoordinateCheckBox.setText(tr("Invert vertical coordinate")); + minPlayersForMultiColumnLayoutLabel.setText(tr("Minimum player count for multi-column layout:")); + maxFontSizeForCardsLabel.setText(tr("Maximum font size for information displayed on cards:")); +} \ No newline at end of file diff --git a/cockatrice/src/interface/widgets/settings_page/appearance_settings_page.h b/cockatrice/src/interface/widgets/settings_page/appearance_settings_page.h new file mode 100644 index 000000000..116311986 --- /dev/null +++ b/cockatrice/src/interface/widgets/settings_page/appearance_settings_page.h @@ -0,0 +1,75 @@ +#ifndef COCKATRICE_APPEARANCE_SETTINGS_PAGE_H +#define COCKATRICE_APPEARANCE_SETTINGS_PAGE_H + +#include "abstract_settings_page.h" + +#include +#include +#include +#include +#include +#include +#include + +class AppearanceSettingsPage : public AbstractSettingsPage +{ + Q_OBJECT +private slots: + void themeBoxChanged(int index); + void openThemeLocation(); + void editPalette(); + void updateHomeTabSettingsVisibility(); + void showShortcutsChanged(QT_STATE_CHANGED_T enabled); + void overrideAllCardArtWithPersonalPreferenceToggled(QT_STATE_CHANGED_T enabled); + + void cardViewInitialRowsMaxChanged(int value); + void cardViewExpandedRowsMaxChanged(int value); + +private: + QLabel themeLabel; + QComboBox themeBox; + QPushButton openThemeButton; + QLabel schemeComboLabel; + QComboBox schemeCombo; + QPushButton editPaletteButton; + QLabel homeTabBackgroundSourceLabel; + QComboBox homeTabBackgroundSourceBox; + QLabel homeTabBackgroundShuffleFrequencyLabel; + QSpinBox homeTabBackgroundShuffleFrequencySpinBox; + QLabel homeTabDisplayCardNameLabel; + QCheckBox homeTabDisplayCardNameCheckBox; + QLabel minPlayersForMultiColumnLayoutLabel; + QLabel maxFontSizeForCardsLabel; + QCheckBox showShortcutsCheckBox; + QCheckBox showGameSelectorFilterToolbarCheckBox; + QCheckBox displayCardNamesCheckBox; + QCheckBox autoRotateSidewaysLayoutCardsCheckBox; + QCheckBox overrideAllCardArtWithPersonalPreferenceCheckBox; + QCheckBox bumpSetsWithCardsInDeckToTopCheckBox; + QCheckBox cardScalingCheckBox; + QCheckBox roundCardCornersCheckBox; + QLabel verticalCardOverlapPercentLabel; + QSpinBox verticalCardOverlapPercentBox; + QLabel cardViewInitialRowsMaxLabel; + QSpinBox cardViewInitialRowsMaxBox; + QLabel cardViewExpandedRowsMaxLabel; + QSpinBox cardViewExpandedRowsMaxBox; + QCheckBox horizontalHandCheckBox; + QCheckBox leftJustifiedHandCheckBox; + QCheckBox invertVerticalCoordinateCheckBox; + QGroupBox *themeGroupBox; + QGroupBox *menuGroupBox; + QGroupBox *cardsGroupBox; + QGroupBox *handGroupBox; + QGroupBox *tableGroupBox; + QGroupBox *cardCountersGroupBox; + QList cardCounterNames; + QSpinBox minPlayersForMultiColumnLayoutEdit; + QSpinBox maxFontSizeForCardsEdit; + +public: + AppearanceSettingsPage(); + void retranslateUi() override; +}; + +#endif // COCKATRICE_APPEARANCE_SETTINGS_PAGE_H diff --git a/cockatrice/src/interface/widgets/settings_page/deck_editor_settings_page.cpp b/cockatrice/src/interface/widgets/settings_page/deck_editor_settings_page.cpp new file mode 100644 index 000000000..b7d699ebc --- /dev/null +++ b/cockatrice/src/interface/widgets/settings_page/deck_editor_settings_page.cpp @@ -0,0 +1,241 @@ +#include "deck_editor_settings_page.h" + +#include "../../../client/settings/cache_settings.h" +#include "update/card_spoiler/spoiler_background_updater.h" + +#include +#include +#include +#include +#include +#include +#include + +DeckEditorSettingsPage::DeckEditorSettingsPage() +{ + picDownloadCheckBox.setChecked(SettingsCache::instance().getPicDownload()); + connect(&picDownloadCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(), + &SettingsCache::setPicDownload); + + urlLinkLabel.setTextInteractionFlags(Qt::LinksAccessibleByMouse); + urlLinkLabel.setOpenExternalLinks(true); + + connect(&resetDownloadURLs, &QPushButton::clicked, this, &DeckEditorSettingsPage::resetDownloadedURLsButtonClicked); + + auto *lpGeneralGrid = new QGridLayout; + auto *lpSpoilerGrid = new QGridLayout; + + mcDownloadSpoilersCheckBox.setChecked(SettingsCache::instance().getDownloadSpoilersStatus()); + + mpSpoilerSavePathLineEdit = new QLineEdit(SettingsCache::instance().getSpoilerCardDatabasePath()); + mpSpoilerSavePathLineEdit->setReadOnly(true); + mpSpoilerPathButton = new QPushButton("..."); + connect(mpSpoilerPathButton, &QPushButton::clicked, this, &DeckEditorSettingsPage::spoilerPathButtonClicked); + + updateNowButton = new QPushButton; + updateNowButton->setFixedWidth(150); + connect(updateNowButton, &QPushButton::clicked, this, &DeckEditorSettingsPage::updateSpoilers); + + // Update the GUI depending on if the box is ticked or not + setSpoilersEnabled(mcDownloadSpoilersCheckBox.isChecked()); + + urlList = new QListWidget; + urlList->setSelectionMode(QAbstractItemView::SingleSelection); + urlList->setAlternatingRowColors(true); + urlList->setDragEnabled(true); + urlList->setDragDropMode(QAbstractItemView::InternalMove); + connect(urlList->model(), &QAbstractItemModel::rowsMoved, this, &DeckEditorSettingsPage::urlListChanged); + + urlList->addItems(SettingsCache::instance().downloads().getAllURLs()); + + aAdd = new QAction(this); + aAdd->setIcon(QPixmap("theme:icons/increment")); + connect(aAdd, &QAction::triggered, this, &DeckEditorSettingsPage::actAddURL); + + aEdit = new QAction(this); + aEdit->setIcon(QPixmap("theme:icons/pencil")); + connect(aEdit, &QAction::triggered, this, &DeckEditorSettingsPage::actEditURL); + + aRemove = new QAction(this); + aRemove->setIcon(QPixmap("theme:icons/decrement")); + connect(aRemove, &QAction::triggered, this, &DeckEditorSettingsPage::actRemoveURL); + + auto *urlToolBar = new QToolBar; + urlToolBar->setOrientation(Qt::Vertical); + urlToolBar->addAction(aAdd); + urlToolBar->addAction(aRemove); + urlToolBar->addAction(aEdit); + urlToolBar->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding); + + auto *urlListLayout = new QHBoxLayout; + urlListLayout->addWidget(urlToolBar); + urlListLayout->addWidget(urlList); + + // Top Layout + lpGeneralGrid->addWidget(&picDownloadCheckBox, 0, 0); + lpGeneralGrid->addWidget(&resetDownloadURLs, 0, 1); + lpGeneralGrid->addLayout(urlListLayout, 1, 0, 1, 2); + lpGeneralGrid->addWidget(&urlLinkLabel, 4, 0); + + // Spoiler Layout + lpSpoilerGrid->addWidget(&mcDownloadSpoilersCheckBox, 0, 0); + lpSpoilerGrid->addWidget(&mcSpoilerSaveLabel, 1, 0); + lpSpoilerGrid->addWidget(mpSpoilerSavePathLineEdit, 1, 1); + lpSpoilerGrid->addWidget(mpSpoilerPathButton, 1, 2); + lpSpoilerGrid->addWidget(&lastUpdatedLabel, 2, 0); + lpSpoilerGrid->addWidget(updateNowButton, 2, 1); + lpSpoilerGrid->addWidget(&infoOnSpoilersLabel, 3, 0, 1, 3, Qt::AlignTop); + + // On a change to the checkbox, hide/un-hide the other fields + connect(&mcDownloadSpoilersCheckBox, &QCheckBox::toggled, &SettingsCache::instance(), + &SettingsCache::setDownloadSpoilerStatus); + connect(&mcDownloadSpoilersCheckBox, &QCheckBox::toggled, this, &DeckEditorSettingsPage::setSpoilersEnabled); + + mpGeneralGroupBox = new QGroupBox; + mpGeneralGroupBox->setLayout(lpGeneralGrid); + + mpSpoilerGroupBox = new QGroupBox; + mpSpoilerGroupBox->setLayout(lpSpoilerGrid); + + auto *lpMainLayout = new QVBoxLayout; + lpMainLayout->addWidget(mpGeneralGroupBox); + lpMainLayout->addWidget(mpSpoilerGroupBox); + + setLayout(lpMainLayout); + + connect(&SettingsCache::instance(), &SettingsCache::langChanged, this, &DeckEditorSettingsPage::retranslateUi); + retranslateUi(); +} + +void DeckEditorSettingsPage::resetDownloadedURLsButtonClicked() +{ + SettingsCache::instance().downloads().resetToDefaultURLs(); + urlList->clear(); + urlList->addItems(SettingsCache::instance().downloads().getAllURLs()); + QMessageBox::information(this, tr("Success"), tr("Download URLs have been reset.")); +} + +void DeckEditorSettingsPage::actAddURL() +{ + bool ok; + QString msg = QInputDialog::getText(this, tr("Add URL"), tr("URL:"), QLineEdit::Normal, QString(), &ok); + if (ok) { + urlList->addItem(msg); + storeSettings(); + } +} + +void DeckEditorSettingsPage::actRemoveURL() +{ + if (urlList->currentItem() != nullptr) { + delete urlList->takeItem(urlList->currentRow()); + storeSettings(); + } +} + +void DeckEditorSettingsPage::actEditURL() +{ + if (urlList->currentItem()) { + QString oldText = urlList->currentItem()->text(); + bool ok; + QString msg = QInputDialog::getText(this, tr("Edit URL"), tr("URL:"), QLineEdit::Normal, oldText, &ok); + if (ok) { + urlList->currentItem()->setText(msg); + storeSettings(); + } + } +} + +void DeckEditorSettingsPage::storeSettings() +{ + qInfo() << "URL Priority Reset"; + + QStringList downloadUrls; + for (int i = 0; i < urlList->count(); i++) { + qInfo() << "Priority" << i << ":" << urlList->item(i)->text(); + downloadUrls << urlList->item(i)->text(); + } + SettingsCache::instance().downloads().setDownloadUrls(downloadUrls); +} + +void DeckEditorSettingsPage::urlListChanged(const QModelIndex &, int, int, const QModelIndex &, int) +{ + storeSettings(); +} + +void DeckEditorSettingsPage::updateSpoilers() +{ + // Disable the button so the user can only press it once at a time + updateNowButton->setDisabled(true); + updateNowButton->setText(tr("Updating...")); + + // Create a new SBU that will act as if the client was just reloaded + auto *sbu = new SpoilerBackgroundUpdater(); + connect(sbu, &SpoilerBackgroundUpdater::spoilerCheckerDone, this, &DeckEditorSettingsPage::unlockSettings); + connect(sbu, &SpoilerBackgroundUpdater::spoilersUpdatedSuccessfully, this, &DeckEditorSettingsPage::unlockSettings); +} + +void DeckEditorSettingsPage::unlockSettings() +{ + updateNowButton->setDisabled(false); + updateNowButton->setText(tr("Update Spoilers")); +} + +QString DeckEditorSettingsPage::getLastUpdateTime() +{ + QString fileName = SettingsCache::instance().getSpoilerCardDatabasePath(); + QFileInfo fi(fileName); + QDir fileDir(fi.path()); + QFile file(fileName); + + if (file.exists()) { + return fi.lastModified().toString("MMM d, hh:mm"); + } + + return QString(); +} + +void DeckEditorSettingsPage::spoilerPathButtonClicked() +{ + QString lsPath = QFileDialog::getExistingDirectory(this, tr("Choose path"), mpSpoilerSavePathLineEdit->text()); + if (lsPath.isEmpty()) { + return; + } + + mpSpoilerSavePathLineEdit->setText(lsPath + "/spoiler.xml"); + SettingsCache::instance().setSpoilerDatabasePath(lsPath + "/spoiler.xml"); +} + +void DeckEditorSettingsPage::setSpoilersEnabled(bool anInput) +{ + msDownloadSpoilersLabel.setEnabled(anInput); + mcSpoilerSaveLabel.setEnabled(anInput); + mpSpoilerSavePathLineEdit->setEnabled(anInput); + mpSpoilerPathButton->setEnabled(anInput); + lastUpdatedLabel.setEnabled(anInput); + updateNowButton->setEnabled(anInput); + infoOnSpoilersLabel.setEnabled(anInput); + + if (!anInput) { + SpoilerBackgroundUpdater::deleteSpoilerFile(); + } +} + +void DeckEditorSettingsPage::retranslateUi() +{ + mpGeneralGroupBox->setTitle(tr("URL Download Priority")); + mpSpoilerGroupBox->setTitle(tr("Spoilers")); + mcDownloadSpoilersCheckBox.setText(tr("Download Spoilers Automatically")); + mcSpoilerSaveLabel.setText(tr("Spoiler Location:")); + lastUpdatedLabel.setText(tr("Last Change") + ": " + getLastUpdateTime()); + infoOnSpoilersLabel.setText(tr("Spoilers download automatically on launch") + "\n" + + tr("Press the button to manually update without relaunching") + "\n\n" + + tr("Do not close settings until manual update is complete")); + picDownloadCheckBox.setText(tr("Download card pictures on the fly")); + urlLinkLabel.setText(QString("%2").arg(WIKI_CUSTOM_PIC_URL).arg(tr("How to add a custom URL"))); + resetDownloadURLs.setText(tr("Reset Download URLs")); + updateNowButton->setText(tr("Update Spoilers")); + aAdd->setText(tr("Add New URL")); + aEdit->setText(tr("Edit URL")); + aRemove->setText(tr("Remove URL")); +} \ No newline at end of file diff --git a/cockatrice/src/interface/widgets/settings_page/deck_editor_settings_page.h b/cockatrice/src/interface/widgets/settings_page/deck_editor_settings_page.h new file mode 100644 index 000000000..5db009c8a --- /dev/null +++ b/cockatrice/src/interface/widgets/settings_page/deck_editor_settings_page.h @@ -0,0 +1,51 @@ +#ifndef COCKATRICE_DECK_EDITOR_SETTINGS_PAGE_H +#define COCKATRICE_DECK_EDITOR_SETTINGS_PAGE_H + +#include "abstract_settings_page.h" + +#include +#include +#include +#include +#include + +class DeckEditorSettingsPage : public AbstractSettingsPage +{ + Q_OBJECT +public: + DeckEditorSettingsPage(); + void retranslateUi() override; + QString getLastUpdateTime(); + +private slots: + void storeSettings(); + void urlListChanged(const QModelIndex &, int, int, const QModelIndex &, int); + void setSpoilersEnabled(bool); + void spoilerPathButtonClicked(); + void updateSpoilers(); + void unlockSettings(); + void actAddURL(); + void actRemoveURL(); + void actEditURL(); + void resetDownloadedURLsButtonClicked(); + +private: + QPushButton resetDownloadURLs; + QLabel urlLinkLabel; + QCheckBox picDownloadCheckBox; + QListWidget *urlList; + QAction *aAdd, *aEdit, *aRemove; + QCheckBox mcDownloadSpoilersCheckBox; + QLabel msDownloadSpoilersLabel; + QGroupBox *mpGeneralGroupBox; + QGroupBox *mpSpoilerGroupBox; + + QLineEdit *mpSpoilerSavePathLineEdit; + QLabel mcSpoilerSaveLabel; + QLabel lastUpdatedLabel; + QLabel infoOnSpoilersLabel; + QPushButton *mpSpoilerPathButton; + QPushButton *updateNowButton; +}; + +#endif // COCKATRICE_DECK_EDITOR_SETTINGS_PAGE_H diff --git a/cockatrice/src/interface/widgets/settings_page/general_settings_page.cpp b/cockatrice/src/interface/widgets/settings_page/general_settings_page.cpp new file mode 100644 index 000000000..a4d34ffb5 --- /dev/null +++ b/cockatrice/src/interface/widgets/settings_page/general_settings_page.cpp @@ -0,0 +1,373 @@ +#include "general_settings_page.h" + +#include "../../../client/settings/cache_settings.h" +#include "../main.h" +#include "update/client/release_channel.h" + +#include +#include +#include +#include +#include + +enum startupCardUpdateCheckBehaviorIndex +{ + startupCardUpdateCheckBehaviorIndexNone, + startupCardUpdateCheckBehaviorIndexPrompt, + startupCardUpdateCheckBehaviorIndexAlways +}; + +GeneralSettingsPage::GeneralSettingsPage() +{ + QStringList languageCodes = findQmFiles(); + for (const QString &code : languageCodes) { + QString langName = languageName(code); + languageBox.addItem(langName, code); + } + + QString setLanguage = QCoreApplication::translate("i18n", DEFAULT_LANG_NAME); + int index = languageBox.findText(setLanguage, Qt::MatchExactly); + if (index == -1) { + qWarning() << "could not find language" << setLanguage; + } else { + languageBox.setCurrentIndex(index); + } + + // updates + SettingsCache &settings = SettingsCache::instance(); + startupUpdateCheckCheckBox.setChecked(settings.getCheckUpdatesOnStartup()); + + startupCardUpdateCheckBehaviorSelector.addItem(""); // these will be set in retranslateUI + startupCardUpdateCheckBehaviorSelector.addItem(""); + startupCardUpdateCheckBehaviorSelector.addItem(""); + if (SettingsCache::instance().getStartupCardUpdateCheckPromptForUpdate()) { + startupCardUpdateCheckBehaviorSelector.setCurrentIndex(startupCardUpdateCheckBehaviorIndexPrompt); + } else if (SettingsCache::instance().getStartupCardUpdateCheckAlwaysUpdate()) { + startupCardUpdateCheckBehaviorSelector.setCurrentIndex(startupCardUpdateCheckBehaviorIndexAlways); + } else { + startupCardUpdateCheckBehaviorSelector.setCurrentIndex(startupCardUpdateCheckBehaviorIndexNone); + } + + cardUpdateCheckIntervalSpinBox.setMinimum(1); + cardUpdateCheckIntervalSpinBox.setMaximum(30); + cardUpdateCheckIntervalSpinBox.setValue(settings.getCardUpdateCheckInterval()); + updateNotificationCheckBox.setChecked(settings.getNotifyAboutUpdates()); + newVersionOracleCheckBox.setChecked(settings.getNotifyAboutNewVersion()); + + showTipsOnStartup.setChecked(settings.getShowTipsOnStartup()); + + advertiseTranslationPageLabel.setTextInteractionFlags(Qt::LinksAccessibleByMouse); + advertiseTranslationPageLabel.setOpenExternalLinks(true); + + connect(&languageBox, qOverload(&QComboBox::currentIndexChanged), this, + &GeneralSettingsPage::languageBoxChanged); + connect(&startupUpdateCheckCheckBox, &QCheckBox::QT_STATE_CHANGED, &settings, + &SettingsCache::setCheckUpdatesOnStartup); + connect(&startupCardUpdateCheckBehaviorSelector, QOverload::of(&QComboBox::currentIndexChanged), this, + [](int index) { + SettingsCache::instance().setStartupCardUpdateCheckPromptForUpdate( + index == startupCardUpdateCheckBehaviorIndexPrompt); + SettingsCache::instance().setStartupCardUpdateCheckAlwaysUpdate( + index == startupCardUpdateCheckBehaviorIndexAlways); + }); + connect(&cardUpdateCheckIntervalSpinBox, qOverload(&QSpinBox::valueChanged), &settings, + &SettingsCache::setCardUpdateCheckInterval); + connect(&updateNotificationCheckBox, &QCheckBox::QT_STATE_CHANGED, &settings, &SettingsCache::setNotifyAboutUpdate); + connect(&newVersionOracleCheckBox, &QCheckBox::QT_STATE_CHANGED, &settings, + &SettingsCache::setNotifyAboutNewVersion); + connect(&showTipsOnStartup, &QCheckBox::clicked, &settings, &SettingsCache::setShowTipsOnStartup); + + auto *personalGrid = new QGridLayout; + personalGrid->addWidget(&languageLabel, 0, 0); + personalGrid->addWidget(&languageBox, 0, 1); + personalGrid->addWidget(&advertiseTranslationPageLabel, 1, 1, Qt::AlignRight); + personalGrid->addWidget(&updateReleaseChannelLabel, 2, 0); + personalGrid->addWidget(&updateReleaseChannelBox, 2, 1); + personalGrid->addWidget(&startupUpdateCheckCheckBox, 4, 0, 1, 2); + personalGrid->addWidget(&startupCardUpdateCheckBehaviorLabel, 5, 0); + personalGrid->addWidget(&startupCardUpdateCheckBehaviorSelector, 5, 1); + personalGrid->addWidget(&cardUpdateCheckIntervalLabel, 6, 0); + personalGrid->addWidget(&cardUpdateCheckIntervalSpinBox, 6, 1); + personalGrid->addWidget(&lastCardUpdateCheckDateLabel, 7, 1); + personalGrid->addWidget(&updateNotificationCheckBox, 8, 0, 1, 2); + personalGrid->addWidget(&newVersionOracleCheckBox, 9, 0, 1, 2); + personalGrid->addWidget(&showTipsOnStartup, 10, 0, 1, 2); + + personalGroupBox = new QGroupBox; + personalGroupBox->setLayout(personalGrid); + + deckPathEdit = new QLineEdit(settings.getDeckPath()); + deckPathEdit->setReadOnly(true); + auto *deckPathButton = new QPushButton("..."); + connect(deckPathButton, &QPushButton::clicked, this, &GeneralSettingsPage::deckPathButtonClicked); + + filtersPathEdit = new QLineEdit(settings.getFiltersPath()); + filtersPathEdit->setReadOnly(true); + auto *filtersPathButton = new QPushButton("..."); + connect(filtersPathButton, &QPushButton::clicked, this, &GeneralSettingsPage::filtersPathButtonClicked); + + replaysPathEdit = new QLineEdit(settings.getReplaysPath()); + replaysPathEdit->setReadOnly(true); + auto *replaysPathButton = new QPushButton("..."); + connect(replaysPathButton, &QPushButton::clicked, this, &GeneralSettingsPage::replaysPathButtonClicked); + + picsPathEdit = new QLineEdit(settings.getPicsPath()); + picsPathEdit->setReadOnly(true); + auto *picsPathButton = new QPushButton("..."); + connect(picsPathButton, &QPushButton::clicked, this, &GeneralSettingsPage::picsPathButtonClicked); + + cardDatabasePathEdit = new QLineEdit(settings.getCardDatabasePath()); + cardDatabasePathEdit->setReadOnly(true); + auto *cardDatabasePathButton = new QPushButton("..."); + connect(cardDatabasePathButton, &QPushButton::clicked, this, &GeneralSettingsPage::cardDatabasePathButtonClicked); + + customCardDatabasePathEdit = new QLineEdit(settings.getCustomCardDatabasePath()); + customCardDatabasePathEdit->setReadOnly(true); + auto *customCardDatabasePathButton = new QPushButton("..."); + connect(customCardDatabasePathButton, &QPushButton::clicked, this, + &GeneralSettingsPage::customCardDatabaseButtonClicked); + + tokenDatabasePathEdit = new QLineEdit(settings.getTokenDatabasePath()); + tokenDatabasePathEdit->setReadOnly(true); + auto *tokenDatabasePathButton = new QPushButton("..."); + connect(tokenDatabasePathButton, &QPushButton::clicked, this, &GeneralSettingsPage::tokenDatabasePathButtonClicked); + + // Required init here to avoid crashing on Portable builds + resetAllPathsButton = new QPushButton; + + bool isPortable = settings.getIsPortableBuild(); + if (isPortable) { + deckPathEdit->setEnabled(false); + filtersPathEdit->setEnabled(false); + replaysPathEdit->setEnabled(false); + picsPathEdit->setEnabled(false); + cardDatabasePathEdit->setEnabled(false); + customCardDatabasePathEdit->setEnabled(false); + tokenDatabasePathEdit->setEnabled(false); + + deckPathButton->setVisible(false); + replaysPathButton->setVisible(false); + picsPathButton->setVisible(false); + cardDatabasePathButton->setVisible(false); + customCardDatabasePathButton->setVisible(false); + tokenDatabasePathButton->setVisible(false); + } else { + connect(resetAllPathsButton, &QPushButton::clicked, this, &GeneralSettingsPage::resetAllPathsClicked); + allPathsResetLabel = new QLabel(tr("All paths have been reset")); + allPathsResetLabel->setVisible(false); + } + + auto *pathsGrid = new QGridLayout; + pathsGrid->addWidget(&deckPathLabel, 0, 0); + pathsGrid->addWidget(deckPathEdit, 0, 1); + pathsGrid->addWidget(deckPathButton, 0, 2); + pathsGrid->addWidget(&filtersPathLabel, 1, 0); + pathsGrid->addWidget(filtersPathEdit, 1, 1); + pathsGrid->addWidget(filtersPathButton, 1, 2); + pathsGrid->addWidget(&replaysPathLabel, 2, 0); + pathsGrid->addWidget(replaysPathEdit, 2, 1); + pathsGrid->addWidget(replaysPathButton, 2, 2); + pathsGrid->addWidget(&picsPathLabel, 3, 0); + pathsGrid->addWidget(picsPathEdit, 3, 1); + pathsGrid->addWidget(picsPathButton, 3, 2); + pathsGrid->addWidget(&cardDatabasePathLabel, 4, 0); + pathsGrid->addWidget(cardDatabasePathEdit, 4, 1); + pathsGrid->addWidget(cardDatabasePathButton, 4, 2); + pathsGrid->addWidget(&customCardDatabasePathLabel, 5, 0); + pathsGrid->addWidget(customCardDatabasePathEdit, 5, 1); + pathsGrid->addWidget(customCardDatabasePathButton, 5, 2); + pathsGrid->addWidget(&tokenDatabasePathLabel, 6, 0); + pathsGrid->addWidget(tokenDatabasePathEdit, 6, 1); + pathsGrid->addWidget(tokenDatabasePathButton, 6, 2); + if (!isPortable) { + pathsGrid->addWidget(resetAllPathsButton, 7, 0); + pathsGrid->addWidget(allPathsResetLabel, 7, 1); + } + pathsGroupBox = new QGroupBox; + pathsGroupBox->setLayout(pathsGrid); + + auto *mainLayout = new QVBoxLayout; + mainLayout->addWidget(personalGroupBox); + mainLayout->addWidget(pathsGroupBox); + mainLayout->addStretch(); + + GeneralSettingsPage::retranslateUi(); + + // connect the ReleaseChannel combo box only after the entries are inserted in retranslateUi + connect(&updateReleaseChannelBox, qOverload(&QComboBox::currentIndexChanged), &settings, + &SettingsCache::setUpdateReleaseChannelIndex); + updateReleaseChannelBox.setCurrentIndex(settings.getUpdateReleaseChannelIndex()); + + setLayout(mainLayout); + + connect(&SettingsCache::instance(), &SettingsCache::langChanged, this, &GeneralSettingsPage::retranslateUi); + retranslateUi(); +} + +QStringList GeneralSettingsPage::findQmFiles() +{ + QDir dir(translationPath); + QStringList fileNames = dir.entryList(QStringList(translationPrefix + "_*.qm"), QDir::Files, QDir::Name); + fileNames.replaceInStrings(QRegularExpression(translationPrefix + "_(.*)\\.qm"), "\\1"); + return fileNames; +} + +QString GeneralSettingsPage::languageName(const QString &lang) +{ + QTranslator qTranslator; + + QString appNameHint = translationPrefix + "_" + lang; + bool appTranslationLoaded = qTranslator.load(appNameHint, translationPath); + if (!appTranslationLoaded) { + qCWarning(GeneralSettingsPageLog) + << "Unable to load" << translationPrefix << "translation" << appNameHint << "at" << translationPath; + } + + return qTranslator.translate("i18n", DEFAULT_LANG_NAME); +} + +void GeneralSettingsPage::deckPathButtonClicked() +{ + QString path = QFileDialog::getExistingDirectory(this, tr("Choose path"), deckPathEdit->text()); + if (path.isEmpty()) { + return; + } + + deckPathEdit->setText(path); + SettingsCache::instance().setDeckPath(path); +} + +void GeneralSettingsPage::filtersPathButtonClicked() +{ + QString path = QFileDialog::getExistingDirectory(this, tr("Choose path"), filtersPathEdit->text()); + if (path.isEmpty()) { + return; + } + + filtersPathEdit->setText(path); + SettingsCache::instance().setFiltersPath(path); +} + +void GeneralSettingsPage::replaysPathButtonClicked() +{ + QString path = QFileDialog::getExistingDirectory(this, tr("Choose path"), replaysPathEdit->text()); + if (path.isEmpty()) { + return; + } + + replaysPathEdit->setText(path); + SettingsCache::instance().setReplaysPath(path); +} + +void GeneralSettingsPage::picsPathButtonClicked() +{ + QString path = QFileDialog::getExistingDirectory(this, tr("Choose path"), picsPathEdit->text()); + if (path.isEmpty()) { + return; + } + + picsPathEdit->setText(path); + SettingsCache::instance().setPicsPath(path); +} + +void GeneralSettingsPage::cardDatabasePathButtonClicked() +{ + QString path = QFileDialog::getOpenFileName(this, tr("Choose path"), cardDatabasePathEdit->text()); + if (path.isEmpty()) { + return; + } + + cardDatabasePathEdit->setText(path); + SettingsCache::instance().setCardDatabasePath(path); +} + +void GeneralSettingsPage::customCardDatabaseButtonClicked() +{ + QString path = QFileDialog::getExistingDirectory(this, tr("Choose path"), customCardDatabasePathEdit->text()); + if (path.isEmpty()) { + return; + } + + customCardDatabasePathEdit->setText(path); + SettingsCache::instance().setCustomCardDatabasePath(path); +} + +void GeneralSettingsPage::tokenDatabasePathButtonClicked() +{ + QString path = QFileDialog::getOpenFileName(this, tr("Choose path"), tokenDatabasePathEdit->text()); + if (path.isEmpty()) { + return; + } + + tokenDatabasePathEdit->setText(path); + SettingsCache::instance().setTokenDatabasePath(path); +} + +void GeneralSettingsPage::resetAllPathsClicked() +{ + SettingsCache &settings = SettingsCache::instance(); + settings.resetPaths(); + deckPathEdit->setText(settings.getDeckPath()); + replaysPathEdit->setText(settings.getReplaysPath()); + picsPathEdit->setText(settings.getPicsPath()); + cardDatabasePathEdit->setText(settings.getCardDatabasePath()); + customCardDatabasePathEdit->setText(settings.getCustomCardDatabasePath()); + tokenDatabasePathEdit->setText(settings.getTokenDatabasePath()); + allPathsResetLabel->setVisible(true); +} + +void GeneralSettingsPage::languageBoxChanged(int index) +{ + SettingsCache::instance().setLang(languageBox.itemData(index).toString()); +} + +void GeneralSettingsPage::retranslateUi() +{ + personalGroupBox->setTitle(tr("Personal settings")); + languageLabel.setText(tr("Language:")); + + if (SettingsCache::instance().getIsPortableBuild()) { + pathsGroupBox->setTitle(tr("Paths (editing disabled in portable mode)")); + } else { + pathsGroupBox->setTitle(tr("Paths")); + } + advertiseTranslationPageLabel.setText( + QString("%2").arg(WIKI_TRANSLATION_FAQ).arg(tr("How to help with translations"))); + deckPathLabel.setText(tr("Decks directory:")); + filtersPathLabel.setText(tr("Filters directory:")); + replaysPathLabel.setText(tr("Replays directory:")); + picsPathLabel.setText(tr("Pictures directory:")); + cardDatabasePathLabel.setText(tr("Card database:")); + customCardDatabasePathLabel.setText(tr("Custom database directory:")); + tokenDatabasePathLabel.setText(tr("Token database:")); + updateReleaseChannelLabel.setText(tr("Update channel")); + startupUpdateCheckCheckBox.setText(tr("Check for client updates on startup")); + startupCardUpdateCheckBehaviorLabel.setText(tr("Check for card database updates on startup")); + startupCardUpdateCheckBehaviorSelector.setItemText(startupCardUpdateCheckBehaviorIndexNone, tr("Don't check")); + startupCardUpdateCheckBehaviorSelector.setItemText(startupCardUpdateCheckBehaviorIndexPrompt, + tr("Prompt for update")); + startupCardUpdateCheckBehaviorSelector.setItemText(startupCardUpdateCheckBehaviorIndexAlways, + tr("Always update in the background")); + cardUpdateCheckIntervalLabel.setText(tr("Check for card database updates every")); + cardUpdateCheckIntervalSpinBox.setSuffix(tr(" days")); + updateNotificationCheckBox.setText(tr("Notify if a feature supported by the server is missing in my client")); + newVersionOracleCheckBox.setText(tr("Automatically run Oracle when running a new version of Cockatrice")); + showTipsOnStartup.setText(tr("Show tips on startup")); + resetAllPathsButton->setText(tr("Reset all paths")); + + const auto &settings = SettingsCache::instance(); + + QDate lastCheckDate = settings.getLastCardUpdateCheck(); + int daysAgo = lastCheckDate.daysTo(QDate::currentDate()); + + lastCardUpdateCheckDateLabel.setText( + tr("Last update check on %1 (%2 days ago)").arg(lastCheckDate.toString()).arg(daysAgo)); + + // We can't change the strings after they're put into the QComboBox, so this is our workaround + int oldIndex = updateReleaseChannelBox.currentIndex(); + updateReleaseChannelBox.clear(); + for (ReleaseChannel *chan : settings.getUpdateReleaseChannels()) { + updateReleaseChannelBox.addItem(tr(chan->getName().toUtf8())); + } + updateReleaseChannelBox.setCurrentIndex(oldIndex); +} \ No newline at end of file diff --git a/cockatrice/src/interface/widgets/settings_page/general_settings_page.h b/cockatrice/src/interface/widgets/settings_page/general_settings_page.h new file mode 100644 index 000000000..0d3c03804 --- /dev/null +++ b/cockatrice/src/interface/widgets/settings_page/general_settings_page.h @@ -0,0 +1,71 @@ +#ifndef COCKATRICE_GENERAL_SETTINGS_PAGE_H +#define COCKATRICE_GENERAL_SETTINGS_PAGE_H + +#include "abstract_settings_page.h" + +#include +#include +#include +#include +#include +#include +#include + +inline Q_LOGGING_CATEGORY(GeneralSettingsPageLog, "general_settings_page"); + +class GeneralSettingsPage : public AbstractSettingsPage +{ + Q_OBJECT +public: + GeneralSettingsPage(); + void retranslateUi() override; + +private slots: + void deckPathButtonClicked(); + void filtersPathButtonClicked(); + void replaysPathButtonClicked(); + void picsPathButtonClicked(); + void cardDatabasePathButtonClicked(); + void customCardDatabaseButtonClicked(); + void tokenDatabasePathButtonClicked(); + void resetAllPathsClicked(); + void languageBoxChanged(int index); + +private: + QStringList findQmFiles(); + QString languageName(const QString &lang); + QLineEdit *deckPathEdit; + QLineEdit *filtersPathEdit; + QLineEdit *replaysPathEdit; + QLineEdit *picsPathEdit; + QLineEdit *cardDatabasePathEdit; + QLineEdit *customCardDatabasePathEdit; + QLineEdit *tokenDatabasePathEdit; + QPushButton *resetAllPathsButton; + QLabel *allPathsResetLabel; + QGroupBox *personalGroupBox; + QGroupBox *pathsGroupBox; + QComboBox languageBox; + QCheckBox startupUpdateCheckCheckBox; + QLabel startupCardUpdateCheckBehaviorLabel; + QComboBox startupCardUpdateCheckBehaviorSelector; + QLabel cardUpdateCheckIntervalLabel; + QSpinBox cardUpdateCheckIntervalSpinBox; + QLabel lastCardUpdateCheckDateLabel; + QCheckBox updateNotificationCheckBox; + QCheckBox newVersionOracleCheckBox; + QComboBox updateReleaseChannelBox; + QLabel languageLabel; + QLabel deckPathLabel; + QLabel filtersPathLabel; + QLabel replaysPathLabel; + QLabel picsPathLabel; + QLabel cardDatabasePathLabel; + QLabel customCardDatabasePathLabel; + QLabel tokenDatabasePathLabel; + QLabel updateReleaseChannelLabel; + QLabel advertiseTranslationPageLabel; + QCheckBox showTipsOnStartup; +}; + +#endif // COCKATRICE_GENERAL_SETTINGS_PAGE_H diff --git a/cockatrice/src/interface/widgets/settings_page/messages_settings_page.cpp b/cockatrice/src/interface/widgets/settings_page/messages_settings_page.cpp new file mode 100644 index 000000000..f64398fe5 --- /dev/null +++ b/cockatrice/src/interface/widgets/settings_page/messages_settings_page.cpp @@ -0,0 +1,252 @@ +#include "messages_settings_page.h" + +#include "../../../client/settings/cache_settings.h" +#include "../interface/widgets/utility/get_text_with_max.h" + +#include +#include +#include + +MessagesSettingsPage::MessagesSettingsPage() +{ + chatMentionCheckBox.setChecked(SettingsCache::instance().getChatMention()); + connect(&chatMentionCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(), + &SettingsCache::setChatMention); + + chatMentionCompleterCheckbox.setChecked(SettingsCache::instance().getChatMentionCompleter()); + connect(&chatMentionCompleterCheckbox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(), + &SettingsCache::setChatMentionCompleter); + + explainMessagesLabel.setTextInteractionFlags(Qt::LinksAccessibleByMouse); + explainMessagesLabel.setOpenExternalLinks(true); + + ignoreUnregUsersMainChat.setChecked(SettingsCache::instance().getIgnoreUnregisteredUsers()); + ignoreUnregUserMessages.setChecked(SettingsCache::instance().getIgnoreUnregisteredUserMessages()); + connect(&ignoreUnregUsersMainChat, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(), + &SettingsCache::setIgnoreUnregisteredUsers); + connect(&ignoreUnregUserMessages, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(), + &SettingsCache::setIgnoreUnregisteredUserMessages); + + invertMentionForeground.setChecked(SettingsCache::instance().getChatMentionForeground()); + connect(&invertMentionForeground, &QCheckBox::QT_STATE_CHANGED, this, &MessagesSettingsPage::updateTextColor); + + invertHighlightForeground.setChecked(SettingsCache::instance().getChatHighlightForeground()); + connect(&invertHighlightForeground, &QCheckBox::QT_STATE_CHANGED, this, + &MessagesSettingsPage::updateTextHighlightColor); + + mentionColor = new QLineEdit(); + mentionColor->setText(SettingsCache::instance().getChatMentionColor()); + updateMentionPreview(); + connect(mentionColor, &QLineEdit::textChanged, this, &MessagesSettingsPage::updateColor); + + messagePopups.setChecked(SettingsCache::instance().getShowMessagePopup()); + connect(&messagePopups, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(), + &SettingsCache::setShowMessagePopups); + + mentionPopups.setChecked(SettingsCache::instance().getShowMentionPopup()); + connect(&mentionPopups, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(), + &SettingsCache::setShowMentionPopups); + + roomHistory.setChecked(SettingsCache::instance().getRoomHistory()); + connect(&roomHistory, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(), &SettingsCache::setRoomHistory); + + customAlertString = new QLineEdit(); + customAlertString->setText(SettingsCache::instance().getHighlightWords()); + connect(customAlertString, &QLineEdit::textChanged, &SettingsCache::instance(), &SettingsCache::setHighlightWords); + + auto *chatGrid = new QGridLayout; + chatGrid->addWidget(&chatMentionCheckBox, 0, 0); + chatGrid->addWidget(&invertMentionForeground, 0, 1); + chatGrid->addWidget(mentionColor, 0, 2); + chatGrid->addWidget(&chatMentionCompleterCheckbox, 1, 0); + chatGrid->addWidget(&ignoreUnregUsersMainChat, 2, 0); + chatGrid->addWidget(&hexLabel, 1, 2); + chatGrid->addWidget(&ignoreUnregUserMessages, 3, 0); + chatGrid->addWidget(&messagePopups, 4, 0); + chatGrid->addWidget(&mentionPopups, 5, 0); + chatGrid->addWidget(&roomHistory, 6, 0); + chatGroupBox = new QGroupBox; + chatGroupBox->setLayout(chatGrid); + + highlightColor = new QLineEdit(); + highlightColor->setText(SettingsCache::instance().getChatHighlightColor()); + updateHighlightPreview(); + connect(highlightColor, &QLineEdit::textChanged, this, &MessagesSettingsPage::updateHighlightColor); + + auto *highlightNotice = new QGridLayout; + highlightNotice->addWidget(highlightColor, 0, 2); + highlightNotice->addWidget(&invertHighlightForeground, 0, 1); + highlightNotice->addWidget(&hexHighlightLabel, 1, 2); + highlightNotice->addWidget(customAlertString, 0, 0); + highlightNotice->addWidget(&customAlertStringLabel, 1, 0); + highlightGroupBox = new QGroupBox; + highlightGroupBox->setLayout(highlightNotice); + + messageList = new QListWidget; + + int count = SettingsCache::instance().messages().getCount(); + for (int i = 0; i < count; i++) { + messageList->addItem(SettingsCache::instance().messages().getMessageAt(i)); + } + + aAdd = new QAction(this); + aAdd->setIcon(QPixmap("theme:icons/increment")); + connect(aAdd, &QAction::triggered, this, &MessagesSettingsPage::actAdd); + + aEdit = new QAction(this); + aEdit->setIcon(QPixmap("theme:icons/pencil")); + connect(aEdit, &QAction::triggered, this, &MessagesSettingsPage::actEdit); + + aRemove = new QAction(this); + aRemove->setIcon(QPixmap("theme:icons/decrement")); + connect(aRemove, &QAction::triggered, this, &MessagesSettingsPage::actRemove); + + auto *messageToolBar = new QToolBar; + messageToolBar->setOrientation(Qt::Vertical); + messageToolBar->addAction(aAdd); + messageToolBar->addAction(aRemove); + messageToolBar->addAction(aEdit); + messageToolBar->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding); + + auto *messageListLayout = new QHBoxLayout; + messageListLayout->addWidget(messageToolBar); + messageListLayout->addWidget(messageList); + + auto *messagesLayout = new QVBoxLayout; // combines the explainer label with the actual messages widget pieces + messagesLayout->addLayout(messageListLayout); + messagesLayout->addWidget(&explainMessagesLabel); + + messageGroupBox = new QGroupBox; // draws a box around the above layout and allows it to be titled + messageGroupBox->setLayout(messagesLayout); + + auto *mainLayout = new QVBoxLayout; // combines the messages groupbox with the rest of the menu + mainLayout->addWidget(messageGroupBox); + mainLayout->addWidget(chatGroupBox); + mainLayout->addWidget(highlightGroupBox); + + setLayout(mainLayout); + + connect(&SettingsCache::instance(), &SettingsCache::langChanged, this, &MessagesSettingsPage::retranslateUi); + retranslateUi(); +} + +void MessagesSettingsPage::updateColor(const QString &value) +{ +#if (QT_VERSION >= QT_VERSION_CHECK(6, 4, 0)) + QColor colorToSet = QColor::fromString("#" + value); +#else + QColor colorToSet; + colorToSet.setNamedColor("#" + value); +#endif + if (colorToSet.isValid()) { + SettingsCache::instance().setChatMentionColor(value); + updateMentionPreview(); + } +} + +void MessagesSettingsPage::updateHighlightColor(const QString &value) +{ +#if (QT_VERSION >= QT_VERSION_CHECK(6, 4, 0)) + QColor colorToSet = QColor::fromString("#" + value); +#else + QColor colorToSet; + colorToSet.setNamedColor("#" + value); +#endif + if (colorToSet.isValid()) { + SettingsCache::instance().setChatHighlightColor(value); + updateHighlightPreview(); + } +} + +void MessagesSettingsPage::updateTextColor(QT_STATE_CHANGED_T value) +{ + SettingsCache::instance().setChatMentionForeground(value); + updateMentionPreview(); +} + +void MessagesSettingsPage::updateTextHighlightColor(QT_STATE_CHANGED_T value) +{ + SettingsCache::instance().setChatHighlightForeground(value); + updateHighlightPreview(); +} + +void MessagesSettingsPage::updateMentionPreview() +{ + mentionColor->setStyleSheet( + "QLineEdit{background:#" + SettingsCache::instance().getChatMentionColor() + + ";color: " + (SettingsCache::instance().getChatMentionForeground() ? "white" : "black") + ";}"); +} + +void MessagesSettingsPage::updateHighlightPreview() +{ + highlightColor->setStyleSheet( + "QLineEdit{background:#" + SettingsCache::instance().getChatHighlightColor() + + ";color: " + (SettingsCache::instance().getChatHighlightForeground() ? "white" : "black") + ";}"); +} + +void MessagesSettingsPage::storeSettings() +{ + SettingsCache::instance().messages().setCount(messageList->count()); + for (int i = 0; i < messageList->count(); i++) { + SettingsCache::instance().messages().setMessageAt(i, messageList->item(i)->text()); + } + emit SettingsCache::instance().messages().messageMacrosChanged(); +} + +void MessagesSettingsPage::actAdd() +{ + bool ok; + QString msg = + getTextWithMax(this, tr("Add message"), tr("Message:"), QLineEdit::Normal, QString(), &ok, MAX_TEXT_LENGTH); + if (ok) { + messageList->addItem(msg); + storeSettings(); + } +} + +void MessagesSettingsPage::actEdit() +{ + if (messageList->currentItem()) { + QString oldText = messageList->currentItem()->text(); + bool ok; + QString msg = + getTextWithMax(this, tr("Edit message"), tr("Message:"), QLineEdit::Normal, oldText, &ok, MAX_TEXT_LENGTH); + if (ok) { + messageList->currentItem()->setText(msg); + storeSettings(); + } + } +} + +void MessagesSettingsPage::actRemove() +{ + if (messageList->currentItem() != nullptr) { + delete messageList->takeItem(messageList->currentRow()); + storeSettings(); + } +} + +void MessagesSettingsPage::retranslateUi() +{ + chatGroupBox->setTitle(tr("Chat settings")); + highlightGroupBox->setTitle(tr("Custom alert words")); + chatMentionCheckBox.setText(tr("Enable chat mentions")); + chatMentionCompleterCheckbox.setText(tr("Enable mention completer")); + messageGroupBox->setTitle(tr("In-game message macros")); + explainMessagesLabel.setText( + QString("%2").arg(WIKI_CUSTOM_SHORTCUTS).arg(tr("How to use in-game message macros"))); + ignoreUnregUsersMainChat.setText(tr("Ignore chat room messages sent by unregistered users")); + ignoreUnregUserMessages.setText(tr("Ignore private messages sent by unregistered users")); + invertMentionForeground.setText(tr("Invert text color")); + invertHighlightForeground.setText(tr("Invert text color")); + messagePopups.setText(tr("Enable desktop notifications for private messages")); + mentionPopups.setText(tr("Enable desktop notification for mentions")); + roomHistory.setText(tr("Enable room message history on join")); + hexLabel.setText(tr("(Color is hexadecimal)")); + hexHighlightLabel.setText(tr("(Color is hexadecimal)")); + customAlertStringLabel.setText(tr("Separate words with a space, alphanumeric characters only")); + customAlertString->setPlaceholderText(tr("Word1 Word2 Word3")); + aAdd->setText(tr("Add New Message")); + aEdit->setText(tr("Edit Message")); + aRemove->setText(tr("Remove Message")); +} \ No newline at end of file diff --git a/cockatrice/src/interface/widgets/settings_page/messages_settings_page.h b/cockatrice/src/interface/widgets/settings_page/messages_settings_page.h new file mode 100644 index 000000000..e8a4a8aa4 --- /dev/null +++ b/cockatrice/src/interface/widgets/settings_page/messages_settings_page.h @@ -0,0 +1,58 @@ +#ifndef COCKATRICE_MESSAGES_SETTINGS_PAGE_H +#define COCKATRICE_MESSAGES_SETTINGS_PAGE_H + +#include "abstract_settings_page.h" + +#include +#include +#include +#include +#include + +class MessagesSettingsPage : public AbstractSettingsPage +{ + Q_OBJECT +public: + MessagesSettingsPage(); + void retranslateUi() override; + +private slots: + void actAdd(); + void actEdit(); + void actRemove(); + void updateColor(const QString &value); + void updateHighlightColor(const QString &value); + void updateTextColor(QT_STATE_CHANGED_T value); + void updateTextHighlightColor(QT_STATE_CHANGED_T value); + +private: + QListWidget *messageList; + QAction *aAdd; + QAction *aEdit; + QAction *aRemove; + QCheckBox chatMentionCheckBox; + QCheckBox chatMentionCompleterCheckbox; + QCheckBox invertMentionForeground; + QCheckBox invertHighlightForeground; + QCheckBox ignoreUnregUsersMainChat; + QCheckBox ignoreUnregUserMessages; + QCheckBox messagePopups; + QCheckBox mentionPopups; + QCheckBox roomHistory; + QGroupBox *chatGroupBox; + QGroupBox *highlightGroupBox; + QGroupBox *messageGroupBox; + QLineEdit *mentionColor; + QLineEdit *highlightColor; + QLineEdit *customAlertString; + QLabel hexLabel; + QLabel hexHighlightLabel; + QLabel customAlertStringLabel; + QLabel explainMessagesLabel; + + void storeSettings(); + void updateMentionPreview(); + void updateHighlightPreview(); +}; + +#endif // COCKATRICE_MESSAGES_SETTINGS_PAGE_H diff --git a/cockatrice/src/interface/widgets/settings_page/shortcut_settings_page.cpp b/cockatrice/src/interface/widgets/settings_page/shortcut_settings_page.cpp new file mode 100644 index 000000000..e7a04ef79 --- /dev/null +++ b/cockatrice/src/interface/widgets/settings_page/shortcut_settings_page.cpp @@ -0,0 +1,128 @@ +#include "shortcut_settings_page.h" + +#include "../../../client/settings/cache_settings.h" +#include "../../../client/settings/shortcut_treeview.h" +#include "../interface/widgets/utility/custom_line_edit.h" +#include "../interface/widgets/utility/sequence_edit.h" + +#include +#include + +ShortcutSettingsPage::ShortcutSettingsPage() +{ + // search bar + searchEdit = new SearchLineEdit; + searchEdit->setObjectName("searchEdit"); + searchEdit->setClearButtonEnabled(true); + + setFocusProxy(searchEdit); + setFocusPolicy(Qt::ClickFocus); + + // table + shortcutsTable = new ShortcutTreeView(this); + + shortcutsTable->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + shortcutsTable->setEditTriggers(QAbstractItemView::NoEditTriggers); + shortcutsTable->setColumnWidth(0, width() / 3 * 2); + searchEdit->setTreeView(shortcutsTable); + + connect(searchEdit, &SearchLineEdit::textChanged, shortcutsTable, &ShortcutTreeView::updateSearchString); + + // edit widget + currentActionGroupLabel = new QLabel(this); + currentActionGroupName = new QLabel(this); + currentActionLabel = new QLabel(this); + currentActionName = new QLabel(this); + currentShortcutLabel = new QLabel(this); + editTextBox = new SequenceEdit("", this); + shortcutsTable->installEventFilter(editTextBox); + + // buttons + faqLabel = new QLabel(this); + faqLabel->setTextInteractionFlags(Qt::LinksAccessibleByMouse); + faqLabel->setOpenExternalLinks(true); + + btnResetAll = new QPushButton(this); + btnClearAll = new QPushButton(this); + + btnResetAll->setIcon(QPixmap("theme:icons/update")); + btnClearAll->setIcon(QPixmap("theme:icons/clearsearch")); + + // layout + auto *_editLayout = new QGridLayout; + _editLayout->addWidget(currentActionGroupLabel, 0, 0); + _editLayout->addWidget(currentActionGroupName, 0, 1); + _editLayout->addWidget(currentActionLabel, 1, 0); + _editLayout->addWidget(currentActionName, 1, 1); + _editLayout->addWidget(currentShortcutLabel, 2, 0); + _editLayout->addWidget(editTextBox, 2, 1); + + editShortcutGroupBox = new QGroupBox; + editShortcutGroupBox->setLayout(_editLayout); + + auto *_buttonsLayout = new QHBoxLayout; + _buttonsLayout->addWidget(faqLabel); + _buttonsLayout->addWidget(btnResetAll); + _buttonsLayout->addWidget(btnClearAll); + + auto *_mainLayout = new QVBoxLayout; + _mainLayout->addWidget(searchEdit); + _mainLayout->addWidget(shortcutsTable); + _mainLayout->addWidget(editShortcutGroupBox); + _mainLayout->addLayout(_buttonsLayout); + + setLayout(_mainLayout); + + connect(btnResetAll, &QPushButton::clicked, this, &ShortcutSettingsPage::resetShortcuts); + connect(btnClearAll, &QPushButton::clicked, this, &ShortcutSettingsPage::clearShortcuts); + + connect(shortcutsTable, &ShortcutTreeView::currentItemChanged, this, &ShortcutSettingsPage::currentItemChanged); + + connect(&SettingsCache::instance(), &SettingsCache::langChanged, this, &ShortcutSettingsPage::retranslateUi); + retranslateUi(); +} + +void ShortcutSettingsPage::currentItemChanged(const QString &key) +{ + if (key.isEmpty()) { + currentActionGroupName->setText(""); + currentActionName->setText(""); + editTextBox->setShortcutName(""); + } else { + QString group = SettingsCache::instance().shortcuts().getShortcut(key).getGroupName(); + QString action = SettingsCache::instance().shortcuts().getShortcut(key).getName(); + currentActionGroupName->setText(group); + currentActionName->setText(action); + editTextBox->setShortcutName(key); + } +} + +void ShortcutSettingsPage::resetShortcuts() +{ + if (QMessageBox::question(this, tr("Restore all default shortcuts"), + tr("Do you really want to restore all default shortcuts?")) == QMessageBox::Yes) { + SettingsCache::instance().shortcuts().resetAllShortcuts(); + } +} + +void ShortcutSettingsPage::clearShortcuts() +{ + if (QMessageBox::question(this, tr("Clear all default shortcuts"), + tr("Do you really want to clear all shortcuts?")) == QMessageBox::Yes) { + SettingsCache::instance().shortcuts().clearAllShortcuts(); + } +} + +void ShortcutSettingsPage::retranslateUi() +{ + shortcutsTable->retranslateUi(); + + currentActionGroupLabel->setText(tr("Section:")); + currentActionLabel->setText(tr("Action:")); + currentShortcutLabel->setText(tr("Shortcut:")); + editTextBox->retranslateUi(); + faqLabel->setText(QString("%2").arg(WIKI_CUSTOM_SHORTCUTS).arg(tr("How to set custom shortcuts"))); + btnResetAll->setText(tr("Restore all default shortcuts")); + btnClearAll->setText(tr("Clear all shortcuts")); + searchEdit->setPlaceholderText(tr("Search by shortcut name")); +} diff --git a/cockatrice/src/interface/widgets/settings_page/shortcut_settings_page.h b/cockatrice/src/interface/widgets/settings_page/shortcut_settings_page.h new file mode 100644 index 000000000..05391df77 --- /dev/null +++ b/cockatrice/src/interface/widgets/settings_page/shortcut_settings_page.h @@ -0,0 +1,45 @@ +#ifndef COCKATRICE_SHORTCUT_SETTINGS_PAGE_H +#define COCKATRICE_SHORTCUT_SETTINGS_PAGE_H + +#include "abstract_settings_page.h" + +#include +#include +#include +#include + +class SequenceEdit; +class ShortcutTreeView; +class SearchLineEdit; + +class ShortcutSettingsPage : public AbstractSettingsPage +{ + Q_OBJECT +public: + ShortcutSettingsPage(); + void retranslateUi() override; + +private: + SearchLineEdit *searchEdit; + ShortcutTreeView *shortcutsTable; + QVBoxLayout *mainLayout; + QHBoxLayout *buttonsLayout; + QGroupBox *editShortcutGroupBox; + QGridLayout *editLayout; + QLabel *currentActionGroupLabel; + QLabel *currentActionGroupName; + QLabel *currentActionLabel; + QLabel *currentActionName; + QLabel *currentShortcutLabel; + SequenceEdit *editTextBox; + QLabel *faqLabel; + QPushButton *btnResetAll; + QPushButton *btnClearAll; + +private slots: + void resetShortcuts(); + void clearShortcuts(); + void currentItemChanged(const QString &key); +}; + +#endif // COCKATRICE_SHORTCUT_SETTINGS_PAGE_H diff --git a/cockatrice/src/interface/widgets/settings_page/sound_settings_page.cpp b/cockatrice/src/interface/widgets/settings_page/sound_settings_page.cpp new file mode 100644 index 000000000..e7e92ea15 --- /dev/null +++ b/cockatrice/src/interface/widgets/settings_page/sound_settings_page.cpp @@ -0,0 +1,86 @@ +#include "sound_settings_page.h" + +#include "../../../client/settings/cache_settings.h" +#include "../client/sound_engine.h" + +#include + +SoundSettingsPage::SoundSettingsPage() +{ + soundEnabledCheckBox.setChecked(SettingsCache::instance().getSoundEnabled()); + connect(&soundEnabledCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(), + &SettingsCache::setSoundEnabled); + + QString themeName = SettingsCache::instance().getSoundThemeName(); + + QStringList themeDirs = soundEngine->getAvailableThemes().keys(); + for (int i = 0; i < themeDirs.size(); i++) { + themeBox.addItem(themeDirs[i]); + if (themeDirs[i] == themeName) { + themeBox.setCurrentIndex(i); + } + } + + connect(&themeBox, qOverload(&QComboBox::currentIndexChanged), this, &SoundSettingsPage::themeBoxChanged); + connect(&soundTestButton, &QPushButton::clicked, soundEngine, &SoundEngine::testSound); + + masterVolumeSlider = new QSlider(Qt::Horizontal); + masterVolumeSlider->setMinimum(0); + masterVolumeSlider->setMaximum(100); + masterVolumeSlider->setValue(SettingsCache::instance().getMasterVolume()); + masterVolumeSlider->setToolTip(QString::number(SettingsCache::instance().getMasterVolume())); + connect(&SettingsCache::instance(), &SettingsCache::masterVolumeChanged, this, + &SoundSettingsPage::masterVolumeChanged); + connect(masterVolumeSlider, &QSlider::sliderReleased, soundEngine, &SoundEngine::testSound); + connect(masterVolumeSlider, &QSlider::valueChanged, &SettingsCache::instance(), &SettingsCache::setMasterVolume); + + masterVolumeSpinBox = new QSpinBox(); + masterVolumeSpinBox->setMinimum(0); + masterVolumeSpinBox->setMaximum(100); + masterVolumeSpinBox->setValue(SettingsCache::instance().getMasterVolume()); + connect(masterVolumeSlider, &QSlider::valueChanged, masterVolumeSpinBox, &QSpinBox::setValue); + connect(masterVolumeSpinBox, qOverload(&QSpinBox::valueChanged), masterVolumeSlider, &QSlider::setValue); + + auto *soundGrid = new QGridLayout; + soundGrid->addWidget(&soundEnabledCheckBox, 0, 0, 1, 3); + soundGrid->addWidget(&masterVolumeLabel, 1, 0); + soundGrid->addWidget(masterVolumeSlider, 1, 1); + soundGrid->addWidget(masterVolumeSpinBox, 1, 2); + soundGrid->addWidget(&themeLabel, 2, 0); + soundGrid->addWidget(&themeBox, 2, 1); + soundGrid->addWidget(&soundTestButton, 3, 1); + + soundGroupBox = new QGroupBox; + soundGroupBox->setLayout(soundGrid); + + auto *mainLayout = new QVBoxLayout; + mainLayout->addWidget(soundGroupBox); + mainLayout->addStretch(); + + setLayout(mainLayout); + + connect(&SettingsCache::instance(), &SettingsCache::langChanged, this, &SoundSettingsPage::retranslateUi); + retranslateUi(); +} + +void SoundSettingsPage::themeBoxChanged(int index) +{ + QStringList themeDirs = soundEngine->getAvailableThemes().keys(); + if (index >= 0 && index < themeDirs.count()) { + SettingsCache::instance().setSoundThemeName(themeDirs.at(index)); + } +} + +void SoundSettingsPage::masterVolumeChanged(int value) +{ + masterVolumeSlider->setToolTip(QString::number(value)); +} + +void SoundSettingsPage::retranslateUi() +{ + soundEnabledCheckBox.setText(tr("Enable &sounds")); + themeLabel.setText(tr("Current sounds theme:")); + soundTestButton.setText(tr("Test system sound engine")); + soundGroupBox->setTitle(tr("Sound settings")); + masterVolumeLabel.setText(tr("Master volume")); +} \ No newline at end of file diff --git a/cockatrice/src/interface/widgets/settings_page/sound_settings_page.h b/cockatrice/src/interface/widgets/settings_page/sound_settings_page.h new file mode 100644 index 000000000..f90bcbc5a --- /dev/null +++ b/cockatrice/src/interface/widgets/settings_page/sound_settings_page.h @@ -0,0 +1,35 @@ +#ifndef COCKATRICE_SOUND_SETTINGS_PAGE_H +#define COCKATRICE_SOUND_SETTINGS_PAGE_H + +#include "abstract_settings_page.h" + +#include +#include +#include +#include +#include +#include + +class SoundSettingsPage : public AbstractSettingsPage +{ + Q_OBJECT +public: + SoundSettingsPage(); + void retranslateUi() override; + +private: + QLabel themeLabel; + QComboBox themeBox; + QGroupBox *soundGroupBox; + QPushButton soundTestButton; + QCheckBox soundEnabledCheckBox; + QLabel masterVolumeLabel; + QSlider *masterVolumeSlider; + QSpinBox *masterVolumeSpinBox; + +private slots: + void masterVolumeChanged(int value); + void themeBoxChanged(int index); +}; + +#endif // COCKATRICE_SOUND_SETTINGS_PAGE_H diff --git a/cockatrice/src/interface/widgets/settings_page/storage_settings_page.cpp b/cockatrice/src/interface/widgets/settings_page/storage_settings_page.cpp new file mode 100644 index 000000000..c9d3c7789 --- /dev/null +++ b/cockatrice/src/interface/widgets/settings_page/storage_settings_page.cpp @@ -0,0 +1,244 @@ +#include "storage_settings_page.h" + +#include "../../../client/settings/cache_settings.h" +#include "../interface/card_picture_loader/card_picture_loader.h" + +#include +#include +#include + +StorageSettingsPage::StorageSettingsPage() +{ + auto *lpNetworkCacheGrid = new QGridLayout; + auto *lpImageBackupGrid = new QGridLayout; + auto *lpPixmapCacheGrid = new QGridLayout; + + networkCacheExplainerLabel.setWordWrap(true); + imageBackupExplainerLabel.setWordWrap(true); + pixmapCacheExplainerLabel.setWordWrap(true); + + connect(&clearDownloadedPicsButton, &QPushButton::clicked, this, + &StorageSettingsPage::clearDownloadedPicsButtonClicked); + + connect(&clearPixmapCacheButton, &QPushButton::clicked, this, &StorageSettingsPage::clearPixmapCacheButtonClicked); + + // pixmap cache + pixmapCacheEdit.setMinimum(PIXMAPCACHE_SIZE_MIN); + // 2047 is the max value to avoid overflowing of QPixmapCache::setCacheLimit(int size) + pixmapCacheEdit.setMaximum(PIXMAPCACHE_SIZE_MAX); + pixmapCacheEdit.setSingleStep(64); + pixmapCacheEdit.setValue(SettingsCache::instance().getPixmapCacheSize()); + pixmapCacheEdit.setSuffix(" MB"); + + // Caching method + + cardPictureLoaderCacheMethodComboBox = new QComboBox; + for (auto method : CardPictureLoaderCacheMethod::methods()) { + cardPictureLoaderCacheMethodComboBox->addItem(method.displayName, static_cast(method.id)); + } + + int currentCacheMethod = static_cast(SettingsCache::instance().getCardPictureLoaderCacheMethod()); + + int currentIndex = cardPictureLoaderCacheMethodComboBox->findData(currentCacheMethod); + if (currentIndex >= 0) { + cardPictureLoaderCacheMethodComboBox->setCurrentIndex(currentIndex); + } + + connect(cardPictureLoaderCacheMethodComboBox, qOverload(&QComboBox::currentIndexChanged), this, + [this](int index) { + auto cacheMethod = static_cast( + cardPictureLoaderCacheMethodComboBox->itemData(index).toInt()); + + bool useNetworkCache = (cacheMethod == CardPictureLoaderCacheMethod::CacheMethod::NETWORK_CACHE); + + if (useNetworkCache) { + clearImageBackupsButtonClicked(); + } else { + clearDownloadedPicsButtonClicked(); + } + + mpNetworkCacheGroupBox->setEnabled(useNetworkCache); + mpImageBackupGroupBox->setEnabled(!useNetworkCache); + + SettingsCache::instance().setCardImageCacheMethod(cacheMethod); + }); + + // Network Cache + + networkCacheEdit.setMinimum(NETWORK_CACHE_SIZE_MIN); + networkCacheEdit.setMaximum(NETWORK_CACHE_SIZE_MAX); + networkCacheEdit.setSingleStep(1); + networkCacheEdit.setValue(SettingsCache::instance().getNetworkCacheSizeInMB()); + networkCacheEdit.setSuffix(" MB"); + + networkRedirectCacheTtlEdit.setMinimum(NETWORK_REDIRECT_CACHE_TTL_MIN); + networkRedirectCacheTtlEdit.setMaximum(NETWORK_REDIRECT_CACHE_TTL_MAX); + networkRedirectCacheTtlEdit.setSingleStep(1); + networkRedirectCacheTtlEdit.setValue(SettingsCache::instance().getRedirectCacheTtl()); + + // Image Backup + localCardImageStorageNamingSchemeComboBox = new QComboBox; + for (const auto &scheme : CardPictureLoaderLocalSchemes::exportSchemes()) { + localCardImageStorageNamingSchemeComboBox->addItem(scheme.displayName, static_cast(scheme.id)); + } + + int current = static_cast(SettingsCache::instance().getLocalCardImageStorageNamingScheme()); + + int index = localCardImageStorageNamingSchemeComboBox->findData(current); + if (index >= 0) { + localCardImageStorageNamingSchemeComboBox->setCurrentIndex(index); + } + + connect(localCardImageStorageNamingSchemeComboBox, qOverload(&QComboBox::currentIndexChanged), this, + [this](int index) { + auto scheme = static_cast( + localCardImageStorageNamingSchemeComboBox->itemData(index).toInt()); + SettingsCache::instance().setLocalCardImageStorageNamingScheme(scheme); + }); + + connect(&clearBackupsButton, &QPushButton::clicked, this, &StorageSettingsPage::clearImageBackupsButtonClicked); + + auto cacheMethodLayout = new QHBoxLayout; + cacheMethodLayout->addWidget(&cardPictureLoaderCacheMethodLabel); + cacheMethodLayout->addWidget(cardPictureLoaderCacheMethodComboBox); + + auto networkCacheLayout = new QHBoxLayout; + networkCacheLayout->addWidget(&clearDownloadedPicsButton); + networkCacheLayout->addStretch(); + networkCacheLayout->addWidget(&networkCacheLabel); + networkCacheLayout->addWidget(&networkCacheEdit); + + auto networkRedirectCacheLayout = new QHBoxLayout; + networkRedirectCacheLayout->addStretch(); + networkRedirectCacheLayout->addWidget(&networkRedirectCacheTtlLabel); + networkRedirectCacheLayout->addWidget(&networkRedirectCacheTtlEdit); + + auto pixmapCacheLayout = new QHBoxLayout; + pixmapCacheLayout->addWidget(&clearPixmapCacheButton); + pixmapCacheLayout->addStretch(); + pixmapCacheLayout->addWidget(&pixmapCacheLabel); + pixmapCacheLayout->addWidget(&pixmapCacheEdit); + + lpNetworkCacheGrid->addWidget(&networkCacheExplainerLabel, 0, 0); + lpNetworkCacheGrid->addLayout(networkCacheLayout, 1, 0); + lpNetworkCacheGrid->addLayout(networkRedirectCacheLayout, 2, 0); + + // Image Backup Layout + lpImageBackupGrid->addWidget(&imageBackupExplainerLabel, 0, 0, 1, 2); + lpImageBackupGrid->addWidget(&localCardImageStorageNamingSchemeLabel, 1, 0); + lpImageBackupGrid->addWidget(localCardImageStorageNamingSchemeComboBox, 1, 1); + lpImageBackupGrid->addWidget(&clearBackupsButton, 2, 0); + + lpPixmapCacheGrid->addWidget(&pixmapCacheExplainerLabel, 0, 0); + lpPixmapCacheGrid->addLayout(pixmapCacheLayout, 1, 0); + + connect(&pixmapCacheEdit, qOverload(&QSpinBox::valueChanged), &SettingsCache::instance(), + &SettingsCache::setPixmapCacheSize); + connect(&networkCacheEdit, qOverload(&QSpinBox::valueChanged), &SettingsCache::instance(), + &SettingsCache::setNetworkCacheSizeInMB); + connect(&networkRedirectCacheTtlEdit, qOverload(&QSpinBox::valueChanged), &SettingsCache::instance(), + &SettingsCache::setNetworkRedirectCacheTtl); + + mpCacheMethodGroupBox = new QGroupBox; + mpCacheMethodGroupBox->setLayout(cacheMethodLayout); + + mpNetworkCacheGroupBox = new QGroupBox; + mpNetworkCacheGroupBox->setLayout(lpNetworkCacheGrid); + + mpImageBackupGroupBox = new QGroupBox; + mpImageBackupGroupBox->setLayout(lpImageBackupGrid); + + mpPixmapCacheGroupBox = new QGroupBox; + mpPixmapCacheGroupBox->setLayout(lpPixmapCacheGrid); + + auto *lpMainLayout = new QVBoxLayout; + + lpMainLayout->addWidget(mpCacheMethodGroupBox); + lpMainLayout->addWidget(mpNetworkCacheGroupBox); + lpMainLayout->addWidget(mpImageBackupGroupBox); + lpMainLayout->addWidget(mpPixmapCacheGroupBox); + lpMainLayout->addStretch(); + + setLayout(lpMainLayout); + + bool useNetworkCache = SettingsCache::instance().getCardPictureLoaderCacheMethod() == + CardPictureLoaderCacheMethod::CacheMethod::NETWORK_CACHE; + + mpNetworkCacheGroupBox->setEnabled(useNetworkCache); + mpImageBackupGroupBox->setEnabled(!useNetworkCache); + + connect(&SettingsCache::instance(), &SettingsCache::langChanged, this, &StorageSettingsPage::retranslateUi); + retranslateUi(); +} + +void StorageSettingsPage::clearDownloadedPicsButtonClicked() +{ + CardPictureLoader::clearNetworkCache(); + CardPictureLoader::clearPixmapCache(); + QMessageBox::information(this, tr("Success"), tr("Cached card pictures have been reset.")); +} + +void StorageSettingsPage::clearImageBackupsButtonClicked() +{ + QString picsPath = SettingsCache::instance().getPicsPath() + "/downloadedPics"; + + QDir dir(picsPath); + bool success = dir.removeRecursively(); + + CardPictureLoader::clearPixmapCache(); + + if (success) { + QMessageBox::information(this, tr("Success"), tr("Downloaded card pictures have been reset.")); + } else { + QMessageBox::critical(this, tr("Error"), tr("One or more downloaded card pictures could not be cleared.")); + } +} + +void StorageSettingsPage::clearPixmapCacheButtonClicked() +{ + CardPictureLoader::clearPixmapCache(); + QMessageBox::information(this, tr("Success"), tr("In-memory (currently loaded) card pictures have been reset.")); +} + +void StorageSettingsPage::retranslateUi() +{ + cardPictureLoaderCacheMethodLabel.setText(tr("Card Picture Loader Caching Method:")); + + networkCacheExplainerLabel.setText( + tr("The network cache is the preferred way of storing images. Downloaded images " + "are stored here until the size of the cache exceeds the configured size. Cockatrice automatically monitors " + "this cache and deletes the least recently seen card images to ensure the cache does not exceed the " + "configured size.")); + imageBackupExplainerLabel.setText( + tr("Writing card images directly to a folder on your hard drive is another way " + "of storing images. This does not change how Cockatrice accesses or downloads " + "images. Cockatrice will NOT automatically monitor and clear this folder, so if you enable this option, it " + "is up to you to ensure sufficient available space. It should also be noted that if a provider outage " + "causes you to download the wrong picture (i.e. wrong printing) you will be stuck with it until you " + "manually delete the file, as opposed to using the network cache, which automatically rotates and thus " + "correct errors after a while.")); + pixmapCacheExplainerLabel.setText( + tr("This is the in-memory picture cache used by the application at runtime. It determines how much memory " + "(RAM) Cockatrice can use before it has to fetch card images from the hard disk again. Increasing this will " + "allow more card images to be displayed at once but shouldn't be necessary. Clearing this will make " + "Cockatrice reload all images from the network cache or the disk.")); + + clearDownloadedPicsButton.setText(tr("Delete Cached Images")); + clearBackupsButton.setText(tr("Delete Saved Images")); + clearPixmapCacheButton.setText(tr("Clear In-Memory Images")); + + mpCacheMethodGroupBox->setTitle(tr("Card Picture Loader Cache Method")); + mpNetworkCacheGroupBox->setTitle(tr("Network Cache")); + mpImageBackupGroupBox->setTitle(tr("Filesystem")); + mpPixmapCacheGroupBox->setTitle(tr("In-Memory Picture Cache")); + + networkCacheLabel.setText(tr("Network Cache Size:")); + networkCacheEdit.setToolTip(tr("On-disk cache for downloaded pictures")); + networkRedirectCacheTtlLabel.setText(tr("Redirect Cache TTL:")); + networkRedirectCacheTtlEdit.setToolTip(tr("How long cached redirects for urls are valid for.")); + pixmapCacheLabel.setText(tr("Picture Cache Size:")); + pixmapCacheEdit.setToolTip(tr("In-memory cache for pictures not currently on screen")); + localCardImageStorageNamingSchemeLabel.setText(tr("Naming scheme:")); + + networkRedirectCacheTtlEdit.setSuffix(" " + tr("Day(s)")); +} \ No newline at end of file diff --git a/cockatrice/src/interface/widgets/settings_page/storage_settings_page.h b/cockatrice/src/interface/widgets/settings_page/storage_settings_page.h new file mode 100644 index 000000000..5c8a00981 --- /dev/null +++ b/cockatrice/src/interface/widgets/settings_page/storage_settings_page.h @@ -0,0 +1,50 @@ +#ifndef COCKATRICE_STORAGE_SETTINGS_PAGE_H +#define COCKATRICE_STORAGE_SETTINGS_PAGE_H + +#include "abstract_settings_page.h" + +#include +#include +#include +#include +#include + +class StorageSettingsPage : public AbstractSettingsPage +{ + Q_OBJECT +public: + StorageSettingsPage(); + void retranslateUi() override; + +private slots: + void clearDownloadedPicsButtonClicked(); + void clearImageBackupsButtonClicked(); + void clearPixmapCacheButtonClicked(); + +private: + QPushButton clearDownloadedPicsButton; + QPushButton clearBackupsButton; + QPushButton clearPixmapCacheButton; + + QGroupBox *mpCacheMethodGroupBox; + QGroupBox *mpNetworkCacheGroupBox; + QGroupBox *mpImageBackupGroupBox; + QGroupBox *mpPixmapCacheGroupBox; + + QLabel networkCacheExplainerLabel; + QLabel imageBackupExplainerLabel; + QLabel pixmapCacheExplainerLabel; + + QLabel cardPictureLoaderCacheMethodLabel; + QComboBox *cardPictureLoaderCacheMethodComboBox; + QLabel networkCacheLabel; + QSpinBox networkCacheEdit; + QLabel networkRedirectCacheTtlLabel; + QSpinBox networkRedirectCacheTtlEdit; + QSpinBox pixmapCacheEdit; + QLabel pixmapCacheLabel; + QLabel localCardImageStorageNamingSchemeLabel; + QComboBox *localCardImageStorageNamingSchemeComboBox; +}; + +#endif // COCKATRICE_STORAGE_SETTINGS_PAGE_H diff --git a/cockatrice/src/interface/widgets/settings_page/user_interface_settings_page.cpp b/cockatrice/src/interface/widgets/settings_page/user_interface_settings_page.cpp new file mode 100644 index 000000000..dfa736a1a --- /dev/null +++ b/cockatrice/src/interface/widgets/settings_page/user_interface_settings_page.cpp @@ -0,0 +1,234 @@ +#include "user_interface_settings_page.h" + +#include "../../../client/settings/cache_settings.h" +#include "../interface/widgets/tabs/tab_supervisor.h" + +#include + +enum visualDeckStoragePromptForConversionIndex +{ + visualDeckStoragePromptForConversionIndexNone, + visualDeckStoragePromptForConversionIndexPrompt, + visualDeckStoragePromptForConversionIndexAlways +}; + +UserInterfaceSettingsPage::UserInterfaceSettingsPage() +{ + // general settings and notification settings + notificationsEnabledCheckBox.setChecked(SettingsCache::instance().getNotificationsEnabled()); + connect(¬ificationsEnabledCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(), + &SettingsCache::setNotificationsEnabled); + connect(¬ificationsEnabledCheckBox, &QCheckBox::QT_STATE_CHANGED, this, + &UserInterfaceSettingsPage::setNotificationEnabled); + + specNotificationsEnabledCheckBox.setChecked(SettingsCache::instance().getSpectatorNotificationsEnabled()); + specNotificationsEnabledCheckBox.setEnabled(SettingsCache::instance().getNotificationsEnabled()); + connect(&specNotificationsEnabledCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(), + &SettingsCache::setSpectatorNotificationsEnabled); + + buddyConnectNotificationsEnabledCheckBox.setChecked( + SettingsCache::instance().getBuddyConnectNotificationsEnabled()); + buddyConnectNotificationsEnabledCheckBox.setEnabled(SettingsCache::instance().getNotificationsEnabled()); + connect(&buddyConnectNotificationsEnabledCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(), + &SettingsCache::setBuddyConnectNotificationsEnabled); + + doubleClickToPlayCheckBox.setChecked(SettingsCache::instance().getDoubleClickToPlay()); + connect(&doubleClickToPlayCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(), + &SettingsCache::setDoubleClickToPlay); + + clickPlaysAllSelectedCheckBox.setChecked(SettingsCache::instance().getClickPlaysAllSelected()); + connect(&clickPlaysAllSelectedCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(), + &SettingsCache::setClickPlaysAllSelected); + + playToStackCheckBox.setChecked(SettingsCache::instance().getPlayToStack()); + connect(&playToStackCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(), + &SettingsCache::setPlayToStack); + + doNotDeleteArrowsInSubPhasesCheckBox.setChecked(SettingsCache::instance().getDoNotDeleteArrowsInSubPhases()); + connect(&doNotDeleteArrowsInSubPhasesCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(), + &SettingsCache::setDoNotDeleteArrowsInSubPhases); + + closeEmptyCardViewCheckBox.setChecked(SettingsCache::instance().getCloseEmptyCardView()); + connect(&closeEmptyCardViewCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(), + &SettingsCache::setCloseEmptyCardView); + + focusCardViewSearchBarCheckBox.setChecked(SettingsCache::instance().getFocusCardViewSearchBar()); + connect(&focusCardViewSearchBarCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(), + &SettingsCache::setFocusCardViewSearchBar); + + annotateTokensCheckBox.setChecked(SettingsCache::instance().getAnnotateTokens()); + connect(&annotateTokensCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(), + &SettingsCache::setAnnotateTokens); + + showDragSelectionCountCheckBox.setChecked(SettingsCache::instance().getShowDragSelectionCount()); + connect(&showDragSelectionCountCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(), + &SettingsCache::setShowDragSelectionCount); + + showTotalSelectionCountCheckBox.setChecked(SettingsCache::instance().getShowTotalSelectionCount()); + connect(&showTotalSelectionCountCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(), + &SettingsCache::setShowTotalSelectionCount); + + useTearOffMenusCheckBox.setChecked(SettingsCache::instance().getUseTearOffMenus()); + connect(&useTearOffMenusCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(), + [](const QT_STATE_CHANGED_T state) { SettingsCache::instance().setUseTearOffMenus(state == Qt::Checked); }); + + auto *generalGrid = new QGridLayout; + generalGrid->addWidget(&doubleClickToPlayCheckBox, 0, 0); + generalGrid->addWidget(&clickPlaysAllSelectedCheckBox, 1, 0); + generalGrid->addWidget(&playToStackCheckBox, 2, 0); + generalGrid->addWidget(&doNotDeleteArrowsInSubPhasesCheckBox, 3, 0); + generalGrid->addWidget(&closeEmptyCardViewCheckBox, 4, 0); + generalGrid->addWidget(&focusCardViewSearchBarCheckBox, 5, 0); + generalGrid->addWidget(&annotateTokensCheckBox, 6, 0); + generalGrid->addWidget(&showDragSelectionCountCheckBox, 7, 0); + generalGrid->addWidget(&showTotalSelectionCountCheckBox, 8, 0); + generalGrid->addWidget(&useTearOffMenusCheckBox, 9, 0); + + generalGroupBox = new QGroupBox; + generalGroupBox->setLayout(generalGrid); + + auto *notificationsGrid = new QGridLayout; + notificationsGrid->addWidget(¬ificationsEnabledCheckBox, 0, 0); + notificationsGrid->addWidget(&specNotificationsEnabledCheckBox, 1, 0); + notificationsGrid->addWidget(&buddyConnectNotificationsEnabledCheckBox, 2, 0); + + notificationsGroupBox = new QGroupBox; + notificationsGroupBox->setLayout(notificationsGrid); + + // animation settings + tapAnimationCheckBox.setChecked(SettingsCache::instance().getTapAnimation()); + connect(&tapAnimationCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(), + &SettingsCache::setTapAnimation); + + auto *animationGrid = new QGridLayout; + animationGrid->addWidget(&tapAnimationCheckBox, 0, 0); + + animationGroupBox = new QGroupBox; + animationGroupBox->setLayout(animationGrid); + + // deck editor settings + openDeckInNewTabCheckBox.setChecked(SettingsCache::instance().getOpenDeckInNewTab()); + connect(&openDeckInNewTabCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(), + &SettingsCache::setOpenDeckInNewTab); + + visualDeckStorageInGameCheckBox.setChecked(SettingsCache::instance().getVisualDeckStorageInGame()); + connect(&visualDeckStorageInGameCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(), + &SettingsCache::setVisualDeckStorageInGame); + + visualDeckStorageSelectionAnimationCheckBox.setChecked( + SettingsCache::instance().getVisualDeckStorageSelectionAnimation()); + connect(&visualDeckStorageSelectionAnimationCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(), + &SettingsCache::setVisualDeckStorageSelectionAnimation); + + visualDeckStoragePromptForConversionSelector.addItem(""); // these will be set in retranslateUI + visualDeckStoragePromptForConversionSelector.addItem(""); + visualDeckStoragePromptForConversionSelector.addItem(""); + if (SettingsCache::instance().getVisualDeckStoragePromptForConversion()) { + visualDeckStoragePromptForConversionSelector.setCurrentIndex(visualDeckStoragePromptForConversionIndexPrompt); + } else if (SettingsCache::instance().getVisualDeckStorageAlwaysConvert()) { + visualDeckStoragePromptForConversionSelector.setCurrentIndex(visualDeckStoragePromptForConversionIndexAlways); + } else { + visualDeckStoragePromptForConversionSelector.setCurrentIndex(visualDeckStoragePromptForConversionIndexNone); + } + connect(&visualDeckStoragePromptForConversionSelector, QOverload::of(&QComboBox::currentIndexChanged), this, + [](int index) { + SettingsCache::instance().setVisualDeckStoragePromptForConversion( + index == visualDeckStoragePromptForConversionIndexPrompt); + SettingsCache::instance().setVisualDeckStorageAlwaysConvert( + index == visualDeckStoragePromptForConversionIndexAlways); + }); + + defaultDeckEditorTypeSelector.addItem(""); // these will be set in retranslateUI + defaultDeckEditorTypeSelector.addItem(""); + defaultDeckEditorTypeSelector.setCurrentIndex(SettingsCache::instance().getDefaultDeckEditorType()); + connect(&defaultDeckEditorTypeSelector, QOverload::of(&QComboBox::currentIndexChanged), + &SettingsCache::instance(), &SettingsCache::setDefaultDeckEditorType); + + auto *deckEditorGrid = new QGridLayout; + deckEditorGrid->addWidget(&openDeckInNewTabCheckBox, 0, 0); + deckEditorGrid->addWidget(&visualDeckStorageInGameCheckBox, 1, 0); + deckEditorGrid->addWidget(&visualDeckStorageSelectionAnimationCheckBox, 2, 0); + deckEditorGrid->addWidget(&visualDeckStoragePromptForConversionLabel, 3, 0); + deckEditorGrid->addWidget(&visualDeckStoragePromptForConversionSelector, 3, 1); + deckEditorGrid->addWidget(&defaultDeckEditorTypeLabel, 4, 0); + deckEditorGrid->addWidget(&defaultDeckEditorTypeSelector, 4, 1); + + deckEditorGroupBox = new QGroupBox; + deckEditorGroupBox->setLayout(deckEditorGrid); + + // replay settings + rewindBufferingMsBox.setRange(0, 9999); + rewindBufferingMsBox.setValue(SettingsCache::instance().getRewindBufferingMs()); + connect(&rewindBufferingMsBox, qOverload(&QSpinBox::valueChanged), &SettingsCache::instance(), + &SettingsCache::setRewindBufferingMs); + + auto *replayGrid = new QGridLayout; + replayGrid->addWidget(&rewindBufferingMsLabel, 0, 0, 1, 1); + replayGrid->addWidget(&rewindBufferingMsBox, 0, 1, 1, 1); + + replayGroupBox = new QGroupBox; + replayGroupBox->setLayout(replayGrid); + + // putting it all together + auto *mainLayout = new QVBoxLayout; + mainLayout->addWidget(generalGroupBox); + mainLayout->addWidget(notificationsGroupBox); + mainLayout->addWidget(animationGroupBox); + mainLayout->addWidget(deckEditorGroupBox); + mainLayout->addWidget(replayGroupBox); + mainLayout->addStretch(); + + setLayout(mainLayout); + + connect(&SettingsCache::instance(), &SettingsCache::langChanged, this, &UserInterfaceSettingsPage::retranslateUi); + retranslateUi(); +} + +void UserInterfaceSettingsPage::setNotificationEnabled(QT_STATE_CHANGED_T i) +{ + specNotificationsEnabledCheckBox.setEnabled(i != 0); + buddyConnectNotificationsEnabledCheckBox.setEnabled(i != 0); + if (i == 0) { + specNotificationsEnabledCheckBox.setChecked(false); + buddyConnectNotificationsEnabledCheckBox.setChecked(false); + } +} + +void UserInterfaceSettingsPage::retranslateUi() +{ + generalGroupBox->setTitle(tr("General interface settings")); + doubleClickToPlayCheckBox.setText(tr("&Double-click cards to play them (instead of single-click)")); + clickPlaysAllSelectedCheckBox.setText(tr("&Clicking plays all selected cards (instead of just the clicked card)")); + playToStackCheckBox.setText(tr("&Play all nonlands onto the stack (not the battlefield) by default")); + doNotDeleteArrowsInSubPhasesCheckBox.setText(tr("Do not delete &arrows inside of subphases")); + closeEmptyCardViewCheckBox.setText(tr("Close card view window when last card is removed")); + focusCardViewSearchBarCheckBox.setText(tr("Auto focus search bar when card view window is opened")); + annotateTokensCheckBox.setText(tr("Annotate card text on tokens")); + showDragSelectionCountCheckBox.setText(tr("Show selection counter during drag selection")); + showTotalSelectionCountCheckBox.setText(tr("Show total selection counter")); + useTearOffMenusCheckBox.setText(tr("Use tear-off menus, allowing right click menus to persist on screen")); + notificationsGroupBox->setTitle(tr("Notifications settings")); + notificationsEnabledCheckBox.setText(tr("Enable notifications in taskbar")); + specNotificationsEnabledCheckBox.setText(tr("Notify in the taskbar for game events while you are spectating")); + buddyConnectNotificationsEnabledCheckBox.setText(tr("Notify in the taskbar when users in your buddy list connect")); + animationGroupBox->setTitle(tr("Animation settings")); + tapAnimationCheckBox.setText(tr("&Tap/untap animation")); + deckEditorGroupBox->setTitle(tr("Deck editor/storage settings")); + openDeckInNewTabCheckBox.setText(tr("Open deck in new tab by default")); + visualDeckStorageInGameCheckBox.setText(tr("Use visual deck storage in game lobby")); + visualDeckStorageSelectionAnimationCheckBox.setText(tr("Use selection animation for Visual Deck Storage")); + visualDeckStoragePromptForConversionLabel.setText( + tr("When adding a tag in the visual deck storage to a .txt deck:")); + visualDeckStoragePromptForConversionSelector.setItemText(visualDeckStoragePromptForConversionIndexNone, + tr("do nothing")); + visualDeckStoragePromptForConversionSelector.setItemText(visualDeckStoragePromptForConversionIndexPrompt, + tr("ask to convert to .cod")); + visualDeckStoragePromptForConversionSelector.setItemText(visualDeckStoragePromptForConversionIndexAlways, + tr("always convert to .cod")); + defaultDeckEditorTypeLabel.setText(tr("Default deck editor type")); + defaultDeckEditorTypeSelector.setItemText(TabSupervisor::ClassicDeckEditor, tr("Classic Deck Editor")); + defaultDeckEditorTypeSelector.setItemText(TabSupervisor::VisualDeckEditor, tr("Visual Deck Editor")); + replayGroupBox->setTitle(tr("Replay settings")); + rewindBufferingMsLabel.setText(tr("Buffer time for backwards skip via shortcut:")); + rewindBufferingMsBox.setSuffix(" ms"); +} \ No newline at end of file diff --git a/cockatrice/src/interface/widgets/settings_page/user_interface_settings_page.h b/cockatrice/src/interface/widgets/settings_page/user_interface_settings_page.h new file mode 100644 index 000000000..6dd43ceae --- /dev/null +++ b/cockatrice/src/interface/widgets/settings_page/user_interface_settings_page.h @@ -0,0 +1,54 @@ +#ifndef COCKATRICE_USER_INTERFACE_SETTINGS_PAGE_H +#define COCKATRICE_USER_INTERFACE_SETTINGS_PAGE_H + +#include "abstract_settings_page.h" + +#include +#include +#include +#include +#include +#include + +class UserInterfaceSettingsPage : public AbstractSettingsPage +{ + Q_OBJECT +private slots: + void setNotificationEnabled(QT_STATE_CHANGED_T); + +private: + QCheckBox notificationsEnabledCheckBox; + QCheckBox specNotificationsEnabledCheckBox; + QCheckBox buddyConnectNotificationsEnabledCheckBox; + QCheckBox doubleClickToPlayCheckBox; + QCheckBox clickPlaysAllSelectedCheckBox; + QCheckBox playToStackCheckBox; + QCheckBox doNotDeleteArrowsInSubPhasesCheckBox; + QCheckBox closeEmptyCardViewCheckBox; + QCheckBox focusCardViewSearchBarCheckBox; + QCheckBox annotateTokensCheckBox; + QCheckBox showDragSelectionCountCheckBox; + QCheckBox showTotalSelectionCountCheckBox; + QCheckBox useTearOffMenusCheckBox; + QCheckBox tapAnimationCheckBox; + QCheckBox openDeckInNewTabCheckBox; + QLabel visualDeckStoragePromptForConversionLabel; + QComboBox visualDeckStoragePromptForConversionSelector; + QCheckBox visualDeckStorageInGameCheckBox; + QCheckBox visualDeckStorageSelectionAnimationCheckBox; + QLabel defaultDeckEditorTypeLabel; + QComboBox defaultDeckEditorTypeSelector; + QLabel rewindBufferingMsLabel; + QSpinBox rewindBufferingMsBox; + QGroupBox *generalGroupBox; + QGroupBox *notificationsGroupBox; + QGroupBox *animationGroupBox; + QGroupBox *deckEditorGroupBox; + QGroupBox *replayGroupBox; + +public: + UserInterfaceSettingsPage(); + void retranslateUi() override; +}; + +#endif // COCKATRICE_USER_INTERFACE_SETTINGS_PAGE_H From 7a5b2e9f0e98cddebae9bdf7c7c0c2462c998bc1 Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Mon, 18 May 2026 20:21:57 +0200 Subject: [PATCH 19/51] [Game] Move state fields out of CardItem (#6904) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [Game] Move state fields out of CardItem Took 1 hour 2 minutes * Move stuff into .cpp Took 14 minutes * Signals pass changed values as params Took 2 minutes * Comments. Took 23 minutes --------- Co-authored-by: Lukas Brübach --- cockatrice/CMakeLists.txt | 1 + cockatrice/src/game/board/card_item.cpp | 105 ++++++++++----------- cockatrice/src/game/board/card_item.h | 29 +++--- cockatrice/src/game/board/card_state.cpp | 111 +++++++++++++++++++++++ cockatrice/src/game/board/card_state.h | 103 +++++++++++++++++++++ 5 files changed, 274 insertions(+), 75 deletions(-) create mode 100644 cockatrice/src/game/board/card_state.cpp create mode 100644 cockatrice/src/game/board/card_state.h diff --git a/cockatrice/CMakeLists.txt b/cockatrice/CMakeLists.txt index 69b052a36..bac565f53 100644 --- a/cockatrice/CMakeLists.txt +++ b/cockatrice/CMakeLists.txt @@ -64,6 +64,7 @@ set(cockatrice_SOURCES src/game/board/card_drag_item.cpp src/game/board/card_item.cpp src/game/board/card_list.cpp + src/game/board/card_state.cpp src/game/board/counter_general.cpp src/game/board/translate_counter_name.cpp src/game/deckview/deck_view.cpp diff --git a/cockatrice/src/game/board/card_item.cpp b/cockatrice/src/game/board/card_item.cpp index d85937894..bd47d5bd5 100644 --- a/cockatrice/src/game/board/card_item.cpp +++ b/cockatrice/src/game/board/card_item.cpp @@ -21,13 +21,12 @@ #include CardItem::CardItem(Player *_owner, QGraphicsItem *parent, const CardRef &cardRef, int _cardid, CardZoneLogic *_zone) - : AbstractCardItem(parent, cardRef, _owner, _cardid), zone(_zone), attacking(false), destroyOnZoneChange(false), - doesntUntap(false), dragItem(nullptr), attachedTo(nullptr) + : AbstractCardItem(parent, cardRef, _owner, _cardid), state(new CardState(this, _zone)), dragItem(nullptr) { owner->addCard(this); connect(&SettingsCache::instance().cardCounters(), &CardCounterSettings::colorChanged, this, [this](int counterId) { - if (counters.contains(counterId)) { + if (state->getCounters().contains(counterId)) { update(); } }); @@ -48,9 +47,9 @@ void CardItem::prepareDelete() attachedCards.first()->setAttachedTo(nullptr); } - if (attachedTo != nullptr) { - attachedTo->removeAttachedCard(this); - attachedTo = nullptr; + if (state->getAttachedTo() != nullptr) { + state->getAttachedTo()->removeAttachedCard(this); + state->setAttachedTo(nullptr); } } @@ -65,7 +64,7 @@ void CardItem::deleteLater() void CardItem::setZone(CardZoneLogic *_zone) { - zone = _zone; + state->setZone(_zone); } void CardItem::retranslateUi() @@ -80,23 +79,23 @@ void CardItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, AbstractCardItem::paint(painter, option, widget); int i = 0; - QMapIterator counterIterator(counters); + QMapIterator counterIterator(state->getCounters()); while (counterIterator.hasNext()) { counterIterator.next(); QColor _color = cardCounterSettings.color(counterIterator.key()); - paintNumberEllipse(counterIterator.value(), 14, _color, i, counters.size(), painter); + paintNumberEllipse(counterIterator.value(), 14, _color, i, state->getCounters().size(), painter); ++i; } QSizeF translatedSize = getTranslatedSize(painter); qreal scaleFactor = translatedSize.width() / boundingRect().width(); - if (!pt.isEmpty()) { + if (!state->getPT().isEmpty()) { painter->save(); transformPainter(painter, translatedSize, tapAngle); - if (!getFaceDown() && pt == exactCard.getInfo().getPowTough()) { + if (!getFaceDown() && state->getPT() == exactCard.getInfo().getPowTough()) { painter->setPen(Qt::white); } else { painter->setPen(QColor(255, 150, 0)); // dark orange @@ -107,11 +106,11 @@ void CardItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, painter->drawText(QRectF(4 * scaleFactor, 4 * scaleFactor, translatedSize.width() - 10 * scaleFactor, translatedSize.height() - 8 * scaleFactor), - Qt::AlignRight | Qt::AlignBottom, pt); + Qt::AlignRight | Qt::AlignBottom, state->getPT()); painter->restore(); } - if (!annotation.isEmpty()) { + if (!state->getAnnotation().isEmpty()) { painter->save(); transformPainter(painter, translatedSize, tapAngle); @@ -121,7 +120,7 @@ void CardItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, painter->drawText(QRectF(4 * scaleFactor, 4 * scaleFactor, translatedSize.width() - 8 * scaleFactor, translatedSize.height() - 8 * scaleFactor), - Qt::AlignCenter | Qt::TextWrapAnywhere, annotation); + Qt::AlignCenter | Qt::TextWrapAnywhere, state->getAnnotation()); painter->restore(); } @@ -129,7 +128,7 @@ void CardItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, painter->fillPath(shape(), QBrush(QColor(255, 0, 0, 100))); } - if (doesntUntap) { + if (state->getDoesntUntap()) { painter->save(); painter->setRenderHint(QPainter::Antialiasing, false); @@ -148,70 +147,66 @@ void CardItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, void CardItem::setAttacking(bool _attacking) { - attacking = _attacking; + state->setAttacking(_attacking); update(); } void CardItem::setCounter(int _id, int _value) { - if (_value) { - counters.insert(_id, _value); - } else { - counters.remove(_id); - } + state->setCounter(_id, _value); update(); } void CardItem::setAnnotation(const QString &_annotation) { - annotation = _annotation; + state->setAnnotation(_annotation); update(); } void CardItem::setDoesntUntap(bool _doesntUntap) { - doesntUntap = _doesntUntap; + state->setDoesntUntap(_doesntUntap); update(); } void CardItem::setPT(const QString &_pt) { - pt = _pt; + state->setPT(_pt); update(); } void CardItem::setAttachedTo(CardItem *_attachedTo) { - if (attachedTo != nullptr) { - attachedTo->removeAttachedCard(this); + if (state->getAttachedTo() != nullptr) { + state->getAttachedTo()->removeAttachedCard(this); } gridPoint.setX(-1); - attachedTo = _attachedTo; - if (attachedTo != nullptr) { + state->setAttachedTo(_attachedTo); + if (state->getAttachedTo() != nullptr) { // If the zone is being torn down, it might already be null by the time a card tries to un-attach all its // attached cards - if (attachedTo->zone == nullptr) { + if (state->getAttachedTo()->getZone() == nullptr) { deleteLater(); } else { - emit attachedTo->zone->cardAdded(this); - attachedTo->addAttachedCard(this); - if (zone != attachedTo->getZone()) { - attachedTo->getZone()->reorganizeCards(); + emit state->getAttachedTo()->getZone()->cardAdded(this); + state->getAttachedTo()->addAttachedCard(this); + if (state->getZone() != state->getAttachedTo()->getZone()) { + state->getAttachedTo()->getZone()->reorganizeCards(); } } } else { // If the zone is being torn down, it might already be null by the time a card tries to un-attach all its // attached cards - if (zone == nullptr) { + if (state->getZone() == nullptr) { deleteLater(); } else { - emit zone->cardAdded(this); + emit state->getZone()->cardAdded(this); } } - if (zone != nullptr) { - zone->reorganizeCards(); + if (state->getZone() != nullptr) { + state->getZone()->reorganizeCards(); } } @@ -220,13 +215,7 @@ void CardItem::setAttachedTo(CardItem *_attachedTo) */ void CardItem::resetState(bool keepAnnotations) { - attacking = false; - counters.clear(); - pt.clear(); - if (!keepAnnotations) { - annotation.clear(); - } - attachedTo = 0; + state->resetState(keepAnnotations); attachedCards.clear(); setTapped(false, false); setDoesntUntap(false); @@ -238,11 +227,11 @@ void CardItem::resetState(bool keepAnnotations) void CardItem::processCardInfo(const ServerInfo_Card &_info) { - counters.clear(); + state->clearCounters(); const int counterListSize = _info.counter_list_size(); for (int i = 0; i < counterListSize; ++i) { const ServerInfo_CardCounter &counterInfo = _info.counter_list(i); - counters.insert(counterInfo.id(), counterInfo.value()); + state->insertCounter(counterInfo.id(), counterInfo.value()); } setId(_info.id()); @@ -299,7 +288,7 @@ void CardItem::drawArrow(const QColor &arrowColor) if (card == nullptr || card == this) { continue; } - if (card->getZone() != zone) { + if (card->getZone() != state->getZone()) { continue; } @@ -324,7 +313,7 @@ void CardItem::drawAttachArrow() if (card == nullptr) { continue; } - if (card->getZone() != zone) { + if (card->getZone() != state->getZone()) { continue; } @@ -357,7 +346,7 @@ void CardItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) 2 * QApplication::startDragDistance()) { return; } - if (const ZoneViewZoneLogic *view = qobject_cast(zone)) { + if (const ZoneViewZoneLogic *view = qobject_cast(state->getZone())) { if (view->getRevealZone() && !view->getWriteableRevealZone()) { return; } @@ -375,12 +364,12 @@ void CardItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) int childIndex = 0; for (const auto &item : scene()->selectedItems()) { CardItem *card = static_cast(item); - if ((card == this) || (card->getZone() != zone)) { + if ((card == this) || (card->getZone() != state->getZone())) { continue; } ++childIndex; QPointF childPos; - if (zone->getHasCardAttr()) { + if (state->getZone()->getHasCardAttr()) { childPos = card->pos() - pos(); } else { childPos = QPointF(childIndex * CardDimensions::WIDTH_HALF_F, 0); @@ -401,15 +390,15 @@ void CardItem::playCard(bool faceDown) return; } - TableZoneLogic *tz = qobject_cast(zone); + TableZoneLogic *tz = qobject_cast(state->getZone()); if (tz) { emit tz->toggleTapped(); } else { if (SettingsCache::instance().getClickPlaysAllSelected()) { - faceDown ? zone->getPlayer()->getPlayerActions()->actPlayFacedown() - : zone->getPlayer()->getPlayerActions()->actPlay(); + faceDown ? state->getZone()->getPlayer()->getPlayerActions()->actPlayFacedown() + : state->getZone()->getPlayer()->getPlayerActions()->actPlay(); } else { - zone->getPlayer()->getPlayerActions()->playCard(this, faceDown); + state->getZone()->getPlayer()->getPlayerActions()->playCard(this, faceDown); } } } @@ -465,11 +454,11 @@ static bool isUnwritableRevealZone(CardZoneLogic *zone) */ void CardItem::handleClickedToPlay(bool shiftHeld) { - if (isUnwritableRevealZone(zone)) { + if (isUnwritableRevealZone(state->getZone())) { if (SettingsCache::instance().getClickPlaysAllSelected()) { - zone->getPlayer()->getPlayerActions()->actHide(); + state->getZone()->getPlayer()->getPlayerActions()->actHide(); } else { - zone->removeCard(this); + state->getZone()->removeCard(this); } } else { playCard(shiftHeld); diff --git a/cockatrice/src/game/board/card_item.h b/cockatrice/src/game/board/card_item.h index c0dd03d3d..aa29ec014 100644 --- a/cockatrice/src/game/board/card_item.h +++ b/cockatrice/src/game/board/card_item.h @@ -9,6 +9,7 @@ #include "../zones/card_zone_logic.h" #include "abstract_card_item.h" +#include "card_state.h" #include @@ -27,16 +28,10 @@ class CardItem : public AbstractCardItem { Q_OBJECT private: - CardZoneLogic *zone; - bool attacking; - QMap counters; - QString annotation; - QString pt; - bool destroyOnZoneChange; - bool doesntUntap; + CardState *state; + QPoint gridPoint; CardDragItem *dragItem; - CardItem *attachedTo; QList attachedCards; void prepareDelete(); @@ -62,7 +57,7 @@ public: void retranslateUi(); [[nodiscard]] CardZoneLogic *getZone() const { - return zone; + return state->getZone(); } void setZone(CardZoneLogic *_zone); void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override; @@ -88,40 +83,40 @@ public: } [[nodiscard]] bool getAttacking() const { - return attacking; + return state->getAttacking(); } void setAttacking(bool _attacking); [[nodiscard]] const QMap &getCounters() const { - return counters; + return state->getCounters(); } void setCounter(int _id, int _value); [[nodiscard]] QString getAnnotation() const { - return annotation; + return state->getAnnotation(); } void setAnnotation(const QString &_annotation); [[nodiscard]] bool getDoesntUntap() const { - return doesntUntap; + return state->getDoesntUntap(); } void setDoesntUntap(bool _doesntUntap); [[nodiscard]] QString getPT() const { - return pt; + return state->getPT(); } void setPT(const QString &_pt); [[nodiscard]] bool getDestroyOnZoneChange() const { - return destroyOnZoneChange; + return state->getDestroyOnZoneChange(); } void setDestroyOnZoneChange(bool _destroy) { - destroyOnZoneChange = _destroy; + state->setDestroyOnZoneChange(_destroy); } [[nodiscard]] CardItem *getAttachedTo() const { - return attachedTo; + return state->getAttachedTo(); } void setAttachedTo(CardItem *_attachedTo); void addAttachedCard(CardItem *card) diff --git a/cockatrice/src/game/board/card_state.cpp b/cockatrice/src/game/board/card_state.cpp new file mode 100644 index 000000000..fe1aa9b73 --- /dev/null +++ b/cockatrice/src/game/board/card_state.cpp @@ -0,0 +1,111 @@ +#include "card_state.h" + +void CardState::resetState(bool keepAnnotations) +{ + attacking = false; + counters.clear(); + pt.clear(); + if (!keepAnnotations) { + annotation.clear(); + } + attachedTo = nullptr; +} + +void CardState::setZone(CardZoneLogic *_zone) +{ + if (zone == _zone) { + return; + } + + zone = _zone; + emit zoneChanged(zone); + emit stateChanged(); +} + +void CardState::setAttacking(bool _attacking) +{ + if (attacking == _attacking) { + return; + } + attacking = _attacking; + emit attackingChanged(_attacking); + emit stateChanged(); +} + +void CardState::insertCounter(int id, int value) +{ + counters.insert(id, value); + + emit countersChanged(counters); + emit stateChanged(); +} + +void CardState::setCounter(int id, int value) +{ + if (value) { + counters[id] = value; + } else { + counters.remove(id); + } + + emit countersChanged(counters); + emit stateChanged(); +} + +void CardState::clearCounters() +{ + counters.clear(); + emit countersChanged(counters); + emit stateChanged(); +} + +void CardState::setAnnotation(const QString &_annotation) +{ + if (annotation == _annotation) { + return; + } + annotation = _annotation; + emit annotationChanged(annotation); + emit stateChanged(); +} + +void CardState::setPT(const QString &_pt) +{ + if (pt == _pt) { + return; + } + pt = _pt; + emit ptChanged(pt); + emit stateChanged(); +} + +void CardState::setDoesntUntap(bool _doesntUntap) +{ + if (doesntUntap == _doesntUntap) { + return; + } + doesntUntap = _doesntUntap; + emit doesntUntapChanged(_doesntUntap); + emit stateChanged(); +} + +void CardState::setDestroyOnZoneChange(bool _destroyOnZoneChange) +{ + if (destroyOnZoneChange == _destroyOnZoneChange) { + return; + } + + destroyOnZoneChange = _destroyOnZoneChange; + emit destroyOnZoneChangeChanged(_destroyOnZoneChange); + emit stateChanged(); +} + +void CardState::setAttachedTo(CardItem *_attachedTo) +{ + if (attachedTo == _attachedTo) { + return; + } + attachedTo = _attachedTo; + emit attachedToChanged(_attachedTo); + emit stateChanged(); +} \ No newline at end of file diff --git a/cockatrice/src/game/board/card_state.h b/cockatrice/src/game/board/card_state.h new file mode 100644 index 000000000..ef17f408c --- /dev/null +++ b/cockatrice/src/game/board/card_state.h @@ -0,0 +1,103 @@ +#ifndef COCKATRICE_CARD_STATE_H +#define COCKATRICE_CARD_STATE_H + +#include +#include + +class CardZoneLogic; +class CardItem; +class CardState : public QObject +{ + Q_OBJECT + +private: + bool attacking = false; + QMap counters; + QString annotation; + QString pt; + bool doesntUntap = false; + bool destroyOnZoneChange = false; + + CardItem *attachedTo = nullptr; + CardZoneLogic *zone = nullptr; + +signals: + void stateChanged(); + + void attackingChanged(bool newValue); + void countersChanged(const QMap &newCounters); + void annotationChanged(const QString &newAnnotation); + void ptChanged(const QString &newPt); + void doesntUntapChanged(bool newValue); + void destroyOnZoneChangeChanged(bool newValue); + void attachedToChanged(CardItem *newAttachedTo); + void zoneChanged(CardZoneLogic *newZone); + +public: + explicit CardState(QObject *parent, CardZoneLogic *_zone) : QObject(parent), zone(_zone) + { + } + + void resetState(bool keepAnnotations); + + CardZoneLogic *getZone() const + { + return zone; + } + + void setZone(CardZoneLogic *_zone); + + bool getAttacking() const + { + return attacking; + } + void setAttacking(bool _attacking); + + const QMap &getCounters() const + { + return counters; + } + + void insertCounter(int id, int value); + + void setCounter(int id, int value); + + void clearCounters(); + + QString getAnnotation() const + { + return annotation; + } + + void setAnnotation(const QString &_annotation); + + QString getPT() const + { + return pt; + } + + void setPT(const QString &_pt); + + bool getDoesntUntap() const + { + return doesntUntap; + } + + void setDoesntUntap(bool _doesntUntap); + + bool getDestroyOnZoneChange() const + { + return destroyOnZoneChange; + } + + void setDestroyOnZoneChange(bool _destroyOnZoneChange); + + CardItem *getAttachedTo() const + { + return attachedTo; + } + + void setAttachedTo(CardItem *_attachedTo); +}; + +#endif // COCKATRICE_CARD_STATE_H From af2f8882935fc2576e3c31f467b7404fd0510718 Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Tue, 19 May 2026 12:10:19 +0200 Subject: [PATCH 20/51] [Player] Pull handVisible out of player_info and let graphics_item just determine this on its own. (#6911) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Took 12 minutes Took 15 seconds Co-authored-by: Lukas Brübach --- .../src/game/player/player_graphics_item.cpp | 15 +++++++-------- cockatrice/src/game/player/player_graphics_item.h | 1 + cockatrice/src/game/player/player_info.cpp | 2 +- cockatrice/src/game/player/player_info.h | 11 ----------- 4 files changed, 9 insertions(+), 20 deletions(-) diff --git a/cockatrice/src/game/player/player_graphics_item.cpp b/cockatrice/src/game/player/player_graphics_item.cpp index a4f515274..52aa231db 100644 --- a/cockatrice/src/game/player/player_graphics_item.cpp +++ b/cockatrice/src/game/player/player_graphics_item.cpp @@ -158,11 +158,11 @@ void PlayerGraphicsItem::rearrangeZones() if (SettingsCache::instance().getHorizontalHand()) { if (mirrored) { if (player->getHandZone()->contentsKnown()) { - player->getPlayerInfo()->setHandVisible(true); + handVisible = true; handZoneGraphicsItem->setPos(base); base += QPointF(0, handZoneGraphicsItem->boundingRect().height()); } else { - player->getPlayerInfo()->setHandVisible(false); + handVisible = false; } stackZoneGraphicsItem->setPos(base); @@ -176,16 +176,16 @@ void PlayerGraphicsItem::rearrangeZones() base += QPointF(0, tableZoneGraphicsItem->boundingRect().height()); if (player->getHandZone()->contentsKnown()) { - player->getPlayerInfo()->setHandVisible(true); + handVisible = true; handZoneGraphicsItem->setPos(base); } else { - player->getPlayerInfo()->setHandVisible(false); + handVisible = false; } } handZoneGraphicsItem->setWidth(tableZoneGraphicsItem->getWidth() + stackZoneGraphicsItem->boundingRect().width()); } else { - player->getPlayerInfo()->setHandVisible(true); + handVisible = true; handZoneGraphicsItem->setPos(base); base += QPointF(handZoneGraphicsItem->boundingRect().width(), 0); @@ -195,7 +195,7 @@ void PlayerGraphicsItem::rearrangeZones() tableZoneGraphicsItem->setPos(base); } - handZoneGraphicsItem->setVisible(player->getPlayerInfo()->getHandVisible()); + handZoneGraphicsItem->setVisible(handVisible); handZoneGraphicsItem->updateOrientation(); tableZoneGraphicsItem->reorganizeCards(); updateBoundingRect(); @@ -207,8 +207,7 @@ void PlayerGraphicsItem::updateBoundingRect() prepareGeometryChange(); qreal width = CardDimensions::HEIGHT_F + 15 + counterAreaWidth + stackZoneGraphicsItem->boundingRect().width(); if (SettingsCache::instance().getHorizontalHand()) { - qreal handHeight = - player->getPlayerInfo()->getHandVisible() ? handZoneGraphicsItem->boundingRect().height() : 0; + qreal handHeight = handVisible ? handZoneGraphicsItem->boundingRect().height() : 0; bRect = QRectF(0, 0, width + tableZoneGraphicsItem->boundingRect().width(), tableZoneGraphicsItem->boundingRect().height() + handHeight); } else { diff --git a/cockatrice/src/game/player/player_graphics_item.h b/cockatrice/src/game/player/player_graphics_item.h index cba664dd9..fd4c469e7 100644 --- a/cockatrice/src/game/player/player_graphics_item.h +++ b/cockatrice/src/game/player/player_graphics_item.h @@ -121,6 +121,7 @@ private: HandZone *handZoneGraphicsItem; QRectF bRect; bool mirrored; + bool handVisible = false; private slots: void updateBoundingRect(); diff --git a/cockatrice/src/game/player/player_info.cpp b/cockatrice/src/game/player/player_info.cpp index 8507f75eb..c4debde0f 100644 --- a/cockatrice/src/game/player/player_info.cpp +++ b/cockatrice/src/game/player/player_info.cpp @@ -1,7 +1,7 @@ #include "player_info.h" PlayerInfo::PlayerInfo(const ServerInfo_User &info, int _id, bool _local, bool _judge) - : id(_id), local(_local), judge(_judge), handVisible(false) + : id(_id), local(_local), judge(_judge) { userInfo = new ServerInfo_User; userInfo->CopyFrom(info); diff --git a/cockatrice/src/game/player/player_info.h b/cockatrice/src/game/player/player_info.h index 2e9b49d6d..36cb2a8bc 100644 --- a/cockatrice/src/game/player/player_info.h +++ b/cockatrice/src/game/player/player_info.h @@ -22,7 +22,6 @@ public: int id; bool local; bool judge; - bool handVisible; int getId() const { @@ -51,16 +50,6 @@ public: return judge; } - void setHandVisible(bool _handVisible) - { - handVisible = _handVisible; - } - - bool getHandVisible() const - { - return handVisible; - } - QString getName() const { return QString::fromStdString(userInfo->name()); From 9f1c225b7a6d8ca1a188ac6063c5a18274c577ca Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Tue, 19 May 2026 12:22:40 +0200 Subject: [PATCH 21/51] [Player] Stop reaching into graphics_item and emit signals instead for conceded and zoneId (#6912) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [Player] Stop reaching into graphics_item and emit signals instead for conceded and zoneId Took 7 minutes Took 3 seconds * Add sameValue check. Took 3 minutes --------- Co-authored-by: Lukas Brübach --- cockatrice/src/game/player/player.cpp | 7 ++++--- cockatrice/src/game/player/player.h | 1 + cockatrice/src/game/player/player_graphics_item.cpp | 2 ++ 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/cockatrice/src/game/player/player.cpp b/cockatrice/src/game/player/player.cpp index b1814a587..ce36af9d4 100644 --- a/cockatrice/src/game/player/player.cpp +++ b/cockatrice/src/game/player/player.cpp @@ -89,7 +89,6 @@ void Player::setConceded(bool _conceded) if (conceded != _conceded) { conceded = _conceded; - getGraphicsItem()->setVisible(!conceded); if (conceded) { clear(); } @@ -99,8 +98,10 @@ void Player::setConceded(bool _conceded) void Player::setZoneId(int _zoneId) { - zoneId = _zoneId; - graphicsItem->getPlayerArea()->setPlayerZoneId(zoneId); + if (zoneId != _zoneId) { + zoneId = _zoneId; + emit zoneIdChanged(zoneId); + } } void Player::processPlayerInfo(const ServerInfo_Player &info) diff --git a/cockatrice/src/game/player/player.h b/cockatrice/src/game/player/player.h index f9ab10207..43520b7ad 100644 --- a/cockatrice/src/game/player/player.h +++ b/cockatrice/src/game/player/player.h @@ -72,6 +72,7 @@ signals: void newCardAdded(AbstractCardItem *card); void rearrangeCounters(); void activeChanged(bool active); + void zoneIdChanged(int zoneId); void concededChanged(int playerId, bool conceded); void clearCustomZonesMenu(); void addViewCustomZoneActionToCustomZoneMenu(QString zoneName); diff --git a/cockatrice/src/game/player/player_graphics_item.cpp b/cockatrice/src/game/player/player_graphics_item.cpp index 52aa231db..c60dbcdd0 100644 --- a/cockatrice/src/game/player/player_graphics_item.cpp +++ b/cockatrice/src/game/player/player_graphics_item.cpp @@ -15,6 +15,8 @@ PlayerGraphicsItem::PlayerGraphicsItem(Player *_player) : player(_player) connect(&SettingsCache::instance(), &SettingsCache::handJustificationChanged, this, &PlayerGraphicsItem::rearrangeZones); connect(player, &Player::rearrangeCounters, this, &PlayerGraphicsItem::rearrangeCounters); + connect(player, &Player::concededChanged, this, [this](int, bool c) { setVisible(!c); }); + connect(player, &Player::zoneIdChanged, this, [this](int id) { playerArea->setPlayerZoneId(id); }); playerArea = new PlayerArea(this); From 40cef0e436ac8f44b120225f73887ba449883632 Mon Sep 17 00:00:00 2001 From: ebbit1q Date: Tue, 19 May 2026 12:25:35 +0200 Subject: [PATCH 22/51] fix resizing the visual card database loading more pages forever (#6884) * fix resizing the vde loading more pages forever * make near end of page const --- .../visual_database_display_widget.cpp | 43 ++++++++----------- .../visual_database_display_widget.h | 2 +- 2 files changed, 20 insertions(+), 25 deletions(-) diff --git a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.cpp b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.cpp index 027092990..70218d478 100644 --- a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.cpp +++ b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.cpp @@ -140,6 +140,8 @@ VisualDatabaseDisplayWidget::VisualDatabaseDisplayWidget(QWidget *parent, databaseLoadIndicator->setVisible(false); } + QScrollBar *scrollBar = flowWidget->scrollArea->verticalScrollBar(); + connect(scrollBar, &QScrollBar::valueChanged, [this](int /*value*/) { loadCurrentPage(); }); retranslateUi(); } @@ -258,9 +260,8 @@ void VisualDatabaseDisplayWidget::onSearchModelChanged() flowWidget->clearLayout(); // Clear existing cards cards->clear(); // Clear the card list // Reset scrollbar position to the top after loading new cards - if (QScrollBar *scrollBar = flowWidget->scrollArea->verticalScrollBar()) { - scrollBar->setValue(0); // Reset scrollbar to top - } + QScrollBar *scrollBar = flowWidget->scrollArea->verticalScrollBar(); + scrollBar->setValue(0); // Reset scrollbar to top currentPage = 0; loadCurrentPage(); @@ -268,6 +269,20 @@ void VisualDatabaseDisplayWidget::onSearchModelChanged() } } +bool VisualDatabaseDisplayWidget::nearEndOfPage() const +{ + if (!flowWidget->isVisible()) { + return false; + } + + QScrollBar *scrollBar = flowWidget->scrollArea->verticalScrollBar(); + if (scrollBar->value() + scrollBar->pageStep() * 2 < scrollBar->maximum()) { + return false; // there is at least two pages of space to scroll remaining + } + + return true; +} + void VisualDatabaseDisplayWidget::loadCurrentPage() { // Ensure only the initial page is loaded @@ -275,7 +290,7 @@ void VisualDatabaseDisplayWidget::loadCurrentPage() // Only load the first page initially qCDebug(VisualDatabaseDisplayLog) << "Loading the first page"; populateCards(); - } else { + } else if (nearEndOfPage()) { // If not the first page, just load the next page and append to the flow widget loadNextPage(); } @@ -354,23 +369,3 @@ void VisualDatabaseDisplayWidget::databaseDataChanged(const QModelIndex &topLeft (void)bottomRight; qCDebug(VisualDatabaseDisplayLog) << "Database Data changed"; } - -void VisualDatabaseDisplayWidget::wheelEvent(QWheelEvent *event) -{ - int totalCards = databaseDisplayModel->rowCount(); // Total number of cards - int loadedCards = currentPage * cardsPerPage; - - // Handle scrolling down - if (event->angleDelta().y() < 0) { - // Check if the next page has any cards to load - if (loadedCards < totalCards) { - loadCurrentPage(); // Load the next page - event->accept(); // Accept the event as valid - return; - } - qCDebug(VisualDatabaseDisplayLog) << loadedCards << ":" << totalCards; - } - - // Prevent overscrolling when there's no more data to load - event->ignore(); -} diff --git a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.h b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.h index 1db953b26..d4a664111 100644 --- a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.h +++ b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.h @@ -85,7 +85,6 @@ protected slots: void onHover(const ExactCard &hoveredCard); void addCard(const ExactCard &cardToAdd); void databaseDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight); - void wheelEvent(QWheelEvent *event) override; void modelDirty() const; void updateSearch(const QString &search) const; void onDisplayModeChanged(bool checked); @@ -122,6 +121,7 @@ private: int cardsPerPage = 100; // Number of cards per page void highlightAllSearchEdit(); + bool nearEndOfPage() const; protected: void resizeEvent(QResizeEvent *event) override; From 40b947c1e7de238d5d693b0a99f2c10b3ecc895f Mon Sep 17 00:00:00 2001 From: ebbit1q Date: Tue, 19 May 2026 12:26:17 +0200 Subject: [PATCH 23/51] fix cards attaching/transforming to the wrong card across players (#6909) * fix cards attaching/transforming to the wrong card across players * move comment --- cockatrice/src/game/player/player_actions.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/cockatrice/src/game/player/player_actions.cpp b/cockatrice/src/game/player/player_actions.cpp index c36cdaa1a..d5ba3b22b 100644 --- a/cockatrice/src/game/player/player_actions.cpp +++ b/cockatrice/src/game/player/player_actions.cpp @@ -1069,7 +1069,14 @@ bool PlayerActions::createRelatedFromRelation(const CardItem *sourceCard, const createCard(sourceCard, dbName, CardRelationType::DoesNotAttach, persistent); } } else { - auto attachType = cardRelation->getAttachType(); + CardRelationType attachType; + // do not attempt to attach to another player's cards, this causes the card to attempt to attach to the same + // cardid on the local player's field instead, which is an entirely different card! + if (player->getPlayerInfo()->getLocalOrJudge()) { + attachType = cardRelation->getAttachType(); + } else { + attachType = CardRelationType::DoesNotAttach; + } // move card onto table first if attaching from some other zone // we only do this for AttachTo because cross-zone TransformInto is already handled server-side From 55c84ca860f538e0ab4565aa8c4b12187f831c49 Mon Sep 17 00:00:00 2001 From: RickyRister <42636155+RickyRister@users.noreply.github.com> Date: Tue, 19 May 2026 03:32:45 -0700 Subject: [PATCH 24/51] [Settings] Clean up groupings in general settings (#6907) --- .../settings_page/general_settings_page.cpp | 110 ++++++++++++------ .../settings_page/general_settings_page.h | 9 +- 2 files changed, 79 insertions(+), 40 deletions(-) diff --git a/cockatrice/src/interface/widgets/settings_page/general_settings_page.cpp b/cockatrice/src/interface/widgets/settings_page/general_settings_page.cpp index a4d34ffb5..9faf67578 100644 --- a/cockatrice/src/interface/widgets/settings_page/general_settings_page.cpp +++ b/cockatrice/src/interface/widgets/settings_page/general_settings_page.cpp @@ -19,6 +19,7 @@ enum startupCardUpdateCheckBehaviorIndex GeneralSettingsPage::GeneralSettingsPage() { + // language settings QStringList languageCodes = findQmFiles(); for (const QString &code : languageCodes) { QString langName = languageName(code); @@ -33,10 +34,45 @@ GeneralSettingsPage::GeneralSettingsPage() languageBox.setCurrentIndex(index); } - // updates + advertiseTranslationPageLabel.setTextInteractionFlags(Qt::LinksAccessibleByMouse); + advertiseTranslationPageLabel.setOpenExternalLinks(true); + + connect(&languageBox, qOverload(&QComboBox::currentIndexChanged), this, + &GeneralSettingsPage::languageBoxChanged); + + auto *languageGrid = new QGridLayout; + languageGrid->addWidget(&languageLabel, 0, 0); + languageGrid->addWidget(&languageBox, 0, 1); + languageGrid->addWidget(&advertiseTranslationPageLabel, 1, 1, Qt::AlignRight); + + languageGroupBox = new QGroupBox; + languageGroupBox->setLayout(languageGrid); + + // version settings SettingsCache &settings = SettingsCache::instance(); startupUpdateCheckCheckBox.setChecked(settings.getCheckUpdatesOnStartup()); + connect(&startupUpdateCheckCheckBox, &QCheckBox::QT_STATE_CHANGED, &settings, + &SettingsCache::setCheckUpdatesOnStartup); + + updateNotificationCheckBox.setChecked(settings.getNotifyAboutUpdates()); + + connect(&updateNotificationCheckBox, &QCheckBox::QT_STATE_CHANGED, &settings, &SettingsCache::setNotifyAboutUpdate); + + connect(&newVersionOracleCheckBox, &QCheckBox::QT_STATE_CHANGED, &settings, + &SettingsCache::setNotifyAboutNewVersion); + + auto *versionGrid = new QGridLayout; + versionGrid->addWidget(&updateReleaseChannelLabel, 0, 0); + versionGrid->addWidget(&updateReleaseChannelBox, 0, 1); + versionGrid->addWidget(&startupUpdateCheckCheckBox, 1, 0, 1, 2); + versionGrid->addWidget(&updateNotificationCheckBox, 2, 0, 1, 2); + versionGrid->addWidget(&newVersionOracleCheckBox, 3, 0, 1, 2); + + versionGroupBox = new QGroupBox; + versionGroupBox->setLayout(versionGrid); + + // card database settings startupCardUpdateCheckBehaviorSelector.addItem(""); // these will be set in retranslateUI startupCardUpdateCheckBehaviorSelector.addItem(""); startupCardUpdateCheckBehaviorSelector.addItem(""); @@ -48,21 +84,6 @@ GeneralSettingsPage::GeneralSettingsPage() startupCardUpdateCheckBehaviorSelector.setCurrentIndex(startupCardUpdateCheckBehaviorIndexNone); } - cardUpdateCheckIntervalSpinBox.setMinimum(1); - cardUpdateCheckIntervalSpinBox.setMaximum(30); - cardUpdateCheckIntervalSpinBox.setValue(settings.getCardUpdateCheckInterval()); - updateNotificationCheckBox.setChecked(settings.getNotifyAboutUpdates()); - newVersionOracleCheckBox.setChecked(settings.getNotifyAboutNewVersion()); - - showTipsOnStartup.setChecked(settings.getShowTipsOnStartup()); - - advertiseTranslationPageLabel.setTextInteractionFlags(Qt::LinksAccessibleByMouse); - advertiseTranslationPageLabel.setOpenExternalLinks(true); - - connect(&languageBox, qOverload(&QComboBox::currentIndexChanged), this, - &GeneralSettingsPage::languageBoxChanged); - connect(&startupUpdateCheckCheckBox, &QCheckBox::QT_STATE_CHANGED, &settings, - &SettingsCache::setCheckUpdatesOnStartup); connect(&startupCardUpdateCheckBehaviorSelector, QOverload::of(&QComboBox::currentIndexChanged), this, [](int index) { SettingsCache::instance().setStartupCardUpdateCheckPromptForUpdate( @@ -70,32 +91,38 @@ GeneralSettingsPage::GeneralSettingsPage() SettingsCache::instance().setStartupCardUpdateCheckAlwaysUpdate( index == startupCardUpdateCheckBehaviorIndexAlways); }); + + cardUpdateCheckIntervalSpinBox.setMinimum(1); + cardUpdateCheckIntervalSpinBox.setMaximum(30); + cardUpdateCheckIntervalSpinBox.setValue(settings.getCardUpdateCheckInterval()); + connect(&cardUpdateCheckIntervalSpinBox, qOverload(&QSpinBox::valueChanged), &settings, &SettingsCache::setCardUpdateCheckInterval); - connect(&updateNotificationCheckBox, &QCheckBox::QT_STATE_CHANGED, &settings, &SettingsCache::setNotifyAboutUpdate); - connect(&newVersionOracleCheckBox, &QCheckBox::QT_STATE_CHANGED, &settings, - &SettingsCache::setNotifyAboutNewVersion); + + newVersionOracleCheckBox.setChecked(settings.getNotifyAboutNewVersion()); + + auto *cardDatabaseGrid = new QGridLayout; + cardDatabaseGrid->addWidget(&startupCardUpdateCheckBehaviorLabel, 0, 0); + cardDatabaseGrid->addWidget(&startupCardUpdateCheckBehaviorSelector, 0, 1); + cardDatabaseGrid->addWidget(&cardUpdateCheckIntervalLabel, 1, 0); + cardDatabaseGrid->addWidget(&cardUpdateCheckIntervalSpinBox, 1, 1); + cardDatabaseGrid->addWidget(&lastCardUpdateCheckDateLabel, 2, 1); + + cardDatabaseGroupBox = new QGroupBox; + cardDatabaseGroupBox->setLayout(cardDatabaseGrid); + + // startup settings + showTipsOnStartup.setChecked(settings.getShowTipsOnStartup()); + connect(&showTipsOnStartup, &QCheckBox::clicked, &settings, &SettingsCache::setShowTipsOnStartup); - auto *personalGrid = new QGridLayout; - personalGrid->addWidget(&languageLabel, 0, 0); - personalGrid->addWidget(&languageBox, 0, 1); - personalGrid->addWidget(&advertiseTranslationPageLabel, 1, 1, Qt::AlignRight); - personalGrid->addWidget(&updateReleaseChannelLabel, 2, 0); - personalGrid->addWidget(&updateReleaseChannelBox, 2, 1); - personalGrid->addWidget(&startupUpdateCheckCheckBox, 4, 0, 1, 2); - personalGrid->addWidget(&startupCardUpdateCheckBehaviorLabel, 5, 0); - personalGrid->addWidget(&startupCardUpdateCheckBehaviorSelector, 5, 1); - personalGrid->addWidget(&cardUpdateCheckIntervalLabel, 6, 0); - personalGrid->addWidget(&cardUpdateCheckIntervalSpinBox, 6, 1); - personalGrid->addWidget(&lastCardUpdateCheckDateLabel, 7, 1); - personalGrid->addWidget(&updateNotificationCheckBox, 8, 0, 1, 2); - personalGrid->addWidget(&newVersionOracleCheckBox, 9, 0, 1, 2); - personalGrid->addWidget(&showTipsOnStartup, 10, 0, 1, 2); + auto *startupGrid = new QGridLayout; + startupGrid->addWidget(&showTipsOnStartup, 0, 0, 1, 2); - personalGroupBox = new QGroupBox; - personalGroupBox->setLayout(personalGrid); + startupGroupBox = new QGroupBox; + startupGroupBox->setLayout(startupGrid); + // paths settings deckPathEdit = new QLineEdit(settings.getDeckPath()); deckPathEdit->setReadOnly(true); auto *deckPathButton = new QPushButton("..."); @@ -187,7 +214,10 @@ GeneralSettingsPage::GeneralSettingsPage() pathsGroupBox->setLayout(pathsGrid); auto *mainLayout = new QVBoxLayout; - mainLayout->addWidget(personalGroupBox); + mainLayout->addWidget(languageGroupBox); + mainLayout->addWidget(versionGroupBox); + mainLayout->addWidget(cardDatabaseGroupBox); + mainLayout->addWidget(startupGroupBox); mainLayout->addWidget(pathsGroupBox); mainLayout->addStretch(); @@ -323,9 +353,13 @@ void GeneralSettingsPage::languageBoxChanged(int index) void GeneralSettingsPage::retranslateUi() { - personalGroupBox->setTitle(tr("Personal settings")); + languageGroupBox->setTitle(tr("Language settings")); languageLabel.setText(tr("Language:")); + versionGroupBox->setTitle(tr("Version settings")); + cardDatabaseGroupBox->setTitle(tr("Card database")); + startupGroupBox->setTitle(tr("Startup settings")); + if (SettingsCache::instance().getIsPortableBuild()) { pathsGroupBox->setTitle(tr("Paths (editing disabled in portable mode)")); } else { diff --git a/cockatrice/src/interface/widgets/settings_page/general_settings_page.h b/cockatrice/src/interface/widgets/settings_page/general_settings_page.h index 0d3c03804..8aa39ff65 100644 --- a/cockatrice/src/interface/widgets/settings_page/general_settings_page.h +++ b/cockatrice/src/interface/widgets/settings_page/general_settings_page.h @@ -34,6 +34,13 @@ private slots: private: QStringList findQmFiles(); QString languageName(const QString &lang); + + QGroupBox *languageGroupBox; + QGroupBox *versionGroupBox; + QGroupBox *cardDatabaseGroupBox; + QGroupBox *startupGroupBox; + QGroupBox *pathsGroupBox; + QLineEdit *deckPathEdit; QLineEdit *filtersPathEdit; QLineEdit *replaysPathEdit; @@ -43,8 +50,6 @@ private: QLineEdit *tokenDatabasePathEdit; QPushButton *resetAllPathsButton; QLabel *allPathsResetLabel; - QGroupBox *personalGroupBox; - QGroupBox *pathsGroupBox; QComboBox languageBox; QCheckBox startupUpdateCheckCheckBox; QLabel startupCardUpdateCheckBehaviorLabel; From fe31a49f86f75f40fea358e681462f09570a2f92 Mon Sep 17 00:00:00 2001 From: RickyRister <42636155+RickyRister@users.noreply.github.com> Date: Tue, 19 May 2026 03:33:25 -0700 Subject: [PATCH 25/51] [Settings] Split appearance home tab settings into own group (#6905) --- .../appearance_settings_page.cpp | 41 +++++++++++-------- .../settings_page/appearance_settings_page.h | 2 +- 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/cockatrice/src/interface/widgets/settings_page/appearance_settings_page.cpp b/cockatrice/src/interface/widgets/settings_page/appearance_settings_page.cpp index f6740f472..9a5b45e5a 100644 --- a/cockatrice/src/interface/widgets/settings_page/appearance_settings_page.cpp +++ b/cockatrice/src/interface/widgets/settings_page/appearance_settings_page.cpp @@ -60,6 +60,18 @@ AppearanceSettingsPage::AppearanceSettingsPage() connect(&editPaletteButton, &QPushButton::clicked, this, &AppearanceSettingsPage::editPalette); + auto *themeGrid = new QGridLayout; + themeGrid->addWidget(&themeLabel, 0, 0); + themeGrid->addWidget(&themeBox, 0, 1); + themeGrid->addWidget(&openThemeButton, 1, 1); + themeGrid->addWidget(&schemeComboLabel, 2, 0); + themeGrid->addWidget(&schemeCombo, 2, 1); + themeGrid->addWidget(&editPaletteButton, 3, 1); + + themeGroupBox = new QGroupBox; + themeGroupBox->setLayout(themeGrid); + + // Home tab settings for (const auto &entry : BackgroundSources::all()) { homeTabBackgroundSourceBox.addItem(QObject::tr(entry.trKey), QVariant::fromValue(entry.type)); } @@ -89,22 +101,15 @@ AppearanceSettingsPage::AppearanceSettingsPage() updateHomeTabSettingsVisibility(); - auto *themeGrid = new QGridLayout; - themeGrid->addWidget(&themeLabel, 0, 0); - themeGrid->addWidget(&themeBox, 0, 1); - themeGrid->addWidget(&openThemeButton, 1, 1); - themeGrid->addWidget(&schemeComboLabel, 2, 0); - themeGrid->addWidget(&schemeCombo, 2, 1); - themeGrid->addWidget(&editPaletteButton, 3, 1); - themeGrid->addWidget(&homeTabBackgroundSourceLabel, 4, 0); - themeGrid->addWidget(&homeTabBackgroundSourceBox, 4, 1); - themeGrid->addWidget(&homeTabBackgroundShuffleFrequencyLabel, 5, 0); - themeGrid->addWidget(&homeTabBackgroundShuffleFrequencySpinBox, 5, 1); - themeGrid->addWidget(&homeTabDisplayCardNameLabel, 6, 0); - themeGrid->addWidget(&homeTabDisplayCardNameCheckBox, 6, 1); + auto *homeTabGrid = new QGridLayout; + homeTabGrid->addWidget(&homeTabBackgroundSourceLabel, 0, 0); + homeTabGrid->addWidget(&homeTabBackgroundSourceBox, 0, 1); + homeTabGrid->addWidget(&homeTabBackgroundShuffleFrequencyLabel, 1, 0); + homeTabGrid->addWidget(&homeTabBackgroundShuffleFrequencySpinBox, 1, 1); + homeTabGrid->addWidget(&homeTabDisplayCardNameCheckBox, 2, 0, 1, 2); - themeGroupBox = new QGroupBox; - themeGroupBox->setLayout(themeGrid); + homeTabGroupBox = new QGroupBox; + homeTabGroupBox->setLayout(homeTabGrid); // Menu settings showShortcutsCheckBox.setChecked(settings.getShowShortcuts()); @@ -266,6 +271,7 @@ AppearanceSettingsPage::AppearanceSettingsPage() // putting it all together auto *mainLayout = new QVBoxLayout; mainLayout->addWidget(themeGroupBox); + mainLayout->addWidget(homeTabGroupBox); mainLayout->addWidget(menuGroupBox); mainLayout->addWidget(cardsGroupBox); mainLayout->addWidget(cardCountersGroupBox); @@ -313,7 +319,6 @@ void AppearanceSettingsPage::updateHomeTabSettingsVisibility() homeTabBackgroundShuffleFrequencyLabel.setVisible(visible); homeTabBackgroundShuffleFrequencySpinBox.setVisible(visible); - homeTabDisplayCardNameLabel.setVisible(visible); homeTabDisplayCardNameCheckBox.setVisible(visible); } @@ -372,10 +377,12 @@ void AppearanceSettingsPage::retranslateUi() openThemeButton.setText(tr("Open themes folder")); schemeComboLabel.setText(tr("Active theme palette:")); editPaletteButton.setText(tr("Edit theme palette")); + + homeTabGroupBox->setTitle(tr("Home tab settings")); homeTabBackgroundSourceLabel.setText(tr("Home tab background source:")); homeTabBackgroundShuffleFrequencyLabel.setText(tr("Home tab background shuffle frequency:")); homeTabBackgroundShuffleFrequencySpinBox.setSpecialValueText(tr("Disabled")); - homeTabDisplayCardNameLabel.setText(tr("Display card name of background in bottom right:")); + homeTabDisplayCardNameCheckBox.setText(tr("Display card name of background in bottom right")); menuGroupBox->setTitle(tr("Menu settings")); showShortcutsCheckBox.setText(tr("Show keyboard shortcuts in right-click menus")); diff --git a/cockatrice/src/interface/widgets/settings_page/appearance_settings_page.h b/cockatrice/src/interface/widgets/settings_page/appearance_settings_page.h index 116311986..f338e8477 100644 --- a/cockatrice/src/interface/widgets/settings_page/appearance_settings_page.h +++ b/cockatrice/src/interface/widgets/settings_page/appearance_settings_page.h @@ -36,7 +36,6 @@ private: QComboBox homeTabBackgroundSourceBox; QLabel homeTabBackgroundShuffleFrequencyLabel; QSpinBox homeTabBackgroundShuffleFrequencySpinBox; - QLabel homeTabDisplayCardNameLabel; QCheckBox homeTabDisplayCardNameCheckBox; QLabel minPlayersForMultiColumnLayoutLabel; QLabel maxFontSizeForCardsLabel; @@ -58,6 +57,7 @@ private: QCheckBox leftJustifiedHandCheckBox; QCheckBox invertVerticalCoordinateCheckBox; QGroupBox *themeGroupBox; + QGroupBox *homeTabGroupBox; QGroupBox *menuGroupBox; QGroupBox *cardsGroupBox; QGroupBox *handGroupBox; From 71790d8e10cb84d28ee4ea033e5cef91684a4471 Mon Sep 17 00:00:00 2001 From: RickyRister <42636155+RickyRister@users.noreply.github.com> Date: Tue, 19 May 2026 03:34:42 -0700 Subject: [PATCH 26/51] [Settings] Split printing settings into own group (#6906) --- .../appearance_settings_page.cpp | 47 +++++++++++-------- .../settings_page/appearance_settings_page.h | 5 +- 2 files changed, 31 insertions(+), 21 deletions(-) diff --git a/cockatrice/src/interface/widgets/settings_page/appearance_settings_page.cpp b/cockatrice/src/interface/widgets/settings_page/appearance_settings_page.cpp index 9a5b45e5a..29a2db1ae 100644 --- a/cockatrice/src/interface/widgets/settings_page/appearance_settings_page.cpp +++ b/cockatrice/src/interface/widgets/settings_page/appearance_settings_page.cpp @@ -126,14 +126,7 @@ AppearanceSettingsPage::AppearanceSettingsPage() menuGroupBox = new QGroupBox; menuGroupBox->setLayout(menuGrid); - // Card rendering - displayCardNamesCheckBox.setChecked(settings.getDisplayCardNames()); - connect(&displayCardNamesCheckBox, &QCheckBox::QT_STATE_CHANGED, &settings, &SettingsCache::setDisplayCardNames); - - autoRotateSidewaysLayoutCardsCheckBox.setChecked(settings.getAutoRotateSidewaysLayoutCards()); - connect(&autoRotateSidewaysLayoutCardsCheckBox, &QCheckBox::QT_STATE_CHANGED, &settings, - &SettingsCache::setAutoRotateSidewaysLayoutCards); - + // Printings settings overrideAllCardArtWithPersonalPreferenceCheckBox.setChecked(settings.getOverrideAllCardArtWithPersonalPreference()); connect(&overrideAllCardArtWithPersonalPreferenceCheckBox, &QCheckBox::QT_STATE_CHANGED, this, &AppearanceSettingsPage::overrideAllCardArtWithPersonalPreferenceToggled); @@ -142,6 +135,21 @@ AppearanceSettingsPage::AppearanceSettingsPage() connect(&bumpSetsWithCardsInDeckToTopCheckBox, &QCheckBox::QT_STATE_CHANGED, &settings, &SettingsCache::setBumpSetsWithCardsInDeckToTop); + auto *printingsGrid = new QGridLayout; + printingsGrid->addWidget(&overrideAllCardArtWithPersonalPreferenceCheckBox, 0, 0, 1, 2); + printingsGrid->addWidget(&bumpSetsWithCardsInDeckToTopCheckBox, 1, 0, 1, 2); + + printingsGroupBox = new QGroupBox; + printingsGroupBox->setLayout(printingsGrid); + + // Card rendering + displayCardNamesCheckBox.setChecked(settings.getDisplayCardNames()); + connect(&displayCardNamesCheckBox, &QCheckBox::QT_STATE_CHANGED, &settings, &SettingsCache::setDisplayCardNames); + + autoRotateSidewaysLayoutCardsCheckBox.setChecked(settings.getAutoRotateSidewaysLayoutCards()); + connect(&autoRotateSidewaysLayoutCardsCheckBox, &QCheckBox::QT_STATE_CHANGED, &settings, + &SettingsCache::setAutoRotateSidewaysLayoutCards); + cardScalingCheckBox.setChecked(settings.getScaleCards()); connect(&cardScalingCheckBox, &QCheckBox::QT_STATE_CHANGED, &settings, &SettingsCache::setCardScaling); @@ -168,14 +176,12 @@ AppearanceSettingsPage::AppearanceSettingsPage() cardsGrid->addWidget(&autoRotateSidewaysLayoutCardsCheckBox, 1, 0, 1, 2); cardsGrid->addWidget(&cardScalingCheckBox, 2, 0, 1, 2); cardsGrid->addWidget(&roundCardCornersCheckBox, 3, 0, 1, 2); - cardsGrid->addWidget(&overrideAllCardArtWithPersonalPreferenceCheckBox, 4, 0, 1, 2); - cardsGrid->addWidget(&bumpSetsWithCardsInDeckToTopCheckBox, 5, 0, 1, 2); - cardsGrid->addWidget(&verticalCardOverlapPercentLabel, 6, 0, 1, 1); - cardsGrid->addWidget(&verticalCardOverlapPercentBox, 6, 1, 1, 1); - cardsGrid->addWidget(&cardViewInitialRowsMaxLabel, 7, 0); - cardsGrid->addWidget(&cardViewInitialRowsMaxBox, 7, 1); - cardsGrid->addWidget(&cardViewExpandedRowsMaxLabel, 8, 0); - cardsGrid->addWidget(&cardViewExpandedRowsMaxBox, 8, 1); + cardsGrid->addWidget(&verticalCardOverlapPercentLabel, 4, 0, 1, 1); + cardsGrid->addWidget(&verticalCardOverlapPercentBox, 4, 1, 1, 1); + cardsGrid->addWidget(&cardViewInitialRowsMaxLabel, 5, 0); + cardsGrid->addWidget(&cardViewInitialRowsMaxBox, 5, 1); + cardsGrid->addWidget(&cardViewExpandedRowsMaxLabel, 6, 0); + cardsGrid->addWidget(&cardViewExpandedRowsMaxBox, 6, 1); cardsGroupBox = new QGroupBox; cardsGroupBox->setLayout(cardsGrid); @@ -273,6 +279,7 @@ AppearanceSettingsPage::AppearanceSettingsPage() mainLayout->addWidget(themeGroupBox); mainLayout->addWidget(homeTabGroupBox); mainLayout->addWidget(menuGroupBox); + mainLayout->addWidget(printingsGroupBox); mainLayout->addWidget(cardsGroupBox); mainLayout->addWidget(cardCountersGroupBox); mainLayout->addWidget(handGroupBox); @@ -388,13 +395,15 @@ void AppearanceSettingsPage::retranslateUi() showShortcutsCheckBox.setText(tr("Show keyboard shortcuts in right-click menus")); showGameSelectorFilterToolbarCheckBox.setText(tr("Show game filter toolbar above list in room tab")); - cardsGroupBox->setTitle(tr("Card rendering")); - displayCardNamesCheckBox.setText(tr("Display card names on cards having a picture")); - autoRotateSidewaysLayoutCardsCheckBox.setText(tr("Auto-Rotate cards with sideways layout")); + printingsGroupBox->setTitle(tr("Card printings")); overrideAllCardArtWithPersonalPreferenceCheckBox.setText( tr("Override all card art with personal set preference (Pre-ProviderID change behavior)")); bumpSetsWithCardsInDeckToTopCheckBox.setText( tr("Bump sets that the deck contains cards from to the top in the printing selector")); + + cardsGroupBox->setTitle(tr("Card rendering")); + displayCardNamesCheckBox.setText(tr("Display card names on cards having a picture")); + autoRotateSidewaysLayoutCardsCheckBox.setText(tr("Auto-Rotate cards with sideways layout")); cardScalingCheckBox.setText(tr("Scale cards on mouse over")); roundCardCornersCheckBox.setText(tr("Use rounded card corners")); verticalCardOverlapPercentLabel.setText( diff --git a/cockatrice/src/interface/widgets/settings_page/appearance_settings_page.h b/cockatrice/src/interface/widgets/settings_page/appearance_settings_page.h index f338e8477..b9958a286 100644 --- a/cockatrice/src/interface/widgets/settings_page/appearance_settings_page.h +++ b/cockatrice/src/interface/widgets/settings_page/appearance_settings_page.h @@ -41,10 +41,10 @@ private: QLabel maxFontSizeForCardsLabel; QCheckBox showShortcutsCheckBox; QCheckBox showGameSelectorFilterToolbarCheckBox; - QCheckBox displayCardNamesCheckBox; - QCheckBox autoRotateSidewaysLayoutCardsCheckBox; QCheckBox overrideAllCardArtWithPersonalPreferenceCheckBox; QCheckBox bumpSetsWithCardsInDeckToTopCheckBox; + QCheckBox displayCardNamesCheckBox; + QCheckBox autoRotateSidewaysLayoutCardsCheckBox; QCheckBox cardScalingCheckBox; QCheckBox roundCardCornersCheckBox; QLabel verticalCardOverlapPercentLabel; @@ -59,6 +59,7 @@ private: QGroupBox *themeGroupBox; QGroupBox *homeTabGroupBox; QGroupBox *menuGroupBox; + QGroupBox *printingsGroupBox; QGroupBox *cardsGroupBox; QGroupBox *handGroupBox; QGroupBox *tableGroupBox; From 5219cffa6be770fe789d9b8d4b70b812fea3ede7 Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Tue, 19 May 2026 12:36:31 +0200 Subject: [PATCH 27/51] [Player] Rename player to player logic (#6913) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Took 13 minutes Took 6 seconds Took 2 minutes Co-authored-by: Lukas Brübach --- cockatrice/CMakeLists.txt | 2 +- cockatrice/src/game/abstract_game.cpp | 4 +- .../src/game/board/abstract_card_item.cpp | 2 +- .../src/game/board/abstract_card_item.h | 4 +- .../src/game/board/abstract_counter.cpp | 4 +- cockatrice/src/game/board/abstract_counter.h | 6 +- cockatrice/src/game/board/arrow_item.cpp | 10 ++- cockatrice/src/game/board/arrow_item.h | 10 +-- cockatrice/src/game/board/arrow_target.cpp | 4 +- cockatrice/src/game/board/arrow_target.h | 8 +- cockatrice/src/game/board/card_item.cpp | 10 ++- cockatrice/src/game/board/card_item.h | 8 +- cockatrice/src/game/board/counter_general.cpp | 2 +- cockatrice/src/game/board/counter_general.h | 2 +- cockatrice/src/game/game_event_handler.cpp | 24 +++--- cockatrice/src/game/game_event_handler.h | 22 +++--- cockatrice/src/game/game_scene.cpp | 26 +++---- cockatrice/src/game/game_scene.h | 16 ++-- .../src/game/log/message_log_widget.cpp | 75 ++++++++++--------- cockatrice/src/game/log/message_log_widget.h | 72 +++++++++--------- cockatrice/src/game/phases_toolbar.h | 2 +- cockatrice/src/game/player/menu/card_menu.cpp | 8 +- cockatrice/src/game/player/menu/card_menu.h | 8 +- .../src/game/player/menu/custom_zone_menu.cpp | 8 +- .../src/game/player/menu/custom_zone_menu.h | 6 +- .../src/game/player/menu/grave_menu.cpp | 4 +- cockatrice/src/game/player/menu/grave_menu.h | 6 +- cockatrice/src/game/player/menu/hand_menu.cpp | 4 +- cockatrice/src/game/player/menu/hand_menu.h | 6 +- .../src/game/player/menu/library_menu.cpp | 8 +- .../src/game/player/menu/library_menu.h | 6 +- cockatrice/src/game/player/menu/move_menu.cpp | 4 +- cockatrice/src/game/player/menu/move_menu.h | 4 +- .../src/game/player/menu/player_menu.cpp | 2 +- cockatrice/src/game/player/menu/player_menu.h | 6 +- cockatrice/src/game/player/menu/pt_menu.cpp | 4 +- cockatrice/src/game/player/menu/pt_menu.h | 4 +- cockatrice/src/game/player/menu/rfg_menu.cpp | 4 +- cockatrice/src/game/player/menu/rfg_menu.h | 6 +- cockatrice/src/game/player/menu/say_menu.cpp | 4 +- cockatrice/src/game/player/menu/say_menu.h | 6 +- .../src/game/player/menu/sideboard_menu.cpp | 4 +- .../src/game/player/menu/sideboard_menu.h | 6 +- .../src/game/player/menu/utility_menu.cpp | 8 +- .../src/game/player/menu/utility_menu.h | 6 +- cockatrice/src/game/player/player_actions.cpp | 4 +- cockatrice/src/game/player/player_actions.h | 8 +- .../src/game/player/player_event_handler.cpp | 20 ++--- .../src/game/player/player_event_handler.h | 56 +++++++------- .../src/game/player/player_graphics_item.cpp | 8 +- .../src/game/player/player_graphics_item.h | 8 +- .../src/game/player/player_list_widget.h | 2 +- .../player/{player.cpp => player_logic.cpp} | 68 ++++++++--------- .../game/player/{player.h => player_logic.h} | 6 +- cockatrice/src/game/player/player_manager.cpp | 28 +++---- cockatrice/src/game/player/player_manager.h | 16 ++-- cockatrice/src/game/player/player_target.cpp | 6 +- cockatrice/src/game/player/player_target.h | 6 +- cockatrice/src/game/zones/card_zone_logic.cpp | 4 +- cockatrice/src/game/zones/card_zone_logic.h | 8 +- cockatrice/src/game/zones/hand_zone_logic.cpp | 2 +- cockatrice/src/game/zones/hand_zone_logic.h | 2 +- cockatrice/src/game/zones/pile_zone_logic.cpp | 2 +- cockatrice/src/game/zones/pile_zone_logic.h | 2 +- .../src/game/zones/stack_zone_logic.cpp | 2 +- cockatrice/src/game/zones/stack_zone_logic.h | 2 +- .../src/game/zones/table_zone_logic.cpp | 2 +- cockatrice/src/game/zones/table_zone_logic.h | 2 +- cockatrice/src/game/zones/view_zone_logic.cpp | 2 +- cockatrice/src/game/zones/view_zone_logic.h | 2 +- .../src/game_graphics/zones/hand_zone.cpp | 2 +- .../src/game_graphics/zones/pile_zone.cpp | 2 +- .../src/game_graphics/zones/stack_zone.cpp | 2 +- .../src/game_graphics/zones/table_zone.cpp | 2 +- .../src/game_graphics/zones/view_zone.cpp | 2 +- .../game_graphics/zones/view_zone_widget.cpp | 4 +- .../game_graphics/zones/view_zone_widget.h | 8 +- .../src/interface/widgets/tabs/tab_game.cpp | 32 ++++---- .../src/interface/widgets/tabs/tab_game.h | 16 ++-- 79 files changed, 397 insertions(+), 386 deletions(-) rename cockatrice/src/game/player/{player.cpp => player_logic.cpp} (86%) rename cockatrice/src/game/player/{player.h => player_logic.h} (97%) diff --git a/cockatrice/CMakeLists.txt b/cockatrice/CMakeLists.txt index bac565f53..389577d4f 100644 --- a/cockatrice/CMakeLists.txt +++ b/cockatrice/CMakeLists.txt @@ -95,13 +95,13 @@ set(cockatrice_SOURCES src/game/player/menu/say_menu.cpp src/game/player/menu/sideboard_menu.cpp src/game/player/menu/utility_menu.cpp - src/game/player/player.cpp src/game/player/player_actions.cpp src/game/player/player_area.cpp src/game/player/player_event_handler.cpp src/game/player/player_graphics_item.cpp src/game/player/player_info.cpp src/game/player/player_list_widget.cpp + src/game/player/player_logic.cpp src/game/player/player_manager.cpp src/game/player/player_target.cpp src/game/replay.cpp diff --git a/cockatrice/src/game/abstract_game.cpp b/cockatrice/src/game/abstract_game.cpp index 8c777d587..5b1b4bff2 100644 --- a/cockatrice/src/game/abstract_game.cpp +++ b/cockatrice/src/game/abstract_game.cpp @@ -1,7 +1,7 @@ #include "abstract_game.h" #include "../interface/widgets/tabs/tab_game.h" -#include "player/player.h" +#include "player/player_logic.h" AbstractGame::AbstractGame(TabGame *_tab) : QObject(_tab), tab(_tab) { @@ -44,7 +44,7 @@ void AbstractGame::setActiveCard(CardItem *card) CardItem *AbstractGame::getCard(int playerId, const QString &zoneName, int cardId) const { - Player *player = playerManager->getPlayer(playerId); + PlayerLogic *player = playerManager->getPlayer(playerId); if (!player) { return nullptr; } diff --git a/cockatrice/src/game/board/abstract_card_item.cpp b/cockatrice/src/game/board/abstract_card_item.cpp index d9458990b..86b3e27c8 100644 --- a/cockatrice/src/game/board/abstract_card_item.cpp +++ b/cockatrice/src/game/board/abstract_card_item.cpp @@ -13,7 +13,7 @@ #include #include -AbstractCardItem::AbstractCardItem(QGraphicsItem *parent, const CardRef &cardRef, Player *_owner, int _id) +AbstractCardItem::AbstractCardItem(QGraphicsItem *parent, const CardRef &cardRef, PlayerLogic *_owner, int _id) : ArrowTarget(_owner, parent), id(_id), cardRef(cardRef), tapped(false), facedown(false), tapAngle(0), bgColor(Qt::transparent), isHovered(false), realZValue(0) { diff --git a/cockatrice/src/game/board/abstract_card_item.h b/cockatrice/src/game/board/abstract_card_item.h index 517b5cf28..ed545e1ab 100644 --- a/cockatrice/src/game/board/abstract_card_item.h +++ b/cockatrice/src/game/board/abstract_card_item.h @@ -14,7 +14,7 @@ #include #include -class Player; +class PlayerLogic; class AbstractCardItem : public ArrowTarget { @@ -56,7 +56,7 @@ public: } explicit AbstractCardItem(QGraphicsItem *parent = nullptr, const CardRef &cardRef = {}, - Player *_owner = nullptr, + PlayerLogic *_owner = nullptr, int _id = -1); ~AbstractCardItem() override; QRectF boundingRect() const override; diff --git a/cockatrice/src/game/board/abstract_counter.cpp b/cockatrice/src/game/board/abstract_counter.cpp index ef3efb539..e0e801ab2 100644 --- a/cockatrice/src/game/board/abstract_counter.cpp +++ b/cockatrice/src/game/board/abstract_counter.cpp @@ -2,8 +2,8 @@ #include "../../client/settings/cache_settings.h" #include "../../interface/widgets/tabs/tab_game.h" -#include "../player/player.h" #include "../player/player_actions.h" +#include "../player/player_logic.h" #include "translate_counter_name.h" #include @@ -16,7 +16,7 @@ #include #include -AbstractCounter::AbstractCounter(Player *_player, +AbstractCounter::AbstractCounter(PlayerLogic *_player, int _id, const QString &_name, bool _shownInCounterArea, diff --git a/cockatrice/src/game/board/abstract_counter.h b/cockatrice/src/game/board/abstract_counter.h index 074650d54..7bc07d41f 100644 --- a/cockatrice/src/game/board/abstract_counter.h +++ b/cockatrice/src/game/board/abstract_counter.h @@ -13,7 +13,7 @@ #include #include -class Player; +class PlayerLogic; class QAction; class QKeyEvent; class QMenu; @@ -25,7 +25,7 @@ class AbstractCounter : public QObject, public QGraphicsItem, public AbstractPla Q_INTERFACES(QGraphicsItem) protected: - Player *player; + PlayerLogic *player; int id; QString name; int value; @@ -48,7 +48,7 @@ private slots: void setCounter(); public: - AbstractCounter(Player *_player, + AbstractCounter(PlayerLogic *_player, int _id, const QString &_name, bool _shownInCounterArea, diff --git a/cockatrice/src/game/board/arrow_item.cpp b/cockatrice/src/game/board/arrow_item.cpp index 498a3dfab..b9d01c40e 100644 --- a/cockatrice/src/game/board/arrow_item.cpp +++ b/cockatrice/src/game/board/arrow_item.cpp @@ -3,8 +3,8 @@ #include "../../client/settings/cache_settings.h" #include "../../game_graphics/zones/card_zone.h" -#include "../player/player.h" #include "../player/player_actions.h" +#include "../player/player_logic.h" #include "../player/player_target.h" #include "../z_values.h" #include "card_item.h" @@ -21,7 +21,11 @@ #include #include -ArrowItem::ArrowItem(Player *_player, int _id, ArrowTarget *_startItem, ArrowTarget *_targetItem, const QColor &_color) +ArrowItem::ArrowItem(PlayerLogic *_player, + int _id, + ArrowTarget *_startItem, + ArrowTarget *_targetItem, + const QColor &_color) : QGraphicsItem(), player(_player), id(_id), startItem(_startItem), targetItem(_targetItem), targetLocked(false), color(_color), fullColor(true) { @@ -160,7 +164,7 @@ void ArrowItem::mousePressEvent(QGraphicsSceneMouseEvent *event) } } -ArrowDragItem::ArrowDragItem(Player *_owner, ArrowTarget *_startItem, const QColor &_color, int _deleteInPhase) +ArrowDragItem::ArrowDragItem(PlayerLogic *_owner, ArrowTarget *_startItem, const QColor &_color, int _deleteInPhase) : ArrowItem(_owner, -1, _startItem, 0, _color), deleteInPhase(_deleteInPhase) { } diff --git a/cockatrice/src/game/board/arrow_item.h b/cockatrice/src/game/board/arrow_item.h index cb78ee066..f2de94d2f 100644 --- a/cockatrice/src/game/board/arrow_item.h +++ b/cockatrice/src/game/board/arrow_item.h @@ -12,7 +12,7 @@ class CardItem; class QGraphicsSceneMouseEvent; class QMenu; -class Player; +class PlayerLogic; class ArrowTarget; class ArrowItem : public QObject, public QGraphicsItem @@ -24,7 +24,7 @@ private: QMenu *menu; protected: - Player *player; + PlayerLogic *player; int id; ArrowTarget *startItem, *targetItem; bool targetLocked; @@ -33,7 +33,7 @@ protected: void mousePressEvent(QGraphicsSceneMouseEvent *event) override; public: - ArrowItem(Player *_player, int _id, ArrowTarget *_startItem, ArrowTarget *_targetItem, const QColor &color); + ArrowItem(PlayerLogic *_player, int _id, ArrowTarget *_startItem, ArrowTarget *_targetItem, const QColor &color); ~ArrowItem() override; void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override; [[nodiscard]] QRectF boundingRect() const override @@ -51,7 +51,7 @@ public: { return id; } - [[nodiscard]] Player *getPlayer() const + [[nodiscard]] PlayerLogic *getPlayer() const { return player; } @@ -86,7 +86,7 @@ private: QList childArrows; public: - ArrowDragItem(Player *_owner, ArrowTarget *_startItem, const QColor &_color, int _deleteInPhase); + ArrowDragItem(PlayerLogic *_owner, ArrowTarget *_startItem, const QColor &_color, int _deleteInPhase); void addChildArrow(ArrowDragItem *childArrow); protected: diff --git a/cockatrice/src/game/board/arrow_target.cpp b/cockatrice/src/game/board/arrow_target.cpp index 2c7cdfec8..bcd067bdb 100644 --- a/cockatrice/src/game/board/arrow_target.cpp +++ b/cockatrice/src/game/board/arrow_target.cpp @@ -1,9 +1,9 @@ #include "arrow_target.h" -#include "../player/player.h" +#include "../player/player_logic.h" #include "arrow_item.h" -ArrowTarget::ArrowTarget(Player *_owner, QGraphicsItem *parent) +ArrowTarget::ArrowTarget(PlayerLogic *_owner, QGraphicsItem *parent) : AbstractGraphicsItem(parent), owner(_owner), beingPointedAt(false) { setFlag(ItemSendsScenePositionChanges); diff --git a/cockatrice/src/game/board/arrow_target.h b/cockatrice/src/game/board/arrow_target.h index 55f4ef678..59ef48277 100644 --- a/cockatrice/src/game/board/arrow_target.h +++ b/cockatrice/src/game/board/arrow_target.h @@ -11,24 +11,24 @@ #include -class Player; +class PlayerLogic; class ArrowItem; class ArrowTarget : public AbstractGraphicsItem { Q_OBJECT protected: - Player *owner; + PlayerLogic *owner; private: bool beingPointedAt; QList arrowsFrom, arrowsTo; public: - explicit ArrowTarget(Player *_owner, QGraphicsItem *parent = nullptr); + explicit ArrowTarget(PlayerLogic *_owner, QGraphicsItem *parent = nullptr); ~ArrowTarget() override; - [[nodiscard]] Player *getOwner() const + [[nodiscard]] PlayerLogic *getOwner() const { return owner; } diff --git a/cockatrice/src/game/board/card_item.cpp b/cockatrice/src/game/board/card_item.cpp index bd47d5bd5..a08194540 100644 --- a/cockatrice/src/game/board/card_item.cpp +++ b/cockatrice/src/game/board/card_item.cpp @@ -6,8 +6,8 @@ #include "../../interface/widgets/tabs/tab_game.h" #include "../game_scene.h" #include "../phase.h" -#include "../player/player.h" #include "../player/player_actions.h" +#include "../player/player_logic.h" #include "../zones/view_zone_logic.h" #include "arrow_item.h" #include "card_drag_item.h" @@ -20,7 +20,11 @@ #include #include -CardItem::CardItem(Player *_owner, QGraphicsItem *parent, const CardRef &cardRef, int _cardid, CardZoneLogic *_zone) +CardItem::CardItem(PlayerLogic *_owner, + QGraphicsItem *parent, + const CardRef &cardRef, + int _cardid, + CardZoneLogic *_zone) : AbstractCardItem(parent, cardRef, _owner, _cardid), state(new CardState(this, _zone)), dragItem(nullptr) { owner->addCard(this); @@ -273,7 +277,7 @@ void CardItem::drawArrow(const QColor &arrowColor) } auto *game = owner->getGame(); - Player *arrowOwner = game->getPlayerManager()->getActiveLocalPlayer(game->getGameState()->getActivePlayer()); + PlayerLogic *arrowOwner = game->getPlayerManager()->getActiveLocalPlayer(game->getGameState()->getActivePlayer()); int phase = 0; // 0 means to not set the phase if (SettingsCache::instance().getDoNotDeleteArrowsInSubPhases()) { int currentPhase = game->getGameState()->getCurrentPhase(); diff --git a/cockatrice/src/game/board/card_item.h b/cockatrice/src/game/board/card_item.h index aa29ec014..1e99dbe2a 100644 --- a/cockatrice/src/game/board/card_item.h +++ b/cockatrice/src/game/board/card_item.h @@ -17,7 +17,7 @@ class CardDatabase; class CardDragItem; class CardZone; class ServerInfo_Card; -class Player; +class PlayerLogic; class QAction; class QColor; @@ -48,7 +48,7 @@ public: { return Type; } - explicit CardItem(Player *_owner, + explicit CardItem(PlayerLogic *_owner, QGraphicsItem *parent = nullptr, const CardRef &cardRef = {}, int _cardid = -1, @@ -73,11 +73,11 @@ public: { return gridPoint; } - [[nodiscard]] Player *getOwner() const + [[nodiscard]] PlayerLogic *getOwner() const { return owner; } - void setOwner(Player *_owner) + void setOwner(PlayerLogic *_owner) { owner = _owner; } diff --git a/cockatrice/src/game/board/counter_general.cpp b/cockatrice/src/game/board/counter_general.cpp index d68486a1b..7dd0b1f15 100644 --- a/cockatrice/src/game/board/counter_general.cpp +++ b/cockatrice/src/game/board/counter_general.cpp @@ -5,7 +5,7 @@ #include -GeneralCounter::GeneralCounter(Player *_player, +GeneralCounter::GeneralCounter(PlayerLogic *_player, int _id, const QString &_name, const QColor &_color, diff --git a/cockatrice/src/game/board/counter_general.h b/cockatrice/src/game/board/counter_general.h index 3db1d7bb4..ac008fa49 100644 --- a/cockatrice/src/game/board/counter_general.h +++ b/cockatrice/src/game/board/counter_general.h @@ -17,7 +17,7 @@ private: int radius; public: - GeneralCounter(Player *_player, + GeneralCounter(PlayerLogic *_player, int _id, const QString &_name, const QColor &_color, diff --git a/cockatrice/src/game/game_event_handler.cpp b/cockatrice/src/game/game_event_handler.cpp index 82fa2b911..b338deaea 100644 --- a/cockatrice/src/game/game_event_handler.cpp +++ b/cockatrice/src/game/game_event_handler.cpp @@ -99,7 +99,7 @@ void GameEventHandler::processGameEventContainer(const GameEventContainer &cont, if (cont.has_forced_by_judge()) { auto id = cont.forced_by_judge(); - Player *judgep = game->getPlayerManager()->getPlayers().value(id, nullptr); + PlayerLogic *judgep = game->getPlayerManager()->getPlayers().value(id, nullptr); if (judgep) { emit setContextJudgeName(judgep->getPlayerInfo()->getName()); } else if (game->getPlayerManager()->getSpectators().contains(id)) { @@ -160,7 +160,7 @@ void GameEventHandler::processGameEventContainer(const GameEventContainer &cont, break; default: { - Player *player = game->getPlayerManager()->getPlayers().value(playerId, 0); + PlayerLogic *player = game->getPlayerManager()->getPlayers().value(playerId, 0); if (!player) { qCWarning(GameEventHandlerLog) << "unhandled game event: invalid player id"; break; @@ -261,7 +261,7 @@ void GameEventHandler::eventGameStateChanged(const Event_GameStateChanged &event emit spectatorJoined(prop); } } else { - Player *player = game->getPlayerManager()->getPlayers().value(playerId, 0); + PlayerLogic *player = game->getPlayerManager()->getPlayers().value(playerId, 0); if (!player) { player = game->getPlayerManager()->addPlayer(playerId, prop.user_info()); emit playerJoined(prop); @@ -310,7 +310,7 @@ void GameEventHandler::processCardAttachmentsForPlayers(const Event_GameStateCha const ServerInfo_Player &playerInfo = event.player_list(i); const ServerInfo_PlayerProperties &prop = playerInfo.properties(); if (!prop.spectator()) { - Player *player = game->getPlayerManager()->getPlayers().value(prop.player_id(), 0); + PlayerLogic *player = game->getPlayerManager()->getPlayers().value(prop.player_id(), 0); if (!player) { continue; } @@ -323,7 +323,7 @@ void GameEventHandler::eventPlayerPropertiesChanged(const Event_PlayerProperties int eventPlayerId, const GameEventContext &context) { - Player *player = game->getPlayerManager()->getPlayers().value(eventPlayerId, 0); + PlayerLogic *player = game->getPlayerManager()->getPlayers().value(eventPlayerId, 0); if (!player) { return; } @@ -347,7 +347,7 @@ void GameEventHandler::eventPlayerPropertiesChanged(const Event_PlayerProperties case GameEventContext::CONCEDE: { player->setConceded(true); - QMapIterator playerIterator(game->getPlayerManager()->getPlayers()); + QMapIterator playerIterator(game->getPlayerManager()->getPlayers()); while (playerIterator.hasNext()) { playerIterator.next().value()->updateZones(); } @@ -359,7 +359,7 @@ void GameEventHandler::eventPlayerPropertiesChanged(const Event_PlayerProperties case GameEventContext::UNCONCEDE: { player->setConceded(false); - QMapIterator playerIterator(game->getPlayerManager()->getPlayers()); + QMapIterator playerIterator(game->getPlayerManager()->getPlayers()); while (playerIterator.hasNext()) { playerIterator.next().value()->updateZones(); } @@ -409,7 +409,7 @@ void GameEventHandler::eventJoin(const Event_Join &event, int /*eventPlayerId*/, emit logJoinSpectator(playerName); emit spectatorJoined(playerInfo); } else { - Player *newPlayer = game->getPlayerManager()->addPlayer(playerId, playerInfo.user_info()); + PlayerLogic *newPlayer = game->getPlayerManager()->addPlayer(playerId, playerInfo.user_info()); emit logJoinPlayer(newPlayer); emit playerJoined(playerInfo); } @@ -437,7 +437,7 @@ QString GameEventHandler::getLeaveReason(Event_Leave::LeaveReason reason) } void GameEventHandler::eventLeave(const Event_Leave &event, int eventPlayerId, const GameEventContext & /*context*/) { - Player *player = game->getPlayerManager()->getPlayers().value(eventPlayerId, 0); + PlayerLogic *player = game->getPlayerManager()->getPlayers().value(eventPlayerId, 0); if (!player) { return; } @@ -452,7 +452,7 @@ void GameEventHandler::eventLeave(const Event_Leave &event, int eventPlayerId, c player->deleteLater(); // Rearrange all remaining zones so that attachment relationship updates take place - QMapIterator playerIterator(game->getPlayerManager()->getPlayers()); + QMapIterator playerIterator(game->getPlayerManager()->getPlayers()); while (playerIterator.hasNext()) { playerIterator.next().value()->updateZones(); } @@ -474,7 +474,7 @@ void GameEventHandler::eventReverseTurn(const Event_ReverseTurn &event, int eventPlayerId, const GameEventContext & /*context*/) { - Player *player = game->getPlayerManager()->getPlayers().value(eventPlayerId, 0); + PlayerLogic *player = game->getPlayerManager()->getPlayers().value(eventPlayerId, 0); if (!player) { return; } @@ -505,7 +505,7 @@ void GameEventHandler::eventSetActivePlayer(const Event_SetActivePlayer &event, const GameEventContext & /*context*/) { game->getGameState()->setActivePlayer(event.active_player_id()); - Player *player = game->getPlayerManager()->getPlayer(event.active_player_id()); + PlayerLogic *player = game->getPlayerManager()->getPlayer(event.active_player_id()); if (!player) { return; } diff --git a/cockatrice/src/game/game_event_handler.h b/cockatrice/src/game/game_event_handler.h index 302e7a6ff..250f2c185 100644 --- a/cockatrice/src/game/game_event_handler.h +++ b/cockatrice/src/game/game_event_handler.h @@ -38,7 +38,7 @@ class Event_Kicked; class Event_ReverseTurn; class AbstractGame; class PendingCommand; -class Player; +class PlayerLogic; inline Q_LOGGING_CATEGORY(GameEventHandlerLog, "game_event_handler"); @@ -95,7 +95,7 @@ public slots: signals: void emitUserEvent(); void addPlayerToAutoCompleteList(QString playerName); - void localPlayerDeckSelected(Player *localPlayer, int playerId, ServerInfo_Player playerInfo); + void localPlayerDeckSelected(PlayerLogic *localPlayer, int playerId, ServerInfo_Player playerInfo); void remotePlayerDeckSelected(QString deckList, int playerId, QString playerName); void remotePlayersDecksSelected(QVector>> opponentDecks); void localPlayerSideboardLocked(int playerId, bool sideboardLocked); @@ -115,18 +115,18 @@ signals: void logSpectatorSay(ServerInfo_User userInfo, QString message); void logSpectatorLeave(QString name, QString reason); void logGameStart(); - void logReadyStart(Player *player); - void logNotReadyStart(Player *player); - void logDeckSelect(Player *player, QString deckHash, int sideboardSize); - void logSideboardLockSet(Player *player, bool sideboardLocked); - void logConnectionStateChanged(Player *player, bool connected); + void logReadyStart(PlayerLogic *player); + void logNotReadyStart(PlayerLogic *player); + void logDeckSelect(PlayerLogic *player, QString deckHash, int sideboardSize); + void logSideboardLockSet(PlayerLogic *player, bool sideboardLocked); + void logConnectionStateChanged(PlayerLogic *player, bool connected); void logJoinSpectator(QString spectatorName); - void logJoinPlayer(Player *player); - void logLeave(Player *player, QString reason); + void logJoinPlayer(PlayerLogic *player); + void logLeave(PlayerLogic *player, QString reason); void logKicked(); - void logTurnReversed(Player *player, bool reversed); + void logTurnReversed(PlayerLogic *player, bool reversed); void logGameClosed(); - void logActivePlayer(Player *activePlayer); + void logActivePlayer(PlayerLogic *activePlayer); void logActivePhaseChanged(int activePhase); void logConcede(int playerId); void logUnconcede(int playerId); diff --git a/cockatrice/src/game/game_scene.cpp b/cockatrice/src/game/game_scene.cpp index b5026ad33..91ac0adc6 100644 --- a/cockatrice/src/game/game_scene.cpp +++ b/cockatrice/src/game/game_scene.cpp @@ -6,8 +6,8 @@ #include "../game_graphics/zones/view_zone_widget.h" #include "board/card_item.h" #include "phases_toolbar.h" -#include "player/player.h" #include "player/player_graphics_item.h" +#include "player/player_logic.h" #include #include @@ -78,7 +78,7 @@ QList GameScene::selectedCards() const * * Connects to the player's sizeChanged signal to recompute layout on resize. */ -void GameScene::addPlayer(Player *player) +void GameScene::addPlayer(PlayerLogic *player) { qCInfo(GameScenePlayerAdditionRemovalLog) << "GameScene::addPlayer name=" << player->getPlayerInfo()->getName(); @@ -93,7 +93,7 @@ void GameScene::addPlayer(Player *player) * * Closes any zone views associated with the player and recomputes layout. */ -void GameScene::removePlayer(Player *player) +void GameScene::removePlayer(PlayerLogic *player) { qCInfo(GameScenePlayerAdditionRemovalLog) << "GameScene::removePlayer name=" << player->getPlayerInfo()->getName(); @@ -178,14 +178,14 @@ void GameScene::processViewSizeChange(const QSize &newSize) * * Used to determine rotation and layout order. */ -QList GameScene::collectActivePlayers(int &firstPlayerIndex) const +QList GameScene::collectActivePlayers(int &firstPlayerIndex) const { - QList activePlayers; + QList activePlayers; firstPlayerIndex = 0; bool firstPlayerFound = false; for (auto *pgItem : players) { - Player *p = pgItem->getPlayer(); + PlayerLogic *p = pgItem->getPlayer(); if (p && !p->getConceded()) { activePlayers.append(p); if (!firstPlayerFound && p->getPlayerInfo()->getLocal()) { @@ -205,9 +205,9 @@ QList GameScene::collectActivePlayers(int &firstPlayerIndex) const * * Applies rotation offset and ensures the list wraps correctly. */ -QList GameScene::rotatePlayers(const QList &activePlayers, int firstPlayerIndex) const +QList GameScene::rotatePlayers(const QList &activePlayers, int firstPlayerIndex) const { - QList rotated = activePlayers; + QList rotated = activePlayers; if (!rotated.isEmpty()) { int totalRotation = firstPlayerIndex + playerRotation; while (totalRotation < 0) { @@ -238,7 +238,7 @@ int GameScene::determineColumnCount(int playerCount) * - Position players in columns with spacing. * - Mirror graphics for visual balance. */ -QSizeF GameScene::computeSceneSizeAndPlayerLayout(const QList &playersPlaying, int columns) +QSizeF GameScene::computeSceneSizeAndPlayerLayout(const QList &playersPlaying, int columns) { playersByColumn.clear(); @@ -246,7 +246,7 @@ QSizeF GameScene::computeSceneSizeAndPlayerLayout(const QList &players qreal sceneHeight = 0, sceneWidth = -playerAreaSpacing; QList columnWidth; - QListIterator playersIter(playersPlaying); + QListIterator playersIter(playersPlaying); for (int col = 0; col < columns; ++col) { playersByColumn.append(QList()); columnWidth.append(0); @@ -254,7 +254,7 @@ QSizeF GameScene::computeSceneSizeAndPlayerLayout(const QList &players int rowsInColumn = rows - (playersPlaying.size() % columns) * col; // Adjust rows for uneven columns for (int j = 0; j < rowsInColumn; ++j) { - Player *player = playersIter.next(); + PlayerLogic *player = playersIter.next(); if (col == 0) { playersByColumn[col].prepend(player->getGraphicsItem()); } else { @@ -435,7 +435,7 @@ CardItem *GameScene::findTopmostCardInZone(const QList &items, * If an identical view exists, it is closed. Otherwise, a new ZoneViewWidget is created * and positioned based on zone type. */ -void GameScene::toggleZoneView(Player *player, const QString &zoneName, int numberCards, bool isReversed) +void GameScene::toggleZoneView(PlayerLogic *player, const QString &zoneName, int numberCards, bool isReversed) { for (auto &view : zoneViews) { ZoneViewZone *temp = view->getZone(); @@ -468,7 +468,7 @@ void GameScene::toggleZoneView(Player *player, const QString &zoneName, int numb * @param cardList List of cards to show. * @param withWritePermission Whether edits are allowed. */ -void GameScene::addRevealedZoneView(Player *player, +void GameScene::addRevealedZoneView(PlayerLogic *player, CardZoneLogic *zone, const QList &cardList, bool withWritePermission) diff --git a/cockatrice/src/game/game_scene.h b/cockatrice/src/game/game_scene.h index 0cb332ad0..a2d712609 100644 --- a/cockatrice/src/game/game_scene.h +++ b/cockatrice/src/game/game_scene.h @@ -12,7 +12,7 @@ inline Q_LOGGING_CATEGORY(GameSceneLog, "game_scene"); inline Q_LOGGING_CATEGORY(GameScenePlayerAdditionRemovalLog, "game_scene.player_addition_removal"); -class Player; +class PlayerLogic; class PlayerGraphicsItem; class ZoneViewWidget; class CardZone; @@ -83,13 +83,13 @@ public: * @brief Adds a player to the scene and stores their graphics item. * @param player Player to add. */ - void addPlayer(Player *player); + void addPlayer(PlayerLogic *player); /** * @brief Removes a player from the scene. * @param player Player to remove. */ - void removePlayer(Player *player); + void removePlayer(PlayerLogic *player); /** * @brief Adjusts the global rotation offset for player layout. @@ -111,7 +111,7 @@ public: * @param firstPlayerIndex Output index of first local player. * @return List of active players. */ - QList collectActivePlayers(int &firstPlayerIndex) const; + QList collectActivePlayers(int &firstPlayerIndex) const; /** * @brief Rotates the list of players for layout. @@ -119,7 +119,7 @@ public: * @param firstPlayerIndex Index of first local player. * @return Rotated list. */ - QList rotatePlayers(const QList &players, int firstPlayerIndex) const; + QList rotatePlayers(const QList &players, int firstPlayerIndex) const; /** * @brief Determines the number of columns to display players in. @@ -134,7 +134,7 @@ public: * @param columns Number of columns to split into. * @return Calculated scene size. */ - QSizeF computeSceneSizeAndPlayerLayout(const QList &playersPlaying, int columns); + QSizeF computeSceneSizeAndPlayerLayout(const QList &playersPlaying, int columns); /** * @brief Computes the minimum width for each column based on player minimum widths. @@ -177,10 +177,10 @@ public: public slots: /** Toggles a zone view for a player. */ - void toggleZoneView(Player *player, const QString &zoneName, int numberCards, bool isReversed = false); + void toggleZoneView(PlayerLogic *player, const QString &zoneName, int numberCards, bool isReversed = false); /** Adds a revealed zone view (for shown cards). */ - void addRevealedZoneView(Player *player, + void addRevealedZoneView(PlayerLogic *player, CardZoneLogic *zone, const QList &cardList, bool withWritePermission); diff --git a/cockatrice/src/game/log/message_log_widget.cpp b/cockatrice/src/game/log/message_log_widget.cpp index 09f6e656b..53f671256 100644 --- a/cockatrice/src/game/log/message_log_widget.cpp +++ b/cockatrice/src/game/log/message_log_widget.cpp @@ -5,7 +5,7 @@ #include "../board/card_item.h" #include "../board/translate_counter_name.h" #include "../phase.h" -#include "../player/player.h" +#include "../player/player_logic.h" #include <../../client/settings/card_counter_settings.h> #include @@ -105,7 +105,7 @@ void MessageLogWidget::containerProcessingStarted(const GameEventContext &contex } } -void MessageLogWidget::logAlwaysRevealTopCard(Player *player, CardZoneLogic *zone, bool reveal) +void MessageLogWidget::logAlwaysRevealTopCard(PlayerLogic *player, CardZoneLogic *zone, bool reveal) { appendHtmlServerMessage((reveal ? tr("%1 is now keeping the top card %2 revealed.") : tr("%1 is not revealing the top card %2 any longer.")) @@ -113,7 +113,7 @@ void MessageLogWidget::logAlwaysRevealTopCard(Player *player, CardZoneLogic *zon .arg(zone->getTranslatedName(true, CaseTopCardsOfZone))); } -void MessageLogWidget::logAlwaysLookAtTopCard(Player *player, CardZoneLogic *zone, bool reveal) +void MessageLogWidget::logAlwaysLookAtTopCard(PlayerLogic *player, CardZoneLogic *zone, bool reveal) { appendHtmlServerMessage((reveal ? tr("%1 can now look at top card %2 at any time.") : tr("%1 no longer can look at top card %2 at any time.")) @@ -121,7 +121,10 @@ void MessageLogWidget::logAlwaysLookAtTopCard(Player *player, CardZoneLogic *zon .arg(zone->getTranslatedName(true, CaseTopCardsOfZone))); } -void MessageLogWidget::logAttachCard(Player *player, QString cardName, Player *targetPlayer, QString targetCardName) +void MessageLogWidget::logAttachCard(PlayerLogic *player, + QString cardName, + PlayerLogic *targetPlayer, + QString targetCardName) { appendHtmlServerMessage(tr("%1 attaches %2 to %3's %4.") .arg(sanitizeHtml(player->getPlayerInfo()->getName())) @@ -148,7 +151,7 @@ void MessageLogWidget::logUnconcede(int playerId) true); } -void MessageLogWidget::logConnectionStateChanged(Player *player, bool connectionState) +void MessageLogWidget::logConnectionStateChanged(PlayerLogic *player, bool connectionState) { if (connectionState) { soundEngine->playSound("player_reconnect"); @@ -161,10 +164,10 @@ void MessageLogWidget::logConnectionStateChanged(Player *player, bool connection } } -void MessageLogWidget::logCreateArrow(Player *player, - Player *startPlayer, +void MessageLogWidget::logCreateArrow(PlayerLogic *player, + PlayerLogic *startPlayer, QString startCard, - Player *targetPlayer, + PlayerLogic *targetPlayer, QString targetCard, bool playerTarget) { @@ -220,7 +223,7 @@ void MessageLogWidget::logCreateArrow(Player *player, } } -void MessageLogWidget::logCreateToken(Player *player, QString cardName, QString pt, bool faceDown) +void MessageLogWidget::logCreateToken(PlayerLogic *player, QString cardName, QString pt, bool faceDown) { if (faceDown) { appendHtmlServerMessage( @@ -233,7 +236,7 @@ void MessageLogWidget::logCreateToken(Player *player, QString cardName, QString } } -void MessageLogWidget::logDeckSelect(Player *player, QString deckHash, int sideboardSize) +void MessageLogWidget::logDeckSelect(PlayerLogic *player, QString deckHash, int sideboardSize) { if (sideboardSize < 0) { appendHtmlServerMessage( @@ -246,13 +249,13 @@ void MessageLogWidget::logDeckSelect(Player *player, QString deckHash, int sideb } } -void MessageLogWidget::logDestroyCard(Player *player, QString cardName) +void MessageLogWidget::logDestroyCard(PlayerLogic *player, QString cardName) { appendHtmlServerMessage( tr("%1 destroys %2.").arg(sanitizeHtml(player->getPlayerInfo()->getName())).arg(cardLink(std::move(cardName)))); } -void MessageLogWidget::logMoveCard(Player *player, +void MessageLogWidget::logMoveCard(PlayerLogic *player, CardItem *card, CardZoneLogic *startZone, int oldX, @@ -359,7 +362,7 @@ void MessageLogWidget::logMoveCard(Player *player, appendHtmlServerMessage(message); } -void MessageLogWidget::logDrawCards(Player *player, int number, bool deckIsEmpty) +void MessageLogWidget::logDrawCards(PlayerLogic *player, int number, bool deckIsEmpty) { soundEngine->playSound("draw_card"); if (currentContext == MessageContext_Mulligan) { @@ -376,7 +379,7 @@ void MessageLogWidget::logDrawCards(Player *player, int number, bool deckIsEmpty } } -void MessageLogWidget::logDumpZone(Player *player, CardZoneLogic *zone, int numberCards, bool isReversed) +void MessageLogWidget::logDumpZone(PlayerLogic *player, CardZoneLogic *zone, int numberCards, bool isReversed) { if (numberCards == -1) { appendHtmlServerMessage(tr("%1 is looking at %2.") @@ -392,7 +395,7 @@ void MessageLogWidget::logDumpZone(Player *player, CardZoneLogic *zone, int numb } } -void MessageLogWidget::logFlipCard(Player *player, QString cardName, bool faceDown) +void MessageLogWidget::logFlipCard(PlayerLogic *player, QString cardName, bool faceDown) { if (faceDown) { appendHtmlServerMessage( @@ -418,7 +421,7 @@ void MessageLogWidget::logGameFlooded() appendMessage(tr("You are flooding the game. Please wait a couple of seconds.")); } -void MessageLogWidget::logJoin(Player *player) +void MessageLogWidget::logJoin(PlayerLogic *player) { soundEngine->playSound("player_join"); appendHtmlServerMessage(tr("%1 has joined the game.").arg(sanitizeHtml(player->getPlayerInfo()->getName()))); @@ -435,7 +438,7 @@ void MessageLogWidget::logKicked() appendHtmlServerMessage(tr("You have been kicked out of the game."), true); } -void MessageLogWidget::logLeave(Player *player, QString reason) +void MessageLogWidget::logLeave(PlayerLogic *player, QString reason) { soundEngine->playSound("player_leave"); appendHtmlServerMessage(tr("%1 has left the game (%2).") @@ -450,13 +453,13 @@ void MessageLogWidget::logLeaveSpectator(QString name, QString reason) .arg(sanitizeHtml(std::move(name)), sanitizeHtml(std::move(reason)))); } -void MessageLogWidget::logNotReadyStart(Player *player) +void MessageLogWidget::logNotReadyStart(PlayerLogic *player) { appendHtmlServerMessage( tr("%1 is not ready to start the game any more.").arg(sanitizeHtml(player->getPlayerInfo()->getName()))); } -void MessageLogWidget::logMulligan(Player *player, int number) +void MessageLogWidget::logMulligan(PlayerLogic *player, int number) { if (!player) { return; @@ -476,16 +479,16 @@ void MessageLogWidget::logReplayStarted(int gameId) appendHtmlServerMessage(tr("You are watching a replay of game #%1.").arg(gameId)); } -void MessageLogWidget::logReadyStart(Player *player) +void MessageLogWidget::logReadyStart(PlayerLogic *player) { appendHtmlServerMessage(tr("%1 is ready to start the game.").arg(sanitizeHtml(player->getPlayerInfo()->getName()))); } -void MessageLogWidget::logRevealCards(Player *player, +void MessageLogWidget::logRevealCards(PlayerLogic *player, CardZoneLogic *zone, int cardId, QString cardName, - Player *otherPlayer, + PlayerLogic *otherPlayer, bool faceDown, int amount, bool isLentToAnotherPlayer) @@ -568,14 +571,14 @@ void MessageLogWidget::logRevealCards(Player *player, } } -void MessageLogWidget::logReverseTurn(Player *player, bool reversed) +void MessageLogWidget::logReverseTurn(PlayerLogic *player, bool reversed) { appendHtmlServerMessage(tr("%1 reversed turn order, now it's %2.") .arg(sanitizeHtml(player->getPlayerInfo()->getName())) .arg(reversed ? tr("reversed") : tr("normal"))); } -void MessageLogWidget::logRollDie(Player *player, int sides, const QList &rolls) +void MessageLogWidget::logRollDie(PlayerLogic *player, int sides, const QList &rolls) { if (rolls.length() == 1) { const auto roll = rolls.at(0); @@ -612,7 +615,7 @@ void MessageLogWidget::logRollDie(Player *player, int sides, const QList & soundEngine->playSound("roll_dice"); } -void MessageLogWidget::logSay(Player *player, QString message) +void MessageLogWidget::logSay(PlayerLogic *player, QString message) { appendMessage(std::move(message), {}, *player->getPlayerInfo()->getUserInfo(), true); } @@ -627,13 +630,13 @@ void MessageLogWidget::logSetActivePhase(int phaseNumber) phase.getName() + ""); } -void MessageLogWidget::logSetActivePlayer(Player *player) +void MessageLogWidget::logSetActivePlayer(PlayerLogic *player) { appendHtml("
    " + QDateTime::currentDateTime().toString("[hh:mm:ss] ") + QString(tr("%1's turn.")).arg(player->getPlayerInfo()->getName()) + "
    "); } -void MessageLogWidget::logSetAnnotation(Player *player, CardItem *card, QString newAnnotation) +void MessageLogWidget::logSetAnnotation(PlayerLogic *player, CardItem *card, QString newAnnotation) { appendHtmlServerMessage( QString(tr("%1 sets annotation of %2 to %3.")) @@ -642,7 +645,7 @@ void MessageLogWidget::logSetAnnotation(Player *player, CardItem *card, QString .arg(QString(""%1"").arg(sanitizeHtml(std::move(newAnnotation))))); } -void MessageLogWidget::logSetCardCounter(Player *player, QString cardName, int counterId, int value, int oldValue) +void MessageLogWidget::logSetCardCounter(PlayerLogic *player, QString cardName, int counterId, int value, int oldValue) { QString finalStr; int delta = abs(oldValue - value); @@ -660,7 +663,7 @@ void MessageLogWidget::logSetCardCounter(Player *player, QString cardName, int c .arg(value)); } -void MessageLogWidget::logSetCounter(Player *player, QString counterName, int value, int oldValue) +void MessageLogWidget::logSetCounter(PlayerLogic *player, QString counterName, int value, int oldValue) { if (counterName == "life") { soundEngine->playSound("life_change"); @@ -675,7 +678,7 @@ void MessageLogWidget::logSetCounter(Player *player, QString counterName, int va .arg(value - oldValue)); } -void MessageLogWidget::logSetDoesntUntap(Player *player, CardItem *card, bool doesntUntap) +void MessageLogWidget::logSetDoesntUntap(PlayerLogic *player, CardItem *card, bool doesntUntap) { QString str; if (doesntUntap) { @@ -686,7 +689,7 @@ void MessageLogWidget::logSetDoesntUntap(Player *player, CardItem *card, bool do appendHtmlServerMessage(str.arg(sanitizeHtml(player->getPlayerInfo()->getName())).arg(cardLink(card->getName()))); } -void MessageLogWidget::logSetPT(Player *player, CardItem *card, QString newPT) +void MessageLogWidget::logSetPT(PlayerLogic *player, CardItem *card, QString newPT) { if (currentContext == MessageContext_MoveCard) { return; @@ -713,7 +716,7 @@ void MessageLogWidget::logSetPT(Player *player, CardItem *card, QString newPT) } } -void MessageLogWidget::logSetSideboardLock(Player *player, bool locked) +void MessageLogWidget::logSetSideboardLock(PlayerLogic *player, bool locked) { if (locked) { appendHtmlServerMessage( @@ -724,7 +727,7 @@ void MessageLogWidget::logSetSideboardLock(Player *player, bool locked) } } -void MessageLogWidget::logSetTapped(Player *player, CardItem *card, bool tapped) +void MessageLogWidget::logSetTapped(PlayerLogic *player, CardItem *card, bool tapped) { if (currentContext == MessageContext_MoveCard) { return; @@ -747,7 +750,7 @@ void MessageLogWidget::logSetTapped(Player *player, CardItem *card, bool tapped) } } -void MessageLogWidget::logShuffle(Player *player, CardZoneLogic *zone, int start, int end) +void MessageLogWidget::logShuffle(PlayerLogic *player, CardZoneLogic *zone, int start, int end) { if (currentContext == MessageContext_Mulligan) { return; @@ -784,14 +787,14 @@ void MessageLogWidget::logSpectatorSay(const ServerInfo_User &spectator, QString appendMessage(std::move(message), {}, spectator, false); } -void MessageLogWidget::logUnattachCard(Player *player, QString cardName) +void MessageLogWidget::logUnattachCard(PlayerLogic *player, QString cardName) { appendHtmlServerMessage(tr("%1 unattaches %2.") .arg(sanitizeHtml(player->getPlayerInfo()->getName())) .arg(cardLink(std::move(cardName)))); } -void MessageLogWidget::logUndoDraw(Player *player, QString cardName) +void MessageLogWidget::logUndoDraw(PlayerLogic *player, QString cardName) { if (cardName.isEmpty()) { appendHtmlServerMessage(tr("%1 undoes their last draw.").arg(sanitizeHtml(player->getPlayerInfo()->getName()))); diff --git a/cockatrice/src/game/log/message_log_widget.h b/cockatrice/src/game/log/message_log_widget.h index 78f830e53..25db21864 100644 --- a/cockatrice/src/game/log/message_log_widget.h +++ b/cockatrice/src/game/log/message_log_widget.h @@ -13,7 +13,7 @@ class AbstractGame; class CardItem; class GameEventContext; -class Player; +class PlayerLogic; class PlayerEventHandler; class MessageLogWidget : public ChatView @@ -39,66 +39,66 @@ public: public slots: void containerProcessingDone(); void containerProcessingStarted(const GameEventContext &context); - void logAlwaysRevealTopCard(Player *player, CardZoneLogic *zone, bool reveal); - void logAlwaysLookAtTopCard(Player *player, CardZoneLogic *zone, bool reveal); - void logAttachCard(Player *player, QString cardName, Player *targetPlayer, QString targetCardName); + void logAlwaysRevealTopCard(PlayerLogic *player, CardZoneLogic *zone, bool reveal); + void logAlwaysLookAtTopCard(PlayerLogic *player, CardZoneLogic *zone, bool reveal); + void logAttachCard(PlayerLogic *player, QString cardName, PlayerLogic *targetPlayer, QString targetCardName); void logConcede(int playerId); void logUnconcede(int playerId); - void logConnectionStateChanged(Player *player, bool connectionState); - void logCreateArrow(Player *player, - Player *startPlayer, + void logConnectionStateChanged(PlayerLogic *player, bool connectionState); + void logCreateArrow(PlayerLogic *player, + PlayerLogic *startPlayer, QString startCard, - Player *targetPlayer, + PlayerLogic *targetPlayer, QString targetCard, bool playerTarget); - void logCreateToken(Player *player, QString cardName, QString pt, bool faceDown); - void logDeckSelect(Player *player, QString deckHash, int sideboardSize); - void logDestroyCard(Player *player, QString cardName); - void logDrawCards(Player *player, int number, bool deckIsEmpty); - void logDumpZone(Player *player, CardZoneLogic *zone, int numberCards, bool isReversed = false); - void logFlipCard(Player *player, QString cardName, bool faceDown); + void logCreateToken(PlayerLogic *player, QString cardName, QString pt, bool faceDown); + void logDeckSelect(PlayerLogic *player, QString deckHash, int sideboardSize); + void logDestroyCard(PlayerLogic *player, QString cardName); + void logDrawCards(PlayerLogic *player, int number, bool deckIsEmpty); + void logDumpZone(PlayerLogic *player, CardZoneLogic *zone, int numberCards, bool isReversed = false); + void logFlipCard(PlayerLogic *player, QString cardName, bool faceDown); void logGameClosed(); void logGameStart(); void logGameFlooded(); - void logJoin(Player *player); + void logJoin(PlayerLogic *player); void logJoinSpectator(QString name); void logKicked(); - void logLeave(Player *player, QString reason); + void logLeave(PlayerLogic *player, QString reason); void logLeaveSpectator(QString name, QString reason); - void logNotReadyStart(Player *player); - void logMoveCard(Player *player, + void logNotReadyStart(PlayerLogic *player); + void logMoveCard(PlayerLogic *player, CardItem *card, CardZoneLogic *startZone, int oldX, CardZoneLogic *targetZone, int newX); - void logMulligan(Player *player, int number); + void logMulligan(PlayerLogic *player, int number); void logReplayStarted(int gameId); - void logReadyStart(Player *player); - void logRevealCards(Player *player, + void logReadyStart(PlayerLogic *player); + void logRevealCards(PlayerLogic *player, CardZoneLogic *zone, int cardId, QString cardName, - Player *otherPlayer, + PlayerLogic *otherPlayer, bool faceDown, int amount, bool isLentToAnotherPlayer); - void logReverseTurn(Player *player, bool reversed); - void logRollDie(Player *player, int sides, const QList &rolls); - void logSay(Player *player, QString message); + void logReverseTurn(PlayerLogic *player, bool reversed); + void logRollDie(PlayerLogic *player, int sides, const QList &rolls); + void logSay(PlayerLogic *player, QString message); void logSetActivePhase(int phase); - void logSetActivePlayer(Player *player); - void logSetAnnotation(Player *player, CardItem *card, QString newAnnotation); - void logSetCardCounter(Player *player, QString cardName, int counterId, int value, int oldValue); - void logSetCounter(Player *player, QString counterName, int value, int oldValue); - void logSetDoesntUntap(Player *player, CardItem *card, bool doesntUntap); - void logSetPT(Player *player, CardItem *card, QString newPT); - void logSetSideboardLock(Player *player, bool locked); - void logSetTapped(Player *player, CardItem *card, bool tapped); - void logShuffle(Player *player, CardZoneLogic *zone, int start, int end); + void logSetActivePlayer(PlayerLogic *player); + void logSetAnnotation(PlayerLogic *player, CardItem *card, QString newAnnotation); + void logSetCardCounter(PlayerLogic *player, QString cardName, int counterId, int value, int oldValue); + void logSetCounter(PlayerLogic *player, QString counterName, int value, int oldValue); + void logSetDoesntUntap(PlayerLogic *player, CardItem *card, bool doesntUntap); + void logSetPT(PlayerLogic *player, CardItem *card, QString newPT); + void logSetSideboardLock(PlayerLogic *player, bool locked); + void logSetTapped(PlayerLogic *player, CardItem *card, bool tapped); + void logShuffle(PlayerLogic *player, CardZoneLogic *zone, int start, int end); void logSpectatorSay(const ServerInfo_User &spectator, QString message); - void logUnattachCard(Player *player, QString cardName); - void logUndoDraw(Player *player, QString cardName); + void logUnattachCard(PlayerLogic *player, QString cardName); + void logUndoDraw(PlayerLogic *player, QString cardName); void setContextJudgeName(QString player); void appendHtmlServerMessage(const QString &html, bool optionalIsBold = false, diff --git a/cockatrice/src/game/phases_toolbar.h b/cockatrice/src/game/phases_toolbar.h index 215a97dd1..dd2477424 100644 --- a/cockatrice/src/game/phases_toolbar.h +++ b/cockatrice/src/game/phases_toolbar.h @@ -21,7 +21,7 @@ namespace protobuf class Message; } } // namespace google -class Player; +class PlayerLogic; class GameCommand; class PhaseButton : public QObject, public QGraphicsItem diff --git a/cockatrice/src/game/player/menu/card_menu.cpp b/cockatrice/src/game/player/menu/card_menu.cpp index 9ece326cc..933f4094c 100644 --- a/cockatrice/src/game/player/menu/card_menu.cpp +++ b/cockatrice/src/game/player/menu/card_menu.cpp @@ -5,8 +5,8 @@ #include "../../board/card_item.h" #include "../../zones/view_zone_logic.h" #include "../card_menu_action_type.h" -#include "../player.h" #include "../player_actions.h" +#include "../player_logic.h" #include "move_menu.h" #include "pt_menu.h" @@ -14,12 +14,12 @@ #include #include -CardMenu::CardMenu(Player *_player, const CardItem *_card, bool _shortcutsActive) +CardMenu::CardMenu(PlayerLogic *_player, const CardItem *_card, bool _shortcutsActive) : player(_player), card(_card), shortcutsActive(_shortcutsActive) { auto playerActions = player->getPlayerActions(); - const QList &players = player->getGame()->getPlayerManager()->getPlayers().values(); + const QList &players = player->getGame()->getPlayerManager()->getPlayers().values(); for (auto playerToAdd : players) { if (playerToAdd == player) { @@ -137,7 +137,7 @@ CardMenu::CardMenu(Player *_player, const CardItem *_card, bool _shortcutsActive } } -void CardMenu::removePlayer(Player *playerToRemove) +void CardMenu::removePlayer(PlayerLogic *playerToRemove) { for (auto it = playersInfo.begin(); it != playersInfo.end();) { if (it->second == playerToRemove->getPlayerInfo()->getId()) { diff --git a/cockatrice/src/game/player/menu/card_menu.h b/cockatrice/src/game/player/menu/card_menu.h index 3cff238de..d214d3557 100644 --- a/cockatrice/src/game/player/menu/card_menu.h +++ b/cockatrice/src/game/player/menu/card_menu.h @@ -10,14 +10,14 @@ #include class CardItem; -class Player; +class PlayerLogic; class CardMenu : public QMenu { Q_OBJECT public: - explicit CardMenu(Player *player, const CardItem *card, bool shortcutsActive); - void removePlayer(Player *playerToRemove); + explicit CardMenu(PlayerLogic *player, const CardItem *card, bool shortcutsActive); + void removePlayer(PlayerLogic *playerToRemove); void createTableMenu(bool canModifyCard); void createStackMenu(bool canModifyCard); void createGraveyardOrExileMenu(bool canModifyCard); @@ -41,7 +41,7 @@ public: QList aAddCounter, aSetCounter, aRemoveCounter; private: - Player *player; + PlayerLogic *player; const CardItem *card; QList> playersInfo; bool shortcutsActive; diff --git a/cockatrice/src/game/player/menu/custom_zone_menu.cpp b/cockatrice/src/game/player/menu/custom_zone_menu.cpp index b0f3284c9..88b7f3710 100644 --- a/cockatrice/src/game/player/menu/custom_zone_menu.cpp +++ b/cockatrice/src/game/player/menu/custom_zone_menu.cpp @@ -1,13 +1,13 @@ #include "custom_zone_menu.h" -#include "../player.h" +#include "../player_logic.h" -CustomZoneMenu::CustomZoneMenu(Player *_player) : player(_player) +CustomZoneMenu::CustomZoneMenu(PlayerLogic *_player) : player(_player) { menuAction()->setVisible(false); - connect(player, &Player::clearCustomZonesMenu, this, &CustomZoneMenu::clearCustomZonesMenu); - connect(player, &Player::addViewCustomZoneActionToCustomZoneMenu, this, + connect(player, &PlayerLogic::clearCustomZonesMenu, this, &CustomZoneMenu::clearCustomZonesMenu); + connect(player, &PlayerLogic::addViewCustomZoneActionToCustomZoneMenu, this, &CustomZoneMenu::addViewCustomZoneActionToCustomZoneMenu); retranslateUi(); diff --git a/cockatrice/src/game/player/menu/custom_zone_menu.h b/cockatrice/src/game/player/menu/custom_zone_menu.h index c4e66754e..a6ea15892 100644 --- a/cockatrice/src/game/player/menu/custom_zone_menu.h +++ b/cockatrice/src/game/player/menu/custom_zone_menu.h @@ -11,12 +11,12 @@ #include -class Player; +class PlayerLogic; class CustomZoneMenu : public QMenu, public AbstractPlayerComponent { Q_OBJECT public: - explicit CustomZoneMenu(Player *player); + explicit CustomZoneMenu(PlayerLogic *player); void retranslateUi() override; void setShortcutsActive() override { @@ -26,7 +26,7 @@ public: } private: - Player *player; + PlayerLogic *player; private slots: void clearCustomZonesMenu(); void addViewCustomZoneActionToCustomZoneMenu(QString zoneName); diff --git a/cockatrice/src/game/player/menu/grave_menu.cpp b/cockatrice/src/game/player/menu/grave_menu.cpp index c3a5eb433..16a5858ca 100644 --- a/cockatrice/src/game/player/menu/grave_menu.cpp +++ b/cockatrice/src/game/player/menu/grave_menu.cpp @@ -1,14 +1,14 @@ #include "grave_menu.h" #include "../../abstract_game.h" -#include "../player.h" #include "../player_actions.h" +#include "../player_logic.h" #include #include #include -GraveyardMenu::GraveyardMenu(Player *_player, QWidget *parent) : TearOffMenu(parent), player(_player) +GraveyardMenu::GraveyardMenu(PlayerLogic *_player, QWidget *parent) : TearOffMenu(parent), player(_player) { createMoveActions(); createViewActions(); diff --git a/cockatrice/src/game/player/menu/grave_menu.h b/cockatrice/src/game/player/menu/grave_menu.h index 429173afa..167714013 100644 --- a/cockatrice/src/game/player/menu/grave_menu.h +++ b/cockatrice/src/game/player/menu/grave_menu.h @@ -13,7 +13,7 @@ #include #include -class Player; +class PlayerLogic; class GraveyardMenu : public TearOffMenu, public AbstractPlayerComponent { Q_OBJECT @@ -21,7 +21,7 @@ signals: void newPlayerActionCreated(QAction *action); public: - explicit GraveyardMenu(Player *player, QWidget *parent = nullptr); + explicit GraveyardMenu(PlayerLogic *player, QWidget *parent = nullptr); void createMoveActions(); void createViewActions(); void populateRevealRandomMenuWithActivePlayers(); @@ -40,7 +40,7 @@ public: QAction *aMoveGraveToRfg = nullptr; private: - Player *player; + PlayerLogic *player; }; #endif // COCKATRICE_GRAVE_MENU_H diff --git a/cockatrice/src/game/player/menu/hand_menu.cpp b/cockatrice/src/game/player/menu/hand_menu.cpp index 156bf2aa9..6ff177655 100644 --- a/cockatrice/src/game/player/menu/hand_menu.cpp +++ b/cockatrice/src/game/player/menu/hand_menu.cpp @@ -4,14 +4,14 @@ #include "../../../client/settings/shortcuts_settings.h" #include "../../../game_graphics/zones/hand_zone.h" #include "../../abstract_game.h" -#include "../player.h" #include "../player_actions.h" +#include "../player_logic.h" #include #include #include -HandMenu::HandMenu(Player *_player, PlayerActions *actions, QWidget *parent) : TearOffMenu(parent), player(_player) +HandMenu::HandMenu(PlayerLogic *_player, PlayerActions *actions, QWidget *parent) : TearOffMenu(parent), player(_player) { if (player->getPlayerInfo()->local || player->getPlayerInfo()->judge) { aViewHand = new QAction(this); diff --git a/cockatrice/src/game/player/menu/hand_menu.h b/cockatrice/src/game/player/menu/hand_menu.h index 76434cc98..4fdd0d6fc 100644 --- a/cockatrice/src/game/player/menu/hand_menu.h +++ b/cockatrice/src/game/player/menu/hand_menu.h @@ -13,7 +13,7 @@ #include #include -class Player; +class PlayerLogic; class PlayerActions; class HandMenu : public TearOffMenu, public AbstractPlayerComponent @@ -21,7 +21,7 @@ class HandMenu : public TearOffMenu, public AbstractPlayerComponent Q_OBJECT public: - HandMenu(Player *player, PlayerActions *actions, QWidget *parent = nullptr); + HandMenu(PlayerLogic *player, PlayerActions *actions, QWidget *parent = nullptr); QMenu *revealHandMenu() const { @@ -43,7 +43,7 @@ private slots: void onRevealRandomHandCardTriggered(); private: - Player *player; + PlayerLogic *player; QAction *aViewHand = nullptr; QAction *aMulligan = nullptr; diff --git a/cockatrice/src/game/player/menu/library_menu.cpp b/cockatrice/src/game/player/menu/library_menu.cpp index 72591575f..8449af05a 100644 --- a/cockatrice/src/game/player/menu/library_menu.cpp +++ b/cockatrice/src/game/player/menu/library_menu.cpp @@ -4,13 +4,13 @@ #include "../../../client/settings/shortcuts_settings.h" #include "../../../interface/widgets/tabs/tab_game.h" #include "../../abstract_game.h" -#include "../player.h" #include "../player_actions.h" +#include "../player_logic.h" #include #include -LibraryMenu::LibraryMenu(Player *_player, QWidget *parent) : TearOffMenu(parent), player(_player) +LibraryMenu::LibraryMenu(PlayerLogic *_player, QWidget *parent) : TearOffMenu(parent), player(_player) { createDrawActions(); createShuffleActions(); @@ -75,8 +75,8 @@ LibraryMenu::LibraryMenu(Player *_player, QWidget *parent) : TearOffMenu(parent) bottomLibraryMenu->addSeparator(); bottomLibraryMenu->addAction(aShuffleBottomCards); - connect(player, &Player::resetTopCardMenuActions, this, &LibraryMenu::resetTopCardMenuActions); - connect(player, &Player::deckChanged, this, &LibraryMenu::enableOpenInDeckEditorAction); + connect(player, &PlayerLogic::resetTopCardMenuActions, this, &LibraryMenu::resetTopCardMenuActions); + connect(player, &PlayerLogic::deckChanged, this, &LibraryMenu::enableOpenInDeckEditorAction); retranslateUi(); } diff --git a/cockatrice/src/game/player/menu/library_menu.h b/cockatrice/src/game/player/menu/library_menu.h index 444e8f516..e69a395e2 100644 --- a/cockatrice/src/game/player/menu/library_menu.h +++ b/cockatrice/src/game/player/menu/library_menu.h @@ -13,7 +13,7 @@ #include #include -class Player; +class PlayerLogic; class PlayerActions; class LibraryMenu : public TearOffMenu, public AbstractPlayerComponent @@ -24,7 +24,7 @@ public slots: void resetTopCardMenuActions(); public: - LibraryMenu(Player *player, QWidget *parent = nullptr); + LibraryMenu(PlayerLogic *player, QWidget *parent = nullptr); void createDrawActions(); void createShuffleActions(); void createMoveActions(); @@ -111,7 +111,7 @@ public: int defaultNumberTopCards = 1; private: - Player *player; + PlayerLogic *player; }; #endif // COCKATRICE_LIBRARY_MENU_H diff --git a/cockatrice/src/game/player/menu/move_menu.cpp b/cockatrice/src/game/player/menu/move_menu.cpp index 91e2d8d10..3a5ad4da3 100644 --- a/cockatrice/src/game/player/menu/move_menu.cpp +++ b/cockatrice/src/game/player/menu/move_menu.cpp @@ -1,10 +1,10 @@ #include "move_menu.h" #include "../card_menu_action_type.h" -#include "../player.h" #include "../player_actions.h" +#include "../player_logic.h" -MoveMenu::MoveMenu(Player *player) : QMenu(tr("Move to")) +MoveMenu::MoveMenu(PlayerLogic *player) : QMenu(tr("Move to")) { aMoveToTopLibrary = new QAction(this); aMoveToTopLibrary->setData(cmMoveToTopLibrary); diff --git a/cockatrice/src/game/player/menu/move_menu.h b/cockatrice/src/game/player/menu/move_menu.h index dc39cb6a5..59078a5c8 100644 --- a/cockatrice/src/game/player/menu/move_menu.h +++ b/cockatrice/src/game/player/menu/move_menu.h @@ -8,13 +8,13 @@ #define COCKATRICE_MOVE_MENU_H #include -class Player; +class PlayerLogic; class MoveMenu : public QMenu { Q_OBJECT public: - explicit MoveMenu(Player *player); + explicit MoveMenu(PlayerLogic *player); void setShortcutsActive(); void retranslateUi(); diff --git a/cockatrice/src/game/player/menu/player_menu.cpp b/cockatrice/src/game/player/menu/player_menu.cpp index 8a0e4af8b..d04950c96 100644 --- a/cockatrice/src/game/player/menu/player_menu.cpp +++ b/cockatrice/src/game/player/menu/player_menu.cpp @@ -10,7 +10,7 @@ #include -PlayerMenu::PlayerMenu(Player *_player) : QObject(_player), player(_player) +PlayerMenu::PlayerMenu(PlayerLogic *_player) : QObject(_player), player(_player) { playerMenu = new TearOffMenu(); diff --git a/cockatrice/src/game/player/menu/player_menu.h b/cockatrice/src/game/player/menu/player_menu.h index 104c5a930..7532ac225 100644 --- a/cockatrice/src/game/player/menu/player_menu.h +++ b/cockatrice/src/game/player/menu/player_menu.h @@ -8,7 +8,7 @@ #define COCKATRICE_PLAYER_MENU_H #include "../../../interface/widgets/menus/tearoff_menu.h" -#include "../player.h" +#include "../player_logic.h" #include "custom_zone_menu.h" #include "grave_menu.h" #include "hand_menu.h" @@ -37,7 +37,7 @@ private slots: void refreshShortcuts(); public: - explicit PlayerMenu(Player *player); + explicit PlayerMenu(PlayerLogic *player); /// Lifecycle methods: delegate to all managedComponents, plus counters separately via player->getCounters(). void retranslateUi(); @@ -74,7 +74,7 @@ public: void setShortcutsInactive(); private: - Player *player; + PlayerLogic *player; TearOffMenu *playerMenu; QMenu *countersMenu; HandMenu *handMenu; diff --git a/cockatrice/src/game/player/menu/pt_menu.cpp b/cockatrice/src/game/player/menu/pt_menu.cpp index dae03e07f..7dc3035c1 100644 --- a/cockatrice/src/game/player/menu/pt_menu.cpp +++ b/cockatrice/src/game/player/menu/pt_menu.cpp @@ -1,9 +1,9 @@ #include "pt_menu.h" -#include "../player.h" #include "../player_actions.h" +#include "../player_logic.h" -PtMenu::PtMenu(Player *player) : QMenu(tr("Power / toughness")) +PtMenu::PtMenu(PlayerLogic *player) : QMenu(tr("Power / toughness")) { PlayerActions *playerActions = player->getPlayerActions(); diff --git a/cockatrice/src/game/player/menu/pt_menu.h b/cockatrice/src/game/player/menu/pt_menu.h index 44112e54f..a1cbd021c 100644 --- a/cockatrice/src/game/player/menu/pt_menu.h +++ b/cockatrice/src/game/player/menu/pt_menu.h @@ -8,14 +8,14 @@ #define COCKATRICE_PT_MENU_H #include -class Player; +class PlayerLogic; class PtMenu : public QMenu { Q_OBJECT public: - explicit PtMenu(Player *player); + explicit PtMenu(PlayerLogic *player); void retranslateUi(); void setShortcutsActive(); diff --git a/cockatrice/src/game/player/menu/rfg_menu.cpp b/cockatrice/src/game/player/menu/rfg_menu.cpp index 8a101c04c..e8aca00cb 100644 --- a/cockatrice/src/game/player/menu/rfg_menu.cpp +++ b/cockatrice/src/game/player/menu/rfg_menu.cpp @@ -1,11 +1,11 @@ #include "rfg_menu.h" -#include "../player.h" #include "../player_actions.h" +#include "../player_logic.h" #include -RfgMenu::RfgMenu(Player *_player, QWidget *parent) : TearOffMenu(parent), player(_player) +RfgMenu::RfgMenu(PlayerLogic *_player, QWidget *parent) : TearOffMenu(parent), player(_player) { createMoveActions(); createViewActions(); diff --git a/cockatrice/src/game/player/menu/rfg_menu.h b/cockatrice/src/game/player/menu/rfg_menu.h index 8f79b2f4a..7025169c8 100644 --- a/cockatrice/src/game/player/menu/rfg_menu.h +++ b/cockatrice/src/game/player/menu/rfg_menu.h @@ -13,12 +13,12 @@ #include #include -class Player; +class PlayerLogic; class RfgMenu : public TearOffMenu, public AbstractPlayerComponent { Q_OBJECT public: - explicit RfgMenu(Player *player, QWidget *parent = nullptr); + explicit RfgMenu(PlayerLogic *player, QWidget *parent = nullptr); void createMoveActions(); void createViewActions(); void retranslateUi() override; @@ -38,7 +38,7 @@ public: QAction *aMoveRfgToGrave = nullptr; private: - Player *player; + PlayerLogic *player; }; #endif // COCKATRICE_RFG_MENU_H diff --git a/cockatrice/src/game/player/menu/say_menu.cpp b/cockatrice/src/game/player/menu/say_menu.cpp index 116fba49a..a2d5ab982 100644 --- a/cockatrice/src/game/player/menu/say_menu.cpp +++ b/cockatrice/src/game/player/menu/say_menu.cpp @@ -1,10 +1,10 @@ #include "say_menu.h" #include "../../../client/settings/cache_settings.h" -#include "../player.h" #include "../player_actions.h" +#include "../player_logic.h" -SayMenu::SayMenu(Player *_player) : player(_player) +SayMenu::SayMenu(PlayerLogic *_player) : player(_player) { connect(&SettingsCache::instance().messages(), &MessageSettings::messageMacrosChanged, this, &SayMenu::initSayMenu); initSayMenu(); diff --git a/cockatrice/src/game/player/menu/say_menu.h b/cockatrice/src/game/player/menu/say_menu.h index fadf5f368..938990193 100644 --- a/cockatrice/src/game/player/menu/say_menu.h +++ b/cockatrice/src/game/player/menu/say_menu.h @@ -11,12 +11,12 @@ #include -class Player; +class PlayerLogic; class SayMenu : public QMenu, public AbstractPlayerComponent { Q_OBJECT public: - explicit SayMenu(Player *player); + explicit SayMenu(PlayerLogic *player); void retranslateUi() override; void setShortcutsActive() override; @@ -26,7 +26,7 @@ private slots: void initSayMenu(); private: - Player *player; + PlayerLogic *player; bool shortcutsActive = false; }; diff --git a/cockatrice/src/game/player/menu/sideboard_menu.cpp b/cockatrice/src/game/player/menu/sideboard_menu.cpp index beaabfcc6..f88625a1f 100644 --- a/cockatrice/src/game/player/menu/sideboard_menu.cpp +++ b/cockatrice/src/game/player/menu/sideboard_menu.cpp @@ -1,9 +1,9 @@ #include "sideboard_menu.h" -#include "../player.h" #include "../player_actions.h" +#include "../player_logic.h" -SideboardMenu::SideboardMenu(Player *player, QMenu *playerMenu) : QMenu(playerMenu) +SideboardMenu::SideboardMenu(PlayerLogic *player, QMenu *playerMenu) : QMenu(playerMenu) { aViewSideboard = new QAction(this); connect(aViewSideboard, &QAction::triggered, player->getPlayerActions(), &PlayerActions::actViewSideboard); diff --git a/cockatrice/src/game/player/menu/sideboard_menu.h b/cockatrice/src/game/player/menu/sideboard_menu.h index 4a77d1b52..b5385997f 100644 --- a/cockatrice/src/game/player/menu/sideboard_menu.h +++ b/cockatrice/src/game/player/menu/sideboard_menu.h @@ -11,19 +11,19 @@ #include -class Player; +class PlayerLogic; class SideboardMenu : public QMenu, public AbstractPlayerComponent { Q_OBJECT public: - explicit SideboardMenu(Player *player, QMenu *playerMenu); + explicit SideboardMenu(PlayerLogic *player, QMenu *playerMenu); void retranslateUi() override; void setShortcutsActive() override; void setShortcutsInactive() override; private: - Player *player; + PlayerLogic *player; QAction *aViewSideboard; }; diff --git a/cockatrice/src/game/player/menu/utility_menu.cpp b/cockatrice/src/game/player/menu/utility_menu.cpp index bcb4683fd..f6d9802ae 100644 --- a/cockatrice/src/game/player/menu/utility_menu.cpp +++ b/cockatrice/src/game/player/menu/utility_menu.cpp @@ -1,14 +1,14 @@ #include "utility_menu.h" #include "../../../interface/deck_loader/deck_loader.h" -#include "../player.h" #include "../player_actions.h" +#include "../player_logic.h" #include "player_menu.h" #include #include -UtilityMenu::UtilityMenu(Player *_player, QMenu *playerMenu) : QMenu(playerMenu), player(_player) +UtilityMenu::UtilityMenu(PlayerLogic *_player, QMenu *playerMenu) : QMenu(playerMenu), player(_player) { PlayerActions *playerActions = player->getPlayerActions(); @@ -30,11 +30,11 @@ UtilityMenu::UtilityMenu(Player *_player, QMenu *playerMenu) : QMenu(playerMenu) aCreateAnotherToken->setEnabled(false); aIncrementAllCardCounters = new QAction(this); - connect(aIncrementAllCardCounters, &QAction::triggered, player, &Player::incrementAllCardCounters); + connect(aIncrementAllCardCounters, &QAction::triggered, player, &PlayerLogic::incrementAllCardCounters); createPredefinedTokenMenu = new QMenu(QString()); createPredefinedTokenMenu->setEnabled(false); - connect(player, &Player::deckChanged, this, &UtilityMenu::populatePredefinedTokensMenu); + connect(player, &PlayerLogic::deckChanged, this, &UtilityMenu::populatePredefinedTokensMenu); playerMenu->addAction(aIncrementAllCardCounters); playerMenu->addSeparator(); diff --git a/cockatrice/src/game/player/menu/utility_menu.h b/cockatrice/src/game/player/menu/utility_menu.h index 117a7e13a..6d922d726 100644 --- a/cockatrice/src/game/player/menu/utility_menu.h +++ b/cockatrice/src/game/player/menu/utility_menu.h @@ -11,7 +11,7 @@ #include -class Player; +class PlayerLogic; class UtilityMenu : public QMenu, public AbstractPlayerComponent { Q_OBJECT @@ -22,7 +22,7 @@ public slots: void setShortcutsInactive() override; public: - explicit UtilityMenu(Player *player, QMenu *playerMenu); + explicit UtilityMenu(PlayerLogic *player, QMenu *playerMenu); [[nodiscard]] bool createAnotherTokenActionExists() const { @@ -41,7 +41,7 @@ public: } private: - Player *player; + PlayerLogic *player; QStringList predefinedTokens; QMenu *createPredefinedTokenMenu; diff --git a/cockatrice/src/game/player/player_actions.cpp b/cockatrice/src/game/player/player_actions.cpp index d5ba3b22b..341769899 100644 --- a/cockatrice/src/game/player/player_actions.cpp +++ b/cockatrice/src/game/player/player_actions.cpp @@ -36,7 +36,7 @@ // milliseconds in between triggers of the move top cards until action static constexpr int MOVE_TOP_CARD_UNTIL_INTERVAL = 100; -PlayerActions::PlayerActions(Player *_player) +PlayerActions::PlayerActions(PlayerLogic *_player) : QObject(_player), player(_player), lastTokenTableRow(0), movingCardsUntil(false) { moveTopCardTimer = new QTimer(this); @@ -1770,7 +1770,7 @@ void PlayerActions::cardMenuAction() return; } - Player *startPlayer = zone->getPlayer(); + PlayerLogic *startPlayer = zone->getPlayer(); if (!startPlayer) { return; } diff --git a/cockatrice/src/game/player/player_actions.h b/cockatrice/src/game/player/player_actions.h index ba62f1c59..535e37707 100644 --- a/cockatrice/src/game/player/player_actions.h +++ b/cockatrice/src/game/player/player_actions.h @@ -10,7 +10,7 @@ #include "../dialogs/dlg_create_token.h" #include "../dialogs/dlg_move_top_cards_until.h" #include "event_processing_options.h" -#include "player.h" +#include "player_logic.h" #include #include @@ -29,7 +29,7 @@ class CardItem; class Command_MoveCard; class GameEventContext; class PendingCommand; -class Player; +class PlayerLogic; class PlayerActions : public QObject { Q_OBJECT @@ -40,7 +40,7 @@ public: RANDOM_CARD_FROM_ZONE = -2 }; - explicit PlayerActions(Player *player); + explicit PlayerActions(PlayerLogic *player); void sendGameCommand(PendingCommand *pend); void sendGameCommand(const google::protobuf::Message &command); @@ -159,7 +159,7 @@ public slots: void cardMenuAction(); private: - Player *player; + PlayerLogic *player; int defaultNumberTopCards = 1; int defaultNumberTopCardsToPlaceBelow = 1; diff --git a/cockatrice/src/game/player/player_event_handler.cpp b/cockatrice/src/game/player/player_event_handler.cpp index afc32208d..244929338 100644 --- a/cockatrice/src/game/player/player_event_handler.cpp +++ b/cockatrice/src/game/player/player_event_handler.cpp @@ -5,8 +5,8 @@ #include "../board/arrow_item.h" #include "../board/card_item.h" #include "../board/card_list.h" -#include "player.h" #include "player_actions.h" +#include "player_logic.h" #include #include @@ -32,7 +32,7 @@ #include #include -PlayerEventHandler::PlayerEventHandler(Player *_player) : QObject(_player), player(_player) +PlayerEventHandler::PlayerEventHandler(PlayerLogic *_player) : QObject(_player), player(_player) { } @@ -261,7 +261,7 @@ void PlayerEventHandler::eventDelCounter(const Event_DelCounter &event) void PlayerEventHandler::eventDumpZone(const Event_DumpZone &event) { - Player *zoneOwner = player->getGame()->getPlayerManager()->getPlayers().value(event.zone_owner_id(), 0); + PlayerLogic *zoneOwner = player->getGame()->getPlayerManager()->getPlayers().value(event.zone_owner_id(), 0); if (!zoneOwner) { return; } @@ -274,13 +274,13 @@ void PlayerEventHandler::eventDumpZone(const Event_DumpZone &event) void PlayerEventHandler::eventMoveCard(const Event_MoveCard &event, const GameEventContext &context) { - Player *startPlayer = player->getGame()->getPlayerManager()->getPlayers().value(event.start_player_id()); + PlayerLogic *startPlayer = player->getGame()->getPlayerManager()->getPlayers().value(event.start_player_id()); if (!startPlayer) { return; } QString startZoneString = QString::fromStdString(event.start_zone()); CardZoneLogic *startZone = startPlayer->getZones().value(startZoneString, 0); - Player *targetPlayer = player->getGame()->getPlayerManager()->getPlayers().value(event.target_player_id()); + PlayerLogic *targetPlayer = player->getGame()->getPlayerManager()->getPlayers().value(event.target_player_id()); if (!targetPlayer) { return; } @@ -353,9 +353,9 @@ void PlayerEventHandler::eventMoveCard(const Event_MoveCard &event, const GameEv // Look at all arrows from and to the card. // If the card was moved to another zone, delete the arrows, otherwise update them. - QMapIterator playerIterator(player->getGame()->getPlayerManager()->getPlayers()); + QMapIterator playerIterator(player->getGame()->getPlayerManager()->getPlayers()); while (playerIterator.hasNext()) { - Player *p = playerIterator.next().value(); + PlayerLogic *p = playerIterator.next().value(); QList arrowsToDelete; QMapIterator arrowIterator(p->getArrows()); @@ -428,8 +428,8 @@ void PlayerEventHandler::eventDestroyCard(const Event_DestroyCard &event) void PlayerEventHandler::eventAttachCard(const Event_AttachCard &event) { - const QMap &playerList = player->getGame()->getPlayerManager()->getPlayers(); - Player *targetPlayer = nullptr; + const QMap &playerList = player->getGame()->getPlayerManager()->getPlayers(); + PlayerLogic *targetPlayer = nullptr; CardZoneLogic *targetZone = nullptr; CardItem *targetCard = nullptr; if (event.has_target_player_id()) { @@ -506,7 +506,7 @@ void PlayerEventHandler::eventRevealCards(const Event_RevealCards &event, EventP if (!zone) { return; } - Player *otherPlayer = nullptr; + PlayerLogic *otherPlayer = nullptr; if (event.has_other_player_id()) { otherPlayer = player->getGame()->getPlayerManager()->getPlayers().value(event.other_player_id()); if (!otherPlayer) { diff --git a/cockatrice/src/game/player/player_event_handler.h b/cockatrice/src/game/player/player_event_handler.h index 9f67d24ab..ae3d9aaae 100644 --- a/cockatrice/src/game/player/player_event_handler.h +++ b/cockatrice/src/game/player/player_event_handler.h @@ -15,7 +15,7 @@ class CardItem; class CardZoneLogic; -class Player; +class PlayerLogic; class Event_AttachCard; class Event_ChangeZoneProperties; class Event_CreateArrow; @@ -40,48 +40,48 @@ class PlayerEventHandler : public QObject Q_OBJECT signals: - void logSay(Player *player, QString message); - void logShuffle(Player *player, CardZoneLogic *zone, int start, int end); - void logRollDie(Player *player, int sides, const QList &rolls); - void logCreateArrow(Player *player, - Player *startPlayer, + void logSay(PlayerLogic *player, QString message); + void logShuffle(PlayerLogic *player, CardZoneLogic *zone, int start, int end); + void logRollDie(PlayerLogic *player, int sides, const QList &rolls); + void logCreateArrow(PlayerLogic *player, + PlayerLogic *startPlayer, QString startCard, - Player *targetPlayer, + PlayerLogic *targetPlayer, QString targetCard, bool _playerTarget); - void logCreateToken(Player *player, QString cardName, QString pt, bool faceDown); - void logDrawCards(Player *player, int number, bool deckIsEmpty); - void logUndoDraw(Player *player, QString cardName); - void logMoveCard(Player *player, + void logCreateToken(PlayerLogic *player, QString cardName, QString pt, bool faceDown); + void logDrawCards(PlayerLogic *player, int number, bool deckIsEmpty); + void logUndoDraw(PlayerLogic *player, QString cardName); + void logMoveCard(PlayerLogic *player, CardItem *card, CardZoneLogic *startZone, int oldX, CardZoneLogic *targetZone, int newX); - void logFlipCard(Player *player, QString cardName, bool faceDown); - void logDestroyCard(Player *player, QString cardName); - void logAttachCard(Player *player, QString cardName, Player *targetPlayer, QString targetCardName); - void logUnattachCard(Player *player, QString cardName); - void logSetCardCounter(Player *player, QString cardName, int counterId, int value, int oldValue); - void logSetTapped(Player *player, CardItem *card, bool tapped); - void logSetCounter(Player *player, QString counterName, int value, int oldValue); - void logSetDoesntUntap(Player *player, CardItem *card, bool doesntUntap); - void logSetPT(Player *player, CardItem *card, QString newPT); - void logSetAnnotation(Player *player, CardItem *card, QString newAnnotation); - void logDumpZone(Player *player, CardZoneLogic *zone, int numberCards, bool isReversed = false); - void logRevealCards(Player *player, + void logFlipCard(PlayerLogic *player, QString cardName, bool faceDown); + void logDestroyCard(PlayerLogic *player, QString cardName); + void logAttachCard(PlayerLogic *player, QString cardName, PlayerLogic *targetPlayer, QString targetCardName); + void logUnattachCard(PlayerLogic *player, QString cardName); + void logSetCardCounter(PlayerLogic *player, QString cardName, int counterId, int value, int oldValue); + void logSetTapped(PlayerLogic *player, CardItem *card, bool tapped); + void logSetCounter(PlayerLogic *player, QString counterName, int value, int oldValue); + void logSetDoesntUntap(PlayerLogic *player, CardItem *card, bool doesntUntap); + void logSetPT(PlayerLogic *player, CardItem *card, QString newPT); + void logSetAnnotation(PlayerLogic *player, CardItem *card, QString newAnnotation); + void logDumpZone(PlayerLogic *player, CardZoneLogic *zone, int numberCards, bool isReversed = false); + void logRevealCards(PlayerLogic *player, CardZoneLogic *zone, int cardId, QString cardName, - Player *otherPlayer, + PlayerLogic *otherPlayer, bool faceDown, int amount, bool isLentToAnotherPlayer = false); - void logAlwaysRevealTopCard(Player *player, CardZoneLogic *zone, bool reveal); - void logAlwaysLookAtTopCard(Player *player, CardZoneLogic *zone, bool reveal); + void logAlwaysRevealTopCard(PlayerLogic *player, CardZoneLogic *zone, bool reveal); + void logAlwaysLookAtTopCard(PlayerLogic *player, CardZoneLogic *zone, bool reveal); public: - PlayerEventHandler(Player *player); + PlayerEventHandler(PlayerLogic *player); void processGameEvent(GameEvent::GameEventType type, const GameEvent &event, @@ -110,7 +110,7 @@ public: void eventChangeZoneProperties(const Event_ChangeZoneProperties &event); private: - Player *player; + PlayerLogic *player; void setCardAttrHelper(const GameEventContext &context, CardItem *card, diff --git a/cockatrice/src/game/player/player_graphics_item.cpp b/cockatrice/src/game/player/player_graphics_item.cpp index c60dbcdd0..eea2434d2 100644 --- a/cockatrice/src/game/player/player_graphics_item.cpp +++ b/cockatrice/src/game/player/player_graphics_item.cpp @@ -8,15 +8,15 @@ #include "../board/abstract_card_item.h" #include "../hand_counter.h" -PlayerGraphicsItem::PlayerGraphicsItem(Player *_player) : player(_player) +PlayerGraphicsItem::PlayerGraphicsItem(PlayerLogic *_player) : player(_player) { connect(&SettingsCache::instance(), &SettingsCache::horizontalHandChanged, this, &PlayerGraphicsItem::rearrangeZones); connect(&SettingsCache::instance(), &SettingsCache::handJustificationChanged, this, &PlayerGraphicsItem::rearrangeZones); - connect(player, &Player::rearrangeCounters, this, &PlayerGraphicsItem::rearrangeCounters); - connect(player, &Player::concededChanged, this, [this](int, bool c) { setVisible(!c); }); - connect(player, &Player::zoneIdChanged, this, [this](int id) { playerArea->setPlayerZoneId(id); }); + connect(player, &PlayerLogic::rearrangeCounters, this, &PlayerGraphicsItem::rearrangeCounters); + connect(player, &PlayerLogic::concededChanged, this, [this](int, bool c) { setVisible(!c); }); + connect(player, &PlayerLogic::zoneIdChanged, this, [this](int id) { playerArea->setPlayerZoneId(id); }); playerArea = new PlayerArea(this); diff --git a/cockatrice/src/game/player/player_graphics_item.h b/cockatrice/src/game/player/player_graphics_item.h index fd4c469e7..33c00be4f 100644 --- a/cockatrice/src/game/player/player_graphics_item.h +++ b/cockatrice/src/game/player/player_graphics_item.h @@ -7,7 +7,7 @@ #ifndef COCKATRICE_PLAYER_GRAPHICS_ITEM_H #define COCKATRICE_PLAYER_GRAPHICS_ITEM_H #include "../game_scene.h" -#include "player.h" +#include "player_logic.h" #include @@ -34,7 +34,7 @@ public: static constexpr int counterAreaWidth = 55; - explicit PlayerGraphicsItem(Player *player); + explicit PlayerGraphicsItem(PlayerLogic *player); void initializeZones(); [[nodiscard]] QRectF boundingRect() const override; @@ -54,7 +54,7 @@ public: return static_cast(scene()); } - Player *getPlayer() const + PlayerLogic *getPlayer() const { return player; } @@ -109,7 +109,7 @@ signals: void playerCountChanged(); private: - Player *player; + PlayerLogic *player; PlayerArea *playerArea; PlayerTarget *playerTarget; PileZone *deckZoneGraphicsItem; diff --git a/cockatrice/src/game/player/player_list_widget.h b/cockatrice/src/game/player/player_list_widget.h index 8f1487563..1815fdccd 100644 --- a/cockatrice/src/game/player/player_list_widget.h +++ b/cockatrice/src/game/player/player_list_widget.h @@ -7,7 +7,7 @@ #ifndef PLAYERLISTWIDGET_H #define PLAYERLISTWIDGET_H -#include "player.h" +#include "player_logic.h" #include #include diff --git a/cockatrice/src/game/player/player.cpp b/cockatrice/src/game/player/player_logic.cpp similarity index 86% rename from cockatrice/src/game/player/player.cpp rename to cockatrice/src/game/player/player_logic.cpp index ce36af9d4..2c09e3634 100644 --- a/cockatrice/src/game/player/player.cpp +++ b/cockatrice/src/game/player/player_logic.cpp @@ -1,4 +1,4 @@ -#include "player.h" +#include "player_logic.h" #include "../../game_graphics/zones/hand_zone.h" #include "../../game_graphics/zones/pile_zone.h" @@ -29,7 +29,7 @@ #include #include -Player::Player(const ServerInfo_User &info, int _id, bool _local, bool _judge, AbstractGame *_parent) +PlayerLogic::PlayerLogic(const ServerInfo_User &info, int _id, bool _local, bool _judge, AbstractGame *_parent) : QObject(_parent), game(_parent), playerInfo(new PlayerInfo(info, _id, _local, _judge)), playerEventHandler(new PlayerEventHandler(this)), playerActions(new PlayerActions(this)), active(false), conceded(false), zoneId(0), dialogSemaphore(false) @@ -40,12 +40,12 @@ Player::Player(const ServerInfo_User &info, int _id, bool _local, bool _judge, A graphicsItem = new PlayerGraphicsItem(this); playerMenu->setMenusForGraphicItems(); - connect(this, &Player::activeChanged, graphicsItem, &PlayerGraphicsItem::onPlayerActiveChanged); + connect(this, &PlayerLogic::activeChanged, graphicsItem, &PlayerGraphicsItem::onPlayerActiveChanged); - connect(this, &Player::openDeckEditor, game->getTab(), &TabGame::openDeckEditor); + connect(this, &PlayerLogic::openDeckEditor, game->getTab(), &TabGame::openDeckEditor); } -void Player::initializeZones() +void PlayerLogic::initializeZones() { addZone(new PileZoneLogic(this, ZoneNames::DECK, false, true, false, this)); addZone(new PileZoneLogic(this, ZoneNames::GRAVE, false, false, true, this)); @@ -58,7 +58,7 @@ void Player::initializeZones() addZone(new HandZoneLogic(this, ZoneNames::HAND, false, false, visibleHand, this)); } -Player::~Player() +PlayerLogic::~PlayerLogic() { qCInfo(PlayerLog) << "Player destructor:" << getPlayerInfo()->getName(); @@ -72,7 +72,7 @@ Player::~Player() delete getPlayerInfo()->userInfo; } -void Player::clear() +void PlayerLogic::clear() { clearArrows(); @@ -84,7 +84,7 @@ void Player::clear() clearCounters(); } -void Player::setConceded(bool _conceded) +void PlayerLogic::setConceded(bool _conceded) { if (conceded != _conceded) { conceded = _conceded; @@ -96,7 +96,7 @@ void Player::setConceded(bool _conceded) } } -void Player::setZoneId(int _zoneId) +void PlayerLogic::setZoneId(int _zoneId) { if (zoneId != _zoneId) { zoneId = _zoneId; @@ -104,7 +104,7 @@ void Player::setZoneId(int _zoneId) } } -void Player::processPlayerInfo(const ServerInfo_Player &info) +void PlayerLogic::processPlayerInfo(const ServerInfo_Player &info) { static QSet builtinZones{/* PileZones */ ZoneNames::DECK, ZoneNames::GRAVE, ZoneNames::EXILE, ZoneNames::SIDEBOARD, @@ -202,7 +202,7 @@ void Player::processPlayerInfo(const ServerInfo_Player &info) setConceded(info.properties().conceded()); } -void Player::processCardAttachment(const ServerInfo_Player &info) +void PlayerLogic::processCardAttachment(const ServerInfo_Player &info) { const int zoneListSize = info.zone_list_size(); for (int i = 0; i < zoneListSize; ++i) { @@ -235,12 +235,12 @@ void Player::processCardAttachment(const ServerInfo_Player &info) } } -void Player::addCard(CardItem *card) +void PlayerLogic::addCard(CardItem *card) { emit newCardAdded(card); } -void Player::deleteCard(CardItem *card) +void PlayerLogic::deleteCard(CardItem *card) { if (card == nullptr) { return; @@ -251,20 +251,20 @@ void Player::deleteCard(CardItem *card) } } -void Player::setDeck(const DeckList &_deck) +void PlayerLogic::setDeck(const DeckList &_deck) { deck = _deck; emit deckChanged(); } -AbstractCounter *Player::addCounter(const ServerInfo_Counter &counter) +AbstractCounter *PlayerLogic::addCounter(const ServerInfo_Counter &counter) { return addCounter(counter.id(), QString::fromStdString(counter.name()), convertColorToQColor(counter.counter_color()), counter.radius(), counter.count()); } -AbstractCounter *Player::addCounter(int counterId, const QString &name, QColor color, int radius, int value) +AbstractCounter *PlayerLogic::addCounter(int counterId, const QString &name, QColor color, int radius, int value) { if (counters.contains(counterId)) { return nullptr; @@ -288,7 +288,7 @@ AbstractCounter *Player::addCounter(int counterId, const QString &name, QColor c return ctr; } -void Player::delCounter(int counterId) +void PlayerLogic::delCounter(int counterId) { AbstractCounter *ctr = counters.value(counterId, 0); if (!ctr) { @@ -300,7 +300,7 @@ void Player::delCounter(int counterId) emit rearrangeCounters(); } -void Player::clearCounters() +void PlayerLogic::clearCounters() { QMapIterator counterIterator(counters); while (counterIterator.hasNext()) { @@ -309,7 +309,7 @@ void Player::clearCounters() counters.clear(); } -void Player::incrementAllCardCounters() +void PlayerLogic::incrementAllCardCounters() { auto cardsToUpdate = getGameScene()->selectedCards(); if (cardsToUpdate.isEmpty()) { @@ -345,7 +345,7 @@ void Player::incrementAllCardCounters() } } -AbstractCounter *Player::getLifeCounter() const +AbstractCounter *PlayerLogic::getLifeCounter() const { for (auto counter : counters.values()) { if (counter->getName() == "life") { @@ -355,11 +355,11 @@ AbstractCounter *Player::getLifeCounter() const return nullptr; } -ArrowItem *Player::addArrow(const ServerInfo_Arrow &arrow) +ArrowItem *PlayerLogic::addArrow(const ServerInfo_Arrow &arrow) { - const QMap &playerList = game->getPlayerManager()->getPlayers(); - Player *startPlayer = playerList.value(arrow.start_player_id(), 0); - Player *targetPlayer = playerList.value(arrow.target_player_id(), 0); + const QMap &playerList = game->getPlayerManager()->getPlayers(); + PlayerLogic *startPlayer = playerList.value(arrow.start_player_id(), 0); + PlayerLogic *targetPlayer = playerList.value(arrow.target_player_id(), 0); if (!startPlayer || !targetPlayer) { return nullptr; } @@ -390,7 +390,7 @@ ArrowItem *Player::addArrow(const ServerInfo_Arrow &arrow) } } -ArrowItem *Player::addArrow(int arrowId, CardItem *startCard, ArrowTarget *targetItem, const QColor &color) +ArrowItem *PlayerLogic::addArrow(int arrowId, CardItem *startCard, ArrowTarget *targetItem, const QColor &color) { auto *arrow = new ArrowItem(this, arrowId, startCard, targetItem, color); arrows.insert(arrowId, arrow); @@ -399,7 +399,7 @@ ArrowItem *Player::addArrow(int arrowId, CardItem *startCard, ArrowTarget *targe return arrow; } -void Player::delArrow(int arrowId) +void PlayerLogic::delArrow(int arrowId) { ArrowItem *arr = arrows.value(arrowId, 0); if (!arr) { @@ -408,14 +408,14 @@ void Player::delArrow(int arrowId) arr->delArrow(); } -void Player::removeArrow(ArrowItem *arrow) +void PlayerLogic::removeArrow(ArrowItem *arrow) { if (arrow->getId() != -1) { arrows.remove(arrow->getId()); } } -void Player::clearArrows() +void PlayerLogic::clearArrows() { QMapIterator arrowIterator(arrows); while (arrowIterator.hasNext()) { @@ -424,7 +424,7 @@ void Player::clearArrows() arrows.clear(); } -bool Player::clearCardsToDelete() +bool PlayerLogic::clearCardsToDelete() { if (cardsToDelete.isEmpty()) { return false; @@ -440,28 +440,28 @@ bool Player::clearCardsToDelete() return true; } -void Player::setActive(bool _active) +void PlayerLogic::setActive(bool _active) { active = _active; emit activeChanged(active); } -void Player::updateZones() +void PlayerLogic::updateZones() { getTableZone()->reorganizeCards(); } -PlayerGraphicsItem *Player::getGraphicsItem() +PlayerGraphicsItem *PlayerLogic::getGraphicsItem() { return graphicsItem; } -GameScene *Player::getGameScene() +GameScene *PlayerLogic::getGameScene() { return getGraphicsItem()->getGameScene(); } -void Player::setGameStarted() +void PlayerLogic::setGameStarted() { if (playerInfo->local) { emit resetTopCardMenuActions(); diff --git a/cockatrice/src/game/player/player.h b/cockatrice/src/game/player/player_logic.h similarity index 97% rename from cockatrice/src/game/player/player.h rename to cockatrice/src/game/player/player_logic.h index 43520b7ad..55599f5e2 100644 --- a/cockatrice/src/game/player/player.h +++ b/cockatrice/src/game/player/player_logic.h @@ -62,7 +62,7 @@ class TabGame; const int MAX_TOKENS_PER_DIALOG = 99; -class Player : public QObject +class PlayerLogic : public QObject { Q_OBJECT @@ -82,8 +82,8 @@ public slots: void setActive(bool _active); public: - Player(const ServerInfo_User &info, int _id, bool _local, bool _judge, AbstractGame *_parent); - ~Player() override; + PlayerLogic(const ServerInfo_User &info, int _id, bool _local, bool _judge, AbstractGame *_parent); + ~PlayerLogic() override; void initializeZones(); void updateZones(); diff --git a/cockatrice/src/game/player/player_manager.cpp b/cockatrice/src/game/player/player_manager.cpp index bd50703de..6772d3ff1 100644 --- a/cockatrice/src/game/player/player_manager.cpp +++ b/cockatrice/src/game/player/player_manager.cpp @@ -1,35 +1,35 @@ #include "player_manager.h" #include "../abstract_game.h" -#include "player.h" +#include "player_logic.h" PlayerManager::PlayerManager(AbstractGame *_game, int _localPlayerId, bool _localPlayerIsJudge, bool localPlayerIsSpectator) - : QObject(_game), game(_game), players(QMap()), localPlayerId(_localPlayerId), + : QObject(_game), game(_game), players(QMap()), localPlayerId(_localPlayerId), localPlayerIsJudge(_localPlayerIsJudge), localPlayerIsSpectator(localPlayerIsSpectator) { } bool PlayerManager::isMainPlayerConceded() const { - Player *player = players.value(localPlayerId, nullptr); + PlayerLogic *player = players.value(localPlayerId, nullptr); return player && player->getConceded(); } -Player *PlayerManager::getActiveLocalPlayer(int activePlayer) const +PlayerLogic *PlayerManager::getActiveLocalPlayer(int activePlayer) const { - Player *active = players.value(activePlayer, 0); + PlayerLogic *active = players.value(activePlayer, 0); if (active) { if (active->getPlayerInfo()->getLocal()) { return active; } } - QMapIterator playerIterator(players); + QMapIterator playerIterator(players); while (playerIterator.hasNext()) { - Player *temp = playerIterator.next().value(); + PlayerLogic *temp = playerIterator.next().value(); if (temp->getPlayerInfo()->getLocal()) { return temp; } @@ -43,11 +43,11 @@ bool PlayerManager::isLocalPlayer(int playerId) return game->getGameState()->getIsLocalGame() || playerId == localPlayerId; } -Player *PlayerManager::addPlayer(int playerId, const ServerInfo_User &info) +PlayerLogic *PlayerManager::addPlayer(int playerId, const ServerInfo_User &info) { - auto *newPlayer = new Player(info, playerId, isLocalPlayer(playerId) || game->getGameState()->getIsLocalGame(), - isJudge(), getGame()); - connect(newPlayer, &Player::concededChanged, this, &PlayerManager::onPlayerConceded); + auto *newPlayer = new PlayerLogic(info, playerId, isLocalPlayer(playerId) || game->getGameState()->getIsLocalGame(), + isJudge(), getGame()); + connect(newPlayer, &PlayerLogic::concededChanged, this, &PlayerManager::onPlayerConceded); players.insert(playerId, newPlayer); emit playerAdded(newPlayer); emit playerCountChanged(); @@ -56,7 +56,7 @@ Player *PlayerManager::addPlayer(int playerId, const ServerInfo_User &info) void PlayerManager::removePlayer(int playerId) { - Player *player = getPlayer(playerId); + PlayerLogic *player = getPlayer(playerId); if (!player) { return; } @@ -66,9 +66,9 @@ void PlayerManager::removePlayer(int playerId) player->deleteLater(); } -Player *PlayerManager::getPlayer(int playerId) const +PlayerLogic *PlayerManager::getPlayer(int playerId) const { - Player *player = players.value(playerId, 0); + PlayerLogic *player = players.value(playerId, 0); if (!player) { return nullptr; } diff --git a/cockatrice/src/game/player/player_manager.h b/cockatrice/src/game/player/player_manager.h index 0f813b3e4..4f6d62a87 100644 --- a/cockatrice/src/game/player/player_manager.h +++ b/cockatrice/src/game/player/player_manager.h @@ -12,7 +12,7 @@ #include class AbstractGame; -class Player; +class PlayerLogic; class PlayerManager : public QObject { Q_OBJECT @@ -21,7 +21,7 @@ public: PlayerManager(AbstractGame *_game, int _localPlayerId, bool _localPlayerIsJudge, bool localPlayerIsSpectator); AbstractGame *game; - QMap players; + QMap players; int localPlayerId; bool localPlayerIsJudge; bool localPlayerIsSpectator; @@ -42,7 +42,7 @@ public: return localPlayerId; } - [[nodiscard]] const QMap &getPlayers() const + [[nodiscard]] const QMap &getPlayers() const { return players; } @@ -52,14 +52,14 @@ public: return players.size(); } - [[nodiscard]] Player *getActiveLocalPlayer(int activePlayer) const; + [[nodiscard]] PlayerLogic *getActiveLocalPlayer(int activePlayer) const; bool isLocalPlayer(int playerId); - Player *addPlayer(int playerId, const ServerInfo_User &info); + PlayerLogic *addPlayer(int playerId, const ServerInfo_User &info); void removePlayer(int playerId); - [[nodiscard]] Player *getPlayer(int playerId) const; + [[nodiscard]] PlayerLogic *getPlayer(int playerId) const; void onPlayerConceded(int playerId, bool conceded); @@ -106,8 +106,8 @@ public: } signals: - void playerAdded(Player *player); - void playerRemoved(Player *player); + void playerAdded(PlayerLogic *player); + void playerRemoved(PlayerLogic *player); void activeLocalPlayerConceded(); void activeLocalPlayerUnconceded(); void playerConceded(int playerId); diff --git a/cockatrice/src/game/player/player_target.cpp b/cockatrice/src/game/player/player_target.cpp index 36c9ae953..93f2c05d4 100644 --- a/cockatrice/src/game/player/player_target.cpp +++ b/cockatrice/src/game/player/player_target.cpp @@ -1,7 +1,7 @@ #include "player_target.h" #include "../../interface/pixel_map_generator.h" -#include "player.h" +#include "player_logic.h" #include #include @@ -9,7 +9,7 @@ #include #include -PlayerCounter::PlayerCounter(Player *_player, int _id, const QString &_name, int _value, QGraphicsItem *parent) +PlayerCounter::PlayerCounter(PlayerLogic *_player, int _id, const QString &_name, int _value, QGraphicsItem *parent) : AbstractCounter(_player, _id, _name, false, _value, false, parent) { } @@ -47,7 +47,7 @@ void PlayerCounter::paint(QPainter *painter, const QStyleOptionGraphicsItem * /* painter->drawText(translatedRect, Qt::AlignCenter, QString::number(value)); } -PlayerTarget::PlayerTarget(Player *_owner, QGraphicsItem *parentItem) +PlayerTarget::PlayerTarget(PlayerLogic *_owner, QGraphicsItem *parentItem) : ArrowTarget(_owner, parentItem), playerCounter(nullptr) { setCacheMode(DeviceCoordinateCache); diff --git a/cockatrice/src/game/player/player_target.h b/cockatrice/src/game/player/player_target.h index b60464e12..3dbc82336 100644 --- a/cockatrice/src/game/player/player_target.h +++ b/cockatrice/src/game/player/player_target.h @@ -13,13 +13,13 @@ #include -class Player; +class PlayerLogic; class PlayerCounter : public AbstractCounter { Q_OBJECT public: - PlayerCounter(Player *_player, int _id, const QString &_name, int _value, QGraphicsItem *parent = nullptr); + PlayerCounter(PlayerLogic *_player, int _id, const QString &_name, int _value, QGraphicsItem *parent = nullptr); QRectF boundingRect() const override; void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override; }; @@ -43,7 +43,7 @@ public: return Type; } - explicit PlayerTarget(Player *_player = nullptr, QGraphicsItem *parentItem = nullptr); + explicit PlayerTarget(PlayerLogic *_player = nullptr, QGraphicsItem *parentItem = nullptr); ~PlayerTarget() override; QRectF boundingRect() const override; void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override; diff --git a/cockatrice/src/game/zones/card_zone_logic.cpp b/cockatrice/src/game/zones/card_zone_logic.cpp index 411aa19a9..aace7097e 100644 --- a/cockatrice/src/game/zones/card_zone_logic.cpp +++ b/cockatrice/src/game/zones/card_zone_logic.cpp @@ -2,8 +2,8 @@ #include "../../game_graphics/zones/view_zone.h" #include "../board/card_item.h" -#include "../player/player.h" #include "../player/player_actions.h" +#include "../player/player_logic.h" #include "view_zone_logic.h" #include @@ -20,7 +20,7 @@ * @param _contentsKnown whether the cards in the zone are known to the client * @param parent the parent QObject. */ -CardZoneLogic::CardZoneLogic(Player *_player, +CardZoneLogic::CardZoneLogic(PlayerLogic *_player, const QString &_name, bool _hasCardAttr, bool _isShufflable, diff --git a/cockatrice/src/game/zones/card_zone_logic.h b/cockatrice/src/game/zones/card_zone_logic.h index af770b104..63341343b 100644 --- a/cockatrice/src/game/zones/card_zone_logic.h +++ b/cockatrice/src/game/zones/card_zone_logic.h @@ -15,7 +15,7 @@ inline Q_LOGGING_CATEGORY(CardZoneLogicLog, "card_zone_logic"); -class Player; +class PlayerLogic; class ZoneViewZone; class QMenu; class QAction; @@ -35,7 +35,7 @@ signals: void retranslateUi(); public: - explicit CardZoneLogic(Player *_player, + explicit CardZoneLogic(PlayerLogic *_player, const QString &_name, bool _hasCardAttr, bool _isShufflable, @@ -68,7 +68,7 @@ public: return name; } [[nodiscard]] QString getTranslatedName(bool theirOwn, GrammaticalCase gc) const; - [[nodiscard]] Player *getPlayer() const + [[nodiscard]] PlayerLogic *getPlayer() const { return player; } @@ -105,7 +105,7 @@ private slots: void refreshCardInfos(); protected: - Player *player; + PlayerLogic *player; QString name; CardList cards; QList views; diff --git a/cockatrice/src/game/zones/hand_zone_logic.cpp b/cockatrice/src/game/zones/hand_zone_logic.cpp index 2dca1c6f7..36af11131 100644 --- a/cockatrice/src/game/zones/hand_zone_logic.cpp +++ b/cockatrice/src/game/zones/hand_zone_logic.cpp @@ -3,7 +3,7 @@ #include "../board/card_item.h" #include "card_zone_algorithms.h" -HandZoneLogic::HandZoneLogic(Player *_player, +HandZoneLogic::HandZoneLogic(PlayerLogic *_player, const QString &_name, bool _hasCardAttr, bool _isShufflable, diff --git a/cockatrice/src/game/zones/hand_zone_logic.h b/cockatrice/src/game/zones/hand_zone_logic.h index 8f34cc851..e5032b327 100644 --- a/cockatrice/src/game/zones/hand_zone_logic.h +++ b/cockatrice/src/game/zones/hand_zone_logic.h @@ -12,7 +12,7 @@ class HandZoneLogic : public CardZoneLogic { Q_OBJECT public: - HandZoneLogic(Player *_player, + HandZoneLogic(PlayerLogic *_player, const QString &_name, bool _hasCardAttr, bool _isShufflable, diff --git a/cockatrice/src/game/zones/pile_zone_logic.cpp b/cockatrice/src/game/zones/pile_zone_logic.cpp index 440b8df81..66edde4b7 100644 --- a/cockatrice/src/game/zones/pile_zone_logic.cpp +++ b/cockatrice/src/game/zones/pile_zone_logic.cpp @@ -2,7 +2,7 @@ #include "../board/card_item.h" -PileZoneLogic::PileZoneLogic(Player *_player, +PileZoneLogic::PileZoneLogic(PlayerLogic *_player, const QString &_name, bool _hasCardAttr, bool _isShufflable, diff --git a/cockatrice/src/game/zones/pile_zone_logic.h b/cockatrice/src/game/zones/pile_zone_logic.h index 498d0d4a2..68b39ec3a 100644 --- a/cockatrice/src/game/zones/pile_zone_logic.h +++ b/cockatrice/src/game/zones/pile_zone_logic.h @@ -17,7 +17,7 @@ signals: void callUpdate(); public: - PileZoneLogic(Player *_player, + PileZoneLogic(PlayerLogic *_player, const QString &_name, bool _hasCardAttr, bool _isShufflable, diff --git a/cockatrice/src/game/zones/stack_zone_logic.cpp b/cockatrice/src/game/zones/stack_zone_logic.cpp index 7208a259d..2120b9a1d 100644 --- a/cockatrice/src/game/zones/stack_zone_logic.cpp +++ b/cockatrice/src/game/zones/stack_zone_logic.cpp @@ -3,7 +3,7 @@ #include "../board/card_item.h" #include "card_zone_algorithms.h" -StackZoneLogic::StackZoneLogic(Player *_player, +StackZoneLogic::StackZoneLogic(PlayerLogic *_player, const QString &_name, bool _hasCardAttr, bool _isShufflable, diff --git a/cockatrice/src/game/zones/stack_zone_logic.h b/cockatrice/src/game/zones/stack_zone_logic.h index 81b9d6969..a0ac65ebf 100644 --- a/cockatrice/src/game/zones/stack_zone_logic.h +++ b/cockatrice/src/game/zones/stack_zone_logic.h @@ -12,7 +12,7 @@ class StackZoneLogic : public CardZoneLogic { Q_OBJECT public: - StackZoneLogic(Player *_player, + StackZoneLogic(PlayerLogic *_player, const QString &_name, bool _hasCardAttr, bool _isShufflable, diff --git a/cockatrice/src/game/zones/table_zone_logic.cpp b/cockatrice/src/game/zones/table_zone_logic.cpp index e6c9b8101..3d7ac4297 100644 --- a/cockatrice/src/game/zones/table_zone_logic.cpp +++ b/cockatrice/src/game/zones/table_zone_logic.cpp @@ -2,7 +2,7 @@ #include "../board/card_item.h" -TableZoneLogic::TableZoneLogic(Player *_player, +TableZoneLogic::TableZoneLogic(PlayerLogic *_player, const QString &_name, bool _hasCardAttr, bool _isShufflable, diff --git a/cockatrice/src/game/zones/table_zone_logic.h b/cockatrice/src/game/zones/table_zone_logic.h index e173bc637..1e473d4ef 100644 --- a/cockatrice/src/game/zones/table_zone_logic.h +++ b/cockatrice/src/game/zones/table_zone_logic.h @@ -16,7 +16,7 @@ signals: void toggleTapped(); public: - TableZoneLogic(Player *_player, + TableZoneLogic(PlayerLogic *_player, const QString &_name, bool _hasCardAttr, bool _isShufflable, diff --git a/cockatrice/src/game/zones/view_zone_logic.cpp b/cockatrice/src/game/zones/view_zone_logic.cpp index d025fc841..fa4a73d38 100644 --- a/cockatrice/src/game/zones/view_zone_logic.cpp +++ b/cockatrice/src/game/zones/view_zone_logic.cpp @@ -9,7 +9,7 @@ * @param _revealZone if false, the cards will be face down. * @param _writeableRevealZone whether the player can interact with the revealed cards. */ -ZoneViewZoneLogic::ZoneViewZoneLogic(Player *_player, +ZoneViewZoneLogic::ZoneViewZoneLogic(PlayerLogic *_player, CardZoneLogic *_origZone, int _numberCards, bool _revealZone, diff --git a/cockatrice/src/game/zones/view_zone_logic.h b/cockatrice/src/game/zones/view_zone_logic.h index 6bd5ecc8d..ef0fb37f3 100644 --- a/cockatrice/src/game/zones/view_zone_logic.h +++ b/cockatrice/src/game/zones/view_zone_logic.h @@ -30,7 +30,7 @@ public: REMOVE_CARD }; - ZoneViewZoneLogic(Player *_player, + ZoneViewZoneLogic(PlayerLogic *_player, CardZoneLogic *_origZone, int _numberCards, bool _revealZone, diff --git a/cockatrice/src/game_graphics/zones/hand_zone.cpp b/cockatrice/src/game_graphics/zones/hand_zone.cpp index 8bae6ed0a..09e9a5091 100644 --- a/cockatrice/src/game_graphics/zones/hand_zone.cpp +++ b/cockatrice/src/game_graphics/zones/hand_zone.cpp @@ -3,8 +3,8 @@ #include "../../client/settings/cache_settings.h" #include "../../game/board/card_drag_item.h" #include "../../game/board/card_item.h" -#include "../../game/player/player.h" #include "../../game/player/player_actions.h" +#include "../../game/player/player_logic.h" #include "../../interface/theme_manager.h" #include diff --git a/cockatrice/src/game_graphics/zones/pile_zone.cpp b/cockatrice/src/game_graphics/zones/pile_zone.cpp index cbc312d0c..302b983d8 100644 --- a/cockatrice/src/game_graphics/zones/pile_zone.cpp +++ b/cockatrice/src/game_graphics/zones/pile_zone.cpp @@ -2,8 +2,8 @@ #include "../../game/board/card_drag_item.h" #include "../../game/board/card_item.h" -#include "../../game/player/player.h" #include "../../game/player/player_actions.h" +#include "../../game/player/player_logic.h" #include "../../game/zones/pile_zone_logic.h" #include "view_zone.h" diff --git a/cockatrice/src/game_graphics/zones/stack_zone.cpp b/cockatrice/src/game_graphics/zones/stack_zone.cpp index b4c00e04e..9b0545b1d 100644 --- a/cockatrice/src/game_graphics/zones/stack_zone.cpp +++ b/cockatrice/src/game_graphics/zones/stack_zone.cpp @@ -3,8 +3,8 @@ #include "../../game/board/card_drag_item.h" #include "../../game/board/card_item.h" #include "../../game/card_dimensions.h" -#include "../../game/player/player.h" #include "../../game/player/player_actions.h" +#include "../../game/player/player_logic.h" #include "../../game/zones/stack_zone_logic.h" #include "../../interface/theme_manager.h" diff --git a/cockatrice/src/game_graphics/zones/table_zone.cpp b/cockatrice/src/game_graphics/zones/table_zone.cpp index d428a8a33..ffb4adf5c 100644 --- a/cockatrice/src/game_graphics/zones/table_zone.cpp +++ b/cockatrice/src/game_graphics/zones/table_zone.cpp @@ -4,8 +4,8 @@ #include "../../game/board/arrow_item.h" #include "../../game/board/card_drag_item.h" #include "../../game/board/card_item.h" -#include "../../game/player/player.h" #include "../../game/player/player_actions.h" +#include "../../game/player/player_logic.h" #include "../../game/z_values.h" #include "../../game/zones/table_zone_logic.h" #include "../../interface/theme_manager.h" diff --git a/cockatrice/src/game_graphics/zones/view_zone.cpp b/cockatrice/src/game_graphics/zones/view_zone.cpp index 185c1cc6e..805c60638 100644 --- a/cockatrice/src/game_graphics/zones/view_zone.cpp +++ b/cockatrice/src/game_graphics/zones/view_zone.cpp @@ -2,8 +2,8 @@ #include "../../game/board/card_drag_item.h" #include "../../game/board/card_item.h" -#include "../../game/player/player.h" #include "../../game/player/player_actions.h" +#include "../../game/player/player_logic.h" #include "../../game/zones/view_zone_logic.h" #include diff --git a/cockatrice/src/game_graphics/zones/view_zone_widget.cpp b/cockatrice/src/game_graphics/zones/view_zone_widget.cpp index a0e63bea0..03c6d8925 100644 --- a/cockatrice/src/game_graphics/zones/view_zone_widget.cpp +++ b/cockatrice/src/game_graphics/zones/view_zone_widget.cpp @@ -4,8 +4,8 @@ #include "../../filters/syntax_help.h" #include "../../game/board/card_item.h" #include "../../game/game_scene.h" -#include "../../game/player/player.h" #include "../../game/player/player_actions.h" +#include "../../game/player/player_logic.h" #include "../../game/z_values.h" #include "../../interface/pixel_map_generator.h" #include "view_zone.h" @@ -37,7 +37,7 @@ constexpr qreal kMinVisibleWidth = 100.0; * @param _revealZone if false, the cards will be face down. * @param _writeableRevealZone whether the player can interact with the revealed cards. */ -ZoneViewWidget::ZoneViewWidget(Player *_player, +ZoneViewWidget::ZoneViewWidget(PlayerLogic *_player, CardZoneLogic *_origZone, int numberCards, bool _revealZone, diff --git a/cockatrice/src/game_graphics/zones/view_zone_widget.h b/cockatrice/src/game_graphics/zones/view_zone_widget.h index f5c29cf7d..6d59a5429 100644 --- a/cockatrice/src/game_graphics/zones/view_zone_widget.h +++ b/cockatrice/src/game_graphics/zones/view_zone_widget.h @@ -20,7 +20,7 @@ class QLabel; class QPushButton; class CardZone; class ZoneViewZone; -class Player; +class PlayerLogic; class CardDatabase; class QScrollBar; class GameScene; @@ -65,7 +65,7 @@ private: bool canBeShuffled; int extraHeight; - Player *player; + PlayerLogic *player; bool draggingWindow = false; QPoint dragStartScreenPos; @@ -108,7 +108,7 @@ private slots: void expandWindow(); public: - ZoneViewWidget(Player *_player, + ZoneViewWidget(PlayerLogic *_player, CardZoneLogic *_origZone, int numberCards = 0, bool _revealZone = false, @@ -119,7 +119,7 @@ public: { return zone; } - Player *getPlayer() const + PlayerLogic *getPlayer() const { return player; } diff --git a/cockatrice/src/interface/widgets/tabs/tab_game.cpp b/cockatrice/src/interface/widgets/tabs/tab_game.cpp index 90756dad2..4dc1d1cb1 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_game.cpp +++ b/cockatrice/src/interface/widgets/tabs/tab_game.cpp @@ -10,8 +10,8 @@ #include "../game/game_view.h" #include "../game/log/message_log_widget.h" #include "../game/phases_toolbar.h" -#include "../game/player/player.h" #include "../game/player/player_list_widget.h" +#include "../game/player/player_logic.h" #include "../game/replay.h" #include "../interface/card_picture_loader/card_picture_loader.h" #include "../interface/widgets/cards/card_info_frame_widget.h" @@ -363,7 +363,7 @@ void TabGame::retranslateUi() cardInfoFrameWidget->retranslateUi(); - QMapIterator i(game->getPlayerManager()->getPlayers()); + QMapIterator i(game->getPlayerManager()->getPlayers()); while (i.hasNext()) { i.next().value()->getGraphicsItem()->retranslateUi(); @@ -489,7 +489,7 @@ void TabGame::actGameInfo() void TabGame::actConcede() { - Player *player = game->getPlayerManager()->getActiveLocalPlayer(game->getGameState()->getActivePlayer()); + PlayerLogic *player = game->getPlayerManager()->getActiveLocalPlayer(game->getGameState()->getActivePlayer()); if (player == nullptr) { return; } @@ -606,9 +606,9 @@ void TabGame::actNextPhaseAction() void TabGame::actRemoveLocalArrows() { - QMapIterator playerIterator(game->getPlayerManager()->getPlayers()); + QMapIterator playerIterator(game->getPlayerManager()->getPlayers()); while (playerIterator.hasNext()) { - Player *player = playerIterator.next().value(); + PlayerLogic *player = playerIterator.next().value(); if (!player->getPlayerInfo()->getLocal()) { continue; } @@ -655,14 +655,14 @@ void TabGame::notifyPlayerKicked() msgBox.exec(); } -Player *TabGame::addPlayer(Player *newPlayer) +PlayerLogic *TabGame::addPlayer(PlayerLogic *newPlayer) { QString newPlayerName = "@" + newPlayer->getPlayerInfo()->getName(); addPlayerToAutoCompleteList(newPlayerName); scene->addPlayer(newPlayer); - connect(newPlayer, &Player::newCardAdded, this, &TabGame::newCardAdded); + connect(newPlayer, &PlayerLogic::newCardAdded, this, &TabGame::newCardAdded); connect(newPlayer->getPlayerMenu(), &PlayerMenu::cardMenuUpdated, this, &TabGame::setCardMenu); messageLog->connectToPlayerEventHandler(newPlayer->getPlayerEventHandler()); @@ -683,7 +683,7 @@ Player *TabGame::addPlayer(Player *newPlayer) return newPlayer; } -void TabGame::addLocalPlayer(Player *newPlayer, int playerId) +void TabGame::addLocalPlayer(PlayerLogic *newPlayer, int playerId) { if (game->getGameState()->getClients().size() == 1) { newPlayer->getPlayerMenu()->setShortcutsActive(); @@ -704,7 +704,7 @@ void TabGame::addLocalPlayer(Player *newPlayer, int playerId) } } -void TabGame::processPlayerLeave(Player *leavingPlayer) +void TabGame::processPlayerLeave(PlayerLogic *leavingPlayer) { QString playerName = "@" + leavingPlayer->getPlayerInfo()->getName(); removePlayerFromAutoCompleteList(playerName); @@ -751,13 +751,13 @@ void TabGame::processMultipleRemotePlayerDeckSelect(QVectorplayerDeckView->setReadyStart(ready); } -void TabGame::createZoneForPlayer(Player *newPlayer, int playerId) +void TabGame::createZoneForPlayer(PlayerLogic *newPlayer, int playerId) { if (!game->getPlayerManager()->getSpectators().contains(playerId)) { @@ -820,7 +820,7 @@ void TabGame::startGame(bool _resuming) mainWidget->setCurrentWidget(gamePlayAreaWidget); if (!_resuming) { - QMapIterator playerIterator(game->getPlayerManager()->getPlayers()); + QMapIterator playerIterator(game->getPlayerManager()->getPlayers()); while (playerIterator.hasNext()) { playerIterator.next().value()->setGameStarted(); } @@ -863,15 +863,15 @@ void TabGame::closeGame() gameMenu->addAction(aLeaveGame); } -Player *TabGame::setActivePlayer(int id) +PlayerLogic *TabGame::setActivePlayer(int id) { - Player *player = game->getPlayerManager()->getPlayer(id); + PlayerLogic *player = game->getPlayerManager()->getPlayer(id); if (!player) { return nullptr; } playerListWidget->setActivePlayer(id); - QMapIterator i(game->getPlayerManager()->getPlayers()); + QMapIterator i(game->getPlayerManager()->getPlayers()); while (i.hasNext()) { i.next(); if (i.value() == player) { diff --git a/cockatrice/src/interface/widgets/tabs/tab_game.h b/cockatrice/src/interface/widgets/tabs/tab_game.h index d8746ccc9..66f23ba09 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_game.h +++ b/cockatrice/src/interface/widgets/tabs/tab_game.h @@ -11,7 +11,7 @@ #include "../game/abstract_game.h" #include "../game/log/message_log_widget.h" -#include "../game/player/player.h" +#include "../game/player/player_logic.h" #include "../interface/widgets/menus/tearoff_menu.h" #include "../interface/widgets/replay/replay_manager.h" #include "tab.h" @@ -99,21 +99,21 @@ private: QMap dockToActions; - Player *addPlayer(Player *newPlayer); - void addLocalPlayer(Player *newPlayer, int playerId); + PlayerLogic *addPlayer(PlayerLogic *newPlayer); + void addLocalPlayer(PlayerLogic *newPlayer, int playerId); void processRemotePlayerDeckSelect(QString deckList, int playerId, QString playerName); void processMultipleRemotePlayerDeckSelect(QVector>> playerIdDeckMap); - void processLocalPlayerDeckSelect(Player *localPlayer, int playerId, ServerInfo_Player playerInfo); - void loadDeckForLocalPlayer(Player *localPlayer, int playerId, ServerInfo_Player playerInfo); + void processLocalPlayerDeckSelect(PlayerLogic *localPlayer, int playerId, ServerInfo_Player playerInfo); + void loadDeckForLocalPlayer(PlayerLogic *localPlayer, int playerId, ServerInfo_Player playerInfo); void processLocalPlayerReady(int playerId, ServerInfo_Player playerInfo); - void createZoneForPlayer(Player *newPlayer, int playerId); + void createZoneForPlayer(PlayerLogic *newPlayer, int playerId); void startGame(bool resuming); void stopGame(); void closeGame(); bool leaveGame(); - Player *setActivePlayer(int id); + PlayerLogic *setActivePlayer(int id); void setActivePhase(int phase); void createMenuItems(); void createReplayMenuItems(); @@ -163,7 +163,7 @@ private slots: void actCompleterChanged(); void notifyPlayerJoin(QString playerName); void notifyPlayerKicked(); - void processPlayerLeave(Player *leavingPlayer); + void processPlayerLeave(PlayerLogic *leavingPlayer); void actResetLayout(); void hideEvent(QHideEvent *event) override; From 10b9a65f1748c5399eb473e71947bef66fb8ae59 Mon Sep 17 00:00:00 2001 From: RickyRister <42636155+RickyRister@users.noreply.github.com> Date: Wed, 20 May 2026 02:23:02 -0700 Subject: [PATCH 28/51] [Server][Game] Make undo draw failure visible in chat (#6889) * [Server][Game] Make undo draw failure visible in chat * genericize the proto --- .../src/game/log/message_log_widget.cpp | 7 +++++++ cockatrice/src/game/log/message_log_widget.h | 1 + .../src/game/player/player_event_handler.cpp | 16 +++++++++++++++ .../src/game/player/player_event_handler.h | 4 ++++ .../server/remote/game/server_player.cpp | 4 ++++ .../libcockatrice/protocol/pb/CMakeLists.txt | 1 + .../protocol/pb/event_game_log_notice.proto | 20 +++++++++++++++++++ .../protocol/pb/game_event.proto | 1 + 8 files changed, 54 insertions(+) create mode 100644 libcockatrice_protocol/libcockatrice/protocol/pb/event_game_log_notice.proto diff --git a/cockatrice/src/game/log/message_log_widget.cpp b/cockatrice/src/game/log/message_log_widget.cpp index 53f671256..fe564b531 100644 --- a/cockatrice/src/game/log/message_log_widget.cpp +++ b/cockatrice/src/game/log/message_log_widget.cpp @@ -806,6 +806,12 @@ void MessageLogWidget::logUndoDraw(PlayerLogic *player, QString cardName) } } +void MessageLogWidget::logUndoDrawFailed(PlayerLogic *player) +{ + appendHtmlServerMessage( + tr("%1 failed to undo their last draw.").arg(sanitizeHtml(player->getPlayerInfo()->getName()))); +} + void MessageLogWidget::setContextJudgeName(QString name) { messagePrefix = QString(""); @@ -839,6 +845,7 @@ void MessageLogWidget::connectToPlayerEventHandler(PlayerEventHandler *playerEve connect(playerEventHandler, &PlayerEventHandler::logDumpZone, this, &MessageLogWidget::logDumpZone); connect(playerEventHandler, &PlayerEventHandler::logDrawCards, this, &MessageLogWidget::logDrawCards); connect(playerEventHandler, &PlayerEventHandler::logUndoDraw, this, &MessageLogWidget::logUndoDraw); + connect(playerEventHandler, &PlayerEventHandler::logUndoDrawFailed, this, &MessageLogWidget::logUndoDrawFailed); connect(playerEventHandler, &PlayerEventHandler::logRevealCards, this, &MessageLogWidget::logRevealCards); connect(playerEventHandler, &PlayerEventHandler::logAlwaysRevealTopCard, this, &MessageLogWidget::logAlwaysRevealTopCard); diff --git a/cockatrice/src/game/log/message_log_widget.h b/cockatrice/src/game/log/message_log_widget.h index 25db21864..f8d70a52e 100644 --- a/cockatrice/src/game/log/message_log_widget.h +++ b/cockatrice/src/game/log/message_log_widget.h @@ -99,6 +99,7 @@ public slots: void logSpectatorSay(const ServerInfo_User &spectator, QString message); void logUnattachCard(PlayerLogic *player, QString cardName); void logUndoDraw(PlayerLogic *player, QString cardName); + void logUndoDrawFailed(PlayerLogic *player); void setContextJudgeName(QString player); void appendHtmlServerMessage(const QString &html, bool optionalIsBold = false, diff --git a/cockatrice/src/game/player/player_event_handler.cpp b/cockatrice/src/game/player/player_event_handler.cpp index 244929338..15c40c638 100644 --- a/cockatrice/src/game/player/player_event_handler.cpp +++ b/cockatrice/src/game/player/player_event_handler.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -581,6 +582,18 @@ void PlayerEventHandler::eventChangeZoneProperties(const Event_ChangeZonePropert } } +void PlayerEventHandler::eventGameLogNotice(const Event_GameLogNotice &event) +{ + Event_GameLogNotice::NoticeType type = event.notice_type(); + switch (type) { + case Event_GameLogNotice::UNDO_DRAW_FAILED: + emit logUndoDrawFailed(player); + break; + default: + qWarning() << "Received Event_GameLogNotice with unknown noticeType: " << type; + } +} + void PlayerEventHandler::processGameEvent(GameEvent::GameEventType type, const GameEvent &event, const GameEventContext &context, @@ -644,6 +657,9 @@ void PlayerEventHandler::processGameEvent(GameEvent::GameEventType type, case GameEvent::CHANGE_ZONE_PROPERTIES: eventChangeZoneProperties(event.GetExtension(Event_ChangeZoneProperties::ext)); break; + case GameEvent::GAME_LOG_NOTICE: + eventGameLogNotice(event.GetExtension(Event_GameLogNotice::ext)); + break; default: { qWarning() << "unhandled game event" << type; } diff --git a/cockatrice/src/game/player/player_event_handler.h b/cockatrice/src/game/player/player_event_handler.h index ae3d9aaae..c9bdb98ae 100644 --- a/cockatrice/src/game/player/player_event_handler.h +++ b/cockatrice/src/game/player/player_event_handler.h @@ -35,6 +35,8 @@ class Event_SetCardAttr; class Event_SetCardCounter; class Event_SetCounter; class Event_Shuffle; +class Event_GameLogNotice; + class PlayerEventHandler : public QObject { @@ -52,6 +54,7 @@ signals: void logCreateToken(PlayerLogic *player, QString cardName, QString pt, bool faceDown); void logDrawCards(PlayerLogic *player, int number, bool deckIsEmpty); void logUndoDraw(PlayerLogic *player, QString cardName); + void logUndoDrawFailed(PlayerLogic *player); void logMoveCard(PlayerLogic *player, CardItem *card, CardZoneLogic *startZone, @@ -108,6 +111,7 @@ public: void eventDrawCards(const Event_DrawCards &event); void eventRevealCards(const Event_RevealCards &event, EventProcessingOptions options); void eventChangeZoneProperties(const Event_ChangeZoneProperties &event); + void eventGameLogNotice(const Event_GameLogNotice &event); private: PlayerLogic *player; diff --git a/libcockatrice_network/libcockatrice/network/server/remote/game/server_player.cpp b/libcockatrice_network/libcockatrice/network/server/remote/game/server_player.cpp index 1175e4b57..a1a0a3b3a 100644 --- a/libcockatrice_network/libcockatrice/network/server/remote/game/server_player.cpp +++ b/libcockatrice_network/libcockatrice/network/server/remote/game/server_player.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -409,6 +410,9 @@ Server_Player::cmdUndoDraw(const Command_UndoDraw & /*cmd*/, ResponseContainer & } if (lastDrawList.isEmpty()) { + Event_GameLogNotice event; + event.set_notice_type(Event_GameLogNotice::UNDO_DRAW_FAILED); + ges.enqueueGameEvent(event, playerId); return Response::RespContextError; } diff --git a/libcockatrice_protocol/libcockatrice/protocol/pb/CMakeLists.txt b/libcockatrice_protocol/libcockatrice/protocol/pb/CMakeLists.txt index 212ab69dd..b4c7b6ac8 100644 --- a/libcockatrice_protocol/libcockatrice/protocol/pb/CMakeLists.txt +++ b/libcockatrice_protocol/libcockatrice/protocol/pb/CMakeLists.txt @@ -76,6 +76,7 @@ set(PROTO_FILES event_game_closed.proto event_game_host_changed.proto event_game_joined.proto + event_game_log_notice.proto event_game_say.proto event_game_state_changed.proto event_game_state_changed.proto diff --git a/libcockatrice_protocol/libcockatrice/protocol/pb/event_game_log_notice.proto b/libcockatrice_protocol/libcockatrice/protocol/pb/event_game_log_notice.proto new file mode 100644 index 000000000..ef0dcc102 --- /dev/null +++ b/libcockatrice_protocol/libcockatrice/protocol/pb/event_game_log_notice.proto @@ -0,0 +1,20 @@ +syntax = "proto2"; +import "game_event.proto"; + +// Notifies clients of an event that happened, and which could safely be dropped without affect the game state. +// This mostly just means events that should cause a message to be logged to chat. +message Event_GameLogNotice { + + // The type of the notice. + // Clients who do not recognize the type should drop the event. + enum NoticeType { + // Player's "undo draw" command failed due to losing track of recent draw + UNDO_DRAW_FAILED = 1; + } + + extend GameEvent { + optional Event_GameLogNotice ext = 2022; + } + + optional NoticeType notice_type = 1; +} diff --git a/libcockatrice_protocol/libcockatrice/protocol/pb/game_event.proto b/libcockatrice_protocol/libcockatrice/protocol/pb/game_event.proto index 8682128af..7d3147701 100644 --- a/libcockatrice_protocol/libcockatrice/protocol/pb/game_event.proto +++ b/libcockatrice_protocol/libcockatrice/protocol/pb/game_event.proto @@ -33,6 +33,7 @@ message GameEvent { // STOP_DUMP_ZONE = 2019; // obsolete CHANGE_ZONE_PROPERTIES = 2020; REVERSE_TURN = 2021; + GAME_LOG_NOTICE = 2022; } optional sint32 player_id = 1 [default = -1]; extensions 100 to max; From 0549892092717dedff51c5da380574d52938f92f Mon Sep 17 00:00:00 2001 From: RickyRister <42636155+RickyRister@users.noreply.github.com> Date: Wed, 20 May 2026 14:00:47 -0700 Subject: [PATCH 29/51] [Settings] Regroup card layout settings (#6914) --- .../appearance_settings_page.cpp | 55 +++++++++++-------- .../settings_page/appearance_settings_page.h | 1 + 2 files changed, 33 insertions(+), 23 deletions(-) diff --git a/cockatrice/src/interface/widgets/settings_page/appearance_settings_page.cpp b/cockatrice/src/interface/widgets/settings_page/appearance_settings_page.cpp index 29a2db1ae..2d32f3ce1 100644 --- a/cockatrice/src/interface/widgets/settings_page/appearance_settings_page.cpp +++ b/cockatrice/src/interface/widgets/settings_page/appearance_settings_page.cpp @@ -156,6 +156,25 @@ AppearanceSettingsPage::AppearanceSettingsPage() roundCardCornersCheckBox.setChecked(settings.getRoundCardCorners()); connect(&roundCardCornersCheckBox, &QAbstractButton::toggled, &settings, &SettingsCache::setRoundCardCorners); + connect(&maxFontSizeForCardsEdit, qOverload(&QSpinBox::valueChanged), &settings, + &SettingsCache::setMaxFontSize); + maxFontSizeForCardsEdit.setValue(settings.getMaxFontSize()); + maxFontSizeForCardsLabel.setBuddy(&maxFontSizeForCardsEdit); + maxFontSizeForCardsEdit.setMinimum(9); + maxFontSizeForCardsEdit.setMaximum(100); + + auto *cardsGrid = new QGridLayout; + cardsGrid->addWidget(&displayCardNamesCheckBox, 0, 0, 1, 2); + cardsGrid->addWidget(&autoRotateSidewaysLayoutCardsCheckBox, 1, 0, 1, 2); + cardsGrid->addWidget(&cardScalingCheckBox, 2, 0, 1, 2); + cardsGrid->addWidget(&roundCardCornersCheckBox, 3, 0, 1, 2); + cardsGrid->addWidget(&maxFontSizeForCardsLabel, 4, 0, 1, 1); + cardsGrid->addWidget(&maxFontSizeForCardsEdit, 4, 1, 1, 1); + + cardsGroupBox = new QGroupBox; + cardsGroupBox->setLayout(cardsGrid); + + // Card layout verticalCardOverlapPercentBox.setValue(settings.getStackCardOverlapPercent()); verticalCardOverlapPercentBox.setRange(0, 80); connect(&verticalCardOverlapPercentBox, qOverload(&QSpinBox::valueChanged), &settings, @@ -171,20 +190,16 @@ AppearanceSettingsPage::AppearanceSettingsPage() connect(&cardViewExpandedRowsMaxBox, qOverload(&QSpinBox::valueChanged), this, &AppearanceSettingsPage::cardViewExpandedRowsMaxChanged); - auto *cardsGrid = new QGridLayout; - cardsGrid->addWidget(&displayCardNamesCheckBox, 0, 0, 1, 2); - cardsGrid->addWidget(&autoRotateSidewaysLayoutCardsCheckBox, 1, 0, 1, 2); - cardsGrid->addWidget(&cardScalingCheckBox, 2, 0, 1, 2); - cardsGrid->addWidget(&roundCardCornersCheckBox, 3, 0, 1, 2); - cardsGrid->addWidget(&verticalCardOverlapPercentLabel, 4, 0, 1, 1); - cardsGrid->addWidget(&verticalCardOverlapPercentBox, 4, 1, 1, 1); - cardsGrid->addWidget(&cardViewInitialRowsMaxLabel, 5, 0); - cardsGrid->addWidget(&cardViewInitialRowsMaxBox, 5, 1); - cardsGrid->addWidget(&cardViewExpandedRowsMaxLabel, 6, 0); - cardsGrid->addWidget(&cardViewExpandedRowsMaxBox, 6, 1); + auto *cardLayoutGrid = new QGridLayout; + cardLayoutGrid->addWidget(&verticalCardOverlapPercentLabel, 0, 0, 1, 1); + cardLayoutGrid->addWidget(&verticalCardOverlapPercentBox, 0, 1, 1, 1); + cardLayoutGrid->addWidget(&cardViewInitialRowsMaxLabel, 1, 0); + cardLayoutGrid->addWidget(&cardViewInitialRowsMaxBox, 1, 1); + cardLayoutGrid->addWidget(&cardViewExpandedRowsMaxLabel, 2, 0); + cardLayoutGrid->addWidget(&cardViewExpandedRowsMaxBox, 2, 1); - cardsGroupBox = new QGroupBox; - cardsGroupBox->setLayout(cardsGrid); + cardLayoutGroupBox = new QGroupBox; + cardLayoutGroupBox->setLayout(cardLayoutGrid); // Card counter colors @@ -257,19 +272,10 @@ AppearanceSettingsPage::AppearanceSettingsPage() &SettingsCache::setMinPlayersForMultiColumnLayout); minPlayersForMultiColumnLayoutLabel.setBuddy(&minPlayersForMultiColumnLayoutEdit); - connect(&maxFontSizeForCardsEdit, qOverload(&QSpinBox::valueChanged), &settings, - &SettingsCache::setMaxFontSize); - maxFontSizeForCardsEdit.setValue(settings.getMaxFontSize()); - maxFontSizeForCardsLabel.setBuddy(&maxFontSizeForCardsEdit); - maxFontSizeForCardsEdit.setMinimum(9); - maxFontSizeForCardsEdit.setMaximum(100); - auto *tableGrid = new QGridLayout; tableGrid->addWidget(&invertVerticalCoordinateCheckBox, 0, 0, 1, 2); tableGrid->addWidget(&minPlayersForMultiColumnLayoutLabel, 1, 0, 1, 1); tableGrid->addWidget(&minPlayersForMultiColumnLayoutEdit, 1, 1, 1, 1); - tableGrid->addWidget(&maxFontSizeForCardsLabel, 2, 0, 1, 1); - tableGrid->addWidget(&maxFontSizeForCardsEdit, 2, 1, 1, 1); tableGroupBox = new QGroupBox; tableGroupBox->setLayout(tableGrid); @@ -281,6 +287,7 @@ AppearanceSettingsPage::AppearanceSettingsPage() mainLayout->addWidget(menuGroupBox); mainLayout->addWidget(printingsGroupBox); mainLayout->addWidget(cardsGroupBox); + mainLayout->addWidget(cardLayoutGroupBox); mainLayout->addWidget(cardCountersGroupBox); mainLayout->addWidget(handGroupBox); mainLayout->addWidget(tableGroupBox); @@ -406,6 +413,9 @@ void AppearanceSettingsPage::retranslateUi() autoRotateSidewaysLayoutCardsCheckBox.setText(tr("Auto-Rotate cards with sideways layout")); cardScalingCheckBox.setText(tr("Scale cards on mouse over")); roundCardCornersCheckBox.setText(tr("Use rounded card corners")); + maxFontSizeForCardsLabel.setText(tr("Maximum font size for information displayed on cards:")); + + cardLayoutGroupBox->setTitle(tr("Card layout")); verticalCardOverlapPercentLabel.setText( tr("Minimum overlap percentage of cards on the stack and in vertical hand")); cardViewInitialRowsMaxLabel.setText(tr("Maximum initial height for card view window:")); @@ -427,5 +437,4 @@ void AppearanceSettingsPage::retranslateUi() tableGroupBox->setTitle(tr("Table grid layout")); invertVerticalCoordinateCheckBox.setText(tr("Invert vertical coordinate")); minPlayersForMultiColumnLayoutLabel.setText(tr("Minimum player count for multi-column layout:")); - maxFontSizeForCardsLabel.setText(tr("Maximum font size for information displayed on cards:")); } \ No newline at end of file diff --git a/cockatrice/src/interface/widgets/settings_page/appearance_settings_page.h b/cockatrice/src/interface/widgets/settings_page/appearance_settings_page.h index b9958a286..9ed27be4d 100644 --- a/cockatrice/src/interface/widgets/settings_page/appearance_settings_page.h +++ b/cockatrice/src/interface/widgets/settings_page/appearance_settings_page.h @@ -61,6 +61,7 @@ private: QGroupBox *menuGroupBox; QGroupBox *printingsGroupBox; QGroupBox *cardsGroupBox; + QGroupBox *cardLayoutGroupBox; QGroupBox *handGroupBox; QGroupBox *tableGroupBox; QGroupBox *cardCountersGroupBox; From bddf9bd818462b26abbc96495ddf0dcc9913c113 Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Thu, 21 May 2026 20:16:28 +0200 Subject: [PATCH 30/51] [Game][Counters] Split counters into AbstractCounter (graphics) and CounterState (logic) (#6917) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [Counters] Split counters into graphics and logic states Took 22 minutes * Don't have widget hold pointer to state -> Copy what we need and subscribe to changes. Took 12 minutes Took 5 seconds * Sync value too. Took 3 minutes --------- Co-authored-by: Lukas Brübach --- cockatrice/CMakeLists.txt | 1 + .../src/game/board/abstract_counter.cpp | 129 ++++++++---------- cockatrice/src/game/board/abstract_counter.h | 39 ++++-- cockatrice/src/game/board/counter_general.cpp | 11 +- cockatrice/src/game/board/counter_general.h | 11 +- cockatrice/src/game/board/counter_state.cpp | 24 ++++ cockatrice/src/game/board/counter_state.h | 51 +++++++ .../src/game/player/menu/player_menu.cpp | 30 +--- cockatrice/src/game/player/menu/player_menu.h | 3 + .../src/game/player/player_event_handler.cpp | 2 +- .../src/game/player/player_graphics_item.cpp | 71 ++++++++-- .../src/game/player/player_graphics_item.h | 6 +- cockatrice/src/game/player/player_logic.cpp | 65 ++++----- cockatrice/src/game/player/player_logic.h | 14 +- cockatrice/src/game/player/player_target.cpp | 10 +- cockatrice/src/game/player/player_target.h | 4 +- .../libcockatrice/utility/color.h | 1 + 17 files changed, 273 insertions(+), 199 deletions(-) create mode 100644 cockatrice/src/game/board/counter_state.cpp create mode 100644 cockatrice/src/game/board/counter_state.h diff --git a/cockatrice/CMakeLists.txt b/cockatrice/CMakeLists.txt index 389577d4f..bd79b62c5 100644 --- a/cockatrice/CMakeLists.txt +++ b/cockatrice/CMakeLists.txt @@ -66,6 +66,7 @@ set(cockatrice_SOURCES src/game/board/card_list.cpp src/game/board/card_state.cpp src/game/board/counter_general.cpp + src/game/board/counter_state.cpp src/game/board/translate_counter_name.cpp src/game/deckview/deck_view.cpp src/game/deckview/deck_view_container.cpp diff --git a/cockatrice/src/game/board/abstract_counter.cpp b/cockatrice/src/game/board/abstract_counter.cpp index e0e801ab2..18787a0bc 100644 --- a/cockatrice/src/game/board/abstract_counter.cpp +++ b/cockatrice/src/game/board/abstract_counter.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -16,24 +17,24 @@ #include #include -AbstractCounter::AbstractCounter(PlayerLogic *_player, - int _id, - const QString &_name, +AbstractCounter::AbstractCounter(CounterState *state, + PlayerLogic *_player, bool _shownInCounterArea, - int _value, bool _useNameForShortcut, QGraphicsItem *parent) - : QGraphicsItem(parent), player(_player), id(_id), name(_name), value(_value), - useNameForShortcut(_useNameForShortcut), hovered(false), aDec(nullptr), aInc(nullptr), dialogSemaphore(false), - deleteAfterDialog(false), shownInCounterArea(_shownInCounterArea) + : QGraphicsItem(parent), player(_player), id(state->getId()), name(state->getName()), value(state->getValue()), + color(state->getColor()), radius(state->getRadius()), useNameForShortcut(_useNameForShortcut), + shownInCounterArea(_shownInCounterArea) { setAcceptHoverEvents(true); - shortcutActive = false; + connect(state, &CounterState::valueChanged, this, [this](int, int newValue) { + value = newValue; + update(); + }); if (player->getPlayerInfo()->getLocalOrJudge()) { - QString displayName = TranslateCounterName::getDisplayName(_name); - menu = new TearOffMenu(displayName); + menu = new TearOffMenu(TranslateCounterName::getDisplayName(state->getName())); aSet = new QAction(this); connect(aSet, &QAction::triggered, this, &AbstractCounter::setCounter); menu->addAction(aSet); @@ -41,17 +42,18 @@ AbstractCounter::AbstractCounter(PlayerLogic *_player, for (int i = 10; i >= -10; --i) { if (i == 0) { menu->addSeparator(); - } else { - QAction *aIncrement = new QAction(QString(i < 0 ? "%1" : "+%1").arg(i), this); - if (i == -1) { - aDec = aIncrement; - } else if (i == 1) { - aInc = aIncrement; - } - aIncrement->setData(i); - connect(aIncrement, &QAction::triggered, this, &AbstractCounter::incrementCounter); - menu->addAction(aIncrement); + continue; } + auto *a = new QAction(QString(i < 0 ? "%1" : "+%1").arg(i), this); + if (i == -1) { + aDec = a; + } + if (i == 1) { + aInc = a; + } + a->setData(i); + connect(a, &QAction::triggered, this, &AbstractCounter::incrementCounter); + menu->addAction(a); } } else { menu = nullptr; @@ -79,31 +81,26 @@ void AbstractCounter::delCounter() void AbstractCounter::retranslateUi() { - if (menu) { + if (aSet) { aSet->setText(tr("&Set counter...")); } } void AbstractCounter::setShortcutsActive() { - if (!menu) { + if (!menu || !player->getPlayerInfo()->getLocal()) { return; } - if (!player->getPlayerInfo()->getLocal()) { - return; - } - - ShortcutsSettings &shortcuts = SettingsCache::instance().shortcuts(); + ShortcutsSettings &sc = SettingsCache::instance().shortcuts(); + shortcutActive = true; if (name == "life") { - shortcutActive = true; - aSet->setShortcuts(shortcuts.getShortcut("Player/aSet")); - aDec->setShortcuts(shortcuts.getShortcut("Player/aDec")); - aInc->setShortcuts(shortcuts.getShortcut("Player/aInc")); + aSet->setShortcuts(sc.getShortcut("Player/aSet")); + aDec->setShortcuts(sc.getShortcut("Player/aDec")); + aInc->setShortcuts(sc.getShortcut("Player/aInc")); } else if (useNameForShortcut) { - shortcutActive = true; - aSet->setShortcuts(shortcuts.getShortcut("Player/aSetCounter_" + name)); - aDec->setShortcuts(shortcuts.getShortcut("Player/aDecCounter_" + name)); - aInc->setShortcuts(shortcuts.getShortcut("Player/aIncCounter_" + name)); + aSet->setShortcuts(sc.getShortcut("Player/aSetCounter_" + name)); + aDec->setShortcuts(sc.getShortcut("Player/aDecCounter_" + name)); + aInc->setShortcuts(sc.getShortcut("Player/aIncCounter_" + name)); } } @@ -128,45 +125,32 @@ void AbstractCounter::refreshShortcuts() } } -void AbstractCounter::setValue(int _value) -{ - value = _value; - update(); -} - void AbstractCounter::mousePressEvent(QGraphicsSceneMouseEvent *event) { - if (isUnderMouse() && player->getPlayerInfo()->getLocalOrJudge()) { - if (event->button() == Qt::MiddleButton || (QApplication::keyboardModifiers() & Qt::ShiftModifier)) { - if (menu) { - menu->exec(event->screenPos()); - } - event->accept(); - } else if (event->button() == Qt::LeftButton) { - Command_IncCounter cmd; - cmd.set_counter_id(id); - cmd.set_delta(1); - player->getPlayerActions()->sendGameCommand(cmd); - event->accept(); - } else if (event->button() == Qt::RightButton) { - Command_IncCounter cmd; - cmd.set_counter_id(id); - cmd.set_delta(-1); - player->getPlayerActions()->sendGameCommand(cmd); - event->accept(); + if (!isUnderMouse() || !player->getPlayerInfo()->getLocalOrJudge()) { + event->ignore(); + return; + } + + if (event->button() == Qt::MiddleButton || QApplication::keyboardModifiers() & Qt::ShiftModifier) { + if (menu) { + menu->exec(event->screenPos()); } } else { - event->ignore(); + Command_IncCounter cmd; + cmd.set_counter_id(id); + cmd.set_delta(event->button() == Qt::LeftButton ? 1 : -1); + player->getPlayerActions()->sendGameCommand(cmd); } + event->accept(); } -void AbstractCounter::hoverEnterEvent(QGraphicsSceneHoverEvent * /*event*/) +void AbstractCounter::hoverEnterEvent(QGraphicsSceneHoverEvent *) { hovered = true; update(); } - -void AbstractCounter::hoverLeaveEvent(QGraphicsSceneHoverEvent * /*event*/) +void AbstractCounter::hoverLeaveEvent(QGraphicsSceneHoverEvent *) { hovered = false; update(); @@ -174,35 +158,36 @@ void AbstractCounter::hoverLeaveEvent(QGraphicsSceneHoverEvent * /*event*/) void AbstractCounter::incrementCounter() { - const int delta = static_cast(sender())->data().toInt(); Command_IncCounter cmd; cmd.set_counter_id(id); - cmd.set_delta(delta); + cmd.set_delta(static_cast(sender())->data().toInt()); player->getPlayerActions()->sendGameCommand(cmd); } void AbstractCounter::setCounter() { + QWidget *parent = nullptr; + if (auto *view = scene() ? scene()->views().value(0) : nullptr) { + parent = view->window(); + } + dialogSemaphore = true; - AbstractCounterDialog dialog(name, QString::number(value), player->getGame()->getTab()); - const int ok = dialog.exec(); + AbstractCounterDialog dlg(name, QString::number(value), parent); + const int ok = dlg.exec(); + dialogSemaphore = false; if (deleteAfterDialog) { deleteLater(); return; } - dialogSemaphore = false; - if (!ok) { return; } Expression exp(value); - int newValue = static_cast(exp.parse(dialog.textValue())); - Command_SetCounter cmd; cmd.set_counter_id(id); - cmd.set_value(newValue); + cmd.set_value(static_cast(exp.parse(dlg.textValue()))); player->getPlayerActions()->sendGameCommand(cmd); } diff --git a/cockatrice/src/game/board/abstract_counter.h b/cockatrice/src/game/board/abstract_counter.h index 7bc07d41f..57bc43856 100644 --- a/cockatrice/src/game/board/abstract_counter.h +++ b/cockatrice/src/game/board/abstract_counter.h @@ -9,6 +9,7 @@ #include "../../interface/widgets/menus/tearoff_menu.h" #include "../player/menu/abstract_player_component.h" +#include "counter_state.h" #include #include @@ -29,18 +30,22 @@ protected: int id; QString name; int value; - bool useNameForShortcut, hovered; + QColor color; + int radius; + bool hovered = false; + bool useNameForShortcut; void mousePressEvent(QGraphicsSceneMouseEvent *event) override; void hoverEnterEvent(QGraphicsSceneHoverEvent *event) override; void hoverLeaveEvent(QGraphicsSceneHoverEvent *event) override; private: - QAction *aSet, *aDec, *aInc; - TearOffMenu *menu; - bool dialogSemaphore, deleteAfterDialog; + QAction *aSet = nullptr, *aDec = nullptr, *aInc = nullptr; + TearOffMenu *menu = nullptr; + bool dialogSemaphore = false; + bool deleteAfterDialog = false; bool shownInCounterArea; - bool shortcutActive; + bool shortcutActive = false; private slots: void refreshShortcuts(); @@ -48,17 +53,14 @@ private slots: void setCounter(); public: - AbstractCounter(PlayerLogic *_player, - int _id, - const QString &_name, - bool _shownInCounterArea, - int _value, - bool _useNameForShortcut = false, + AbstractCounter(CounterState *state, + PlayerLogic *player, + bool shownInCounterArea, + bool useNameForShortcut = false, QGraphicsItem *parent = nullptr); ~AbstractCounter() override; void retranslateUi() override; - void setValue(int _value); void setShortcutsActive() override; void setShortcutsInactive() override; void delCounter(); @@ -67,7 +69,6 @@ public: { return menu; } - int getId() const { return id; @@ -76,14 +77,22 @@ public: { return name; } - bool getShownInCounterArea() const + QColor getColor() const { - return shownInCounterArea; + return color; + } + int getRadius() const + { + return radius; } int getValue() const { return value; } + bool getShownInCounterArea() const + { + return shownInCounterArea; + } }; class AbstractCounterDialog : public QInputDialog diff --git a/cockatrice/src/game/board/counter_general.cpp b/cockatrice/src/game/board/counter_general.cpp index 7dd0b1f15..5147ede6b 100644 --- a/cockatrice/src/game/board/counter_general.cpp +++ b/cockatrice/src/game/board/counter_general.cpp @@ -5,15 +5,8 @@ #include -GeneralCounter::GeneralCounter(PlayerLogic *_player, - int _id, - const QString &_name, - const QColor &_color, - int _radius, - int _value, - bool useNameForShortcut, - QGraphicsItem *parent) - : AbstractCounter(_player, _id, _name, true, _value, useNameForShortcut, parent), color(_color), radius(_radius) +GeneralCounter::GeneralCounter(CounterState *state, PlayerLogic *player, bool useNameForShortcut, QGraphicsItem *parent) + : AbstractCounter(state, player, true, useNameForShortcut, parent) { setCacheMode(DeviceCoordinateCache); } diff --git a/cockatrice/src/game/board/counter_general.h b/cockatrice/src/game/board/counter_general.h index ac008fa49..db1ee2743 100644 --- a/cockatrice/src/game/board/counter_general.h +++ b/cockatrice/src/game/board/counter_general.h @@ -12,17 +12,10 @@ class GeneralCounter : public AbstractCounter { Q_OBJECT -private: - QColor color; - int radius; public: - GeneralCounter(PlayerLogic *_player, - int _id, - const QString &_name, - const QColor &_color, - int _radius, - int _value, + GeneralCounter(CounterState *state, + PlayerLogic *player, bool useNameForShortcut = false, QGraphicsItem *parent = nullptr); QRectF boundingRect() const override; diff --git a/cockatrice/src/game/board/counter_state.cpp b/cockatrice/src/game/board/counter_state.cpp new file mode 100644 index 000000000..6da18b662 --- /dev/null +++ b/cockatrice/src/game/board/counter_state.cpp @@ -0,0 +1,24 @@ +#include "counter_state.h" + +#include + +CounterState::CounterState(int id, const QString &name, const QColor &color, int radius, int value, QObject *parent) + : QObject(parent), id(id), name(name), color(color), radius(radius), value(value) +{ +} + +CounterState *CounterState::fromProto(const ServerInfo_Counter &counter, QObject *parent) +{ + return new CounterState(counter.id(), QString::fromStdString(counter.name()), + convertColorToQColor(counter.counter_color()), counter.radius(), counter.count(), parent); +} + +void CounterState::setValue(int newValue) +{ + if (newValue == value) { + return; + } + int old = value; + value = newValue; + emit valueChanged(old, newValue); +} \ No newline at end of file diff --git a/cockatrice/src/game/board/counter_state.h b/cockatrice/src/game/board/counter_state.h new file mode 100644 index 000000000..0f2f16b55 --- /dev/null +++ b/cockatrice/src/game/board/counter_state.h @@ -0,0 +1,51 @@ +#ifndef COCKATRICE_COUNTER_STATE_H +#define COCKATRICE_COUNTER_STATE_H + +#include +#include +#include +#include + +class CounterState : public QObject +{ + Q_OBJECT +public: + CounterState(int id, const QString &name, const QColor &color, int radius, int value, QObject *parent = nullptr); + + static CounterState *fromProto(const ServerInfo_Counter &counter, QObject *parent = nullptr); + + int getId() const + { + return id; + } + QString getName() const + { + return name; + } + QColor getColor() const + { + return color; + } + int getRadius() const + { + return radius; + } + int getValue() const + { + return value; + } + + void setValue(int newValue); + +signals: + void valueChanged(int oldValue, int newValue); + +private: + int id; + QString name; + QColor color; + int radius; + int value; +}; + +#endif // COCKATRICE_COUNTER_STATE_H diff --git a/cockatrice/src/game/player/menu/player_menu.cpp b/cockatrice/src/game/player/menu/player_menu.cpp index d04950c96..9e7b91923 100644 --- a/cockatrice/src/game/player/menu/player_menu.cpp +++ b/cockatrice/src/game/player/menu/player_menu.cpp @@ -97,10 +97,7 @@ void PlayerMenu::retranslateUi() countersMenu->setTitle(tr("&Counters")); } - QMapIterator counterIterator(player->getCounters()); - while (counterIterator.hasNext()) { - counterIterator.next().value()->retranslateUi(); - } + emit retranslateRequested(); } void PlayerMenu::refreshShortcuts() @@ -120,30 +117,17 @@ void PlayerMenu::refreshShortcuts() void PlayerMenu::setShortcutsActive() { shortcutsActive = true; - - for (auto *component : managedComponents) { - component->setShortcutsActive(); - } - - // Counters implement AbstractPlayerComponent but are iterated via Player::counters - // (the authoritative source) rather than managedComponents to avoid a redundant - // list that must stay in sync with the map. - QMapIterator counterIterator(player->getCounters()); - while (counterIterator.hasNext()) { - counterIterator.next().value()->setShortcutsActive(); + for (auto *c : managedComponents) { + c->setShortcutsActive(); } + emit shortcutsActivated(); } void PlayerMenu::setShortcutsInactive() { shortcutsActive = false; - - for (auto *component : managedComponents) { - component->setShortcutsInactive(); - } - - QMapIterator counterIterator(player->getCounters()); - while (counterIterator.hasNext()) { - counterIterator.next().value()->setShortcutsInactive(); + for (auto *c : managedComponents) { + c->setShortcutsInactive(); } + emit shortcutsDeactivated(); } \ No newline at end of file diff --git a/cockatrice/src/game/player/menu/player_menu.h b/cockatrice/src/game/player/menu/player_menu.h index 7532ac225..78e810e62 100644 --- a/cockatrice/src/game/player/menu/player_menu.h +++ b/cockatrice/src/game/player/menu/player_menu.h @@ -29,6 +29,9 @@ class PlayerMenu : public QObject signals: void cardMenuUpdated(QMenu *cardMenu); + void shortcutsActivated(); + void shortcutsDeactivated(); + void retranslateRequested(); public slots: void setMenusForGraphicItems(); diff --git a/cockatrice/src/game/player/player_event_handler.cpp b/cockatrice/src/game/player/player_event_handler.cpp index 15c40c638..1345924b6 100644 --- a/cockatrice/src/game/player/player_event_handler.cpp +++ b/cockatrice/src/game/player/player_event_handler.cpp @@ -246,7 +246,7 @@ void PlayerEventHandler::eventCreateCounter(const Event_CreateCounter &event) void PlayerEventHandler::eventSetCounter(const Event_SetCounter &event) { - AbstractCounter *ctr = player->getCounters().value(event.counter_id(), 0); + CounterState *ctr = player->getCounters().value(event.counter_id(), nullptr); if (!ctr) { return; } diff --git a/cockatrice/src/game/player/player_graphics_item.cpp b/cockatrice/src/game/player/player_graphics_item.cpp index eea2434d2..0d4f8c3ed 100644 --- a/cockatrice/src/game/player/player_graphics_item.cpp +++ b/cockatrice/src/game/player/player_graphics_item.cpp @@ -6,6 +6,7 @@ #include "../../game_graphics/zones/table_zone.h" #include "../../interface/widgets/tabs/tab_game.h" #include "../board/abstract_card_item.h" +#include "../board/counter_general.h" #include "../hand_counter.h" PlayerGraphicsItem::PlayerGraphicsItem(PlayerLogic *_player) : player(_player) @@ -18,6 +19,25 @@ PlayerGraphicsItem::PlayerGraphicsItem(PlayerLogic *_player) : player(_player) connect(player, &PlayerLogic::concededChanged, this, [this](int, bool c) { setVisible(!c); }); connect(player, &PlayerLogic::zoneIdChanged, this, [this](int id) { playerArea->setPlayerZoneId(id); }); + connect(player, &PlayerLogic::counterAdded, this, &PlayerGraphicsItem::onCounterAdded); + connect(player, &PlayerLogic::counterRemoved, this, &PlayerGraphicsItem::onCounterRemoved); + + connect(player->getPlayerMenu(), &PlayerMenu::shortcutsActivated, this, [this]() { + for (auto *ctr : counterWidgets) { + ctr->setShortcutsActive(); + } + }); + connect(player->getPlayerMenu(), &PlayerMenu::shortcutsDeactivated, this, [this]() { + for (auto *ctr : counterWidgets) { + ctr->setShortcutsInactive(); + } + }); + connect(player->getPlayerMenu(), &PlayerMenu::retranslateRequested, this, [this]() { + for (auto *ctr : counterWidgets) { + ctr->retranslateUi(); + } + }); + playerArea = new PlayerArea(this); playerTarget = new PlayerTarget(player, playerArea); @@ -43,11 +63,6 @@ void PlayerGraphicsItem::retranslateUi() while (zoneIterator.hasNext()) { emit zoneIterator.next().value()->retranslateUi(); } - - QMapIterator counterIterator(player->getCounters()); - while (counterIterator.hasNext()) { - counterIterator.next().value()->retranslateUi(); - } } void PlayerGraphicsItem::onPlayerActiveChanged(bool _active) @@ -134,20 +149,48 @@ void PlayerGraphicsItem::setMirrored(bool _mirrored) } } +void PlayerGraphicsItem::onCounterAdded(CounterState *state) +{ + AbstractCounter *widget; + if (state->getName() == "life") { + widget = playerTarget->addCounter(state); + } else { + widget = new GeneralCounter(state, player, true, this); + } + counterWidgets.insert(state->getId(), widget); + + if (player->getPlayerMenu()->getCountersMenu() && widget->getMenu()) { + player->getPlayerMenu()->getCountersMenu()->addMenu(widget->getMenu()); + } + + if (player->getPlayerMenu()->getShortcutsActive()) { + widget->setShortcutsActive(); + } + + rearrangeCounters(); +} + +void PlayerGraphicsItem::onCounterRemoved(int counterId) +{ + auto *widget = counterWidgets.take(counterId); + if (!widget) { + return; + } + if (player->getPlayerMenu()->getCountersMenu() && widget->getMenu()) { + player->getPlayerMenu()->getCountersMenu()->removeAction(widget->getMenu()->menuAction()); + } + widget->delCounter(); + rearrangeCounters(); +} + void PlayerGraphicsItem::rearrangeCounters() { - qreal marginTop = 80; - const qreal padding = 5; - qreal ySize = boundingRect().y() + marginTop; - - // Place objects - for (const auto &counter : player->getCounters()) { - AbstractCounter *ctr = counter; - + qreal ySize = boundingRect().y() + 80; + constexpr qreal padding = 5; + for (auto *ctr : counterWidgets.values()) { if (!ctr->getShownInCounterArea()) { continue; } - QRectF br = ctr->boundingRect(); ctr->setPos((counterAreaWidth - br.width()) / 2, ySize); ySize += br.height() + padding; diff --git a/cockatrice/src/game/player/player_graphics_item.h b/cockatrice/src/game/player/player_graphics_item.h index 33c00be4f..264654e9c 100644 --- a/cockatrice/src/game/player/player_graphics_item.h +++ b/cockatrice/src/game/player/player_graphics_item.h @@ -6,6 +6,7 @@ #ifndef COCKATRICE_PLAYER_GRAPHICS_ITEM_H #define COCKATRICE_PLAYER_GRAPHICS_ITEM_H +#include "../board/abstract_counter.h" #include "../game_scene.h" #include "player_logic.h" @@ -102,6 +103,9 @@ public: public slots: void onPlayerActiveChanged(bool _active); + void onCounterAdded(CounterState *state); + void onCounterRemoved(int counterId); + void rearrangeCounters(); void retranslateUi(); signals: @@ -112,6 +116,7 @@ private: PlayerLogic *player; PlayerArea *playerArea; PlayerTarget *playerTarget; + QMap counterWidgets; PileZone *deckZoneGraphicsItem; PileZone *sideboardGraphicsItem; PileZone *graveyardZoneGraphicsItem; @@ -126,7 +131,6 @@ private: private slots: void updateBoundingRect(); void rearrangeZones(); - void rearrangeCounters(); }; #endif // COCKATRICE_PLAYER_GRAPHICS_ITEM_H diff --git a/cockatrice/src/game/player/player_logic.cpp b/cockatrice/src/game/player/player_logic.cpp index 2c09e3634..677cc0d91 100644 --- a/cockatrice/src/game/player/player_logic.cpp +++ b/cockatrice/src/game/player/player_logic.cpp @@ -258,57 +258,52 @@ void PlayerLogic::setDeck(const DeckList &_deck) emit deckChanged(); } -AbstractCounter *PlayerLogic::addCounter(const ServerInfo_Counter &counter) +CounterState *PlayerLogic::addCounter(const ServerInfo_Counter &counter) { return addCounter(counter.id(), QString::fromStdString(counter.name()), convertColorToQColor(counter.counter_color()), counter.radius(), counter.count()); } -AbstractCounter *PlayerLogic::addCounter(int counterId, const QString &name, QColor color, int radius, int value) +CounterState *PlayerLogic::addCounter(int id, const QString &name, const QColor &color, int radius, int value) { - if (counters.contains(counterId)) { + if (counters.contains(id)) { return nullptr; } - - AbstractCounter *ctr; - if (name == "life") { - ctr = getGraphicsItem()->getPlayerTarget()->addCounter(counterId, name, value); - } else { - ctr = new GeneralCounter(this, counterId, name, color, radius, value, true, graphicsItem); - } - counters.insert(counterId, ctr); - - if (playerMenu->getCountersMenu() && ctr->getMenu()) { - playerMenu->getCountersMenu()->addMenu(ctr->getMenu()); - } - if (playerMenu->getShortcutsActive()) { - ctr->setShortcutsActive(); - } - emit rearrangeCounters(); - return ctr; + auto *state = new CounterState(id, name, color, radius, value, this); + counters.insert(id, state); + emit counterAdded(state); + return state; } -void PlayerLogic::delCounter(int counterId) +void PlayerLogic::delCounter(int id) { - AbstractCounter *ctr = counters.value(counterId, 0); - if (!ctr) { + auto *state = counters.take(id); + if (!state) { return; } - - ctr->delCounter(); - counters.remove(counterId); - emit rearrangeCounters(); + emit counterRemoved(id); + state->deleteLater(); } void PlayerLogic::clearCounters() { - QMapIterator counterIterator(counters); - while (counterIterator.hasNext()) { - counterIterator.next().value()->delCounter(); + for (int id : counters.keys()) { + emit counterRemoved(id); } + qDeleteAll(counters); counters.clear(); } +CounterState *PlayerLogic::getLifeCounter() const +{ + for (auto *s : counters.values()) { + if (s->getName() == "life") { + return s; + } + } + return nullptr; +} + void PlayerLogic::incrementAllCardCounters() { auto cardsToUpdate = getGameScene()->selectedCards(); @@ -345,16 +340,6 @@ void PlayerLogic::incrementAllCardCounters() } } -AbstractCounter *PlayerLogic::getLifeCounter() const -{ - for (auto counter : counters.values()) { - if (counter->getName() == "life") { - return counter; - } - } - return nullptr; -} - ArrowItem *PlayerLogic::addArrow(const ServerInfo_Arrow &arrow) { const QMap &playerList = game->getPlayerManager()->getPlayers(); diff --git a/cockatrice/src/game/player/player_logic.h b/cockatrice/src/game/player/player_logic.h index 55599f5e2..01d7052df 100644 --- a/cockatrice/src/game/player/player_logic.h +++ b/cockatrice/src/game/player/player_logic.h @@ -7,7 +7,6 @@ #ifndef PLAYER_H #define PLAYER_H -#include "../../game_graphics/board/abstract_graphics_item.h" #include "../../interface/widgets/menus/tearoff_menu.h" #include "../interface/deck_loader/loaded_deck.h" #include "../zones/hand_zone_logic.h" @@ -39,7 +38,6 @@ class Message; } } // namespace google class AbstractCardItem; -class AbstractCounter; class AbstractGame; class ArrowItem; class ArrowTarget; @@ -70,6 +68,8 @@ signals: void openDeckEditor(const LoadedDeck &deck); void deckChanged(); void newCardAdded(AbstractCardItem *card); + void counterAdded(CounterState *state); + void counterRemoved(int counterId); void rearrangeCounters(); void activeChanged(bool active); void zoneIdChanged(int zoneId); @@ -189,13 +189,13 @@ public: return qobject_cast(zones.value(ZoneNames::HAND)); } - AbstractCounter *addCounter(const ServerInfo_Counter &counter); - AbstractCounter *addCounter(int counterId, const QString &name, QColor color, int radius, int value); + CounterState *addCounter(const ServerInfo_Counter &counter); + CounterState *addCounter(int id, const QString &name, const QColor &color, int radius, int value); void delCounter(int counterId); void clearCounters(); void incrementAllCardCounters(); - QMap getCounters() + QMap getCounters() const { return counters; } @@ -203,7 +203,7 @@ public: /** * Gets the counter that represents the life total. */ - AbstractCounter *getLifeCounter() const; + CounterState *getLifeCounter() const; ArrowItem *addArrow(const ServerInfo_Arrow &arrow); ArrowItem *addArrow(int arrowId, CardItem *startCard, ArrowTarget *targetItem, const QColor &color); @@ -251,7 +251,7 @@ private: int zoneId; QMap zones; - QMap counters; + QMap counters; QMap arrows; bool dialogSemaphore; diff --git a/cockatrice/src/game/player/player_target.cpp b/cockatrice/src/game/player/player_target.cpp index 93f2c05d4..97fd51998 100644 --- a/cockatrice/src/game/player/player_target.cpp +++ b/cockatrice/src/game/player/player_target.cpp @@ -9,8 +9,8 @@ #include #include -PlayerCounter::PlayerCounter(PlayerLogic *_player, int _id, const QString &_name, int _value, QGraphicsItem *parent) - : AbstractCounter(_player, _id, _name, false, _value, false, parent) +PlayerCounter::PlayerCounter(CounterState *state, PlayerLogic *player, QGraphicsItem *parent) + : AbstractCounter(state, player, false, false, parent) { } @@ -150,18 +150,16 @@ void PlayerTarget::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*o } } -AbstractCounter *PlayerTarget::addCounter(int _counterId, const QString &_name, int _value) +AbstractCounter *PlayerTarget::addCounter(CounterState *state) { if (playerCounter) { disconnect(playerCounter, nullptr, this, nullptr); playerCounter->delCounter(); } - - playerCounter = new PlayerCounter(owner, _counterId, _name, _value, this); + playerCounter = new PlayerCounter(state, owner, this); playerCounter->setPos(boundingRect().width() - playerCounter->boundingRect().width(), boundingRect().height() - playerCounter->boundingRect().height()); connect(playerCounter, &PlayerCounter::destroyed, this, &PlayerTarget::counterDeleted); - return playerCounter; } diff --git a/cockatrice/src/game/player/player_target.h b/cockatrice/src/game/player/player_target.h index 3dbc82336..0dd494ce3 100644 --- a/cockatrice/src/game/player/player_target.h +++ b/cockatrice/src/game/player/player_target.h @@ -19,7 +19,7 @@ class PlayerCounter : public AbstractCounter { Q_OBJECT public: - PlayerCounter(PlayerLogic *_player, int _id, const QString &_name, int _value, QGraphicsItem *parent = nullptr); + PlayerCounter(CounterState *state, PlayerLogic *player, QGraphicsItem *parent); QRectF boundingRect() const override; void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override; }; @@ -48,7 +48,7 @@ public: QRectF boundingRect() const override; void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override; - AbstractCounter *addCounter(int _counterId, const QString &_name, int _value); + AbstractCounter *addCounter(CounterState *state); }; #endif diff --git a/libcockatrice_utility/libcockatrice/utility/color.h b/libcockatrice_utility/libcockatrice/utility/color.h index 31bcb3734..6afe984bd 100644 --- a/libcockatrice_utility/libcockatrice/utility/color.h +++ b/libcockatrice_utility/libcockatrice/utility/color.h @@ -22,6 +22,7 @@ inline color convertQColorToColor(const QColor &c) return result; } +#include #include namespace GameSpecificColors From 491d1c91879d67415e858477ff244b67b812f458 Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Thu, 21 May 2026 20:31:14 +0200 Subject: [PATCH 31/51] [Game][Arrows] Split Arrows into ArrowData and ArrowItem (#6918) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [Game][Arrows] Split Arrows into ArrowData and ArrowItem Took 13 minutes Took 5 seconds Took 1 minute Took 26 seconds * Address comments. Took 17 minutes Took 9 seconds Took 1 minute * Change check. Took 3 minutes * Pass by const reference. Took 10 minutes * Remove extra method Took 2 minutes --------- Co-authored-by: Lukas Brübach --- cockatrice/CMakeLists.txt | 1 + cockatrice/src/game/board/arrow_data.cpp | 19 ++ cockatrice/src/game/board/arrow_data.h | 28 +++ cockatrice/src/game/board/arrow_item.cpp | 227 +++++++++--------- cockatrice/src/game/board/arrow_item.h | 34 ++- cockatrice/src/game/board/arrow_target.cpp | 32 +-- cockatrice/src/game/board/arrow_target.h | 35 +-- cockatrice/src/game/game_scene.cpp | 97 +++++++- cockatrice/src/game/game_scene.h | 11 +- .../src/game/player/player_event_handler.cpp | 67 +++--- .../src/game/player/player_event_handler.h | 1 + cockatrice/src/game/player/player_logic.cpp | 75 +----- cockatrice/src/game/player/player_logic.h | 18 +- .../src/interface/widgets/tabs/tab_game.cpp | 18 +- .../src/interface/widgets/tabs/tab_game.h | 1 - 15 files changed, 337 insertions(+), 327 deletions(-) create mode 100644 cockatrice/src/game/board/arrow_data.cpp create mode 100644 cockatrice/src/game/board/arrow_data.h diff --git a/cockatrice/CMakeLists.txt b/cockatrice/CMakeLists.txt index bd79b62c5..0b2192399 100644 --- a/cockatrice/CMakeLists.txt +++ b/cockatrice/CMakeLists.txt @@ -59,6 +59,7 @@ set(cockatrice_SOURCES src/game/board/abstract_card_drag_item.cpp src/game/board/abstract_card_item.cpp src/game/board/abstract_counter.cpp + src/game/board/arrow_data.cpp src/game/board/arrow_item.cpp src/game/board/arrow_target.cpp src/game/board/card_drag_item.cpp diff --git a/cockatrice/src/game/board/arrow_data.cpp b/cockatrice/src/game/board/arrow_data.cpp new file mode 100644 index 000000000..bbb70f474 --- /dev/null +++ b/cockatrice/src/game/board/arrow_data.cpp @@ -0,0 +1,19 @@ +#include "arrow_data.h" + +ArrowData ArrowData::fromProto(const ServerInfo_Arrow &arrow) +{ + ArrowData data; + data.id = arrow.id(); + data.startPlayerId = arrow.start_player_id(); + data.startZone = QString::fromStdString(arrow.start_zone()); + data.startCardId = arrow.start_card_id(); + data.targetPlayerId = arrow.target_player_id(); + data.color = convertColorToQColor(arrow.arrow_color()); + + if (arrow.has_target_zone()) { + data.targetZone = QString::fromStdString(arrow.target_zone()); + data.targetCardId = arrow.target_card_id(); + } + + return data; +} \ No newline at end of file diff --git a/cockatrice/src/game/board/arrow_data.h b/cockatrice/src/game/board/arrow_data.h new file mode 100644 index 000000000..a8b35dad6 --- /dev/null +++ b/cockatrice/src/game/board/arrow_data.h @@ -0,0 +1,28 @@ +#ifndef COCKATRICE_ARROW_DATA_H +#define COCKATRICE_ARROW_DATA_H + +#include +#include +#include +#include + +struct ArrowData +{ + int id; + int startPlayerId; + QString startZone; + int startCardId; + int targetPlayerId; + QString targetZone; // empty = targeting a player + int targetCardId = -1; // -1 = targeting a player + QColor color; + + static ArrowData fromProto(const ServerInfo_Arrow &arrow); + + bool isPlayerTargeted() const + { + return targetZone.isEmpty(); + } +}; + +#endif // COCKATRICE_ARROW_DATA_H diff --git a/cockatrice/src/game/board/arrow_item.cpp b/cockatrice/src/game/board/arrow_item.cpp index b9d01c40e..bfc219a3f 100644 --- a/cockatrice/src/game/board/arrow_item.cpp +++ b/cockatrice/src/game/board/arrow_item.cpp @@ -26,16 +26,23 @@ ArrowItem::ArrowItem(PlayerLogic *_player, ArrowTarget *_startItem, ArrowTarget *_targetItem, const QColor &_color) - : QGraphicsItem(), player(_player), id(_id), startItem(_startItem), targetItem(_targetItem), targetLocked(false), - color(_color), fullColor(true) + : player(_player), id(_id), startItem(_startItem), targetItem(_targetItem), color(_color) { setZValue(ZValues::ARROWS); + auto doUpdate = [this]() { + if (startItem && targetItem) { + updatePath(); + } + }; + if (startItem) { - startItem->addArrowFrom(this); + connect(startItem, &ArrowTarget::scenePositionChanged, this, doUpdate); + connect(startItem, &QObject::destroyed, this, &ArrowItem::delArrow); } if (targetItem) { - targetItem->addArrowTo(this); + connect(targetItem, &ArrowTarget::scenePositionChanged, this, doUpdate); + connect(targetItem, &QObject::destroyed, this, &ArrowItem::delArrow); } if (startItem && targetItem) { @@ -43,24 +50,11 @@ ArrowItem::ArrowItem(PlayerLogic *_player, } } -ArrowItem::~ArrowItem() -{ -} - void ArrowItem::delArrow() { - if (startItem) { - startItem->removeArrowFrom(this); - startItem = 0; - } - if (targetItem) { targetItem->setBeingPointedAt(false); - targetItem->removeArrowTo(this); - targetItem = 0; } - - player->removeArrow(this); deleteLater(); } @@ -148,8 +142,7 @@ void ArrowItem::mousePressEvent(QGraphicsSceneMouseEvent *event) return; } - QList colliding = scene()->items(event->scenePos()); - for (QGraphicsItem *item : colliding) { + for (auto *item : scene()->items(event->scenePos())) { if (qgraphicsitem_cast(item)) { event->ignore(); return; @@ -164,60 +157,62 @@ void ArrowItem::mousePressEvent(QGraphicsSceneMouseEvent *event) } } +// ArrowDragItem + ArrowDragItem::ArrowDragItem(PlayerLogic *_owner, ArrowTarget *_startItem, const QColor &_color, int _deleteInPhase) - : ArrowItem(_owner, -1, _startItem, 0, _color), deleteInPhase(_deleteInPhase) + : ArrowItem(_owner, -1, _startItem, nullptr, _color), deleteInPhase(_deleteInPhase) { } -void ArrowDragItem::addChildArrow(ArrowDragItem *childArrow) +void ArrowDragItem::addChildArrow(ArrowDragItem *child) { - childArrows.append(childArrow); + childArrows.append(child); } void ArrowDragItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { - // This ensures that if a mouse move event happens after a call to delArrow(), - // the event will be discarded as it would create some stray pointers. if (targetLocked || !startItem) { return; } - QPointF endPos = event->scenePos(); + const QPointF endPos = event->scenePos(); - QList colliding = scene()->items(endPos); - ArrowTarget *cursorItem = 0; + ArrowTarget *cursorItem = nullptr; qreal cursorItemZ = -1; - for (int i = colliding.size() - 1; i >= 0; i--) { - if (qgraphicsitem_cast(colliding.at(i)) || qgraphicsitem_cast(colliding.at(i))) { - if (colliding.at(i)->zValue() > cursorItemZ) { - cursorItem = static_cast(colliding.at(i)); - cursorItemZ = cursorItem->zValue(); - } + for (auto *item : scene()->items(endPos)) { + ArrowTarget *candidate = nullptr; + if (auto *card = qgraphicsitem_cast(item)) { + candidate = card; + } else if (auto *pt = qgraphicsitem_cast(item)) { + candidate = pt; + } + + if (candidate && candidate->zValue() > cursorItemZ) { + cursorItem = candidate; + cursorItemZ = candidate->zValue(); } } - if ((cursorItem != targetItem) && targetItem) { - targetItem->setBeingPointedAt(false); - targetItem->removeArrowTo(this); - } - if (!cursorItem) { - fullColor = false; - targetItem = 0; - updatePath(endPos); - } else { - if (cursorItem != targetItem) { - fullColor = true; - if (cursorItem != startItem) { - cursorItem->setBeingPointedAt(true); - cursorItem->addArrowTo(this); - } - targetItem = cursorItem; + if (cursorItem != targetItem) { + if (targetItem) { + disconnect(positionConnection); + targetItem->setBeingPointedAt(false); + } + + targetItem = cursorItem; + fullColor = (cursorItem != nullptr); + + if (cursorItem && cursorItem != startItem) { + cursorItem->setBeingPointedAt(true); + positionConnection = + connect(cursorItem, &ArrowTarget::scenePositionChanged, this, [this]() { updatePath(); }); } - updatePath(); } + + targetItem ? updatePath() : updatePath(endPos); update(); - for (ArrowDragItem *child : childArrows) { + for (auto *child : childArrows) { child->mouseMoveEvent(event); } } @@ -228,12 +223,16 @@ void ArrowDragItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) return; } - if (targetItem && (targetItem != startItem)) { - CardZoneLogic *startZone = static_cast(startItem)->getZone(); + if (targetItem && targetItem != startItem) { + CardItem *startCard = qgraphicsitem_cast(startItem); // For now, we can safely assume that the start item is always a card. // The target item can be a player as well. - CardItem *startCard = qgraphicsitem_cast(startItem); - CardItem *targetCard = qgraphicsitem_cast(targetItem); + if (!startCard) { + delArrow(); + return; + } + + CardZoneLogic *startZone = startCard->getZone(); Command_CreateArrow cmd; cmd.mutable_arrow_color()->CopyFrom(convertQColorToColor(color)); @@ -241,14 +240,16 @@ void ArrowDragItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) cmd.set_start_zone(startZone->getName().toStdString()); cmd.set_start_card_id(startCard->getId()); - if (targetCard) { + if (auto *targetCard = qgraphicsitem_cast(targetItem)) { CardZoneLogic *targetZone = targetCard->getZone(); cmd.set_target_player_id(targetZone->getPlayer()->getPlayerInfo()->getId()); cmd.set_target_zone(targetZone->getName().toStdString()); cmd.set_target_card_id(targetCard->getId()); - } else { // failed to cast target to card, this means it's a player - PlayerTarget *targetPlayer = qgraphicsitem_cast(targetItem); + } else if (auto *targetPlayer = qgraphicsitem_cast(targetItem)) { cmd.set_target_player_id(targetPlayer->getOwner()->getPlayerInfo()->getId()); + } else { + delArrow(); + return; } // if the card is in hand then we will move the card to stack or table as part of drawing the arrow @@ -271,21 +272,22 @@ void ArrowDragItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) player->getPlayerActions()->sendGameCommand(cmd); } - delArrow(); - for (ArrowDragItem *child : childArrows) { + delArrow(); + for (auto *child : childArrows) { child->mouseReleaseEvent(event); } } +// ArrowAttachItem ArrowAttachItem::ArrowAttachItem(ArrowTarget *_startItem) - : ArrowItem(_startItem->getOwner(), -1, _startItem, 0, Qt::green) + : ArrowItem(_startItem->getOwner(), -1, _startItem, nullptr, Qt::green) { } -void ArrowAttachItem::addChildArrow(ArrowAttachItem *childArrow) +void ArrowAttachItem::addChildArrow(ArrowAttachItem *child) { - childArrows.append(childArrow); + childArrows.append(child); } void ArrowAttachItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) @@ -294,67 +296,43 @@ void ArrowAttachItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) return; } - QPointF endPos = event->scenePos(); + const QPointF endPos = event->scenePos(); - QList colliding = scene()->items(endPos); - ArrowTarget *cursorItem = 0; + ArrowTarget *cursorItem = nullptr; qreal cursorItemZ = -1; - for (int i = colliding.size() - 1; i >= 0; i--) { - if (qgraphicsitem_cast(colliding.at(i))) { - if (colliding.at(i)->zValue() > cursorItemZ) { - cursorItem = static_cast(colliding.at(i)); - cursorItemZ = cursorItem->zValue(); + for (auto *item : scene()->items(endPos)) { + if (auto *card = qgraphicsitem_cast(item)) { + if (card->zValue() > cursorItemZ) { + cursorItem = card; + cursorItemZ = card->zValue(); } } } - if ((cursorItem != targetItem) && targetItem) { - targetItem->setBeingPointedAt(false); - } - if (!cursorItem) { - fullColor = false; - targetItem = 0; - updatePath(endPos); - } else { - fullColor = true; - if (cursorItem != startItem) { - cursorItem->setBeingPointedAt(true); + if (cursorItem != targetItem) { + if (targetItem) { + disconnect(positionConnection); + targetItem->setBeingPointedAt(false); } + targetItem = cursorItem; - updatePath(); + fullColor = (cursorItem != nullptr); + + if (cursorItem && cursorItem != startItem) { + cursorItem->setBeingPointedAt(true); + positionConnection = + connect(cursorItem, &ArrowTarget::scenePositionChanged, this, [this]() { updatePath(); }); + } } + + targetItem ? updatePath() : updatePath(endPos); update(); - for (ArrowAttachItem *child : childArrows) { + for (auto *child : childArrows) { child->mouseMoveEvent(event); } } -void ArrowAttachItem::attachCards(CardItem *startCard, const CardItem *targetCard) -{ - // do nothing if target is already attached to another card or is not in play - if (targetCard->getAttachedTo() || targetCard->getZone()->getName() != ZoneNames::TABLE) { - return; - } - - CardZoneLogic *startZone = startCard->getZone(); - CardZoneLogic *targetZone = targetCard->getZone(); - - // move card onto table first if attaching from some other zone - if (startZone->getName() != ZoneNames::TABLE) { - player->getPlayerActions()->playCardToTable(startCard, false); - } - - Command_AttachCard cmd; - cmd.set_start_zone(ZoneNames::TABLE); - cmd.set_card_id(startCard->getId()); - cmd.set_target_player_id(targetZone->getPlayer()->getPlayerInfo()->getId()); - cmd.set_target_zone(targetZone->getName().toStdString()); - cmd.set_target_card_id(targetCard->getId()); - - player->getPlayerActions()->sendGameCommand(cmd); -} - void ArrowAttachItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { if (!startItem) { @@ -363,21 +341,40 @@ void ArrowAttachItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) // Attaching could move startItem under the current cursor position, causing all children to retarget to it right // before they are processed. Prevent that. - for (ArrowAttachItem *child : childArrows) { + for (auto *child : childArrows) { child->setTargetLocked(true); } - if (targetItem && (targetItem != startItem)) { - auto startCard = qgraphicsitem_cast(startItem); - auto targetCard = qgraphicsitem_cast(targetItem); + if (targetItem && targetItem != startItem) { + auto *startCard = qgraphicsitem_cast(startItem); + auto *targetCard = qgraphicsitem_cast(targetItem); if (startCard && targetCard) { attachCards(startCard, targetCard); } } delArrow(); - - for (ArrowAttachItem *child : childArrows) { + for (auto *child : childArrows) { child->mouseReleaseEvent(event); } } + +void ArrowAttachItem::attachCards(CardItem *startCard, const CardItem *targetCard) +{ + if (targetCard->getAttachedTo() || targetCard->getZone()->getName() != ZoneNames::TABLE) { + return; + } + + // move card onto table first if attaching from some other zone + if (startCard->getZone()->getName() != ZoneNames::TABLE) { + player->getPlayerActions()->playCardToTable(startCard, false); + } + + Command_AttachCard cmd; + cmd.set_start_zone(ZoneNames::TABLE); + cmd.set_card_id(startCard->getId()); + cmd.set_target_player_id(targetCard->getZone()->getPlayer()->getPlayerInfo()->getId()); + cmd.set_target_zone(targetCard->getZone()->getName().toStdString()); + cmd.set_target_card_id(targetCard->getId()); + player->getPlayerActions()->sendGameCommand(cmd); +} \ No newline at end of file diff --git a/cockatrice/src/game/board/arrow_item.h b/cockatrice/src/game/board/arrow_item.h index f2de94d2f..43c0d2b91 100644 --- a/cockatrice/src/game/board/arrow_item.h +++ b/cockatrice/src/game/board/arrow_item.h @@ -7,13 +7,15 @@ #ifndef ARROWITEM_H #define ARROWITEM_H +#include "arrow_target.h" + #include +#include class CardItem; class QGraphicsSceneMouseEvent; class QMenu; class PlayerLogic; -class ArrowTarget; class ArrowItem : public QObject, public QGraphicsItem { @@ -21,20 +23,21 @@ class ArrowItem : public QObject, public QGraphicsItem Q_INTERFACES(QGraphicsItem) private: QPainterPath path; - QMenu *menu; protected: PlayerLogic *player; int id; - ArrowTarget *startItem, *targetItem; - bool targetLocked; + QPointer startItem; + QPointer targetItem; + bool targetLocked = false; QColor color; - bool fullColor; + bool fullColor = true; + void mousePressEvent(QGraphicsSceneMouseEvent *event) override; public: - ArrowItem(PlayerLogic *_player, int _id, ArrowTarget *_startItem, ArrowTarget *_targetItem, const QColor &color); - ~ArrowItem() override; + ArrowItem(PlayerLogic *_player, int _id, ArrowTarget *_startItem, ArrowTarget *_targetItem, const QColor &_color); + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override; [[nodiscard]] QRectF boundingRect() const override { @@ -44,6 +47,7 @@ public: { return path; } + void updatePath(); void updatePath(const QPointF &endPoint); @@ -55,14 +59,6 @@ public: { return player; } - void setStartItem(ArrowTarget *_item) - { - startItem = _item; - } - void setTargetItem(ArrowTarget *_item) - { - targetItem = _item; - } [[nodiscard]] ArrowTarget *getStartItem() const { return startItem; @@ -75,6 +71,7 @@ public: { targetLocked = _targetLocked; } + void delArrow(); }; @@ -84,10 +81,11 @@ class ArrowDragItem : public ArrowItem private: int deleteInPhase; QList childArrows; + QMetaObject::Connection positionConnection; public: ArrowDragItem(PlayerLogic *_owner, ArrowTarget *_startItem, const QColor &_color, int _deleteInPhase); - void addChildArrow(ArrowDragItem *childArrow); + void addChildArrow(ArrowDragItem *child); protected: void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override; @@ -99,12 +97,12 @@ class ArrowAttachItem : public ArrowItem Q_OBJECT private: QList childArrows; - + QMetaObject::Connection positionConnection; void attachCards(CardItem *startCard, const CardItem *targetCard); public: explicit ArrowAttachItem(ArrowTarget *_startItem); - void addChildArrow(ArrowAttachItem *childArrow); + void addChildArrow(ArrowAttachItem *child); protected: void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override; diff --git a/cockatrice/src/game/board/arrow_target.cpp b/cockatrice/src/game/board/arrow_target.cpp index bcd067bdb..edf526e4e 100644 --- a/cockatrice/src/game/board/arrow_target.cpp +++ b/cockatrice/src/game/board/arrow_target.cpp @@ -3,41 +3,21 @@ #include "../player/player_logic.h" #include "arrow_item.h" -ArrowTarget::ArrowTarget(PlayerLogic *_owner, QGraphicsItem *parent) - : AbstractGraphicsItem(parent), owner(_owner), beingPointedAt(false) +ArrowTarget::ArrowTarget(PlayerLogic *_owner, QGraphicsItem *parent) : AbstractGraphicsItem(parent), owner(_owner) { setFlag(ItemSendsScenePositionChanges); } -ArrowTarget::~ArrowTarget() -{ - for (int i = 0; i < arrowsFrom.size(); ++i) { - arrowsFrom[i]->setStartItem(0); - arrowsFrom[i]->delArrow(); - } - for (int i = 0; i < arrowsTo.size(); ++i) { - arrowsTo[i]->setTargetItem(0); - arrowsTo[i]->delArrow(); - } -} - void ArrowTarget::setBeingPointedAt(bool _beingPointedAt) { beingPointedAt = _beingPointedAt; update(); } -QVariant ArrowTarget::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) +QVariant ArrowTarget::itemChange(GraphicsItemChange change, const QVariant &value) { - if (change == ItemScenePositionHasChanged && scene()) { - for (auto *arrow : arrowsFrom) { - arrow->updatePath(); - } - - for (auto *arrow : arrowsTo) { - arrow->updatePath(); - } + if (change == ItemScenePositionHasChanged) { + emit scenePositionChanged(); } - - return QGraphicsItem::itemChange(change, value); -} + return AbstractGraphicsItem::itemChange(change, value); +} \ No newline at end of file diff --git a/cockatrice/src/game/board/arrow_target.h b/cockatrice/src/game/board/arrow_target.h index 59ef48277..9c9aaa315 100644 --- a/cockatrice/src/game/board/arrow_target.h +++ b/cockatrice/src/game/board/arrow_target.h @@ -21,12 +21,14 @@ protected: PlayerLogic *owner; private: - bool beingPointedAt; - QList arrowsFrom, arrowsTo; + bool beingPointedAt = false; + +signals: + void scenePositionChanged(); public: explicit ArrowTarget(PlayerLogic *_owner, QGraphicsItem *parent = nullptr); - ~ArrowTarget() override; + ~ArrowTarget() override = default; [[nodiscard]] PlayerLogic *getOwner() const { @@ -39,32 +41,7 @@ public: return beingPointedAt; } - [[nodiscard]] const QList &getArrowsFrom() const - { - return arrowsFrom; - } - void addArrowFrom(ArrowItem *arrow) - { - arrowsFrom.append(arrow); - } - void removeArrowFrom(ArrowItem *arrow) - { - arrowsFrom.removeOne(arrow); - } - [[nodiscard]] const QList &getArrowsTo() const - { - return arrowsTo; - } - void addArrowTo(ArrowItem *arrow) - { - arrowsTo.append(arrow); - } - void removeArrowTo(ArrowItem *arrow) - { - arrowsTo.removeOne(arrow); - } - protected: - QVariant itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) override; + QVariant itemChange(GraphicsItemChange change, const QVariant &value) override; }; #endif diff --git a/cockatrice/src/game/game_scene.cpp b/cockatrice/src/game/game_scene.cpp index 91ac0adc6..71b9caa4b 100644 --- a/cockatrice/src/game/game_scene.cpp +++ b/cockatrice/src/game/game_scene.cpp @@ -82,9 +82,25 @@ void GameScene::addPlayer(PlayerLogic *player) { qCInfo(GameScenePlayerAdditionRemovalLog) << "GameScene::addPlayer name=" << player->getPlayerInfo()->getName(); - players << player->getGraphicsItem(); + playerViews.insert(player->getPlayerInfo()->getId(), player->getGraphicsItem()); addItem(player->getGraphicsItem()); connect(player->getGraphicsItem(), &PlayerGraphicsItem::sizeChanged, this, &GameScene::rearrange); + + connect(player, &PlayerLogic::concededChanged, this, [this](int id, bool conceded) { + if (conceded) { + clearArrowsForPlayer(id); + } + rearrange(); + }); + + connect(player, &PlayerLogic::arrowCreateRequested, this, &GameScene::onArrowCreateRequested); + connect(player, &PlayerLogic::arrowDeleteRequested, this, &GameScene::onArrowDeleteRequested); + connect(player, &PlayerLogic::arrowsCleared, this, + [this, id = player->getPlayerInfo()->getId()]() { clearArrowsForPlayer(id); }); + + connect(player->getPlayerEventHandler(), &PlayerEventHandler::cardZoneChanged, this, &GameScene::onCardZoneChanged); + + rearrange(); } /** @@ -97,13 +113,15 @@ void GameScene::removePlayer(PlayerLogic *player) { qCInfo(GameScenePlayerAdditionRemovalLog) << "GameScene::removePlayer name=" << player->getPlayerInfo()->getName(); + clearArrowsForPlayer(player->getPlayerInfo()->getId()); + for (ZoneViewWidget *zone : zoneViews) { if (zone->getPlayer() == player) { zone->close(); } } - players.removeOne(player->getGraphicsItem()); - removeItem(player->getGraphicsItem()); + auto *view = playerViews.take(player->getPlayerInfo()->getId()); + removeItem(view); rearrange(); } @@ -184,7 +202,7 @@ QList GameScene::collectActivePlayers(int &firstPlayerIndex) cons firstPlayerIndex = 0; bool firstPlayerFound = false; - for (auto *pgItem : players) { + for (auto *pgItem : playerViews.values()) { PlayerLogic *p = pgItem->getPlayer(); if (p && !p->getConceded()) { activePlayers.append(p); @@ -348,6 +366,77 @@ void GameScene::resizeColumnsAndPlayers(const QList &minWidthByColumn, qr } } +void GameScene::onArrowCreateRequested(const ArrowData &data) +{ + auto *startView = playerViews.value(data.startPlayerId); + auto *targetView = playerViews.value(data.targetPlayerId); + if (!startView || !targetView) { + return; + } + + PlayerLogic *startLogic = startView->getPlayer(); + auto *startZone = startLogic->getZones().value(data.startZone); + if (!startZone) { + return; + } + + CardItem *startCard = startZone->getCard(data.startCardId); + if (!startCard) { + return; + } + + ArrowTarget *targetItem = nullptr; + if (data.isPlayerTargeted()) { + targetItem = targetView->getPlayerTarget(); + } else { + auto *zone = targetView->getPlayer()->getZones().value(data.targetZone); + if (zone) { + targetItem = zone->getCard(data.targetCardId); + } + } + if (!targetItem) { + return; + } + + auto *arrow = new ArrowItem(startView->getPlayer(), data.id, startCard, targetItem, data.color); + addItem(arrow); + arrowRegistry.insert(data.id, arrow); + connect(arrow, &QObject::destroyed, this, [this, id = data.id]() { arrowRegistry.remove(id); }); +} + +void GameScene::onArrowDeleteRequested(int arrowId) +{ + if (arrowRegistry.contains(arrowId)) { + emit requestArrowDeletion(arrowId); + } +} + +void GameScene::onCardZoneChanged(CardItem *card, bool sameZone) +{ + QList toDelete; + for (auto *arrow : arrowRegistry.values()) { + if (arrow->getStartItem() == card || arrow->getTargetItem() == card) { + if (sameZone) { + arrow->updatePath(); + } else { + toDelete.append(arrow); + } + } + } + for (auto *arrow : toDelete) { + emit requestArrowDeletion(arrow->getId()); + } +} + +void GameScene::clearArrowsForPlayer(int playerId) +{ + for (auto *arrow : arrowRegistry.values()) { + if (arrow->getPlayer()->getPlayerInfo()->getId() == playerId) { + emit requestArrowDeletion(arrow->getId()); + } + } +} + // ---------- Hover Handling ---------- void GameScene::updateHover(const QPointF &scenePos) diff --git a/cockatrice/src/game/game_scene.h b/cockatrice/src/game/game_scene.h index a2d712609..aadbd536e 100644 --- a/cockatrice/src/game/game_scene.h +++ b/cockatrice/src/game/game_scene.h @@ -1,6 +1,8 @@ #ifndef GAMESCENE_H #define GAMESCENE_H +#include "board/arrow_data.h" +#include "board/arrow_item.h" #include "zones/card_zone_logic.h" #include @@ -41,8 +43,9 @@ private: static const int playerAreaSpacing = 5; ///< Space between player areas PhasesToolbar *phasesToolbar; ///< Toolbar showing game phases - QList players; ///< All player graphics items + QMap playerViews; ///< ID lookup for player graphics items QList> playersByColumn; ///< Players organized by column + QMap arrowRegistry; ///< ID registry for arrow graphics items QList zoneViews; ///< Active zone view widgets QSize viewSize; ///< Current view size QPointer hoveredCard; ///< Currently hovered card @@ -196,6 +199,11 @@ public slots: QTransform getViewTransform() const; QTransform getViewportTransform() const; + void onArrowCreateRequested(const ArrowData &data); + void onArrowDeleteRequested(int arrowId); + void onCardZoneChanged(CardItem *card, bool sameZone); + void clearArrowsForPlayer(int playerId); + protected: /** Handles hover updates. */ bool event(QEvent *event) override; @@ -207,6 +215,7 @@ signals: void sigStartRubberBand(const QPointF &selectionOrigin); void sigResizeRubberBand(const QPointF &cursorPoint, int selectedCount); void sigStopRubberBand(); + void requestArrowDeletion(int arrowId); }; #endif diff --git a/cockatrice/src/game/player/player_event_handler.cpp b/cockatrice/src/game/player/player_event_handler.cpp index 1345924b6..24030057b 100644 --- a/cockatrice/src/game/player/player_event_handler.cpp +++ b/cockatrice/src/game/player/player_event_handler.cpp @@ -2,9 +2,11 @@ #include "../../game_graphics/zones/view_zone.h" #include "../../interface/widgets/tabs/tab_game.h" +#include "../board/arrow_data.h" #include "../board/arrow_item.h" #include "../board/card_item.h" #include "../board/card_list.h" +#include "libcockatrice/utility/color.h" #include "player_actions.h" #include "player_logic.h" @@ -90,25 +92,43 @@ void PlayerEventHandler::eventRollDie(const Event_RollDie &event) void PlayerEventHandler::eventCreateArrow(const Event_CreateArrow &event) { - ArrowItem *arrow = player->addArrow(event.arrow_info()); - if (!arrow) { - return; + const ArrowData data = ArrowData::fromProto(event.arrow_info()); + + // Resolve names for logging + const auto &playerList = player->getGame()->getPlayerManager()->getPlayers(); + PlayerLogic *startPlayer = playerList.value(data.startPlayerId); + PlayerLogic *targetPlayer = playerList.value(data.targetPlayerId); + + QString startCardName, targetCardName; + if (startPlayer) { + auto *zone = startPlayer->getZones().value(data.startZone); + if (zone) { + if (auto *card = zone->getCard(data.startCardId)) { + startCardName = card->getName(); + } + } + } + if (!data.isPlayerTargeted() && targetPlayer) { + auto *zone = targetPlayer->getZones().value(data.targetZone); + if (zone) { + if (auto *card = zone->getCard(data.targetCardId)) { + targetCardName = card->getName(); + } + } } - auto *startCard = static_cast(arrow->getStartItem()); - auto *targetCard = qgraphicsitem_cast(arrow->getTargetItem()); - if (targetCard) { - emit logCreateArrow(player, startCard->getOwner(), startCard->getName(), targetCard->getOwner(), - targetCard->getName(), false); - } else { - emit logCreateArrow(player, startCard->getOwner(), startCard->getName(), arrow->getTargetItem()->getOwner(), - QString(), true); + emit player->arrowCreateRequested(data); + + const bool validForLogging = !startCardName.isEmpty() && (data.isPlayerTargeted() || !targetCardName.isEmpty()); + + if (startPlayer && targetPlayer && validForLogging) { + emit logCreateArrow(player, startPlayer, startCardName, targetPlayer, targetCardName, data.isPlayerTargeted()); } } void PlayerEventHandler::eventDeleteArrow(const Event_DeleteArrow &event) { - player->delArrow(event.arrow_id()); + emit player->arrowDeleteRequested(event.arrow_id()); } void PlayerEventHandler::eventCreateToken(const Event_CreateToken &event) @@ -352,28 +372,7 @@ void PlayerEventHandler::eventMoveCard(const Event_MoveCard &event, const GameEv targetZone->addCard(card, true, x, y); - // Look at all arrows from and to the card. - // If the card was moved to another zone, delete the arrows, otherwise update them. - QMapIterator playerIterator(player->getGame()->getPlayerManager()->getPlayers()); - while (playerIterator.hasNext()) { - PlayerLogic *p = playerIterator.next().value(); - - QList arrowsToDelete; - QMapIterator arrowIterator(p->getArrows()); - while (arrowIterator.hasNext()) { - ArrowItem *arrow = arrowIterator.next().value(); - if ((arrow->getStartItem() == card) || (arrow->getTargetItem() == card)) { - if (startZone == targetZone) { - arrow->updatePath(); - } else { - arrowsToDelete.append(arrow); - } - } - } - for (auto &i : arrowsToDelete) { - i->delArrow(); - } - } + emit cardZoneChanged(card, startZone == targetZone); player->getPlayerMenu()->updateCardMenu(card); if (player->getPlayerActions()->isMovingCardsUntil() && startZoneString == ZoneNames::DECK && diff --git a/cockatrice/src/game/player/player_event_handler.h b/cockatrice/src/game/player/player_event_handler.h index c9bdb98ae..84acbb8ea 100644 --- a/cockatrice/src/game/player/player_event_handler.h +++ b/cockatrice/src/game/player/player_event_handler.h @@ -82,6 +82,7 @@ signals: bool isLentToAnotherPlayer = false); void logAlwaysRevealTopCard(PlayerLogic *player, CardZoneLogic *zone, bool reveal); void logAlwaysLookAtTopCard(PlayerLogic *player, CardZoneLogic *zone, bool reveal); + void cardZoneChanged(CardItem *card, bool sameZone); public: PlayerEventHandler(PlayerLogic *player); diff --git a/cockatrice/src/game/player/player_logic.cpp b/cockatrice/src/game/player/player_logic.cpp index 677cc0d91..7fdb48868 100644 --- a/cockatrice/src/game/player/player_logic.cpp +++ b/cockatrice/src/game/player/player_logic.cpp @@ -74,7 +74,7 @@ PlayerLogic::~PlayerLogic() void PlayerLogic::clear() { - clearArrows(); + emit arrowsCleared(); QMapIterator i(zones); while (i.hasNext()) { @@ -115,7 +115,7 @@ void PlayerLogic::processPlayerInfo(const ServerInfo_Player &info) /* HandZone */ ZoneNames::HAND}; clearCounters(); - clearArrows(); + emit arrowsCleared(); QMutableMapIterator zoneIt(zones); while (zoneIt.hasNext()) { @@ -231,7 +231,7 @@ void PlayerLogic::processCardAttachment(const ServerInfo_Player &info) const int arrowListSize = info.arrow_list_size(); for (int i = 0; i < arrowListSize; ++i) { - addArrow(info.arrow_list(i)); + emit arrowCreateRequested(ArrowData::fromProto(info.arrow_list(i))); } } @@ -340,75 +340,6 @@ void PlayerLogic::incrementAllCardCounters() } } -ArrowItem *PlayerLogic::addArrow(const ServerInfo_Arrow &arrow) -{ - const QMap &playerList = game->getPlayerManager()->getPlayers(); - PlayerLogic *startPlayer = playerList.value(arrow.start_player_id(), 0); - PlayerLogic *targetPlayer = playerList.value(arrow.target_player_id(), 0); - if (!startPlayer || !targetPlayer) { - return nullptr; - } - - CardZoneLogic *startZone = startPlayer->getZones().value(QString::fromStdString(arrow.start_zone()), 0); - CardZoneLogic *targetZone = nullptr; - if (arrow.has_target_zone()) { - targetZone = targetPlayer->getZones().value(QString::fromStdString(arrow.target_zone()), 0); - } - if (!startZone || (!targetZone && arrow.has_target_zone())) { - return nullptr; - } - - CardItem *startCard = startZone->getCard(arrow.start_card_id()); - CardItem *targetCard = nullptr; - if (targetZone) { - targetCard = targetZone->getCard(arrow.target_card_id()); - } - if (!startCard || (!targetCard && arrow.has_target_card_id())) { - return nullptr; - } - - if (targetCard) { - return addArrow(arrow.id(), startCard, targetCard, convertColorToQColor(arrow.arrow_color())); - } else { - return addArrow(arrow.id(), startCard, targetPlayer->getGraphicsItem()->getPlayerTarget(), - convertColorToQColor(arrow.arrow_color())); - } -} - -ArrowItem *PlayerLogic::addArrow(int arrowId, CardItem *startCard, ArrowTarget *targetItem, const QColor &color) -{ - auto *arrow = new ArrowItem(this, arrowId, startCard, targetItem, color); - arrows.insert(arrowId, arrow); - - getGameScene()->addItem(arrow); - return arrow; -} - -void PlayerLogic::delArrow(int arrowId) -{ - ArrowItem *arr = arrows.value(arrowId, 0); - if (!arr) { - return; - } - arr->delArrow(); -} - -void PlayerLogic::removeArrow(ArrowItem *arrow) -{ - if (arrow->getId() != -1) { - arrows.remove(arrow->getId()); - } -} - -void PlayerLogic::clearArrows() -{ - QMapIterator arrowIterator(arrows); - while (arrowIterator.hasNext()) { - arrowIterator.next().value()->delArrow(); - } - arrows.clear(); -} - bool PlayerLogic::clearCardsToDelete() { if (cardsToDelete.isEmpty()) { diff --git a/cockatrice/src/game/player/player_logic.h b/cockatrice/src/game/player/player_logic.h index 01d7052df..138ed94ef 100644 --- a/cockatrice/src/game/player/player_logic.h +++ b/cockatrice/src/game/player/player_logic.h @@ -8,6 +8,7 @@ #define PLAYER_H #include "../../interface/widgets/menus/tearoff_menu.h" +#include "../board/arrow_data.h" #include "../interface/deck_loader/loaded_deck.h" #include "../zones/hand_zone_logic.h" #include "../zones/pile_zone_logic.h" @@ -77,6 +78,9 @@ signals: void clearCustomZonesMenu(); void addViewCustomZoneActionToCustomZoneMenu(QString zoneName); void resetTopCardMenuActions(); + void arrowCreateRequested(ArrowData data); + void arrowDeleteRequested(int arrowId); + void arrowsCleared(); // fires on clear() and processPlayerInfo public slots: void setActive(bool _active); @@ -205,17 +209,6 @@ public: */ CounterState *getLifeCounter() const; - ArrowItem *addArrow(const ServerInfo_Arrow &arrow); - ArrowItem *addArrow(int arrowId, CardItem *startCard, ArrowTarget *targetItem, const QColor &color); - void delArrow(int arrowId); - void removeArrow(ArrowItem *arrow); - void clearArrows(); - - const QMap &getArrows() const - { - return arrows; - } - void setConceded(bool _conceded); bool getConceded() const { @@ -252,12 +245,9 @@ private: int zoneId; QMap zones; QMap counters; - QMap arrows; bool dialogSemaphore; QList cardsToDelete; - - // void eventConnectionStateChanged(const Event_ConnectionStateChanged &event); }; class AnnotationDialog : public QInputDialog diff --git a/cockatrice/src/interface/widgets/tabs/tab_game.cpp b/cockatrice/src/interface/widgets/tabs/tab_game.cpp index 4dc1d1cb1..6b7b3539c 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_game.cpp +++ b/cockatrice/src/interface/widgets/tabs/tab_game.cpp @@ -606,17 +606,9 @@ void TabGame::actNextPhaseAction() void TabGame::actRemoveLocalArrows() { - QMapIterator playerIterator(game->getPlayerManager()->getPlayers()); - while (playerIterator.hasNext()) { - PlayerLogic *player = playerIterator.next().value(); - if (!player->getPlayerInfo()->getLocal()) { - continue; - } - QMapIterator arrowIterator(player->getArrows()); - while (arrowIterator.hasNext()) { - ArrowItem *a = arrowIterator.next().value(); - emit arrowDeletionRequested(a->getId()); - } + auto *local = game->getPlayerManager()->getActiveLocalPlayer(game->getGameState()->getActivePlayer()); + if (local) { + scene->clearArrowsForPlayer(local->getPlayerInfo()->getId()); } } @@ -970,8 +962,6 @@ void TabGame::createMenuItems() connect(aReverseTurn, &QAction::triggered, game->getGameEventHandler(), &GameEventHandler::handleReverseTurn); aRemoveLocalArrows = new QAction(this); connect(aRemoveLocalArrows, &QAction::triggered, this, &TabGame::actRemoveLocalArrows); - connect(this, &TabGame::arrowDeletionRequested, game->getGameEventHandler(), - &GameEventHandler::handleArrowDeletion); aRotateViewCW = new QAction(this); connect(aRotateViewCW, &QAction::triggered, this, &TabGame::actRotateViewCW); aRotateViewCCW = new QAction(this); @@ -1155,6 +1145,8 @@ void TabGame::createPlayAreaWidget(bool bReplay) scene = new GameScene(phasesToolbar, this); connect(game->getPlayerManager(), &PlayerManager::playerConceded, scene, &GameScene::rearrange); connect(game->getPlayerManager(), &PlayerManager::playerCountChanged, scene, &GameScene::rearrange); + connect(scene, &GameScene::requestArrowDeletion, game->getGameEventHandler(), + &GameEventHandler::handleArrowDeletion); gameView = new GameView(scene); auto gamePlayAreaVBox = new QVBoxLayout; diff --git a/cockatrice/src/interface/widgets/tabs/tab_game.h b/cockatrice/src/interface/widgets/tabs/tab_game.h index 66f23ba09..c8dfc3093 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_game.h +++ b/cockatrice/src/interface/widgets/tabs/tab_game.h @@ -137,7 +137,6 @@ signals: void gameLeft(); void chatMessageSent(QString chatMessage); void turnAdvanced(); - void arrowDeletionRequested(int arrowId); private slots: void adminLockChanged(bool lock); From 03d54265fe546cb529b8820470cfc70664919fd0 Mon Sep 17 00:00:00 2001 From: tooomm Date: Thu, 21 May 2026 22:02:09 +0200 Subject: [PATCH 32/51] escape ampersand (#6900) --- .ci/prep_release.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.ci/prep_release.sh b/.ci/prep_release.sh index cddf49aa6..7f4f7d961 100755 --- a/.ci/prep_release.sh +++ b/.ci/prep_release.sh @@ -89,6 +89,8 @@ else echo "'$previous' to '$TAG' ($count commits)" # --> is the markdown comment escape sequence, emojis are way better generated_list="${generated_list//-->/→}" + # Escape & to preserve it from commit message into markdown output + generated_list="${generated_list//&/\\&}" body="${body//--REPLACE-WITH-GENERATED-LIST--/$generated_list}" body="${body//--REPLACE-WITH-COMMIT-COUNT--/$count}" body="${body//--REPLACE-WITH-PREVIOUS-RELEASE-TAG--/$previous}" From 33e0f8699b373d222a80d5403eacac7cbb73cf42 Mon Sep 17 00:00:00 2001 From: DawnFire42 Date: Thu, 21 May 2026 16:58:07 -0400 Subject: [PATCH 33/51] Standardize Doxygen documentation (#6885) --- .github/CONTRIBUTING.md | 10 +++ .../network/interfaces/deck_stats_interface.h | 2 +- .../network/interfaces/tapped_out_interface.h | 2 +- .../parsers/deck_link_to_api_transformer.h | 2 +- .../parsers/interface_json_deck_parser.h | 2 +- .../card_spoiler/spoiler_background_updater.h | 2 +- .../update/client/client_update_checker.h | 2 +- .../network/update/client/release_channel.h | 2 +- .../network/update/client/update_downloader.h | 2 +- .../src/client/settings/cache_settings.h | 2 +- .../client/settings/card_counter_settings.h | 2 +- .../src/client/settings/shortcut_treeview.h | 2 +- .../client/settings/shortcuts_settings.cpp | 13 ++-- .../src/client/settings/shortcuts_settings.h | 2 +- cockatrice/src/client/sound_engine.h | 2 +- cockatrice/src/filters/deck_filter_string.h | 2 +- cockatrice/src/filters/filter_builder.h | 2 +- cockatrice/src/filters/filter_tree_model.h | 2 +- cockatrice/src/filters/syntax_help.h | 2 +- cockatrice/src/game/abstract_game.h | 2 +- .../src/game/board/abstract_card_drag_item.h | 2 +- cockatrice/src/game/board/abstract_counter.h | 2 +- cockatrice/src/game/board/arrow_item.h | 2 +- cockatrice/src/game/board/arrow_target.h | 2 +- cockatrice/src/game/board/card_drag_item.h | 2 +- cockatrice/src/game/board/card_item.h | 2 +- cockatrice/src/game/board/card_list.h | 2 +- cockatrice/src/game/board/counter_general.h | 2 +- .../src/game/board/translate_counter_name.h | 2 +- cockatrice/src/game/card_dimensions.h | 8 +-- cockatrice/src/game/deckview/deck_view.h | 2 +- .../src/game/deckview/deck_view_container.h | 2 +- .../deckview/tabbed_deck_view_container.h | 2 +- .../src/game/dialogs/dlg_create_token.h | 2 +- .../game/dialogs/dlg_move_top_cards_until.h | 2 +- cockatrice/src/game/dialogs/dlg_roll_dice.h | 2 +- cockatrice/src/game/game.h | 2 +- cockatrice/src/game/game_event_handler.h | 2 +- cockatrice/src/game/game_meta_info.h | 2 +- cockatrice/src/game/game_scene.h | 40 +++++------ cockatrice/src/game/game_state.h | 2 +- cockatrice/src/game/game_view.h | 2 +- cockatrice/src/game/hand_counter.h | 2 +- cockatrice/src/game/log/message_log_widget.h | 2 +- cockatrice/src/game/phase.h | 2 +- cockatrice/src/game/phases_toolbar.h | 2 +- .../src/game/player/card_menu_action_type.h | 2 +- .../game/player/event_processing_options.h | 2 +- .../player/menu/abstract_player_component.h | 6 +- cockatrice/src/game/player/menu/card_menu.h | 2 +- .../src/game/player/menu/custom_zone_menu.h | 2 +- cockatrice/src/game/player/menu/grave_menu.h | 2 +- cockatrice/src/game/player/menu/hand_menu.h | 2 +- .../src/game/player/menu/library_menu.h | 2 +- cockatrice/src/game/player/menu/move_menu.h | 2 +- cockatrice/src/game/player/menu/player_menu.h | 14 ++-- cockatrice/src/game/player/menu/pt_menu.h | 2 +- cockatrice/src/game/player/menu/rfg_menu.h | 2 +- cockatrice/src/game/player/menu/say_menu.h | 2 +- .../src/game/player/menu/sideboard_menu.h | 2 +- .../src/game/player/menu/utility_menu.h | 2 +- cockatrice/src/game/player/player_actions.h | 2 +- cockatrice/src/game/player/player_area.h | 2 +- .../src/game/player/player_event_handler.h | 2 +- .../src/game/player/player_graphics_item.h | 2 +- cockatrice/src/game/player/player_info.h | 2 +- .../src/game/player/player_list_widget.h | 2 +- cockatrice/src/game/player/player_logic.h | 2 +- cockatrice/src/game/player/player_manager.h | 2 +- cockatrice/src/game/player/player_target.h | 2 +- cockatrice/src/game/replay.h | 2 +- cockatrice/src/game/z_value_layer_manager.h | 9 +-- cockatrice/src/game/zones/card_zone_logic.h | 2 +- cockatrice/src/game/zones/hand_zone_logic.h | 2 +- cockatrice/src/game/zones/pile_zone_logic.h | 2 +- cockatrice/src/game/zones/stack_zone_logic.h | 2 +- cockatrice/src/game/zones/table_zone_logic.h | 2 +- cockatrice/src/game/zones/view_zone_logic.h | 2 +- .../board/abstract_graphics_item.h | 2 +- .../game_graphics/board/graphics_item_type.h | 2 +- .../src/game_graphics/zones/card_zone.h | 9 ++- .../src/game_graphics/zones/pile_zone.h | 2 +- .../src/game_graphics/zones/select_zone.h | 68 ++++++++++++------- .../src/game_graphics/zones/stack_zone.h | 2 +- .../src/game_graphics/zones/table_zone.h | 11 ++- .../src/game_graphics/zones/view_zone.h | 2 +- .../game_graphics/zones/view_zone_widget.h | 2 +- .../card_picture_to_load.cpp | 2 +- .../src/interface/deck_loader/deck_loader.h | 2 +- cockatrice/src/interface/key_signals.h | 2 +- .../src/interface/layouts/flow_layout.h | 1 + .../src/interface/layouts/overlap_layout.cpp | 2 +- .../src/interface/layouts/overlap_layout.h | 2 +- cockatrice/src/interface/logger.h | 2 +- .../src/interface/pixel_map_generator.h | 2 +- cockatrice/src/interface/theme_manager.cpp | 2 +- cockatrice/src/interface/theme_manager.h | 2 +- .../additional_info/color_identity_widget.h | 2 +- .../cards/additional_info/mana_cost_widget.h | 2 +- .../additional_info/mana_symbol_widget.h | 2 +- .../card_group_display_widget.h | 2 +- .../flat_card_group_display_widget.h | 2 +- .../overlapped_card_group_display_widget.h | 2 +- .../widgets/cards/card_info_display_widget.h | 2 +- .../widgets/cards/card_info_frame_widget.h | 2 +- .../cards/card_info_picture_art_crop_widget.h | 2 +- .../cards/card_info_picture_enlarged_widget.h | 2 +- .../widgets/cards/card_info_picture_widget.h | 2 +- ...rd_info_picture_with_text_overlay_widget.h | 2 +- .../widgets/cards/card_info_text_widget.h | 2 +- .../widgets/cards/card_size_widget.h | 2 +- .../cards/deck_card_zone_display_widget.h | 2 +- .../cards/deck_preview_card_picture_widget.h | 2 +- .../mana_base/mana_base_widget.h | 2 +- .../mana_curve/mana_curve_widget.h | 4 +- .../mana_devotion/mana_devotion_widget.h | 2 +- .../deck_editor_deck_dock_widget.cpp | 14 ++-- .../widgets/deck_editor/deck_state_manager.h | 8 ++- .../interface/widgets/dialogs/dlg_connect.h | 2 +- .../dialogs/dlg_convert_deck_to_cod_format.h | 2 +- .../widgets/dialogs/dlg_create_game.h | 2 +- .../widgets/dialogs/dlg_default_tags_editor.h | 2 +- .../widgets/dialogs/dlg_edit_avatar.h | 2 +- .../widgets/dialogs/dlg_edit_password.cpp | 2 +- .../widgets/dialogs/dlg_edit_password.h | 2 +- .../widgets/dialogs/dlg_edit_tokens.h | 2 +- .../interface/widgets/dialogs/dlg_edit_user.h | 2 +- .../widgets/dialogs/dlg_filter_games.h | 2 +- .../dialogs/dlg_forgot_password_challenge.h | 2 +- .../dialogs/dlg_forgot_password_request.h | 2 +- .../dialogs/dlg_forgot_password_reset.cpp | 2 +- .../dialogs/dlg_forgot_password_reset.h | 2 +- .../interface/widgets/dialogs/dlg_load_deck.h | 2 +- .../dialogs/dlg_load_deck_from_clipboard.h | 2 +- .../dialogs/dlg_load_deck_from_website.h | 2 +- .../widgets/dialogs/dlg_load_remote_deck.h | 2 +- .../widgets/dialogs/dlg_manage_sets.h | 2 +- .../widgets/dialogs/dlg_register.cpp | 2 +- .../interface/widgets/dialogs/dlg_register.h | 2 +- .../dialogs/dlg_select_set_for_cards.h | 2 +- .../widgets/dialogs/dlg_settings.cpp | 4 +- .../interface/widgets/dialogs/dlg_settings.h | 2 +- .../widgets/dialogs/dlg_startup_card_check.h | 2 +- .../widgets/dialogs/dlg_tip_of_the_day.h | 2 +- .../interface/widgets/dialogs/dlg_update.cpp | 2 +- .../interface/widgets/dialogs/dlg_update.h | 2 +- .../interface/widgets/dialogs/dlg_view_log.h | 2 +- .../widgets/dialogs/tip_of_the_day.h | 2 +- .../widgets/general/background_sources.h | 2 +- .../widgets/general/display/banner_widget.h | 2 +- .../general/display/charts/bars/bar_widget.h | 2 +- .../general/display/charts/bars/color_bar.h | 6 +- .../display/charts/bars/percent_bar_widget.h | 2 +- .../general/display/dynamic_font_size_label.h | 2 +- .../display/dynamic_font_size_push_button.h | 2 +- .../widgets/general/display/labeled_input.h | 2 +- .../general/display/shadow_background_label.h | 2 +- .../widgets/general/home_styled_button.h | 2 +- .../interface/widgets/general/home_widget.h | 2 +- .../general/layout_containers/flow_widget.h | 1 + .../overlap_control_widget.cpp | 2 +- .../overlap_control_widget.h | 2 +- .../layout_containers/overlap_widget.h | 2 +- .../widgets/menus/deck_editor_menu.h | 2 +- .../interface/widgets/menus/tearoff_menu.h | 2 +- .../all_zones_card_amount_widget.h | 2 +- .../printing_selector/card_amount_widget.h | 2 +- .../printing_selector/printing_selector.h | 2 +- .../printing_selector_card_display_widget.h | 2 +- .../printing_selector_card_overlay_widget.h | 2 +- .../printing_selector_card_search_widget.h | 2 +- .../printing_selector_card_selection_widget.h | 2 +- .../printing_selector_card_sorting_widget.h | 2 +- ...ame_and_collectors_number_display_widget.h | 2 +- .../quick_settings/settings_button_widget.h | 4 +- .../quick_settings/settings_popup_widget.h | 2 +- .../interface/widgets/replay/replay_manager.h | 2 +- .../widgets/replay/replay_timeline_widget.cpp | 10 ++- .../widgets/replay/replay_timeline_widget.h | 2 +- .../widgets/server/chat_view/chat_view.cpp | 6 +- .../widgets/server/chat_view/chat_view.h | 2 +- .../widgets/server/handle_public_servers.h | 2 +- .../remote/remote_decklist_tree_widget.h | 2 +- .../remote/remote_replay_list_tree_widget.h | 2 +- .../widgets/server/user/user_context_menu.h | 2 +- .../widgets/server/user/user_info_box.h | 2 +- .../server/user/user_info_connection.h | 2 +- .../widgets/server/user/user_list_manager.h | 2 +- .../widgets/server/user/user_list_proxy.h | 2 +- .../widgets/server/user/user_list_widget.h | 2 +- .../card/archidekt_api_response_card.cpp | 10 +-- .../deck/archidekt_api_response_deck.cpp | 2 +- ...kt_api_response_deck_listing_container.cpp | 2 +- .../archidekt_api_response_deck_owner.cpp | 2 +- ...pi_response_deck_listings_display_widget.h | 8 +-- .../average_deck/edhrec_deck_api_response.h | 2 +- .../edhrec_api_response_card_prices.h | 2 +- .../edhrec_api_response_card_container.h | 2 +- .../cards/edhrec_api_response_card_details.h | 2 +- .../cards/edhrec_api_response_card_list.h | 2 +- ...commander_api_response_commander_details.h | 2 +- .../top_cards/edhrec_top_cards_api_response.h | 2 +- .../edhrec_top_commanders_api_response.h | 2 +- .../top_tags/edhrec_top_tags_api_response.h | 2 +- ..._api_response_card_prices_display_widget.h | 2 +- ...api_response_card_details_display_widget.h | 2 +- ...i_response_card_inclusion_display_widget.h | 2 +- ...ec_api_response_card_list_display_widget.h | 2 +- ...api_response_card_synergy_display_widget.h | 2 +- ...esponse_commander_details_display_widget.h | 2 +- ...ec_commander_api_response_display_widget.h | 2 +- ...commander_api_response_navigation_widget.h | 2 +- ...ec_top_cards_api_response_display_widget.h | 2 +- ...p_commanders_api_response_display_widget.h | 2 +- ...rec_top_tags_api_response_display_widget.h | 2 +- .../widgets/tabs/api/edhrec/tab_edhrec.h | 2 +- .../widgets/tabs/api/edhrec/tab_edhrec_main.h | 2 +- cockatrice/src/interface/widgets/tabs/tab.h | 2 +- .../src/interface/widgets/tabs/tab_account.h | 2 +- .../src/interface/widgets/tabs/tab_admin.h | 2 +- .../interface/widgets/tabs/tab_deck_storage.h | 2 +- .../src/interface/widgets/tabs/tab_game.h | 2 +- .../src/interface/widgets/tabs/tab_home.h | 2 +- .../src/interface/widgets/tabs/tab_logs.h | 2 +- .../src/interface/widgets/tabs/tab_message.h | 2 +- .../src/interface/widgets/tabs/tab_replays.h | 2 +- .../src/interface/widgets/tabs/tab_room.h | 2 +- .../src/interface/widgets/tabs/tab_server.h | 2 +- .../interface/widgets/tabs/tab_supervisor.h | 2 +- .../tabs/tab_visual_database_display.h | 2 +- .../tab_deck_editor_visual_tab_widget.h | 10 +-- .../tab_deck_storage_visual.h | 2 +- .../widgets/utility/custom_line_edit.h | 2 +- .../widgets/utility/line_edit_completer.h | 2 +- .../interface/widgets/utility/sequence_edit.h | 2 +- ...ual_database_display_color_filter_widget.h | 2 +- ...database_display_filter_save_load_widget.h | 2 +- ...database_display_main_type_filter_widget.h | 2 +- ...sual_database_display_name_filter_widget.h | 2 +- ...isual_database_display_set_filter_widget.h | 2 +- ..._database_display_sub_type_filter_widget.h | 2 +- .../visual_database_display_widget.h | 2 +- .../visual_database_filter_display_widget.h | 2 +- .../visual_deck_display_options_widget.h | 22 +++--- .../visual_deck_editor_sample_hand_widget.h | 2 +- .../visual_deck_editor_widget.cpp | 4 +- .../visual_deck_editor_widget.h | 2 +- ...eck_preview_color_identity_filter_widget.h | 2 +- .../deck_preview_deck_tags_display_widget.h | 2 +- .../deck_preview_tag_addition_widget.h | 2 +- .../deck_preview/deck_preview_tag_dialog.h | 2 +- .../deck_preview_tag_display_widget.h | 2 +- .../deck_preview_tag_item_widget.h | 2 +- .../deck_preview/deck_preview_widget.cpp | 4 +- .../deck_preview/deck_preview_widget.h | 2 +- ...isual_deck_storage_folder_display_widget.h | 2 +- .../visual_deck_storage_search_widget.h | 2 +- .../visual_deck_storage_sort_widget.h | 2 +- .../visual_deck_storage_tag_filter_widget.h | 2 +- .../visual_deck_storage_widget.h | 2 +- cockatrice/src/interface/window_main.h | 2 +- cockatrice/src/main.h | 2 +- .../libcockatrice/card/card_info_comparator.h | 2 +- .../card/database/card_database.h | 18 ++--- .../card/database/card_database_manager.h | 6 +- .../libcockatrice/card/game_specific_terms.h | 2 +- .../libcockatrice/card/set/card_set.h | 16 ++--- .../card/set/card_set_comparator.h | 2 +- .../libcockatrice/deck_list/deck_list.h | 24 ++++--- .../deck_list/deck_list_node_tree.h | 6 +- .../libcockatrice/deck_list/sideboard_plan.h | 6 +- .../tree/abstract_deck_list_card_node.h | 24 +++---- .../deck_list/tree/abstract_deck_list_node.h | 4 +- .../deck_list/tree/deck_list_card_node.h | 26 +++---- .../deck_list/tree/inner_deck_list_node.h | 22 +++--- .../libcockatrice/filters/filter_card.h | 2 +- .../libcockatrice/filters/filter_string.h | 2 +- .../libcockatrice/filters/filter_tree.h | 17 +++-- .../card/card_completer_proxy_model.h | 2 +- .../models/database/card/card_search_model.h | 2 +- .../database/card_set/card_sets_model.h | 2 +- .../database/token/token_display_model.h | 2 +- .../models/database/token/token_edit_model.h | 2 +- .../models/deck_list/deck_list_model.cpp | 11 +-- .../deck_list_sort_filter_proxy_model.h | 2 +- .../network/client/abstract/abstract_client.h | 2 +- .../network/client/local/local_client.h | 2 +- .../network/client/remote/remote_client.cpp | 4 +- .../network/client/remote/remote_client.h | 2 +- .../network/server/local/local_server.h | 2 +- .../server/local/local_server_interface.h | 2 +- .../server/remote/game/server_game.cpp | 4 +- .../network/server/remote/server.cpp | 2 +- .../libcockatrice/protocol/pending_command.h | 2 +- .../settings/card_database_settings.h | 2 +- .../settings/card_override_settings.h | 2 +- .../libcockatrice/settings/debug_settings.h | 2 +- .../settings/download_settings.h | 2 +- .../settings/game_filters_settings.h | 2 +- .../libcockatrice/settings/layouts_settings.h | 2 +- .../libcockatrice/settings/message_settings.h | 2 +- .../libcockatrice/settings/recents_settings.h | 2 +- .../libcockatrice/settings/servers_settings.h | 2 +- .../libcockatrice/settings/settings_manager.h | 2 +- .../libcockatrice/utility/levenshtein.h | 2 +- servatrice/src/serversocketinterface.cpp | 4 +- 306 files changed, 539 insertions(+), 487 deletions(-) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index b293b3937..56ad64283 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -209,6 +209,16 @@ nowadays and clean it up for you. Lines should be 120 characters or less. Please break up lines that are too long into smaller parts, for example at spaces or after opening a brace. +### Documentation Comments ### + +Use [Doxygen](https://www.doxygen.nl/) for code documentation: + +- **Doc blocks**: Use `/** @brief Description */` (Javadoc-style), not `///` +- **Member comments**: Use trailing `///<` for inline member documentation +- **TODOs**: Use `//! \todo Description` (Qt-style), Doxygen collects them into a Todo List + (uses [Qt-style comments](https://www.doxygen.nl/manual/docblocks.html) with + Doxygen's [\todo command](https://www.doxygen.nl/manual/commands.html#cmdtodo)) + ### Memory Management ### New code should be written using references over pointers and stack allocation diff --git a/cockatrice/src/client/network/interfaces/deck_stats_interface.h b/cockatrice/src/client/network/interfaces/deck_stats_interface.h index 7dc841027..2ec67a5a7 100644 --- a/cockatrice/src/client/network/interfaces/deck_stats_interface.h +++ b/cockatrice/src/client/network/interfaces/deck_stats_interface.h @@ -1,8 +1,8 @@ /** * @file deck_stats_interface.h * @ingroup ApiInterfaces - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef DECKSTATS_INTERFACE_H #define DECKSTATS_INTERFACE_H diff --git a/cockatrice/src/client/network/interfaces/tapped_out_interface.h b/cockatrice/src/client/network/interfaces/tapped_out_interface.h index 0ea9c8358..f1cc1cbeb 100644 --- a/cockatrice/src/client/network/interfaces/tapped_out_interface.h +++ b/cockatrice/src/client/network/interfaces/tapped_out_interface.h @@ -1,8 +1,8 @@ /** * @file tapped_out_interface.h * @ingroup ApiInterfaces - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef TAPPEDOUT_INTERFACE_H #define TAPPEDOUT_INTERFACE_H diff --git a/cockatrice/src/client/network/parsers/deck_link_to_api_transformer.h b/cockatrice/src/client/network/parsers/deck_link_to_api_transformer.h index 1e2372fd1..bbdd70c97 100644 --- a/cockatrice/src/client/network/parsers/deck_link_to_api_transformer.h +++ b/cockatrice/src/client/network/parsers/deck_link_to_api_transformer.h @@ -1,8 +1,8 @@ /** * @file deck_link_to_api_transformer.h * @ingroup ApiInterfaces - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef DECK_LINK_TO_API_TRANSFORMER_H #define DECK_LINK_TO_API_TRANSFORMER_H diff --git a/cockatrice/src/client/network/parsers/interface_json_deck_parser.h b/cockatrice/src/client/network/parsers/interface_json_deck_parser.h index 1818aa35c..87fde4d54 100644 --- a/cockatrice/src/client/network/parsers/interface_json_deck_parser.h +++ b/cockatrice/src/client/network/parsers/interface_json_deck_parser.h @@ -1,8 +1,8 @@ /** * @file interface_json_deck_parser.h * @ingroup ApiInterfaces - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef INTERFACE_JSON_DECK_PARSER_H #define INTERFACE_JSON_DECK_PARSER_H diff --git a/cockatrice/src/client/network/update/card_spoiler/spoiler_background_updater.h b/cockatrice/src/client/network/update/card_spoiler/spoiler_background_updater.h index a2feb5ccf..03d4897a2 100644 --- a/cockatrice/src/client/network/update/card_spoiler/spoiler_background_updater.h +++ b/cockatrice/src/client/network/update/card_spoiler/spoiler_background_updater.h @@ -1,8 +1,8 @@ /** * @file spoiler_background_updater.h * @ingroup Client - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef COCKATRICE_SPOILER_DOWNLOADER_H #define COCKATRICE_SPOILER_DOWNLOADER_H diff --git a/cockatrice/src/client/network/update/client/client_update_checker.h b/cockatrice/src/client/network/update/client/client_update_checker.h index 4e6f279c3..1a89de533 100644 --- a/cockatrice/src/client/network/update/client/client_update_checker.h +++ b/cockatrice/src/client/network/update/client/client_update_checker.h @@ -1,8 +1,8 @@ /** * @file client_update_checker.h * @ingroup ClientUpdate - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef CLIENT_UPDATE_CHECKER_H #define CLIENT_UPDATE_CHECKER_H diff --git a/cockatrice/src/client/network/update/client/release_channel.h b/cockatrice/src/client/network/update/client/release_channel.h index 93e6b985d..c56d0cfce 100644 --- a/cockatrice/src/client/network/update/client/release_channel.h +++ b/cockatrice/src/client/network/update/client/release_channel.h @@ -1,8 +1,8 @@ /** * @file release_channel.h * @ingroup ClientUpdate - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef RELEASECHANNEL_H #define RELEASECHANNEL_H diff --git a/cockatrice/src/client/network/update/client/update_downloader.h b/cockatrice/src/client/network/update/client/update_downloader.h index d70759038..9a0caccbc 100644 --- a/cockatrice/src/client/network/update/client/update_downloader.h +++ b/cockatrice/src/client/network/update/client/update_downloader.h @@ -1,8 +1,8 @@ /** * @file update_downloader.h * @ingroup ClientUpdate - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef COCKATRICE_UPDATEDOWNLOADER_H #define COCKATRICE_UPDATEDOWNLOADER_H diff --git a/cockatrice/src/client/settings/cache_settings.h b/cockatrice/src/client/settings/cache_settings.h index 90aa8eedb..b1197e267 100644 --- a/cockatrice/src/client/settings/cache_settings.h +++ b/cockatrice/src/client/settings/cache_settings.h @@ -1,8 +1,8 @@ /** * @file cache_settings.h * @ingroup Settings - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef SETTINGSCACHE_H #define SETTINGSCACHE_H diff --git a/cockatrice/src/client/settings/card_counter_settings.h b/cockatrice/src/client/settings/card_counter_settings.h index b1d467d67..2ac658177 100644 --- a/cockatrice/src/client/settings/card_counter_settings.h +++ b/cockatrice/src/client/settings/card_counter_settings.h @@ -1,8 +1,8 @@ /** * @file card_counter_settings.h * @ingroup GameSettings - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef CARD_COUNTER_SETTINGS_H #define CARD_COUNTER_SETTINGS_H diff --git a/cockatrice/src/client/settings/shortcut_treeview.h b/cockatrice/src/client/settings/shortcut_treeview.h index 8d74a6f1e..afaf7e7ed 100644 --- a/cockatrice/src/client/settings/shortcut_treeview.h +++ b/cockatrice/src/client/settings/shortcut_treeview.h @@ -1,8 +1,8 @@ /** * @file shortcut_treeview.h * @ingroup CoreSettings - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef SHORTCUT_TREEVIEW_H #define SHORTCUT_TREEVIEW_H diff --git a/cockatrice/src/client/settings/shortcuts_settings.cpp b/cockatrice/src/client/settings/shortcuts_settings.cpp index 53c6f6a23..2ff65ab6f 100644 --- a/cockatrice/src/client/settings/shortcuts_settings.cpp +++ b/cockatrice/src/client/settings/shortcuts_settings.cpp @@ -64,8 +64,13 @@ ShortcutsSettings::ShortcutsSettings(const QString &settingsPath, QObject *paren } } -/// PR 5079 changes Textbox/unfocusTextBox to Player/unfocusTextBox and tab_game/aFocusChat to Player/aFocusChat. -/// A migration is necessary to let players keep their already configured shortcuts. +/** + * @brief Migrates legacy shortcut key names to current naming scheme. + * + * PR 5079 changed Textbox/unfocusTextBox to Player/unfocusTextBox and + * tab_game/aFocusChat to Player/aFocusChat. This migration allows players + * to keep their already configured shortcuts. + */ void ShortcutsSettings::migrateShortcuts() { if (QFile(settingsFilePath).exists()) { @@ -236,9 +241,7 @@ bool ShortcutsSettings::isValid(const QString &name, const QString &sequences) c return findOverlaps(name, sequences).isEmpty(); } -/** - * Checks if the shortcut is a shortcut that is active in all windows - */ +/** @brief Checks if the shortcut is a shortcut that is active in all windows. */ static bool isAlwaysActiveShortcut(const QString &shortcutName) { return shortcutName.startsWith("MainWindow") || shortcutName.startsWith("Tabs"); diff --git a/cockatrice/src/client/settings/shortcuts_settings.h b/cockatrice/src/client/settings/shortcuts_settings.h index fc159db48..45e2c4fca 100644 --- a/cockatrice/src/client/settings/shortcuts_settings.h +++ b/cockatrice/src/client/settings/shortcuts_settings.h @@ -1,8 +1,8 @@ /** * @file shortcuts_settings.h * @ingroup CoreSettings - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef SHORTCUTSSETTINGS_H #define SHORTCUTSSETTINGS_H diff --git a/cockatrice/src/client/sound_engine.h b/cockatrice/src/client/sound_engine.h index f45cccf7d..0c201523a 100644 --- a/cockatrice/src/client/sound_engine.h +++ b/cockatrice/src/client/sound_engine.h @@ -1,8 +1,8 @@ /** * @file sound_engine.h * @ingroup Core - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef SOUNDENGINE_H #define SOUNDENGINE_H diff --git a/cockatrice/src/filters/deck_filter_string.h b/cockatrice/src/filters/deck_filter_string.h index 1b43d770d..916b629ee 100644 --- a/cockatrice/src/filters/deck_filter_string.h +++ b/cockatrice/src/filters/deck_filter_string.h @@ -1,8 +1,8 @@ /** * @file deck_filter_string.h * @ingroup DeckStorageWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef DECK_FILTER_STRING_H #define DECK_FILTER_STRING_H diff --git a/cockatrice/src/filters/filter_builder.h b/cockatrice/src/filters/filter_builder.h index 74872e3cd..98fe3fd02 100644 --- a/cockatrice/src/filters/filter_builder.h +++ b/cockatrice/src/filters/filter_builder.h @@ -1,8 +1,8 @@ /** * @file filter_builder.h * @ingroup CardDatabaseModelFilters - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef FILTERBUILDER_H #define FILTERBUILDER_H diff --git a/cockatrice/src/filters/filter_tree_model.h b/cockatrice/src/filters/filter_tree_model.h index c6666a838..7452f7a61 100644 --- a/cockatrice/src/filters/filter_tree_model.h +++ b/cockatrice/src/filters/filter_tree_model.h @@ -1,8 +1,8 @@ /** * @file filter_tree_model.h * @ingroup CardDatabaseModelFilters - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef FILTERTREEMODEL_H #define FILTERTREEMODEL_H diff --git a/cockatrice/src/filters/syntax_help.h b/cockatrice/src/filters/syntax_help.h index 7e5ef3e0e..d06fe03e5 100644 --- a/cockatrice/src/filters/syntax_help.h +++ b/cockatrice/src/filters/syntax_help.h @@ -2,8 +2,8 @@ * @file syntax_help.h * @ingroup CardDatabaseModelFilters * @ingroup DeckStorageWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef SEARCH_SYNTAX_HELP_H #define SEARCH_SYNTAX_HELP_H diff --git a/cockatrice/src/game/abstract_game.h b/cockatrice/src/game/abstract_game.h index cb4dbac2a..2441bac2d 100644 --- a/cockatrice/src/game/abstract_game.h +++ b/cockatrice/src/game/abstract_game.h @@ -1,8 +1,8 @@ /** * @file abstract_game.h * @ingroup GameLogic - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef COCKATRICE_ABSTRACT_GAME_H #define COCKATRICE_ABSTRACT_GAME_H diff --git a/cockatrice/src/game/board/abstract_card_drag_item.h b/cockatrice/src/game/board/abstract_card_drag_item.h index fe3b87983..1cbeb4fe7 100644 --- a/cockatrice/src/game/board/abstract_card_drag_item.h +++ b/cockatrice/src/game/board/abstract_card_drag_item.h @@ -1,8 +1,8 @@ /** * @file abstract_card_drag_item.h * @ingroup GameGraphicsCards - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef ABSTRACTCARDDRAGITEM_H #define ABSTRACTCARDDRAGITEM_H diff --git a/cockatrice/src/game/board/abstract_counter.h b/cockatrice/src/game/board/abstract_counter.h index 57bc43856..b31bd1aa3 100644 --- a/cockatrice/src/game/board/abstract_counter.h +++ b/cockatrice/src/game/board/abstract_counter.h @@ -1,8 +1,8 @@ /** * @file abstract_counter.h * @ingroup GameGraphicsPlayers - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef COUNTER_H #define COUNTER_H diff --git a/cockatrice/src/game/board/arrow_item.h b/cockatrice/src/game/board/arrow_item.h index 43c0d2b91..ebaea032a 100644 --- a/cockatrice/src/game/board/arrow_item.h +++ b/cockatrice/src/game/board/arrow_item.h @@ -1,8 +1,8 @@ /** * @file arrow_item.h * @ingroup GameGraphics - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef ARROWITEM_H #define ARROWITEM_H diff --git a/cockatrice/src/game/board/arrow_target.h b/cockatrice/src/game/board/arrow_target.h index 9c9aaa315..664572705 100644 --- a/cockatrice/src/game/board/arrow_target.h +++ b/cockatrice/src/game/board/arrow_target.h @@ -1,8 +1,8 @@ /** * @file arrow_target.h * @ingroup GameGraphics - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef ARROWTARGET_H #define ARROWTARGET_H diff --git a/cockatrice/src/game/board/card_drag_item.h b/cockatrice/src/game/board/card_drag_item.h index 930c6be6f..74d25ad04 100644 --- a/cockatrice/src/game/board/card_drag_item.h +++ b/cockatrice/src/game/board/card_drag_item.h @@ -1,8 +1,8 @@ /** * @file card_drag_item.h * @ingroup GameGraphicsCards - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef CARDDRAGITEM_H #define CARDDRAGITEM_H diff --git a/cockatrice/src/game/board/card_item.h b/cockatrice/src/game/board/card_item.h index 1e99dbe2a..408bb03a7 100644 --- a/cockatrice/src/game/board/card_item.h +++ b/cockatrice/src/game/board/card_item.h @@ -1,8 +1,8 @@ /** * @file card_item.h * @ingroup GameGraphicsCards - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef CARDITEM_H #define CARDITEM_H diff --git a/cockatrice/src/game/board/card_list.h b/cockatrice/src/game/board/card_list.h index 07be33b32..85a6848b7 100644 --- a/cockatrice/src/game/board/card_list.h +++ b/cockatrice/src/game/board/card_list.h @@ -1,8 +1,8 @@ /** * @file card_list.h * @ingroup GameLogicCards - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef CARDLIST_H #define CARDLIST_H diff --git a/cockatrice/src/game/board/counter_general.h b/cockatrice/src/game/board/counter_general.h index db1ee2743..0a2e882ce 100644 --- a/cockatrice/src/game/board/counter_general.h +++ b/cockatrice/src/game/board/counter_general.h @@ -1,8 +1,8 @@ /** * @file counter_general.h * @ingroup GameGraphicsPlayers - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef COUNTER_GENERAL_H #define COUNTER_GENERAL_H diff --git a/cockatrice/src/game/board/translate_counter_name.h b/cockatrice/src/game/board/translate_counter_name.h index fdb277c11..ba3a94fa5 100644 --- a/cockatrice/src/game/board/translate_counter_name.h +++ b/cockatrice/src/game/board/translate_counter_name.h @@ -1,8 +1,8 @@ /** * @file translate_counter_name.h * @ingroup GameGraphicsPlayers - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef TRANSLATECOUNTERNAME_H #define TRANSLATECOUNTERNAME_H diff --git a/cockatrice/src/game/card_dimensions.h b/cockatrice/src/game/card_dimensions.h index 255d0bc04..c59a01b48 100644 --- a/cockatrice/src/game/card_dimensions.h +++ b/cockatrice/src/game/card_dimensions.h @@ -12,16 +12,16 @@ */ namespace CardDimensions { -/// Card width in pixels +/** @brief Card width in pixels. */ constexpr int WIDTH = 72; -/// Card height in pixels +/** @brief Card height in pixels. */ constexpr int HEIGHT = 102; -/// Pre-converted for floating-point contexts (Z-value calculations) +/** @brief Pre-converted for floating-point contexts (Z-value calculations). */ constexpr qreal WIDTH_F = static_cast(WIDTH); constexpr qreal HEIGHT_F = static_cast(HEIGHT); -/// Half-dimensions for centering and rotation transforms +/** @brief Half-dimensions for centering and rotation transforms. */ constexpr qreal WIDTH_HALF_F = WIDTH_F / 2; constexpr qreal HEIGHT_HALF_F = HEIGHT_F / 2; } // namespace CardDimensions diff --git a/cockatrice/src/game/deckview/deck_view.h b/cockatrice/src/game/deckview/deck_view.h index 5abc558bd..f996fd4da 100644 --- a/cockatrice/src/game/deckview/deck_view.h +++ b/cockatrice/src/game/deckview/deck_view.h @@ -1,8 +1,8 @@ /** * @file deck_view.h * @ingroup Lobby - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef DECKVIEW_H #define DECKVIEW_H diff --git a/cockatrice/src/game/deckview/deck_view_container.h b/cockatrice/src/game/deckview/deck_view_container.h index 6d685cd79..ec024bace 100644 --- a/cockatrice/src/game/deckview/deck_view_container.h +++ b/cockatrice/src/game/deckview/deck_view_container.h @@ -1,8 +1,8 @@ /** * @file deck_view_container.h * @ingroup Lobby - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef DECK_VIEW_CONTAINER_H #define DECK_VIEW_CONTAINER_H diff --git a/cockatrice/src/game/deckview/tabbed_deck_view_container.h b/cockatrice/src/game/deckview/tabbed_deck_view_container.h index c34eef1ef..7cfa8c9aa 100644 --- a/cockatrice/src/game/deckview/tabbed_deck_view_container.h +++ b/cockatrice/src/game/deckview/tabbed_deck_view_container.h @@ -1,8 +1,8 @@ /** * @file tabbed_deck_view_container.h * @ingroup Lobby - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef TABBED_DECK_VIEW_CONTAINER_H #define TABBED_DECK_VIEW_CONTAINER_H diff --git a/cockatrice/src/game/dialogs/dlg_create_token.h b/cockatrice/src/game/dialogs/dlg_create_token.h index 9a18f1a57..281e161fc 100644 --- a/cockatrice/src/game/dialogs/dlg_create_token.h +++ b/cockatrice/src/game/dialogs/dlg_create_token.h @@ -1,8 +1,8 @@ /** * @file dlg_create_token.h * @ingroup GameDialogs - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef DLG_CREATETOKEN_H #define DLG_CREATETOKEN_H diff --git a/cockatrice/src/game/dialogs/dlg_move_top_cards_until.h b/cockatrice/src/game/dialogs/dlg_move_top_cards_until.h index 20ba11c5c..ac9d41a94 100644 --- a/cockatrice/src/game/dialogs/dlg_move_top_cards_until.h +++ b/cockatrice/src/game/dialogs/dlg_move_top_cards_until.h @@ -1,8 +1,8 @@ /** * @file dlg_move_top_cards_until.h * @ingroup GameDialogs - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef DLG_MOVE_TOP_CARDS_UNTIL_H #define DLG_MOVE_TOP_CARDS_UNTIL_H diff --git a/cockatrice/src/game/dialogs/dlg_roll_dice.h b/cockatrice/src/game/dialogs/dlg_roll_dice.h index 69edd0757..15f7dc1ba 100644 --- a/cockatrice/src/game/dialogs/dlg_roll_dice.h +++ b/cockatrice/src/game/dialogs/dlg_roll_dice.h @@ -1,8 +1,8 @@ /** * @file dlg_roll_dice.h * @ingroup GameDialogs - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef DLG_ROLL_DICE_H #define DLG_ROLL_DICE_H diff --git a/cockatrice/src/game/game.h b/cockatrice/src/game/game.h index 96ebbae4d..ccdb679df 100644 --- a/cockatrice/src/game/game.h +++ b/cockatrice/src/game/game.h @@ -1,8 +1,8 @@ /** * @file game.h * @ingroup GameLogic - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef COCKATRICE_GAME_H #define COCKATRICE_GAME_H diff --git a/cockatrice/src/game/game_event_handler.h b/cockatrice/src/game/game_event_handler.h index 250f2c185..7587ab46d 100644 --- a/cockatrice/src/game/game_event_handler.h +++ b/cockatrice/src/game/game_event_handler.h @@ -1,8 +1,8 @@ /** * @file game_event_handler.h * @ingroup GameLogic - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef COCKATRICE_GAME_EVENT_HANDLER_H #define COCKATRICE_GAME_EVENT_HANDLER_H diff --git a/cockatrice/src/game/game_meta_info.h b/cockatrice/src/game/game_meta_info.h index 8226af2ae..cdba1605f 100644 --- a/cockatrice/src/game/game_meta_info.h +++ b/cockatrice/src/game/game_meta_info.h @@ -1,8 +1,8 @@ /** * @file game_meta_info.h * @ingroup GameLogic - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef GAME_META_INFO_H #define GAME_META_INFO_H diff --git a/cockatrice/src/game/game_scene.h b/cockatrice/src/game/game_scene.h index aadbd536e..5e0e6b7c9 100644 --- a/cockatrice/src/game/game_scene.h +++ b/cockatrice/src/game/game_scene.h @@ -59,10 +59,12 @@ private: */ void updateHover(const QPointF &scenePos); - /// Activates hover state and escapes the card from its clip container so hover scaling is visible beyond zone - /// bounds. + /** + * @brief Activates hover state and escapes the card from its clip container + * so hover scaling is visible beyond zone bounds. + */ void beginCardHover(CardItem *card); - /// Deactivates hover state and restores the card to its clip container. + /** @brief Deactivates hover state and restores the card to its clip container. */ void endCardHover(CardItem *card); public: @@ -73,13 +75,13 @@ public: */ explicit GameScene(PhasesToolbar *_phasesToolbar, QObject *parent = nullptr); - /** Destructor, cleans up timer and zone views. */ + /** @brief Destructor, cleans up timer and zone views. */ ~GameScene() override; - /** Updates UI text for all zone views. */ + /** @brief Updates UI text for all zone views. */ void retranslateUi(); - /** Gets all selected CardItems */ + /** @brief Gets all selected CardItems. */ QList selectedCards() const; /** @@ -100,7 +102,7 @@ public: */ void adjustPlayerRotation(int rotationAdjustment); - /** Recomputes the layout of players and the scene size. */ + /** @brief Recomputes the layout of players and the scene size. */ void rearrange(); /** @@ -160,41 +162,41 @@ public: */ void resizeColumnsAndPlayers(const QList &minWidthByColumn, qreal newWidth); - /** Finds the topmost card zone under the cursor. */ + /** @brief Finds the topmost card zone under the cursor. */ static CardZone *findTopmostZone(const QList &items); - /** Finds the topmost card in a given zone, considering attachments and Z-order. */ + /** @brief Finds the topmost card in a given zone, considering attachments and Z-order. */ static CardItem *findTopmostCardInZone(const QList &items, CardZone *zone); - /** Updates hovered card highlighting. */ + /** @brief Updates hovered card highlighting. */ void updateHoveredCard(CardItem *newCard); - /** Registers a card for animation updates. */ + /** @brief Registers a card for animation updates. */ void registerAnimationItem(AbstractCardItem *card); - /** Unregisters a card from animation updates. */ + /** @brief Unregisters a card from animation updates. */ void unregisterAnimationItem(AbstractCardItem *card); void startRubberBand(const QPointF &selectionOrigin); void resizeRubberBand(const QPointF &cursorPoint, int selectedCount); void stopRubberBand(); public slots: - /** Toggles a zone view for a player. */ + /** @brief Toggles a zone view for a player. */ void toggleZoneView(PlayerLogic *player, const QString &zoneName, int numberCards, bool isReversed = false); - /** Adds a revealed zone view (for shown cards). */ + /** @brief Adds a revealed zone view (for shown cards). */ void addRevealedZoneView(PlayerLogic *player, CardZoneLogic *zone, const QList &cardList, bool withWritePermission); - /** Removes a zone view widget from the scene. */ + /** @brief Removes a zone view widget from the scene. */ void removeZoneView(ZoneViewWidget *item); - /** Closes all zone views. */ + /** @brief Closes all zone views. */ void clearViews(); - /** Closes the most recently added zone view. */ + /** @brief Closes the most recently added zone view. */ void closeMostRecentZoneView(); QTransform getViewTransform() const; QTransform getViewportTransform() const; @@ -205,10 +207,10 @@ public slots: void clearArrowsForPlayer(int playerId); protected: - /** Handles hover updates. */ + /** @brief Handles hover updates. */ bool event(QEvent *event) override; - /** Handles animation timer updates. */ + /** @brief Handles animation timer updates. */ void timerEvent(QTimerEvent *event) override; signals: diff --git a/cockatrice/src/game/game_state.h b/cockatrice/src/game/game_state.h index 54f6d9276..5a57d4321 100644 --- a/cockatrice/src/game/game_state.h +++ b/cockatrice/src/game/game_state.h @@ -1,8 +1,8 @@ /** * @file game_state.h * @ingroup GameLogic - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef COCKATRICE_GAME_STATE_H #define COCKATRICE_GAME_STATE_H diff --git a/cockatrice/src/game/game_view.h b/cockatrice/src/game/game_view.h index a77ab9257..15abad9af 100644 --- a/cockatrice/src/game/game_view.h +++ b/cockatrice/src/game/game_view.h @@ -1,8 +1,8 @@ /** * @file game_view.h * @ingroup GameGraphics - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef GAMEVIEW_H #define GAMEVIEW_H diff --git a/cockatrice/src/game/hand_counter.h b/cockatrice/src/game/hand_counter.h index 2c0175ecc..41ab3b5b2 100644 --- a/cockatrice/src/game/hand_counter.h +++ b/cockatrice/src/game/hand_counter.h @@ -1,8 +1,8 @@ /** * @file hand_counter.h * @ingroup GameGraphicsPlayers - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef HANDCOUNTER_H #define HANDCOUNTER_H diff --git a/cockatrice/src/game/log/message_log_widget.h b/cockatrice/src/game/log/message_log_widget.h index f8d70a52e..9f1990ac4 100644 --- a/cockatrice/src/game/log/message_log_widget.h +++ b/cockatrice/src/game/log/message_log_widget.h @@ -1,8 +1,8 @@ /** * @file message_log_widget.h * @ingroup GameWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef MESSAGELOGWIDGET_H #define MESSAGELOGWIDGET_H diff --git a/cockatrice/src/game/phase.h b/cockatrice/src/game/phase.h index 2e712932f..a888ad43b 100644 --- a/cockatrice/src/game/phase.h +++ b/cockatrice/src/game/phase.h @@ -1,8 +1,8 @@ /** * @file phase.h * @ingroup GameLogic - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef PHASE_H #define PHASE_H diff --git a/cockatrice/src/game/phases_toolbar.h b/cockatrice/src/game/phases_toolbar.h index dd2477424..6f0931d61 100644 --- a/cockatrice/src/game/phases_toolbar.h +++ b/cockatrice/src/game/phases_toolbar.h @@ -2,8 +2,8 @@ * @file phases_toolbar.h * @ingroup GameGraphics * @ingroup GameWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef PHASESTOOLBAR_H #define PHASESTOOLBAR_H diff --git a/cockatrice/src/game/player/card_menu_action_type.h b/cockatrice/src/game/player/card_menu_action_type.h index 1b63674fa..4cae22716 100644 --- a/cockatrice/src/game/player/card_menu_action_type.h +++ b/cockatrice/src/game/player/card_menu_action_type.h @@ -1,8 +1,8 @@ /** * @file card_menu_action_type.h * @ingroup GameMenusPlayers - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef COCKATRICE_CARD_MENU_ACTION_TYPE_H #define COCKATRICE_CARD_MENU_ACTION_TYPE_H diff --git a/cockatrice/src/game/player/event_processing_options.h b/cockatrice/src/game/player/event_processing_options.h index 3e743bdb3..4c7663789 100644 --- a/cockatrice/src/game/player/event_processing_options.h +++ b/cockatrice/src/game/player/event_processing_options.h @@ -1,8 +1,8 @@ /** * @file event_processing_options.h * @ingroup GameLogicPlayers - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef COCKATRICE_EVENT_PROCESSING_OPTIONS_H #define COCKATRICE_EVENT_PROCESSING_OPTIONS_H diff --git a/cockatrice/src/game/player/menu/abstract_player_component.h b/cockatrice/src/game/player/menu/abstract_player_component.h index 989300d41..ee310c428 100644 --- a/cockatrice/src/game/player/menu/abstract_player_component.h +++ b/cockatrice/src/game/player/menu/abstract_player_component.h @@ -19,13 +19,13 @@ class AbstractPlayerComponent public: virtual ~AbstractPlayerComponent() = default; - /// Bind keyboard shortcuts. Called when this player gains focus. + /** @brief Bind keyboard shortcuts. Called when this player gains focus. */ virtual void setShortcutsActive() = 0; - /// Unbind keyboard shortcuts. Called when this player loses focus. + /** @brief Unbind keyboard shortcuts. Called when this player loses focus. */ virtual void setShortcutsInactive() = 0; - /// Retranslate all user-visible strings. Called on language change. + /** @brief Retranslate all user-visible strings. Called on language change. */ virtual void retranslateUi() = 0; }; diff --git a/cockatrice/src/game/player/menu/card_menu.h b/cockatrice/src/game/player/menu/card_menu.h index d214d3557..ad3962caf 100644 --- a/cockatrice/src/game/player/menu/card_menu.h +++ b/cockatrice/src/game/player/menu/card_menu.h @@ -1,8 +1,8 @@ /** * @file card_menu.h * @ingroup GameMenusCards - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef COCKATRICE_CARD_MENU_H #define COCKATRICE_CARD_MENU_H diff --git a/cockatrice/src/game/player/menu/custom_zone_menu.h b/cockatrice/src/game/player/menu/custom_zone_menu.h index a6ea15892..e10f6a4f0 100644 --- a/cockatrice/src/game/player/menu/custom_zone_menu.h +++ b/cockatrice/src/game/player/menu/custom_zone_menu.h @@ -1,8 +1,8 @@ /** * @file custom_zone_menu.h * @ingroup GameMenusZones - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef COCKATRICE_CUSTOM_ZONE_MENU_H #define COCKATRICE_CUSTOM_ZONE_MENU_H diff --git a/cockatrice/src/game/player/menu/grave_menu.h b/cockatrice/src/game/player/menu/grave_menu.h index 167714013..d3d98802d 100644 --- a/cockatrice/src/game/player/menu/grave_menu.h +++ b/cockatrice/src/game/player/menu/grave_menu.h @@ -1,8 +1,8 @@ /** * @file grave_menu.h * @ingroup GameMenusZones - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef COCKATRICE_GRAVE_MENU_H #define COCKATRICE_GRAVE_MENU_H diff --git a/cockatrice/src/game/player/menu/hand_menu.h b/cockatrice/src/game/player/menu/hand_menu.h index 4fdd0d6fc..1e2ddd95a 100644 --- a/cockatrice/src/game/player/menu/hand_menu.h +++ b/cockatrice/src/game/player/menu/hand_menu.h @@ -1,8 +1,8 @@ /** * @file hand_menu.h * @ingroup GameMenusZones - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef COCKATRICE_HAND_MENU_H #define COCKATRICE_HAND_MENU_H diff --git a/cockatrice/src/game/player/menu/library_menu.h b/cockatrice/src/game/player/menu/library_menu.h index e69a395e2..a941c54b1 100644 --- a/cockatrice/src/game/player/menu/library_menu.h +++ b/cockatrice/src/game/player/menu/library_menu.h @@ -1,8 +1,8 @@ /** * @file library_menu.h * @ingroup GameMenusZones - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef COCKATRICE_LIBRARY_MENU_H #define COCKATRICE_LIBRARY_MENU_H diff --git a/cockatrice/src/game/player/menu/move_menu.h b/cockatrice/src/game/player/menu/move_menu.h index 59078a5c8..4e257b7fb 100644 --- a/cockatrice/src/game/player/menu/move_menu.h +++ b/cockatrice/src/game/player/menu/move_menu.h @@ -1,8 +1,8 @@ /** * @file move_menu.h * @ingroup GameMenusZones - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef COCKATRICE_MOVE_MENU_H #define COCKATRICE_MOVE_MENU_H diff --git a/cockatrice/src/game/player/menu/player_menu.h b/cockatrice/src/game/player/menu/player_menu.h index 78e810e62..d5c19df58 100644 --- a/cockatrice/src/game/player/menu/player_menu.h +++ b/cockatrice/src/game/player/menu/player_menu.h @@ -41,7 +41,7 @@ private slots: public: explicit PlayerMenu(PlayerLogic *player); - /// Lifecycle methods: delegate to all managedComponents, plus counters separately via player->getCounters(). + /** @brief Retranslate all user-visible strings. Called on language change. */ void retranslateUi(); QMenu *updateCardMenu(const CardItem *card); @@ -71,9 +71,9 @@ public: return shortcutsActive; } - /// Delegates to all managedComponents, plus counters separately. + /** @brief Bind keyboard shortcuts. Called when this player gains focus. */ void setShortcutsActive(); - /// Delegates to all managedComponents, plus counters separately. + /** @brief Unbind keyboard shortcuts. Called when this player loses focus. */ void setShortcutsInactive(); private: @@ -89,11 +89,13 @@ private: SayMenu *sayMenu; CustomZoneMenu *customZonesMenu; - /// Drives AbstractPlayerComponent lifecycle delegation. Counters are iterated separately via player->getCounters(). + /** @brief Drives AbstractPlayerComponent lifecycle delegation. Counters are iterated separately via + * player->getCounters(). + */ QList managedComponents; bool shortcutsActive = false; - /// Creates component, adds it as a submenu of playerMenu, and registers in managedComponents. + /** @brief Creates component, adds it as a submenu of playerMenu, and registers in managedComponents. */ template MenuT *addManagedMenu(Args &&...args) { auto *menu = new MenuT(std::forward(args)...); @@ -102,7 +104,7 @@ private: return menu; } - /// Creates component and registers in managedComponents, but does NOT add it as a submenu. + /** @brief Creates component and registers in managedComponents, but does NOT add it as a submenu. */ template ComponentT *createManagedComponent(Args &&...args) { auto *component = new ComponentT(std::forward(args)...); diff --git a/cockatrice/src/game/player/menu/pt_menu.h b/cockatrice/src/game/player/menu/pt_menu.h index a1cbd021c..645449586 100644 --- a/cockatrice/src/game/player/menu/pt_menu.h +++ b/cockatrice/src/game/player/menu/pt_menu.h @@ -1,8 +1,8 @@ /** * @file pt_menu.h * @ingroup GameMenusCards - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef COCKATRICE_PT_MENU_H #define COCKATRICE_PT_MENU_H diff --git a/cockatrice/src/game/player/menu/rfg_menu.h b/cockatrice/src/game/player/menu/rfg_menu.h index 7025169c8..9e179f8fd 100644 --- a/cockatrice/src/game/player/menu/rfg_menu.h +++ b/cockatrice/src/game/player/menu/rfg_menu.h @@ -1,8 +1,8 @@ /** * @file rfg_menu.h * @ingroup GameMenusZones - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef COCKATRICE_RFG_MENU_H #define COCKATRICE_RFG_MENU_H diff --git a/cockatrice/src/game/player/menu/say_menu.h b/cockatrice/src/game/player/menu/say_menu.h index 938990193..3de70e85c 100644 --- a/cockatrice/src/game/player/menu/say_menu.h +++ b/cockatrice/src/game/player/menu/say_menu.h @@ -1,8 +1,8 @@ /** * @file say_menu.h * @ingroup GameMenusPlayers - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef COCKATRICE_SAY_MENU_H #define COCKATRICE_SAY_MENU_H diff --git a/cockatrice/src/game/player/menu/sideboard_menu.h b/cockatrice/src/game/player/menu/sideboard_menu.h index b5385997f..20a206782 100644 --- a/cockatrice/src/game/player/menu/sideboard_menu.h +++ b/cockatrice/src/game/player/menu/sideboard_menu.h @@ -1,8 +1,8 @@ /** * @file sideboard_menu.h * @ingroup GameMenusZones - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef COCKATRICE_SIDEBOARD_MENU_H #define COCKATRICE_SIDEBOARD_MENU_H diff --git a/cockatrice/src/game/player/menu/utility_menu.h b/cockatrice/src/game/player/menu/utility_menu.h index 6d922d726..fab3211ca 100644 --- a/cockatrice/src/game/player/menu/utility_menu.h +++ b/cockatrice/src/game/player/menu/utility_menu.h @@ -1,8 +1,8 @@ /** * @file utility_menu.h * @ingroup GameMenusPlayers - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef COCKATRICE_UTILITY_MENU_H #define COCKATRICE_UTILITY_MENU_H diff --git a/cockatrice/src/game/player/player_actions.h b/cockatrice/src/game/player/player_actions.h index 535e37707..d294d2c40 100644 --- a/cockatrice/src/game/player/player_actions.h +++ b/cockatrice/src/game/player/player_actions.h @@ -2,8 +2,8 @@ * @file player_actions.h * @ingroup GameLogicActions * @ingroup GameLogicPlayers - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef COCKATRICE_PLAYER_ACTIONS_H #define COCKATRICE_PLAYER_ACTIONS_H diff --git a/cockatrice/src/game/player/player_area.h b/cockatrice/src/game/player/player_area.h index ec0d23cb6..6ffaf4958 100644 --- a/cockatrice/src/game/player/player_area.h +++ b/cockatrice/src/game/player/player_area.h @@ -1,8 +1,8 @@ /** * @file player_area.h * @ingroup GameGraphicsPlayers - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef COCKATRICE_PLAYER_AREA_H #define COCKATRICE_PLAYER_AREA_H diff --git a/cockatrice/src/game/player/player_event_handler.h b/cockatrice/src/game/player/player_event_handler.h index 84acbb8ea..958dee16b 100644 --- a/cockatrice/src/game/player/player_event_handler.h +++ b/cockatrice/src/game/player/player_event_handler.h @@ -1,8 +1,8 @@ /** * @file player_event_handler.h * @ingroup GameLogicPlayers - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef COCKATRICE_PLAYER_EVENT_HANDLER_H #define COCKATRICE_PLAYER_EVENT_HANDLER_H diff --git a/cockatrice/src/game/player/player_graphics_item.h b/cockatrice/src/game/player/player_graphics_item.h index 264654e9c..e37fe7290 100644 --- a/cockatrice/src/game/player/player_graphics_item.h +++ b/cockatrice/src/game/player/player_graphics_item.h @@ -1,8 +1,8 @@ /** * @file player_graphics_item.h * @ingroup GameGraphicsPlayers - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef COCKATRICE_PLAYER_GRAPHICS_ITEM_H #define COCKATRICE_PLAYER_GRAPHICS_ITEM_H diff --git a/cockatrice/src/game/player/player_info.h b/cockatrice/src/game/player/player_info.h index 36cb2a8bc..e67131ceb 100644 --- a/cockatrice/src/game/player/player_info.h +++ b/cockatrice/src/game/player/player_info.h @@ -1,8 +1,8 @@ /** * @file player_info.h * @ingroup GameLogicPlayers - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef COCKATRICE_PLAYER_INFO_H #define COCKATRICE_PLAYER_INFO_H diff --git a/cockatrice/src/game/player/player_list_widget.h b/cockatrice/src/game/player/player_list_widget.h index 1815fdccd..842c45873 100644 --- a/cockatrice/src/game/player/player_list_widget.h +++ b/cockatrice/src/game/player/player_list_widget.h @@ -1,8 +1,8 @@ /** * @file player_list_widget.h * @ingroup GameWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef PLAYERLISTWIDGET_H #define PLAYERLISTWIDGET_H diff --git a/cockatrice/src/game/player/player_logic.h b/cockatrice/src/game/player/player_logic.h index 138ed94ef..fdeef49ba 100644 --- a/cockatrice/src/game/player/player_logic.h +++ b/cockatrice/src/game/player/player_logic.h @@ -1,8 +1,8 @@ /** * @file player.h * @ingroup GameLogicPlayers - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef PLAYER_H #define PLAYER_H diff --git a/cockatrice/src/game/player/player_manager.h b/cockatrice/src/game/player/player_manager.h index 4f6d62a87..2f8b87af8 100644 --- a/cockatrice/src/game/player/player_manager.h +++ b/cockatrice/src/game/player/player_manager.h @@ -1,8 +1,8 @@ /** * @file player_manager.h * @ingroup GameLogicPlayers - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef COCKATRICE_PLAYER_MANAGER_H #define COCKATRICE_PLAYER_MANAGER_H diff --git a/cockatrice/src/game/player/player_target.h b/cockatrice/src/game/player/player_target.h index 0dd494ce3..d3facc60d 100644 --- a/cockatrice/src/game/player/player_target.h +++ b/cockatrice/src/game/player/player_target.h @@ -1,8 +1,8 @@ /** * @file player_target.h * @ingroup GameGraphicsPlayers - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef PLAYERTARGET_H #define PLAYERTARGET_H diff --git a/cockatrice/src/game/replay.h b/cockatrice/src/game/replay.h index 301f47580..b837e4b8c 100644 --- a/cockatrice/src/game/replay.h +++ b/cockatrice/src/game/replay.h @@ -2,8 +2,8 @@ * @file replay.h * @ingroup GameLogic * @ingroup Replay - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef COCKATRICE_REPLAY_H #define COCKATRICE_REPLAY_H diff --git a/cockatrice/src/game/z_value_layer_manager.h b/cockatrice/src/game/z_value_layer_manager.h index 4eb864486..d35ab5c1c 100644 --- a/cockatrice/src/game/z_value_layer_manager.h +++ b/cockatrice/src/game/z_value_layer_manager.h @@ -66,12 +66,9 @@ namespace ZValueLayerManager */ enum class Layer { - /// Zone-level elements like backgrounds and containers - Zone, - /// Cards rendered in zones (uses sequential Z-values) - Card, - /// Temporary UI elements like hovered cards and drag items - Overlay + Zone, ///< Zone-level elements like backgrounds and containers. + Card, ///< Cards rendered in zones (uses sequential Z-values). + Overlay ///< Temporary UI elements like hovered cards and drag items. }; /** diff --git a/cockatrice/src/game/zones/card_zone_logic.h b/cockatrice/src/game/zones/card_zone_logic.h index 63341343b..ae97719a9 100644 --- a/cockatrice/src/game/zones/card_zone_logic.h +++ b/cockatrice/src/game/zones/card_zone_logic.h @@ -1,8 +1,8 @@ /** * @file card_zone_logic.h * @ingroup GameLogicZones - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef COCKATRICE_CARD_ZONE_LOGIC_H #define COCKATRICE_CARD_ZONE_LOGIC_H diff --git a/cockatrice/src/game/zones/hand_zone_logic.h b/cockatrice/src/game/zones/hand_zone_logic.h index e5032b327..400506248 100644 --- a/cockatrice/src/game/zones/hand_zone_logic.h +++ b/cockatrice/src/game/zones/hand_zone_logic.h @@ -1,8 +1,8 @@ /** * @file hand_zone_logic.h * @ingroup GameLogicZones - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef COCKATRICE_HAND_ZONE_LOGIC_H #define COCKATRICE_HAND_ZONE_LOGIC_H diff --git a/cockatrice/src/game/zones/pile_zone_logic.h b/cockatrice/src/game/zones/pile_zone_logic.h index 68b39ec3a..522d99b89 100644 --- a/cockatrice/src/game/zones/pile_zone_logic.h +++ b/cockatrice/src/game/zones/pile_zone_logic.h @@ -1,8 +1,8 @@ /** * @file pile_zone_logic.h * @ingroup GameLogicZones - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef COCKATRICE_PILE_ZONE_LOGIC_H #define COCKATRICE_PILE_ZONE_LOGIC_H diff --git a/cockatrice/src/game/zones/stack_zone_logic.h b/cockatrice/src/game/zones/stack_zone_logic.h index a0ac65ebf..cce4bd0fa 100644 --- a/cockatrice/src/game/zones/stack_zone_logic.h +++ b/cockatrice/src/game/zones/stack_zone_logic.h @@ -1,8 +1,8 @@ /** * @file stack_zone_logic.h * @ingroup GameLogicZones - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef COCKATRICE_STACK_ZONE_LOGIC_H #define COCKATRICE_STACK_ZONE_LOGIC_H diff --git a/cockatrice/src/game/zones/table_zone_logic.h b/cockatrice/src/game/zones/table_zone_logic.h index 1e473d4ef..6d8d64a20 100644 --- a/cockatrice/src/game/zones/table_zone_logic.h +++ b/cockatrice/src/game/zones/table_zone_logic.h @@ -1,8 +1,8 @@ /** * @file table_zone_logic.h * @ingroup GameLogicZones - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef COCKATRICE_TABLE_ZONE_LOGIC_H #define COCKATRICE_TABLE_ZONE_LOGIC_H diff --git a/cockatrice/src/game/zones/view_zone_logic.h b/cockatrice/src/game/zones/view_zone_logic.h index ef0fb37f3..04ed20e45 100644 --- a/cockatrice/src/game/zones/view_zone_logic.h +++ b/cockatrice/src/game/zones/view_zone_logic.h @@ -1,8 +1,8 @@ /** * @file view_zone_logic.h * @ingroup GameLogicZones - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef COCKATRICE_VIEW_ZONE_LOGIC_H #define COCKATRICE_VIEW_ZONE_LOGIC_H diff --git a/cockatrice/src/game_graphics/board/abstract_graphics_item.h b/cockatrice/src/game_graphics/board/abstract_graphics_item.h index 93b9bff1b..287c2c0b3 100644 --- a/cockatrice/src/game_graphics/board/abstract_graphics_item.h +++ b/cockatrice/src/game_graphics/board/abstract_graphics_item.h @@ -1,8 +1,8 @@ /** * @file abstract_graphics_item.h * @ingroup GameGraphics - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef ABSTRACTGRAPHICSITEM_H #define ABSTRACTGRAPHICSITEM_H diff --git a/cockatrice/src/game_graphics/board/graphics_item_type.h b/cockatrice/src/game_graphics/board/graphics_item_type.h index c48ae4ed6..7eac132b0 100644 --- a/cockatrice/src/game_graphics/board/graphics_item_type.h +++ b/cockatrice/src/game_graphics/board/graphics_item_type.h @@ -1,8 +1,8 @@ /** * @file graphics_item_type.h * @ingroup GameGraphics - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef COCKATRICE_GRAPHICS_ITEM_TYPE_H #define COCKATRICE_GRAPHICS_ITEM_TYPE_H diff --git a/cockatrice/src/game_graphics/zones/card_zone.h b/cockatrice/src/game_graphics/zones/card_zone.h index 80226de3c..4cef6ca80 100644 --- a/cockatrice/src/game_graphics/zones/card_zone.h +++ b/cockatrice/src/game_graphics/zones/card_zone.h @@ -40,9 +40,12 @@ protected: } public slots: bool showContextMenu(const QPoint &screenPos); - /// @brief Called when a card is added to this zone. Default: reparents card to this item. - /// Virtual so subclasses (e.g. SelectZone) can override parenting behavior — the Qt signal - /// connection in CardZone's constructor dispatches through the vtable. + /** + * @brief Called when a card is added to this zone. Default: reparents card to this item. + * + * Virtual so subclasses (e.g. SelectZone) can override parenting behavior — the Qt signal + * connection in CardZone's constructor dispatches through the vtable. + */ virtual void onCardAdded(CardItem *addedCard); public: diff --git a/cockatrice/src/game_graphics/zones/pile_zone.h b/cockatrice/src/game_graphics/zones/pile_zone.h index 8cf04676d..099bc6f60 100644 --- a/cockatrice/src/game_graphics/zones/pile_zone.h +++ b/cockatrice/src/game_graphics/zones/pile_zone.h @@ -1,8 +1,8 @@ /** * @file pile_zone.h * @ingroup GameGraphicsZones - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef PILEZONE_H #define PILEZONE_H diff --git a/cockatrice/src/game_graphics/zones/select_zone.h b/cockatrice/src/game_graphics/zones/select_zone.h index 1da5c1988..7408f29b6 100644 --- a/cockatrice/src/game_graphics/zones/select_zone.h +++ b/cockatrice/src/game_graphics/zones/select_zone.h @@ -21,33 +21,41 @@ class SelectZone : public CardZone { Q_OBJECT public: - /// Finds the SelectZone that owns a card, regardless of whether the card is parented - /// to the zone directly or to its clip container. Returns nullptr if not in a SelectZone. + /** + * @brief Finds the SelectZone that owns a card, regardless of whether the card is parented + * to the zone directly or to its clip container. Returns nullptr if not in a SelectZone. + */ static SelectZone *findOwningSelectZone(const QGraphicsItem *card); SelectZone(CardZoneLogic *logic, QGraphicsItem *parent = nullptr); ~SelectZone() override; void onCardAdded(CardItem *addedCard) override; - /// @brief Temporarily reparents a card from the clip container to this zone so hover scaling is visible beyond clip - /// bounds. Safe no-op if no clip container exists. Coordinates are preserved (clip container is at (0,0) with no - /// transform). + /** + * @brief Temporarily reparents a card from the clip container to this zone so hover scaling is visible beyond clip + * bounds. Safe no-op if no clip container exists. Coordinates are preserved (clip container is at (0,0) with no + * transform). + */ void escapeClipForHover(QGraphicsItem *card); - /// @brief Restores a hover-escaped card back to the clip container. Guards against zone transitions that already - /// reparented the card. + /** + * @brief Restores a hover-escaped card back to the clip container. Guards against zone transitions that already + * reparented the card. + */ void restoreClipAfterHover(QGraphicsItem *card); private: QPointF selectionOrigin; QSet cardsInSelectionRect; - /// Invisible clipping parent for cards; owned by Qt parent-child tree (parented to this zone). - /// Created by setupClipContainer(); null when no clip container is active. + /** + * @brief Invisible clipping parent for cards; owned by Qt parent-child tree (parented to this zone). + * Created by setupClipContainer(); null when no clip container is active. + */ QGraphicsRectItem *cardClipContainer = nullptr; protected: // -- Layout computation -- - /// Parameters describing a vertical card stack's geometry. + /** @brief Parameters describing a vertical card stack's geometry. */ struct StackLayoutParams { int cardCount; ///< Number of cards in the stack @@ -55,21 +63,23 @@ protected: qreal cardHeight; ///< Height of a single card qreal desiredOffset; ///< Preferred vertical offset between card tops qreal minOffset = 0.0; ///< Minimum offset to preserve (0 allows full compression) - /// When false (default), reserves full cardHeight for the bottom card, ensuring - /// all cards remain within zone bounds. When true, allows the bottom card to - /// partially overflow using sqrt-scaled allowance. Use with setupClipContainer() - /// for zones too short to fit a full card. + /** + * @brief When false (default), reserves full cardHeight for the bottom card, ensuring + * all cards remain within zone bounds. When true, allows the bottom card to + * partially overflow using sqrt-scaled allowance. Use with setupClipContainer() + * for zones too short to fit a full card. + */ bool allowBottomOverflow = false; }; - /// Result of computing a vertical stack layout. + /** @brief Result of computing a vertical stack layout. */ struct ZoneLayout { qreal effectiveOffset; ///< Actual offset between card tops (may be compressed) qreal start; ///< Y coordinate of the first card's top edge }; - /// Minimum visible pixels of each card's top edge when stacking compresses offsets in tight zones. + /** @brief Minimum visible pixels of each card's top edge when stacking compresses offsets in tight zones. */ static constexpr qreal MIN_CARD_VISIBLE = 10.0; /** @@ -88,11 +98,13 @@ protected: */ static ZoneLayout computeZoneLayout(const StackLayoutParams ¶ms); - /// Builds StackLayoutParams from the current card list and zone geometry. + /** @brief Builds StackLayoutParams from the current card list and zone geometry. */ StackLayoutParams buildStackParams(qreal minOffset = 0.0) const; - /// Computes the card index at a given y-coordinate within the zone's vertical layout. - /// Returns 0 if the zone has no cards or the offset is zero. + /** + * @brief Computes the card index at a given y-coordinate within the zone's vertical layout. + * Returns 0 if the zone has no cards or the offset is zero. + */ int calcDropIndexFromY(qreal dropY, qreal minOffset = 0.0) const; /** @@ -111,17 +123,21 @@ protected: // (e.g., zones too short to fit a full card). To enable: call setupClipContainer() in the // zone's constructor, and set allowBottomOverflow=true in layout params. - /// Restores any cards that were hover-escaped but whose hover state was not properly cleaned up. - /// Call at the start of reorganizeCards() in zones that use a clip container. + /** + * @brief Restores any cards that were hover-escaped but whose hover state was not properly cleaned up. + * Call at the start of reorganizeCards() in zones that use a clip container. + */ void restoreStaleEscapedCards(); - /// Creates a clip container child item that clips card overflow to zone bounds. - /// Cards entering this zone are reparented to this container by the onCardAdded override. - /// Disables zone-level child clipping; clipping is delegated to the container. - /// @param zValue Optional z-value for the clip container (e.g. ZValues::CARD_BASE) + /** + * @brief Creates a clip container child item that clips card overflow to zone bounds. + * Cards entering this zone are reparented to this container by the onCardAdded override. + * Disables zone-level child clipping; clipping is delegated to the container. + * @param zValue Optional z-value for the clip container (e.g. ZValues::CARD_BASE) + */ void setupClipContainer(std::optional zValue = std::nullopt); - /// Updates the clip container rect to match this zone's current boundingRect(). + /** @brief Updates the clip container rect to match this zone's current boundingRect(). */ void updateClipRect(); void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override; diff --git a/cockatrice/src/game_graphics/zones/stack_zone.h b/cockatrice/src/game_graphics/zones/stack_zone.h index ed13ae1f9..147c3e2fc 100644 --- a/cockatrice/src/game_graphics/zones/stack_zone.h +++ b/cockatrice/src/game_graphics/zones/stack_zone.h @@ -20,7 +20,7 @@ private slots: public: StackZone(StackZoneLogic *_logic, int _zoneHeight, QGraphicsItem *parent); - /// @brief Resizes the stack zone height, e.g. when sharing vertical space with the command zone. + /** @brief Resizes the stack zone height, e.g. when sharing vertical space with the command zone. */ void setHeight(qreal newHeight); void handleDropEvent(const QList &dragItems, CardZoneLogic *startZone, const QPoint &dropPoint) override; diff --git a/cockatrice/src/game_graphics/zones/table_zone.h b/cockatrice/src/game_graphics/zones/table_zone.h index b5e941782..f46531520 100644 --- a/cockatrice/src/game_graphics/zones/table_zone.h +++ b/cockatrice/src/game_graphics/zones/table_zone.h @@ -1,8 +1,8 @@ /** * @file table_zone.h * @ingroup GameGraphicsZones - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef TABLEZONE_H #define TABLEZONE_H @@ -11,13 +11,12 @@ #include "../../game/zones/table_zone_logic.h" #include "select_zone.h" -/* - * TableZone is the grid based rect where CardItems may be placed. - * It is the main play zone and can be customized with background images. +/** + * @brief TableZone is the grid based rect where CardItems may be placed. * - * TODO: Refactor methods to make more readable, extract some logic to - * private methods (Im looking at you TableZone::reorganizeCards()) + * It is the main play zone and can be customized with background images. */ +//! \todo Refactor methods to make more readable, extract logic to private methods (especially reorganizeCards()). class TableZone : public SelectZone { Q_OBJECT diff --git a/cockatrice/src/game_graphics/zones/view_zone.h b/cockatrice/src/game_graphics/zones/view_zone.h index 65e4846d0..9dfa00ce2 100644 --- a/cockatrice/src/game_graphics/zones/view_zone.h +++ b/cockatrice/src/game_graphics/zones/view_zone.h @@ -1,8 +1,8 @@ /** * @file view_zone.h * @ingroup GameGraphicsZones - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef ZONEVIEWERZONE_H #define ZONEVIEWERZONE_H diff --git a/cockatrice/src/game_graphics/zones/view_zone_widget.h b/cockatrice/src/game_graphics/zones/view_zone_widget.h index 6d59a5429..de5ad28d5 100644 --- a/cockatrice/src/game_graphics/zones/view_zone_widget.h +++ b/cockatrice/src/game_graphics/zones/view_zone_widget.h @@ -1,8 +1,8 @@ /** * @file view_zone_widget.h * @ingroup GameGraphicsZones - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef ZONEVIEWWIDGET_H #define ZONEVIEWWIDGET_H diff --git a/cockatrice/src/interface/card_picture_loader/card_picture_to_load.cpp b/cockatrice/src/interface/card_picture_loader/card_picture_to_load.cpp index f95d8ec8f..63846e5fd 100644 --- a/cockatrice/src/interface/card_picture_loader/card_picture_to_load.cpp +++ b/cockatrice/src/interface/card_picture_loader/card_picture_to_load.cpp @@ -53,12 +53,12 @@ QList CardPictureToLoad::extractSetsSorted(const ExactCard &card) * PrintingInfo for the set is returned. * * This method only exists to maintain existing behavior. - * TODO: check if going through all sets is still necessary after the ExactCard refactor. * * @param card The card to look in * @param setName The set's short name * @return A PrintingInfo, or a default-constructed PrintingInfo if the set name is not in the CardInfo. */ +//! \todo Check if going through all sets is still necessary after the ExactCard refactor. static PrintingInfo findPrintingForSet(const ExactCard &card, const QString &setName) { SetToPrintingsMap setsToPrintings = card.getInfo().getSets(); diff --git a/cockatrice/src/interface/deck_loader/deck_loader.h b/cockatrice/src/interface/deck_loader/deck_loader.h index c707c33dc..ac23e1ee0 100644 --- a/cockatrice/src/interface/deck_loader/deck_loader.h +++ b/cockatrice/src/interface/deck_loader/deck_loader.h @@ -1,8 +1,8 @@ /** * @file deck_loader.h * @ingroup ImportExport - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef DECK_LOADER_H #define DECK_LOADER_H diff --git a/cockatrice/src/interface/key_signals.h b/cockatrice/src/interface/key_signals.h index 3404dca9e..30dcee0ba 100644 --- a/cockatrice/src/interface/key_signals.h +++ b/cockatrice/src/interface/key_signals.h @@ -2,8 +2,8 @@ * @file key_signals.h * @ingroup Core * @ingroup UI - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef KEYSIGNALS_H #define KEYSIGNALS_H diff --git a/cockatrice/src/interface/layouts/flow_layout.h b/cockatrice/src/interface/layouts/flow_layout.h index cc206afae..9adcd8bb5 100644 --- a/cockatrice/src/interface/layouts/flow_layout.h +++ b/cockatrice/src/interface/layouts/flow_layout.h @@ -4,6 +4,7 @@ * @brief A QLayout subclass that arranges child widgets in wrapping rows (horizontal flow) * or wrapping columns (vertical flow). */ +//! \todo Document this file. #ifndef FLOW_LAYOUT_H #define FLOW_LAYOUT_H diff --git a/cockatrice/src/interface/layouts/overlap_layout.cpp b/cockatrice/src/interface/layouts/overlap_layout.cpp index 9bf5e8468..a4c13518a 100644 --- a/cockatrice/src/interface/layouts/overlap_layout.cpp +++ b/cockatrice/src/interface/layouts/overlap_layout.cpp @@ -223,7 +223,7 @@ void OverlapLayout::setGeometry(const QRect &rect) const int yPos = rect.top() + currentRow * (maxItemHeight - overlapOffsetHeight); item->setGeometry(QRect(xPos, yPos, maxItemWidth, maxItemHeight)); - // TODO: Figure this out properly or maybe adjust size hint to account for this? + //! \todo Figure this out properly or maybe adjust size hint to account for this. // Update row and column indices based on the layout direction. if (overlapDirection == Qt::Horizontal) { currentColumn++; diff --git a/cockatrice/src/interface/layouts/overlap_layout.h b/cockatrice/src/interface/layouts/overlap_layout.h index 5844fca41..c1b6a8e51 100644 --- a/cockatrice/src/interface/layouts/overlap_layout.h +++ b/cockatrice/src/interface/layouts/overlap_layout.h @@ -1,8 +1,8 @@ /** * @file overlap_layout.h * @ingroup UI - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef OVERLAP_LAYOUT_H #define OVERLAP_LAYOUT_H diff --git a/cockatrice/src/interface/logger.h b/cockatrice/src/interface/logger.h index 59244e226..fc6dd70be 100644 --- a/cockatrice/src/interface/logger.h +++ b/cockatrice/src/interface/logger.h @@ -1,8 +1,8 @@ /** * @file logger.h * @ingroup Core - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef LOGGER_H #define LOGGER_H diff --git a/cockatrice/src/interface/pixel_map_generator.h b/cockatrice/src/interface/pixel_map_generator.h index 36d1e45f3..22f44d8db 100644 --- a/cockatrice/src/interface/pixel_map_generator.h +++ b/cockatrice/src/interface/pixel_map_generator.h @@ -1,8 +1,8 @@ /** * @file pixel_map_generator.h * @ingroup UI - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef PIXMAPGENERATOR_H #define PIXMAPGENERATOR_H diff --git a/cockatrice/src/interface/theme_manager.cpp b/cockatrice/src/interface/theme_manager.cpp index abdc02eef..086845fe6 100644 --- a/cockatrice/src/interface/theme_manager.cpp +++ b/cockatrice/src/interface/theme_manager.cpp @@ -92,7 +92,7 @@ struct PaletteColorInfo ThemeManager::ThemeManager(QObject *parent) : QObject(parent) { defaultStyleName = qApp->style()->objectName(); - // FIXME workaround for windows11 style being broken + //! \todo Workaround for windows11 style being broken. if (defaultStyleName == "windows11") { defaultStyleName = "windowsvista"; } diff --git a/cockatrice/src/interface/theme_manager.h b/cockatrice/src/interface/theme_manager.h index 4b1fd2026..b9e764d08 100644 --- a/cockatrice/src/interface/theme_manager.h +++ b/cockatrice/src/interface/theme_manager.h @@ -1,8 +1,8 @@ /** * @file theme_manager.h * @ingroup CoreSettings - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef THEMEMANAGER_H #define THEMEMANAGER_H diff --git a/cockatrice/src/interface/widgets/cards/additional_info/color_identity_widget.h b/cockatrice/src/interface/widgets/cards/additional_info/color_identity_widget.h index 6512ba890..f776d4c77 100644 --- a/cockatrice/src/interface/widgets/cards/additional_info/color_identity_widget.h +++ b/cockatrice/src/interface/widgets/cards/additional_info/color_identity_widget.h @@ -1,8 +1,8 @@ /** * @file color_identity_widget.h * @ingroup CardExtraInfoWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef COLOR_IDENTITY_WIDGET_H #define COLOR_IDENTITY_WIDGET_H diff --git a/cockatrice/src/interface/widgets/cards/additional_info/mana_cost_widget.h b/cockatrice/src/interface/widgets/cards/additional_info/mana_cost_widget.h index 26a186c59..b2f6b62c0 100644 --- a/cockatrice/src/interface/widgets/cards/additional_info/mana_cost_widget.h +++ b/cockatrice/src/interface/widgets/cards/additional_info/mana_cost_widget.h @@ -1,8 +1,8 @@ /** * @file mana_cost_widget.h * @ingroup CardExtraInfoWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef MANA_COST_WIDGET_H #define MANA_COST_WIDGET_H diff --git a/cockatrice/src/interface/widgets/cards/additional_info/mana_symbol_widget.h b/cockatrice/src/interface/widgets/cards/additional_info/mana_symbol_widget.h index 8d2c6813f..0f2d7acd1 100644 --- a/cockatrice/src/interface/widgets/cards/additional_info/mana_symbol_widget.h +++ b/cockatrice/src/interface/widgets/cards/additional_info/mana_symbol_widget.h @@ -1,8 +1,8 @@ /** * @file mana_symbol_widget.h * @ingroup CardExtraInfoWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef MANA_SYMBOL_WIDGET_H #define MANA_SYMBOL_WIDGET_H diff --git a/cockatrice/src/interface/widgets/cards/card_group_display_widgets/card_group_display_widget.h b/cockatrice/src/interface/widgets/cards/card_group_display_widgets/card_group_display_widget.h index 0f1209b29..848bebb7e 100644 --- a/cockatrice/src/interface/widgets/cards/card_group_display_widgets/card_group_display_widget.h +++ b/cockatrice/src/interface/widgets/cards/card_group_display_widgets/card_group_display_widget.h @@ -1,8 +1,8 @@ /** * @file card_group_display_widget.h * @ingroup DeckEditorCardGroupWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef CARD_GROUP_DISPLAY_WIDGET_H #define CARD_GROUP_DISPLAY_WIDGET_H diff --git a/cockatrice/src/interface/widgets/cards/card_group_display_widgets/flat_card_group_display_widget.h b/cockatrice/src/interface/widgets/cards/card_group_display_widgets/flat_card_group_display_widget.h index e07152b34..0772c1ab4 100644 --- a/cockatrice/src/interface/widgets/cards/card_group_display_widgets/flat_card_group_display_widget.h +++ b/cockatrice/src/interface/widgets/cards/card_group_display_widgets/flat_card_group_display_widget.h @@ -1,8 +1,8 @@ /** * @file flat_card_group_display_widget.h * @ingroup DeckEditorCardGroupWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef FLAT_CARD_GROUP_DISPLAY_WIDGET_H #define FLAT_CARD_GROUP_DISPLAY_WIDGET_H diff --git a/cockatrice/src/interface/widgets/cards/card_group_display_widgets/overlapped_card_group_display_widget.h b/cockatrice/src/interface/widgets/cards/card_group_display_widgets/overlapped_card_group_display_widget.h index 288e46129..5b4b80d6b 100644 --- a/cockatrice/src/interface/widgets/cards/card_group_display_widgets/overlapped_card_group_display_widget.h +++ b/cockatrice/src/interface/widgets/cards/card_group_display_widgets/overlapped_card_group_display_widget.h @@ -1,8 +1,8 @@ /** * @file overlapped_card_group_display_widget.h * @ingroup DeckEditorCardGroupWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef OVERLAPPED_CARD_GROUP_DISPLAY_WIDGET_H #define OVERLAPPED_CARD_GROUP_DISPLAY_WIDGET_H diff --git a/cockatrice/src/interface/widgets/cards/card_info_display_widget.h b/cockatrice/src/interface/widgets/cards/card_info_display_widget.h index d44c4c205..f8f33f3d4 100644 --- a/cockatrice/src/interface/widgets/cards/card_info_display_widget.h +++ b/cockatrice/src/interface/widgets/cards/card_info_display_widget.h @@ -1,8 +1,8 @@ /** * @file card_info_display_widget.h * @ingroup CardWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef CARDINFOWIDGET_H #define CARDINFOWIDGET_H diff --git a/cockatrice/src/interface/widgets/cards/card_info_frame_widget.h b/cockatrice/src/interface/widgets/cards/card_info_frame_widget.h index 11b991e87..e766fac7a 100644 --- a/cockatrice/src/interface/widgets/cards/card_info_frame_widget.h +++ b/cockatrice/src/interface/widgets/cards/card_info_frame_widget.h @@ -1,8 +1,8 @@ /** * @file card_info_frame_widget.h * @ingroup CardWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef CARDFRAME_H #define CARDFRAME_H diff --git a/cockatrice/src/interface/widgets/cards/card_info_picture_art_crop_widget.h b/cockatrice/src/interface/widgets/cards/card_info_picture_art_crop_widget.h index 0185f758c..ce22a1a44 100644 --- a/cockatrice/src/interface/widgets/cards/card_info_picture_art_crop_widget.h +++ b/cockatrice/src/interface/widgets/cards/card_info_picture_art_crop_widget.h @@ -1,8 +1,8 @@ /** * @file card_info_picture_art_crop_widget.h * @ingroup CardWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef CARD_INFO_PICTURE_ART_CROP_WIDGET_H #define CARD_INFO_PICTURE_ART_CROP_WIDGET_H diff --git a/cockatrice/src/interface/widgets/cards/card_info_picture_enlarged_widget.h b/cockatrice/src/interface/widgets/cards/card_info_picture_enlarged_widget.h index 10eb32940..a158ac6cf 100644 --- a/cockatrice/src/interface/widgets/cards/card_info_picture_enlarged_widget.h +++ b/cockatrice/src/interface/widgets/cards/card_info_picture_enlarged_widget.h @@ -2,8 +2,8 @@ * @file card_info_picture_enlarged_widget.h * @ingroup CardWigets * @ingroup DeckEditorWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef CARD_PICTURE_ENLARGED_WIDGET_H #define CARD_PICTURE_ENLARGED_WIDGET_H diff --git a/cockatrice/src/interface/widgets/cards/card_info_picture_widget.h b/cockatrice/src/interface/widgets/cards/card_info_picture_widget.h index 5eb2d88d9..bfa6584b1 100644 --- a/cockatrice/src/interface/widgets/cards/card_info_picture_widget.h +++ b/cockatrice/src/interface/widgets/cards/card_info_picture_widget.h @@ -1,8 +1,8 @@ /** * @file card_info_picture_widget.h * @ingroup CardWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef CARD_INFO_PICTURE_H #define CARD_INFO_PICTURE_H diff --git a/cockatrice/src/interface/widgets/cards/card_info_picture_with_text_overlay_widget.h b/cockatrice/src/interface/widgets/cards/card_info_picture_with_text_overlay_widget.h index eed827292..0cc7e501c 100644 --- a/cockatrice/src/interface/widgets/cards/card_info_picture_with_text_overlay_widget.h +++ b/cockatrice/src/interface/widgets/cards/card_info_picture_with_text_overlay_widget.h @@ -2,8 +2,8 @@ * @file card_info_picture_with_text_overlay_widget.h * @ingroup CardWidgets * @ingroup DeckStorageWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef CARD_PICTURE_WITH_TEXT_OVERLAY_H #define CARD_PICTURE_WITH_TEXT_OVERLAY_H diff --git a/cockatrice/src/interface/widgets/cards/card_info_text_widget.h b/cockatrice/src/interface/widgets/cards/card_info_text_widget.h index 95b588882..a9c29da37 100644 --- a/cockatrice/src/interface/widgets/cards/card_info_text_widget.h +++ b/cockatrice/src/interface/widgets/cards/card_info_text_widget.h @@ -1,8 +1,8 @@ /** * @file card_info_text_widget.h * @ingroup CardWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef CARDINFOTEXT_H #define CARDINFOTEXT_H diff --git a/cockatrice/src/interface/widgets/cards/card_size_widget.h b/cockatrice/src/interface/widgets/cards/card_size_widget.h index 638c263ea..9f4c165fd 100644 --- a/cockatrice/src/interface/widgets/cards/card_size_widget.h +++ b/cockatrice/src/interface/widgets/cards/card_size_widget.h @@ -3,8 +3,8 @@ * @ingroup CardWidgets * @ingroup DeckEditorWidgets * @ingroup DeckStorageWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef CARD_SIZE_WIDGET_H #define CARD_SIZE_WIDGET_H diff --git a/cockatrice/src/interface/widgets/cards/deck_card_zone_display_widget.h b/cockatrice/src/interface/widgets/cards/deck_card_zone_display_widget.h index dc0f3d734..074a77e53 100644 --- a/cockatrice/src/interface/widgets/cards/deck_card_zone_display_widget.h +++ b/cockatrice/src/interface/widgets/cards/deck_card_zone_display_widget.h @@ -1,8 +1,8 @@ /** * @file deck_card_zone_display_widget.h * @ingroup DeckEditorWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef DECK_CARD_ZONE_DISPLAY_WIDGET_H #define DECK_CARD_ZONE_DISPLAY_WIDGET_H diff --git a/cockatrice/src/interface/widgets/cards/deck_preview_card_picture_widget.h b/cockatrice/src/interface/widgets/cards/deck_preview_card_picture_widget.h index acb67a49a..154e938aa 100644 --- a/cockatrice/src/interface/widgets/cards/deck_preview_card_picture_widget.h +++ b/cockatrice/src/interface/widgets/cards/deck_preview_card_picture_widget.h @@ -2,8 +2,8 @@ * @file deck_preview_card_picture_widget.h * @ingroup CardWidgets * @ingroup Lobby - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef DECK_PREVIEW_CARD_PICTURE_WIDGET_H #define DECK_PREVIEW_CARD_PICTURE_WIDGET_H diff --git a/cockatrice/src/interface/widgets/deck_analytics/analyzer_modules/mana_base/mana_base_widget.h b/cockatrice/src/interface/widgets/deck_analytics/analyzer_modules/mana_base/mana_base_widget.h index 39380c07e..85b2a13b3 100644 --- a/cockatrice/src/interface/widgets/deck_analytics/analyzer_modules/mana_base/mana_base_widget.h +++ b/cockatrice/src/interface/widgets/deck_analytics/analyzer_modules/mana_base/mana_base_widget.h @@ -1,8 +1,8 @@ /** * @file mana_base_widget.h * @ingroup DeckEditorAnalyticsWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef MANA_BASE_WIDGET_H #define MANA_BASE_WIDGET_H diff --git a/cockatrice/src/interface/widgets/deck_analytics/analyzer_modules/mana_curve/mana_curve_widget.h b/cockatrice/src/interface/widgets/deck_analytics/analyzer_modules/mana_curve/mana_curve_widget.h index da59da9a8..d3e56d44c 100644 --- a/cockatrice/src/interface/widgets/deck_analytics/analyzer_modules/mana_curve/mana_curve_widget.h +++ b/cockatrice/src/interface/widgets/deck_analytics/analyzer_modules/mana_curve/mana_curve_widget.h @@ -1,8 +1,8 @@ /** * @file mana_curve_widget.h * @ingroup DeckEditorAnalyticsWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef MANA_CURVE_WIDGET_H #define MANA_CURVE_WIDGET_H @@ -37,7 +37,7 @@ public: { config = ManaCurveConfig::fromJson(o); updateDisplay(); - }; + } QJsonObject extractConfigFromDialog(QDialog *dlg) const override; diff --git a/cockatrice/src/interface/widgets/deck_analytics/analyzer_modules/mana_devotion/mana_devotion_widget.h b/cockatrice/src/interface/widgets/deck_analytics/analyzer_modules/mana_devotion/mana_devotion_widget.h index 833f12938..af0215305 100644 --- a/cockatrice/src/interface/widgets/deck_analytics/analyzer_modules/mana_devotion/mana_devotion_widget.h +++ b/cockatrice/src/interface/widgets/deck_analytics/analyzer_modules/mana_devotion/mana_devotion_widget.h @@ -1,8 +1,8 @@ /** * @file mana_devotion_widget.h * @ingroup DeckEditorAnalyticsWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef MANA_DEVOTION_WIDGET_H #define MANA_DEVOTION_WIDGET_H diff --git a/cockatrice/src/interface/widgets/deck_editor/deck_editor_deck_dock_widget.cpp b/cockatrice/src/interface/widgets/deck_editor/deck_editor_deck_dock_widget.cpp index 25d9db079..f751fa225 100644 --- a/cockatrice/src/interface/widgets/deck_editor/deck_editor_deck_dock_widget.cpp +++ b/cockatrice/src/interface/widgets/deck_editor/deck_editor_deck_dock_widget.cpp @@ -531,7 +531,7 @@ void DeckEditorDeckDockWidget::changeSelectedCard(int changeBy) // currentIndex will return an index for the underlying deckModel instead of the proxy. // That index will return an invalid index when indexBelow/indexAbove crosses a header node, // causing the selection to fail to move down. - /// \todo Figure out why it's happening so we can do a proper fix instead of a hacky workaround + //! \todo Figure out why it's happening so we can do a proper fix instead of a hacky workaround. if (deckViewCurrentIndex.model() == proxy->sourceModel()) { deckViewCurrentIndex = proxy->mapFromSource(deckViewCurrentIndex); } @@ -635,8 +635,8 @@ void DeckEditorDeckDockWidget::actSwapSelection() { auto selectedRows = getSelectedCardNodeSourceIndices(); - // hack to maintain the old reselection behavior when currently selected row of a single-selection gets deleted - // TODO: remove the hack and also handle reselection when all rows of a multi-selection gets deleted + //! \todo Remove the hack and also handle reselection when all rows of a multi-selection gets deleted. + // Hack: maintains old reselection behavior when single-selection row is deleted. if (selectedRows.length() == 1) { deckView->setSelectionMode(QAbstractItemView::SingleSelection); } @@ -666,8 +666,8 @@ void DeckEditorDeckDockWidget::actDecrementSelection() { auto selectedRows = getSelectedCardNodeSourceIndices(); - // hack to maintain the old reselection behavior when currently selected row of a single-selection gets deleted - // TODO: remove the hack and also handle reselection when all rows of a multi-selection gets deleted + //! \todo Remove the hack and also handle reselection when all rows of a multi-selection gets deleted. + // Hack: maintains old reselection behavior when single-selection row is deleted. if (selectedRows.length() == 1) { deckView->setSelectionMode(QAbstractItemView::SingleSelection); } @@ -683,8 +683,8 @@ void DeckEditorDeckDockWidget::actRemoveCard() { auto selectedRows = getSelectedCardNodeSourceIndices(); - // hack to maintain the old reselection behavior when currently selected row of a single-selection gets deleted - // TODO: remove the hack and also handle reselection when all rows of a multi-selection gets deleted + //! \todo Remove the hack and also handle reselection when all rows of a multi-selection gets deleted. + // Hack: maintains old reselection behavior when single-selection row is deleted. if (selectedRows.length() == 1) { deckView->setSelectionMode(QAbstractItemView::SingleSelection); } diff --git a/cockatrice/src/interface/widgets/deck_editor/deck_state_manager.h b/cockatrice/src/interface/widgets/deck_editor/deck_state_manager.h index 4f1ec7e04..10312d0a0 100644 --- a/cockatrice/src/interface/widgets/deck_editor/deck_state_manager.h +++ b/cockatrice/src/interface/widgets/deck_editor/deck_state_manager.h @@ -154,9 +154,11 @@ public: */ QModelIndex modifyDeck(const QString &reason, const std::function &operation); - /// @name Metadata setters - /// @brief These methods set the metadata. Will no-op if the new value is the same as the current value. - /// Saves the operation to history if successful. + /** + * @name Metadata setters + * @brief These methods set the metadata. Will no-op if the new value is the same as the current value. + * Saves the operation to history if successful. + */ ///@{ void setName(const QString &name); void setComments(const QString &comments); diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_connect.h b/cockatrice/src/interface/widgets/dialogs/dlg_connect.h index 41993e068..083dad0ad 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_connect.h +++ b/cockatrice/src/interface/widgets/dialogs/dlg_connect.h @@ -1,8 +1,8 @@ /** * @file dlg_connect.h * @ingroup ConnectionDialogs - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef DLG_CONNECT_H #define DLG_CONNECT_H diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_convert_deck_to_cod_format.h b/cockatrice/src/interface/widgets/dialogs/dlg_convert_deck_to_cod_format.h index 61eea1d6e..6642ad8c6 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_convert_deck_to_cod_format.h +++ b/cockatrice/src/interface/widgets/dialogs/dlg_convert_deck_to_cod_format.h @@ -2,8 +2,8 @@ * @file dlg_convert_deck_to_cod_format.h * @ingroup LocalDeckStorageDialogs * @ingroup Lobby - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef DIALOG_CONVERT_DECK_TO_COD_FORMAT_H #define DIALOG_CONVERT_DECK_TO_COD_FORMAT_H diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_create_game.h b/cockatrice/src/interface/widgets/dialogs/dlg_create_game.h index e28363311..61925286d 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_create_game.h +++ b/cockatrice/src/interface/widgets/dialogs/dlg_create_game.h @@ -1,8 +1,8 @@ /** * @file dlg_create_game.h * @ingroup RoomDialogs - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef DLG_CREATEGAME_H #define DLG_CREATEGAME_H diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_default_tags_editor.h b/cockatrice/src/interface/widgets/dialogs/dlg_default_tags_editor.h index 27af74105..e584d0731 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_default_tags_editor.h +++ b/cockatrice/src/interface/widgets/dialogs/dlg_default_tags_editor.h @@ -2,8 +2,8 @@ * @file dlg_default_tags_editor.h * @ingroup Dialogs * @ingroup DeckStorageWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef DLG_DEFAULT_TAGS_EDITOR_H #define DLG_DEFAULT_TAGS_EDITOR_H diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_edit_avatar.h b/cockatrice/src/interface/widgets/dialogs/dlg_edit_avatar.h index 641b736dc..d635ac2a8 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_edit_avatar.h +++ b/cockatrice/src/interface/widgets/dialogs/dlg_edit_avatar.h @@ -1,8 +1,8 @@ /** * @file dlg_edit_avatar.h * @ingroup AccountDialogs - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef DLG_EDITAVATAR_H #define DLG_EDITAVATAR_H diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_edit_password.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_edit_password.cpp index e3bbc7435..cdd4433a7 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_edit_password.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_edit_password.cpp @@ -59,7 +59,7 @@ DlgEditPassword::DlgEditPassword(QWidget *parent) : QDialog(parent) void DlgEditPassword::actOk() { - //! \todo this stuff should be using qvalidators + //! \todo This stuff should be using QValidators. if (newPasswordEdit->text().length() < 8) { QMessageBox::critical(this, tr("Error"), tr("Your password is too short.")); return; diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_edit_password.h b/cockatrice/src/interface/widgets/dialogs/dlg_edit_password.h index ee8e45985..85c72233d 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_edit_password.h +++ b/cockatrice/src/interface/widgets/dialogs/dlg_edit_password.h @@ -1,8 +1,8 @@ /** * @file dlg_edit_password.h * @ingroup AccountDialogs - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef DLG_EDITPASSWORD_H #define DLG_EDITPASSWORD_H diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_edit_tokens.h b/cockatrice/src/interface/widgets/dialogs/dlg_edit_tokens.h index f19646756..202212e98 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_edit_tokens.h +++ b/cockatrice/src/interface/widgets/dialogs/dlg_edit_tokens.h @@ -1,8 +1,8 @@ /** * @file dlg_edit_tokens.h * @ingroup GameDialogs - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef DLG_EDIT_TOKENS_H #define DLG_EDIT_TOKENS_H diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_edit_user.h b/cockatrice/src/interface/widgets/dialogs/dlg_edit_user.h index b89a3be04..35a8bfb46 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_edit_user.h +++ b/cockatrice/src/interface/widgets/dialogs/dlg_edit_user.h @@ -1,8 +1,8 @@ /** * @file dlg_edit user.h * @ingroup NetworkDialogs - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef DLG_EDITUSER_H #define DLG_EDITUSER_H diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_filter_games.h b/cockatrice/src/interface/widgets/dialogs/dlg_filter_games.h index c4cc2dd60..447f9b16c 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_filter_games.h +++ b/cockatrice/src/interface/widgets/dialogs/dlg_filter_games.h @@ -1,8 +1,8 @@ /** * @file dlg_filter_games.h * @ingroup RoomDialogs - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef DLG_FILTER_GAMES_H #define DLG_FILTER_GAMES_H diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_forgot_password_challenge.h b/cockatrice/src/interface/widgets/dialogs/dlg_forgot_password_challenge.h index e8925b1d3..d32e2fc3e 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_forgot_password_challenge.h +++ b/cockatrice/src/interface/widgets/dialogs/dlg_forgot_password_challenge.h @@ -1,8 +1,8 @@ /** * @file dlg_forgot_password_challenge.h * @ingroup AccountDialogs - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef DLG_FORGOTPASSWORDCHALLENGE_H #define DLG_FORGOTPASSWORDCHALLENGE_H diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_forgot_password_request.h b/cockatrice/src/interface/widgets/dialogs/dlg_forgot_password_request.h index e51dad810..2cf352e0d 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_forgot_password_request.h +++ b/cockatrice/src/interface/widgets/dialogs/dlg_forgot_password_request.h @@ -1,8 +1,8 @@ /** * @file dlg_forgot_password_request.h * @ingroup AccountDialogs - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef DLG_FORGOTPASSWORDREQUEST_H #define DLG_FORGOTPASSWORDREQUEST_H diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_forgot_password_reset.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_forgot_password_reset.cpp index c9c41722e..d2eb081d1 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_forgot_password_reset.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_forgot_password_reset.cpp @@ -121,7 +121,7 @@ void DlgForgotPasswordReset::actOk() return; } - //! \todo this stuff should be using qvalidators + //! \todo This stuff should be using QValidators. if (newpasswordEdit->text().length() < 8) { QMessageBox::critical(this, tr("Error"), tr("Your password is too short.")); return; diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_forgot_password_reset.h b/cockatrice/src/interface/widgets/dialogs/dlg_forgot_password_reset.h index 3d110c71d..8a443b906 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_forgot_password_reset.h +++ b/cockatrice/src/interface/widgets/dialogs/dlg_forgot_password_reset.h @@ -1,8 +1,8 @@ /** * @file dlg_forgot_password_reset.h * @ingroup AccountDialogs - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef DLG_FORGOTPASSWORDRESET_H #define DLG_FORGOTPASSWORDRESET_H diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_load_deck.h b/cockatrice/src/interface/widgets/dialogs/dlg_load_deck.h index b103f6a56..27d658902 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_load_deck.h +++ b/cockatrice/src/interface/widgets/dialogs/dlg_load_deck.h @@ -2,8 +2,8 @@ * @file dlg_load_deck.h * @ingroup LocalDeckStorageDialogs * @ingroup Lobby - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef DLG_LOAD_DECK_H #define DLG_LOAD_DECK_H diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_load_deck_from_clipboard.h b/cockatrice/src/interface/widgets/dialogs/dlg_load_deck_from_clipboard.h index 0e59653ea..dce9d712c 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_load_deck_from_clipboard.h +++ b/cockatrice/src/interface/widgets/dialogs/dlg_load_deck_from_clipboard.h @@ -2,8 +2,8 @@ * @file dlg_load_deck_from_clipboard.h * @ingroup LocalDeckStorageDialogs * @ingroup Lobby - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef DLG_LOAD_DECK_FROM_CLIPBOARD_H #define DLG_LOAD_DECK_FROM_CLIPBOARD_H diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_load_deck_from_website.h b/cockatrice/src/interface/widgets/dialogs/dlg_load_deck_from_website.h index 1ac98d206..2890148b9 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_load_deck_from_website.h +++ b/cockatrice/src/interface/widgets/dialogs/dlg_load_deck_from_website.h @@ -2,8 +2,8 @@ * @file dlg_load_deck_from_website.h * @ingroup RemoteDeckStorageDialogs * @ingroup Lobby - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef DLG_LOAD_DECK_FROM_WEBSITE_H #define DLG_LOAD_DECK_FROM_WEBSITE_H diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_load_remote_deck.h b/cockatrice/src/interface/widgets/dialogs/dlg_load_remote_deck.h index b7e0d7aa3..9c81e9ae3 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_load_remote_deck.h +++ b/cockatrice/src/interface/widgets/dialogs/dlg_load_remote_deck.h @@ -2,8 +2,8 @@ * @file dlg_load_remote_deck.h * @ingroup RemoteDeckStorageDialogs * @ingroup Lobby - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef DLG_STARTGAME_H #define DLG_STARTGAME_H diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_manage_sets.h b/cockatrice/src/interface/widgets/dialogs/dlg_manage_sets.h index d9b77a76e..2ed5eca0f 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_manage_sets.h +++ b/cockatrice/src/interface/widgets/dialogs/dlg_manage_sets.h @@ -1,8 +1,8 @@ /** * @file dlg_manage_sets.h * @ingroup Dialogs - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef DLG_MANAGE_SETS_H #define DLG_MANAGE_SETS_H diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_register.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_register.cpp index 7b84a9a06..0f7c17b18 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_register.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_register.cpp @@ -357,7 +357,7 @@ DlgRegister::DlgRegister(QWidget *parent) : QDialog(parent) void DlgRegister::actOk() { - //! \todo this stuff should be using qvalidators + //! \todo This stuff should be using QValidators. if (passwordEdit->text().length() < 8) { QMessageBox::critical(this, tr("Registration Warning"), tr("Your password is too short.")); return; diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_register.h b/cockatrice/src/interface/widgets/dialogs/dlg_register.h index bebbfc500..abed9ff51 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_register.h +++ b/cockatrice/src/interface/widgets/dialogs/dlg_register.h @@ -1,8 +1,8 @@ /** * @file dlg_register.h * @ingroup AccountDialogs - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef DLG_REGISTER_H #define DLG_REGISTER_H diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_select_set_for_cards.h b/cockatrice/src/interface/widgets/dialogs/dlg_select_set_for_cards.h index 795366b57..92f285aa0 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_select_set_for_cards.h +++ b/cockatrice/src/interface/widgets/dialogs/dlg_select_set_for_cards.h @@ -1,8 +1,8 @@ /** * @file dlg_select_set_for_cards.h * @ingroup Dialogs - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef DLG_SELECT_SET_FOR_CARDS_H #define DLG_SELECT_SET_FOR_CARDS_H diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_settings.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_settings.cpp index 3f133c5b6..ff42596ea 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_settings.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_settings.cpp @@ -206,7 +206,7 @@ void DlgSettings::closeEvent(QCloseEvent *event) } if (!QDir(SettingsCache::instance().getDeckPath()).exists() || SettingsCache::instance().getDeckPath().isEmpty()) { - //! \todo Prompt to create it + //! \todo Prompt to create the deck directory. if (QMessageBox::critical( this, tr("Error"), tr("The path to your deck directory is invalid. Would you like to go back and set the correct path?"), @@ -217,7 +217,7 @@ void DlgSettings::closeEvent(QCloseEvent *event) } if (!QDir(SettingsCache::instance().getPicsPath()).exists() || SettingsCache::instance().getPicsPath().isEmpty()) { - //! \todo Prompt to create it + //! \todo Prompt to create the pictures directory. if (QMessageBox::critical(this, tr("Error"), tr("The path to your card pictures directory is invalid. Would you like to go back " "and set the correct path?"), diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_settings.h b/cockatrice/src/interface/widgets/dialogs/dlg_settings.h index f228bde92..3ffee6388 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_settings.h +++ b/cockatrice/src/interface/widgets/dialogs/dlg_settings.h @@ -1,8 +1,8 @@ /** * @file dlg_settings.h * @ingroup Dialogs - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef DLG_SETTINGS_H #define DLG_SETTINGS_H diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_startup_card_check.h b/cockatrice/src/interface/widgets/dialogs/dlg_startup_card_check.h index 44fc59d58..d26610983 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_startup_card_check.h +++ b/cockatrice/src/interface/widgets/dialogs/dlg_startup_card_check.h @@ -1,8 +1,8 @@ /** * @file dlg_startup_card_check.h * @ingroup CardDatabaseUpdateDialogs - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef DLG_STARTUP_CARD_CHECK_H #define DLG_STARTUP_CARD_CHECK_H diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_tip_of_the_day.h b/cockatrice/src/interface/widgets/dialogs/dlg_tip_of_the_day.h index 3dad7c652..e493481d0 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_tip_of_the_day.h +++ b/cockatrice/src/interface/widgets/dialogs/dlg_tip_of_the_day.h @@ -1,8 +1,8 @@ /** * @file dlg_tip_of_the_day.h * @ingroup Dialogs - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef DLG_TIPOFDAY_H #define DLG_TIPOFDAY_H diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_update.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_update.cpp index 417dcb3eb..15735168f 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_update.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_update.cpp @@ -40,7 +40,7 @@ DlgUpdate::DlgUpdate(QWidget *parent) : QDialog(parent) buttonBox->addButton(ok, QDialogButtonBox::AcceptRole); connect(gotoDownload, &QPushButton::clicked, this, &DlgUpdate::gotoDownloadPage); - // TODO: make reinstall button actually do something when clicked + //! \todo Make reinstall button actually do something when clicked. // connect(manualDownload, &QPushButton::clicked, this, &DlgUpdate::downloadUpdate); connect(stopDownload, &QPushButton::clicked, this, &DlgUpdate::cancelDownload); connect(ok, &QPushButton::clicked, this, &DlgUpdate::closeDialog); diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_update.h b/cockatrice/src/interface/widgets/dialogs/dlg_update.h index daf0b9e47..7bd0020d5 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_update.h +++ b/cockatrice/src/interface/widgets/dialogs/dlg_update.h @@ -1,8 +1,8 @@ /** * @file dlg_update.h * @ingroup ClientUpdateDialogs - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef DLG_UPDATE_H #define DLG_UPDATE_H diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_view_log.h b/cockatrice/src/interface/widgets/dialogs/dlg_view_log.h index f0b900527..5c7315b50 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_view_log.h +++ b/cockatrice/src/interface/widgets/dialogs/dlg_view_log.h @@ -1,8 +1,8 @@ /** * @file dlg_view_log.h * @ingroup ServerLogDialogs - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef DLG_VIEWLOG_H #define DLG_VIEWLOG_H diff --git a/cockatrice/src/interface/widgets/dialogs/tip_of_the_day.h b/cockatrice/src/interface/widgets/dialogs/tip_of_the_day.h index d61fddab5..9cda07e2b 100644 --- a/cockatrice/src/interface/widgets/dialogs/tip_of_the_day.h +++ b/cockatrice/src/interface/widgets/dialogs/tip_of_the_day.h @@ -1,8 +1,8 @@ /** * @file tip_of_the_day.h * @ingroup Dialogs - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef TIP_OF_DAY_H #define TIP_OF_DAY_H diff --git a/cockatrice/src/interface/widgets/general/background_sources.h b/cockatrice/src/interface/widgets/general/background_sources.h index 04cafe830..423111bb6 100644 --- a/cockatrice/src/interface/widgets/general/background_sources.h +++ b/cockatrice/src/interface/widgets/general/background_sources.h @@ -1,8 +1,8 @@ /** * @file background_sources.h * @ingroup UI - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef COCKATRICE_BACKGROUND_SOURCES_H #define COCKATRICE_BACKGROUND_SOURCES_H diff --git a/cockatrice/src/interface/widgets/general/display/banner_widget.h b/cockatrice/src/interface/widgets/general/display/banner_widget.h index 8a81dcfce..77a05abb6 100644 --- a/cockatrice/src/interface/widgets/general/display/banner_widget.h +++ b/cockatrice/src/interface/widgets/general/display/banner_widget.h @@ -3,8 +3,8 @@ * @ingroup Widgets * @ingroup DeckEditorCardGroupWidgets * @ingroup DeckStorageWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef BANNER_WIDGET_H #define BANNER_WIDGET_H diff --git a/cockatrice/src/interface/widgets/general/display/charts/bars/bar_widget.h b/cockatrice/src/interface/widgets/general/display/charts/bars/bar_widget.h index 67ad24995..05814f15b 100644 --- a/cockatrice/src/interface/widgets/general/display/charts/bars/bar_widget.h +++ b/cockatrice/src/interface/widgets/general/display/charts/bars/bar_widget.h @@ -2,8 +2,8 @@ * @file bar_widget.h * @ingroup Widgets * @ingroup DeckEditorAnalyticsWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef BAR_WIDGET_H #define BAR_WIDGET_H diff --git a/cockatrice/src/interface/widgets/general/display/charts/bars/color_bar.h b/cockatrice/src/interface/widgets/general/display/charts/bars/color_bar.h index 0ef68f578..100f95310 100644 --- a/cockatrice/src/interface/widgets/general/display/charts/bars/color_bar.h +++ b/cockatrice/src/interface/widgets/general/display/charts/bars/color_bar.h @@ -99,13 +99,13 @@ protected: void mouseMoveEvent(QMouseEvent *event) override; private: - /// Map of color keys to counts used for rendering. + /** @brief Map of color keys to counts used for rendering. */ QList> colors; - /// True if the mouse is currently inside the widget. + /** @brief True if the mouse is currently inside the widget. */ bool isHovered = false; - /// Minimum ratio a segment must exceed to be drawn. + /** @brief Minimum ratio a segment must exceed to be drawn. */ double minRatioThreshold = 0.0; /** diff --git a/cockatrice/src/interface/widgets/general/display/charts/bars/percent_bar_widget.h b/cockatrice/src/interface/widgets/general/display/charts/bars/percent_bar_widget.h index ff7d91363..9cd6039c8 100644 --- a/cockatrice/src/interface/widgets/general/display/charts/bars/percent_bar_widget.h +++ b/cockatrice/src/interface/widgets/general/display/charts/bars/percent_bar_widget.h @@ -2,8 +2,8 @@ * @file percent_bar_widget.h * @ingroup Widgets * @ingroup DeckEditorAnalyticsWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef PERCENT_BAR_WIDGET_H #define PERCENT_BAR_WIDGET_H diff --git a/cockatrice/src/interface/widgets/general/display/dynamic_font_size_label.h b/cockatrice/src/interface/widgets/general/display/dynamic_font_size_label.h index ca3043d10..c9b159b02 100644 --- a/cockatrice/src/interface/widgets/general/display/dynamic_font_size_label.h +++ b/cockatrice/src/interface/widgets/general/display/dynamic_font_size_label.h @@ -1,8 +1,8 @@ /** * @file dynamic_font_size_label.h * @ingroup Widgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef DYNAMICFONTSIZELABEL_H #define DYNAMICFONTSIZELABEL_H diff --git a/cockatrice/src/interface/widgets/general/display/dynamic_font_size_push_button.h b/cockatrice/src/interface/widgets/general/display/dynamic_font_size_push_button.h index 19e67fd28..540abfe6b 100644 --- a/cockatrice/src/interface/widgets/general/display/dynamic_font_size_push_button.h +++ b/cockatrice/src/interface/widgets/general/display/dynamic_font_size_push_button.h @@ -1,8 +1,8 @@ /** * @file dynamic_font_size_push_button.h * @ingroup PrintingWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef DYNAMICFONTSIZEPUSHBUTTON_H #define DYNAMICFONTSIZEPUSHBUTTON_H diff --git a/cockatrice/src/interface/widgets/general/display/labeled_input.h b/cockatrice/src/interface/widgets/general/display/labeled_input.h index 8424e09f0..838dfb280 100644 --- a/cockatrice/src/interface/widgets/general/display/labeled_input.h +++ b/cockatrice/src/interface/widgets/general/display/labeled_input.h @@ -1,8 +1,8 @@ /** * @file labeled_input.h * @ingroup DeckEditorCardGroupWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef LABELED_INPUT_H #define LABELED_INPUT_H diff --git a/cockatrice/src/interface/widgets/general/display/shadow_background_label.h b/cockatrice/src/interface/widgets/general/display/shadow_background_label.h index b2344b7d0..69232691e 100644 --- a/cockatrice/src/interface/widgets/general/display/shadow_background_label.h +++ b/cockatrice/src/interface/widgets/general/display/shadow_background_label.h @@ -1,8 +1,8 @@ /** * @file shadow_background_label.h * @ingroup PrintingWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef STYLEDLABEL_H #define STYLEDLABEL_H diff --git a/cockatrice/src/interface/widgets/general/home_styled_button.h b/cockatrice/src/interface/widgets/general/home_styled_button.h index a053993da..f8d97e9aa 100644 --- a/cockatrice/src/interface/widgets/general/home_styled_button.h +++ b/cockatrice/src/interface/widgets/general/home_styled_button.h @@ -1,8 +1,8 @@ /** * @file home_styled_button.h * @ingroup Widgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef HOME_STYLED_BUTTON_H #define HOME_STYLED_BUTTON_H diff --git a/cockatrice/src/interface/widgets/general/home_widget.h b/cockatrice/src/interface/widgets/general/home_widget.h index b30bb5407..90d003aa7 100644 --- a/cockatrice/src/interface/widgets/general/home_widget.h +++ b/cockatrice/src/interface/widgets/general/home_widget.h @@ -2,8 +2,8 @@ * @file home_widget.h * @ingroup Core * @ingroup Widgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef HOME_WIDGET_H #define HOME_WIDGET_H diff --git a/cockatrice/src/interface/widgets/general/layout_containers/flow_widget.h b/cockatrice/src/interface/widgets/general/layout_containers/flow_widget.h index 1932ce70a..a232336d8 100644 --- a/cockatrice/src/interface/widgets/general/layout_containers/flow_widget.h +++ b/cockatrice/src/interface/widgets/general/layout_containers/flow_widget.h @@ -3,6 +3,7 @@ * @ingroup UI * @brief A QWidget that wraps a FlowLayout inside an optional QScrollArea. */ +//! \todo Document this file. #ifndef FLOW_WIDGET_H #define FLOW_WIDGET_H diff --git a/cockatrice/src/interface/widgets/general/layout_containers/overlap_control_widget.cpp b/cockatrice/src/interface/widgets/general/layout_containers/overlap_control_widget.cpp index 2fd6cd6b8..97068978d 100644 --- a/cockatrice/src/interface/widgets/general/layout_containers/overlap_control_widget.cpp +++ b/cockatrice/src/interface/widgets/general/layout_containers/overlap_control_widget.cpp @@ -33,7 +33,7 @@ OverlapControlWidget::OverlapControlWidget(int overlapPercentage, layout->addWidget(overlap_percentage_input); layout->addWidget(overlap_direction); - // TODO probably connect this to the parent + //! \todo Probably connect this to the parent. // connect(card_size_slider, &QSlider::valueChanged, display, &CardPicture::setScaleFactor); } diff --git a/cockatrice/src/interface/widgets/general/layout_containers/overlap_control_widget.h b/cockatrice/src/interface/widgets/general/layout_containers/overlap_control_widget.h index b2c19a07f..104a97da9 100644 --- a/cockatrice/src/interface/widgets/general/layout_containers/overlap_control_widget.h +++ b/cockatrice/src/interface/widgets/general/layout_containers/overlap_control_widget.h @@ -1,8 +1,8 @@ /** * @file overlap_control_widget.h * @ingroup UI - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef OVERLAP_CONTROL_WIDGET_H #define OVERLAP_CONTROL_WIDGET_H diff --git a/cockatrice/src/interface/widgets/general/layout_containers/overlap_widget.h b/cockatrice/src/interface/widgets/general/layout_containers/overlap_widget.h index 9ac6ac80e..62c620201 100644 --- a/cockatrice/src/interface/widgets/general/layout_containers/overlap_widget.h +++ b/cockatrice/src/interface/widgets/general/layout_containers/overlap_widget.h @@ -1,8 +1,8 @@ /** * @file overlap_widget.h * @ingroup UI - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef OVERLAP_WIDGET_H #define OVERLAP_WIDGET_H diff --git a/cockatrice/src/interface/widgets/menus/deck_editor_menu.h b/cockatrice/src/interface/widgets/menus/deck_editor_menu.h index ac8f3b787..eff9257bb 100644 --- a/cockatrice/src/interface/widgets/menus/deck_editor_menu.h +++ b/cockatrice/src/interface/widgets/menus/deck_editor_menu.h @@ -1,8 +1,8 @@ /** * @file deck_editor_menu.h * @ingroup DeckEditors - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef DECK_EDITOR_MENU_H #define DECK_EDITOR_MENU_H diff --git a/cockatrice/src/interface/widgets/menus/tearoff_menu.h b/cockatrice/src/interface/widgets/menus/tearoff_menu.h index 3e6c47012..ef1dfbcb3 100644 --- a/cockatrice/src/interface/widgets/menus/tearoff_menu.h +++ b/cockatrice/src/interface/widgets/menus/tearoff_menu.h @@ -1,8 +1,8 @@ /** * @file tearoff_menu.h * @ingroup GameMenus - * @brief TODO: Document this. */ +//! \todo Document this file. #pragma once diff --git a/cockatrice/src/interface/widgets/printing_selector/all_zones_card_amount_widget.h b/cockatrice/src/interface/widgets/printing_selector/all_zones_card_amount_widget.h index d158d257e..05047d94f 100644 --- a/cockatrice/src/interface/widgets/printing_selector/all_zones_card_amount_widget.h +++ b/cockatrice/src/interface/widgets/printing_selector/all_zones_card_amount_widget.h @@ -2,8 +2,8 @@ * @file all_zones_card_amount_widget.h * @ingroup CardExtraInfoWidgets * @ingroup PrintingWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef ALL_ZONES_CARD_AMOUNT_WIDGET_H #define ALL_ZONES_CARD_AMOUNT_WIDGET_H diff --git a/cockatrice/src/interface/widgets/printing_selector/card_amount_widget.h b/cockatrice/src/interface/widgets/printing_selector/card_amount_widget.h index 3051b1691..f0f2128f0 100644 --- a/cockatrice/src/interface/widgets/printing_selector/card_amount_widget.h +++ b/cockatrice/src/interface/widgets/printing_selector/card_amount_widget.h @@ -2,8 +2,8 @@ * @file card_amount_widget.h * @ingroup CardExtraInfoWidgets * @ingroup PrintingWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef CARD_AMOUNT_WIDGET_H #define CARD_AMOUNT_WIDGET_H diff --git a/cockatrice/src/interface/widgets/printing_selector/printing_selector.h b/cockatrice/src/interface/widgets/printing_selector/printing_selector.h index f7844504d..b9e6723f2 100644 --- a/cockatrice/src/interface/widgets/printing_selector/printing_selector.h +++ b/cockatrice/src/interface/widgets/printing_selector/printing_selector.h @@ -1,8 +1,8 @@ /** * @file printing_selector.h * @ingroup PrintingWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef PRINTING_SELECTOR_H #define PRINTING_SELECTOR_H diff --git a/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_display_widget.h b/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_display_widget.h index ac5c7c05f..b708bd973 100644 --- a/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_display_widget.h +++ b/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_display_widget.h @@ -1,8 +1,8 @@ /** * @file printing_selector_card_display_widget.h * @ingroup PrintingWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef PRINTING_SELECTOR_CARD_DISPLAY_WIDGET_H #define PRINTING_SELECTOR_CARD_DISPLAY_WIDGET_H diff --git a/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_overlay_widget.h b/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_overlay_widget.h index ae2307c45..2fdf5ab74 100644 --- a/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_overlay_widget.h +++ b/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_overlay_widget.h @@ -1,8 +1,8 @@ /** * @file printing_selector_card_overlay_widget.h * @ingroup PrintingWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef PRINTING_SELECTOR_CARD_OVERLAY_WIDGET_H #define PRINTING_SELECTOR_CARD_OVERLAY_WIDGET_H diff --git a/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_search_widget.h b/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_search_widget.h index 821addd01..3efabe13c 100644 --- a/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_search_widget.h +++ b/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_search_widget.h @@ -1,8 +1,8 @@ /** * @file printing_selector_card_search_widget.h * @ingroup PrintingWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef PRINTING_SELECTOR_CARD_SEARCH_WIDGET_H #define PRINTING_SELECTOR_CARD_SEARCH_WIDGET_H diff --git a/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_selection_widget.h b/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_selection_widget.h index ecd5c83e3..0aa56c9d8 100644 --- a/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_selection_widget.h +++ b/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_selection_widget.h @@ -1,8 +1,8 @@ /** * @file printing_selector_card_selection_widget.h * @ingroup PrintingWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef PRINTING_SELECTOR_CARD_SELECTION_WIDGET_H #define PRINTING_SELECTOR_CARD_SELECTION_WIDGET_H diff --git a/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_sorting_widget.h b/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_sorting_widget.h index b5a00b81e..bb5b60cdc 100644 --- a/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_sorting_widget.h +++ b/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_sorting_widget.h @@ -1,8 +1,8 @@ /** * @file printing_selector_card_sorting_widget.h * @ingroup PrintingWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef PRINTING_SELECTOR_CARD_SORTING_WIDGET_H #define PRINTING_SELECTOR_CARD_SORTING_WIDGET_H diff --git a/cockatrice/src/interface/widgets/printing_selector/set_name_and_collectors_number_display_widget.h b/cockatrice/src/interface/widgets/printing_selector/set_name_and_collectors_number_display_widget.h index 220f57256..140f190df 100644 --- a/cockatrice/src/interface/widgets/printing_selector/set_name_and_collectors_number_display_widget.h +++ b/cockatrice/src/interface/widgets/printing_selector/set_name_and_collectors_number_display_widget.h @@ -2,8 +2,8 @@ * @file set_name_and_collectors_number_display_widget.h * @ingroup CardExtraInfoWidgets * @ingroup PrintingWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef SET_NAME_AND_COLLECTORS_NUMBER_DISPLAY_WIDGET_H #define SET_NAME_AND_COLLECTORS_NUMBER_DISPLAY_WIDGET_H diff --git a/cockatrice/src/interface/widgets/quick_settings/settings_button_widget.h b/cockatrice/src/interface/widgets/quick_settings/settings_button_widget.h index 43de8183f..5dcbe059a 100644 --- a/cockatrice/src/interface/widgets/quick_settings/settings_button_widget.h +++ b/cockatrice/src/interface/widgets/quick_settings/settings_button_widget.h @@ -2,8 +2,8 @@ * @file settings_button_widget.h * @ingroup Widgets * @ingroup Settings - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef SETTINGS_BUTTON_WIDGET_H #define SETTINGS_BUTTON_WIDGET_H @@ -27,7 +27,7 @@ public: bool isCompact() const { return compact; - }; + } protected: void mousePressEvent(QMouseEvent *event) override; diff --git a/cockatrice/src/interface/widgets/quick_settings/settings_popup_widget.h b/cockatrice/src/interface/widgets/quick_settings/settings_popup_widget.h index e9605e473..01e86abfe 100644 --- a/cockatrice/src/interface/widgets/quick_settings/settings_popup_widget.h +++ b/cockatrice/src/interface/widgets/quick_settings/settings_popup_widget.h @@ -2,8 +2,8 @@ * @file settings_popup_widget.h * @ingroup Widgets * @ingroup Settings - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef SETTINGS_POPUP_WIDGET_H #define SETTINGS_POPUP_WIDGET_H diff --git a/cockatrice/src/interface/widgets/replay/replay_manager.h b/cockatrice/src/interface/widgets/replay/replay_manager.h index 9469adcd4..d67ae5a90 100644 --- a/cockatrice/src/interface/widgets/replay/replay_manager.h +++ b/cockatrice/src/interface/widgets/replay/replay_manager.h @@ -2,8 +2,8 @@ * @file replay_manager.h * @ingroup Core * @ingroup Replay - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef REPLAY_MANAGER_H #define REPLAY_MANAGER_H diff --git a/cockatrice/src/interface/widgets/replay/replay_timeline_widget.cpp b/cockatrice/src/interface/widgets/replay/replay_timeline_widget.cpp index 508d45666..46a3dff40 100644 --- a/cockatrice/src/interface/widgets/replay/replay_timeline_widget.cpp +++ b/cockatrice/src/interface/widgets/replay/replay_timeline_widget.cpp @@ -103,8 +103,12 @@ void ReplayTimelineWidget::skipToTime(int newTime, bool doRewindBuffering) update(); } -/// @param doRewindBuffering When true, if multiple backward skips are made in quick succession, only a single rewind -/// is processed at the end. When false, the backwards skip will always cause an immediate rewind +/** + * @brief Handles a backwards skip in the replay timeline. + * + * @param doRewindBuffering When true, if multiple backward skips are made in quick succession, only a single rewind + * is processed at the end. When false, the backwards skip will always cause an immediate rewind. + */ void ReplayTimelineWidget::handleBackwardsSkip(bool doRewindBuffering) { if (doRewindBuffering) { @@ -151,7 +155,7 @@ void ReplayTimelineWidget::replayTimerTimeout() } } -/// Processes all unprocessed events up to the current time. +/** @brief Processes all unprocessed events up to the current time. */ void ReplayTimelineWidget::processNewEvents(PlaybackMode playbackMode) { currentProcessedTime = currentVisualTime; diff --git a/cockatrice/src/interface/widgets/replay/replay_timeline_widget.h b/cockatrice/src/interface/widgets/replay/replay_timeline_widget.h index 07a0c0b4c..418d0c7e0 100644 --- a/cockatrice/src/interface/widgets/replay/replay_timeline_widget.h +++ b/cockatrice/src/interface/widgets/replay/replay_timeline_widget.h @@ -1,8 +1,8 @@ /** * @file replay_timeline_widget.h * @ingroup Replay - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef REPLAY_TIMELINE_WIDGET #define REPLAY_TIMELINE_WIDGET diff --git a/cockatrice/src/interface/widgets/server/chat_view/chat_view.cpp b/cockatrice/src/interface/widgets/server/chat_view/chat_view.cpp index 1fe77e278..ccbbe9246 100644 --- a/cockatrice/src/interface/widgets/server/chat_view/chat_view.cpp +++ b/cockatrice/src/interface/widgets/server/chat_view/chat_view.cpp @@ -261,7 +261,8 @@ void ChatView::appendMessage(QString message, defaultFormat = QTextCharFormat(); if (!isUserMessage) { if (messageType == Event_RoomSay::ChatHistory) { - defaultFormat.setForeground(Qt::gray); //! \todo hardcoded color + //! \todo Remove hardcoded color. + defaultFormat.setForeground(Qt::gray); defaultFormat.setFontWeight(QFont::Light); defaultFormat.setFontItalic(true); static const QRegularExpression userNameRegex("^(\\[[^\\]]*\\]\\s)(\\S+):\\s"); @@ -284,7 +285,8 @@ void ChatView::appendMessage(QString message, message.remove(0, pos.relativePosition - 2); // do not remove semicolon } } else { - defaultFormat.setForeground(Qt::darkGreen); //! \todo hardcoded color + //! \todo Remove hardcoded color. + defaultFormat.setForeground(Qt::darkGreen); defaultFormat.setFontWeight(QFont::Bold); } } diff --git a/cockatrice/src/interface/widgets/server/chat_view/chat_view.h b/cockatrice/src/interface/widgets/server/chat_view/chat_view.h index d1939fbea..c5ae2b81a 100644 --- a/cockatrice/src/interface/widgets/server/chat_view/chat_view.h +++ b/cockatrice/src/interface/widgets/server/chat_view/chat_view.h @@ -2,8 +2,8 @@ * @file chat_view.h * @ingroup NetworkingWidgets * @ingroup Lobby - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef CHATVIEW_H #define CHATVIEW_H diff --git a/cockatrice/src/interface/widgets/server/handle_public_servers.h b/cockatrice/src/interface/widgets/server/handle_public_servers.h index f06bb3ff6..fa924b183 100644 --- a/cockatrice/src/interface/widgets/server/handle_public_servers.h +++ b/cockatrice/src/interface/widgets/server/handle_public_servers.h @@ -1,8 +1,8 @@ /** * @file handle_public_servers.h * @ingroup Server - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef COCKATRICE_HANDLE_PUBLIC_SERVERS_H #define COCKATRICE_HANDLE_PUBLIC_SERVERS_H diff --git a/cockatrice/src/interface/widgets/server/remote/remote_decklist_tree_widget.h b/cockatrice/src/interface/widgets/server/remote/remote_decklist_tree_widget.h index bca46fd47..3dd91d7a4 100644 --- a/cockatrice/src/interface/widgets/server/remote/remote_decklist_tree_widget.h +++ b/cockatrice/src/interface/widgets/server/remote/remote_decklist_tree_widget.h @@ -2,8 +2,8 @@ * @file remote_decklist_tree_widget.h * @ingroup NetworkingWidgets * @ingroup DeckStorageWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef REMOTEDECKLIST_TREEWIDGET_H #define REMOTEDECKLIST_TREEWIDGET_H diff --git a/cockatrice/src/interface/widgets/server/remote/remote_replay_list_tree_widget.h b/cockatrice/src/interface/widgets/server/remote/remote_replay_list_tree_widget.h index 6d81aefca..10e698aee 100644 --- a/cockatrice/src/interface/widgets/server/remote/remote_replay_list_tree_widget.h +++ b/cockatrice/src/interface/widgets/server/remote/remote_replay_list_tree_widget.h @@ -3,8 +3,8 @@ * @ingroup DeckStorageWidgets * @ingroup Replays * @ingroup NetworkingWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef REMOTEREPLAYLIST_TREEWIDGET_H #define REMOTEREPLAYLIST_TREEWIDGET_H diff --git a/cockatrice/src/interface/widgets/server/user/user_context_menu.h b/cockatrice/src/interface/widgets/server/user/user_context_menu.h index 0056d74ae..b0ff89816 100644 --- a/cockatrice/src/interface/widgets/server/user/user_context_menu.h +++ b/cockatrice/src/interface/widgets/server/user/user_context_menu.h @@ -1,8 +1,8 @@ /** * @file user_context_menu.h * @ingroup Lobby - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef USER_CONTEXT_MENU_H #define USER_CONTEXT_MENU_H diff --git a/cockatrice/src/interface/widgets/server/user/user_info_box.h b/cockatrice/src/interface/widgets/server/user/user_info_box.h index d3d926bed..299deed2f 100644 --- a/cockatrice/src/interface/widgets/server/user/user_info_box.h +++ b/cockatrice/src/interface/widgets/server/user/user_info_box.h @@ -1,8 +1,8 @@ /** * @file user_info_box.h * @ingroup Lobby - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef USERINFOBOX_H #define USERINFOBOX_H diff --git a/cockatrice/src/interface/widgets/server/user/user_info_connection.h b/cockatrice/src/interface/widgets/server/user/user_info_connection.h index cfba22346..6278815a9 100644 --- a/cockatrice/src/interface/widgets/server/user/user_info_connection.h +++ b/cockatrice/src/interface/widgets/server/user/user_info_connection.h @@ -1,8 +1,8 @@ /** * @file user_info_connection.h * @ingroup Client - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef USERCONNECTION_INFORMATION_H #define USERCONNECTION_INFORMATION_H diff --git a/cockatrice/src/interface/widgets/server/user/user_list_manager.h b/cockatrice/src/interface/widgets/server/user/user_list_manager.h index f378bd08d..f09284bd0 100644 --- a/cockatrice/src/interface/widgets/server/user/user_list_manager.h +++ b/cockatrice/src/interface/widgets/server/user/user_list_manager.h @@ -1,8 +1,8 @@ /** * @file user_list_manager.h * @ingroup Lobby - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef COCKATRICE_USER_LIST_MANAGER_H #define COCKATRICE_USER_LIST_MANAGER_H diff --git a/cockatrice/src/interface/widgets/server/user/user_list_proxy.h b/cockatrice/src/interface/widgets/server/user/user_list_proxy.h index bff76077f..626f89b8f 100644 --- a/cockatrice/src/interface/widgets/server/user/user_list_proxy.h +++ b/cockatrice/src/interface/widgets/server/user/user_list_proxy.h @@ -2,8 +2,8 @@ * @file user_list_proxy.h * @ingroup UI * @ingroup Lobby - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef COCKATRICE_USERLISTPROXY_H #define COCKATRICE_USERLISTPROXY_H diff --git a/cockatrice/src/interface/widgets/server/user/user_list_widget.h b/cockatrice/src/interface/widgets/server/user/user_list_widget.h index 036837673..5a8c00d10 100644 --- a/cockatrice/src/interface/widgets/server/user/user_list_widget.h +++ b/cockatrice/src/interface/widgets/server/user/user_list_widget.h @@ -1,8 +1,8 @@ /** * @file user_list_widget.h * @ingroup Lobby - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef USERLIST_H #define USERLIST_H diff --git a/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/card/archidekt_api_response_card.cpp b/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/card/archidekt_api_response_card.cpp index 5b879f8ae..46c229156 100644 --- a/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/card/archidekt_api_response_card.cpp +++ b/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/card/archidekt_api_response_card.cpp @@ -21,16 +21,16 @@ void ArchidektApiResponseCard::fromJson(const QJsonObject &json) edition.fromJson(json.value("edition").toObject()); flavor = json.value("flavor").toString(); - //! \todo but not really important - //! \todo games = {""}; - //! \todo options = {""}; + //! \todo Parse games and options fields (not really important). + // games = {""}; + // options = {""}; scryfallImageHash = json.value("scryfallImageHash").toString(); oracleCard = json.value("oracleCard").toObject(); owned = json.value("owned").toInt(); pinnedStatus = json.value("pinnedStatus").toInt(); rarity = json.value("rarity").toString(); - //! \todo but not really important - //! \todo globalCategories = {""}; + //! \todo Parse globalCategories field (not really important). + // globalCategories = {""}; } void ArchidektApiResponseCard::debugPrint() const diff --git a/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/deck/archidekt_api_response_deck.cpp b/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/deck/archidekt_api_response_deck.cpp index 98d8c6c8c..a27d8d961 100644 --- a/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/deck/archidekt_api_response_deck.cpp +++ b/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/deck/archidekt_api_response_deck.cpp @@ -44,7 +44,7 @@ void ArchidektApiResponseDeck::fromJson(const QJsonObject &json) cards.append(entry); } - // TODO but not really important + //! \todo Parse customCards field (not really important). // customCards = {""}; } diff --git a/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/deck_listings/archidekt_api_response_deck_listing_container.cpp b/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/deck_listings/archidekt_api_response_deck_listing_container.cpp index 16ea60487..416621b41 100644 --- a/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/deck_listings/archidekt_api_response_deck_listing_container.cpp +++ b/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/deck_listings/archidekt_api_response_deck_listing_container.cpp @@ -23,7 +23,7 @@ void ArchidektApiResponseDeckListingContainer::fromJson(const QJsonObject &json) theoryCrafted = json.value("theoryCrafted").toBool(); game = json.value("game").toString(); hasDescription = json.value("hasDescription").toBool(); - // TODO + //! \todo Parse tags field. // tags = {""}; parentFolderId = json.value("parentFolderId").toInt(); owner.fromJson(json.value("owner").toObject()); diff --git a/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/deck_listings/archidekt_api_response_deck_owner.cpp b/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/deck_listings/archidekt_api_response_deck_owner.cpp index 2ba926f8b..3d6eac03d 100644 --- a/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/deck_listings/archidekt_api_response_deck_owner.cpp +++ b/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/deck_listings/archidekt_api_response_deck_owner.cpp @@ -7,7 +7,7 @@ void ArchidektApiResponseDeckOwner::fromJson(const QJsonObject &json) avatar = QUrl(json.value("avatar").toString()); moderator = json.value("moderator").toBool(); pledgeLevel = json.value("pledgeLevel").toInt(); - // TODO but not really important + //! \todo Parse roles field (not really important). // roles = {""}; } diff --git a/cockatrice/src/interface/widgets/tabs/api/archidekt/display/archidekt_api_response_deck_listings_display_widget.h b/cockatrice/src/interface/widgets/tabs/api/archidekt/display/archidekt_api_response_deck_listings_display_widget.h index 479de5fc8..f9a887aa4 100644 --- a/cockatrice/src/interface/widgets/tabs/api/archidekt/display/archidekt_api_response_deck_listings_display_widget.h +++ b/cockatrice/src/interface/widgets/tabs/api/archidekt/display/archidekt_api_response_deck_listings_display_widget.h @@ -82,16 +82,16 @@ public: void resizeEvent(QResizeEvent *event) override; private: - /// Slider controlling the scale of card thumbnails in all deck entry widgets. + /** @brief Slider controlling the scale of card thumbnails in all deck entry widgets. */ CardSizeWidget *cardSizeSlider; - /// Main horizontal layout containing the FlowWidget. + /** @brief Main horizontal layout containing the FlowWidget. */ QHBoxLayout *layout; - /// Container providing scrollable multi-row flow layout of deck entries. + /** @brief Container providing scrollable multi-row flow layout of deck entries. */ FlowWidget *flowWidget; - /// Shared network manager used to download card images for all child entry widgets. + /** @brief Shared network manager used to download card images for all child entry widgets. */ QNetworkAccessManager *imageNetworkManager; }; diff --git a/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/average_deck/edhrec_deck_api_response.h b/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/average_deck/edhrec_deck_api_response.h index cd4f9d99c..7bc97c431 100644 --- a/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/average_deck/edhrec_deck_api_response.h +++ b/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/average_deck/edhrec_deck_api_response.h @@ -1,8 +1,8 @@ /** * @file edhrec_deck_api_response.h * @ingroup ApiResponses - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef EDHREC_DECK_API_RESPONSE_H #define EDHREC_DECK_API_RESPONSE_H diff --git a/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/card_prices/edhrec_api_response_card_prices.h b/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/card_prices/edhrec_api_response_card_prices.h index 66a407acd..bd874d067 100644 --- a/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/card_prices/edhrec_api_response_card_prices.h +++ b/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/card_prices/edhrec_api_response_card_prices.h @@ -1,8 +1,8 @@ /** * @file edhrec_api_response_card_prices.h * @ingroup ApiResponses - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef EDHREC_COMMANDER_API_RESPONSE_CARD_PRICES_H #define EDHREC_COMMANDER_API_RESPONSE_CARD_PRICES_H diff --git a/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/cards/edhrec_api_response_card_container.h b/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/cards/edhrec_api_response_card_container.h index 07b53dd97..d76dda490 100644 --- a/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/cards/edhrec_api_response_card_container.h +++ b/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/cards/edhrec_api_response_card_container.h @@ -1,8 +1,8 @@ /** * @file edhrec_api_response_card_container.h * @ingroup ApiResponses - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef CONTAINER_ENTRY_H #define CONTAINER_ENTRY_H diff --git a/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/cards/edhrec_api_response_card_details.h b/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/cards/edhrec_api_response_card_details.h index 86d78c5e3..931850ea9 100644 --- a/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/cards/edhrec_api_response_card_details.h +++ b/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/cards/edhrec_api_response_card_details.h @@ -1,8 +1,8 @@ /** * @file edhrec_api_response_card_details.h * @ingroup ApiResponses - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef CARD_VIEW_H #define CARD_VIEW_H diff --git a/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/cards/edhrec_api_response_card_list.h b/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/cards/edhrec_api_response_card_list.h index 15691fbe4..2df29de0c 100644 --- a/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/cards/edhrec_api_response_card_list.h +++ b/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/cards/edhrec_api_response_card_list.h @@ -1,8 +1,8 @@ /** * @file edhrec_api_response_card_list.h * @ingroup ApiResponses - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef CARD_LIST_H #define CARD_LIST_H diff --git a/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/cards/edhrec_commander_api_response_commander_details.h b/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/cards/edhrec_commander_api_response_commander_details.h index 629eb8273..293e9a150 100644 --- a/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/cards/edhrec_commander_api_response_commander_details.h +++ b/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/cards/edhrec_commander_api_response_commander_details.h @@ -1,8 +1,8 @@ /** * @file edhrec_commander_api_response_commander_details.h * @ingroup ApiResponses - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef EDHREC_COMMANDER_API_RESPONSE_COMMANDER_DETAILS_H #define EDHREC_COMMANDER_API_RESPONSE_COMMANDER_DETAILS_H diff --git a/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/top_cards/edhrec_top_cards_api_response.h b/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/top_cards/edhrec_top_cards_api_response.h index fb89c0b12..695498e2b 100644 --- a/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/top_cards/edhrec_top_cards_api_response.h +++ b/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/top_cards/edhrec_top_cards_api_response.h @@ -1,8 +1,8 @@ /** * @file edhrec_top_cards_api_response.h * @ingroup ApiResponses - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef EDHREC_TOP_CARDS_API_RESPONSE_H #define EDHREC_TOP_CARDS_API_RESPONSE_H diff --git a/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/top_commanders/edhrec_top_commanders_api_response.h b/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/top_commanders/edhrec_top_commanders_api_response.h index 26c5afedb..10aa51ff4 100644 --- a/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/top_commanders/edhrec_top_commanders_api_response.h +++ b/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/top_commanders/edhrec_top_commanders_api_response.h @@ -1,8 +1,8 @@ /** * @file edhrec_top_commanders_api_response.h * @ingroup ApiResponses - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef EDHREC_TOP_COMMANDERS_API_RESPONSE_H #define EDHREC_TOP_COMMANDERS_API_RESPONSE_H diff --git a/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/top_tags/edhrec_top_tags_api_response.h b/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/top_tags/edhrec_top_tags_api_response.h index 48219893a..0337d94f8 100644 --- a/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/top_tags/edhrec_top_tags_api_response.h +++ b/cockatrice/src/interface/widgets/tabs/api/edhrec/api_response/top_tags/edhrec_top_tags_api_response.h @@ -1,8 +1,8 @@ /** * @file edhrec_top_tags_api_response.h * @ingroup ApiResponses - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef EDHREC_TOP_TAGS_API_RESPONSE_H #define EDHREC_TOP_TAGS_API_RESPONSE_H diff --git a/cockatrice/src/interface/widgets/tabs/api/edhrec/display/card_prices/edhrec_api_response_card_prices_display_widget.h b/cockatrice/src/interface/widgets/tabs/api/edhrec/display/card_prices/edhrec_api_response_card_prices_display_widget.h index 80d32a394..8943ae9f3 100644 --- a/cockatrice/src/interface/widgets/tabs/api/edhrec/display/card_prices/edhrec_api_response_card_prices_display_widget.h +++ b/cockatrice/src/interface/widgets/tabs/api/edhrec/display/card_prices/edhrec_api_response_card_prices_display_widget.h @@ -1,8 +1,8 @@ /** * @file edhrec_api_response_card_prices_display_widget.h * @ingroup ApiResponseDisplayWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef EDHREC_API_RESPONSE_CARD_PRICES_DISPLAY_WIDGET_H #define EDHREC_API_RESPONSE_CARD_PRICES_DISPLAY_WIDGET_H diff --git a/cockatrice/src/interface/widgets/tabs/api/edhrec/display/cards/edhrec_api_response_card_details_display_widget.h b/cockatrice/src/interface/widgets/tabs/api/edhrec/display/cards/edhrec_api_response_card_details_display_widget.h index 82dcfb8b0..5daf32412 100644 --- a/cockatrice/src/interface/widgets/tabs/api/edhrec/display/cards/edhrec_api_response_card_details_display_widget.h +++ b/cockatrice/src/interface/widgets/tabs/api/edhrec/display/cards/edhrec_api_response_card_details_display_widget.h @@ -1,8 +1,8 @@ /** * @file edhrec_api_response_card_details_display_widget.h * @ingroup ApiResponseDisplayWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef EDHREC_COMMANDER_API_RESPONSE_CARD_DETAILS_DISPLAY_WIDGET_H #define EDHREC_COMMANDER_API_RESPONSE_CARD_DETAILS_DISPLAY_WIDGET_H diff --git a/cockatrice/src/interface/widgets/tabs/api/edhrec/display/cards/edhrec_api_response_card_inclusion_display_widget.h b/cockatrice/src/interface/widgets/tabs/api/edhrec/display/cards/edhrec_api_response_card_inclusion_display_widget.h index 43baddb4c..516d820eb 100644 --- a/cockatrice/src/interface/widgets/tabs/api/edhrec/display/cards/edhrec_api_response_card_inclusion_display_widget.h +++ b/cockatrice/src/interface/widgets/tabs/api/edhrec/display/cards/edhrec_api_response_card_inclusion_display_widget.h @@ -1,8 +1,8 @@ /** * @file edhrec_api_response_card_inclusion_display_widget.h * @ingroup ApiResponseDisplayWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef EDHREC_API_RESPONSE_CARD_INCLUSION_DISPLAY_WIDGET_H #define EDHREC_API_RESPONSE_CARD_INCLUSION_DISPLAY_WIDGET_H diff --git a/cockatrice/src/interface/widgets/tabs/api/edhrec/display/cards/edhrec_api_response_card_list_display_widget.h b/cockatrice/src/interface/widgets/tabs/api/edhrec/display/cards/edhrec_api_response_card_list_display_widget.h index d34c3da34..555da6ecf 100644 --- a/cockatrice/src/interface/widgets/tabs/api/edhrec/display/cards/edhrec_api_response_card_list_display_widget.h +++ b/cockatrice/src/interface/widgets/tabs/api/edhrec/display/cards/edhrec_api_response_card_list_display_widget.h @@ -1,8 +1,8 @@ /** * @file edhrec_api_response_card_list_display_widget.h * @ingroup ApiResponseDisplayWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef EDHREC_COMMANDER_API_RESPONSE_CARD_LIST_DISPLAY_WIDGET_H #define EDHREC_COMMANDER_API_RESPONSE_CARD_LIST_DISPLAY_WIDGET_H diff --git a/cockatrice/src/interface/widgets/tabs/api/edhrec/display/cards/edhrec_api_response_card_synergy_display_widget.h b/cockatrice/src/interface/widgets/tabs/api/edhrec/display/cards/edhrec_api_response_card_synergy_display_widget.h index c2e1c018c..5800b5497 100644 --- a/cockatrice/src/interface/widgets/tabs/api/edhrec/display/cards/edhrec_api_response_card_synergy_display_widget.h +++ b/cockatrice/src/interface/widgets/tabs/api/edhrec/display/cards/edhrec_api_response_card_synergy_display_widget.h @@ -1,8 +1,8 @@ /** * @file edhrec_api_response_card_synergy_display_widget.h * @ingroup ApiResponseDisplayWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef EDHREC_API_RESPONSE_CARD_SYNERGY_DISPLAY_WIDGET_H #define EDHREC_API_RESPONSE_CARD_SYNERGY_DISPLAY_WIDGET_H diff --git a/cockatrice/src/interface/widgets/tabs/api/edhrec/display/commander/edhrec_api_response_commander_details_display_widget.h b/cockatrice/src/interface/widgets/tabs/api/edhrec/display/commander/edhrec_api_response_commander_details_display_widget.h index 8e74588e2..4201ce3b3 100644 --- a/cockatrice/src/interface/widgets/tabs/api/edhrec/display/commander/edhrec_api_response_commander_details_display_widget.h +++ b/cockatrice/src/interface/widgets/tabs/api/edhrec/display/commander/edhrec_api_response_commander_details_display_widget.h @@ -1,8 +1,8 @@ /** * @file edhrec_api_response_commander_details_display_widget.h * @ingroup ApiResponseDisplayWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef EDHREC_COMMANDER_API_RESPONSE_COMMANDER_DETAILS_DISPLAY_WIDGET_H #define EDHREC_COMMANDER_API_RESPONSE_COMMANDER_DETAILS_DISPLAY_WIDGET_H diff --git a/cockatrice/src/interface/widgets/tabs/api/edhrec/display/commander/edhrec_commander_api_response_display_widget.h b/cockatrice/src/interface/widgets/tabs/api/edhrec/display/commander/edhrec_commander_api_response_display_widget.h index 1678e1380..80da8a7f8 100644 --- a/cockatrice/src/interface/widgets/tabs/api/edhrec/display/commander/edhrec_commander_api_response_display_widget.h +++ b/cockatrice/src/interface/widgets/tabs/api/edhrec/display/commander/edhrec_commander_api_response_display_widget.h @@ -1,8 +1,8 @@ /** * @file edhrec_commander_api_response_display_widget.h * @ingroup ApiResponseDisplayWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef EDHREC_COMMANDER_API_RESPONSE_DISPLAY_WIDGET_H #define EDHREC_COMMANDER_API_RESPONSE_DISPLAY_WIDGET_H diff --git a/cockatrice/src/interface/widgets/tabs/api/edhrec/display/commander/edhrec_commander_api_response_navigation_widget.h b/cockatrice/src/interface/widgets/tabs/api/edhrec/display/commander/edhrec_commander_api_response_navigation_widget.h index 10dfa8223..9b46b54ba 100644 --- a/cockatrice/src/interface/widgets/tabs/api/edhrec/display/commander/edhrec_commander_api_response_navigation_widget.h +++ b/cockatrice/src/interface/widgets/tabs/api/edhrec/display/commander/edhrec_commander_api_response_navigation_widget.h @@ -1,8 +1,8 @@ /** * @file edhrec_commander_api_response_navigation_widget.h * @ingroup ApiResponseDisplayWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef EDHREC_COMMANDER_API_RESPONSE_NAVIGATION_WIDGET_H #define EDHREC_COMMANDER_API_RESPONSE_NAVIGATION_WIDGET_H diff --git a/cockatrice/src/interface/widgets/tabs/api/edhrec/display/top_cards/edhrec_top_cards_api_response_display_widget.h b/cockatrice/src/interface/widgets/tabs/api/edhrec/display/top_cards/edhrec_top_cards_api_response_display_widget.h index e2748bf10..30998391c 100644 --- a/cockatrice/src/interface/widgets/tabs/api/edhrec/display/top_cards/edhrec_top_cards_api_response_display_widget.h +++ b/cockatrice/src/interface/widgets/tabs/api/edhrec/display/top_cards/edhrec_top_cards_api_response_display_widget.h @@ -1,8 +1,8 @@ /** * @file edhrec_top_cards_api_response_display_widget.h * @ingroup ApiResponseDisplayWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef EDHREC_TOP_CARDS_API_RESPONSE_DISPLAY_WIDGET_H #define EDHREC_TOP_CARDS_API_RESPONSE_DISPLAY_WIDGET_H diff --git a/cockatrice/src/interface/widgets/tabs/api/edhrec/display/top_commander/edhrec_top_commanders_api_response_display_widget.h b/cockatrice/src/interface/widgets/tabs/api/edhrec/display/top_commander/edhrec_top_commanders_api_response_display_widget.h index 766518c02..2b9563ea5 100644 --- a/cockatrice/src/interface/widgets/tabs/api/edhrec/display/top_commander/edhrec_top_commanders_api_response_display_widget.h +++ b/cockatrice/src/interface/widgets/tabs/api/edhrec/display/top_commander/edhrec_top_commanders_api_response_display_widget.h @@ -1,8 +1,8 @@ /** * @file edhrec_top_commanders_api_response_display_widget.h * @ingroup ApiResponseDisplayWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef EDHREC_TOP_COMMANDERS_API_RESPONSE_DISPLAY_WIDGET_H #define EDHREC_TOP_COMMANDERS_API_RESPONSE_DISPLAY_WIDGET_H diff --git a/cockatrice/src/interface/widgets/tabs/api/edhrec/display/top_tags/edhrec_top_tags_api_response_display_widget.h b/cockatrice/src/interface/widgets/tabs/api/edhrec/display/top_tags/edhrec_top_tags_api_response_display_widget.h index 64228b85d..4a4fc8991 100644 --- a/cockatrice/src/interface/widgets/tabs/api/edhrec/display/top_tags/edhrec_top_tags_api_response_display_widget.h +++ b/cockatrice/src/interface/widgets/tabs/api/edhrec/display/top_tags/edhrec_top_tags_api_response_display_widget.h @@ -1,8 +1,8 @@ /** * @file edhrec_top_tags_api_response_display_widget.h * @ingroup ApiResponseDisplayWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef EDHREC_TOP_TAGS_API_RESPONSE_DISPLAY_WIDGET_H #define EDHREC_TOP_TAGS_API_RESPONSE_DISPLAY_WIDGET_H diff --git a/cockatrice/src/interface/widgets/tabs/api/edhrec/tab_edhrec.h b/cockatrice/src/interface/widgets/tabs/api/edhrec/tab_edhrec.h index b5ee8d2ca..5ce36c9cf 100644 --- a/cockatrice/src/interface/widgets/tabs/api/edhrec/tab_edhrec.h +++ b/cockatrice/src/interface/widgets/tabs/api/edhrec/tab_edhrec.h @@ -1,8 +1,8 @@ /** * @file tab_edhrec.h * @ingroup Tabs - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef TAB_EDHREC_H #define TAB_EDHREC_H diff --git a/cockatrice/src/interface/widgets/tabs/api/edhrec/tab_edhrec_main.h b/cockatrice/src/interface/widgets/tabs/api/edhrec/tab_edhrec_main.h index 04cf03fc1..a7ed83efd 100644 --- a/cockatrice/src/interface/widgets/tabs/api/edhrec/tab_edhrec_main.h +++ b/cockatrice/src/interface/widgets/tabs/api/edhrec/tab_edhrec_main.h @@ -1,8 +1,8 @@ /** * @file tab_edhrec_main.h * @ingroup Tabs - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef TAB_EDHREC_MAIN_H #define TAB_EDHREC_MAIN_H diff --git a/cockatrice/src/interface/widgets/tabs/tab.h b/cockatrice/src/interface/widgets/tabs/tab.h index 7cff01130..6ea1f5077 100644 --- a/cockatrice/src/interface/widgets/tabs/tab.h +++ b/cockatrice/src/interface/widgets/tabs/tab.h @@ -1,8 +1,8 @@ /** * @file tab.h * @ingroup Tabs - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef TAB_H #define TAB_H diff --git a/cockatrice/src/interface/widgets/tabs/tab_account.h b/cockatrice/src/interface/widgets/tabs/tab_account.h index e09c12eb2..887038ebb 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_account.h +++ b/cockatrice/src/interface/widgets/tabs/tab_account.h @@ -1,8 +1,8 @@ /** * @file tab_account.h * @ingroup AccountTabs - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef TAB_ACCOUNT_H #define TAB_ACCOUNT_H diff --git a/cockatrice/src/interface/widgets/tabs/tab_admin.h b/cockatrice/src/interface/widgets/tabs/tab_admin.h index e1935e351..0da098ba5 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_admin.h +++ b/cockatrice/src/interface/widgets/tabs/tab_admin.h @@ -1,8 +1,8 @@ /** * @file tab_admin.h * @ingroup ServerTabs - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef TAB_ADMIN_H #define TAB_ADMIN_H diff --git a/cockatrice/src/interface/widgets/tabs/tab_deck_storage.h b/cockatrice/src/interface/widgets/tabs/tab_deck_storage.h index f8c0497f7..a863e0625 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_deck_storage.h +++ b/cockatrice/src/interface/widgets/tabs/tab_deck_storage.h @@ -2,8 +2,8 @@ * @file tab_deck_storage.h * @ingroup DeckStorageWidgets * @ingroup Tabs - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef TAB_DECK_STORAGE_H #define TAB_DECK_STORAGE_H diff --git a/cockatrice/src/interface/widgets/tabs/tab_game.h b/cockatrice/src/interface/widgets/tabs/tab_game.h index c8dfc3093..7f9392034 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_game.h +++ b/cockatrice/src/interface/widgets/tabs/tab_game.h @@ -3,8 +3,8 @@ * @ingroup Tabs * @ingroup GameWidgets * @ingroup Lobby - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef TAB_GAME_H #define TAB_GAME_H diff --git a/cockatrice/src/interface/widgets/tabs/tab_home.h b/cockatrice/src/interface/widgets/tabs/tab_home.h index c40dfc269..3aae19c2b 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_home.h +++ b/cockatrice/src/interface/widgets/tabs/tab_home.h @@ -1,8 +1,8 @@ /** * @file tab_home.h * @ingroup Tabs - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef TAB_HOME_H #define TAB_HOME_H diff --git a/cockatrice/src/interface/widgets/tabs/tab_logs.h b/cockatrice/src/interface/widgets/tabs/tab_logs.h index a73af651b..5d164dc92 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_logs.h +++ b/cockatrice/src/interface/widgets/tabs/tab_logs.h @@ -1,8 +1,8 @@ /** * @file tab_logs.h * @ingroup ServerTabs - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef TAB_LOG_H #define TAB_LOG_H diff --git a/cockatrice/src/interface/widgets/tabs/tab_message.h b/cockatrice/src/interface/widgets/tabs/tab_message.h index 36a0b5f78..0472bb061 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_message.h +++ b/cockatrice/src/interface/widgets/tabs/tab_message.h @@ -1,8 +1,8 @@ /** * @file tab_message.h * @ingroup MessagingTabs - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef TAB_MESSAGE_H #define TAB_MESSAGE_H diff --git a/cockatrice/src/interface/widgets/tabs/tab_replays.h b/cockatrice/src/interface/widgets/tabs/tab_replays.h index fa1131cd5..aa4ec039c 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_replays.h +++ b/cockatrice/src/interface/widgets/tabs/tab_replays.h @@ -2,8 +2,8 @@ * @file tab_replays.h * @ingroup Replays * @ingroup Tabs - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef TAB_REPLAYS_H #define TAB_REPLAYS_H diff --git a/cockatrice/src/interface/widgets/tabs/tab_room.h b/cockatrice/src/interface/widgets/tabs/tab_room.h index 67d9afc86..eeb5a9e14 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_room.h +++ b/cockatrice/src/interface/widgets/tabs/tab_room.h @@ -2,8 +2,8 @@ * @file tab_room.h * @ingroup RoomTabs * @ingroup Lobby - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef TAB_ROOM_H #define TAB_ROOM_H diff --git a/cockatrice/src/interface/widgets/tabs/tab_server.h b/cockatrice/src/interface/widgets/tabs/tab_server.h index f2dd8f0a2..137823592 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_server.h +++ b/cockatrice/src/interface/widgets/tabs/tab_server.h @@ -1,8 +1,8 @@ /** * @file tab_server.h * @ingroup ServerTabs - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef TAB_SERVER_H #define TAB_SERVER_H diff --git a/cockatrice/src/interface/widgets/tabs/tab_supervisor.h b/cockatrice/src/interface/widgets/tabs/tab_supervisor.h index 0c4428f83..e77fb4f7b 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_supervisor.h +++ b/cockatrice/src/interface/widgets/tabs/tab_supervisor.h @@ -2,8 +2,8 @@ * @file tab_supervisor.h * @ingroup Core * @ingroup Tabs - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef TAB_SUPERVISOR_H #define TAB_SUPERVISOR_H diff --git a/cockatrice/src/interface/widgets/tabs/tab_visual_database_display.h b/cockatrice/src/interface/widgets/tabs/tab_visual_database_display.h index 4fe4d3e8f..f5aef6d9b 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_visual_database_display.h +++ b/cockatrice/src/interface/widgets/tabs/tab_visual_database_display.h @@ -1,8 +1,8 @@ /** * @file tab_visual_database_display.h * @ingroup Tabs - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef TAB_VISUAL_DATABASE_DISPLAY_H #define TAB_VISUAL_DATABASE_DISPLAY_H diff --git a/cockatrice/src/interface/widgets/tabs/visual_deck_editor/tab_deck_editor_visual_tab_widget.h b/cockatrice/src/interface/widgets/tabs/visual_deck_editor/tab_deck_editor_visual_tab_widget.h index 9468df425..48dd8ea9d 100644 --- a/cockatrice/src/interface/widgets/tabs/visual_deck_editor/tab_deck_editor_visual_tab_widget.h +++ b/cockatrice/src/interface/widgets/tabs/visual_deck_editor/tab_deck_editor_visual_tab_widget.h @@ -63,19 +63,19 @@ public: CardDatabaseModel *_cardDatabaseModel, CardDatabaseDisplayModel *_cardDatabaseDisplayModel); - /// Add a new tab with a widget and title. + /** @brief Add a new tab with a widget and title. */ void addNewTab(QWidget *widget, const QString &title); - /// Remove the currently active tab. + /** @brief Remove the currently active tab. */ void removeCurrentTab(); - /// Set the title of a specific tab. + /** @brief Set the title of a specific tab. */ void setTabTitle(int index, const QString &title); - /// Get the currently active tab widget. + /** @brief Get the currently active tab widget. */ [[nodiscard]] QWidget *getCurrentTab() const; - /// Get the total number of tabs. + /** @brief Get the total number of tabs. */ [[nodiscard]] int getTabCount() const; VisualDeckEditorWidget *visualDeckView; ///< Visual deck editor widget. diff --git a/cockatrice/src/interface/widgets/tabs/visual_deck_storage/tab_deck_storage_visual.h b/cockatrice/src/interface/widgets/tabs/visual_deck_storage/tab_deck_storage_visual.h index ccf752e67..d3f64e23d 100644 --- a/cockatrice/src/interface/widgets/tabs/visual_deck_storage/tab_deck_storage_visual.h +++ b/cockatrice/src/interface/widgets/tabs/visual_deck_storage/tab_deck_storage_visual.h @@ -1,8 +1,8 @@ /** * @file tab_deck_storage_visual.h * @ingroup Tabs - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef TAB_DECK_STORAGE_VISUAL_H #define TAB_DECK_STORAGE_VISUAL_H diff --git a/cockatrice/src/interface/widgets/utility/custom_line_edit.h b/cockatrice/src/interface/widgets/utility/custom_line_edit.h index 2026c1c1c..8c389b797 100644 --- a/cockatrice/src/interface/widgets/utility/custom_line_edit.h +++ b/cockatrice/src/interface/widgets/utility/custom_line_edit.h @@ -1,8 +1,8 @@ /** * @file custom_line_edit.h * @ingroup UI - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef CUSTOMLINEEDIT_H #define CUSTOMLINEEDIT_H diff --git a/cockatrice/src/interface/widgets/utility/line_edit_completer.h b/cockatrice/src/interface/widgets/utility/line_edit_completer.h index 7b3756e3c..65fa382ac 100644 --- a/cockatrice/src/interface/widgets/utility/line_edit_completer.h +++ b/cockatrice/src/interface/widgets/utility/line_edit_completer.h @@ -1,8 +1,8 @@ /** * @file line_edit_completer.h * @ingroup UI - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef LINEEDITCOMPLETER_H #define LINEEDITCOMPLETER_H diff --git a/cockatrice/src/interface/widgets/utility/sequence_edit.h b/cockatrice/src/interface/widgets/utility/sequence_edit.h index a5fe1a1c6..28e18d42f 100644 --- a/cockatrice/src/interface/widgets/utility/sequence_edit.h +++ b/cockatrice/src/interface/widgets/utility/sequence_edit.h @@ -1,8 +1,8 @@ /** * @file sequence_edit.h * @ingroup UI - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef SEQUENCEEDIT_H #define SEQUENCEEDIT_H diff --git a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_color_filter_widget.h b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_color_filter_widget.h index 698ea9e97..497d25fce 100644 --- a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_color_filter_widget.h +++ b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_color_filter_widget.h @@ -1,8 +1,8 @@ /** * @file visual_database_display_color_filter_widget.h * @ingroup VisualCardDatabaseWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef VISUAL_DATABASE_DISPLAY_COLOR_FILTER_WIDGET_H #define VISUAL_DATABASE_DISPLAY_COLOR_FILTER_WIDGET_H diff --git a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_filter_save_load_widget.h b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_filter_save_load_widget.h index bb5921a02..459633e42 100644 --- a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_filter_save_load_widget.h +++ b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_filter_save_load_widget.h @@ -1,8 +1,8 @@ /** * @file visual_database_display_filter_save_load_widget.h * @ingroup VisualCardDatabaseWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef VISUAL_DATABASE_DISPLAY_FILTER_SAVE_LOAD_WIDGET_H #define VISUAL_DATABASE_DISPLAY_FILTER_SAVE_LOAD_WIDGET_H diff --git a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_main_type_filter_widget.h b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_main_type_filter_widget.h index 9145812a7..6dec58319 100644 --- a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_main_type_filter_widget.h +++ b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_main_type_filter_widget.h @@ -1,8 +1,8 @@ /** * @file visual_database_display_main_type_filter_widget.h * @ingroup VisualCardDatabaseWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef VISUAL_DATABASE_DISPLAY_MAIN_TYPE_FILTER_WIDGET_H #define VISUAL_DATABASE_DISPLAY_MAIN_TYPE_FILTER_WIDGET_H diff --git a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_name_filter_widget.h b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_name_filter_widget.h index 76d3ec29e..5a8438a05 100644 --- a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_name_filter_widget.h +++ b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_name_filter_widget.h @@ -1,8 +1,8 @@ /** * @file visual_database_display_name_filter_widget.h * @ingroup VisualCardDatabaseWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef VISUAL_DATABASE_DISPLAY_NAME_FILTER_WIDGET_H #define VISUAL_DATABASE_DISPLAY_NAME_FILTER_WIDGET_H diff --git a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_set_filter_widget.h b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_set_filter_widget.h index dc7fd0e92..bcc5e93c2 100644 --- a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_set_filter_widget.h +++ b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_set_filter_widget.h @@ -1,8 +1,8 @@ /** * @file visual_database_display_set_filter_widget.h * @ingroup VisualCardDatabaseWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef VISUAL_DATABASE_DISPLAY_SET_FILTER_WIDGET_H #define VISUAL_DATABASE_DISPLAY_SET_FILTER_WIDGET_H diff --git a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_sub_type_filter_widget.h b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_sub_type_filter_widget.h index ce5546fc8..d713c7f99 100644 --- a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_sub_type_filter_widget.h +++ b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_sub_type_filter_widget.h @@ -1,8 +1,8 @@ /** * @file visual_database_display_sub_type_filter_widget.h * @ingroup VisualCardDatabaseWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef VISUAL_DATABASE_DISPLAY_SUB_TYPE_FILTER_WIDGET_H #define VISUAL_DATABASE_DISPLAY_SUB_TYPE_FILTER_WIDGET_H diff --git a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.h b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.h index d4a664111..48a026d11 100644 --- a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.h +++ b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.h @@ -1,8 +1,8 @@ /** * @file visual_database_display_widget.h * @ingroup VisualCardDatabaseWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef VISUAL_DATABASE_DISPLAY_WIDGET_H #define VISUAL_DATABASE_DISPLAY_WIDGET_H diff --git a/cockatrice/src/interface/widgets/visual_database_display/visual_database_filter_display_widget.h b/cockatrice/src/interface/widgets/visual_database_display/visual_database_filter_display_widget.h index 05bf43118..5fe29fa2d 100644 --- a/cockatrice/src/interface/widgets/visual_database_display/visual_database_filter_display_widget.h +++ b/cockatrice/src/interface/widgets/visual_database_display/visual_database_filter_display_widget.h @@ -1,8 +1,8 @@ /** * @file visual_database_filter_display_widget.h * @ingroup VisualCardDatabaseWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef VISUAL_DATABASE_FILTER_DISPLAY_WIDGET_H #define VISUAL_DATABASE_FILTER_DISPLAY_WIDGET_H diff --git a/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_display_options_widget.h b/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_display_options_widget.h index 9930ff50b..bc11884df 100644 --- a/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_display_options_widget.h +++ b/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_display_options_widget.h @@ -104,37 +104,37 @@ private slots: void updateDisplayType(); private: - /// Layout for grouping and sorting UI elements. + /** @brief Layout for grouping and sorting UI elements. */ QHBoxLayout *groupAndSortLayout; - /// Current deck display type. + /** @brief Current deck display type. */ DisplayType currentDisplayType = DisplayType::Overlap; - /// Button used to toggle the display layout. + /** @brief Button used to toggle the display layout. */ CompactPushButton *displayTypeButton; - /// Label for the group-by selector. + /** @brief Label for the group-by selector. */ QLabel *groupByLabel; - /// Combo box listing group-by criteria. + /** @brief Combo box listing group-by criteria. */ QComboBox *groupByComboBox; - /// Currently active group-by criterion. + /** @brief Currently active group-by criterion. */ QString activeGroupCriteria = "maintype"; - /// Encapsulates the sort settings widgets (label + list). + /** @brief Encapsulates the sort settings widgets (label + list). */ SettingsButtonWidget *sortCriteriaButton; - /// Label for “Sort by”. + /** @brief Label for "Sort by". */ QLabel *sortByLabel; - /// Descriptive label inside the sort criteria button. + /** @brief Descriptive label inside the sort criteria button. */ QLabel *sortLabel; - /// Draggable list of sort criteria. + /** @brief Draggable list of sort criteria. */ QListWidget *sortByListWidget; - /// Ordered list of current sort criteria. + /** @brief Ordered list of current sort criteria. */ QStringList activeSortCriteria = {"name", "cmc", "colors", "maintype"}; }; diff --git a/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_sample_hand_widget.h b/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_sample_hand_widget.h index c63c74a4d..c6c07dd55 100644 --- a/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_sample_hand_widget.h +++ b/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_sample_hand_widget.h @@ -1,8 +1,8 @@ /** * @file visual_deck_editor_sample_hand_widget.h * @ingroup DeckEditorAnalyticsWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef VISUAL_DECK_EDITOR_SAMPLE_HAND_WIDGET_H #define VISUAL_DECK_EDITOR_SAMPLE_HAND_WIDGET_H diff --git a/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.cpp b/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.cpp index 971498af1..4a67edcd1 100644 --- a/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.cpp +++ b/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.cpp @@ -418,7 +418,7 @@ void VisualDeckEditorWidget::onHover(const ExactCard &hoveredCard) // If nothing is selected -> this is our "active/preview" card emit activeCardChanged(hoveredCard); - // TODO: highlight hovered card visually: + //! \todo Highlight hovered card visually. // highlightHoveredCard(hoveredCard); } @@ -429,7 +429,7 @@ void VisualDeckEditorWidget::setSelectionModel(QItemSelectionModel *model) } if (selectionModel) { - // TODO: Possibly disconnect old ones? + //! \todo Possibly disconnect old signal connections. } selectionModel = model; diff --git a/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.h b/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.h index 3b90ee4e2..1af565b29 100644 --- a/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.h +++ b/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.h @@ -1,8 +1,8 @@ /** * @file visual_deck_editor_widget.h * @ingroup DeckEditors - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef VISUAL_DECK_EDITOR_H #define VISUAL_DECK_EDITOR_H diff --git a/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_color_identity_filter_widget.h b/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_color_identity_filter_widget.h index 551dbb35c..0207e2ee2 100644 --- a/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_color_identity_filter_widget.h +++ b/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_color_identity_filter_widget.h @@ -1,8 +1,8 @@ /** * @file deck_preview_color_identity_filter_widget.h * @ingroup VisualDeckPreviewWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef DECK_PREVIEW_COLOR_IDENTITY_FILTER_WIDGET_H #define DECK_PREVIEW_COLOR_IDENTITY_FILTER_WIDGET_H diff --git a/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_deck_tags_display_widget.h b/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_deck_tags_display_widget.h index bfd0a170d..4bd7915cd 100644 --- a/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_deck_tags_display_widget.h +++ b/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_deck_tags_display_widget.h @@ -1,8 +1,8 @@ /** * @file deck_preview_deck_tags_display_widget.h * @ingroup VisualDeckPreviewWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef DECK_PREVIEW_DECK_TAGS_DISPLAY_WIDGET_H #define DECK_PREVIEW_DECK_TAGS_DISPLAY_WIDGET_H diff --git a/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_tag_addition_widget.h b/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_tag_addition_widget.h index c0fa86d19..7a3a735a2 100644 --- a/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_tag_addition_widget.h +++ b/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_tag_addition_widget.h @@ -1,8 +1,8 @@ /** * @file deck_preview_tag_addition_widget.h * @ingroup VisualDeckPreviewWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef DECK_PREVIEW_TAG_ADDITION_WIDGET_H #define DECK_PREVIEW_TAG_ADDITION_WIDGET_H diff --git a/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_tag_dialog.h b/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_tag_dialog.h index 59b330a65..4d9040af4 100644 --- a/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_tag_dialog.h +++ b/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_tag_dialog.h @@ -2,8 +2,8 @@ * @file deck_preview_tag_dialog.h * @ingroup VisualDeckPreviewWidgets * @ingroup Dialogs - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef DECK_PREVIEW_TAG_DIALOG_H #define DECK_PREVIEW_TAG_DIALOG_H diff --git a/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_tag_display_widget.h b/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_tag_display_widget.h index a868aa4f1..980741c5d 100644 --- a/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_tag_display_widget.h +++ b/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_tag_display_widget.h @@ -1,8 +1,8 @@ /** * @file deck_preview_tag_display_widget.h * @ingroup VisualDeckPreviewWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef DECK_PREVIEW_TAG_DISPLAY_WIDGET_H #define DECK_PREVIEW_TAG_DISPLAY_WIDGET_H diff --git a/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_tag_item_widget.h b/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_tag_item_widget.h index 5caae90a1..a3301799a 100644 --- a/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_tag_item_widget.h +++ b/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_tag_item_widget.h @@ -1,8 +1,8 @@ /** * @file deck_preview_tag_item_widget.h * @ingroup VisualDeckPreviewWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef DECK_PREVIEW_TAG_ITEM_WIDGET_H #define DECK_PREVIEW_TAG_ITEM_WIDGET_H diff --git a/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_widget.cpp b/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_widget.cpp index 77ea8f865..06dc9dd84 100644 --- a/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_widget.cpp +++ b/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_widget.cpp @@ -28,8 +28,8 @@ DeckPreviewWidget::DeckPreviewWidget(QWidget *_parent, deckLoader = new DeckLoader(this); connect(deckLoader, &DeckLoader::loadFinished, this, &DeckPreviewWidget::initializeUi); - /* TODO: We shouldn't update the tags on *every* deck load, since it's kinda expensive. We should instead count how - many deck loads have finished already and if we've loaded all decks and THEN load all the tags at once. */ + //! \todo Batch tag refresh: count finished deck loads and refresh tags once all decks are loaded. + // Currently expensive: refreshes on each individual deck load instead of once at the end. connect(deckLoader, &DeckLoader::loadFinished, visualDeckStorageWidget->tagFilterWidget, &VisualDeckStorageTagFilterWidget::refreshTags); deckLoader->loadFromFileAsync(filePath, DeckFileFormat::getFormatFromName(filePath), false); diff --git a/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_widget.h b/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_widget.h index 98116cabe..0ed64e9e2 100644 --- a/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_widget.h +++ b/cockatrice/src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_widget.h @@ -1,8 +1,8 @@ /** * @file deck_preview_widget.h * @ingroup VisualDeckPreviewWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef DECK_PREVIEW_WIDGET_H #define DECK_PREVIEW_WIDGET_H diff --git a/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_folder_display_widget.h b/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_folder_display_widget.h index d76fb0497..a5e3be212 100644 --- a/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_folder_display_widget.h +++ b/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_folder_display_widget.h @@ -1,8 +1,8 @@ /** * @file visual_deck_storage_folder_display_widget.h * @ingroup VisualDeckStorageWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef VISUAL_DECK_STORAGE_FOLDER_DISPLAY_WIDGET_H #define VISUAL_DECK_STORAGE_FOLDER_DISPLAY_WIDGET_H diff --git a/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_search_widget.h b/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_search_widget.h index 67d260b21..2f3d81aeb 100644 --- a/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_search_widget.h +++ b/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_search_widget.h @@ -1,8 +1,8 @@ /** * @file visual_deck_storage_search_widget.h * @ingroup VisualDeckStorageWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef VISUAL_DECK_STORAGE_SEARCH_WIDGET_H #define VISUAL_DECK_STORAGE_SEARCH_WIDGET_H diff --git a/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_sort_widget.h b/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_sort_widget.h index 1ea06aba4..24eddba33 100644 --- a/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_sort_widget.h +++ b/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_sort_widget.h @@ -1,8 +1,8 @@ /** * @file visual_deck_storage_sort_widget.h * @ingroup VisualDeckStorageWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef VISUAL_DECK_STORAGE_SORT_WIDGET_H #define VISUAL_DECK_STORAGE_SORT_WIDGET_H diff --git a/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_tag_filter_widget.h b/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_tag_filter_widget.h index ada94a244..3290c9e9a 100644 --- a/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_tag_filter_widget.h +++ b/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_tag_filter_widget.h @@ -1,8 +1,8 @@ /** * @file visual_deck_storage_tag_filter_widget.h * @ingroup VisualDeckStorageWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef VISUAL_DECK_STORAGE_TAG_FILTER_WIDGET_H #define VISUAL_DECK_STORAGE_TAG_FILTER_WIDGET_H diff --git a/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_widget.h b/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_widget.h index b13c51700..c3c0ae91b 100644 --- a/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_widget.h +++ b/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_widget.h @@ -1,8 +1,8 @@ /** * @file visual_deck_storage_widget.h * @ingroup VisualDeckStorageWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef VISUAL_DECK_STORAGE_WIDGET_H #define VISUAL_DECK_STORAGE_WIDGET_H diff --git a/cockatrice/src/interface/window_main.h b/cockatrice/src/interface/window_main.h index 528e6f211..5f631ddc3 100644 --- a/cockatrice/src/interface/window_main.h +++ b/cockatrice/src/interface/window_main.h @@ -20,8 +20,8 @@ /** * @file window_main.h * @ingroup Core - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef WINDOW_H #define WINDOW_H diff --git a/cockatrice/src/main.h b/cockatrice/src/main.h index b6e086744..ef75a41f4 100644 --- a/cockatrice/src/main.h +++ b/cockatrice/src/main.h @@ -1,8 +1,8 @@ /** * @file main.h * @ingroup Core - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef MAIN_H #define MAIN_H diff --git a/libcockatrice_card/libcockatrice/card/card_info_comparator.h b/libcockatrice_card/libcockatrice/card/card_info_comparator.h index b8d9c47e6..b6df8c7a3 100644 --- a/libcockatrice_card/libcockatrice/card/card_info_comparator.h +++ b/libcockatrice_card/libcockatrice/card/card_info_comparator.h @@ -1,8 +1,8 @@ /** * @file card_info_comparator.h * @ingroup Cards - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef CARD_INFO_COMPARATOR_H #define CARD_INFO_COMPARATOR_H diff --git a/libcockatrice_card/libcockatrice/card/database/card_database.h b/libcockatrice_card/libcockatrice/card/database/card_database.h index b1af3a2c0..521be8fbc 100644 --- a/libcockatrice_card/libcockatrice/card/database/card_database.h +++ b/libcockatrice_card/libcockatrice/card/database/card_database.h @@ -30,27 +30,27 @@ class CardDatabase : public QObject Q_OBJECT protected: - /// Controller to determine set priority when choosing preferred printings. + /** @brief Controller to determine set priority when choosing preferred printings. */ ICardSetPriorityController *setPriorityController; - /// Cards indexed by exact name + /** @brief Cards indexed by exact name. */ CardNameMap cards; - /// Cards indexed by simplified name (normalized) + /** @brief Cards indexed by simplified name (normalized). */ CardNameMap simpleNameCards; - /// Sets indexed by short name + /** @brief Sets indexed by short name. */ SetNameMap sets; FormatRulesNameMap formats; - /// Loader responsible for file discovery and parsing + /** @brief Loader responsible for file discovery and parsing. */ CardDatabaseLoader *loader; - /// Current load status of the database + /** @brief Current load status of the database. */ LoadStatus loadStatus; - /// Querier for higher-level card lookups + /** @brief Querier for higher-level card lookups. */ CardDatabaseQuerier *querier; private: @@ -64,7 +64,7 @@ private: */ void refreshCachedReverseRelatedCards(); - /// Mutexes for thread safety + /** @brief Mutexes for thread safety. */ QBasicMutex *clearDatabaseMutex = new QBasicMutex(), *addCardMutex = new QBasicMutex(), *removeCardMutex = new QBasicMutex(); @@ -133,7 +133,7 @@ public: ICardSetPriorityController *getPriorityController() { return setPriorityController; - }; + } public slots: /** diff --git a/libcockatrice_card/libcockatrice/card/database/card_database_manager.h b/libcockatrice_card/libcockatrice/card/database/card_database_manager.h index 58a744fbb..c7de66a25 100644 --- a/libcockatrice_card/libcockatrice/card/database/card_database_manager.h +++ b/libcockatrice_card/libcockatrice/card/database/card_database_manager.h @@ -67,13 +67,13 @@ private: /** @brief Private destructor. */ ~CardDatabaseManager() = default; - /// Static card preference provider pointer (default: Noop) + /** @brief Static card preference provider pointer (default: Noop). */ static ICardPreferenceProvider *cardPreferenceProvider; - /// Static path provider pointer (default: Noop) + /** @brief Static path provider pointer (default: Noop). */ static ICardDatabasePathProvider *pathProvider; - /// Static set priority controller pointer (default: Noop) + /** @brief Static set priority controller pointer (default: Noop). */ static ICardSetPriorityController *setPriorityController; }; diff --git a/libcockatrice_card/libcockatrice/card/game_specific_terms.h b/libcockatrice_card/libcockatrice/card/game_specific_terms.h index 3616745be..e9160e514 100644 --- a/libcockatrice_card/libcockatrice/card/game_specific_terms.h +++ b/libcockatrice_card/libcockatrice/card/game_specific_terms.h @@ -1,8 +1,8 @@ /** * @file game_specific_terms.h * @ingroup Cards - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef GAME_SPECIFIC_TERMS_H #define GAME_SPECIFIC_TERMS_H diff --git a/libcockatrice_card/libcockatrice/card/set/card_set.h b/libcockatrice_card/libcockatrice/card/set/card_set.h index 2cedb597e..8e16e01df 100644 --- a/libcockatrice_card/libcockatrice/card/set/card_set.h +++ b/libcockatrice_card/libcockatrice/card/set/card_set.h @@ -107,31 +107,31 @@ public: */ [[nodiscard]] QString getCorrectedShortName() const; - /// @return Short identifier of the set. + /** @return Short identifier of the set. */ [[nodiscard]] QString getShortName() const { return shortName; } - /// @return Descriptive name of the set. + /** @return Descriptive name of the set. */ [[nodiscard]] QString getLongName() const { return longName; } - /// @return Type/category string of the set. + /** @return Type/category string of the set. */ [[nodiscard]] QString getSetType() const { return setType; } - /// @return Release date of the set. + /** @return Release date of the set. */ [[nodiscard]] QDate getReleaseDate() const { return releaseDate; } - /// @return Priority level of the set. + /** @return Priority level of the set. */ [[nodiscard]] Priority getPriority() const { return priority; @@ -190,7 +190,7 @@ public: enabled = _enabled; } - /// @return The sort key assigned to this set. + /** @return The sort key assigned to this set. */ [[nodiscard]] int getSortKey() const { return sortKey; @@ -202,7 +202,7 @@ public: */ void setSortKey(unsigned int _sortKey); - /// @return True if the set is enabled. + /** @return True if the set is enabled. */ [[nodiscard]] bool getEnabled() const { return enabled; @@ -214,7 +214,7 @@ public: */ void setEnabled(bool _enabled); - /// @return True if the set is considered known. + /** @return True if the set is considered known. */ [[nodiscard]] bool getIsKnown() const { return isknown; diff --git a/libcockatrice_card/libcockatrice/card/set/card_set_comparator.h b/libcockatrice_card/libcockatrice/card/set/card_set_comparator.h index 96f1052a9..0caa9f156 100644 --- a/libcockatrice_card/libcockatrice/card/set/card_set_comparator.h +++ b/libcockatrice_card/libcockatrice/card/set/card_set_comparator.h @@ -1,8 +1,8 @@ /** * @file card_set_comparator.h * @ingroup CardSets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef SET_PRIORITY_COMPARATOR_H #define SET_PRIORITY_COMPARATOR_H diff --git a/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.h b/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.h index a96adeb38..e792c85dc 100644 --- a/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.h +++ b/libcockatrice_deck_list/libcockatrice/deck_list/deck_list.h @@ -89,7 +89,7 @@ private: mutable QString cachedDeckHash; public: - /// @name Metadata setters + /** @name Metadata setters */ ///@{ void setName(const QString &_name = QString()) { @@ -125,11 +125,11 @@ public: } ///@} - /// @brief Construct an empty deck. + /** @brief Construct an empty deck. */ explicit DeckList(); - /// @brief Construct from a serialized native-format string. + /** @brief Construct from a serialized native-format string. */ explicit DeckList(const QString &nativeString); - /// @brief Construct from components + /** @brief Construct from components. */ DeckList(const Metadata &metadata, const DecklistNodeTree &tree, const QMap &sideboardPlans = {}); @@ -144,8 +144,10 @@ public: return &tree; } - /// @name Metadata getters - /// The individual metadata getters still exist for backwards compatibility. + /** + * @name Metadata getters + * The individual metadata getters still exist for backwards compatibility. + */ ///@{ //! \todo Figure out when we can remove them. const Metadata &getMetadata() const @@ -183,7 +185,7 @@ public: return metadata.isEmpty() && getCardList().isEmpty(); } - /// @name Sideboard plans + /** @name Sideboard plans */ ///@{ QList getCurrentSideboardPlan() const; void setCurrentSideboardPlan(const QList &plan); @@ -193,7 +195,7 @@ public: } ///@} - /// @name Serialization (XML) + /** @name Serialization (XML) */ ///@{ bool readElement(QXmlStreamReader *xml); void write(QXmlStreamWriter *xml) const; @@ -204,7 +206,7 @@ public: bool saveToFile_Native(QIODevice *device) const; ///@} - /// @name Serialization (Plain text) + /** @name Serialization (Plain text) */ ///@{ bool loadFromStream_Plain(QTextStream &stream, bool preserveMetadata, @@ -216,7 +218,7 @@ public: QString writeToString_Plain(bool prefixSideboardCards = true, bool slashTappedOutSplitCards = false) const; ///@} - /// @name Deck manipulation + /** @name Deck manipulation */ ///@{ void cleanList(bool preserveMetadata = false); bool isEmpty() const @@ -238,7 +240,7 @@ public: const bool formatLegal = true); ///@} - /// @name Deck identity + /** @name Deck identity */ ///@{ QString getDeckHash() const; void refreshDeckHash(); diff --git a/libcockatrice_deck_list/libcockatrice/deck_list/deck_list_node_tree.h b/libcockatrice_deck_list/libcockatrice/deck_list/deck_list_node_tree.h index 6de760634..8ef0b18a5 100644 --- a/libcockatrice_deck_list/libcockatrice/deck_list/deck_list_node_tree.h +++ b/libcockatrice_deck_list/libcockatrice/deck_list/deck_list_node_tree.h @@ -12,11 +12,11 @@ class DecklistNodeTree InnerDecklistNode *root; ///< Root of the deck tree (zones + cards). public: - /// @brief Constructs an empty DecklistNodeTree + /** @brief Constructs an empty DecklistNodeTree. */ explicit DecklistNodeTree(); - /// @brief Copy constructor. Deep copies the tree + /** @brief Copy constructor. Deep copies the tree. */ explicit DecklistNodeTree(const DecklistNodeTree &other); - /// @brief Copy-assignment operator. Deep copies the tree + /** @brief Copy-assignment operator. Deep copies the tree. */ DecklistNodeTree &operator=(const DecklistNodeTree &other); virtual ~DecklistNodeTree(); diff --git a/libcockatrice_deck_list/libcockatrice/deck_list/sideboard_plan.h b/libcockatrice_deck_list/libcockatrice/deck_list/sideboard_plan.h index 524217c2d..fff4ff2f3 100644 --- a/libcockatrice_deck_list/libcockatrice/deck_list/sideboard_plan.h +++ b/libcockatrice_deck_list/libcockatrice/deck_list/sideboard_plan.h @@ -51,19 +51,19 @@ public: */ void write(QXmlStreamWriter *xml) const; - /// @return The plan name. + /** @return The plan name. */ [[nodiscard]] QString getName() const { return name; } - /// @return Const reference to the move list. + /** @return Const reference to the move list. */ [[nodiscard]] const QList &getMoveList() const { return moveList; } - /// @brief Replace the move list with a new one. + /** @brief Replace the move list with a new one. */ void setMoveList(const QList &_moveList); }; diff --git a/libcockatrice_deck_list/libcockatrice/deck_list/tree/abstract_deck_list_card_node.h b/libcockatrice_deck_list/libcockatrice/deck_list/tree/abstract_deck_list_card_node.h index 88d8b0930..df903a168 100644 --- a/libcockatrice_deck_list/libcockatrice/deck_list/tree/abstract_deck_list_card_node.h +++ b/libcockatrice_deck_list/libcockatrice/deck_list/tree/abstract_deck_list_card_node.h @@ -58,40 +58,40 @@ public: { } - /// @return The number of copies of this card in the deck. + /** @return The number of copies of this card in the deck. */ [[nodiscard]] virtual int getNumber() const = 0; - /// @param _number Set the number of copies of this card. + /** @param _number Set the number of copies of this card. */ virtual void setNumber(int _number) = 0; - /// @return The display name of this card. + /** @return The display name of this card. */ [[nodiscard]] QString getName() const override = 0; - /// @param _name Set the display name of this card. + /** @param _name Set the display name of this card. */ virtual void setName(const QString &_name) = 0; - /// @return The provider identifier for this card (e.g., UUID). + /** @return The provider identifier for this card (e.g., UUID). */ [[nodiscard]] virtual QString getCardProviderId() const override = 0; - /// @param _cardProviderId Set the provider identifier for this card. + /** @param _cardProviderId Set the provider identifier for this card. */ virtual void setCardProviderId(const QString &_cardProviderId) = 0; - /// @return The abbreviated set code (e.g., "NEO"). + /** @return The abbreviated set code (e.g., "NEO"). */ [[nodiscard]] virtual QString getCardSetShortName() const override = 0; - /// @param _cardSetShortName Set the abbreviated set code. + /** @param _cardSetShortName Set the abbreviated set code. */ virtual void setCardSetShortName(const QString &_cardSetShortName) = 0; - /// @return The collector number of the card within its set. + /** @return The collector number of the card within its set. */ [[nodiscard]] virtual QString getCardCollectorNumber() const override = 0; - /// @param _cardSetNumber Set the collector number. + /** @param _cardSetNumber Set the collector number. */ virtual void setCardCollectorNumber(const QString &_cardSetNumber) = 0; - /// @return The format legality of the card + /** @return The format legality of the card. */ virtual bool getFormatLegality() const = 0; - /// @param _formatLegal If the card is considered legal + /** @param _formatLegal If the card is considered legal. */ virtual void setFormatLegality(const bool _formatLegal) = 0; /** diff --git a/libcockatrice_deck_list/libcockatrice/deck_list/tree/abstract_deck_list_node.h b/libcockatrice_deck_list/libcockatrice/deck_list/tree/abstract_deck_list_node.h index 877705705..a39f0e7b2 100644 --- a/libcockatrice_deck_list/libcockatrice/deck_list/tree/abstract_deck_list_node.h +++ b/libcockatrice_deck_list/libcockatrice/deck_list/tree/abstract_deck_list_node.h @@ -101,7 +101,7 @@ public: */ explicit AbstractDecklistNode(InnerDecklistNode *_parent = nullptr, int position = -1); - /// Virtual destructor. Child classes must clean up their resources. + /** @brief Virtual destructor. Child classes must clean up their resources. */ virtual ~AbstractDecklistNode() = default; /** @@ -136,7 +136,7 @@ public: */ [[nodiscard]] virtual bool isDeckHeader() const = 0; - /// @return The parent node, or nullptr if this is the root. + /** @return The parent node, or nullptr if this is the root. */ [[nodiscard]] InnerDecklistNode *getParent() const { return parent; diff --git a/libcockatrice_deck_list/libcockatrice/deck_list/tree/deck_list_card_node.h b/libcockatrice_deck_list/libcockatrice/deck_list/tree/deck_list_card_node.h index b3d42b89a..3bab5405a 100644 --- a/libcockatrice_deck_list/libcockatrice/deck_list/tree/deck_list_card_node.h +++ b/libcockatrice_deck_list/libcockatrice/deck_list/tree/deck_list_card_node.h @@ -93,79 +93,79 @@ public: */ explicit DecklistCardNode(DecklistCardNode *other, InnerDecklistNode *_parent); - /// @return The quantity of this card. + /** @return The quantity of this card. */ [[nodiscard]] int getNumber() const override { return number; } - /// @param _number Set the quantity of this card. + /** @param _number Set the quantity of this card. */ void setNumber(int _number) override { number = _number; } - /// @return The display name of this card. + /** @return The display name of this card. */ [[nodiscard]] QString getName() const override { return name; } - /// @param _name Set the display name of this card. + /** @param _name Set the display name of this card. */ void setName(const QString &_name) override { name = _name; } - /// @return The provider identifier for this card. + /** @return The provider identifier for this card. */ [[nodiscard]] QString getCardProviderId() const override { return cardProviderId; } - /// @param _providerId Set the provider identifier for this card. + /** @param _providerId Set the provider identifier for this card. */ void setCardProviderId(const QString &_providerId) override { cardProviderId = _providerId; } - /// @return The short set code (e.g., "NEO"). + /** @return The short set code (e.g., "NEO"). */ [[nodiscard]] QString getCardSetShortName() const override { return cardSetShortName; } - /// @param _cardSetShortName Set the short set code. + /** @param _cardSetShortName Set the short set code. */ void setCardSetShortName(const QString &_cardSetShortName) override { cardSetShortName = _cardSetShortName; } - /// @return The collector number of this card within its set. + /** @return The collector number of this card within its set. */ [[nodiscard]] QString getCardCollectorNumber() const override { return cardSetNumber; } - /// @param _cardSetNumber Set the collector number. + /** @param _cardSetNumber Set the collector number. */ void setCardCollectorNumber(const QString &_cardSetNumber) override { cardSetNumber = _cardSetNumber; } - /// @return The format legality of the card + /** @return The format legality of the card. */ [[nodiscard]] bool getFormatLegality() const override { return formatLegal; } - /// @param _formatLegal If the card is considered legal + /** @param _formatLegal If the card is considered legal. */ void setFormatLegality(const bool _formatLegal) override { formatLegal = _formatLegal; } - /// @return Always false; card nodes are not deck headers. + /** @return Always false; card nodes are not deck headers. */ [[nodiscard]] bool isDeckHeader() const override { return false; diff --git a/libcockatrice_deck_list/libcockatrice/deck_list/tree/inner_deck_list_node.h b/libcockatrice_deck_list/libcockatrice/deck_list/tree/inner_deck_list_node.h index f4c48afce..81c37dffa 100644 --- a/libcockatrice_deck_list/libcockatrice/deck_list/tree/inner_deck_list_node.h +++ b/libcockatrice_deck_list/libcockatrice/deck_list/tree/inner_deck_list_node.h @@ -18,11 +18,11 @@ #include "abstract_deck_list_node.h" -/// Constant for the "main" deck zone name. +/** @brief Constant for the "main" deck zone name. */ #define DECK_ZONE_MAIN "main" -/// Constant for the "sideboard" zone name. +/** @brief Constant for the "sideboard" zone name. */ #define DECK_ZONE_SIDE "side" -/// Constant for the "tokens" zone name. +/** @brief Constant for the "tokens" zone name. */ #define DECK_ZONE_TOKENS "tokens" /** @@ -93,13 +93,13 @@ public: */ void setSortMethod(DeckSortMethod method) override; - /// @return The internal name of this node. + /** @return The internal name of this node. */ [[nodiscard]] QString getName() const override { return name; } - /// @param _name Set the internal name of this node. + /** @param _name Set the internal name of this node. */ void setName(const QString &_name) { name = _name; @@ -122,25 +122,25 @@ public: */ [[nodiscard]] virtual QString getVisibleName() const; - /// @return Always empty for container nodes. + /** @return Always empty for container nodes. */ [[nodiscard]] QString getCardProviderId() const override { return ""; } - /// @return Always empty for container nodes. + /** @return Always empty for container nodes. */ [[nodiscard]] QString getCardSetShortName() const override { return ""; } - /// @return Always empty for container nodes. + /** @return Always empty for container nodes. */ [[nodiscard]] QString getCardCollectorNumber() const override { return ""; } - /// @return Always true; InnerDecklistNode represents deck structure. + /** @return Always true; InnerDecklistNode represents deck structure. */ [[nodiscard]] bool isDeckHeader() const override { return true; @@ -196,10 +196,10 @@ public: */ bool compare(AbstractDecklistNode *other) const override; - /// @copydoc compare(AbstractDecklistNode*) const + /** @copydoc compare(AbstractDecklistNode*) const */ bool compareNumber(AbstractDecklistNode *other) const; - /// @copydoc compare(AbstractDecklistNode*) const + /** @copydoc compare(AbstractDecklistNode*) const */ bool compareName(AbstractDecklistNode *other) const; /** diff --git a/libcockatrice_filters/libcockatrice/filters/filter_card.h b/libcockatrice_filters/libcockatrice/filters/filter_card.h index 732e43a09..bb1e0ef53 100644 --- a/libcockatrice_filters/libcockatrice/filters/filter_card.h +++ b/libcockatrice_filters/libcockatrice/filters/filter_card.h @@ -1,8 +1,8 @@ /** * @file filter_card.h * @ingroup CardDatabaseModelFilters - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef CARDFILTER_H #define CARDFILTER_H diff --git a/libcockatrice_filters/libcockatrice/filters/filter_string.h b/libcockatrice_filters/libcockatrice/filters/filter_string.h index 8fc41ce68..71a99f7b5 100644 --- a/libcockatrice_filters/libcockatrice/filters/filter_string.h +++ b/libcockatrice_filters/libcockatrice/filters/filter_string.h @@ -1,8 +1,8 @@ /** * @file filter_string.h * @ingroup CardDatabaseModelFilters - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef FILTER_STRING_H #define FILTER_STRING_H diff --git a/libcockatrice_filters/libcockatrice/filters/filter_tree.h b/libcockatrice_filters/libcockatrice/filters/filter_tree.h index 75d4241a5..aac1777e0 100644 --- a/libcockatrice_filters/libcockatrice/filters/filter_tree.h +++ b/libcockatrice_filters/libcockatrice/filters/filter_tree.h @@ -1,8 +1,8 @@ /** * @file filter_tree.h * @ingroup CardDatabaseModelFilters - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef FILTERTREE_H #define FILTERTREE_H @@ -70,28 +70,33 @@ public: } virtual void nodeChanged() const { - if (parent() != nullptr) + if (parent() != nullptr) { parent()->nodeChanged(); + } } virtual void preInsertChild(const FilterTreeNode *p, int i) const { - if (parent() != nullptr) + if (parent() != nullptr) { parent()->preInsertChild(p, i); + } } virtual void postInsertChild(const FilterTreeNode *p, int i) const { - if (parent() != nullptr) + if (parent() != nullptr) { parent()->postInsertChild(p, i); + } } virtual void preRemoveChild(const FilterTreeNode *p, int i) const { - if (parent() != nullptr) + if (parent() != nullptr) { parent()->preRemoveChild(p, i); + } } virtual void postRemoveChild(const FilterTreeNode *p, int i) const { - if (parent() != nullptr) + if (parent() != nullptr) { parent()->postRemoveChild(p, i); + } } }; diff --git a/libcockatrice_models/libcockatrice/models/database/card/card_completer_proxy_model.h b/libcockatrice_models/libcockatrice/models/database/card/card_completer_proxy_model.h index afb6f1fcf..91dc06335 100644 --- a/libcockatrice_models/libcockatrice/models/database/card/card_completer_proxy_model.h +++ b/libcockatrice_models/libcockatrice/models/database/card/card_completer_proxy_model.h @@ -1,8 +1,8 @@ /** * @file card_completer_proxy_model.h * @ingroup CardDatabaseModels - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef CARD_COMPLETER_PROXY_MODEL_H #define CARD_COMPLETER_PROXY_MODEL_H diff --git a/libcockatrice_models/libcockatrice/models/database/card/card_search_model.h b/libcockatrice_models/libcockatrice/models/database/card/card_search_model.h index 18be2c55a..bc4be7a0e 100644 --- a/libcockatrice_models/libcockatrice/models/database/card/card_search_model.h +++ b/libcockatrice_models/libcockatrice/models/database/card/card_search_model.h @@ -1,8 +1,8 @@ /** * @file card_search_model.h * @ingroup CardDatabaseModels - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef CARD_SEARCH_MODEL_H #define CARD_SEARCH_MODEL_H diff --git a/libcockatrice_models/libcockatrice/models/database/card_set/card_sets_model.h b/libcockatrice_models/libcockatrice/models/database/card_set/card_sets_model.h index 0ffc5a847..2adf71def 100644 --- a/libcockatrice_models/libcockatrice/models/database/card_set/card_sets_model.h +++ b/libcockatrice_models/libcockatrice/models/database/card_set/card_sets_model.h @@ -1,8 +1,8 @@ /** * @file sets_model.h * @ingroup CardDatabaseModels - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef SETSMODEL_H #define SETSMODEL_H diff --git a/libcockatrice_models/libcockatrice/models/database/token/token_display_model.h b/libcockatrice_models/libcockatrice/models/database/token/token_display_model.h index f6b2fdfbb..c8f767189 100644 --- a/libcockatrice_models/libcockatrice/models/database/token/token_display_model.h +++ b/libcockatrice_models/libcockatrice/models/database/token/token_display_model.h @@ -1,8 +1,8 @@ /** * @file token_display_model.h * @ingroup CardDatabaseModels - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef COCKATRICE_TOKEN_DISPLAY_MODEL_H #define COCKATRICE_TOKEN_DISPLAY_MODEL_H diff --git a/libcockatrice_models/libcockatrice/models/database/token/token_edit_model.h b/libcockatrice_models/libcockatrice/models/database/token/token_edit_model.h index 5e5843761..92dfaadd7 100644 --- a/libcockatrice_models/libcockatrice/models/database/token/token_edit_model.h +++ b/libcockatrice_models/libcockatrice/models/database/token/token_edit_model.h @@ -1,8 +1,8 @@ /** * @file token_edit_model.h * @ingroup CardDatabaseModels - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef COCKATRICE_TOKEN_EDIT_MODEL_H #define COCKATRICE_TOKEN_EDIT_MODEL_H diff --git a/libcockatrice_models/libcockatrice/models/deck_list/deck_list_model.cpp b/libcockatrice_models/libcockatrice/models/deck_list/deck_list_model.cpp index e43c612f0..9b43281c1 100644 --- a/libcockatrice_models/libcockatrice/models/deck_list/deck_list_model.cpp +++ b/libcockatrice_models/libcockatrice/models/deck_list/deck_list_model.cpp @@ -66,7 +66,7 @@ void DeckListModel::rebuildTree() for (int j = 0; j < currentZone->size(); j++) { auto *currentCard = dynamic_cast(currentZone->at(j)); - // TODO: better sanity checking + //! \todo Better sanity checking. if (currentCard == nullptr) { continue; } @@ -257,8 +257,9 @@ Qt::ItemFlags DeckListModel::flags(const QModelIndex &index) const void DeckListModel::emitBackgroundUpdates(const QModelIndex &parent) { int rows = rowCount(parent); - if (rows == 0) + if (rows == 0) { return; + } QModelIndex topLeft = index(0, 0, parent); QModelIndex bottomRight = index(rows - 1, columnCount() - 1, parent); @@ -539,8 +540,9 @@ int DeckListModel::findSortedInsertRow(const InnerDecklistNode *parent, const Ca for (int i = 0; i < parent->size(); ++i) { auto *existingCard = dynamic_cast(parent->at(i)); - if (!existingCard) + if (!existingCard) { continue; + } bool lessThan = false; switch (lastKnownColumn) { @@ -557,8 +559,9 @@ int DeckListModel::findSortedInsertRow(const InnerDecklistNode *parent, const Ca break; } - if (lessThan) + if (lessThan) { return i; + } } return parent->size(); // insert at end if no earlier match diff --git a/libcockatrice_models/libcockatrice/models/deck_list/deck_list_sort_filter_proxy_model.h b/libcockatrice_models/libcockatrice/models/deck_list/deck_list_sort_filter_proxy_model.h index 94742795d..1565417f0 100644 --- a/libcockatrice_models/libcockatrice/models/deck_list/deck_list_sort_filter_proxy_model.h +++ b/libcockatrice_models/libcockatrice/models/deck_list/deck_list_sort_filter_proxy_model.h @@ -1,8 +1,8 @@ /** * @file deck_list_sort_filter_proxy_model.h * @ingroup DeckEditorCardGroupWidgets - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef COCKATRICE_DECK_LIST_SORT_FILTER_PROXY_MODEL_H #define COCKATRICE_DECK_LIST_SORT_FILTER_PROXY_MODEL_H diff --git a/libcockatrice_network/libcockatrice/network/client/abstract/abstract_client.h b/libcockatrice_network/libcockatrice/network/client/abstract/abstract_client.h index dc3be5a94..2eb7e3356 100644 --- a/libcockatrice_network/libcockatrice/network/client/abstract/abstract_client.h +++ b/libcockatrice_network/libcockatrice/network/client/abstract/abstract_client.h @@ -1,8 +1,8 @@ /** * @file abstract_client.h * @ingroup Client - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef ABSTRACTCLIENT_H #define ABSTRACTCLIENT_H diff --git a/libcockatrice_network/libcockatrice/network/client/local/local_client.h b/libcockatrice_network/libcockatrice/network/client/local/local_client.h index e8c5330ac..9e1c89ddd 100644 --- a/libcockatrice_network/libcockatrice/network/client/local/local_client.h +++ b/libcockatrice_network/libcockatrice/network/client/local/local_client.h @@ -1,8 +1,8 @@ /** * @file local_client.h * @ingroup Client - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef LOCALCLIENT_H #define LOCALCLIENT_H diff --git a/libcockatrice_network/libcockatrice/network/client/remote/remote_client.cpp b/libcockatrice_network/libcockatrice/network/client/remote/remote_client.cpp index 0ef211b94..7e20f2722 100644 --- a/libcockatrice_network/libcockatrice/network/client/remote/remote_client.cpp +++ b/libcockatrice_network/libcockatrice/network/client/remote/remote_client.cpp @@ -224,14 +224,14 @@ Command_Login RemoteClient::generateCommandLogin() void RemoteClient::doLogin() { if (!password.isEmpty() && serverSupportsPasswordHash) { - // TODO store and log in using stored hashed password + //! \todo Store and log in using stored hashed password. if (hashedPassword.isEmpty()) { doRequestPasswordSalt(); // ask salt to create hashedPassword, then log in } else { doHashedLogin(); // log in using hashed password instead } } else { - // TODO add setting for client to reject unhashed logins + //! \todo Add setting for client to reject unhashed logins. setStatus(StatusLoggingIn); Command_Login cmdLogin = generateCommandLogin(); if (!password.isEmpty()) { diff --git a/libcockatrice_network/libcockatrice/network/client/remote/remote_client.h b/libcockatrice_network/libcockatrice/network/client/remote/remote_client.h index 15e3e8ef5..289fdc5d0 100644 --- a/libcockatrice_network/libcockatrice/network/client/remote/remote_client.h +++ b/libcockatrice_network/libcockatrice/network/client/remote/remote_client.h @@ -1,8 +1,8 @@ /** * @file remote_client.h * @ingroup Client - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef REMOTECLIENT_H #define REMOTECLIENT_H diff --git a/libcockatrice_network/libcockatrice/network/server/local/local_server.h b/libcockatrice_network/libcockatrice/network/server/local/local_server.h index 70586f6c1..0112afa72 100644 --- a/libcockatrice_network/libcockatrice/network/server/local/local_server.h +++ b/libcockatrice_network/libcockatrice/network/server/local/local_server.h @@ -1,8 +1,8 @@ /** * @file local_server.h * @ingroup Server - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef LOCALSERVER_H #define LOCALSERVER_H diff --git a/libcockatrice_network/libcockatrice/network/server/local/local_server_interface.h b/libcockatrice_network/libcockatrice/network/server/local/local_server_interface.h index 4410fd65c..44e3b3e53 100644 --- a/libcockatrice_network/libcockatrice/network/server/local/local_server_interface.h +++ b/libcockatrice_network/libcockatrice/network/server/local/local_server_interface.h @@ -1,8 +1,8 @@ /** * @file local_server_interface.h * @ingroup Server - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef LOCALSERVERINTERFACE_H #define LOCALSERVERINTERFACE_H diff --git a/libcockatrice_network/libcockatrice/network/server/remote/game/server_game.cpp b/libcockatrice_network/libcockatrice/network/server/remote/game/server_game.cpp index f5a4889d0..50fff4812 100644 --- a/libcockatrice_network/libcockatrice/network/server/remote/game/server_game.cpp +++ b/libcockatrice_network/libcockatrice/network/server/remote/game/server_game.cpp @@ -334,7 +334,7 @@ void Server_Game::doStartGameIfReady(bool forceStartGame) if (!player->getReadyStart()) { if (forceStartGame) { // Player is not ready to start, so kick them - // TODO: Move them to Spectators instead + //! \todo Move them to Spectators instead. kickParticipant(player->getPlayerId()); } else { return; @@ -517,7 +517,7 @@ void Server_Game::addPlayer(Server_AbstractUserInterface *userInterface, allPlayersEver.insert(playerName); // if the original creator of the game joins, give them host status back - //! \todo transferring host to spectators has side effects + //! \todo Transferring host to spectators has side effects. if (newParticipant->getUserInfo()->name() == creatorInfo->name()) { hostId = newParticipant->getPlayerId(); sendGameEventContainer(prepareGameEvent(Event_GameHostChanged(), hostId)); diff --git a/libcockatrice_network/libcockatrice/network/server/remote/server.cpp b/libcockatrice_network/libcockatrice/network/server/remote/server.cpp index 904637797..3da9ddc73 100644 --- a/libcockatrice_network/libcockatrice/network/server/remote/server.cpp +++ b/libcockatrice_network/libcockatrice/network/server/remote/server.cpp @@ -286,7 +286,7 @@ QList Server::getOnlineModeratorList() const for (auto &client : clients) { ServerInfo_User *data = client->getUserInfo(); - // TODO: this line should be updated in the event there is any type of new user level created + //! \todo This line should be updated in the event there is any type of new user level created. if (data && (data->user_level() & ServerInfo_User::IsModerator || data->user_level() & ServerInfo_User::IsAdmin)) { results << QString::fromStdString(data->name()).simplified(); diff --git a/libcockatrice_protocol/libcockatrice/protocol/pending_command.h b/libcockatrice_protocol/libcockatrice/protocol/pending_command.h index 1d2d9ff17..dbe57e7fc 100644 --- a/libcockatrice_protocol/libcockatrice/protocol/pending_command.h +++ b/libcockatrice_protocol/libcockatrice/protocol/pending_command.h @@ -1,8 +1,8 @@ /** * @file pending_command.h * @ingroup Messages - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef PENDING_COMMAND_H #define PENDING_COMMAND_H diff --git a/libcockatrice_settings/libcockatrice/settings/card_database_settings.h b/libcockatrice_settings/libcockatrice/settings/card_database_settings.h index 5dea1b552..97efb5753 100644 --- a/libcockatrice_settings/libcockatrice/settings/card_database_settings.h +++ b/libcockatrice_settings/libcockatrice/settings/card_database_settings.h @@ -2,8 +2,8 @@ * @file card_database_settings.h * @ingroup CardDatabase * @ingroup CardSettings - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef CARDDATABASESETTINGS_H #define CARDDATABASESETTINGS_H diff --git a/libcockatrice_settings/libcockatrice/settings/card_override_settings.h b/libcockatrice_settings/libcockatrice/settings/card_override_settings.h index 3d9db4e65..cd515d4da 100644 --- a/libcockatrice_settings/libcockatrice/settings/card_override_settings.h +++ b/libcockatrice_settings/libcockatrice/settings/card_override_settings.h @@ -1,8 +1,8 @@ /** * @file card_override_settings.h * @ingroup CardSettings - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef COCKATRICE_CARD_OVERRIDE_SETTINGS_H #define COCKATRICE_CARD_OVERRIDE_SETTINGS_H diff --git a/libcockatrice_settings/libcockatrice/settings/debug_settings.h b/libcockatrice_settings/libcockatrice/settings/debug_settings.h index 30cdd5fa5..acb5cf313 100644 --- a/libcockatrice_settings/libcockatrice/settings/debug_settings.h +++ b/libcockatrice_settings/libcockatrice/settings/debug_settings.h @@ -1,8 +1,8 @@ /** * @file debug_settings.h * @ingroup CoreSettings - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef DEBUG_SETTINGS_H #define DEBUG_SETTINGS_H diff --git a/libcockatrice_settings/libcockatrice/settings/download_settings.h b/libcockatrice_settings/libcockatrice/settings/download_settings.h index b7442301e..60e59220b 100644 --- a/libcockatrice_settings/libcockatrice/settings/download_settings.h +++ b/libcockatrice_settings/libcockatrice/settings/download_settings.h @@ -1,8 +1,8 @@ /** * @file download_settings.h * @ingroup NetworkSettings - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef COCKATRICE_DOWNLOADSETTINGS_H #define COCKATRICE_DOWNLOADSETTINGS_H diff --git a/libcockatrice_settings/libcockatrice/settings/game_filters_settings.h b/libcockatrice_settings/libcockatrice/settings/game_filters_settings.h index c0e60551a..24f582007 100644 --- a/libcockatrice_settings/libcockatrice/settings/game_filters_settings.h +++ b/libcockatrice_settings/libcockatrice/settings/game_filters_settings.h @@ -2,8 +2,8 @@ * @file game_filters_settings.h * @ingroup Lobby * @ingroup GameSettings - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef GAMEFILTERSSETTINGS_H #define GAMEFILTERSSETTINGS_H diff --git a/libcockatrice_settings/libcockatrice/settings/layouts_settings.h b/libcockatrice_settings/libcockatrice/settings/layouts_settings.h index 5353ce15a..d5f26b61b 100644 --- a/libcockatrice_settings/libcockatrice/settings/layouts_settings.h +++ b/libcockatrice_settings/libcockatrice/settings/layouts_settings.h @@ -1,8 +1,8 @@ /** * @file layouts_settings.h * @ingroup CoreSettings - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef LAYOUTSSETTINGS_H #define LAYOUTSSETTINGS_H diff --git a/libcockatrice_settings/libcockatrice/settings/message_settings.h b/libcockatrice_settings/libcockatrice/settings/message_settings.h index ec70027af..8276aa39d 100644 --- a/libcockatrice_settings/libcockatrice/settings/message_settings.h +++ b/libcockatrice_settings/libcockatrice/settings/message_settings.h @@ -1,8 +1,8 @@ /** * @file message_settings.h * @ingroup NetworkSettings - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef MESSAGESETTINGS_H #define MESSAGESETTINGS_H diff --git a/libcockatrice_settings/libcockatrice/settings/recents_settings.h b/libcockatrice_settings/libcockatrice/settings/recents_settings.h index 3aebff334..01b2a37bc 100644 --- a/libcockatrice_settings/libcockatrice/settings/recents_settings.h +++ b/libcockatrice_settings/libcockatrice/settings/recents_settings.h @@ -1,8 +1,8 @@ /** * @file recents_settings.h * @ingroup DeckSettings - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef RECENTS_SETTINGS_H #define RECENTS_SETTINGS_H diff --git a/libcockatrice_settings/libcockatrice/settings/servers_settings.h b/libcockatrice_settings/libcockatrice/settings/servers_settings.h index 22603a356..40fa996fb 100644 --- a/libcockatrice_settings/libcockatrice/settings/servers_settings.h +++ b/libcockatrice_settings/libcockatrice/settings/servers_settings.h @@ -1,8 +1,8 @@ /** * @file servers_settings.h * @ingroup NetworkSettings - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef SERVERSSETTINGS_H #define SERVERSSETTINGS_H diff --git a/libcockatrice_settings/libcockatrice/settings/settings_manager.h b/libcockatrice_settings/libcockatrice/settings/settings_manager.h index a02bafcac..4213cf4c1 100644 --- a/libcockatrice_settings/libcockatrice/settings/settings_manager.h +++ b/libcockatrice_settings/libcockatrice/settings/settings_manager.h @@ -1,8 +1,8 @@ /** * @file settings_manager.h * @ingroup Settings - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef SETTINGSMANAGER_H #define SETTINGSMANAGER_H diff --git a/libcockatrice_utility/libcockatrice/utility/levenshtein.h b/libcockatrice_utility/libcockatrice/utility/levenshtein.h index e83235470..3da730e53 100644 --- a/libcockatrice_utility/libcockatrice/utility/levenshtein.h +++ b/libcockatrice_utility/libcockatrice/utility/levenshtein.h @@ -1,8 +1,8 @@ /** * @file levenshtein.h * @ingroup Core - * @brief TODO: Document this. */ +//! \todo Document this file. #ifndef LEVENSHTEIN_H #define LEVENSHTEIN_H diff --git a/servatrice/src/serversocketinterface.cpp b/servatrice/src/serversocketinterface.cpp index 5549074c5..bc90a3ef1 100644 --- a/servatrice/src/serversocketinterface.cpp +++ b/servatrice/src/serversocketinterface.cpp @@ -1286,7 +1286,7 @@ Response::ResponseCode AbstractServerSocketInterface::cmdRegisterAccount(const C return Response::RespEmailBlackListed; } - //! \todo Move this method outside of the db interface + //! \todo Move this method outside of the db interface. QString errorString; if (!sqlInterface->usernameIsValid(userName, errorString)) { if (servatrice->getEnableRegistrationAudit()) { @@ -1421,7 +1421,7 @@ Response::ResponseCode AbstractServerSocketInterface::cmdRegisterAccount(const C bool AbstractServerSocketInterface::tooManyRegistrationAttempts(const QString &ipAddress) { - //! \todo implement + //! \todo Implement registration attempt limiting. Q_UNUSED(ipAddress); return false; } From 6faa0d54e321481c410eb0112fbdcbb7e74fb4d3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 21 May 2026 19:14:58 -0400 Subject: [PATCH 34/51] Update translation files (#6920) Co-authored-by: github-actions --- cockatrice/translations/cockatrice_it.ts | 117 ++++++++------ cockatrice/translations/cockatrice_pt_BR.ts | 163 ++++++++++---------- cockatrice/translations/cockatrice_yue.ts | 104 ++++++------- 3 files changed, 200 insertions(+), 184 deletions(-) diff --git a/cockatrice/translations/cockatrice_it.ts b/cockatrice/translations/cockatrice_it.ts index 8356063d6..3990d532f 100644 --- a/cockatrice/translations/cockatrice_it.ts +++ b/cockatrice/translations/cockatrice_it.ts @@ -180,7 +180,7 @@ Controlla se la cartella è valida e prova ancora. Display card name of background in bottom right: - + Mostra nome della carta di sfondo in basso a destra @@ -4513,12 +4513,12 @@ Dovrai scaricare la nuova versione manualmente. &Top of library... - &In cima al grimorio... + &Dalla cima del grimorio... &Bottom of library... - &In fondo al grimorio... + &Dal fondo del grimorio... @@ -6438,7 +6438,7 @@ Il database delle carte verrà ricaricato. &Top of library in random order - &In cima al grimorio in ordine casuale + &Cima al grimorio in ordine casuale @@ -6448,7 +6448,7 @@ Il database delle carte verrà ricaricato. &Bottom of library in random order - In &fondo al grimorio in ordine casuale + &Fondo al grimorio in ordine casuale @@ -6833,12 +6833,15 @@ Il database delle carte verrà ricaricato. This setting means you'll only see the default printing for each card, instead of being able to select a printing, and will not see the printings other people have selected. - + Il selettore di stampa è disabilitato perchè hai abilitato la funzionalità di sovrascrivere le stampe selezionate con le preferenze personali per set. + +Questo significa che vedrai solo la stampa predefinita per ciascuna scarta anzichè poterle selezionare e che non vedrai le stampe scelte da altri utenti. + Enable printings again - + Abilita il selettore di stampa @@ -6851,7 +6854,7 @@ This setting means you'll only see the default printing for each card, instead o Printing Selector - + Selettore di stampa @@ -6937,7 +6940,7 @@ This setting means you'll only see the default printing for each card, instead o Select a card to view its available printings - + Seleziona una carta per vedere le stampe disponibili. @@ -7087,7 +7090,13 @@ You will not be able to manage printing preferences on a per-deck basis, or see You will have to use the Set Manager, available through Card Database -> Manage Sets. Are you sure you would like to enable this feature? - + Abilitare questa funzione disattiverà il Selettore di stampa. + +Non potrai gestire le preferenze delle stampe per i singoli mazzi, o vedere le stampe scelte dagli altri giocatori per i loro mazzi. + +Dovrai usare il Gestore dei set, raggiungibile tramite Database carte -> Organizza set. + +Sicuro di voler abilitare questa funzione? @@ -7098,12 +7107,18 @@ You can now choose printings on a per-deck basis in the Deck Editor and configur You can also use the Set Manager to adjust custom sort order for printings in the Printing Selector (other sort orders like alphabetical or release date are available). Are you sure you would like to disable this feature? - + Disabilitare questa funzione attiverà il Selettore di stampa. + +Potrai gestire le preferenze delle stampe per i singoli mazzi nell'Editor, e configurare quale stampa viene aggiunta di default a un mazzo fissandola nel selettore. + +Potrai anche usare il Gestore dei set per personalizzare l'ordine delle stampe nel Selettore (sono disponibili anche ordinamenti predefiniti come alfabetico o per data di uscita). + +Sicuro di voler disabilitare questa funzione? Confirm Change - + Conferma modifica @@ -7331,7 +7346,7 @@ Are you sure you would like to disable this feature? S&ay - + Invi&a @@ -7753,104 +7768,104 @@ Controlla le impostazioni! Desc. - Decrescente + Decresc. AND - + AND Require ALL selected colors - + Richiede TUTTI i colori selezionati Deck name... - + Nome mazzo... Owner... - + Proprietario... Packages - + Package Advanced Filters - + Filtri avanzati Bracket: - + Fascia: Any - + Qualsiasi Contains card... - + Contiene carta... Commander... - + Comandante... Tag... - + Tag... Deck Size - + Dimensione mazzo Cards: - + Carte: Asc. - Crescente + Cresc. Sort by: - + Ordina per: Filter by: - + Filtra per: Display Settings - + Impostazioni di visualizzazione @@ -9532,12 +9547,12 @@ Se pregato di evitare di continuare questa attività o potrebbero venire presi u Show selection counter during drag selection - + Mostra un contatore quando selezioni per trascinamento Show total selection counter - + Mostra un contatore di elementi selezionati @@ -9701,23 +9716,23 @@ Se pregato di evitare di continuare questa attività o potrebbero venire presi u Exact match - + Corrispondenza esatta Includes - + Include Include / Exclude Mode: Includes - + Include / Esclude How selected and unselected colors are combined in the filter - + Come vengono combinati colori selezionati e non selezionati nel filtro @@ -9748,12 +9763,12 @@ Se pregato di evitare di continuare questa attività o potrebbero venire presi u Sort by - + Ordina per Filter by - + Filtra per @@ -9783,12 +9798,12 @@ Se pregato di evitare di continuare questa attività o potrebbero venire presi u Filter by format legality - + Filtra per legalità di formato Save/Load - + Salva/Carica @@ -9821,7 +9836,7 @@ Se pregato di evitare di continuare questa attività o potrebbero venire presi u Show formats with at least: - + Mostra formati con almeno: @@ -9854,7 +9869,7 @@ Se pregato di evitare di continuare questa attività o potrebbero venire presi u Show main types with at least: - + Mostra tipi con almeno: @@ -9948,7 +9963,7 @@ Se pregato di evitare di continuare questa attività o potrebbero venire presi u Show sub types with at least: - + Mostra sottotipi con almeno: @@ -10111,7 +10126,7 @@ Se pregato di evitare di continuare questa attività o potrebbero venire presi u Show Color Identity - + Mostra identità di colore @@ -11135,7 +11150,7 @@ Se pregato di evitare di continuare questa attività o potrebbero venire presi u Toggle Skip Untapping Toggle Untap - + Salta lo STAP @@ -11155,7 +11170,7 @@ Se pregato di evitare di continuare questa attività o potrebbero venire presi u Play Card, Face Down - + Gioca la carta a faccia in giù @@ -11293,25 +11308,25 @@ Se pregato di evitare di continuare questa attività o potrebbero venire presi u Graveyard (Multiple) - Cimitero (multiplo) + Cimitero (Multiple) Graveyard (Multiple), Face Down - + Cimitero (Multiple), a faccia in giù Exile (Multiple) - Esilia (multiplo) + Esilia (Multiple) Exile (Multiple), Face Down - + Esilio (Multiple), a faccia in giù diff --git a/cockatrice/translations/cockatrice_pt_BR.ts b/cockatrice/translations/cockatrice_pt_BR.ts index 2c331260f..9956c1793 100644 --- a/cockatrice/translations/cockatrice_pt_BR.ts +++ b/cockatrice/translations/cockatrice_pt_BR.ts @@ -1085,7 +1085,7 @@ Isto será visto somente por moderadores e não pode ser visto pela pessoa banid Colors - + Cores @@ -1125,12 +1125,12 @@ Isto será visto somente por moderadores e não pode ser visto pela pessoa banid Group by: - + Agrupar por: Format: - + Formato: @@ -1258,7 +1258,7 @@ Isto será visto somente por moderadores e não pode ser visto pela pessoa banid Load deck from online service... - + Carregar baralho de serviço online... @@ -1471,17 +1471,17 @@ Isto será visto somente por moderadores e não pode ser visto pela pessoa banid Undo - + Desfazer Redo - + Refazer Undo/Redo history - + Histórico Desfazer/Refazer @@ -1491,12 +1491,12 @@ Isto será visto somente por moderadores e não pode ser visto pela pessoa banid [redo] - + [refazer] [undo] - + [desfazer] @@ -1601,7 +1601,7 @@ Isto será visto somente por moderadores e não pode ser visto pela pessoa banid Edit default tags - + Editar tags padrão @@ -1729,12 +1729,12 @@ Isto será visto somente por moderadores e não pode ser visto pela pessoa banid Rename deck to "%1" from "%2" - + Renomear baralho de "%1" para "%2" Updated comments (was %1 chars, now %2 chars) - + Comentários atualizados (eram %1 caracteres, agora são %2 caracteres) @@ -1744,42 +1744,42 @@ Isto será visto somente por moderadores e não pode ser visto pela pessoa banid Tags changed - + Tags alteradas Set format to %1 - + Definir formato para %1 Added (%1): %2 (%3) %4 - + Adicionado (%1): %2 (%3) %4 Moved to %1 1 × "%2" (%3) - + Movido para %1 1 × "%2" (%3) Removed "%1" (all copies) - + Removido "%1" (todas as cópias) %1 1 × "%2" (%3) - + %1 1 × "%2" (%3) Added - + Adicionado Removed - + Removido @@ -1811,12 +1811,12 @@ Isto será visto somente por moderadores e não pode ser visto pela pessoa banid Load from clipboard... - + Carregado da área de transferência... Load from website... - + Carregado do website... @@ -1857,13 +1857,14 @@ Isto será visto somente por moderadores e não pode ser visto pela pessoa banid Deck is greater than maximum file size. - + O baralho é maior que o tamanho máximo de arquivo. Are you sure you want to force start? This will kick all non-ready players from the game. - + Tem certeza que deseja forçar o início? +Isso irá expulsar todos os jogadores não preparados do jogo. @@ -2127,12 +2128,12 @@ Deseja converter o deck para .cod? Open decklists in lobby - + Abrir lista de baralhos no lobby Create game as judge - + Criar jogo como juíz @@ -2268,53 +2269,53 @@ Deseja converter o deck para .cod? Edit Tags - + Editar Tags Add - + Adicionar Confirm - + Confirmar Cancel - + Cancelar Enter a tag and press Enter - + Insira a tag e aperte Enter ✖ - + Invalid Input - + Valor Inválido Tag name cannot be empty! - + Nomes de tags não podem ser vazios! Duplicate Tag - + Tag Duplicada This tag already exists. - + Essa tag já existe. @@ -2600,7 +2601,7 @@ Certifique-se de habilitar a expansão 'Fichas' em "Gerenciar exp Hide games not created by buddies Hide games not created by buddy - + Esconder jogos não criados por amigos @@ -2902,7 +2903,7 @@ Certifique-se de habilitar a expansão 'Fichas' em "Gerenciar exp Load Deck from Website - + Carregar Baralho de Website @@ -2913,7 +2914,7 @@ Certifique-se de habilitar a expansão 'Fichas' em "Gerenciar exp Network error: %1 - + Erro de rede: %1 @@ -2950,17 +2951,17 @@ https://tappedout.net/mtg-decks/your-deck-name/ Players: - + Jogadores: General - + Geral Starting life total: - + Vida inicial total: @@ -2970,12 +2971,12 @@ https://tappedout.net/mtg-decks/your-deck-name/ Remember settings - + Lembrar configurações Local game options - + Opções de jogo local @@ -3132,12 +3133,12 @@ Seu e-mail será utilizado para verificar sua conta. Unmodified Cards: - + Cartas não modificadas: Modified Cards: - + Cartas Modificadas: @@ -3318,7 +3319,7 @@ Você gostaria de alterar seu local de configuração do banco de dados? Card Update Check - + Checar Atualização de Carta @@ -3350,7 +3351,7 @@ You can always change this behavior in the 'General' settings tab. Don't run this time - + Não executar desta vez @@ -3547,7 +3548,7 @@ Talvez você tenha que baixar a nova versão manualmente. Copy to clipboard - + Copiar para área de transferência @@ -3565,58 +3566,58 @@ Talvez você tenha que baixar a nova versão manualmente. Criteria: - + Critério: Card Name - + Nome da Carta Type - + Tipo Subtype - + Subtipo Mana Value - + Valor de mana Exactness: - + Exatidão At least - + Pelo menos Exactly - + Exatamente Quantity (N): - + Quantidade (N): Cards drawn (M): - + Cartas compradas (M): cards - + cartas @@ -3624,7 +3625,7 @@ Talvez você tenha que baixar a nova versão manualmente. Draw Probability - + Probabilidade de compra @@ -3634,32 +3635,32 @@ Talvez você tenha que baixar a nova versão manualmente. Card Name - + Nome da Carta Type - + Tipo Subtype - + Subtipo Mana Value - + Valor de Mana At least - + Pelo menos Exactly - + Exatamente @@ -3669,22 +3670,22 @@ Talvez você tenha que baixar a nova versão manualmente. cards - + cartas Category - + Categoria Qty - + Qtd Odds (%) - + Chances (%) @@ -3715,7 +3716,7 @@ Talvez você tenha que baixar a nova versão manualmente. Card Market - + Mercado de Cartas @@ -3769,7 +3770,7 @@ Talvez você tenha que baixar a nova versão manualmente. Budget - + Orçamento @@ -3777,7 +3778,7 @@ Talvez você tenha que baixar a nova versão manualmente. Combos - + Combos @@ -3806,7 +3807,7 @@ Talvez você tenha que baixar a nova versão manualmente. Confirm Delete - + Confirmar Exclusão @@ -3816,12 +3817,12 @@ Talvez você tenha que baixar a nova versão manualmente. Delete Failed - + Falha na Exclusão Failed to delete filter '%1'. - + Falha ao remover filtro '%1'. @@ -3834,17 +3835,17 @@ Talvez você tenha que baixar a nova versão manualmente. player left the game - + jogador saiu do jogo player disconnected from server - + jogador desconectado do servidor reason unknown - + motivo desconhecido @@ -3920,7 +3921,7 @@ Talvez você tenha que baixar a nova versão manualmente. Join Game as Judge - + Entrar no Jogo como Juíz diff --git a/cockatrice/translations/cockatrice_yue.ts b/cockatrice/translations/cockatrice_yue.ts index 1f206c1eb..e3c73b94a 100644 --- a/cockatrice/translations/cockatrice_yue.ts +++ b/cockatrice/translations/cockatrice_yue.ts @@ -25,12 +25,12 @@ &Refresh - + &刷新 Parse Set Name and Number (if available) - + 解析組名及編號(如果有) @@ -43,7 +43,7 @@ Are you sure? - + 你確定嗎? @@ -59,7 +59,7 @@ Do you want to save the changes? Error - + 出錯 @@ -254,12 +254,12 @@ Please check that the directory is writable and try again. Card counters - + 牌指示物 Counter %1 - + 指示物 %1 @@ -302,12 +302,12 @@ Please check that the directory is writable and try again. Back to results - + 返去結果 Open Deck in Deck Editor - + 在套牌編輯&打開牌庫檔案 @@ -315,7 +315,7 @@ Please check that the directory is writable and try again. Theme - + 卡牌主题 @@ -531,7 +531,7 @@ This is only saved for moderators and cannot be seen by the banned person. Name (Exact) - + 名稱(確切) @@ -591,12 +591,12 @@ This is only saved for moderators and cannot be seen by the banned person. Main Type - + 主要類型 Sub Type - + 副類型 @@ -619,7 +619,7 @@ This is only saved for moderators and cannot be seen by the banned person. View transformation - + 查看轉化 @@ -632,17 +632,17 @@ This is only saved for moderators and cannot be seen by the banned person. Add card to deck - + 添加卡牌到牌庫 Mainboard - + 主牌庫 Sideboard - + 副牌庫 @@ -655,12 +655,12 @@ This is only saved for moderators and cannot be seen by the banned person. Set: - + 牌組: Collector Number: - + 收藏號碼: @@ -678,63 +678,63 @@ This is only saved for moderators and cannot be seen by the banned person. Re&veal to... - + &展示给... &All players - + &所有玩家 View related cards - + 查看關聯卡牌 Token: - + 令牌: All tokens - + 所有令牌 &Select All - + &全選 S&elect Row - + &選擇橫行 S&elect Column - + &選擇直行 &Play - + &使出 &Hide - + &隱藏 Play &Face Down - + &面朝下使出 &Tap / Untap Turn sideways or back again - + &横置/重置 @@ -812,133 +812,133 @@ This is only saved for moderators and cannot be seen by the banned person. their hand nominative - + 它們的手牌 %1's hand nominative - + %1的手牌 their library look at zone - + 它們的牌庫 %1's library look at zone - + %1的牌庫 of their library top cards of zone, - + 它們的牌庫中 of %1's library top cards of zone - + %1的牌庫中 their library reveal zone - + 它們的牌庫 %1's library reveal zone - + %1的牌庫 their library shuffle - + 它們的牌庫 %1's library shuffle - + %1的牌庫 their library nominative - + 它們的牌庫 %1's library nominative - + %1的牌庫 their graveyard nominative - + 它們的墳場 %1's graveyard nominative - + %1的的墳場 their exile nominative - + 它們的放逐區 %1's exile nominative - + %1的放逐區 their sideboard look at zone - + 它們的備牌 %1's sideboard look at zone - + %1的備牌 their sideboard nominative - + 它們的備牌 %1's sideboard nominative - + %1的備牌 their custom zone '%1' nominative - + 它們的自定區域 '%1' %1's custom zone '%2' nominative - + %1的自定區域'%2' From a9003be30f163334407030992645cc7d61a0b560 Mon Sep 17 00:00:00 2001 From: ebbit1q Date: Fri, 22 May 2026 01:35:01 +0200 Subject: [PATCH 35/51] update version to 3.1.0 for subsequent beta releases (#6921) --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 14137ac55..c10e1db68 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -74,7 +74,7 @@ endif() # A project name is needed for CPack # Version can be overriden by git tags, see cmake/getversion.cmake -project("Cockatrice" VERSION 3.0.1) +project("Cockatrice" VERSION 3.1.0) # Set release name if not provided via env/cmake var if(NOT DEFINED GIT_TAG_RELEASENAME) From 74102aa1ec05381b96fadedeb05a18891b852658 Mon Sep 17 00:00:00 2001 From: tooomm Date: Fri, 22 May 2026 03:31:59 +0200 Subject: [PATCH 36/51] Update external c libs: SFMT & peglib (#6901) --- .../libcockatrice/rng/sfmt/SFMT.c | 4 +- .../libcockatrice/rng/sfmt/SFMT.h | 21 +++++- .../libcockatrice/utility/peglib.h | 73 +++++++++++++++---- 3 files changed, 80 insertions(+), 18 deletions(-) diff --git a/libcockatrice_rng/libcockatrice/rng/sfmt/SFMT.c b/libcockatrice_rng/libcockatrice/rng/sfmt/SFMT.c index b4ac9308b..fde6367a0 100644 --- a/libcockatrice_rng/libcockatrice/rng/sfmt/SFMT.c +++ b/libcockatrice_rng/libcockatrice/rng/sfmt/SFMT.c @@ -60,7 +60,9 @@ inline static void swap(w128_t *array, int size); */ static const w128_t sse2_param_mask = {{SFMT_MSK1, SFMT_MSK2, SFMT_MSK3, SFMT_MSK4}}; - #if defined(_MSC_VER) + #if defined(__AVX2__) && (SFMT_SL1 >= 16) && !(SFMT_N & 1) && !(SFMT_POS1 & 1) + #include "SFMT-avx256.h" + #elif defined(_MSC_VER) #include "SFMT-sse2-msc.h" #else #include "SFMT-sse2.h" diff --git a/libcockatrice_rng/libcockatrice/rng/sfmt/SFMT.h b/libcockatrice_rng/libcockatrice/rng/sfmt/SFMT.h index 79e012d63..34d9e746f 100644 --- a/libcockatrice_rng/libcockatrice/rng/sfmt/SFMT.h +++ b/libcockatrice_rng/libcockatrice/rng/sfmt/SFMT.h @@ -88,8 +88,13 @@ union W128_T { uint64_t u64[2]; uint32x4_t si; }; +//#elif defined(HAVE_SSE2) #elif defined(HAVE_SSE2) - #include + #if defined(__AVX2__) + #include + #else + #include + #endif /** 128-bit data structure */ union W128_T { @@ -112,8 +117,18 @@ typedef union W128_T w128_t; * SFMT internal state */ struct SFMT_T { +#if defined(__AVX2__) + union { + w128_t state[SFMT_N]; + __m256i state_ymm[SFMT_N/2]; + #if defined(__AVX512VL__) + __m512i state_zmm[SFMT_N/4]; + #endif + }; +#else /** the 128-bit internal state array */ w128_t state[SFMT_N]; +#endif /** index counter to the 32-bit internal state array */ int idx; }; @@ -249,9 +264,9 @@ inline static double sfmt_genrand_real3(sfmt_t * sfmt) } /** - * converts an unsigned 32-bit integer to double on [0,1) + * converts an unsigned 64-bit integer to double on [0,1) * with 53-bit resolution. - * @param v 32-bit unsigned integer + * @param v 64-bit unsigned integer * @return double on [0,1)-real-interval with 53-bit resolution. */ inline static double sfmt_to_res53(uint64_t v) diff --git a/libcockatrice_utility/libcockatrice/utility/peglib.h b/libcockatrice_utility/libcockatrice/utility/peglib.h index 3ae6040c4..e7e558dff 100644 --- a/libcockatrice_utility/libcockatrice/utility/peglib.h +++ b/libcockatrice_utility/libcockatrice/utility/peglib.h @@ -37,6 +37,7 @@ #include #include #include +#include #include #if !defined(__cplusplus) || __cplusplus < 201703L @@ -505,7 +506,7 @@ inline constexpr unsigned int str2tag(std::string_view sv) { namespace udl { -inline constexpr unsigned int operator""_(const char *s, size_t l) { +inline constexpr unsigned int operator"" _(const char *s, size_t l) { return str2tag_core(s, l, 0); } @@ -2434,10 +2435,11 @@ struct ComputeFirstSet : public TraversalVisitor { void visit(Sequence &ope) override { for (const auto &op : ope.opes_) { + FirstSet element_fs; auto save = result_; result_ = FirstSet{}; op->accept(*this); - auto element_fs = result_; + element_fs = result_; result_ = save; result_.chars |= element_fs.chars; if (element_fs.any_char) { result_.any_char = true; } @@ -2526,10 +2528,22 @@ struct ComputeFirstSet : public TraversalVisitor { void visit(BackReference &) override { result_.any_char = true; } void visit(Cut &) override { result_.can_be_empty = true; } + // Per-rule cache shared across a SetupFirstSets traversal. Without it, + // every alternative of every PrioritizedChoice re-walks referenced + // rules — O(refs^depth) work for grammars with many cross-references. + // Only cycle-free rule computations are cached; results computed under + // a cycle (left recursion) would be incomplete and unsafe to reuse from + // a different call context. + using FirstSetCache = std::unordered_map; + + explicit ComputeFirstSet(FirstSetCache &cache) : cache_(cache) {} + FirstSet result_; private: - std::unordered_set refs_; + FirstSetCache &cache_; + std::unordered_set refs_; + size_t cycle_count_ = 0; }; struct SetupFirstSets : public TraversalVisitor { @@ -2542,7 +2556,7 @@ struct SetupFirstSets : public TraversalVisitor { ope.first_sets_.clear(); ope.first_sets_.reserve(ope.opes_.size()); for (const auto &op : ope.opes_) { - ComputeFirstSet cfs; + ComputeFirstSet cfs(first_set_cache_); op->accept(cfs); ope.first_sets_.push_back(cfs.result_); } @@ -2559,7 +2573,8 @@ struct SetupFirstSets : public TraversalVisitor { void visit(Reference &ope) override; private: - std::unordered_set refs_; + ComputeFirstSet::FirstSetCache first_set_cache_; + std::unordered_set visited_rules_; }; /* @@ -3806,20 +3821,50 @@ inline void ComputeFirstSet::visit(Reference &ope) { result_.any_char = true; return; } - if (refs_.count(ope.name_)) { return; } - refs_.insert(ope.name_); - ope.rule_->accept(*this); - if (!result_.first_rule && ope.rule_->is_token()) { - result_.first_rule = ope.rule_; + + auto it = cache_.find(ope.rule_); + FirstSet computed; + const FirstSet *rule_fs; + if (it != cache_.end()) { + rule_fs = &it->second; + } else { + if (!refs_.insert(ope.rule_).second) { + cycle_count_++; // cycle / left recursion + return; + } + auto save = std::exchange(result_, FirstSet{}); + auto saved_cycle_count = cycle_count_; + ope.rule_->accept(*this); + computed = std::move(result_); + result_ = std::move(save); + refs_.erase(ope.rule_); + if (cycle_count_ == saved_cycle_count) { + // Cycle-free: cached value is complete and safe to reuse. + it = cache_.try_emplace(ope.rule_, std::move(computed)).first; + rule_fs = &it->second; + } else { + // Cycle was hit during this rule's computation — its result may be + // missing contributions from rules that were on the call stack. + // Use the value here but do not cache it for other call contexts. + rule_fs = &computed; + } + } + + result_.merge(*rule_fs); + if (!result_.first_literal) { + result_.first_literal = rule_fs->first_literal; + } + if (!result_.first_rule) { + result_.first_rule = rule_fs->first_rule + ? rule_fs->first_rule + : (ope.rule_->is_token() ? ope.rule_ : nullptr); } - refs_.erase(ope.name_); } inline void SetupFirstSets::visit(Reference &ope) { - if (!ope.rule_ || refs_.count(ope.name_)) { return; } - refs_.insert(ope.name_); + if (!ope.rule_) { return; } + if (!visited_rules_.insert(ope.rule_).second) { return; } ope.rule_->accept(*this); - refs_.erase(ope.name_); } inline void SetupFirstSets::visit(Sequence &ope) { From 8dca14933c24e91c9328c1df2cc7566dc8c8d2ea Mon Sep 17 00:00:00 2001 From: DawnFire42 Date: Thu, 21 May 2026 23:39:35 -0400 Subject: [PATCH 37/51] Centralize counter API with server-side bounds and no-op filtering (#6879) * Refactor server counter API to own overflow protection and filter no-op events Counter modifications now clamp to int bounds server-side and return change status, allowing command handlers to skip network broadcasts when values don't actually change. * Centralize MAX_COUNTERS_ON_CARD and enforce [0, 999] bounds on server - Move MAX_COUNTERS_ON_CARD to trice_limits.h - Server clamps values in setCounter() and incrementCounter() - Client uses clamped comparison to allow recovery from invalid states - Add tests for clamping behavior * move incrementCount() implementation from header to cpp --- cockatrice/src/game/board/card_item.h | 2 +- cockatrice/src/game/player/player_actions.cpp | 9 +- .../remote/game/server_abstract_player.cpp | 20 +- .../server/remote/game/server_card.cpp | 40 +++- .../network/server/remote/game/server_card.h | 19 +- .../server/remote/game/server_counter.cpp | 12 ++ .../server/remote/game/server_counter.h | 36 +++- .../server/remote/game/server_player.cpp | 39 ++-- .../libcockatrice/utility/trice_limits.h | 6 + tests/CMakeLists.txt | 12 ++ tests/server_card_counter_test.cpp | 183 ++++++++++++++++++ tests/server_counter_test.cpp | 86 ++++++++ 12 files changed, 432 insertions(+), 32 deletions(-) create mode 100644 tests/server_card_counter_test.cpp create mode 100644 tests/server_counter_test.cpp diff --git a/cockatrice/src/game/board/card_item.h b/cockatrice/src/game/board/card_item.h index 408bb03a7..451fed0c6 100644 --- a/cockatrice/src/game/board/card_item.h +++ b/cockatrice/src/game/board/card_item.h @@ -12,6 +12,7 @@ #include "card_state.h" #include +#include class CardDatabase; class CardDragItem; @@ -21,7 +22,6 @@ class PlayerLogic; class QAction; class QColor; -const int MAX_COUNTERS_ON_CARD = 999; const int ROTATION_DEGREES_PER_FRAME = 10; class CardItem : public AbstractCardItem diff --git a/cockatrice/src/game/player/player_actions.cpp b/cockatrice/src/game/player/player_actions.cpp index 341769899..c2b9140af 100644 --- a/cockatrice/src/game/player/player_actions.cpp +++ b/cockatrice/src/game/player/player_actions.cpp @@ -1501,7 +1501,10 @@ void PlayerActions::offsetCardCounter(int counterId, int offset) int oldValue = card->getCounters().value(counterId, 0); int newValue = oldValue + offset; - if (newValue >= 0 && newValue <= MAX_COUNTERS_ON_CARD) { + // Early exit optimization: server enforces [0, MAX_COUNTERS_ON_CARD]. + // Compare clamped value to allow recovery from invalid states. + int clampedValue = qBound(0, newValue, MAX_COUNTERS_ON_CARD); + if (clampedValue != oldValue) { auto *cmd = new Command_SetCardCounter; cmd->set_zone(card->getZone()->getName().toStdString()); cmd->set_card_id(card->getId()); @@ -1541,7 +1544,9 @@ void PlayerActions::actSetCardCounter(int counterId) for (auto card : sel) { int oldValue = card->getCounters().value(counterId, 0); Expression exp(oldValue); - int number = static_cast(exp.parse(dialog.textValue())); + double parsed = exp.parse(dialog.textValue()); + // Clamp in double precision first to avoid UB, then cast + int number = static_cast(qBound(0.0, parsed, static_cast(MAX_COUNTERS_ON_CARD))); auto *cmd = new Command_SetCardCounter; cmd->set_zone(card->getZone()->getName().toStdString()); diff --git a/libcockatrice_network/libcockatrice/network/server/remote/game/server_abstract_player.cpp b/libcockatrice_network/libcockatrice/network/server/remote/game/server_abstract_player.cpp index 36ab75675..100a4ebc6 100644 --- a/libcockatrice_network/libcockatrice/network/server/remote/game/server_abstract_player.cpp +++ b/libcockatrice_network/libcockatrice/network/server/remote/game/server_abstract_player.cpp @@ -49,6 +49,7 @@ #include #include #include +#include #include Server_AbstractPlayer::Server_AbstractPlayer(Server_Game *_game, @@ -1091,8 +1092,9 @@ Server_AbstractPlayer::cmdCreateToken(const Command_CreateToken &cmd, ResponseCo _event.set_zone_name(card->getZone()->getName().toStdString()); _event.set_card_id(card->getId()); - card->setCounter(i.key(), i.value(), &_event); - ges.enqueueGameEvent(_event, playerId); + if (card->setCounter(i.key(), i.value(), &_event)) { + ges.enqueueGameEvent(_event, playerId); + } } // Copy parent card @@ -1338,8 +1340,9 @@ Response::ResponseCode Server_AbstractPlayer::cmdSetCardCounter(const Command_Se Event_SetCardCounter event; event.set_zone_name(zone->getName().toStdString()); event.set_card_id(card->getId()); - card->setCounter(cmd.counter_id(), cmd.counter_value(), &event); - ges.enqueueGameEvent(event, playerId); + if (card->setCounter(cmd.counter_id(), cmd.counter_value(), &event)) { + ges.enqueueGameEvent(event, playerId); + } return Response::RespOk; } @@ -1368,14 +1371,13 @@ Response::ResponseCode Server_AbstractPlayer::cmdIncCardCounter(const Command_In return Response::RespNameNotFound; } - int newValue = card->getCounter(cmd.counter_id()) + cmd.counter_delta(); - card->setCounter(cmd.counter_id(), newValue); - Event_SetCardCounter event; event.set_zone_name(zone->getName().toStdString()); event.set_card_id(card->getId()); - event.set_counter_id(cmd.counter_id()); - event.set_counter_value(newValue); + if (!card->incrementCounter(cmd.counter_id(), cmd.counter_delta(), &event)) { + return Response::RespOk; + } + ges.enqueueGameEvent(event, playerId); return Response::RespOk; diff --git a/libcockatrice_network/libcockatrice/network/server/remote/game/server_card.cpp b/libcockatrice_network/libcockatrice/network/server/remote/game/server_card.cpp index e3d53ace8..b858314c0 100644 --- a/libcockatrice_network/libcockatrice/network/server/remote/game/server_card.cpp +++ b/libcockatrice_network/libcockatrice/network/server/remote/game/server_card.cpp @@ -26,6 +26,8 @@ #include #include #include +#include +#include Server_Card::Server_Card(const CardRef &cardRef, int _id, int _coord_x, int _coord_y, Server_CardZone *_zone) : zone(_zone), id(_id), coord_x(_coord_x), coord_y(_coord_y), cardRef(cardRef), tapped(false), attacking(false), @@ -110,8 +112,16 @@ QString Server_Card::setAttribute(CardAttribute attribute, const QString &avalue return avalue; } -void Server_Card::setCounter(int _id, int value, Event_SetCardCounter *event) +bool Server_Card::setCounter(int _id, int value, Event_SetCardCounter *event) { + // Clamp to valid card counter range [0, MAX_COUNTERS_ON_CARD] + value = qBound(0, value, MAX_COUNTERS_ON_CARD); + + const int oldValue = counters.value(_id, 0); + if (value == oldValue) { + return false; + } + if (value) { counters.insert(_id, value); } else { @@ -122,6 +132,34 @@ void Server_Card::setCounter(int _id, int value, Event_SetCardCounter *event) event->set_counter_id(_id); event->set_counter_value(value); } + + return true; +} + +bool Server_Card::incrementCounter(int counterId, int delta, Event_SetCardCounter *event) +{ + const int oldValue = counters.value(counterId, 0); + const auto result = static_cast(oldValue) + static_cast(delta); + // Clamp to [0, MAX_COUNTERS_ON_CARD] for card counters + const int newValue = + static_cast(qBound(static_cast(0), result, static_cast(MAX_COUNTERS_ON_CARD))); + + if (newValue == oldValue) { + return false; + } + + if (newValue) { + counters.insert(counterId, newValue); + } else { + counters.remove(counterId); + } + + if (event) { + event->set_counter_id(counterId); + event->set_counter_value(newValue); + } + + return true; } void Server_Card::setParentCard(Server_Card *_parentCard) diff --git a/libcockatrice_network/libcockatrice/network/server/remote/game/server_card.h b/libcockatrice_network/libcockatrice/network/server/remote/game/server_card.h index bc326bbc4..3d7e649b9 100644 --- a/libcockatrice_network/libcockatrice/network/server/remote/game/server_card.h +++ b/libcockatrice_network/libcockatrice/network/server/remote/game/server_card.h @@ -153,7 +153,24 @@ public: { cardRef = _cardRef; } - void setCounter(int _id, int value, Event_SetCardCounter *event = nullptr); + /** + * @brief Sets a card counter to an exact value with clamping. + * @param _id The counter ID. + * @param value The desired value (clamped to [0, MAX_COUNTERS_ON_CARD]; 0 removes the counter). + * @param event Optional event to populate with counter state. + * @return true if the value changed, false otherwise. + */ + [[nodiscard]] bool setCounter(int _id, int value, Event_SetCardCounter *event = nullptr); + /** + * @brief Increments a card counter with overflow-safe arithmetic. + * @param counterId The counter ID to modify. + * @param delta The amount to add (may be negative for decrement). + * @param event Optional event to populate with counter state. + * @return true if the value changed, false otherwise. + * @note If counter does not exist, starts from 0. Counter is removed if result is 0. + * @note Clamps result to [0, MAX_COUNTERS_ON_CARD]. + */ + [[nodiscard]] bool incrementCounter(int counterId, int delta, Event_SetCardCounter *event = nullptr); void setTapped(bool _tapped) { tapped = _tapped; diff --git a/libcockatrice_network/libcockatrice/network/server/remote/game/server_counter.cpp b/libcockatrice_network/libcockatrice/network/server/remote/game/server_counter.cpp index b18e11c2b..e65205cbb 100644 --- a/libcockatrice_network/libcockatrice/network/server/remote/game/server_counter.cpp +++ b/libcockatrice_network/libcockatrice/network/server/remote/game/server_counter.cpp @@ -1,12 +1,24 @@ #include "server_counter.h" #include +#include Server_Counter::Server_Counter(int _id, const QString &_name, const color &_counterColor, int _radius, int _count) : id(_id), name(_name), counterColor(_counterColor), radius(_radius), count(_count) { } +//! \todo Extract overflow-safe arithmetic into shared helper. +//! Duplicated in Server_Card::incrementCounter() - keep in sync if modified. +bool Server_Counter::incrementCount(int delta) +{ + const int oldCount = count; + const auto result = static_cast(count) + static_cast(delta); + count = static_cast(qBound(static_cast(std::numeric_limits::min()), result, + static_cast(std::numeric_limits::max()))); + return count != oldCount; +} + void Server_Counter::getInfo(ServerInfo_Counter *info) { info->set_id(id); diff --git a/libcockatrice_network/libcockatrice/network/server/remote/game/server_counter.h b/libcockatrice_network/libcockatrice/network/server/remote/game/server_counter.h index 55aad991c..8226e663f 100644 --- a/libcockatrice_network/libcockatrice/network/server/remote/game/server_counter.h +++ b/libcockatrice_network/libcockatrice/network/server/remote/game/server_counter.h @@ -25,6 +25,18 @@ class ServerInfo_Counter; +/** + * @class Server_Counter + * @brief Represents a player counter with overflow-safe increment arithmetic. + * + * All value modifications return whether the value actually changed, + * enabling callers to skip unnecessary network events. + * + * @note Direct assignment via setCount() does not clamp; only + * incrementCount() enforces int boundary saturation. + * @note Unlike card counters, player counters are never auto-removed + * when they reach zero - they persist with value 0. + */ class Server_Counter { protected: @@ -59,11 +71,33 @@ public: { return count; } - void setCount(int _count) + + /** + * @brief Sets the counter to an exact value. + * @param _count The new value (assigned directly without clamping). + * @return true if the value changed, false otherwise. + * @warning This performs raw assignment. For overflow-safe incrementing, + * use incrementCount(). + */ + [[nodiscard]] bool setCount(int _count) { + const int oldCount = count; count = _count; + return count != oldCount; } + /** + * @brief Increments the counter by delta with overflow-safe arithmetic. + * @param delta The amount to add (may be negative for decrement). + * @return true if the value changed, false otherwise. + * @note Clamps result to [INT_MIN, INT_MAX] to prevent overflow. + */ + [[nodiscard]] bool incrementCount(int delta); + + /** + * @brief Populates info with this counter's current state for network serialization. + * @param info The protobuf message to populate. + */ void getInfo(ServerInfo_Counter *info); }; diff --git a/libcockatrice_network/libcockatrice/network/server/remote/game/server_player.cpp b/libcockatrice_network/libcockatrice/network/server/remote/game/server_player.cpp index a1a0a3b3a..56e3f9f8e 100644 --- a/libcockatrice_network/libcockatrice/network/server/remote/game/server_player.cpp +++ b/libcockatrice_network/libcockatrice/network/server/remote/game/server_player.cpp @@ -436,17 +436,19 @@ Server_Player::cmdIncCounter(const Command_IncCounter &cmd, ResponseContainer & return Response::RespContextError; } - Server_Counter *c = counters.value(cmd.counter_id(), 0); + const int counterId = cmd.counter_id(); + Server_Counter *c = counters.value(counterId, nullptr); if (!c) { return Response::RespNameNotFound; } - c->setCount(c->getCount() + cmd.delta()); - - Event_SetCounter event; - event.set_counter_id(c->getId()); - event.set_value(c->getCount()); - ges.enqueueGameEvent(event, playerId); + bool didChange = c->incrementCount(cmd.delta()); + if (didChange) { + Event_SetCounter event; + event.set_counter_id(c->getId()); + event.set_value(c->getCount()); + ges.enqueueGameEvent(event, playerId); + } return Response::RespOk; } @@ -487,17 +489,19 @@ Server_Player::cmdSetCounter(const Command_SetCounter &cmd, ResponseContainer & return Response::RespContextError; } - Server_Counter *c = counters.value(cmd.counter_id(), 0); + const int counterId = cmd.counter_id(); + Server_Counter *c = counters.value(counterId, nullptr); if (!c) { return Response::RespNameNotFound; } - c->setCount(cmd.value()); - - Event_SetCounter event; - event.set_counter_id(c->getId()); - event.set_value(c->getCount()); - ges.enqueueGameEvent(event, playerId); + bool didChange = c->setCount(cmd.value()); + if (didChange) { + Event_SetCounter event; + event.set_counter_id(c->getId()); + event.set_value(c->getCount()); + ges.enqueueGameEvent(event, playerId); + } return Response::RespOk; } @@ -512,15 +516,16 @@ Server_Player::cmdDelCounter(const Command_DelCounter &cmd, ResponseContainer & return Response::RespContextError; } - Server_Counter *counter = counters.value(cmd.counter_id(), 0); + const int counterId = cmd.counter_id(); + Server_Counter *counter = counters.value(counterId, nullptr); if (!counter) { return Response::RespNameNotFound; } - counters.remove(cmd.counter_id()); + counters.remove(counterId); delete counter; Event_DelCounter event; - event.set_counter_id(cmd.counter_id()); + event.set_counter_id(counterId); ges.enqueueGameEvent(event, playerId); return Response::RespOk; diff --git a/libcockatrice_utility/libcockatrice/utility/trice_limits.h b/libcockatrice_utility/libcockatrice/utility/trice_limits.h index fa7ce7489..833ce1b98 100644 --- a/libcockatrice_utility/libcockatrice/utility/trice_limits.h +++ b/libcockatrice_utility/libcockatrice/utility/trice_limits.h @@ -15,6 +15,12 @@ constexpr uint MAXIMUM_DIE_SIDES = 1000000; constexpr uint MINIMUM_DICE_TO_ROLL = 1; constexpr uint MAXIMUM_DICE_TO_ROLL = 100; +// Card counter value bounds [0, MAX_COUNTERS_ON_CARD]. +// Counters on cards (e.g., +1/+1 counters, charge counters) are non-negative physical game objects. +// The max of 999 is a display constraint (3-digit rendering) and reasonable gameplay limit. +// Server enforces these bounds; client may also check for UX optimization. +constexpr int MAX_COUNTERS_ON_CARD = 999; + // optimized functions to get qstrings that are at most that long static inline QString nameFromStdString(const std::string &_string) { diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index fffaf1bda..00eba288e 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -6,6 +6,8 @@ add_test(NAME dummy_test COMMAND dummy_test) add_test(NAME expression_test COMMAND expression_test) add_test(NAME test_age_formatting COMMAND test_age_formatting) add_test(NAME password_hash_test COMMAND password_hash_test) +add_test(NAME server_card_counter_test COMMAND server_card_counter_test) +add_test(NAME server_counter_test COMMAND server_counter_test) add_test(NAME deck_hash_performance_test COMMAND deck_hash_performance_test) set_tests_properties(deck_hash_performance_test PROPERTIES TIMEOUT 5) @@ -17,6 +19,8 @@ add_executable(expression_test expression_test.cpp) add_executable(test_age_formatting test_age_formatting.cpp) add_executable(password_hash_test password_hash_test.cpp) add_executable(deck_hash_performance_test deck_hash_performance_test.cpp) +add_executable(server_card_counter_test server_card_counter_test.cpp) +add_executable(server_counter_test server_counter_test.cpp) find_package(GTest) @@ -48,6 +52,8 @@ if(NOT GTEST_FOUND) add_dependencies(test_age_formatting gtest) add_dependencies(password_hash_test gtest) add_dependencies(deck_hash_performance_test gtest) + add_dependencies(server_card_counter_test gtest) + add_dependencies(server_counter_test gtest) endif() include_directories(${GTEST_INCLUDE_DIRS}) @@ -61,6 +67,12 @@ target_link_libraries( deck_hash_performance_test libcockatrice_deck_list libcockatrice_utility Threads::Threads ${GTEST_BOTH_LIBRARIES} ${TEST_QT_MODULES} ) +target_link_libraries( + server_card_counter_test libcockatrice_network Threads::Threads ${GTEST_BOTH_LIBRARIES} ${TEST_QT_MODULES} +) +target_link_libraries( + server_counter_test libcockatrice_network Threads::Threads ${GTEST_BOTH_LIBRARIES} ${TEST_QT_MODULES} +) add_subdirectory(card_zone_algorithms) add_subdirectory(carddatabase) diff --git a/tests/server_card_counter_test.cpp b/tests/server_card_counter_test.cpp new file mode 100644 index 000000000..ff906b906 --- /dev/null +++ b/tests/server_card_counter_test.cpp @@ -0,0 +1,183 @@ +/** @file server_card_counter_test.cpp + * @brief Tests for Server_Card counter operations. + * @ingroup Tests + */ + +#include +#include +#include +#include +#include +#include + +TEST(ServerCardCounter, IncrementNewCounter) +{ + Server_Card card(CardRef{"TestCard", ""}, 1, 0, 0); + EXPECT_TRUE(card.incrementCounter(1, 10)); + EXPECT_EQ(card.getCounter(1), 10); +} + +TEST(ServerCardCounter, IncrementExistingCounter) +{ + Server_Card card(CardRef{"TestCard", ""}, 1, 0, 0); + ASSERT_TRUE(card.setCounter(1, 50)); + EXPECT_TRUE(card.incrementCounter(1, 10)); + EXPECT_EQ(card.getCounter(1), 60); +} + +TEST(ServerCardCounter, IncrementOverflowProtection) +{ + Server_Card card(CardRef{"TestCard", ""}, 1, 0, 0); + ASSERT_TRUE(card.setCounter(1, MAX_COUNTERS_ON_CARD)); + EXPECT_FALSE(card.incrementCounter(1, 1)); + EXPECT_EQ(card.getCounter(1), MAX_COUNTERS_ON_CARD); +} + +TEST(ServerCardCounter, DecrementUnderflowProtection) +{ + Server_Card card(CardRef{"TestCard", ""}, 1, 0, 0); + ASSERT_TRUE(card.setCounter(1, 5)); + EXPECT_TRUE(card.incrementCounter(1, -10)); + EXPECT_EQ(card.getCounter(1), 0); + EXPECT_FALSE(card.getCounters().contains(1)); +} + +TEST(ServerCardCounter, ReturnsFalseWhenUnchanged) +{ + Server_Card card(CardRef{"TestCard", ""}, 1, 0, 0); + ASSERT_TRUE(card.setCounter(1, 50)); + EXPECT_FALSE(card.incrementCounter(1, 0)); + EXPECT_EQ(card.getCounter(1), 50); +} + +TEST(ServerCardCounter, DecrementToZeroRemovesCounter) +{ + Server_Card card(CardRef{"TestCard", ""}, 1, 0, 0); + ASSERT_TRUE(card.setCounter(1, 10)); + EXPECT_TRUE(card.incrementCounter(1, -10)); + EXPECT_EQ(card.getCounter(1), 0); + EXPECT_FALSE(card.getCounters().contains(1)); +} + +TEST(ServerCardCounter, SetToZeroRemovesCounter) +{ + Server_Card card(CardRef{"TestCard", ""}, 1, 0, 0); + ASSERT_TRUE(card.setCounter(1, 10)); + EXPECT_TRUE(card.setCounter(1, 0)); + EXPECT_EQ(card.getCounter(1), 0); + EXPECT_FALSE(card.getCounters().contains(1)); +} + +TEST(ServerCardCounter, SetCounterReturnsFalseWhenUnchanged) +{ + Server_Card card(CardRef{"TestCard", ""}, 1, 0, 0); + ASSERT_TRUE(card.setCounter(1, 50)); + EXPECT_FALSE(card.setCounter(1, 50)); + EXPECT_EQ(card.getCounter(1), 50); +} + +TEST(ServerCardCounter, SetCounterReturnsTrueWhenChanged) +{ + Server_Card card(CardRef{"TestCard", ""}, 1, 0, 0); + ASSERT_TRUE(card.setCounter(1, 50)); + EXPECT_TRUE(card.setCounter(1, 100)); + EXPECT_EQ(card.getCounter(1), 100); +} + +TEST(ServerCardCounter, SetCounterEventNotPopulatedWhenUnchanged) +{ + Server_Card card(CardRef{"TestCard", ""}, 1, 0, 0); + ASSERT_TRUE(card.setCounter(1, 50)); + + Event_SetCardCounter event; + event.set_counter_id(999); + event.set_counter_value(999); + + EXPECT_FALSE(card.setCounter(1, 50, &event)); + EXPECT_EQ(event.counter_id(), 999); + EXPECT_EQ(event.counter_value(), 999); +} + +TEST(ServerCardCounter, IncrementCounterPopulatesEvent) +{ + Server_Card card(CardRef{"TestCard", ""}, 1, 0, 0); + ASSERT_TRUE(card.setCounter(1, 50)); + + Event_SetCardCounter event; + EXPECT_TRUE(card.incrementCounter(1, 10, &event)); + + EXPECT_EQ(event.counter_id(), 1); + EXPECT_EQ(event.counter_value(), 60); +} + +TEST(ServerCardCounter, IncrementCounterEventReflectsClampedValue) +{ + Server_Card card(CardRef{"TestCard", ""}, 1, 0, 0); + ASSERT_TRUE(card.setCounter(1, MAX_COUNTERS_ON_CARD - 5)); + + Event_SetCardCounter event; + EXPECT_TRUE(card.incrementCounter(1, 10, &event)); + + EXPECT_EQ(event.counter_id(), 1); + EXPECT_EQ(event.counter_value(), MAX_COUNTERS_ON_CARD); +} + +TEST(ServerCardCounter, IncrementCounterNoEventWhenNullptr) +{ + Server_Card card(CardRef{"TestCard", ""}, 1, 0, 0); + ASSERT_TRUE(card.setCounter(1, 50)); + EXPECT_TRUE(card.incrementCounter(1, 10, nullptr)); + EXPECT_EQ(card.getCounter(1), 60); +} + +TEST(ServerCardCounter, IncrementCounterEventNotPopulatedWhenUnchanged) +{ + Server_Card card(CardRef{"TestCard", ""}, 1, 0, 0); + ASSERT_TRUE(card.setCounter(1, MAX_COUNTERS_ON_CARD)); + + Event_SetCardCounter event; + event.set_counter_id(999); + event.set_counter_value(999); + + EXPECT_FALSE(card.incrementCounter(1, 1, &event)); + EXPECT_EQ(event.counter_id(), 999); + EXPECT_EQ(event.counter_value(), 999); +} + +TEST(ServerCardCounter, SetCounterClampsNegativeToZero) +{ + Server_Card card(CardRef{"TestCard", ""}, 1, 0, 0); + EXPECT_FALSE(card.setCounter(1, -5)); + EXPECT_EQ(card.getCounter(1), 0); + EXPECT_FALSE(card.getCounters().contains(1)); +} + +TEST(ServerCardCounter, SetCounterClampsAboveMaxToMax) +{ + Server_Card card(CardRef{"TestCard", ""}, 1, 0, 0); + EXPECT_TRUE(card.setCounter(1, 1500)); + EXPECT_EQ(card.getCounter(1), MAX_COUNTERS_ON_CARD); +} + +TEST(ServerCardCounter, IncrementDoesNotGoBelowZero) +{ + Server_Card card(CardRef{"TestCard", ""}, 1, 0, 0); + ASSERT_TRUE(card.setCounter(1, 5)); + EXPECT_TRUE(card.incrementCounter(1, -10)); + EXPECT_EQ(card.getCounter(1), 0); + EXPECT_FALSE(card.getCounters().contains(1)); +} + +TEST(ServerCardCounter, IncrementDoesNotExceedMax) +{ + Server_Card card(CardRef{"TestCard", ""}, 1, 0, 0); + ASSERT_TRUE(card.setCounter(1, MAX_COUNTERS_ON_CARD - 5)); + EXPECT_TRUE(card.incrementCounter(1, 10)); + EXPECT_EQ(card.getCounter(1), MAX_COUNTERS_ON_CARD); +} + +int main(int argc, char **argv) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/tests/server_counter_test.cpp b/tests/server_counter_test.cpp new file mode 100644 index 000000000..0f41f2cbd --- /dev/null +++ b/tests/server_counter_test.cpp @@ -0,0 +1,86 @@ +/** @file server_counter_test.cpp + * @brief Tests for Server_Counter operations. + * @ingroup Tests + */ + +#include +#include +#include + +TEST(ServerCounter, IncrementDoesNotOverflow) +{ + Server_Counter c(1, "test", color(), 10, std::numeric_limits::max()); + bool changed = c.incrementCount(1); + EXPECT_FALSE(changed); + EXPECT_EQ(c.getCount(), std::numeric_limits::max()); +} + +TEST(ServerCounter, DecrementDoesNotUnderflow) +{ + Server_Counter c(1, "test", color(), 10, std::numeric_limits::min()); + bool changed = c.incrementCount(-1); + EXPECT_FALSE(changed); + EXPECT_EQ(c.getCount(), std::numeric_limits::min()); +} + +TEST(ServerCounter, SetCountReturnsFalseWhenUnchanged) +{ + Server_Counter c(1, "test", color(), 10, 50); + bool changed = c.setCount(50); + EXPECT_FALSE(changed); +} + +TEST(ServerCounter, IncrementReturnsChangeStatus) +{ + Server_Counter c(1, "test", color(), 10, 50); + EXPECT_TRUE(c.incrementCount(10)); + EXPECT_EQ(c.getCount(), 60); + EXPECT_FALSE(c.incrementCount(0)); + EXPECT_EQ(c.getCount(), 60); +} + +TEST(ServerCounter, LargePositiveDeltaDoesNotOverflow) +{ + Server_Counter c(1, "test", color(), 10, std::numeric_limits::max() - 10); + bool changed = c.incrementCount(std::numeric_limits::max()); + EXPECT_TRUE(changed); // Value changes from INT_MAX-10 to INT_MAX (clamped) + EXPECT_EQ(c.getCount(), std::numeric_limits::max()); +} + +TEST(ServerCounter, LargeNegativeDeltaDoesNotUnderflow) +{ + Server_Counter c(1, "test", color(), 10, std::numeric_limits::min() + 10); + bool changed = c.incrementCount(std::numeric_limits::min()); + EXPECT_TRUE(changed); // Value changes from INT_MIN+10 to INT_MIN (clamped) + EXPECT_EQ(c.getCount(), std::numeric_limits::min()); +} + +TEST(ServerCounter, SetCountReturnsTrueWhenChanged) +{ + Server_Counter c(1, "test", color(), 10, 50); + EXPECT_TRUE(c.setCount(100)); + EXPECT_EQ(c.getCount(), 100); +} + +TEST(ServerCounter, BasicIncrementWorks) +{ + Server_Counter c(1, "test", color(), 10, 50); + EXPECT_TRUE(c.incrementCount(10)); + EXPECT_EQ(c.getCount(), 60); + EXPECT_TRUE(c.incrementCount(-20)); + EXPECT_EQ(c.getCount(), 40); +} + +TEST(ServerCounter, MixedExtremesDoNotClamp) +{ + Server_Counter c(1, "test", color(), 10, std::numeric_limits::max()); + bool changed = c.incrementCount(std::numeric_limits::min()); + EXPECT_TRUE(changed); + EXPECT_EQ(c.getCount(), -1); +} + +int main(int argc, char **argv) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} From 81a2712b92eb1007195f17f524732ba808315a94 Mon Sep 17 00:00:00 2001 From: DawnFire42 Date: Fri, 22 May 2026 01:56:24 -0400 Subject: [PATCH 38/51] Fix card stacking overflow when vertical zone has many cards (#6925) Previously, minOffset (10px) was enforced unconditionally, causing card tops to overflow zone bounds when many cards were stacked. For example, 50 cards in a 200px zone would place the last card's top at y=490. Now offsets compress below minOffset when necessary to keep all card tops visible. The constraint is guarded by !allowBottomOverflow to preserve future clipping zone semantics. --- cockatrice/src/game_graphics/zones/select_zone.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/cockatrice/src/game_graphics/zones/select_zone.cpp b/cockatrice/src/game_graphics/zones/select_zone.cpp index d43753603..90d53b464 100644 --- a/cockatrice/src/game_graphics/zones/select_zone.cpp +++ b/cockatrice/src/game_graphics/zones/select_zone.cpp @@ -42,7 +42,19 @@ SelectZone::ZoneLayout SelectZone::computeZoneLayout(const StackLayoutParams &pa reservedForBottomCard = params.cardHeight; } fitOffset = (params.totalHeight - reservedForBottomCard) / (params.cardCount - 1); - effectiveOffset = qMax(params.minOffset, qMin(params.desiredOffset, fitOffset)); + + if (!params.allowBottomOverflow) { + // Constrain offset so all card tops remain within zone bounds. + // With start=0, last card top at (cardCount-1) * effectiveOffset must be < totalHeight. + qreal maxOffsetForTops = params.totalHeight / (params.cardCount - 1); + fitOffset = qMin(fitOffset, maxOffsetForTops); + } + + // Apply minOffset only if it fits; otherwise compress further to keep all card tops visible. + effectiveOffset = qMin(params.desiredOffset, fitOffset); + if (fitOffset >= params.minOffset) { + effectiveOffset = qMax(params.minOffset, effectiveOffset); + } } } qreal stackHeight = (params.cardCount - 1) * effectiveOffset + params.cardHeight; From 09d817770e6d13692930a6a2f9e195a0ee48bf49 Mon Sep 17 00:00:00 2001 From: RickyRister <42636155+RickyRister@users.noreply.github.com> Date: Fri, 22 May 2026 01:25:00 -0700 Subject: [PATCH 39/51] [Game] Refactor: move proliferate action code to PlayerActions (#6926) --- .../src/game/player/menu/utility_menu.cpp | 3 +- cockatrice/src/game/player/player_actions.cpp | 36 +++++++++++++++++++ cockatrice/src/game/player/player_actions.h | 1 + cockatrice/src/game/player/player_logic.cpp | 36 ------------------- cockatrice/src/game/player/player_logic.h | 1 - 5 files changed, 39 insertions(+), 38 deletions(-) diff --git a/cockatrice/src/game/player/menu/utility_menu.cpp b/cockatrice/src/game/player/menu/utility_menu.cpp index f6d9802ae..6b33d7bde 100644 --- a/cockatrice/src/game/player/menu/utility_menu.cpp +++ b/cockatrice/src/game/player/menu/utility_menu.cpp @@ -30,7 +30,8 @@ UtilityMenu::UtilityMenu(PlayerLogic *_player, QMenu *playerMenu) : QMenu(player aCreateAnotherToken->setEnabled(false); aIncrementAllCardCounters = new QAction(this); - connect(aIncrementAllCardCounters, &QAction::triggered, player, &PlayerLogic::incrementAllCardCounters); + connect(aIncrementAllCardCounters, &QAction::triggered, playerActions, + &PlayerActions::actIncrementAllCardCounters); createPredefinedTokenMenu = new QMenu(QString()); createPredefinedTokenMenu->setEnabled(false); diff --git a/cockatrice/src/game/player/player_actions.cpp b/cockatrice/src/game/player/player_actions.cpp index c2b9140af..1706c44dc 100644 --- a/cockatrice/src/game/player/player_actions.cpp +++ b/cockatrice/src/game/player/player_actions.cpp @@ -1559,6 +1559,42 @@ void PlayerActions::actSetCardCounter(int counterId) sendGameCommand(prepareGameCommand(commandList)); } +void PlayerActions::actIncrementAllCardCounters() +{ + auto cardsToUpdate = player->getGameScene()->selectedCards(); + if (cardsToUpdate.isEmpty()) { + // If no cards selected, update all cards on table + cardsToUpdate = static_cast>(player->getTableZone()->getCards()); + } + + QList commandList; + + for (const auto *card : cardsToUpdate) { + const auto &cardCounters = card->getCounters(); + + QMapIterator counterIterator(cardCounters); + while (counterIterator.hasNext()) { + counterIterator.next(); + int counterId = counterIterator.key(); + int currentValue = counterIterator.value(); + if (currentValue >= MAX_COUNTERS_ON_CARD) { + continue; + } + + auto cmd = std::make_unique(); + cmd->set_zone(card->getZone()->getName().toStdString()); + cmd->set_card_id(card->getId()); + cmd->set_counter_id(counterId); + cmd->set_counter_value(currentValue + 1); + commandList.append(cmd.release()); + } + } + + if (!commandList.isEmpty()) { + sendGameCommand(prepareGameCommand(commandList)); + } +} + /** * @brief returns true if the zone is a unwritable reveal zone view (eg a card reveal window). Will return false if zone * is nullptr. diff --git a/cockatrice/src/game/player/player_actions.h b/cockatrice/src/game/player/player_actions.h index d294d2c40..3b822b61a 100644 --- a/cockatrice/src/game/player/player_actions.h +++ b/cockatrice/src/game/player/player_actions.h @@ -131,6 +131,7 @@ public slots: void actRemoveCardCounter(int counterId); void actAddCardCounter(int counterId); void actSetCardCounter(int counterId); + void actIncrementAllCardCounters(); void actAttach(); void actUnattach(); void actDrawArrow(); diff --git a/cockatrice/src/game/player/player_logic.cpp b/cockatrice/src/game/player/player_logic.cpp index 7fdb48868..67c6e9519 100644 --- a/cockatrice/src/game/player/player_logic.cpp +++ b/cockatrice/src/game/player/player_logic.cpp @@ -304,42 +304,6 @@ CounterState *PlayerLogic::getLifeCounter() const return nullptr; } -void PlayerLogic::incrementAllCardCounters() -{ - auto cardsToUpdate = getGameScene()->selectedCards(); - if (cardsToUpdate.isEmpty()) { - // If no cards selected, update all cards on table - cardsToUpdate = static_cast>(getTableZone()->getCards()); - } - - QList commandList; - - for (const auto *card : cardsToUpdate) { - const auto &cardCounters = card->getCounters(); - - QMapIterator counterIterator(cardCounters); - while (counterIterator.hasNext()) { - counterIterator.next(); - int counterId = counterIterator.key(); - int currentValue = counterIterator.value(); - if (currentValue >= MAX_COUNTERS_ON_CARD) { - continue; - } - - auto cmd = std::make_unique(); - cmd->set_zone(card->getZone()->getName().toStdString()); - cmd->set_card_id(card->getId()); - cmd->set_counter_id(counterId); - cmd->set_counter_value(currentValue + 1); - commandList.append(cmd.release()); - } - } - - if (!commandList.isEmpty()) { - playerActions->sendGameCommand(playerActions->prepareGameCommand(commandList)); - } -} - bool PlayerLogic::clearCardsToDelete() { if (cardsToDelete.isEmpty()) { diff --git a/cockatrice/src/game/player/player_logic.h b/cockatrice/src/game/player/player_logic.h index fdeef49ba..5f58ca265 100644 --- a/cockatrice/src/game/player/player_logic.h +++ b/cockatrice/src/game/player/player_logic.h @@ -197,7 +197,6 @@ public: CounterState *addCounter(int id, const QString &name, const QColor &color, int radius, int value); void delCounter(int counterId); void clearCounters(); - void incrementAllCardCounters(); QMap getCounters() const { From 8751f0605d242066e677ffa17f85af120064f3c9 Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Fri, 22 May 2026 10:25:13 +0200 Subject: [PATCH 40/51] [Game][Arrows] Don't request deletion on inbound arrow deletion signal again but react to it locally (#6927) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [Game][Arrows] Deleting arrows has no acknowledgement command so we have to delete locally as well. Took 22 minutes * Fix properly. Took 15 minutes --------- Co-authored-by: Lukas Brübach --- cockatrice/src/game/game_scene.cpp | 8 ++++++++ cockatrice/src/game/game_scene.h | 1 + cockatrice/src/game/player/player_event_handler.cpp | 2 +- cockatrice/src/game/player/player_logic.h | 1 + 4 files changed, 11 insertions(+), 1 deletion(-) diff --git a/cockatrice/src/game/game_scene.cpp b/cockatrice/src/game/game_scene.cpp index 71b9caa4b..e70069ee3 100644 --- a/cockatrice/src/game/game_scene.cpp +++ b/cockatrice/src/game/game_scene.cpp @@ -93,6 +93,7 @@ void GameScene::addPlayer(PlayerLogic *player) rearrange(); }); + connect(player, &PlayerLogic::arrowDeleted, this, &GameScene::onArrowDeleted); connect(player, &PlayerLogic::arrowCreateRequested, this, &GameScene::onArrowCreateRequested); connect(player, &PlayerLogic::arrowDeleteRequested, this, &GameScene::onArrowDeleteRequested); connect(player, &PlayerLogic::arrowsCleared, this, @@ -404,6 +405,13 @@ void GameScene::onArrowCreateRequested(const ArrowData &data) connect(arrow, &QObject::destroyed, this, [this, id = data.id]() { arrowRegistry.remove(id); }); } +void GameScene::onArrowDeleted(int arrowId) +{ + if (arrowRegistry.contains(arrowId)) { + arrowRegistry.take(arrowId)->delArrow(); + } +} + void GameScene::onArrowDeleteRequested(int arrowId) { if (arrowRegistry.contains(arrowId)) { diff --git a/cockatrice/src/game/game_scene.h b/cockatrice/src/game/game_scene.h index 5e0e6b7c9..235ce6550 100644 --- a/cockatrice/src/game/game_scene.h +++ b/cockatrice/src/game/game_scene.h @@ -202,6 +202,7 @@ public slots: QTransform getViewportTransform() const; void onArrowCreateRequested(const ArrowData &data); + void onArrowDeleted(int arrowId); void onArrowDeleteRequested(int arrowId); void onCardZoneChanged(CardItem *card, bool sameZone); void clearArrowsForPlayer(int playerId); diff --git a/cockatrice/src/game/player/player_event_handler.cpp b/cockatrice/src/game/player/player_event_handler.cpp index 24030057b..3a7d0345b 100644 --- a/cockatrice/src/game/player/player_event_handler.cpp +++ b/cockatrice/src/game/player/player_event_handler.cpp @@ -128,7 +128,7 @@ void PlayerEventHandler::eventCreateArrow(const Event_CreateArrow &event) void PlayerEventHandler::eventDeleteArrow(const Event_DeleteArrow &event) { - emit player->arrowDeleteRequested(event.arrow_id()); + emit player->arrowDeleted(event.arrow_id()); } void PlayerEventHandler::eventCreateToken(const Event_CreateToken &event) diff --git a/cockatrice/src/game/player/player_logic.h b/cockatrice/src/game/player/player_logic.h index 5f58ca265..20d7597b4 100644 --- a/cockatrice/src/game/player/player_logic.h +++ b/cockatrice/src/game/player/player_logic.h @@ -80,6 +80,7 @@ signals: void resetTopCardMenuActions(); void arrowCreateRequested(ArrowData data); void arrowDeleteRequested(int arrowId); + void arrowDeleted(int arrowId); void arrowsCleared(); // fires on clear() and processPlayerInfo public slots: From 8004d4f2d449d709f0df071668cb29d7d74016be Mon Sep 17 00:00:00 2001 From: RickyRister <42636155+RickyRister@users.noreply.github.com> Date: Fri, 22 May 2026 03:26:52 -0700 Subject: [PATCH 41/51] [VDE] Disable filter dock widget (#6924) --- .../visual_deck_editor/tab_deck_editor_visual.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/cockatrice/src/interface/widgets/tabs/visual_deck_editor/tab_deck_editor_visual.cpp b/cockatrice/src/interface/widgets/tabs/visual_deck_editor/tab_deck_editor_visual.cpp index 081766cdf..3cdad91fc 100644 --- a/cockatrice/src/interface/widgets/tabs/visual_deck_editor/tab_deck_editor_visual.cpp +++ b/cockatrice/src/interface/widgets/tabs/visual_deck_editor/tab_deck_editor_visual.cpp @@ -50,6 +50,7 @@ TabDeckEditorVisual::TabDeckEditorVisual(TabSupervisor *_tabSupervisor) : Abstra refreshShortcuts(); loadLayout(); + filterDockWidget->setHidden(true); cardDatabaseDockWidget->setHidden(true); } @@ -99,7 +100,7 @@ void TabDeckEditorVisual::createMenus() registerDockWidget(viewMenu, cardInfoDockWidget, {250, 500}); registerDockWidget(viewMenu, deckDockWidget, {250, 360}); - registerDockWidget(viewMenu, filterDockWidget, {250, 250}); + // registerDockWidget(viewMenu, filterDockWidget, {250, 250}); registerDockWidget(viewMenu, printingSelectorDockWidget, {525, 250}); viewMenu->addSeparator(); @@ -276,18 +277,18 @@ void TabDeckEditorVisual::restartLayout() deckDockWidget->setVisible(true); cardInfoDockWidget->setVisible(true); - filterDockWidget->setVisible(false); + // filterDockWidget->setVisible(false); printingSelectorDockWidget->setVisible(true); setCentralWidget(centralWidget); addDockWidget(Qt::RightDockWidgetArea, deckDockWidget); addDockWidget(Qt::RightDockWidgetArea, cardInfoDockWidget); - addDockWidget(Qt::RightDockWidgetArea, filterDockWidget); + // addDockWidget(Qt::RightDockWidgetArea, filterDockWidget); addDockWidget(Qt::RightDockWidgetArea, printingSelectorDockWidget); splitDockWidget(cardInfoDockWidget, printingSelectorDockWidget, Qt::Vertical); splitDockWidget(cardInfoDockWidget, deckDockWidget, Qt::Horizontal); - splitDockWidget(cardInfoDockWidget, filterDockWidget, Qt::Horizontal); + // splitDockWidget(cardInfoDockWidget, filterDockWidget, Qt::Horizontal); QTimer::singleShot(100, this, SLOT(freeDocksSize())); } @@ -299,13 +300,13 @@ void TabDeckEditorVisual::retranslateUi() cardInfoDockWidget->setWindowTitle(tr("Card Info")); deckDockWidget->setWindowTitle(tr("Deck")); - filterDockWidget->setWindowTitle(tr("Filters")); + // filterDockWidget->setWindowTitle(tr("Filters")); viewMenu->setTitle(tr("&View")); dockToActions[cardInfoDockWidget].menu->setTitle(tr("Card Info")); dockToActions[deckDockWidget].menu->setTitle(tr("Deck")); - dockToActions[filterDockWidget].menu->setTitle(tr("Filters")); + // dockToActions[filterDockWidget].menu->setTitle(tr("Filters")); dockToActions[printingSelectorDockWidget].menu->setTitle(tr("Printing")); for (auto &actions : dockToActions.values()) { From d2164c3f08ec6dfe5b4371942f0527cc1ea4ee5d Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Fri, 22 May 2026 22:36:53 +0200 Subject: [PATCH 42/51] [Oracle] Change basic lands exception to regex to deal with snow basics. (#6931) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [Oracle] Change basic lands exception to regex to deal with snow basics. Took 45 minutes * Update oracle/src/oracleimporter.cpp Co-authored-by: ebbit1q --------- Co-authored-by: Lukas Brübach Co-authored-by: ebbit1q --- oracle/src/oracleimporter.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/oracle/src/oracleimporter.cpp b/oracle/src/oracleimporter.cpp index 05a3a7ca3..bace63508 100644 --- a/oracle/src/oracleimporter.cpp +++ b/oracle/src/oracleimporter.cpp @@ -473,8 +473,8 @@ FormatRulesNameMap OracleImporter::createDefaultMagicFormats() // Predefined common exceptions CardCondition superTypeIsBasic; superTypeIsBasic.field = "type"; - superTypeIsBasic.matchType = "contains"; - superTypeIsBasic.value = "Basic Land"; + superTypeIsBasic.matchType = "regex"; + superTypeIsBasic.value = "\bBasic\b[^—]+\bLand\b"; ExceptionRule basicLands; basicLands.conditions.append(superTypeIsBasic); From 98c00c55ed46ca523f0b3a3d7e3bf30d4784503e Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Sat, 23 May 2026 02:20:41 +0200 Subject: [PATCH 43/51] [Game][Arrows] ArrowItem should not send deletion game commands by itself (#6932) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Took 13 minutes Co-authored-by: Lukas Brübach --- cockatrice/src/game/board/arrow_item.cpp | 13 ++++++++----- cockatrice/src/game/board/arrow_item.h | 4 ++++ cockatrice/src/game/game_scene.cpp | 2 +- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/cockatrice/src/game/board/arrow_item.cpp b/cockatrice/src/game/board/arrow_item.cpp index bfc219a3f..430477d76 100644 --- a/cockatrice/src/game/board/arrow_item.cpp +++ b/cockatrice/src/game/board/arrow_item.cpp @@ -38,11 +38,11 @@ ArrowItem::ArrowItem(PlayerLogic *_player, if (startItem) { connect(startItem, &ArrowTarget::scenePositionChanged, this, doUpdate); - connect(startItem, &QObject::destroyed, this, &ArrowItem::delArrow); + connect(startItem, &QObject::destroyed, this, &ArrowItem::onTargetDestroyed); } if (targetItem) { connect(targetItem, &ArrowTarget::scenePositionChanged, this, doUpdate); - connect(targetItem, &QObject::destroyed, this, &ArrowItem::delArrow); + connect(targetItem, &QObject::destroyed, this, &ArrowItem::onTargetDestroyed); } if (startItem && targetItem) { @@ -50,6 +50,11 @@ ArrowItem::ArrowItem(PlayerLogic *_player, } } +void ArrowItem::onTargetDestroyed() +{ + emit requestDeletion(id); +} + void ArrowItem::delArrow() { if (targetItem) { @@ -151,9 +156,7 @@ void ArrowItem::mousePressEvent(QGraphicsSceneMouseEvent *event) event->accept(); if (event->button() == Qt::RightButton) { - Command_DeleteArrow cmd; - cmd.set_arrow_id(id); - player->getPlayerActions()->sendGameCommand(cmd); + emit requestDeletion(id); } } diff --git a/cockatrice/src/game/board/arrow_item.h b/cockatrice/src/game/board/arrow_item.h index ebaea032a..7dc0f9477 100644 --- a/cockatrice/src/game/board/arrow_item.h +++ b/cockatrice/src/game/board/arrow_item.h @@ -21,6 +21,9 @@ class ArrowItem : public QObject, public QGraphicsItem { Q_OBJECT Q_INTERFACES(QGraphicsItem) +signals: + void requestDeletion(int id); + private: QPainterPath path; @@ -37,6 +40,7 @@ protected: public: ArrowItem(PlayerLogic *_player, int _id, ArrowTarget *_startItem, ArrowTarget *_targetItem, const QColor &_color); + void onTargetDestroyed(); void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override; [[nodiscard]] QRectF boundingRect() const override diff --git a/cockatrice/src/game/game_scene.cpp b/cockatrice/src/game/game_scene.cpp index e70069ee3..500c1cbe0 100644 --- a/cockatrice/src/game/game_scene.cpp +++ b/cockatrice/src/game/game_scene.cpp @@ -402,7 +402,7 @@ void GameScene::onArrowCreateRequested(const ArrowData &data) auto *arrow = new ArrowItem(startView->getPlayer(), data.id, startCard, targetItem, data.color); addItem(arrow); arrowRegistry.insert(data.id, arrow); - connect(arrow, &QObject::destroyed, this, [this, id = data.id]() { arrowRegistry.remove(id); }); + connect(arrow, &ArrowItem::requestDeletion, this, &GameScene::onArrowDeleteRequested); } void GameScene::onArrowDeleted(int arrowId) From 90ab663212d5a891378330d304d9f6a5714a37c5 Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Mon, 25 May 2026 08:19:17 +0200 Subject: [PATCH 44/51] [Server][Game][Arrows] Properly notify clients when deleting arrows on card move and transform into (#6936) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [Server][Game][Arrows] Properly notify clients when deleting arrows on card move and transform into Took 15 minutes * Observe "not found" response Took 18 minutes Took 4 seconds --------- Co-authored-by: Lukas Brübach --- cockatrice/src/game/game_event_handler.cpp | 15 +++++++++++- cockatrice/src/game/game_event_handler.h | 2 ++ .../src/interface/widgets/tabs/tab_game.cpp | 1 + .../remote/game/server_abstract_player.cpp | 23 +++++++++++++------ 4 files changed, 33 insertions(+), 8 deletions(-) diff --git a/cockatrice/src/game/game_event_handler.cpp b/cockatrice/src/game/game_event_handler.cpp index b338deaea..cff80a1ec 100644 --- a/cockatrice/src/game/game_event_handler.cpp +++ b/cockatrice/src/game/game_event_handler.cpp @@ -217,7 +217,20 @@ void GameEventHandler::handleArrowDeletion(int arrowId) { Command_DeleteArrow cmd; cmd.set_arrow_id(arrowId); - sendGameCommand(cmd); + + auto preparedCommand = prepareGameCommand(cmd); + + connect(preparedCommand, &PendingCommand::finished, this, + [arrowId, this](const Response &response) { handleArrowDeletionFinished(response, arrowId); }); + + sendGameCommand(preparedCommand); +} + +void GameEventHandler::handleArrowDeletionFinished(const Response &response, int arrowId) +{ + if (response.response_code() == Response::RespNameNotFound) { + emit arrowDeleted(arrowId); + } } void GameEventHandler::eventSpectatorSay(const Event_GameSay &event, diff --git a/cockatrice/src/game/game_event_handler.h b/cockatrice/src/game/game_event_handler.h index 7587ab46d..bc4812aa4 100644 --- a/cockatrice/src/game/game_event_handler.h +++ b/cockatrice/src/game/game_event_handler.h @@ -61,6 +61,7 @@ public: void handleGameLeft(); void handleChatMessageSent(const QString &chatMessage); void handleArrowDeletion(int arrowId); + void handleArrowDeletionFinished(const Response &response, int arrowId); void eventSpectatorSay(const Event_GameSay &event, int eventPlayerId, const GameEventContext &context); void eventSpectatorLeave(const Event_Leave &event, int eventPlayerId, const GameEventContext &context); @@ -112,6 +113,7 @@ signals: void containerProcessingStarted(GameEventContext context); void setContextJudgeName(QString judgeName); void containerProcessingDone(); + void arrowDeleted(int arrowId); void logSpectatorSay(ServerInfo_User userInfo, QString message); void logSpectatorLeave(QString name, QString reason); void logGameStart(); diff --git a/cockatrice/src/interface/widgets/tabs/tab_game.cpp b/cockatrice/src/interface/widgets/tabs/tab_game.cpp index 6b7b3539c..dd5df72a1 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_game.cpp +++ b/cockatrice/src/interface/widgets/tabs/tab_game.cpp @@ -1147,6 +1147,7 @@ void TabGame::createPlayAreaWidget(bool bReplay) connect(game->getPlayerManager(), &PlayerManager::playerCountChanged, scene, &GameScene::rearrange); connect(scene, &GameScene::requestArrowDeletion, game->getGameEventHandler(), &GameEventHandler::handleArrowDeletion); + connect(game->getGameEventHandler(), &GameEventHandler::arrowDeleted, scene, &GameScene::onArrowDeleted); gameView = new GameView(scene); auto gamePlayAreaVBox = new QVBoxLayout; diff --git a/libcockatrice_network/libcockatrice/network/server/remote/game/server_abstract_player.cpp b/libcockatrice_network/libcockatrice/network/server/remote/game/server_abstract_player.cpp index 100a4ebc6..3e489233c 100644 --- a/libcockatrice_network/libcockatrice/network/server/remote/game/server_abstract_player.cpp +++ b/libcockatrice_network/libcockatrice/network/server/remote/game/server_abstract_player.cpp @@ -397,6 +397,9 @@ void Server_AbstractPlayer::processMoveCard(GameEventStorage &ges, } } for (int j : arrowsToDelete) { + Event_DeleteArrow event; + event.set_arrow_id(j); + ges.enqueueGameEvent(event, player->getPlayerId()); player->deleteArrow(j); } } @@ -1132,12 +1135,18 @@ Server_AbstractPlayer::cmdCreateToken(const Command_CreateToken &cmd, ResponseCo targetItem = card; } if (sendGameEvent) { - Event_CreateArrow _event; - ServerInfo_Arrow *arrowInfo = _event.mutable_arrow_info(); - changedArrowIds.append(arrow->getId()); - int id = player->newArrowId(); - arrow->setId(id); - arrowInfo->set_id(id); + const int oldId = arrow->getId(); + changedArrowIds.append(oldId); + + Event_DeleteArrow deleteEvent; + deleteEvent.set_arrow_id(oldId); + ges.enqueueGameEvent(deleteEvent, player->getPlayerId()); + + Event_CreateArrow createEvent; + ServerInfo_Arrow *arrowInfo = createEvent.mutable_arrow_info(); + const int newId = player->newArrowId(); + arrow->setId(newId); + arrowInfo->set_id(newId); arrowInfo->set_start_player_id(player->getPlayerId()); arrowInfo->set_start_zone(startCard->getZone()->getName().toStdString()); arrowInfo->set_start_card_id(startCard->getId()); @@ -1151,7 +1160,7 @@ Server_AbstractPlayer::cmdCreateToken(const Command_CreateToken &cmd, ResponseCo arrowInfo->set_target_card_id(arrowTargetCard->getId()); } arrowInfo->mutable_arrow_color()->CopyFrom(arrow->getColor()); - ges.enqueueGameEvent(_event, player->getPlayerId()); + ges.enqueueGameEvent(createEvent, player->getPlayerId()); } } for (int id : changedArrowIds) { From b3c89167c53673ade34f376f60769dd5ff6355c8 Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Mon, 25 May 2026 08:19:27 +0200 Subject: [PATCH 45/51] [Game][Arrows] Hook up to the state zone change properly. (#6937) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Took 17 minutes Took 3 seconds Took 2 minutes Took 10 minutes Co-authored-by: Lukas Brübach --- cockatrice/src/game/board/card_item.h | 4 ++++ cockatrice/src/game/board/card_state.cpp | 2 +- cockatrice/src/game/board/card_state.h | 2 +- cockatrice/src/game/game_scene.cpp | 2 +- cockatrice/src/interface/widgets/tabs/tab_game.cpp | 5 +++++ 5 files changed, 12 insertions(+), 3 deletions(-) diff --git a/cockatrice/src/game/board/card_item.h b/cockatrice/src/game/board/card_item.h index 451fed0c6..87f9667de 100644 --- a/cockatrice/src/game/board/card_item.h +++ b/cockatrice/src/game/board/card_item.h @@ -55,6 +55,10 @@ public: CardZoneLogic *_zone = nullptr); void retranslateUi(); + [[nodiscard]] CardState *getState() const + { + return state; + } [[nodiscard]] CardZoneLogic *getZone() const { return state->getZone(); diff --git a/cockatrice/src/game/board/card_state.cpp b/cockatrice/src/game/board/card_state.cpp index fe1aa9b73..4319400d7 100644 --- a/cockatrice/src/game/board/card_state.cpp +++ b/cockatrice/src/game/board/card_state.cpp @@ -18,7 +18,7 @@ void CardState::setZone(CardZoneLogic *_zone) } zone = _zone; - emit zoneChanged(zone); + emit zoneChanged(this, zone); emit stateChanged(); } diff --git a/cockatrice/src/game/board/card_state.h b/cockatrice/src/game/board/card_state.h index ef17f408c..0498b1aa2 100644 --- a/cockatrice/src/game/board/card_state.h +++ b/cockatrice/src/game/board/card_state.h @@ -31,7 +31,7 @@ signals: void doesntUntapChanged(bool newValue); void destroyOnZoneChangeChanged(bool newValue); void attachedToChanged(CardItem *newAttachedTo); - void zoneChanged(CardZoneLogic *newZone); + void zoneChanged(CardState *changedCard, CardZoneLogic *newZone); public: explicit CardState(QObject *parent, CardZoneLogic *_zone) : QObject(parent), zone(_zone) diff --git a/cockatrice/src/game/game_scene.cpp b/cockatrice/src/game/game_scene.cpp index 500c1cbe0..9f466c2ac 100644 --- a/cockatrice/src/game/game_scene.cpp +++ b/cockatrice/src/game/game_scene.cpp @@ -432,7 +432,7 @@ void GameScene::onCardZoneChanged(CardItem *card, bool sameZone) } } for (auto *arrow : toDelete) { - emit requestArrowDeletion(arrow->getId()); + onArrowDeleted(arrow->getId()); } } diff --git a/cockatrice/src/interface/widgets/tabs/tab_game.cpp b/cockatrice/src/interface/widgets/tabs/tab_game.cpp index dd5df72a1..3da3685dd 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_game.cpp +++ b/cockatrice/src/interface/widgets/tabs/tab_game.cpp @@ -895,6 +895,11 @@ void TabGame::newCardAdded(AbstractCardItem *card) connect(card, &AbstractCardItem::showCardInfoPopup, this, &TabGame::showCardInfoPopup); connect(card, SIGNAL(deleteCardInfoPopup(QString)), this, SLOT(deleteCardInfoPopup(QString))); connect(card, &AbstractCardItem::cardShiftClicked, this, &TabGame::linkCardToChat); + CardItem *cardItem = qobject_cast(card); + if (cardItem) { + connect(cardItem->getState(), &CardState::zoneChanged, scene, + [this, cardItem]() { scene->onCardZoneChanged(cardItem, false); }); + } } QString TabGame::getTabText() const From 1d5d3f2d38fa4b1d23d3f496abf48d0918b97012 Mon Sep 17 00:00:00 2001 From: RickyRister <42636155+RickyRister@users.noreply.github.com> Date: Tue, 26 May 2026 15:11:38 -0700 Subject: [PATCH 46/51] Run formatter on all our files (#6942) --- .../card_picture_loader_local_schemes.h | 21 ++++--- .../card_picture_loader_worker.cpp | 3 +- .../src/interface/layouts/flow_layout.cpp | 12 ++-- .../general/layout_containers/flow_widget.cpp | 3 +- .../card/archidekt_api_response_card.h | 2 +- .../card/archidekt_api_response_card_entry.h | 2 +- .../deck/archidekt_api_response_deck.h | 4 +- ...database_display_filter_toolbar_widget.cpp | 3 +- .../libcockatrice/filters/filter_string.cpp | 24 +++++--- .../libcockatrice/filters/filter_tree.cpp | 9 ++- .../interface_card_set_priority_controller.h | 3 +- .../noop_card_set_priority_controller.h | 5 +- .../database/card/card_search_model.cpp | 15 +++-- .../database/card_database_display_model.cpp | 24 +++++--- .../models/database/card_database_model.cpp | 18 ++++-- .../database/card_set/card_sets_model.cpp | 60 ++++++++++++------- .../models/deck_list/deck_list_model.h | 12 ++-- .../deck_list_sort_filter_proxy_model.cpp | 12 ++-- oracle/src/pagetemplates.h | 2 +- 19 files changed, 153 insertions(+), 81 deletions(-) diff --git a/cockatrice/src/interface/card_picture_loader/card_picture_loader_local_schemes.h b/cockatrice/src/interface/card_picture_loader/card_picture_loader_local_schemes.h index cad7d2d5f..d51d646e6 100644 --- a/cockatrice/src/interface/card_picture_loader/card_picture_loader_local_schemes.h +++ b/cockatrice/src/interface/card_picture_loader/card_picture_loader_local_schemes.h @@ -61,24 +61,30 @@ inline QString expandPattern(const QString &pattern, QString result = pattern; auto replaceIfPresent = [&](const QString &token, const QString &value) -> bool { - if (!result.contains(token)) + if (!result.contains(token)) { return true; + } - if (value.isEmpty()) + if (value.isEmpty()) { return false; + } result.replace(token, value); return true; }; - if (!replaceIfPresent("{name}", name)) + if (!replaceIfPresent("{name}", name)) { return {}; - if (!replaceIfPresent("{set}", set)) + } + if (!replaceIfPresent("{set}", set)) { return {}; - if (!replaceIfPresent("{collector}", collector)) + } + if (!replaceIfPresent("{collector}", collector)) { return {}; - if (!replaceIfPresent("{providerId}", providerId)) + } + if (!replaceIfPresent("{providerId}", providerId)) { return {}; + } return result; } @@ -96,8 +102,9 @@ generateImportVariants(const QString &name, const QString &set, const QString &c pattern.replace("_", sep); QString v = expandPattern(pattern, name, set, collector, providerId); - if (!v.isEmpty()) + if (!v.isEmpty()) { variants << v; + } } } diff --git a/cockatrice/src/interface/card_picture_loader/card_picture_loader_worker.cpp b/cockatrice/src/interface/card_picture_loader/card_picture_loader_worker.cpp index a0f000139..2f51ba986 100644 --- a/cockatrice/src/interface/card_picture_loader/card_picture_loader_worker.cpp +++ b/cockatrice/src/interface/card_picture_loader/card_picture_loader_worker.cpp @@ -28,8 +28,9 @@ CardPictureLoaderWorker::CardPictureLoaderWorker() static_cast(SettingsCache::instance().getNetworkCacheSizeInMB())); connect(&SettingsCache::instance(), &SettingsCache::networkCacheSizeChanged, cache, [this](int newSizeInMB) { - if (cache) + if (cache) { cache->setMaximumCacheSize(1024L * 1024L * static_cast(newSizeInMB)); + } }); networkManager->setCache(cache); diff --git a/cockatrice/src/interface/layouts/flow_layout.cpp b/cockatrice/src/interface/layouts/flow_layout.cpp index 36edd2c21..0d03b7789 100644 --- a/cockatrice/src/interface/layouts/flow_layout.cpp +++ b/cockatrice/src/interface/layouts/flow_layout.cpp @@ -70,8 +70,9 @@ bool FlowLayout::hasHeightForWidth() const */ int FlowLayout::heightForWidth(const int width) const { - if (flowDirection != Qt::Horizontal) + if (flowDirection != Qt::Horizontal) { return -1; + } int totalHeight = 0; int rowUsedWidth = 0; @@ -181,8 +182,9 @@ int FlowLayout::layoutAllRows(const int originX, const int originY, const int av */ void FlowLayout::layoutSingleRow(const QVector &rowItems, int x, const int y, const int availableWidth) { - if (rowItems.isEmpty()) + if (rowItems.isEmpty()) { return; + } // ── Pass 1: measure fixed width and count expanding items ──────────────── int fixedWidth = 0; @@ -211,12 +213,14 @@ void FlowLayout::layoutSingleRow(const QVector &rowItems, int x, // ── Pass 2: place items ────────────────────────────────────────────────── for (QLayoutItem *item : rowItems) { - if (!item || item->isEmpty()) + if (!item || item->isEmpty()) { continue; + } QWidget *widget = item->widget(); - if (!widget) + if (!widget) { continue; + } const QSizePolicy::Policy hPolicy = widget->sizePolicy().horizontalPolicy(); const QSize maxSize = widget->maximumSize(); diff --git a/cockatrice/src/interface/widgets/general/layout_containers/flow_widget.cpp b/cockatrice/src/interface/widgets/general/layout_containers/flow_widget.cpp index 59c657724..025f457bd 100644 --- a/cockatrice/src/interface/widgets/general/layout_containers/flow_widget.cpp +++ b/cockatrice/src/interface/widgets/general/layout_containers/flow_widget.cpp @@ -108,8 +108,9 @@ void FlowWidget::clearLayout() if (flowLayout) { QLayoutItem *item; while ((item = flowLayout->takeAt(0))) { - if (item->widget()) + if (item->widget()) { item->widget()->deleteLater(); + } delete item; } } else { diff --git a/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/card/archidekt_api_response_card.h b/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/card/archidekt_api_response_card.h index 265498228..559580da2 100644 --- a/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/card/archidekt_api_response_card.h +++ b/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/card/archidekt_api_response_card.h @@ -24,7 +24,7 @@ public: QJsonObject getOracleCard() const { return oracleCard; - }; + } QString getCollectorNumber() const { diff --git a/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/card/archidekt_api_response_card_entry.h b/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/card/archidekt_api_response_card_entry.h index f3961dc6f..118cf5b13 100644 --- a/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/card/archidekt_api_response_card_entry.h +++ b/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/card/archidekt_api_response_card_entry.h @@ -33,7 +33,7 @@ public: ArchidektApiResponseCard getCard() const { return card; - }; + } QList getCategories() const { diff --git a/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/deck/archidekt_api_response_deck.h b/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/deck/archidekt_api_response_deck.h index fce437751..b539d9dd1 100644 --- a/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/deck/archidekt_api_response_deck.h +++ b/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/deck/archidekt_api_response_deck.h @@ -27,7 +27,7 @@ public: QVector getCards() const { return cards; - }; + } QVector getCategories() const { @@ -37,7 +37,7 @@ public: QString getDeckName() const { return name; - }; + } int getDeckFormat() const { diff --git a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_filter_toolbar_widget.cpp b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_filter_toolbar_widget.cpp index 885925694..0c1280009 100644 --- a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_filter_toolbar_widget.cpp +++ b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_filter_toolbar_widget.cpp @@ -174,7 +174,8 @@ void VisualDatabaseDisplayFilterToolbarWidget::updateCompactMode(int availableWi }; for (auto *btn : filterButtons) { - if (btn->isCompact() != compact) // only act on transitions + if (btn->isCompact() != compact) { // only act on transitions btn->setCompact(compact); + } } } \ No newline at end of file diff --git a/libcockatrice_filters/libcockatrice/filters/filter_string.cpp b/libcockatrice_filters/libcockatrice/filters/filter_string.cpp index 704e8fadb..25e8e97db 100644 --- a/libcockatrice_filters/libcockatrice/filters/filter_string.cpp +++ b/libcockatrice_filters/libcockatrice/filters/filter_string.cpp @@ -251,20 +251,27 @@ static void setupParserRules() const auto arg = std::any_cast(sv[1]); const auto op = std::any_cast(sv[0]); - if (op == ">") + if (op == ">") { return [=](const int s) { return s > arg; }; - if (op == ">=") + } + if (op == ">=") { return [=](const int s) { return s >= arg; }; - if (op == "<") + } + if (op == "<") { return [=](const int s) { return s < arg; }; - if (op == "<=") + } + if (op == "<=") { return [=](const int s) { return s <= arg; }; - if (op == "=") + } + if (op == "=") { return [=](const int s) { return s == arg; }; - if (op == ":") + } + if (op == ":") { return [=](const int s) { return s == arg; }; - if (op == "!=") + } + if (op == "!=") { return [=](const int s) { return s != arg; }; + } return [](int) { return false; }; }; @@ -315,8 +322,9 @@ static void setupParserRules() return true; } - if (parts.contains("c") && match.length() == 0) + if (parts.contains("c") && match.length() == 0) { return true; + } auto containsColor = [&parts](const QString &s) { return parts.contains(s); }; return std::any_of(match.begin(), match.end(), containsColor); diff --git a/libcockatrice_filters/libcockatrice/filters/filter_tree.cpp b/libcockatrice_filters/libcockatrice/filters/filter_tree.cpp index 19e8c2d8d..8502db50b 100644 --- a/libcockatrice_filters/libcockatrice/filters/filter_tree.cpp +++ b/libcockatrice_filters/libcockatrice/filters/filter_tree.cpp @@ -205,8 +205,9 @@ bool FilterItem::acceptColor(const CardInfoPtr info) const */ int match_count = 0; for (auto &it : converted_term) { - if (info->getColors().contains(it, Qt::CaseInsensitive)) + if (info->getColors().contains(it, Qt::CaseInsensitive)) { match_count++; + } } return match_count == converted_term.length(); @@ -542,12 +543,14 @@ void FilterTree::removeFilter(const CardFilter *toRemove) { for (int i = childNodes.size() - 1; i >= 0; --i) { auto *logicMap = dynamic_cast(childNodes.at(i)); - if (!logicMap || logicMap->attr != toRemove->attr()) + if (!logicMap || logicMap->attr != toRemove->attr()) { continue; + } FilterItemList *typeList = logicMap->typeList(toRemove->type()); - if (!typeList) + if (!typeList) { continue; + } int termIdx = typeList->termIndex(toRemove->term()); if (termIdx != -1) { diff --git a/libcockatrice_interfaces/libcockatrice/interfaces/interface_card_set_priority_controller.h b/libcockatrice_interfaces/libcockatrice/interfaces/interface_card_set_priority_controller.h index 333190015..9559967af 100644 --- a/libcockatrice_interfaces/libcockatrice/interfaces/interface_card_set_priority_controller.h +++ b/libcockatrice_interfaces/libcockatrice/interfaces/interface_card_set_priority_controller.h @@ -6,7 +6,8 @@ class ICardSetPriorityController { public: - struct SetSaveData { + struct SetSaveData + { QString shortName; unsigned int sortKey; bool enabled; diff --git a/libcockatrice_interfaces/libcockatrice/interfaces/noop_card_set_priority_controller.h b/libcockatrice_interfaces/libcockatrice/interfaces/noop_card_set_priority_controller.h index 16fc4c19a..188e2ced9 100644 --- a/libcockatrice_interfaces/libcockatrice/interfaces/noop_card_set_priority_controller.h +++ b/libcockatrice_interfaces/libcockatrice/interfaces/noop_card_set_priority_controller.h @@ -29,8 +29,9 @@ public: return true; } - void saveSets(const QVector & /* data */) override { - }; + void saveSets(const QVector & /* data */) override + { + } }; #endif // COCKATRICE_NOOP_CARD_SET_PRIORITY_CONTROLLER_H diff --git a/libcockatrice_models/libcockatrice/models/database/card/card_search_model.cpp b/libcockatrice_models/libcockatrice/models/database/card/card_search_model.cpp index 6a930c1da..d1fbbac2f 100644 --- a/libcockatrice_models/libcockatrice/models/database/card/card_search_model.cpp +++ b/libcockatrice_models/libcockatrice/models/database/card/card_search_model.cpp @@ -19,8 +19,9 @@ int CardSearchModel::rowCount(const QModelIndex &parent) const QVariant CardSearchModel::data(const QModelIndex &index, int role) const { - if (!index.isValid() || index.row() >= searchResults.size()) + if (!index.isValid() || index.row() >= searchResults.size()) { return QVariant(); + } if (role == Qt::DisplayRole) { return searchResults.at(index.row()).card->getName(); @@ -34,8 +35,9 @@ void CardSearchModel::updateSearchResults(const QString &query) beginResetModel(); searchResults.clear(); - if (query.isEmpty() || !sourceModel) + if (query.isEmpty() || !sourceModel) { return; + } // Set the filter for the display model sourceModel->setCardName(query); @@ -46,13 +48,15 @@ void CardSearchModel::updateSearchResults(const QString &query) QModelIndex sourceIndex = sourceModel->mapToSource(modelIndex); CardDatabaseModel *sourceDbModel = qobject_cast(sourceModel->sourceModel()); - if (!sourceDbModel || !sourceIndex.isValid()) + if (!sourceDbModel || !sourceIndex.isValid()) { return; + } CardInfoPtr card = sourceDbModel->getCard(sourceIndex.row()); - if (!card) + if (!card) { continue; + } int distance = levenshteinDistance(query.toLower(), card->getName().toLower()); searchResults.append({card, distance}); @@ -63,8 +67,9 @@ void CardSearchModel::updateSearchResults(const QString &query) [](const SearchResult &a, const SearchResult &b) { return a.distance < b.distance; }); // Keep only the top 5 results - if (searchResults.size() > 10) + if (searchResults.size() > 10) { searchResults = searchResults.mid(0, 10); + } emit dataChanged(index(0, 0), index(rowCount() - 1, 0)); emit layoutChanged(); diff --git a/libcockatrice_models/libcockatrice/models/database/card_database_display_model.cpp b/libcockatrice_models/libcockatrice/models/database/card_database_display_model.cpp index b9c38d3d7..724ee61f2 100644 --- a/libcockatrice_models/libcockatrice/models/database/card_database_display_model.cpp +++ b/libcockatrice_models/libcockatrice/models/database/card_database_display_model.cpp @@ -75,12 +75,14 @@ bool CardDatabaseDisplayModel::lessThan(const QModelIndex &left, const QModelInd // test for an exact match: isLeftType && leftString.size() == cardName.size() // or an exclusive start match: isLeftType && !isRightType - if (isLeftType && (!isRightType || leftString.size() == cardName.size())) + if (isLeftType && (!isRightType || leftString.size() == cardName.size())) { return true; + } // same checks for the right string - if (isRightType && (!isLeftType || rightString.size() == cardName.size())) + if (isRightType && (!isLeftType || rightString.size() == cardName.size())) { return false; + } } else if (right.column() == CardDatabaseModel::PTColumn && left.column() == CardDatabaseModel::PTColumn) { QStringList leftList = leftString.split("/"); QStringList rightList = rightString.split("/"); @@ -172,8 +174,9 @@ bool CardDatabaseDisplayModel::filterAcceptsRow(int sourceRow, const QModelIndex { CardInfoPtr info = static_cast(sourceModel())->getCard(sourceRow); - if (((isToken == ShowTrue) && !info->getIsToken()) || ((isToken == ShowFalse) && info->getIsToken())) + if (((isToken == ShowTrue) && !info->getIsToken()) || ((isToken == ShowFalse) && info->getIsToken())) { return false; + } if (filterString != nullptr) { if (filterTree != nullptr && !filterTree->acceptsCard(info)) { @@ -187,14 +190,17 @@ bool CardDatabaseDisplayModel::filterAcceptsRow(int sourceRow, const QModelIndex bool CardDatabaseDisplayModel::rowMatchesCardName(CardInfoPtr info) const { - if (!cardName.isEmpty() && !info->getName().contains(cardName, Qt::CaseInsensitive)) + if (!cardName.isEmpty() && !info->getName().contains(cardName, Qt::CaseInsensitive)) { return false; + } - if (!cardNameSet.isEmpty() && !cardNameSet.contains(info->getName())) + if (!cardNameSet.isEmpty() && !cardNameSet.contains(info->getName())) { return false; + } - if (filterTree != nullptr) + if (filterTree != nullptr) { return filterTree->acceptsCard(info); + } return true; } @@ -208,8 +214,9 @@ void CardDatabaseDisplayModel::clearFilterAll() cardText.clear(); cardTypes.clear(); cardColors.clear(); - if (filterTree != nullptr) + if (filterTree != nullptr) { filterTree->clear(); + } #if (QT_VERSION >= QT_VERSION_CHECK(6, 10, 0)) endFilterChange(QSortFilterProxyModel::Direction::Rows); #else @@ -219,8 +226,9 @@ void CardDatabaseDisplayModel::clearFilterAll() void CardDatabaseDisplayModel::setFilterTree(FilterTree *_filterTree) { - if (this->filterTree != nullptr) + if (this->filterTree != nullptr) { disconnect(this->filterTree, nullptr, this, nullptr); + } this->filterTree = _filterTree; connect(this->filterTree, &FilterTree::changed, this, &CardDatabaseDisplayModel::filterTreeChanged); diff --git a/libcockatrice_models/libcockatrice/models/database/card_database_model.cpp b/libcockatrice_models/libcockatrice/models/database/card_database_model.cpp index e33156329..5ef84a276 100644 --- a/libcockatrice_models/libcockatrice/models/database/card_database_model.cpp +++ b/libcockatrice_models/libcockatrice/models/database/card_database_model.cpp @@ -31,8 +31,9 @@ int CardDatabaseModel::columnCount(const QModelIndex & /*parent*/) const QVariant CardDatabaseModel::data(const QModelIndex &index, int role) const { if (!index.isValid() || index.row() >= cardList.size() || index.column() >= CARDDBMODEL_COLUMNS || - (role != Qt::DisplayRole && role != SortRole)) + (role != Qt::DisplayRole && role != SortRole)) { return QVariant(); + } CardInfoPtr card = cardList.at(index.row()); switch (index.column()) { @@ -56,10 +57,12 @@ QVariant CardDatabaseModel::data(const QModelIndex &index, int role) const QVariant CardDatabaseModel::headerData(int section, Qt::Orientation orientation, int role) const { - if (role != Qt::DisplayRole) + if (role != Qt::DisplayRole) { return QVariant(); - if (orientation != Qt::Horizontal) + } + if (orientation != Qt::Horizontal) { return QVariant(); + } switch (section) { case NameColumn: return QString(tr("Name")); @@ -81,21 +84,24 @@ QVariant CardDatabaseModel::headerData(int section, Qt::Orientation orientation, void CardDatabaseModel::cardInfoChanged(CardInfoPtr card) { const int row = cardList.indexOf(card); - if (row == -1) + if (row == -1) { return; + } emit dataChanged(index(row, 0), index(row, CARDDBMODEL_COLUMNS - 1)); } bool CardDatabaseModel::checkCardHasAtLeastOneEnabledSet(CardInfoPtr card) { - if (!showOnlyCardsFromEnabledSets) + if (!showOnlyCardsFromEnabledSets) { return true; + } for (const auto &printings : card->getSets()) { for (const auto &printing : printings) { - if (printing.getSet()->getEnabled()) + if (printing.getSet()->getEnabled()) { return true; + } } } diff --git a/libcockatrice_models/libcockatrice/models/database/card_set/card_sets_model.cpp b/libcockatrice_models/libcockatrice/models/database/card_set/card_sets_model.cpp index c0164ad75..5e0cc31d8 100644 --- a/libcockatrice_models/libcockatrice/models/database/card_set/card_sets_model.cpp +++ b/libcockatrice_models/libcockatrice/models/database/card_set/card_sets_model.cpp @@ -6,8 +6,9 @@ SetsModel::SetsModel(CardDatabase *_db, QObject *parent) : QAbstractTableModel(p { sets.sortByKey(); for (const CardSetPtr &set : sets) { - if (set->getEnabled()) + if (set->getEnabled()) { enabledSets.insert(set); + } } } @@ -15,16 +16,18 @@ SetsModel::~SetsModel() = default; int SetsModel::rowCount(const QModelIndex &parent) const { - if (parent.isValid()) + if (parent.isValid()) { return 0; - else + } else { return sets.size(); + } } QVariant SetsModel::data(const QModelIndex &index, int role) const { - if (!index.isValid() || (index.column() >= NUM_COLS) || (index.row() >= rowCount())) + if (!index.isValid() || (index.column() >= NUM_COLS) || (index.row() >= rowCount())) { return QVariant(); + } CardSetPtr set = sets[index.row()]; @@ -40,8 +43,9 @@ QVariant SetsModel::data(const QModelIndex &index, int role) const } } - if (role != Qt::DisplayRole && role != SortRole) + if (role != Qt::DisplayRole && role != SortRole) { return QVariant(); + } switch (index.column()) { case SortKeyCol: @@ -72,8 +76,9 @@ bool SetsModel::setData(const QModelIndex &index, const QVariant &value, int rol QVariant SetsModel::headerData(int section, Qt::Orientation orientation, int role) const { - if ((role != Qt::DisplayRole) || (orientation != Qt::Horizontal)) + if ((role != Qt::DisplayRole) || (orientation != Qt::Horizontal)) { return QVariant(); + } switch (section) { case SortKeyCol: return QString("Key"); /* no tr() for translations needed, column just used for sorting --> hidden */ @@ -97,13 +102,15 @@ QVariant SetsModel::headerData(int section, Qt::Orientation orientation, int rol Qt::ItemFlags SetsModel::flags(const QModelIndex &index) const { - if (!index.isValid()) + if (!index.isValid()) { return Qt::NoItemFlags; + } Qt::ItemFlags flags = QAbstractTableModel::flags(index) | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled; - if (index.column() == EnabledCol) + if (index.column() == EnabledCol) { flags |= Qt::ItemIsUserCheckable; + } return flags; } @@ -115,8 +122,9 @@ Qt::DropActions SetsModel::supportedDropActions() const QMimeData *SetsModel::mimeData(const QModelIndexList &indexes) const { - if (indexes.isEmpty()) + if (indexes.isEmpty()) { return 0; + } SetsMimeData *result = new SetsMimeData(indexes[0].row()); return qobject_cast(result); @@ -128,16 +136,19 @@ bool SetsModel::dropMimeData(const QMimeData *data, int /*column*/, const QModelIndex &parent) { - if (action != Qt::MoveAction) + if (action != Qt::MoveAction) { return false; + } if (row == -1) { - if (!parent.isValid()) + if (!parent.isValid()) { return false; + } row = parent.row(); } int oldRow = qobject_cast(data)->getOldRow(); - if (oldRow < row) + if (oldRow < row) { row--; + } swapRows(oldRow, row); @@ -148,10 +159,11 @@ void SetsModel::toggleRow(int row, bool enable) { CardSetPtr temp = sets.at(row); - if (enable) + if (enable) { enabledSets.insert(temp); - else + } else { enabledSets.remove(temp); + } emit dataChanged(index(row, EnabledCol), index(row, EnabledCol)); } @@ -160,13 +172,15 @@ void SetsModel::toggleRow(int row) { CardSetPtr tmp = sets.at(row); - if (tmp == nullptr) + if (tmp == nullptr) { return; + } - if (enabledSets.contains(tmp)) + if (enabledSets.contains(tmp)) { enabledSets.remove(tmp); - else + } else { enabledSets.insert(tmp); + } emit dataChanged(index(row, EnabledCol), index(row, EnabledCol)); } @@ -175,9 +189,11 @@ void SetsModel::toggleAll(bool enabled) { enabledSets.clear(); - if (enabled) - for (CardSetPtr set : sets) + if (enabled) { + for (CardSetPtr set : sets) { enabledSets.insert(set); + } + } emit dataChanged(index(0, 0), index(rowCount() - 1, columnCount() - 1)); } @@ -208,8 +224,9 @@ void SetsModel::sort(int column, Qt::SortOrder order) int numRows = rowCount(); int row; - for (row = 0; row < numRows; ++row) + for (row = 0; row < numRows; ++row) { setMap.insert(index(row, column).data(SetsModel::SortRole).toString(), sets.at(row)); + } QList tmp = setMap.values(); sets.clear(); @@ -253,8 +270,9 @@ void SetsModel::restore(CardDatabase *db) // enabled sets enabledSets.clear(); for (const CardSetPtr &set : sets) { - if (set->getEnabled()) + if (set->getEnabled()) { enabledSets.insert(set); + } } emit dataChanged(index(0, 0), index(rowCount() - 1, columnCount() - 1)); diff --git a/libcockatrice_models/libcockatrice/models/deck_list/deck_list_model.h b/libcockatrice_models/libcockatrice/models/deck_list/deck_list_model.h index 86d36b7f9..209ec8c42 100644 --- a/libcockatrice_models/libcockatrice/models/deck_list/deck_list_model.h +++ b/libcockatrice_models/libcockatrice/models/deck_list/deck_list_model.h @@ -89,12 +89,15 @@ static inline QString toString(Type t) static inline Type fromString(const QString &s) { - if (s == "Main Type") + if (s == "Main Type") { return MAIN_TYPE; - if (s == "Mana Cost") + } + if (s == "Mana Cost") { return MANA_COST; - if (s == "Colors") + } + if (s == "Colors") { return COLOR; + } return MAIN_TYPE; // default } } // namespace DeckListModelGroupCriteria @@ -427,8 +430,9 @@ private: template T getNode(const QModelIndex &index) const { - if (!index.isValid()) + if (!index.isValid()) { return dynamic_cast(root); + } return dynamic_cast(static_cast(index.internalPointer())); } diff --git a/libcockatrice_models/libcockatrice/models/deck_list/deck_list_sort_filter_proxy_model.cpp b/libcockatrice_models/libcockatrice/models/deck_list/deck_list_sort_filter_proxy_model.cpp index 0ec159737..3d433153a 100644 --- a/libcockatrice_models/libcockatrice/models/deck_list/deck_list_sort_filter_proxy_model.cpp +++ b/libcockatrice_models/libcockatrice/models/deck_list/deck_list_sort_filter_proxy_model.cpp @@ -29,25 +29,29 @@ bool DeckListSortFilterProxyModel::lessThan(const QModelIndex &left, const QMode QString ln = lNode->getName(); QString rn = rNode->getName(); int cmp = ln.localeAwareCompare(rn); - if (cmp != 0) + if (cmp != 0) { return cmp < 0; + } } else if (crit == "cmc") { int lc = lInfo ? lInfo->getCmc().toInt() : 0; int rc = rInfo ? rInfo->getCmc().toInt() : 0; - if (lc != rc) + if (lc != rc) { return lc < rc; + } } else if (crit == "colors") { QString lr = lInfo ? lInfo->getColors() : QString(); QString rr = rInfo ? rInfo->getColors() : QString(); int cmp = lr.localeAwareCompare(rr); - if (cmp != 0) + if (cmp != 0) { return cmp < 0; + } } else if (crit == "maintype") { QString lr = lInfo ? lInfo->getMainCardType() : QString(); QString rr = rInfo ? rInfo->getMainCardType() : QString(); int cmp = lr.localeAwareCompare(rr); - if (cmp != 0) + if (cmp != 0) { return cmp < 0; + } } } diff --git a/oracle/src/pagetemplates.h b/oracle/src/pagetemplates.h index 79dcdd632..6e79c867e 100644 --- a/oracle/src/pagetemplates.h +++ b/oracle/src/pagetemplates.h @@ -27,7 +27,7 @@ protected: inline OracleWizard *wizard() { return (OracleWizard *)QWizardPage::wizard(); - }; + } }; class SimpleDownloadFilePage : public OracleWizardPage From 7f30728f87b3b8a631a3e0a43f6e4fda3750ec69 Mon Sep 17 00:00:00 2001 From: RickyRister <42636155+RickyRister@users.noreply.github.com> Date: Tue, 26 May 2026 18:53:20 -0700 Subject: [PATCH 47/51] [CardDatabaseModel] Pass CardInfoPtr by const ref (#6940) --- .../libcockatrice/models/database/card_database_model.cpp | 6 +++--- .../libcockatrice/models/database/card_database_model.h | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/libcockatrice_models/libcockatrice/models/database/card_database_model.cpp b/libcockatrice_models/libcockatrice/models/database/card_database_model.cpp index 5ef84a276..253dcd134 100644 --- a/libcockatrice_models/libcockatrice/models/database/card_database_model.cpp +++ b/libcockatrice_models/libcockatrice/models/database/card_database_model.cpp @@ -81,7 +81,7 @@ QVariant CardDatabaseModel::headerData(int section, Qt::Orientation orientation, } } -void CardDatabaseModel::cardInfoChanged(CardInfoPtr card) +void CardDatabaseModel::cardInfoChanged(const CardInfoPtr &card) { const int row = cardList.indexOf(card); if (row == -1) { @@ -91,7 +91,7 @@ void CardDatabaseModel::cardInfoChanged(CardInfoPtr card) emit dataChanged(index(row, 0), index(row, CARDDBMODEL_COLUMNS - 1)); } -bool CardDatabaseModel::checkCardHasAtLeastOneEnabledSet(CardInfoPtr card) +bool CardDatabaseModel::checkCardHasAtLeastOneEnabledSet(const CardInfoPtr &card) const { if (!showOnlyCardsFromEnabledSets) { return true; @@ -125,7 +125,7 @@ void CardDatabaseModel::cardDatabaseEnabledSetsChanged() } } -void CardDatabaseModel::cardAdded(CardInfoPtr card) +void CardDatabaseModel::cardAdded(const CardInfoPtr &card) { if (checkCardHasAtLeastOneEnabledSet(card)) { // add the card if it's present in at least one enabled set diff --git a/libcockatrice_models/libcockatrice/models/database/card_database_model.h b/libcockatrice_models/libcockatrice/models/database/card_database_model.h index 218cfff92..8655389d7 100644 --- a/libcockatrice_models/libcockatrice/models/database/card_database_model.h +++ b/libcockatrice_models/libcockatrice/models/database/card_database_model.h @@ -51,11 +51,11 @@ private: CardDatabase *db; bool showOnlyCardsFromEnabledSets; - inline bool checkCardHasAtLeastOneEnabledSet(CardInfoPtr card); + inline bool checkCardHasAtLeastOneEnabledSet(const CardInfoPtr &card) const; private slots: - void cardAdded(CardInfoPtr card); + void cardAdded(const CardInfoPtr &card); void cardRemoved(CardInfoPtr card); - void cardInfoChanged(CardInfoPtr card); + void cardInfoChanged(const CardInfoPtr &card); void cardDatabaseEnabledSetsChanged(); }; From 0d7047a7289f5a28ac5c97c2461544b10d91d9ce Mon Sep 17 00:00:00 2001 From: RickyRister <42636155+RickyRister@users.noreply.github.com> Date: Thu, 28 May 2026 02:05:26 -0700 Subject: [PATCH 48/51] [Game] Show color icons in counters menu (#6947) --- cockatrice/src/game/player/menu/card_menu.cpp | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/cockatrice/src/game/player/menu/card_menu.cpp b/cockatrice/src/game/player/menu/card_menu.cpp index 933f4094c..3b866d4e0 100644 --- a/cockatrice/src/game/player/menu/card_menu.cpp +++ b/cockatrice/src/game/player/menu/card_menu.cpp @@ -10,10 +10,27 @@ #include "move_menu.h" #include "pt_menu.h" +#include #include #include #include +/** + * @brief Creates a circular icon filled with the specified color. + */ +static QIcon createCircleIcon(const QColor &color) +{ + QPixmap pixmap(32, 32); + pixmap.fill(Qt::transparent); + QPainter painter(&pixmap); + painter.setRenderHint(QPainter::Antialiasing); + painter.setPen(Qt::NoPen); + painter.setBrush(color); + painter.drawEllipse(pixmap.rect()); + + return QIcon(pixmap); +} + CardMenu::CardMenu(PlayerLogic *_player, const CardItem *_card, bool _shortcutsActive) : player(_player), card(_card), shortcutsActive(_shortcutsActive) { @@ -77,9 +94,21 @@ CardMenu::CardMenu(PlayerLogic *_player, const CardItem *_card, bool _shortcutsA mCardCounters = new QMenu; for (int i = 0; i < 6; ++i) { + QColor color = SettingsCache::instance().cardCounters().color(i); + QIcon circleIcon = createCircleIcon(color); + auto *tempAddCounter = new QAction(this); + tempAddCounter->setIconVisibleInMenu(true); + tempAddCounter->setIcon(circleIcon); + auto *tempRemoveCounter = new QAction(this); + tempRemoveCounter->setIconVisibleInMenu(true); + tempRemoveCounter->setIcon(circleIcon); + auto *tempSetCounter = new QAction(this); + tempSetCounter->setIconVisibleInMenu(true); + tempSetCounter->setIcon(circleIcon); + aAddCounter.append(tempAddCounter); aRemoveCounter.append(tempRemoveCounter); aSetCounter.append(tempSetCounter); From c4f4cece01f5654bf9d6e08e69454545b2d5f9de Mon Sep 17 00:00:00 2001 From: RickyRister <42636155+RickyRister@users.noreply.github.com> Date: Thu, 28 May 2026 02:15:30 -0700 Subject: [PATCH 49/51] [Game] Show counter color icons in game log (#6948) --- cockatrice/src/game/log/message_log_widget.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/cockatrice/src/game/log/message_log_widget.cpp b/cockatrice/src/game/log/message_log_widget.cpp index fe564b531..906f15c2e 100644 --- a/cockatrice/src/game/log/message_log_widget.cpp +++ b/cockatrice/src/game/log/message_log_widget.cpp @@ -650,14 +650,16 @@ void MessageLogWidget::logSetCardCounter(PlayerLogic *player, QString cardName, QString finalStr; int delta = abs(oldValue - value); if (value > oldValue) { - finalStr = tr("%1 places %2 \"%3\" counter(s) on %4 (now %5).", "", delta); + finalStr = tr("%1 places %2 %3%4 counter(s) on %5 (now %6).", "", delta); } else { - finalStr = tr("%1 removes %2 \"%3\" counter(s) from %4 (now %5).", "", delta); + finalStr = tr("%1 removes %2 %3%4 counter(s) from %5 (now %6).", "", delta); } auto &cardCounterSettings = SettingsCache::instance().cardCounters(); + QString hex = cardCounterSettings.color(counterId).name(); appendHtmlServerMessage(finalStr.arg(sanitizeHtml(player->getPlayerInfo()->getName())) .arg("" + QString::number(delta) + "") + .arg("") .arg(cardCounterSettings.displayName(counterId)) .arg(cardLink(std::move(cardName))) .arg(value)); From 43c3bf59668c29ce794988cea46ddc07147dd325 Mon Sep 17 00:00:00 2001 From: RickyRister <42636155+RickyRister@users.noreply.github.com> Date: Thu, 28 May 2026 02:32:40 -0700 Subject: [PATCH 50/51] [Game][Arrow] Refactor: Rename arrow methods in GameScene (#6949) * [Game][Arrow] Rename methods in GameScene * move stuff around and docs --- cockatrice/src/game/game_scene.cpp | 42 +++++++++---------- cockatrice/src/game/game_scene.h | 14 ++++--- .../src/interface/widgets/tabs/tab_game.cpp | 6 +-- 3 files changed, 33 insertions(+), 29 deletions(-) diff --git a/cockatrice/src/game/game_scene.cpp b/cockatrice/src/game/game_scene.cpp index 9f466c2ac..d9ffe3443 100644 --- a/cockatrice/src/game/game_scene.cpp +++ b/cockatrice/src/game/game_scene.cpp @@ -88,16 +88,16 @@ void GameScene::addPlayer(PlayerLogic *player) connect(player, &PlayerLogic::concededChanged, this, [this](int id, bool conceded) { if (conceded) { - clearArrowsForPlayer(id); + requestClearArrowsForPlayer(id); } rearrange(); }); - connect(player, &PlayerLogic::arrowDeleted, this, &GameScene::onArrowDeleted); - connect(player, &PlayerLogic::arrowCreateRequested, this, &GameScene::onArrowCreateRequested); - connect(player, &PlayerLogic::arrowDeleteRequested, this, &GameScene::onArrowDeleteRequested); + connect(player, &PlayerLogic::arrowDeleted, this, &GameScene::deleteArrow); + connect(player, &PlayerLogic::arrowCreateRequested, this, &GameScene::addArrow); + connect(player, &PlayerLogic::arrowDeleteRequested, this, &GameScene::requestArrowDeletion); connect(player, &PlayerLogic::arrowsCleared, this, - [this, id = player->getPlayerInfo()->getId()]() { clearArrowsForPlayer(id); }); + [this, id = player->getPlayerInfo()->getId()]() { requestClearArrowsForPlayer(id); }); connect(player->getPlayerEventHandler(), &PlayerEventHandler::cardZoneChanged, this, &GameScene::onCardZoneChanged); @@ -114,7 +114,7 @@ void GameScene::removePlayer(PlayerLogic *player) { qCInfo(GameScenePlayerAdditionRemovalLog) << "GameScene::removePlayer name=" << player->getPlayerInfo()->getName(); - clearArrowsForPlayer(player->getPlayerInfo()->getId()); + requestClearArrowsForPlayer(player->getPlayerInfo()->getId()); for (ZoneViewWidget *zone : zoneViews) { if (zone->getPlayer() == player) { @@ -367,7 +367,7 @@ void GameScene::resizeColumnsAndPlayers(const QList &minWidthByColumn, qr } } -void GameScene::onArrowCreateRequested(const ArrowData &data) +void GameScene::addArrow(const ArrowData &data) { auto *startView = playerViews.value(data.startPlayerId); auto *targetView = playerViews.value(data.targetPlayerId); @@ -402,20 +402,29 @@ void GameScene::onArrowCreateRequested(const ArrowData &data) auto *arrow = new ArrowItem(startView->getPlayer(), data.id, startCard, targetItem, data.color); addItem(arrow); arrowRegistry.insert(data.id, arrow); - connect(arrow, &ArrowItem::requestDeletion, this, &GameScene::onArrowDeleteRequested); + connect(arrow, &ArrowItem::requestDeletion, this, &GameScene::requestArrowDeletion); } -void GameScene::onArrowDeleted(int arrowId) +void GameScene::deleteArrow(int arrowId) { if (arrowRegistry.contains(arrowId)) { arrowRegistry.take(arrowId)->delArrow(); } } -void GameScene::onArrowDeleteRequested(int arrowId) +void GameScene::requestArrowDeletion(int arrowId) { if (arrowRegistry.contains(arrowId)) { - emit requestArrowDeletion(arrowId); + emit arrowDeletionRequested(arrowId); + } +} + +void GameScene::requestClearArrowsForPlayer(int playerId) +{ + for (auto *arrow : arrowRegistry.values()) { + if (arrow->getPlayer()->getPlayerInfo()->getId() == playerId) { + emit requestArrowDeletion(arrow->getId()); + } } } @@ -432,16 +441,7 @@ void GameScene::onCardZoneChanged(CardItem *card, bool sameZone) } } for (auto *arrow : toDelete) { - onArrowDeleted(arrow->getId()); - } -} - -void GameScene::clearArrowsForPlayer(int playerId) -{ - for (auto *arrow : arrowRegistry.values()) { - if (arrow->getPlayer()->getPlayerInfo()->getId() == playerId) { - emit requestArrowDeletion(arrow->getId()); - } + deleteArrow(arrow->getId()); } } diff --git a/cockatrice/src/game/game_scene.h b/cockatrice/src/game/game_scene.h index 235ce6550..70dbfb3d9 100644 --- a/cockatrice/src/game/game_scene.h +++ b/cockatrice/src/game/game_scene.h @@ -201,11 +201,15 @@ public slots: QTransform getViewTransform() const; QTransform getViewportTransform() const; - void onArrowCreateRequested(const ArrowData &data); - void onArrowDeleted(int arrowId); - void onArrowDeleteRequested(int arrowId); + /// Directly modifies the scene + void addArrow(const ArrowData &data); + void deleteArrow(int arrowId); + + /// Queues up arrow deletion but doesn't directly modify the scene + void requestArrowDeletion(int arrowId); + void requestClearArrowsForPlayer(int playerId); + void onCardZoneChanged(CardItem *card, bool sameZone); - void clearArrowsForPlayer(int playerId); protected: /** @brief Handles hover updates. */ @@ -218,7 +222,7 @@ signals: void sigStartRubberBand(const QPointF &selectionOrigin); void sigResizeRubberBand(const QPointF &cursorPoint, int selectedCount); void sigStopRubberBand(); - void requestArrowDeletion(int arrowId); + void arrowDeletionRequested(int arrowId); }; #endif diff --git a/cockatrice/src/interface/widgets/tabs/tab_game.cpp b/cockatrice/src/interface/widgets/tabs/tab_game.cpp index 3da3685dd..9fc123a8c 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_game.cpp +++ b/cockatrice/src/interface/widgets/tabs/tab_game.cpp @@ -608,7 +608,7 @@ void TabGame::actRemoveLocalArrows() { auto *local = game->getPlayerManager()->getActiveLocalPlayer(game->getGameState()->getActivePlayer()); if (local) { - scene->clearArrowsForPlayer(local->getPlayerInfo()->getId()); + scene->requestClearArrowsForPlayer(local->getPlayerInfo()->getId()); } } @@ -1150,9 +1150,9 @@ void TabGame::createPlayAreaWidget(bool bReplay) scene = new GameScene(phasesToolbar, this); connect(game->getPlayerManager(), &PlayerManager::playerConceded, scene, &GameScene::rearrange); connect(game->getPlayerManager(), &PlayerManager::playerCountChanged, scene, &GameScene::rearrange); - connect(scene, &GameScene::requestArrowDeletion, game->getGameEventHandler(), + connect(scene, &GameScene::arrowDeletionRequested, game->getGameEventHandler(), &GameEventHandler::handleArrowDeletion); - connect(game->getGameEventHandler(), &GameEventHandler::arrowDeleted, scene, &GameScene::onArrowDeleted); + connect(game->getGameEventHandler(), &GameEventHandler::arrowDeleted, scene, &GameScene::deleteArrow); gameView = new GameView(scene); auto gamePlayAreaVBox = new QVBoxLayout; From 6de55e90968f2c51f411a8682d0647c547a1706b Mon Sep 17 00:00:00 2001 From: RickyRister <42636155+RickyRister@users.noreply.github.com> Date: Thu, 28 May 2026 23:51:12 -0700 Subject: [PATCH 51/51] [Game][Arrow] Correctly call clear all arrows for player (#6951) --- cockatrice/src/game/game_scene.cpp | 21 ++++++++++++++++++--- cockatrice/src/game/game_scene.h | 1 + 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/cockatrice/src/game/game_scene.cpp b/cockatrice/src/game/game_scene.cpp index d9ffe3443..1b4f0d461 100644 --- a/cockatrice/src/game/game_scene.cpp +++ b/cockatrice/src/game/game_scene.cpp @@ -88,7 +88,7 @@ void GameScene::addPlayer(PlayerLogic *player) connect(player, &PlayerLogic::concededChanged, this, [this](int id, bool conceded) { if (conceded) { - requestClearArrowsForPlayer(id); + clearArrowsForPlayer(id); } rearrange(); }); @@ -97,7 +97,7 @@ void GameScene::addPlayer(PlayerLogic *player) connect(player, &PlayerLogic::arrowCreateRequested, this, &GameScene::addArrow); connect(player, &PlayerLogic::arrowDeleteRequested, this, &GameScene::requestArrowDeletion); connect(player, &PlayerLogic::arrowsCleared, this, - [this, id = player->getPlayerInfo()->getId()]() { requestClearArrowsForPlayer(id); }); + [this, id = player->getPlayerInfo()->getId()]() { clearArrowsForPlayer(id); }); connect(player->getPlayerEventHandler(), &PlayerEventHandler::cardZoneChanged, this, &GameScene::onCardZoneChanged); @@ -114,7 +114,7 @@ void GameScene::removePlayer(PlayerLogic *player) { qCInfo(GameScenePlayerAdditionRemovalLog) << "GameScene::removePlayer name=" << player->getPlayerInfo()->getName(); - requestClearArrowsForPlayer(player->getPlayerInfo()->getId()); + clearArrowsForPlayer(player->getPlayerInfo()->getId()); for (ZoneViewWidget *zone : zoneViews) { if (zone->getPlayer() == player) { @@ -412,6 +412,21 @@ void GameScene::deleteArrow(int arrowId) } } +void GameScene::clearArrowsForPlayer(int playerId) +{ + QList toDelete; + for (auto i = arrowRegistry.cbegin(); i != arrowRegistry.cend(); ++i) { + auto *arrow = i.value(); + if (arrow->getPlayer()->getPlayerInfo()->getId() == playerId) { + toDelete.append(i.key()); + } + } + + for (int arrowId : toDelete) { + arrowRegistry.take(arrowId)->delArrow(); + } +} + void GameScene::requestArrowDeletion(int arrowId) { if (arrowRegistry.contains(arrowId)) { diff --git a/cockatrice/src/game/game_scene.h b/cockatrice/src/game/game_scene.h index 70dbfb3d9..1551c8365 100644 --- a/cockatrice/src/game/game_scene.h +++ b/cockatrice/src/game/game_scene.h @@ -204,6 +204,7 @@ public slots: /// Directly modifies the scene void addArrow(const ArrowData &data); void deleteArrow(int arrowId); + void clearArrowsForPlayer(int playerId); /// Queues up arrow deletion but doesn't directly modify the scene void requestArrowDeletion(int arrowId);