diff --git a/cockatrice/CMakeLists.txt b/cockatrice/CMakeLists.txt index 4ca3b07fa..30e117b98 100644 --- a/cockatrice/CMakeLists.txt +++ b/cockatrice/CMakeLists.txt @@ -94,6 +94,12 @@ set(cockatrice_SOURCES src/game/player/player.cpp src/game/player/player_list_widget.cpp src/game/player/player_target.cpp + src/client/ui/widgets/printing_selector/all_zones_card_amount_widget.cpp + src/client/ui/widgets/printing_selector/card_amount_widget.cpp + src/client/ui/widgets/printing_selector/printing_selector.cpp + src/client/ui/widgets/printing_selector/printing_selector_card_display_widget.cpp + src/client/ui/widgets/printing_selector/printing_selector_card_overlay_widget.cpp + src/client/ui/widgets/printing_selector/set_name_and_collectors_number_display_widget.cpp src/client/network/release_channel.cpp src/server/remote/remote_client.cpp src/server/remote/remote_decklist_tree_widget.cpp diff --git a/cockatrice/src/client/tabs/tab_deck_editor.cpp b/cockatrice/src/client/tabs/tab_deck_editor.cpp index 1e2284186..999f22580 100644 --- a/cockatrice/src/client/tabs/tab_deck_editor.cpp +++ b/cockatrice/src/client/tabs/tab_deck_editor.cpp @@ -15,6 +15,7 @@ #include "../../settings/cache_settings.h" #include "../ui/picture_loader.h" #include "../ui/pixel_map_generator.h" +#include "../ui/widgets/printing_selector/printing_selector.h" #include "pb/command_deck_upload.pb.h" #include "pb/response.pb.h" #include "tab_supervisor.h" @@ -78,9 +79,13 @@ void TabDeckEditor::createDeckDock() deckView->sortByColumn(1, Qt::AscendingOrder); deckView->header()->setSectionResizeMode(QHeaderView::ResizeToContents); deckView->installEventFilter(&deckViewKeySignals); + deckView->setContextMenuPolicy(Qt::CustomContextMenu); connect(deckView->selectionModel(), SIGNAL(currentRowChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(updateCardInfoRight(const QModelIndex &, const QModelIndex &))); + connect(deckView->selectionModel(), SIGNAL(currentRowChanged(const QModelIndex &, const QModelIndex &)), this, + SLOT(updatePrintingSelectorDeckView(const QModelIndex &, const QModelIndex &))); connect(deckView, SIGNAL(doubleClicked(const QModelIndex &)), this, SLOT(actSwapCard())); + connect(deckView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(decklistCustomMenu(QPoint))); connect(&deckViewKeySignals, SIGNAL(onShiftS()), this, SLOT(actSwapCard())); connect(&deckViewKeySignals, SIGNAL(onEnter()), this, SLOT(actIncrement())); connect(&deckViewKeySignals, SIGNAL(onCtrlAltEqual()), this, SLOT(actIncrement())); @@ -172,7 +177,6 @@ void TabDeckEditor::createDeckDock() deckDock = new QDockWidget(this); deckDock->setObjectName("deckDock"); - deckDock->setMinimumSize(QSize(200, 41)); deckDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); deckDock->setFeatures(QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetMovable); @@ -196,7 +200,6 @@ void TabDeckEditor::createCardInfoDock() cardInfoDock = new QDockWidget(this); cardInfoDock->setObjectName("cardInfoDock"); - cardInfoDock->setMinimumSize(QSize(200, 41)); cardInfoDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); cardInfoDock->setFeatures(QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetMovable); @@ -271,6 +274,32 @@ void TabDeckEditor::createFiltersDock() connect(filterDock, SIGNAL(topLevelChanged(bool)), this, SLOT(dockTopLevelChanged(bool))); } +void TabDeckEditor::createPrintingSelectorDock() +{ + printingSelector = new PrintingSelector(this, this, deckModel, deckView); + printingSelector->setObjectName("printingSelector"); + auto *printingSelectorFrame = new QVBoxLayout; + printingSelectorFrame->setObjectName("printingSelectorFrame"); + printingSelectorFrame->addWidget(printingSelector); + + printingSelectorDock = new QDockWidget(this); + printingSelectorDock->setObjectName("printingSelectorDock"); + + printingSelectorDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); + printingSelectorDock->setFeatures(QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetFloatable | + QDockWidget::DockWidgetMovable); + auto *printingSelectorDockContents = new QWidget(); + printingSelectorDockContents->setObjectName("printingSelectorDockContents"); + printingSelectorDockContents->setLayout(printingSelectorFrame); + printingSelectorDock->setWidget(printingSelectorDockContents); + + printingSelectorDock->installEventFilter(this); + connect(printingSelectorDock, SIGNAL(topLevelChanged(bool)), this, SLOT(dockTopLevelChanged(bool))); + + addDockWidget(Qt::RightDockWidgetArea, printingSelectorDock); + printingSelectorDock->setFloating(false); +} + void TabDeckEditor::createMenus() { aNewDeck = new QAction(QString(), this); @@ -349,6 +378,7 @@ void TabDeckEditor::createMenus() cardInfoDockMenu = viewMenu->addMenu(QString()); deckDockMenu = viewMenu->addMenu(QString()); filterDockMenu = viewMenu->addMenu(QString()); + printingSelectorDockMenu = viewMenu->addMenu(QString()); aCardInfoDockVisible = cardInfoDockMenu->addAction(QString()); aCardInfoDockVisible->setCheckable(true); @@ -371,6 +401,13 @@ void TabDeckEditor::createMenus() aFilterDockFloating->setCheckable(true); connect(aFilterDockFloating, SIGNAL(triggered()), this, SLOT(dockFloatingTriggered())); + aPrintingSelectorDockVisible = printingSelectorDockMenu->addAction(QString()); + aPrintingSelectorDockVisible->setCheckable(true); + connect(aPrintingSelectorDockVisible, SIGNAL(triggered()), this, SLOT(dockVisibleTriggered())); + aPrintingSelectorDockFloating = printingSelectorDockMenu->addAction(QString()); + aPrintingSelectorDockFloating->setCheckable(true); + connect(aPrintingSelectorDockFloating, SIGNAL(triggered()), this, SLOT(dockFloatingTriggered())); + viewMenu->addSeparator(); aResetLayout = viewMenu->addAction(QString()); @@ -426,6 +463,8 @@ void TabDeckEditor::createCentralFrame() connect(databaseView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(databaseCustomMenu(QPoint))); connect(databaseView->selectionModel(), SIGNAL(currentRowChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(updateCardInfoLeft(const QModelIndex &, const QModelIndex &))); + connect(databaseView->selectionModel(), SIGNAL(currentRowChanged(const QModelIndex &, const QModelIndex &)), this, + SLOT(updatePrintingSelectorDatabase(const QModelIndex &, const QModelIndex &))); connect(databaseView, SIGNAL(doubleClicked(const QModelIndex &)), this, SLOT(actAddCard())); QByteArray dbHeaderState = SettingsCache::instance().layouts().getDeckEditorDbHeaderState(); @@ -465,6 +504,7 @@ void TabDeckEditor::createCentralFrame() centralWidget = new QWidget(this); centralWidget->setObjectName("centralWidget"); centralWidget->setLayout(centralFrame); + centralWidget->setMaximumSize(900, 5000); setCentralWidget(centralWidget); setDockOptions(QMainWindow::AnimatedDocks | QMainWindow::AllowNestedDocks | QMainWindow::AllowTabbedDocks); } @@ -475,11 +515,14 @@ void TabDeckEditor::databaseCustomMenu(QPoint point) const CardInfoPtr info = currentCardInfo(); // add to deck and sideboard options - QAction *addToDeck, *addToSideboard; + QAction *addToDeck, *addToSideboard, *selectPrinting; addToDeck = menu.addAction(tr("Add to Deck")); addToSideboard = menu.addAction(tr("Add to Sideboard")); + selectPrinting = menu.addAction(tr("Select Printing")); + connect(addToDeck, SIGNAL(triggered()), this, SLOT(actAddCard())); connect(addToSideboard, SIGNAL(triggered()), this, SLOT(actAddCardToSideboard())); + connect(selectPrinting, &QAction::triggered, this, [this, info] { this->showPrintingSelector(); }); // filling out the related cards submenu auto *relatedMenu = new QMenu(tr("Show Related cards")); @@ -498,36 +541,58 @@ void TabDeckEditor::databaseCustomMenu(QPoint point) menu.exec(databaseView->mapToGlobal(point)); } +void TabDeckEditor::decklistCustomMenu(QPoint point) +{ + QMenu menu; + const CardInfoPtr info = cardInfo->getInfo(); + + QAction *selectPrinting = menu.addAction(tr("Select Printing")); + + connect(selectPrinting, &QAction::triggered, this, &TabDeckEditor::showPrintingSelector); + + menu.exec(deckView->mapToGlobal(point)); +} + +void TabDeckEditor::showPrintingSelector() +{ + printingSelector->setCard(cardInfo->getInfo(), DECK_ZONE_MAIN); + printingSelector->updateDisplay(); + aPrintingSelectorDockVisible->setChecked(true); + printingSelectorDock->setVisible(true); +} + void TabDeckEditor::restartLayout() { deckDock->setVisible(true); cardInfoDock->setVisible(true); filterDock->setVisible(true); + printingSelectorDock->setVisible(false); deckDock->setFloating(false); cardInfoDock->setFloating(false); filterDock->setFloating(false); + printingSelectorDock->setFloating(false); aCardInfoDockVisible->setChecked(true); aDeckDockVisible->setChecked(true); aFilterDockVisible->setChecked(true); + aPrintingSelectorDockVisible->setChecked(false); aCardInfoDockFloating->setChecked(false); aDeckDockFloating->setChecked(false); aFilterDockFloating->setChecked(false); + aPrintingSelectorDockFloating->setChecked(false); addDockWidget(static_cast(2), deckDock); addDockWidget(static_cast(2), cardInfoDock); addDockWidget(static_cast(2), filterDock); + addDockWidget(static_cast(2), printingSelectorDock); - splitDockWidget(cardInfoDock, deckDock, Qt::Horizontal); + splitDockWidget(cardInfoDock, printingSelectorDock, Qt::Horizontal); + splitDockWidget(printingSelectorDock, deckDock, Qt::Horizontal); + splitDockWidget(cardInfoDock, printingSelectorDock, Qt::Horizontal); splitDockWidget(cardInfoDock, filterDock, Qt::Vertical); - deckDock->setMinimumWidth(360); - deckDock->setMaximumWidth(360); - - cardInfoDock->setMinimumSize(250, 360); - cardInfoDock->setMaximumSize(250, 360); QTimer::singleShot(100, this, SLOT(freeDocksSize())); } @@ -541,6 +606,11 @@ void TabDeckEditor::freeDocksSize() filterDock->setMinimumSize(100, 100); filterDock->setMaximumSize(5000, 5000); + + printingSelectorDock->setMinimumSize(525, 100); + printingSelectorDock->setMaximumSize(5000, 5000); + + centralWidget->setMaximumSize(900, 5000); } void TabDeckEditor::refreshShortcuts() @@ -583,14 +653,17 @@ void TabDeckEditor::loadLayout() aCardInfoDockVisible->setChecked(cardInfoDock->isVisible()); aFilterDockVisible->setChecked(filterDock->isVisible()); aDeckDockVisible->setChecked(deckDock->isVisible()); + aPrintingSelectorDockVisible->setChecked(printingSelectorDock->isVisible()); aCardInfoDockFloating->setEnabled(aCardInfoDockVisible->isChecked()); aDeckDockFloating->setEnabled(aDeckDockVisible->isChecked()); aFilterDockFloating->setEnabled(aFilterDockVisible->isChecked()); + aPrintingSelectorDockFloating->setEnabled(aPrintingSelectorDockVisible->isChecked()); aCardInfoDockFloating->setChecked(cardInfoDock->isFloating()); aFilterDockFloating->setChecked(filterDock->isFloating()); aDeckDockFloating->setChecked(deckDock->isFloating()); + aPrintingSelectorDockFloating->setChecked(printingSelectorDock->isFloating()); cardInfoDock->setMinimumSize(layouts.getDeckEditorCardSize()); cardInfoDock->setMaximumSize(layouts.getDeckEditorCardSize()); @@ -601,6 +674,9 @@ void TabDeckEditor::loadLayout() deckDock->setMinimumSize(layouts.getDeckEditorDeckSize()); deckDock->setMaximumSize(layouts.getDeckEditorDeckSize()); + printingSelectorDock->setMinimumSize(layouts.getDeckEditorPrintingSelectorSize()); + printingSelectorDock->setMaximumSize(layouts.getDeckEditorPrintingSelectorSize()); + QTimer::singleShot(100, this, SLOT(freeDocksSize())); } @@ -616,6 +692,7 @@ TabDeckEditor::TabDeckEditor(TabSupervisor *_tabSupervisor, QWidget *parent) createDeckDock(); createCardInfoDock(); createFiltersDock(); + createPrintingSelectorDock(); this->installEventFilter(this); @@ -675,11 +752,13 @@ void TabDeckEditor::retranslateUi() cardInfoDock->setWindowTitle(tr("Card Info")); deckDock->setWindowTitle(tr("Deck")); filterDock->setWindowTitle(tr("Filters")); + printingSelectorDock->setWindowTitle(tr("Printing Selector")); viewMenu->setTitle(tr("&View")); cardInfoDockMenu->setTitle(tr("Card Info")); deckDockMenu->setTitle(tr("Deck")); filterDockMenu->setTitle(tr("Filters")); + printingSelectorDockMenu->setTitle(tr("Printing")); aCardInfoDockVisible->setText(tr("Visible")); aCardInfoDockFloating->setText(tr("Floating")); @@ -690,6 +769,9 @@ void TabDeckEditor::retranslateUi() aFilterDockVisible->setText(tr("Visible")); aFilterDockFloating->setText(tr("Floating")); + aPrintingSelectorDockVisible->setText(tr("Visible")); + aPrintingSelectorDockFloating->setText(tr("Floating")); + aResetLayout->setText(tr("Reset layout")); } @@ -715,6 +797,11 @@ void TabDeckEditor::updateComments() setSaveStatus(true); } +void TabDeckEditor::updateCardInfo(CardInfoPtr _card) +{ + cardInfo->setCard(_card); +} + void TabDeckEditor::updateCardInfoLeft(const QModelIndex ¤t, const QModelIndex & /*previous*/) { cardInfo->setCard(current.sibling(current.row(), 0).data().toString()); @@ -730,6 +817,43 @@ void TabDeckEditor::updateCardInfoRight(const QModelIndex ¤t, const QModel } } +void TabDeckEditor::updatePrintingSelectorDatabase(const QModelIndex ¤t, const QModelIndex & /*previous*/) +{ + const QString cardName = current.sibling(current.row(), 0).data().toString(); + const QString cardProviderID = CardDatabaseManager::getInstance()->getPreferredPrintingProviderIdForCard(cardName); + + if (!current.isValid()) { + return; + } + + if (!current.model()->hasChildren(current.sibling(current.row(), 0))) { + printingSelector->setCard( + CardDatabaseManager::getInstance()->getCardByNameAndProviderId(cardName, cardProviderID), DECK_ZONE_MAIN); + } +} + +void TabDeckEditor::updatePrintingSelectorDeckView(const QModelIndex ¤t, const QModelIndex & /*previous*/) +{ + const QString cardName = current.sibling(current.row(), 1).data().toString(); + const QString cardProviderID = current.sibling(current.row(), 4).data().toString(); + const QModelIndex gparent = current.parent().parent(); + + if (!gparent.isValid()) { + return; + } + + const QString zoneName = gparent.sibling(gparent.row(), 1).data(Qt::EditRole).toString(); + + if (!current.isValid()) { + return; + } + + if (!current.model()->hasChildren(current.sibling(current.row(), 0))) { + printingSelector->setCard( + CardDatabaseManager::getInstance()->getCardByNameAndProviderId(cardName, cardProviderID), zoneName); + } +} + void TabDeckEditor::updateSearch(const QString &search) { databaseDisplayModel->setStringFilter(search); @@ -1096,7 +1220,7 @@ void TabDeckEditor::actSwapCard() if (!currentIndex.isValid()) return; const QString cardName = currentIndex.sibling(currentIndex.row(), 1).data().toString(); - const QString cardProviderID = currentIndex.sibling(currentIndex.row(), 2).data().toString(); + const QString cardProviderID = currentIndex.sibling(currentIndex.row(), 4).data().toString(); const QModelIndex gparent = currentIndex.parent().parent(); if (!gparent.isValid()) @@ -1270,6 +1394,9 @@ bool TabDeckEditor::eventFilter(QObject *o, QEvent *e) } else if (o == filterDock) { aFilterDockVisible->setChecked(false); aFilterDockFloating->setEnabled(false); + } else if (o == printingSelectorDock) { + aPrintingSelectorDockVisible->setChecked(false); + aPrintingSelectorDockFloating->setEnabled(false); } } if (o == this && e->type() == QEvent::Hide) { @@ -1279,6 +1406,7 @@ bool TabDeckEditor::eventFilter(QObject *o, QEvent *e) layouts.setDeckEditorCardSize(cardInfoDock->size()); layouts.setDeckEditorFilterSize(filterDock->size()); layouts.setDeckEditorDeckSize(deckDock->size()); + layouts.setDeckEditorPrintingSelectorSize(printingSelectorDock->size()); } return false; } @@ -1303,6 +1431,12 @@ void TabDeckEditor::dockVisibleTriggered() aFilterDockFloating->setEnabled(aFilterDockVisible->isChecked()); return; } + + if (o == aPrintingSelectorDockVisible) { + printingSelectorDock->setVisible(aPrintingSelectorDockVisible->isChecked()); + aPrintingSelectorDockFloating->setEnabled(aPrintingSelectorDockVisible->isChecked()); + return; + } } void TabDeckEditor::dockFloatingTriggered() @@ -1322,6 +1456,11 @@ void TabDeckEditor::dockFloatingTriggered() filterDock->setFloating(aFilterDockFloating->isChecked()); return; } + + if (o == aPrintingSelectorDockFloating) { + printingSelectorDock->setFloating(aPrintingSelectorDockFloating->isChecked()); + return; + } } void TabDeckEditor::dockTopLevelChanged(bool topLevel) @@ -1341,6 +1480,11 @@ void TabDeckEditor::dockTopLevelChanged(bool topLevel) aFilterDockFloating->setChecked(topLevel); return; } + + if (o == printingSelectorDock) { + aPrintingSelectorDockFloating->setChecked(topLevel); + return; + } } void TabDeckEditor::saveDbHeaderState() diff --git a/cockatrice/src/client/tabs/tab_deck_editor.h b/cockatrice/src/client/tabs/tab_deck_editor.h index 6aff1cc31..3fc49e1f6 100644 --- a/cockatrice/src/client/tabs/tab_deck_editor.h +++ b/cockatrice/src/client/tabs/tab_deck_editor.h @@ -4,6 +4,7 @@ #include "../../deck/custom_line_edit.h" #include "../../game/cards/card_database.h" #include "../game_logic/key_signals.h" +#include "../ui/widgets/printing_selector/printing_selector.h" #include "tab.h" #include @@ -55,8 +56,12 @@ private slots: void updateHash(); void updateCardInfoLeft(const QModelIndex ¤t, const QModelIndex &previous); void updateCardInfoRight(const QModelIndex ¤t, const QModelIndex &previous); + void updatePrintingSelectorDatabase(const QModelIndex ¤t, const QModelIndex &previous); + void updatePrintingSelectorDeckView(const QModelIndex ¤t, const QModelIndex &previous); void updateSearch(const QString &search); void databaseCustomMenu(QPoint point); + void decklistCustomMenu(QPoint point); + void showPrintingSelector(); void actNewDeck(); void actLoadDeck(); @@ -129,6 +134,7 @@ private: QTreeView *deckView; KeySignals deckViewKeySignals; CardInfoFrameWidget *cardInfo; + PrintingSelector *printingSelector; SearchLineEdit *searchEdit; KeySignals searchKeySignals; @@ -143,8 +149,8 @@ private: KeySignals filterViewKeySignals; QWidget *filterBox; - QMenu *deckMenu, *viewMenu, *cardInfoDockMenu, *deckDockMenu, *filterDockMenu, *analyzeDeckMenu, - *saveDeckToClipboardMenu; + QMenu *deckMenu, *viewMenu, *cardInfoDockMenu, *deckDockMenu, *filterDockMenu, *printingSelectorDockMenu, + *analyzeDeckMenu, *saveDeckToClipboardMenu; QAction *aNewDeck, *aLoadDeck, *aSaveDeck, *aSaveDeckAs, *aLoadDeckFromClipboard, *aSaveDeckToClipboard, *aSaveDeckToClipboardRaw, *aPrintDeck, *aExportDeckDecklist, *aAnalyzeDeckDeckstats, *aAnalyzeDeckTappedout, *aClose; @@ -152,7 +158,7 @@ private: QAction *aAddCard, *aAddCardToSideboard, *aRemoveCard, *aIncrement, *aDecrement; QAction *aResetLayout; QAction *aCardInfoDockVisible, *aCardInfoDockFloating, *aDeckDockVisible, *aDeckDockFloating, *aFilterDockVisible, - *aFilterDockFloating; + *aFilterDockFloating, *aPrintingSelectorDockVisible, *aPrintingSelectorDockFloating; bool modified; QVBoxLayout *centralFrame; @@ -160,6 +166,7 @@ private: QDockWidget *cardInfoDock; QDockWidget *deckDock; QDockWidget *filterDock; + QDockWidget *printingSelectorDock; QWidget *centralWidget; public: @@ -173,8 +180,10 @@ public: void createDeckDock(); void createCardInfoDock(); void createFiltersDock(); + void createPrintingSelectorDock(); void createMenus(); void createCentralFrame(); + void updateCardInfo(CardInfoPtr _card); public slots: void closeRequest() override; diff --git a/cockatrice/src/client/ui/picture_loader.cpp b/cockatrice/src/client/ui/picture_loader.cpp index a28a98eac..36d46eba7 100644 --- a/cockatrice/src/client/ui/picture_loader.cpp +++ b/cockatrice/src/client/ui/picture_loader.cpp @@ -525,6 +525,7 @@ void PictureLoaderWorker::loadRedirectCache() void PictureLoaderWorker::saveRedirectCache() const { + qDebug() << "Saving redirect cache"; QSettings settings(cacheFilePath, QSettings::IniFormat); settings.beginWriteArray(REDIRECT_HEADER_NAME, static_cast(redirectCache.size())); @@ -717,6 +718,26 @@ void PictureLoader::getCardBackPixmap(QPixmap &pixmap, QSize size) } } +void PictureLoader::getCardBackLoadingInProgressPixmap(QPixmap &pixmap, QSize size) +{ + QString backCacheKey = "_trice_card_back_" + QString::number(size.width()) + QString::number(size.height()); + if (!QPixmapCache::find(backCacheKey, &pixmap)) { + qDebug() << "PictureLoader: cache fail for" << backCacheKey; + pixmap = QPixmap("theme:cardback").scaled(size, Qt::KeepAspectRatio, Qt::SmoothTransformation); + QPixmapCache::insert(backCacheKey, pixmap); + } +} + +void PictureLoader::getCardBackLoadingFailedPixmap(QPixmap &pixmap, QSize size) +{ + QString backCacheKey = "_trice_card_back_" + QString::number(size.width()) + QString::number(size.height()); + if (!QPixmapCache::find(backCacheKey, &pixmap)) { + qDebug() << "PictureLoader: cache fail for" << backCacheKey; + pixmap = QPixmap("theme:cardback").scaled(size, Qt::KeepAspectRatio, Qt::SmoothTransformation); + QPixmapCache::insert(backCacheKey, pixmap); + } +} + void PictureLoader::getPixmap(QPixmap &pixmap, CardInfoPtr card, QSize size) { if (card == nullptr) { diff --git a/cockatrice/src/client/ui/picture_loader.h b/cockatrice/src/client/ui/picture_loader.h index 245114358..e781efd91 100644 --- a/cockatrice/src/client/ui/picture_loader.h +++ b/cockatrice/src/client/ui/picture_loader.h @@ -142,6 +142,8 @@ private: public: static void getPixmap(QPixmap &pixmap, CardInfoPtr card, QSize size); static void getCardBackPixmap(QPixmap &pixmap, QSize size); + static void getCardBackLoadingInProgressPixmap(QPixmap &pixmap, QSize size); + static void getCardBackLoadingFailedPixmap(QPixmap &pixmap, QSize size); static void clearPixmapCache(CardInfoPtr card); static void clearPixmapCache(); static void cacheCardPixmaps(QList cards); diff --git a/cockatrice/src/client/ui/widgets/cards/card_info_frame_widget.h b/cockatrice/src/client/ui/widgets/cards/card_info_frame_widget.h index a9a4a0597..fd354c31c 100644 --- a/cockatrice/src/client/ui/widgets/cards/card_info_frame_widget.h +++ b/cockatrice/src/client/ui/widgets/cards/card_info_frame_widget.h @@ -30,7 +30,12 @@ public: TextOnlyView, ImageAndTextView }; + explicit CardInfoFrameWidget(const QString &cardName = QString(), QWidget *parent = nullptr); + CardInfoPtr getInfo() + { + return info; + } void retranslateUi(); public slots: diff --git a/cockatrice/src/client/ui/widgets/cards/card_info_picture_widget.cpp b/cockatrice/src/client/ui/widgets/cards/card_info_picture_widget.cpp index 8b71c9000..f0b5d6f65 100644 --- a/cockatrice/src/client/ui/widgets/cards/card_info_picture_widget.cpp +++ b/cockatrice/src/client/ui/widgets/cards/card_info_picture_widget.cpp @@ -92,7 +92,7 @@ void CardInfoPictureWidget::resizeEvent(QResizeEvent *event) */ void CardInfoPictureWidget::setScaleFactor(const int scale) { - const int newWidth = baseWidth + scale * 20; + const int newWidth = baseWidth * scale / 100; const int newHeight = static_cast(newWidth * aspectRatio); scaleFactor = scale; @@ -119,10 +119,11 @@ void CardInfoPictureWidget::updatePixmap() */ void CardInfoPictureWidget::loadPixmap() { + PictureLoader::getCardBackLoadingInProgressPixmap(resizedPixmap, size()); if (info) { PictureLoader::getPixmap(resizedPixmap, info, size()); } else { - PictureLoader::getCardBackPixmap(resizedPixmap, size()); + PictureLoader::getCardBackLoadingFailedPixmap(resizedPixmap, size()); } pixmapDirty = false; diff --git a/cockatrice/src/client/ui/widgets/general/layout_containers/flow_widget.cpp b/cockatrice/src/client/ui/widgets/general/layout_containers/flow_widget.cpp index 7bcb6ea75..3bfa293f8 100644 --- a/cockatrice/src/client/ui/widgets/general/layout_containers/flow_widget.cpp +++ b/cockatrice/src/client/ui/widgets/general/layout_containers/flow_widget.cpp @@ -139,3 +139,46 @@ void FlowWidget::resizeEvent(QResizeEvent *event) } } } + +/** + * @brief Sets the minimum size for all widgets inside the FlowWidget to the maximum sizeHint of all of them. + */ +void FlowWidget::setMinimumSizeToMaxSizeHint() +{ + QSize maxSize(0, 0); // Initialize to a zero size + + // Iterate over all widgets in the flow layout to find the maximum sizeHint + for (int i = 0; i < flow_layout->count(); ++i) { + QLayoutItem *item = flow_layout->itemAt(i); + if (item) { + QWidget *widget = item->widget(); + if (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())); + } + } + } + + // Set the minimum size for all widgets to the max sizeHint + for (int i = 0; i < flow_layout->count(); ++i) { + QLayoutItem *item = flow_layout->itemAt(i); + if (item) { + QWidget *widget = item->widget(); + if (widget) { + widget->setMinimumSize(maxSize); + } + } + } +} + +QLayoutItem *FlowWidget::itemAt(int index) const +{ + return flow_layout->itemAt(index); +} + +int FlowWidget::count() const +{ + return flow_layout->count(); +} \ No newline at end of file diff --git a/cockatrice/src/client/ui/widgets/general/layout_containers/flow_widget.h b/cockatrice/src/client/ui/widgets/general/layout_containers/flow_widget.h index a52cca6e2..ed6dd0f7a 100644 --- a/cockatrice/src/client/ui/widgets/general/layout_containers/flow_widget.h +++ b/cockatrice/src/client/ui/widgets/general/layout_containers/flow_widget.h @@ -14,9 +14,14 @@ public: FlowWidget(QWidget *parent, Qt::ScrollBarPolicy horizontalPolicy, Qt::ScrollBarPolicy verticalPolicy); void addWidget(QWidget *widget_to_add) const; void clearLayout(); + [[nodiscard]] int count() const; + [[nodiscard]] QLayoutItem *itemAt(int index) const; QScrollArea *scrollArea; +public slots: + void setMinimumSizeToMaxSizeHint(); + protected: void resizeEvent(QResizeEvent *event) override; diff --git a/cockatrice/src/client/ui/widgets/printing_selector/all_zones_card_amount_widget.cpp b/cockatrice/src/client/ui/widgets/printing_selector/all_zones_card_amount_widget.cpp new file mode 100644 index 000000000..c2a482c8e --- /dev/null +++ b/cockatrice/src/client/ui/widgets/printing_selector/all_zones_card_amount_widget.cpp @@ -0,0 +1,55 @@ +#include "all_zones_card_amount_widget.h" + +AllZonesCardAmountWidget::AllZonesCardAmountWidget(QWidget *parent, + TabDeckEditor *deckEditor, + DeckListModel *deckModel, + QTreeView *deckView, + CardInfoPtr rootCard, + CardInfoPerSet setInfoForCard) + : QWidget(parent), deckEditor(deckEditor), deckModel(deckModel), deckView(deckView), rootCard(rootCard), + setInfoForCard(setInfoForCard) +{ + layout = new QVBoxLayout(this); + layout->setAlignment(Qt::AlignCenter); + setLayout(layout); + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + + zoneLabelMainboard = new QLabel(tr("Mainboard"), this); + zoneLabelMainboard->setStyleSheet(R"( + QLabel { + background-color: rgba(0, 0, 0, 128); /* Semi-transparent black */ + color: white; /* Text color */ + font-size: 16px; + border-radius: 5px; /* Rounded corners */ + padding: 5px; /* Padding around text */ + } + )"); + buttonBoxMainboard = + new CardAmountWidget(this, deckEditor, deckModel, deckView, rootCard, setInfoForCard, DECK_ZONE_MAIN); + zoneLabelSideboard = new QLabel(tr("Sideboard"), this); + zoneLabelSideboard->setStyleSheet(R"( + QLabel { + background-color: rgba(0, 0, 0, 128); /* Semi-transparent black */ + color: white; /* Text color */ + font-size: 16px; + border-radius: 5px; /* Rounded corners */ + padding: 5px; /* Padding around text */ + } + )"); + buttonBoxSideboard = + new CardAmountWidget(this, deckEditor, deckModel, deckView, rootCard, setInfoForCard, DECK_ZONE_SIDE); + + layout->addWidget(zoneLabelMainboard, 0, Qt::AlignHCenter | Qt::AlignBottom); + layout->addWidget(buttonBoxMainboard, 0, Qt::AlignHCenter | Qt::AlignTop); + layout->addSpacing(25); + layout->addWidget(zoneLabelSideboard, 0, Qt::AlignHCenter | Qt::AlignBottom); + layout->addWidget(buttonBoxSideboard, 0, Qt::AlignHCenter | Qt::AlignTop); + + setMouseTracking(true); +} + +void AllZonesCardAmountWidget::enterEvent(QEnterEvent *event) +{ + QWidget::enterEvent(event); + update(); +} \ No newline at end of file diff --git a/cockatrice/src/client/ui/widgets/printing_selector/all_zones_card_amount_widget.h b/cockatrice/src/client/ui/widgets/printing_selector/all_zones_card_amount_widget.h new file mode 100644 index 000000000..46d1436df --- /dev/null +++ b/cockatrice/src/client/ui/widgets/printing_selector/all_zones_card_amount_widget.h @@ -0,0 +1,36 @@ +#ifndef ALL_ZONES_CARD_AMOUNT_WIDGET_H +#define ALL_ZONES_CARD_AMOUNT_WIDGET_H +#include "../../../../deck/deck_list_model.h" +#include "../../../../deck/deck_loader.h" +#include "../../../../deck/deck_view.h" +#include "card_amount_widget.h" + +#include +#include + +class AllZonesCardAmountWidget : public QWidget +{ + Q_OBJECT +public: + explicit AllZonesCardAmountWidget(QWidget *parent, + TabDeckEditor *deckEditor, + DeckListModel *deckModel, + QTreeView *deckView, + CardInfoPtr rootCard, + CardInfoPerSet setInfoForCard); + void enterEvent(QEnterEvent *event) override; + +private: + QVBoxLayout *layout; + TabDeckEditor *deckEditor; + DeckListModel *deckModel; + QTreeView *deckView; + CardInfoPtr rootCard; + CardInfoPerSet setInfoForCard; + QLabel *zoneLabelMainboard; + CardAmountWidget *buttonBoxMainboard; + QLabel *zoneLabelSideboard; + CardAmountWidget *buttonBoxSideboard; +}; + +#endif // ALL_ZONES_CARD_AMOUNT_WIDGET_H diff --git a/cockatrice/src/client/ui/widgets/printing_selector/card_amount_widget.cpp b/cockatrice/src/client/ui/widgets/printing_selector/card_amount_widget.cpp new file mode 100644 index 000000000..722c62a7d --- /dev/null +++ b/cockatrice/src/client/ui/widgets/printing_selector/card_amount_widget.cpp @@ -0,0 +1,197 @@ +#include "card_amount_widget.h" + +CardAmountWidget::CardAmountWidget(QWidget *parent, + TabDeckEditor *deckEditor, + DeckListModel *deckModel, + QTreeView *deckView, + CardInfoPtr &rootCard, + CardInfoPerSet &setInfoForCard, + QString zoneName) + : QWidget(parent), deckEditor(deckEditor), deckModel(deckModel), deckView(deckView), rootCard(rootCard), + setInfoForCard(setInfoForCard), zoneName(zoneName), hovered(false) +{ + layout = new QHBoxLayout(this); + layout->setContentsMargins(0, 0, 0, 0); + layout->setSpacing(10); + this->setLayout(layout); + this->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + + incrementButton = new QPushButton(this); + incrementButton->setText("+"); + decrementButton = new QPushButton(this); + decrementButton->setText("-"); + + incrementButton->setFixedSize(30, 30); + decrementButton->setFixedSize(30, 30); + + // Apply styles for gradient buttons + QString buttonStyle = R"( + QPushButton { + background: qlineargradient(spread:pad, x1:0.5, y1:0, x2:0.5, y2:1, + stop:0 rgba(64, 64, 64, 255), stop:1 rgba(32, 32, 32, 255)); + border: none; + color: white; + font-size: 16px; + } + QPushButton:hover { + background: qlineargradient(spread:pad, x1:0.5, y1:0, x2:0.5, y2:1, + stop:0 rgba(96, 96, 96, 255), stop:1 rgba(48, 48, 48, 255)); + } + QPushButton:pressed { + background: qlineargradient(spread:pad, x1:0.5, y1:0, x2:0.5, y2:1, + stop:0 rgba(128, 128, 128, 255), stop:1 rgba(64, 64, 64, 255)); + } + )"; + incrementButton->setStyleSheet(buttonStyle); + decrementButton->setStyleSheet(buttonStyle); + + // Set up connections + if (zoneName == DECK_ZONE_MAIN) { + connect(incrementButton, &QPushButton::clicked, this, &CardAmountWidget::addPrintingMainboard); + connect(decrementButton, &QPushButton::clicked, this, &CardAmountWidget::removePrintingMainboard); + } else if (zoneName == DECK_ZONE_SIDE) { + connect(incrementButton, &QPushButton::clicked, this, &CardAmountWidget::addPrintingSideboard); + connect(decrementButton, &QPushButton::clicked, this, &CardAmountWidget::removePrintingSideboard); + } + + cardCountInZone = new QLabel(QString::number(countCardsInZone(zoneName)), this); + cardCountInZone->setStyleSheet("color: white; font-size: 16px;"); + cardCountInZone->setAlignment(Qt::AlignCenter); + + layout->addWidget(decrementButton); + layout->addWidget(cardCountInZone); + layout->addWidget(incrementButton); + + // React to model changes + connect(deckModel, &DeckListModel::dataChanged, this, &CardAmountWidget::updateCardCount); + connect(deckModel, &QAbstractItemModel::rowsRemoved, this, &CardAmountWidget::updateCardCount); + + // Initially hide UI elements + fadeAnimation = new QPropertyAnimation(this, "opacity"); +} + +void CardAmountWidget::paintEvent(QPaintEvent *event) +{ + QPainter painter(this); + painter.setRenderHint(QPainter::Antialiasing); + + // Draw semi-transparent black background + painter.setBrush(QBrush(QColor(0, 0, 0, 128))); + painter.setPen(Qt::NoPen); + painter.drawRect(rect()); + + QWidget::paintEvent(event); +} + +void CardAmountWidget::updateCardCount() +{ + cardCountInZone->setText(QString::number(countCardsInZone(zoneName))); +} + +void CardAmountWidget::addPrinting(const QString &zone) +{ + const auto newCardIndex = deckModel->addCard(rootCard->getName(), setInfoForCard, zone); + recursiveExpand(newCardIndex); + QModelIndex find_card = deckModel->findCard(rootCard->getName(), zone); + if (find_card.isValid() && find_card != newCardIndex) { + deckModel->removeRow(find_card.row(), find_card.parent()); + }; + deckView->setFocus(Qt::FocusReason::MouseFocusReason); +} + +void CardAmountWidget::addPrintingMainboard() +{ + addPrinting(DECK_ZONE_MAIN); +} + +void CardAmountWidget::addPrintingSideboard() +{ + addPrinting(DECK_ZONE_SIDE); +} + +void CardAmountWidget::removePrintingMainboard() +{ + decrementCardHelper(DECK_ZONE_MAIN); +} + +void CardAmountWidget::removePrintingSideboard() +{ + decrementCardHelper(DECK_ZONE_SIDE); +} + +void CardAmountWidget::recursiveExpand(const QModelIndex &index) +{ + if (index.parent().isValid()) { + recursiveExpand(index.parent()); + } + deckView->expand(index); +} + +void CardAmountWidget::offsetCountAtIndex(const QModelIndex &idx, int offset) +{ + if (!idx.isValid() || offset == 0) { + return; + } + + const QModelIndex numberIndex = idx.sibling(idx.row(), 0); + const int count = deckModel->data(numberIndex, Qt::EditRole).toInt(); + const int new_count = count + offset; + deckView->setCurrentIndex(numberIndex); + if (new_count <= 0) { + deckModel->removeRow(idx.row(), idx.parent()); + } else { + deckModel->setData(numberIndex, new_count, Qt::EditRole); + } + deckEditor->setModified(true); +} + +void CardAmountWidget::decrementCardHelper(const QString &zone) +{ + QModelIndex idx; + idx = deckModel->findCard(rootCard->getName(), zone, setInfoForCard.getProperty("uuid")); + offsetCountAtIndex(idx, -1); +} + +int CardAmountWidget::countCardsInZone(const QString &deckZone) +{ + int count = 0; + + if (!deckModel) { + return -1; + } + + DeckList *decklist = deckModel->getDeckList(); + if (!decklist) { + return -1; + } + + InnerDecklistNode *listRoot = decklist->getRoot(); + if (!listRoot) { + return -1; + } + + for (auto *i : *listRoot) { + auto *countCurrentZone = dynamic_cast(i); + if (!countCurrentZone) { + continue; + } + + if (countCurrentZone->getName() != deckZone) { + continue; + } + + for (auto *cardNode : *countCurrentZone) { + auto *currentCard = dynamic_cast(cardNode); + if (!currentCard) { + continue; + } + + for (int k = 0; k < currentCard->getNumber(); ++k) { + if (currentCard->getCardProviderId() == setInfoForCard.getProperty("uuid")) { + count++; + } + } + } + } + return count; +} \ No newline at end of file diff --git a/cockatrice/src/client/ui/widgets/printing_selector/card_amount_widget.h b/cockatrice/src/client/ui/widgets/printing_selector/card_amount_widget.h new file mode 100644 index 000000000..894eb8905 --- /dev/null +++ b/cockatrice/src/client/ui/widgets/printing_selector/card_amount_widget.h @@ -0,0 +1,65 @@ +#ifndef CARD_AMOUNT_WIDGET_H +#define CARD_AMOUNT_WIDGET_H + +#include "../../../../deck/deck_list_model.h" +#include "../../../../deck/deck_loader.h" +#include "../../../../deck/deck_view.h" +#include "../../../../game/cards/card_database.h" +#include "../../../tabs/tab_deck_editor.h" + +#include +#include +#include +#include +#include +#include + +class CardAmountWidget : public QWidget +{ + Q_OBJECT +public: + explicit CardAmountWidget(QWidget *parent, + TabDeckEditor *deckEditor, + DeckListModel *deckModel, + QTreeView *deckView, + CardInfoPtr &rootCard, + CardInfoPerSet &setInfoForCard, + QString zoneName); + int countCardsInZone(const QString &deckZone); + +public slots: + void updateCardCount(); + void addPrinting(const QString &zone); + +protected: + void paintEvent(QPaintEvent *event) override; + void hideElements(); + void showElements(); + +private: + TabDeckEditor *deckEditor; + DeckListModel *deckModel; + QTreeView *deckView; + CardInfoPtr rootCard; + CardInfoPerSet setInfoForCard; + QString zoneName; + QHBoxLayout *layout; + QPushButton *incrementButton; + QPushButton *decrementButton; + QLabel *cardCountInZone; + + bool hovered; + QPropertyAnimation *fadeAnimation; + + void offsetCountAtIndex(const QModelIndex &idx, int offset); + void decrementCardHelper(const QString &zoneName); + void recursiveExpand(const QModelIndex &index); + +private slots: + void addPrintingMainboard(); + void addPrintingSideboard(); + void removePrintingMainboard(); + void removePrintingSideboard(); +}; + +#endif // CARD_AMOUNT_WIDGET_H diff --git a/cockatrice/src/client/ui/widgets/printing_selector/printing_selector.cpp b/cockatrice/src/client/ui/widgets/printing_selector/printing_selector.cpp new file mode 100644 index 000000000..32c0768f3 --- /dev/null +++ b/cockatrice/src/client/ui/widgets/printing_selector/printing_selector.cpp @@ -0,0 +1,293 @@ +#include "printing_selector.h" + +#include "../../../../utility/card_set_comparator.h" +#include "printing_selector_card_display_widget.h" + +#include +#include +#include +#include + +const QString PrintingSelector::SORT_OPTIONS_ALPHABETICAL = tr("Alphabetical"); +const QString PrintingSelector::SORT_OPTIONS_PREFERENCE = tr("Preference"); +const QString PrintingSelector::SORT_OPTIONS_RELEASE_DATE = tr("Release Date"); +const QString PrintingSelector::SORT_OPTIONS_CONTAINED_IN_DECK = tr("Contained in Deck"); +const QString PrintingSelector::SORT_OPTIONS_POTENTIAL_CARDS = tr("Potential Cards in Deck"); + +const QStringList PrintingSelector::SORT_OPTIONS = {SORT_OPTIONS_ALPHABETICAL, SORT_OPTIONS_PREFERENCE, + SORT_OPTIONS_RELEASE_DATE, SORT_OPTIONS_CONTAINED_IN_DECK, + SORT_OPTIONS_POTENTIAL_CARDS}; +PrintingSelector::PrintingSelector(QWidget *parent, + TabDeckEditor *deckEditor, + DeckListModel *deckModel, + QTreeView *deckView) + : QWidget(parent), deckEditor(deckEditor), deckModel(deckModel), deckView(deckView) +{ + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + layout = new QVBoxLayout(); + setLayout(layout); + + sortToolBar = new QHBoxLayout(this); + + sortOptionsSelector = new QComboBox(this); + sortOptionsSelector->addItems(SORT_OPTIONS); + connect(sortOptionsSelector, &QComboBox::currentTextChanged, this, &PrintingSelector::updateDisplay); + sortToolBar->addWidget(sortOptionsSelector); + + toggleSortOrder = new QPushButton(this); + toggleSortOrder->setText(tr("Ascending")); + descendingSort = false; + connect(toggleSortOrder, &QPushButton::clicked, this, &PrintingSelector::updateSortOrder); + sortToolBar->addWidget(toggleSortOrder); + + layout->addLayout(sortToolBar); + + // Add the search bar + searchBar = new QLineEdit(this); + searchBar->setPlaceholderText(tr("Search by set name or set code")); + layout->addWidget(searchBar); + + // Add a debounce timer for the search bar + searchDebounceTimer = new QTimer(this); + searchDebounceTimer->setSingleShot(true); + connect(searchBar, &QLineEdit::textChanged, this, [this]() { + searchDebounceTimer->start(300); // 300ms debounce + }); + connect(searchDebounceTimer, &QTimer::timeout, this, &PrintingSelector::updateDisplay); + + flowWidget = new FlowWidget(this, Qt::ScrollBarAlwaysOff, Qt::ScrollBarAsNeeded); + layout->addWidget(flowWidget); + + cardSizeWidget = new QWidget(this); + cardSizeLayout = new QHBoxLayout(this); + cardSizeWidget->setLayout(cardSizeLayout); + + cardSizeLabel = new QLabel(tr("Card Size"), cardSizeWidget); + cardSizeLabel->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); + cardSizeSlider = new QSlider(Qt::Horizontal, cardSizeWidget); + cardSizeSlider->setRange(25, 250); + cardSizeSlider->setValue(100); + connect(cardSizeSlider, &QSlider::valueChanged, flowWidget, &FlowWidget::setMinimumSizeToMaxSizeHint); + + cardSizeLayout->addWidget(cardSizeLabel); + cardSizeLayout->addWidget(cardSizeSlider); + + layout->addWidget(cardSizeWidget); + + cardSelectionBar = new QWidget(this); + cardSelectionBarLayout = new QHBoxLayout(cardSelectionBar); + previousCardButton = new QPushButton(cardSelectionBar); + previousCardButton->setText(tr("Previous Card")); + connect(previousCardButton, &QPushButton::clicked, this, &PrintingSelector::selectPreviousCard); + nextCardButton = new QPushButton(cardSelectionBar); + nextCardButton->setText(tr("Next Card")); + connect(nextCardButton, &QPushButton::clicked, this, &PrintingSelector::selectNextCard); + + cardSelectionBarLayout->addWidget(previousCardButton); + cardSelectionBarLayout->addWidget(nextCardButton); + + layout->addWidget(cardSelectionBar); +} + +void PrintingSelector::updateSortOrder() +{ + if (descendingSort) { + toggleSortOrder->setText(tr("Ascending")); + } else { + toggleSortOrder->setText(tr("Descending")); + } + descendingSort = !descendingSort; + updateDisplay(); +} + +void PrintingSelector::updateDisplay() +{ + flowWidget->clearLayout(); + if (selectedCard != nullptr) { + setWindowTitle(selectedCard->getName()); + } + getAllSetsForCurrentCard(); +} + +void PrintingSelector::setCard(const CardInfoPtr &newCard, const QString &_currentZone) +{ + if (newCard.isNull()) { + return; + } + selectedCard = newCard; + currentZone = _currentZone; + if (isVisible()) { + updateDisplay(); + } + flowWidget->scrollArea->verticalScrollBar()->setValue(0); +} + +void PrintingSelector::selectPreviousCard() +{ + selectCard(-1); +} + +void PrintingSelector::selectNextCard() +{ + selectCard(1); +} + +void PrintingSelector::selectCard(int changeBy) +{ + if (changeBy == 0) { + return; + } + + // Get the current index of the selected item + auto currentIndex = deckView->currentIndex(); + + auto nextIndex = currentIndex.siblingAtRow(currentIndex.row() + changeBy); + if (!nextIndex.isValid()) { + nextIndex = currentIndex; + + // Increment to the next valid index, skipping header rows + AbstractDecklistNode *node; + do { + if (changeBy > 0) { + nextIndex = deckView->indexBelow(nextIndex); + } else { + nextIndex = deckView->indexAbove(nextIndex); + } + node = static_cast(nextIndex.internalPointer()); + } while (node && node->isDeckHeader()); + } + + if (nextIndex.isValid()) { + deckView->setCurrentIndex(nextIndex); + deckView->setFocus(Qt::FocusReason::MouseFocusReason); + } +} + +CardInfoPerSet PrintingSelector::getSetForUUID(const QString &uuid) +{ + CardInfoPerSetMap cardInfoPerSets = selectedCard->getSets(); + + for (const auto &cardInfoPerSet : cardInfoPerSets) { + if (cardInfoPerSet.getProperty("uuid") == uuid) { + return cardInfoPerSet; + } + } + + return CardInfoPerSet(); +} + +QList PrintingSelector::prependPrintingsInDeck(const QList &sets) +{ + CardInfoPerSetMap cardInfoPerSets = selectedCard->getSets(); + QList> countList; + + // Collect sets with their counts + for (const auto &cardInfoPerSet : cardInfoPerSets) { + QModelIndex find_card = + deckModel->findCard(selectedCard->getName(), DECK_ZONE_MAIN, cardInfoPerSet.getProperty("uuid")); + if (find_card.isValid()) { + int count = + deckModel->data(find_card, Qt::DisplayRole).toInt(); // Ensure the count is treated as an integer + if (count > 0) { + countList.append(qMakePair(cardInfoPerSet, count)); + } + } + } + + // Sort sets by count in descending numerical order + std::sort(countList.begin(), countList.end(), + [](const QPair &a, const QPair &b) { + return a.second > b.second; // Ensure numerical comparison + }); + + // Create a copy of the original list to modify + QList result = sets; + + // Prepend sorted sets and remove them from the original list + for (const auto &pair : countList) { + auto it = std::find_if(result.begin(), result.end(), [&pair](const CardInfoPerSet &item) { + return item.getProperty("uuid") == pair.first.getProperty("uuid"); + }); + if (it != result.end()) { + result.erase(it); // Remove the matching entry + } + result.prepend(pair.first); // Prepend the sorted item + } + + return result; +} + +QList PrintingSelector::sortSets() +{ + if (selectedCard.isNull()) { + return {}; + } + CardInfoPerSetMap cardInfoPerSets = selectedCard->getSets(); + + QList sortedSets; + + for (const auto &set : cardInfoPerSets) { + sortedSets << set.getPtr(); + } + + if (sortedSets.empty()) { + sortedSets << CardSet::newInstance("", "", "", QDate()); + } + + if (sortOptionsSelector->currentText() == SORT_OPTIONS_PREFERENCE) { + std::sort(sortedSets.begin(), sortedSets.end(), SetPriorityComparator()); + } else if (sortOptionsSelector->currentText() == SORT_OPTIONS_RELEASE_DATE) { + std::sort(sortedSets.begin(), sortedSets.end(), SetReleaseDateComparator()); + } + + QList sortedCardInfoPerSets; + // Reconstruct sorted list of CardInfoPerSet + for (const auto &set : sortedSets) { + for (auto it = cardInfoPerSets.begin(); it != cardInfoPerSets.end(); ++it) { + if (it.value().getPtr() == set) { + sortedCardInfoPerSets << it.value(); + } + } + } + + if (descendingSort) { + std::reverse(sortedCardInfoPerSets.begin(), sortedCardInfoPerSets.end()); + } + + return sortedCardInfoPerSets; +} + +QList PrintingSelector::filterSets(const QList &sets) const +{ + const QString searchText = searchBar->text().trimmed().toLower(); + + if (searchText.isEmpty()) { + return sets; + } + + QList filteredSets; + + for (const auto &set : sets) { + const QString longName = set.getPtr()->getLongName().toLower(); + const QString shortName = set.getPtr()->getShortName().toLower(); + + if (longName.contains(searchText) || shortName.contains(searchText)) { + filteredSets << set; + } + } + + return filteredSets; +} + +void PrintingSelector::getAllSetsForCurrentCard() +{ + const QList sortedSets = sortSets(); + const QList filteredSets = filterSets(sortedSets); + const QList prependedSets = prependPrintingsInDeck(filteredSets); + + for (const auto &cardInfoPerSet : prependedSets) { + auto *cardDisplayWidget = new PrintingSelectorCardDisplayWidget( + this, deckEditor, deckModel, deckView, cardSizeSlider, selectedCard, cardInfoPerSet, currentZone); + flowWidget->addWidget(cardDisplayWidget); + } +} diff --git a/cockatrice/src/client/ui/widgets/printing_selector/printing_selector.h b/cockatrice/src/client/ui/widgets/printing_selector/printing_selector.h new file mode 100644 index 000000000..1329629fc --- /dev/null +++ b/cockatrice/src/client/ui/widgets/printing_selector/printing_selector.h @@ -0,0 +1,67 @@ +#ifndef PRINTING_SELECTOR_H +#define PRINTING_SELECTOR_H + +#include "../../../../deck/deck_list_model.h" +#include "../../../../deck/deck_view.h" +#include "../../../../game/cards/card_database.h" +#include "../general/layout_containers/flow_widget.h" + +#include +#include +#include +#include +#include +#include + +class TabDeckEditor; +class PrintingSelector : public QWidget +{ + Q_OBJECT + +public: + PrintingSelector(QWidget *parent, TabDeckEditor *deckEditor, DeckListModel *deckModel, QTreeView *deckView); + void setCard(const CardInfoPtr &newCard, const QString &_currentZone); + CardInfoPerSet getSetForUUID(const QString &uuid); + QList prependPrintingsInDeck(const QList &sets); + QList sortSets(); + QList filterSets(const QList &sets) const; + void getAllSetsForCurrentCard(); + +public slots: + void updateDisplay(); + void selectPreviousCard(); + void selectNextCard(); + void updateSortOrder(); + +private: + QVBoxLayout *layout; + QHBoxLayout *sortToolBar; + static const QString SORT_OPTIONS_ALPHABETICAL; + static const QString SORT_OPTIONS_PREFERENCE; + static const QString SORT_OPTIONS_RELEASE_DATE; + static const QString SORT_OPTIONS_CONTAINED_IN_DECK; + static const QString SORT_OPTIONS_POTENTIAL_CARDS; + static const QStringList SORT_OPTIONS; + QComboBox *sortOptionsSelector; + bool descendingSort; + QPushButton *toggleSortOrder; + QLineEdit *searchBar; + QTimer *searchDebounceTimer; + FlowWidget *flowWidget; + QWidget *cardSizeWidget; + QHBoxLayout *cardSizeLayout; + QLabel *cardSizeLabel; + QSlider *cardSizeSlider; + QWidget *cardSelectionBar; + QHBoxLayout *cardSelectionBarLayout; + QPushButton *previousCardButton; + QPushButton *nextCardButton; + TabDeckEditor *deckEditor; + DeckListModel *deckModel; + QTreeView *deckView; + CardInfoPtr selectedCard; + QString currentZone; + void selectCard(int changeBy); +}; + +#endif // PRINTING_SELECTOR_H diff --git a/cockatrice/src/client/ui/widgets/printing_selector/printing_selector_card_display_widget.cpp b/cockatrice/src/client/ui/widgets/printing_selector/printing_selector_card_display_widget.cpp new file mode 100644 index 000000000..1945fa09f --- /dev/null +++ b/cockatrice/src/client/ui/widgets/printing_selector/printing_selector_card_display_widget.cpp @@ -0,0 +1,53 @@ +#include "printing_selector_card_display_widget.h" + +#include "../../../../deck/deck_loader.h" +#include "../../../../game/cards/card_database_manager.h" +#include "card_amount_widget.h" +#include "printing_selector_card_overlay_widget.h" +#include "set_name_and_collectors_number_display_widget.h" + +#include +#include +#include + +PrintingSelectorCardDisplayWidget::PrintingSelectorCardDisplayWidget(QWidget *parent, + TabDeckEditor *deckEditor, + DeckListModel *deckModel, + QTreeView *deckView, + QSlider *cardSizeSlider, + CardInfoPtr rootCard, + CardInfoPerSet setInfoForCard, + QString ¤tZone) + : QWidget(parent), deckEditor(deckEditor), deckModel(deckModel), deckView(deckView), cardSizeSlider(cardSizeSlider), + rootCard(rootCard), setInfoForCard(setInfoForCard), currentZone(currentZone) +{ + layout = new QVBoxLayout(this); + setLayout(layout); + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + + overlayWidget = new PrintingSelectorCardOverlayWidget(this, deckEditor, deckModel, deckView, cardSizeSlider, + rootCard, setInfoForCard); + + const QString combinedSetName = + QString(setInfoForCard.getPtr()->getLongName() + " (" + setInfoForCard.getPtr()->getShortName() + ")"); + setNameAndCollectorsNumberDisplayWidget = + new SetNameAndCollectorsNumberDisplayWidget(this, combinedSetName, setInfoForCard.getProperty("num")); + + layout->addWidget(overlayWidget); + layout->addWidget(setNameAndCollectorsNumberDisplayWidget, 1, Qt::AlignHCenter | Qt::AlignBottom); + setMouseTracking(true); +} + +void PrintingSelectorCardDisplayWidget::enterEvent(QEnterEvent *event) +{ + QWidget::enterEvent(event); + update(); +} + +void PrintingSelectorCardDisplayWidget::resizeEvent(QResizeEvent *event) +{ + QWidget::resizeEvent(event); // Ensure the parent class handles the event first + + // Set the maximum width for the setName QLabel + setNameAndCollectorsNumberDisplayWidget->setMaximumWidth(overlayWidget->width()); +} diff --git a/cockatrice/src/client/ui/widgets/printing_selector/printing_selector_card_display_widget.h b/cockatrice/src/client/ui/widgets/printing_selector/printing_selector_card_display_widget.h new file mode 100644 index 000000000..fa64293f3 --- /dev/null +++ b/cockatrice/src/client/ui/widgets/printing_selector/printing_selector_card_display_widget.h @@ -0,0 +1,53 @@ +#ifndef PRINTING_SELECTOR_CARD_DISPLAY_WIDGET_H +#define PRINTING_SELECTOR_CARD_DISPLAY_WIDGET_H + +#include "../../../../client/ui/widgets/cards/card_info_picture_widget.h" +#include "../../../../deck/deck_list_model.h" +#include "../../../../deck/deck_view.h" +#include "../../../../game/cards/card_database.h" +#include "../../../tabs/tab_deck_editor.h" +#include "all_zones_card_amount_widget.h" +#include "card_amount_widget.h" +#include "printing_selector_card_overlay_widget.h" +#include "set_name_and_collectors_number_display_widget.h" + +#include +#include +#include +#include +#include +#include + +class PrintingSelectorCardDisplayWidget : public QWidget +{ + Q_OBJECT + +public: + PrintingSelectorCardDisplayWidget(QWidget *parent, + TabDeckEditor *deckEditor, + DeckListModel *deckModel, + QTreeView *deckView, + QSlider *cardSizeSlider, + CardInfoPtr rootCard, + CardInfoPerSet setInfoForCard, + QString ¤tZone); + void enterEvent(QEnterEvent *event) override; + void resizeEvent(QResizeEvent *event) override; + +private: + QVBoxLayout *layout; + AllZonesCardAmountWidget *allZonesCardAmountWidget; + SetNameAndCollectorsNumberDisplayWidget *setNameAndCollectorsNumberDisplayWidget; + TabDeckEditor *deckEditor; + DeckListModel *deckModel; + QTreeView *deckView; + QSlider *cardSizeSlider; + CardInfoPtr rootCard; + CardInfoPtr setCard; + CardInfoPerSet setInfoForCard; + QString currentZone; + CardInfoPictureWidget *cardInfoPicture; + PrintingSelectorCardOverlayWidget *overlayWidget; +}; + +#endif // PRINTING_SELECTOR_CARD_DISPLAY_WIDGET_H diff --git a/cockatrice/src/client/ui/widgets/printing_selector/printing_selector_card_overlay_widget.cpp b/cockatrice/src/client/ui/widgets/printing_selector/printing_selector_card_overlay_widget.cpp new file mode 100644 index 000000000..3dd05b9fa --- /dev/null +++ b/cockatrice/src/client/ui/widgets/printing_selector/printing_selector_card_overlay_widget.cpp @@ -0,0 +1,63 @@ +#include "printing_selector_card_overlay_widget.h" + +#include "../../../../game/cards/card_database_manager.h" + +#include + +PrintingSelectorCardOverlayWidget::PrintingSelectorCardOverlayWidget(QWidget *parent, + TabDeckEditor *deckEditor, + DeckListModel *deckModel, + QTreeView *deckView, + QSlider *cardSizeSlider, + CardInfoPtr rootCard, + CardInfoPerSet setInfoForCard) + : QWidget(parent), deckEditor(deckEditor), deckModel(deckModel), deckView(deckView), rootCard(rootCard), + setInfoForCard(setInfoForCard) +{ + // Set up the main layout + auto *mainLayout = new QVBoxLayout(this); + mainLayout->setContentsMargins(0, 0, 0, 0); + mainLayout->setSpacing(0); + setLayout(mainLayout); + + // Add CardInfoPictureWidget + cardInfoPicture = new CardInfoPictureWidget(this); + cardInfoPicture->setMinimumSize(0, 0); + cardInfoPicture->setScaleFactor(cardSizeSlider->value()); + setCard = CardDatabaseManager::getInstance()->getCardByNameAndProviderId(rootCard->getName(), + setInfoForCard.getProperty("uuid")); + cardInfoPicture->setCard(setCard); + mainLayout->addWidget(cardInfoPicture); + + // Add AllZonesCardAmountWidget + allZonesCardAmountWidget = + new AllZonesCardAmountWidget(this, deckEditor, deckModel, deckView, setCard, setInfoForCard); + + allZonesCardAmountWidget->raise(); // Ensure it's on top of the picture + allZonesCardAmountWidget->setVisible(false); + + connect(cardSizeSlider, &QSlider::valueChanged, cardInfoPicture, &CardInfoPictureWidget::setScaleFactor); +} + +void PrintingSelectorCardOverlayWidget::resizeEvent(QResizeEvent *event) +{ + // Ensure the amount widget matches the parent size + QWidget::resizeEvent(event); + if (allZonesCardAmountWidget) { + allZonesCardAmountWidget->resize(cardInfoPicture->size()); + } + resize(cardInfoPicture->size()); +} + +void PrintingSelectorCardOverlayWidget::enterEvent(QEnterEvent *event) +{ + QWidget::enterEvent(event); + allZonesCardAmountWidget->setVisible(true); + deckEditor->updateCardInfo(setCard); +} + +void PrintingSelectorCardOverlayWidget::leaveEvent(QEvent *event) +{ + QWidget::leaveEvent(event); + allZonesCardAmountWidget->setVisible(false); +} \ No newline at end of file diff --git a/cockatrice/src/client/ui/widgets/printing_selector/printing_selector_card_overlay_widget.h b/cockatrice/src/client/ui/widgets/printing_selector/printing_selector_card_overlay_widget.h new file mode 100644 index 000000000..c4817b64f --- /dev/null +++ b/cockatrice/src/client/ui/widgets/printing_selector/printing_selector_card_overlay_widget.h @@ -0,0 +1,48 @@ +#ifndef PRINTING_SELECTOR_CARD_OVERLAY_WIDGET_H +#define PRINTING_SELECTOR_CARD_OVERLAY_WIDGET_H + +#ifndef CARDOVERLAYWIDGET_H +#define CARDOVERLAYWIDGET_H + +#include "../../../../client/ui/widgets/cards/card_info_picture_widget.h" +#include "../../../../deck/deck_list_model.h" +#include "../../../../deck/deck_view.h" +#include "../../../../game/cards/card_database.h" +#include "../../../tabs/tab_deck_editor.h" +#include "all_zones_card_amount_widget.h" +#include "card_amount_widget.h" +#include "set_name_and_collectors_number_display_widget.h" + +class PrintingSelectorCardOverlayWidget : public QWidget +{ + Q_OBJECT + +public: + explicit PrintingSelectorCardOverlayWidget(QWidget *parent, + TabDeckEditor *deckEditor, + DeckListModel *deckModel, + QTreeView *deckView, + QSlider *cardSizeSlider, + CardInfoPtr rootCard, + CardInfoPerSet setInfoForCard); + +protected: + void resizeEvent(QResizeEvent *event) override; + void enterEvent(QEnterEvent *event) override; + void leaveEvent(QEvent *event) override; + +private: + CardInfoPictureWidget *cardInfoPicture; + AllZonesCardAmountWidget *allZonesCardAmountWidget; + TabDeckEditor *deckEditor; + DeckListModel *deckModel; + QTreeView *deckView; + QSlider *cardSizeSlider; + CardInfoPtr rootCard; + CardInfoPtr setCard; + CardInfoPerSet setInfoForCard; +}; + +#endif // CARDOVERLAYWIDGET_H + +#endif // PRINTING_SELECTOR_CARD_OVERLAY_WIDGET_H diff --git a/cockatrice/src/client/ui/widgets/printing_selector/set_name_and_collectors_number_display_widget.cpp b/cockatrice/src/client/ui/widgets/printing_selector/set_name_and_collectors_number_display_widget.cpp new file mode 100644 index 000000000..f8c4fb87f --- /dev/null +++ b/cockatrice/src/client/ui/widgets/printing_selector/set_name_and_collectors_number_display_widget.cpp @@ -0,0 +1,39 @@ +#include "set_name_and_collectors_number_display_widget.h" + +SetNameAndCollectorsNumberDisplayWidget::SetNameAndCollectorsNumberDisplayWidget(QWidget *parent, + const QString &_setName, + const QString &_collectorsNumber) + : QWidget(parent) +{ + layout = new QVBoxLayout(this); + setLayout(layout); + setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred); + setMinimumSize(QWidget::sizeHint()); + + setName = new QLabel(_setName); + setName->setWordWrap(true); + setName->setAlignment(Qt::AlignHCenter | Qt::AlignBottom); + setName->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding); + + collectorsNumber = new QLabel(_collectorsNumber); + collectorsNumber->setAlignment(Qt::AlignHCenter | Qt::AlignBottom); + collectorsNumber->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); + + layout->addWidget(setName); + layout->addWidget(collectorsNumber); +} + +void SetNameAndCollectorsNumberDisplayWidget::resizeEvent(QResizeEvent *event) +{ + QWidget::resizeEvent(event); // Ensure the parent class handles the event first + + QFontMetrics fm(setName->font()); + int labelWidth = setName->width(); // Get the current width of the QLabel + QString text = setName->text(); // The text to be rendered + + // Calculate the height required to render the text with word wrapping + int textHeight = fm.boundingRect(0, 0, labelWidth, 0, Qt::TextWordWrap, text).height(); + + // Set the minimum height to accommodate the required text height + setName->setMinimumHeight(textHeight); +} diff --git a/cockatrice/src/client/ui/widgets/printing_selector/set_name_and_collectors_number_display_widget.h b/cockatrice/src/client/ui/widgets/printing_selector/set_name_and_collectors_number_display_widget.h new file mode 100644 index 000000000..3fa051f9d --- /dev/null +++ b/cockatrice/src/client/ui/widgets/printing_selector/set_name_and_collectors_number_display_widget.h @@ -0,0 +1,21 @@ +#ifndef SET_NAME_AND_COLLECTORS_NUMBER_DISPLAY_WIDGET_H +#define SET_NAME_AND_COLLECTORS_NUMBER_DISPLAY_WIDGET_H + +#include +#include +#include + +class SetNameAndCollectorsNumberDisplayWidget : public QWidget +{ + Q_OBJECT +public: + SetNameAndCollectorsNumberDisplayWidget(QWidget *parent, const QString &setName, const QString &collectorsNumber); + void resizeEvent(QResizeEvent *event) override; + +private: + QVBoxLayout *layout; + QLabel *setName; + QLabel *collectorsNumber; +}; + +#endif // SET_NAME_AND_COLLECTORS_NUMBER_DISPLAY_WIDGET_H diff --git a/cockatrice/src/deck/deck_list_model.cpp b/cockatrice/src/deck/deck_list_model.cpp index a33e72c7e..cc60444c5 100644 --- a/cockatrice/src/deck/deck_list_model.cpp +++ b/cockatrice/src/deck/deck_list_model.cpp @@ -332,9 +332,6 @@ DeckListModel::findCardNode(const QString &cardName, const QString &zoneName, co return nullptr; } - if (providerId.isEmpty()) { - return dynamic_cast(typeNode->findChild(cardName)); - } return dynamic_cast(typeNode->findCardChildByNameAndProviderId(cardName, providerId)); } diff --git a/cockatrice/src/deck/deck_list_model.h b/cockatrice/src/deck/deck_list_model.h index 24eaea612..486ca799b 100644 --- a/cockatrice/src/deck/deck_list_model.h +++ b/cockatrice/src/deck/deck_list_model.h @@ -66,6 +66,10 @@ public: { return dataNode; } + [[nodiscard]] bool isDeckHeader() const override + { + return false; + } }; class DeckListModel : public QAbstractItemModel diff --git a/cockatrice/src/game/cards/card_database.cpp b/cockatrice/src/game/cards/card_database.cpp index 5372bc1ff..70da23bff 100644 --- a/cockatrice/src/game/cards/card_database.cpp +++ b/cockatrice/src/game/cards/card_database.cpp @@ -614,7 +614,7 @@ void CardDatabase::refreshPreferredPrintings() } } -CardInfoPerSet CardDatabase::getPreferredSetForCard(const QString &cardName) +CardInfoPerSet CardDatabase::getPreferredSetForCard(const QString &cardName) const { CardInfoPtr cardInfo = getCard(cardName); if (!cardInfo) { @@ -663,6 +663,10 @@ CardInfoPerSet CardDatabase::getSpecificSetForCard(const QString &cardName, cons } } + if (providerId.isNull()) { + return getPreferredSetForCard(cardName); + } + return CardInfoPerSet(nullptr); } diff --git a/cockatrice/src/game/cards/card_database.h b/cockatrice/src/game/cards/card_database.h index 6f73f16a4..b508a3fe5 100644 --- a/cockatrice/src/game/cards/card_database.h +++ b/cockatrice/src/game/cards/card_database.h @@ -450,19 +450,19 @@ public: ~CardDatabase() override; void clear(); void removeCard(CardInfoPtr card); - CardInfoPtr getCard(const QString &cardName) const; - QList getCards(const QStringList &cardNames) const; - CardInfoPtr getCardByNameAndProviderId(const QString &cardName, const QString &providerId) const; - CardInfoPerSet getPreferredSetForCard(const QString &cardName); - CardInfoPerSet getSpecificSetForCard(const QString &cardName, const QString &providerId) const; + [[nodiscard]] CardInfoPtr getCard(const QString &cardName) const; + [[nodiscard]] QList getCards(const QStringList &cardNames) const; + [[nodiscard]] CardInfoPtr getCardByNameAndProviderId(const QString &cardName, const QString &providerId) const; + [[nodiscard]] CardInfoPerSet getPreferredSetForCard(const QString &cardName) const; + [[nodiscard]] CardInfoPerSet getSpecificSetForCard(const QString &cardName, const QString &providerId) const; QString getPreferredPrintingProviderIdForCard(const QString &cardName); - CardInfoPtr guessCard(const QString &cardName) const; + [[nodiscard]] CardInfoPtr guessCard(const QString &cardName) const; /* * Get a card by its simple name. The name will be simplified in this * function, so you don't need to simplify it beforehand. */ - CardInfoPtr getCardBySimpleName(const QString &cardName) const; + [[nodiscard]] CardInfoPtr getCardBySimpleName(const QString &cardName) const; CardSetPtr getSet(const QString &setName); bool isProviderIdForPreferredPrinting(const QString &cardName, const QString &providerId); diff --git a/cockatrice/src/settings/layouts_settings.cpp b/cockatrice/src/settings/layouts_settings.cpp index 7e17451b9..5791cbfe9 100644 --- a/cockatrice/src/settings/layouts_settings.cpp +++ b/cockatrice/src/settings/layouts_settings.cpp @@ -1,6 +1,6 @@ #include "layouts_settings.h" -LayoutsSettings::LayoutsSettings(QString settingPath, QObject *parent) +LayoutsSettings::LayoutsSettings(const QString &settingPath, QObject *parent) : SettingsManager(settingPath + "layouts.ini", parent) { } @@ -25,7 +25,7 @@ void LayoutsSettings::setDeckEditorGeometry(const QByteArray &value) setValue(value, "layouts/deckEditor_geometry"); } -const QSize LayoutsSettings::getDeckEditorCardSize() +QSize LayoutsSettings::getDeckEditorCardSize() { QVariant previous = getValue("layouts/deckEditor_CardSize"); return previous == QVariant() ? QSize(250, 500) : previous.toSize(); @@ -36,7 +36,7 @@ void LayoutsSettings::setDeckEditorCardSize(const QSize &value) setValue(value, "layouts/deckEditor_CardSize"); } -const QSize LayoutsSettings::getDeckEditorDeckSize() +QSize LayoutsSettings::getDeckEditorDeckSize() { QVariant previous = getValue("layouts/deckEditor_DeckSize"); return previous == QVariant() ? QSize(250, 360) : previous.toSize(); @@ -47,7 +47,18 @@ void LayoutsSettings::setDeckEditorDeckSize(const QSize &value) setValue(value, "layouts/deckEditor_DeckSize"); } -const QSize LayoutsSettings::getDeckEditorFilterSize() +QSize LayoutsSettings::getDeckEditorPrintingSelectorSize() +{ + QVariant previous = getValue("layouts/deckEditor_PrintingSelectorSize"); + return previous == QVariant() ? QSize(525, 250) : previous.toSize(); +} + +void LayoutsSettings::setDeckEditorPrintingSelectorSize(const QSize &value) +{ + setValue(value, "layouts/deckEditor_PrintingSelectorSize"); +} + +QSize LayoutsSettings::getDeckEditorFilterSize() { QVariant previous = getValue("layouts/deckEditor_FilterSize"); return previous == QVariant() ? QSize(250, 250) : previous.toSize(); diff --git a/cockatrice/src/settings/layouts_settings.h b/cockatrice/src/settings/layouts_settings.h index 80bd71fe8..0464bec01 100644 --- a/cockatrice/src/settings/layouts_settings.h +++ b/cockatrice/src/settings/layouts_settings.h @@ -15,6 +15,7 @@ public: void setDeckEditorGeometry(const QByteArray &value); void setDeckEditorCardSize(const QSize &value); void setDeckEditorDeckSize(const QSize &value); + void setDeckEditorPrintingSelectorSize(const QSize &value); void setDeckEditorFilterSize(const QSize &value); void setDeckEditorDbHeaderState(const QByteArray &value); void setSetsDialogHeaderState(const QByteArray &value); @@ -34,9 +35,10 @@ public: const QByteArray getDeckEditorLayoutState(); const QByteArray getDeckEditorGeometry(); - const QSize getDeckEditorCardSize(); - const QSize getDeckEditorDeckSize(); - const QSize getDeckEditorFilterSize(); + QSize getDeckEditorCardSize(); + QSize getDeckEditorDeckSize(); + QSize getDeckEditorPrintingSelectorSize(); + QSize getDeckEditorFilterSize(); const QByteArray getDeckEditorDbHeaderState(); const QByteArray getSetsDialogHeaderState(); @@ -57,7 +59,7 @@ signals: public slots: private: - explicit LayoutsSettings(QString settingPath, QObject *parent = nullptr); + explicit LayoutsSettings(const QString &settingPath, QObject *parent = nullptr); LayoutsSettings(const LayoutsSettings & /*other*/); }; diff --git a/cockatrice/src/utility/card_set_comparator.h b/cockatrice/src/utility/card_set_comparator.h index 1aa1500fb..107b618fb 100644 --- a/cockatrice/src/utility/card_set_comparator.h +++ b/cockatrice/src/utility/card_set_comparator.h @@ -21,4 +21,40 @@ public: } }; +class SetReleaseDateComparator +{ +public: + /* + * Returns true if a has higher download priority than b + * Enabled sets have priority over disabled sets + * Both groups follow the user-defined order + */ + inline bool operator()(const CardSetPtr &a, const CardSetPtr &b) const + { + if (a->getEnabled()) { + return !b->getEnabled() || a->getReleaseDate() < b->getReleaseDate(); + } else { + return !b->getEnabled() && a->getReleaseDate() < b->getReleaseDate(); + } + } +}; + +class CardSetPriorityComparator +{ +public: + /* + * Returns true if a has higher download priority than b + * Enabled sets have priority over disabled sets + * Both groups follow the user-defined order + */ + inline bool operator()(const CardInfoPerSet &a, const CardInfoPerSet &b) const + { + if (a.getPtr()->getEnabled()) { + return !b.getPtr()->getEnabled() || a.getPtr()->getSortKey() < b.getPtr()->getSortKey(); + } else { + return !b.getPtr()->getEnabled() && a.getPtr()->getSortKey() < b.getPtr()->getSortKey(); + } + } +}; + #endif // SET_PRIORITY_COMPARATOR_H \ No newline at end of file diff --git a/common/decklist.cpp b/common/decklist.cpp index 011c9e0f3..b269d43f0 100644 --- a/common/decklist.cpp +++ b/common/decklist.cpp @@ -319,13 +319,13 @@ void AbstractDecklistCardNode::writeElement(QXmlStreamWriter *xml) xml->writeAttribute("number", QString::number(getNumber())); xml->writeAttribute("name", getName()); - if (getCardSetShortName().isEmpty()) { + if (!getCardSetShortName().isEmpty()) { xml->writeAttribute("setShortName", getCardSetShortName()); } - if (getCardCollectorNumber().isEmpty()) { + if (!getCardCollectorNumber().isEmpty()) { xml->writeAttribute("collectorNumber", getCardCollectorNumber()); } - if (getCardProviderId().isEmpty()) { + if (!getCardProviderId().isEmpty()) { xml->writeAttribute("uuid", getCardProviderId()); } } diff --git a/common/decklist.h b/common/decklist.h index ad5f59b22..02b3a537d 100644 --- a/common/decklist.h +++ b/common/decklist.h @@ -66,6 +66,7 @@ public: virtual QString getCardProviderId() const = 0; virtual QString getCardSetShortName() const = 0; virtual QString getCardCollectorNumber() const = 0; + [[nodiscard]] virtual bool isDeckHeader() const = 0; InnerDecklistNode *getParent() const { return parent; @@ -128,6 +129,10 @@ public: { cardCollectorNumber = _cardCollectorNumber; } + [[nodiscard]] bool isDeckHeader() const override + { + return true; + } void clearTree(); AbstractDecklistNode *findChild(const QString &_name); @@ -233,6 +238,10 @@ public: { cardSetNumber = _cardSetNumber; } + [[nodiscard]] bool isDeckHeader() const override + { + return false; + } }; class DeckList : public QObject