mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-11-08 02:53:25 -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>
607 lines
19 KiB
C++
607 lines
19 KiB
C++
#include "deck_view.h"
|
|
|
|
#include "../../client/settings/cache_settings.h"
|
|
#include "../../interface/theme_manager.h"
|
|
#include "../board/abstract_card_drag_item.h"
|
|
#include "../card_dimensions.h"
|
|
#include "libcockatrice/card/printing/exact_card.h"
|
|
#include "libcockatrice/deck_list/tree/deck_list_card_node.h"
|
|
#include "libcockatrice/deck_list/tree/inner_deck_list_node.h"
|
|
#include "libcockatrice/protocol/pb/move_card_to_zone.pb.h"
|
|
|
|
#include <QApplication>
|
|
#include <QBrush>
|
|
#include <QColor>
|
|
#include <QCursor>
|
|
#include <QFlags>
|
|
#include <QFont>
|
|
#include <QFontMetrics>
|
|
#include <QGraphicsSceneHoverEvent>
|
|
#include <QGraphicsSceneMouseEvent>
|
|
#include <QMapIterator>
|
|
#include <QMouseEvent>
|
|
#include <QPainter>
|
|
#include <QPen>
|
|
#include <QPoint>
|
|
#include <QSet>
|
|
#include <QSharedPointer>
|
|
#include <QSize>
|
|
#include <QStringList>
|
|
#include <QtGlobal>
|
|
#include <QtMath>
|
|
#include <algorithm>
|
|
#include <compare>
|
|
#include <libcockatrice/card/card_info.h>
|
|
#include <libcockatrice/deck_list/deck_list.h>
|
|
#include <libcockatrice/settings/cards_display_settings.h>
|
|
#include <libcockatrice/utility/card_ref.h>
|
|
#include <qnamespace.h>
|
|
#include <string>
|
|
#include <utility>
|
|
|
|
class QObject;
|
|
class QRectF;
|
|
class QWidget;
|
|
struct CardRef;
|
|
|
|
DeckViewCardDragItem::DeckViewCardDragItem(DeckViewCard *_item,
|
|
const QPointF &_hotSpot,
|
|
AbstractCardDragItem *parentDrag)
|
|
: AbstractCardDragItem(_item, _hotSpot, parentDrag), currentZone(0)
|
|
{
|
|
}
|
|
|
|
void DeckViewCardDragItem::updatePosition(const QPointF &cursorScenePos)
|
|
{
|
|
QList<QGraphicsItem *> colliding = scene()->items(cursorScenePos);
|
|
|
|
DeckViewCardContainer *cursorZone = 0;
|
|
for (int i = colliding.size() - 1; i >= 0; i--) {
|
|
if ((cursorZone = qgraphicsitem_cast<DeckViewCardContainer *>(colliding.at(i)))) {
|
|
break;
|
|
}
|
|
}
|
|
if (!cursorZone) {
|
|
return;
|
|
}
|
|
currentZone = cursorZone;
|
|
|
|
QPointF newPos = cursorScenePos;
|
|
if (newPos != pos()) {
|
|
for (int i = 0; i < childDrags.size(); i++) {
|
|
childDrags[i]->setPos(newPos + childDrags[i]->getHotSpot());
|
|
}
|
|
setPos(newPos);
|
|
}
|
|
}
|
|
|
|
void DeckViewCardDragItem::handleDrop(DeckViewCardContainer *target)
|
|
{
|
|
auto *card = static_cast<DeckViewCard *>(item);
|
|
auto *start = static_cast<DeckViewCardContainer *>(item->parentItem());
|
|
start->removeCard(card);
|
|
target->addCard(card);
|
|
card->setParentItem(target);
|
|
}
|
|
|
|
void DeckViewCardDragItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
|
{
|
|
setCursor(Qt::OpenHandCursor);
|
|
auto *sc = static_cast<DeckViewScene *>(scene());
|
|
sc->removeItem(this);
|
|
|
|
if (currentZone) {
|
|
handleDrop(currentZone);
|
|
for (int i = 0; i < childDrags.size(); i++) {
|
|
auto *c = static_cast<DeckViewCardDragItem *>(childDrags[i]);
|
|
c->handleDrop(currentZone);
|
|
sc->removeItem(c);
|
|
}
|
|
|
|
sc->updateContents();
|
|
}
|
|
|
|
event->accept();
|
|
}
|
|
|
|
DeckViewCard::DeckViewCard(QGraphicsItem *parent, const CardRef &cardRef, const QString &_originZone)
|
|
: AbstractCardItem(parent, cardRef, 0, -1), originZone(_originZone), dragItem(0)
|
|
{
|
|
setAcceptHoverEvents(true);
|
|
|
|
connect(&SettingsCache::instance().cardsDisplay(), &CardsDisplaySettings::roundCardCornersChanged, this,
|
|
[this](bool _roundCardCorners) {
|
|
Q_UNUSED(_roundCardCorners);
|
|
|
|
update();
|
|
});
|
|
}
|
|
|
|
DeckViewCard::~DeckViewCard()
|
|
{
|
|
delete dragItem;
|
|
}
|
|
|
|
void DeckViewCard::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
|
|
{
|
|
AbstractCardItem::paint(painter, option, widget);
|
|
|
|
painter->save();
|
|
QPen pen;
|
|
pen.setWidth(3);
|
|
pen.setJoinStyle(Qt::MiterJoin);
|
|
pen.setColor(originZone == DECK_ZONE_MAIN ? Qt::green : Qt::red);
|
|
painter->setPen(pen);
|
|
qreal cardRadius =
|
|
SettingsCache::instance().cardsDisplay().getRoundCardCorners() ? 0.05 * (CardDimensions::WIDTH_F - 3) : 0.0;
|
|
painter->drawRoundedRect(QRectF(1.5, 1.5, CardDimensions::WIDTH_F - 3, CardDimensions::HEIGHT_F - 3), cardRadius,
|
|
cardRadius);
|
|
painter->restore();
|
|
}
|
|
|
|
void DeckViewCard::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
|
{
|
|
if ((event->screenPos() - event->buttonDownScreenPos(Qt::LeftButton)).manhattanLength() <
|
|
2 * QApplication::startDragDistance()) {
|
|
return;
|
|
}
|
|
|
|
if (static_cast<DeckViewScene *>(scene())->getLocked()) {
|
|
return;
|
|
}
|
|
|
|
delete dragItem;
|
|
dragItem = new DeckViewCardDragItem(this, event->pos());
|
|
scene()->addItem(dragItem);
|
|
dragItem->updatePosition(event->scenePos());
|
|
dragItem->grabMouse();
|
|
|
|
QList<QGraphicsItem *> sel = scene()->selectedItems();
|
|
int j = 0;
|
|
for (int i = 0; i < sel.size(); i++) {
|
|
auto *c = static_cast<DeckViewCard *>(sel.at(i));
|
|
if (c == this) {
|
|
continue;
|
|
}
|
|
++j;
|
|
auto childPos = QPointF(j * CardDimensions::WIDTH_HALF_F, 0);
|
|
auto *drag = new DeckViewCardDragItem(c, childPos, dragItem);
|
|
drag->setPos(dragItem->pos() + childPos);
|
|
scene()->addItem(drag);
|
|
}
|
|
setCursor(Qt::OpenHandCursor);
|
|
}
|
|
|
|
void DeckView::mouseDoubleClickEvent(QMouseEvent *event)
|
|
{
|
|
if (static_cast<DeckViewScene *>(scene())->getLocked()) {
|
|
return;
|
|
}
|
|
|
|
if (event->button() == Qt::LeftButton) {
|
|
QList<MoveCard_ToZone> result;
|
|
QList<QGraphicsItem *> sel = scene()->selectedItems();
|
|
|
|
// The double-click goes to the view, not the card, so cancel any pending
|
|
// selection collapse on the cards before reading the selection.
|
|
for (auto *item : sel) {
|
|
if (auto *c = dynamic_cast<DeckViewCard *>(item)) {
|
|
c->cancelPendingSelectionCollapse();
|
|
}
|
|
}
|
|
sel = scene()->selectedItems();
|
|
|
|
for (int i = 0; i < sel.size(); i++) {
|
|
auto *c = static_cast<DeckViewCard *>(sel.at(i));
|
|
auto *zone = static_cast<DeckViewCardContainer *>(c->parentItem());
|
|
MoveCard_ToZone m;
|
|
m.set_card_name(c->getName().toStdString());
|
|
m.set_start_zone(zone->getName().toStdString());
|
|
|
|
if (zone->getName() == DECK_ZONE_MAIN) {
|
|
m.set_target_zone(DECK_ZONE_SIDE);
|
|
} else if (zone->getName() == DECK_ZONE_SIDE) {
|
|
m.set_target_zone(DECK_ZONE_MAIN);
|
|
} else { // Trying to move from another zone
|
|
m.set_target_zone(zone->getName().toStdString());
|
|
}
|
|
|
|
result.append(m);
|
|
}
|
|
|
|
deckViewScene->applySideboardPlan(result);
|
|
deckViewScene->rearrangeItems();
|
|
emit deckViewScene->sideboardPlanChanged();
|
|
}
|
|
}
|
|
|
|
void DeckViewCard::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
|
|
{
|
|
event->accept();
|
|
processHoverEvent();
|
|
}
|
|
|
|
DeckViewCardContainer::DeckViewCardContainer(const QString &_name) : QGraphicsItem(), name(_name), width(0), height(0)
|
|
{
|
|
setCacheMode(DeviceCoordinateCache);
|
|
}
|
|
|
|
QRectF DeckViewCardContainer::boundingRect() const
|
|
{
|
|
return QRectF(0, 0, width, height);
|
|
}
|
|
|
|
void DeckViewCardContainer::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*option*/, QWidget * /*widget*/)
|
|
{
|
|
qreal totalTextWidth = getCardTypeTextWidth();
|
|
|
|
painter->fillRect(boundingRect(), themeManager->getBgBrush(ThemeManager::Table));
|
|
painter->setPen(QColor(255, 255, 255, 100));
|
|
painter->drawLine(QPointF(0, separatorY), QPointF(width, separatorY));
|
|
|
|
painter->setPen(QColor(Qt::white));
|
|
QFont f("Serif");
|
|
f.setStyleHint(QFont::Serif);
|
|
f.setPixelSize(24);
|
|
f.setWeight(QFont::Bold);
|
|
painter->setFont(f);
|
|
painter->drawText(10, 0, width - 20, separatorY, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextSingleLine,
|
|
InnerDecklistNode::visibleNameFromName(name) + QString(": %1").arg(cards.size()));
|
|
|
|
f.setPixelSize(16);
|
|
painter->setFont(f);
|
|
QList<QString> cardTypeList = cardsByType.uniqueKeys();
|
|
qreal yUntilNow = separatorY + paddingY;
|
|
for (int i = 0; i < cardTypeList.size(); ++i) {
|
|
if (i != 0) {
|
|
painter->setPen(QColor(255, 255, 255, 100));
|
|
painter->drawLine(QPointF(0, yUntilNow - paddingY / 2), QPointF(width, yUntilNow - paddingY / 2));
|
|
}
|
|
qreal thisRowHeight = CardDimensions::HEIGHT_F * currentRowsAndCols[i].first;
|
|
QRectF textRect(0, yUntilNow, totalTextWidth, thisRowHeight);
|
|
yUntilNow += thisRowHeight + paddingY;
|
|
|
|
QString displayString = QString("%1\n(%2)").arg(cardTypeList[i]).arg(cardsByType.count(cardTypeList[i]));
|
|
|
|
painter->setPen(Qt::white);
|
|
painter->drawText(textRect, Qt::AlignHCenter | Qt::AlignVCenter, displayString);
|
|
}
|
|
}
|
|
|
|
void DeckViewCardContainer::addCard(DeckViewCard *card)
|
|
{
|
|
cards.append(card);
|
|
cardsByType.insert(card->getCard().isEmpty() ? "" : card->getCardInfo().getMainCardType(), card);
|
|
}
|
|
|
|
void DeckViewCardContainer::removeCard(DeckViewCard *card)
|
|
{
|
|
cards.removeOne(card);
|
|
cardsByType.remove(card->getCard().isEmpty() ? "" : card->getCardInfo().getMainCardType(), card);
|
|
}
|
|
|
|
QList<QPair<int, int>> DeckViewCardContainer::getRowsAndCols() const
|
|
{
|
|
QList<QPair<int, int>> result;
|
|
QList<QString> cardTypeList = cardsByType.uniqueKeys();
|
|
for (int i = 0; i < cardTypeList.size(); ++i) {
|
|
result.append(QPair<int, int>(1, cardsByType.count(cardTypeList[i])));
|
|
}
|
|
return result;
|
|
}
|
|
|
|
int DeckViewCardContainer::getCardTypeTextWidth() const
|
|
{
|
|
QFont f("Serif");
|
|
f.setStyleHint(QFont::Serif);
|
|
f.setPixelSize(16);
|
|
f.setWeight(QFont::Bold);
|
|
QFontMetrics fm(f);
|
|
|
|
int maxCardTypeWidth = 0;
|
|
for (const auto &key : cardsByType.keys()) {
|
|
int cardTypeWidth = fm.size(Qt::TextSingleLine, key).width();
|
|
maxCardTypeWidth = qMax(maxCardTypeWidth, cardTypeWidth);
|
|
}
|
|
|
|
return maxCardTypeWidth + 15;
|
|
}
|
|
|
|
QSizeF DeckViewCardContainer::calculateBoundingRect(const QList<QPair<int, int>> &rowsAndCols) const
|
|
{
|
|
qreal totalHeight = 0;
|
|
qreal totalWidth = 0;
|
|
|
|
// 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) {
|
|
totalWidth = CardDimensions::WIDTH_F * rowsAndCols[i].second;
|
|
}
|
|
}
|
|
|
|
return QSizeF(getCardTypeTextWidth() + totalWidth, totalHeight + separatorY + paddingY);
|
|
}
|
|
|
|
bool DeckViewCardContainer::sortCardsByName(DeckViewCard *c1, DeckViewCard *c2)
|
|
{
|
|
if (c1 && c2) {
|
|
return c1->getName() < c2->getName();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void DeckViewCardContainer::rearrangeItems(const QList<QPair<int, int>> &rowsAndCols)
|
|
{
|
|
currentRowsAndCols = rowsAndCols;
|
|
|
|
qreal yUntilNow = separatorY + paddingY;
|
|
qreal x = (qreal)getCardTypeTextWidth();
|
|
for (int i = 0; i < rowsAndCols.size(); ++i) {
|
|
const int tempRows = rowsAndCols[i].first;
|
|
const int tempCols = rowsAndCols[i].second;
|
|
QList<QString> cardTypeList = cardsByType.uniqueKeys();
|
|
QList<DeckViewCard *> row = cardsByType.values(cardTypeList[i]);
|
|
std::sort(row.begin(), row.end(), DeckViewCardContainer::sortCardsByName);
|
|
for (int j = 0; j < row.size(); ++j) {
|
|
DeckViewCard *card = row[j];
|
|
card->setPos(x + (j % tempCols) * CardDimensions::WIDTH_F,
|
|
yUntilNow + (j / tempCols) * CardDimensions::HEIGHT_F);
|
|
}
|
|
yUntilNow += tempRows * CardDimensions::HEIGHT_F + paddingY;
|
|
}
|
|
|
|
prepareGeometryChange();
|
|
QSizeF bRect = calculateBoundingRect(rowsAndCols);
|
|
width = bRect.width();
|
|
height = bRect.height();
|
|
}
|
|
|
|
void DeckViewCardContainer::setWidth(qreal _width)
|
|
{
|
|
prepareGeometryChange();
|
|
width = _width;
|
|
update();
|
|
}
|
|
|
|
DeckViewScene::DeckViewScene(QObject *parent) : QGraphicsScene(parent), locked(true), deck(0), optimalAspectRatio(1.0)
|
|
{
|
|
}
|
|
|
|
DeckViewScene::~DeckViewScene()
|
|
{
|
|
clearContents();
|
|
delete deck;
|
|
}
|
|
|
|
void DeckViewScene::clearContents()
|
|
{
|
|
QMapIterator<QString, DeckViewCardContainer *> i(cardContainers);
|
|
while (i.hasNext()) {
|
|
delete i.next().value();
|
|
}
|
|
cardContainers.clear();
|
|
}
|
|
|
|
void DeckViewScene::setDeck(const DeckList &_deck)
|
|
{
|
|
if (deck) {
|
|
delete deck;
|
|
}
|
|
|
|
deck = new DeckList(_deck.writeToString_Native());
|
|
rebuildTree();
|
|
applySideboardPlan(deck->getCurrentSideboardPlan());
|
|
rearrangeItems();
|
|
}
|
|
|
|
void DeckViewScene::rebuildTree()
|
|
{
|
|
clearContents();
|
|
|
|
if (!deck) {
|
|
return;
|
|
}
|
|
|
|
QStringList requiredZones = {DECK_ZONE_MAIN, DECK_ZONE_SIDE};
|
|
|
|
for (const QString &zoneName : requiredZones) {
|
|
if (!cardContainers.contains(zoneName)) {
|
|
auto *container = new DeckViewCardContainer(zoneName);
|
|
cardContainers.insert(zoneName, container);
|
|
addItem(container);
|
|
}
|
|
}
|
|
|
|
for (auto *currentZone : deck->getZoneNodes()) {
|
|
DeckViewCardContainer *container = cardContainers.value(currentZone->getName(), 0);
|
|
if (!container) {
|
|
container = new DeckViewCardContainer(currentZone->getName());
|
|
cardContainers.insert(currentZone->getName(), container);
|
|
addItem(container);
|
|
}
|
|
|
|
// Cards in custom zones nested under a board are regular board cards in-game.
|
|
// They are collected recursively (like every other consumer) and reported with
|
|
// the top-level board zone as their origin, so that sideboard plans keep working.
|
|
for (auto *currentCard : deck->getCardNodes({currentZone->getName()})) {
|
|
for (int k = 0; k < currentCard->getNumber(); ++k) {
|
|
auto *newCard = new DeckViewCard(container, currentCard->toCardRef(), currentZone->getName());
|
|
container->addCard(newCard);
|
|
emit newCardAdded(newCard);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void DeckViewScene::applySideboardPlan(const QList<MoveCard_ToZone> &plan)
|
|
{
|
|
for (int i = 0; i < plan.size(); ++i) {
|
|
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) {
|
|
continue;
|
|
}
|
|
|
|
DeckViewCard *card = 0;
|
|
const QList<DeckViewCard *> &cardList = start->getCards();
|
|
for (int j = 0; j < cardList.size(); ++j) {
|
|
if (cardList[j]->getName() == QString::fromStdString(m.card_name())) {
|
|
card = cardList[j];
|
|
break;
|
|
}
|
|
}
|
|
if (!card) {
|
|
continue;
|
|
}
|
|
|
|
start->removeCard(card);
|
|
target->addCard(card);
|
|
card->setParentItem(target);
|
|
}
|
|
}
|
|
|
|
void DeckViewScene::rearrangeItems()
|
|
{
|
|
const int spacing = CardDimensions::HEIGHT / 3;
|
|
QList<DeckViewCardContainer *> contList = cardContainers.values();
|
|
|
|
// Initialize space requirements
|
|
QList<QList<QPair<int, int>>> rowsAndColsList;
|
|
QList<QList<int>> cardCountList;
|
|
for (int i = 0; i < contList.size(); ++i) {
|
|
QList<QPair<int, int>> rowsAndCols = contList[i]->getRowsAndCols();
|
|
rowsAndColsList.append(rowsAndCols);
|
|
|
|
cardCountList.append(QList<int>());
|
|
for (int j = 0; j < rowsAndCols.size(); ++j) {
|
|
cardCountList[i].append(rowsAndCols[j].second);
|
|
}
|
|
}
|
|
|
|
qreal totalHeight, totalWidth;
|
|
for (;;) {
|
|
// Calculate total size before this iteration
|
|
totalHeight = -spacing;
|
|
totalWidth = 0;
|
|
for (int i = 0; i < contList.size(); ++i) {
|
|
QSizeF contSize = contList[i]->calculateBoundingRect(rowsAndColsList[i]);
|
|
totalHeight += contSize.height() + spacing;
|
|
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) {
|
|
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) {
|
|
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;
|
|
const int maxCardCount = cardCountList[maxIndex1][maxIndex2];
|
|
rowsAndColsList[maxIndex1][maxIndex2] =
|
|
QPair<int, int>(maxRows + 1, (int)qCeil((qreal)maxCardCount / (qreal)(maxRows + 1)));
|
|
}
|
|
|
|
totalHeight = -spacing;
|
|
for (int i = 0; i < contList.size(); ++i) {
|
|
DeckViewCardContainer *c = contList[i];
|
|
c->rearrangeItems(rowsAndColsList[i]);
|
|
c->setPos(0, totalHeight + spacing);
|
|
totalHeight += c->boundingRect().height() + spacing;
|
|
}
|
|
|
|
totalWidth = totalHeight * optimalAspectRatio;
|
|
for (int i = 0; i < contList.size(); ++i) {
|
|
contList[i]->setWidth(totalWidth);
|
|
}
|
|
|
|
setSceneRect(QRectF(0, 0, totalWidth, totalHeight));
|
|
}
|
|
|
|
void DeckViewScene::updateContents()
|
|
{
|
|
rearrangeItems();
|
|
emit sideboardPlanChanged();
|
|
}
|
|
|
|
QList<MoveCard_ToZone> DeckViewScene::getSideboardPlan() const
|
|
{
|
|
QList<MoveCard_ToZone> result;
|
|
QMapIterator<QString, DeckViewCardContainer *> containerIterator(cardContainers);
|
|
while (containerIterator.hasNext()) {
|
|
DeckViewCardContainer *cont = containerIterator.next().value();
|
|
const QList<DeckViewCard *> cardList = cont->getCards();
|
|
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());
|
|
m.set_start_zone(cardList[i]->getOriginZone().toStdString());
|
|
m.set_target_zone(cont->getName().toStdString());
|
|
result.append(m);
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
void DeckViewScene::resetSideboardPlan()
|
|
{
|
|
rebuildTree();
|
|
rearrangeItems();
|
|
}
|
|
|
|
DeckView::DeckView(QWidget *parent) : QGraphicsView(parent)
|
|
{
|
|
deckViewScene = new DeckViewScene(this);
|
|
|
|
setBackgroundBrush(QBrush(QColor(0, 0, 0)));
|
|
setDragMode(RubberBandDrag);
|
|
setRenderHints(QPainter::TextAntialiasing | QPainter::Antialiasing /* | QPainter::SmoothPixmapTransform*/);
|
|
setScene(deckViewScene);
|
|
|
|
connect(deckViewScene, &DeckViewScene::sceneRectChanged, this, &DeckView::updateSceneRect);
|
|
connect(deckViewScene, &DeckViewScene::newCardAdded, this, &DeckView::newCardAdded);
|
|
connect(deckViewScene, &DeckViewScene::sideboardPlanChanged, this, &DeckView::sideboardPlanChanged);
|
|
}
|
|
|
|
void DeckView::resizeEvent(QResizeEvent *event)
|
|
{
|
|
QGraphicsView::resizeEvent(event);
|
|
deckViewScene->setOptimalAspectRatio((qreal)width() / (qreal)height());
|
|
deckViewScene->rearrangeItems();
|
|
}
|
|
|
|
void DeckView::updateSceneRect(const QRectF &rect)
|
|
{
|
|
fitInView(rect, Qt::KeepAspectRatio);
|
|
}
|
|
|
|
void DeckView::setDeck(const DeckList &_deck)
|
|
{
|
|
deckViewScene->setDeck(_deck);
|
|
}
|
|
|
|
void DeckView::clearDeck()
|
|
{
|
|
deckViewScene->clearContents();
|
|
}
|
|
|
|
void DeckView::resetSideboardPlan()
|
|
{
|
|
deckViewScene->resetSideboardPlan();
|
|
}
|