mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-11-09 03:23:24 -08:00
* [Game] Raise rubber band above count label and collapse multi-selection on click Raise rubber band on start and collapse multi-selection to clicked card when left-clicking an already-selected card with no modifiers. * [Game] Collapse multi-selection on release instead of press Collapsing at press time dropped the selection before the drag started, which broke dragging multiple cards. Keep the selection on press and collapse it on release when the pointer stayed within the drag distance. * [Game] Defer selection collapse until the double-click window passes A release without drag collapsed the multi-selection immediately, so a double-click that followed (playSelected acts on scene()->selectedItems()) only ever saw the single clicked card. When the card handles double-clicks on the selection, arm the collapse on a single-shot timer for QApplication::doubleClickInterval() instead and cancel it from the double-click handler; a new press disarms the other cards and a selection-count guard covers rubber-band/ctrl changes meanwhile. * [Game] Keep sideboard multi-selection on double-click DeckViewCard overrides doubleClickActsOnSelection to preserve the selection, restoring master behavior where double-clicking moves all selected cards between main and side. DeckView cancels any pending collapse before reading the selection. * [Game] Remove duplicated inline selection-collapse declarations * [Game] Fix DeckView collapse call visibility and multi-selection collapse Make cancelPendingSelectionCollapse() public so DeckView can call it on selected DeckViewCards. Always arm the deferred collapse on release instead of skipping cards whose double-click acts on the selection; the double-click-interval timer plus the cancel calls in CardItem::mouseDoubleClickEvent and DeckView::mouseDoubleClickEvent already preserve the selection for double-clicks. --------- Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
181 lines
5 KiB
C++
181 lines
5 KiB
C++
/**
|
|
* @file card_item.h
|
|
* @ingroup GameGraphicsCards
|
|
*/
|
|
//! \todo Document this file.
|
|
|
|
#ifndef CARDITEM_H
|
|
#define CARDITEM_H
|
|
|
|
#include "../../game/board/card_state.h"
|
|
#include "abstract_card_item.h"
|
|
#include "graphics_item_type.h"
|
|
|
|
#include <QList>
|
|
#include <QPoint>
|
|
#include <QPointF>
|
|
#include <QString>
|
|
#include <QVariantList>
|
|
#include <qtmetamacros.h>
|
|
|
|
class CardDragItem;
|
|
class ServerInfo_Card;
|
|
class PlayerLogic;
|
|
class QColor;
|
|
class CardZoneLogic;
|
|
class QGraphicsItem;
|
|
struct CardRef;
|
|
template <class Key, class T> class QMap;
|
|
|
|
const int ROTATION_DEGREES_PER_FRAME = 10;
|
|
|
|
class CardItem : public AbstractCardItem
|
|
{
|
|
Q_OBJECT
|
|
private:
|
|
CardState *state;
|
|
|
|
QPoint gridPoint;
|
|
CardDragItem *dragItem;
|
|
QList<CardItem *> attachedCards;
|
|
|
|
void prepareDelete();
|
|
void handleClickedToPlay(bool shiftHeld);
|
|
public slots:
|
|
void deleteLater();
|
|
|
|
public:
|
|
enum
|
|
{
|
|
Type = typeCard
|
|
};
|
|
[[nodiscard]] int type() const override
|
|
{
|
|
return Type;
|
|
}
|
|
explicit CardItem(PlayerLogic *_owner,
|
|
QGraphicsItem *parent = nullptr,
|
|
const CardRef &cardRef = {},
|
|
int _cardid = -1,
|
|
CardZoneLogic *_zone = nullptr);
|
|
|
|
void retranslateUi();
|
|
[[nodiscard]] CardState *getState() const
|
|
{
|
|
return state;
|
|
}
|
|
[[nodiscard]] CardZoneLogic *getZone() const
|
|
{
|
|
return state->getZone();
|
|
}
|
|
void setZone(CardZoneLogic *_zone);
|
|
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
|
|
[[nodiscard]] QPoint getGridPoint() const
|
|
{
|
|
return gridPoint;
|
|
}
|
|
void setGridPoint(const QPoint &_gridPoint)
|
|
{
|
|
gridPoint = _gridPoint;
|
|
}
|
|
[[nodiscard]] QPoint getGridPos() const
|
|
{
|
|
return gridPoint;
|
|
}
|
|
[[nodiscard]] PlayerLogic *getOwner() const
|
|
{
|
|
return owner;
|
|
}
|
|
void setOwner(PlayerLogic *_owner)
|
|
{
|
|
owner = _owner;
|
|
}
|
|
[[nodiscard]] bool getAttacking() const
|
|
{
|
|
return state->getAttacking();
|
|
}
|
|
void setAttacking(bool _attacking);
|
|
[[nodiscard]] const QMap<int, int> &getCounters() const
|
|
{
|
|
return state->getCounters();
|
|
}
|
|
void setCounter(int _id, int _value);
|
|
[[nodiscard]] QString getAnnotation() const
|
|
{
|
|
return state->getAnnotation();
|
|
}
|
|
void setAnnotation(const QString &_annotation);
|
|
[[nodiscard]] bool getDoesntUntap() const
|
|
{
|
|
return state->getDoesntUntap();
|
|
}
|
|
void setDoesntUntap(bool _doesntUntap);
|
|
[[nodiscard]] QString getPT() const
|
|
{
|
|
return state->getPT();
|
|
}
|
|
void setPT(const QString &_pt);
|
|
[[nodiscard]] bool getDestroyOnZoneChange() const
|
|
{
|
|
return state->getDestroyOnZoneChange();
|
|
}
|
|
void setDestroyOnZoneChange(bool _destroy)
|
|
{
|
|
state->setDestroyOnZoneChange(_destroy);
|
|
}
|
|
[[nodiscard]] CardItem *getAttachedTo() const
|
|
{
|
|
return state->getAttachedTo();
|
|
}
|
|
void setAttachedTo(CardItem *_attachedTo);
|
|
void addAttachedCard(CardItem *card)
|
|
{
|
|
attachedCards.append(card);
|
|
}
|
|
void removeAttachedCard(CardItem *card)
|
|
{
|
|
attachedCards.removeOne(card);
|
|
}
|
|
[[nodiscard]] const QList<CardItem *> &getAttachedCards() const
|
|
{
|
|
return attachedCards;
|
|
}
|
|
void resetState(bool keepAnnotations = false);
|
|
void processCardInfo(const ServerInfo_Card &_info);
|
|
|
|
bool animationEvent() override;
|
|
CardDragItem *createDragItem(int _id, const QPointF &_pos, const QPointF &_scenePos, bool forceFaceDown);
|
|
void deleteDragItem();
|
|
void drawArrow(const QColor &arrowColor);
|
|
void drawAttachArrow();
|
|
void playCard(bool faceDown);
|
|
|
|
/**
|
|
* @brief Parses a string representing a p/t in order to extract the values from it.
|
|
*
|
|
* If the string contains '/', the string will be split at the '/' and each side will be parsed separately,
|
|
* which means the result list will have two elements.
|
|
*
|
|
* If '/' is not found, then the entire string is parsed together, which means the result list will
|
|
* have a single element.
|
|
*
|
|
* If either side of the split is empty, there will also only be a single element in the result list.
|
|
*
|
|
* This function will attempt to parse each substring as an int first, handling plus and minus prefixes.
|
|
* If successful, it will put the parsed value into the QVariant as an int.
|
|
* If failed, it will just put the substring into the QVariant as a QString.
|
|
*
|
|
* @param pt The p/t string
|
|
* @return A QVariantList that can contain one or two elements, where each QVariant can be either int or QString
|
|
*/
|
|
static QVariantList parsePT(const QString &pt);
|
|
|
|
protected:
|
|
void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override;
|
|
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
|
|
void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) override;
|
|
QVariant itemChange(GraphicsItemChange change, const QVariant &value) override;
|
|
bool doubleClickActsOnSelection() const override;
|
|
};
|
|
|
|
#endif
|