diff --git a/cockatrice/CMakeLists.txt b/cockatrice/CMakeLists.txt index 2501f0fb9..f8be8aca5 100644 --- a/cockatrice/CMakeLists.txt +++ b/cockatrice/CMakeLists.txt @@ -198,6 +198,7 @@ set(cockatrice_SOURCES src/game/cards/card_database_parser/cockatrice_xml_4.cpp src/game/cards/card_info.cpp src/game/cards/card_search_model.cpp + src/game/cards/exact_card.cpp src/game/deckview/deck_view.cpp src/game/deckview/deck_view_container.cpp src/game/filters/deck_filter_string.cpp diff --git a/cockatrice/src/client/tabs/abstract_tab_deck_editor.cpp b/cockatrice/src/client/tabs/abstract_tab_deck_editor.cpp index 6467ceb66..b6908ce94 100644 --- a/cockatrice/src/client/tabs/abstract_tab_deck_editor.cpp +++ b/cockatrice/src/client/tabs/abstract_tab_deck_editor.cpp @@ -72,10 +72,10 @@ AbstractTabDeckEditor::AbstractTabDeckEditor(TabSupervisor *_tabSupervisor) : Ta &AbstractTabDeckEditor::refreshShortcuts); } -void AbstractTabDeckEditor::updateCard(CardInfoPtr _card) +void AbstractTabDeckEditor::updateCard(const ExactCard &card) { - cardInfoDockWidget->updateCard(_card); - printingSelectorDockWidget->printingSelector->setCard(_card, DECK_ZONE_MAIN); + cardInfoDockWidget->updateCard(card); + printingSelectorDockWidget->printingSelector->setCard(card.getCardPtr(), DECK_ZONE_MAIN); } void AbstractTabDeckEditor::onDeckChanged() @@ -88,14 +88,14 @@ void AbstractTabDeckEditor::onDeckModified() deckMenu->setSaveStatus(!isBlankNewDeck()); } -void AbstractTabDeckEditor::addCardHelper(const CardInfoPtr info, QString zoneName) +void AbstractTabDeckEditor::addCardHelper(const ExactCard &card, QString zoneName) { - if (!info) + if (!card) return; - if (info->getIsToken()) + if (card.getInfo().getIsToken()) zoneName = DECK_ZONE_TOKENS; - QModelIndex newCardIndex = deckDockWidget->deckModel->addPreferredPrintingCard(info->getName(), zoneName, false); + QModelIndex newCardIndex = deckDockWidget->deckModel->addCard(card, zoneName); // recursiveExpand(newCardIndex); deckDockWidget->deckView->clearSelection(); deckDockWidget->deckView->setCurrentIndex(newCardIndex); @@ -103,39 +103,39 @@ void AbstractTabDeckEditor::addCardHelper(const CardInfoPtr info, QString zoneNa databaseDisplayDockWidget->searchEdit->setSelection(0, databaseDisplayDockWidget->searchEdit->text().length()); } -void AbstractTabDeckEditor::actAddCard(CardInfoPtr info) +void AbstractTabDeckEditor::actAddCard(const ExactCard &card) { if (QApplication::keyboardModifiers() & Qt::ControlModifier) - actAddCardToSideboard(info); + actAddCardToSideboard(card); else - addCardHelper(info, DECK_ZONE_MAIN); + addCardHelper(card, DECK_ZONE_MAIN); deckMenu->setSaveStatus(true); } -void AbstractTabDeckEditor::actAddCardToSideboard(CardInfoPtr info) +void AbstractTabDeckEditor::actAddCardToSideboard(const ExactCard &card) { - addCardHelper(info, DECK_ZONE_SIDE); + addCardHelper(card, DECK_ZONE_SIDE); deckMenu->setSaveStatus(true); } -void AbstractTabDeckEditor::actDecrementCard(CardInfoPtr info) +void AbstractTabDeckEditor::actDecrementCard(const ExactCard &card) { - emit decrementCard(info, DECK_ZONE_MAIN); + emit decrementCard(card, DECK_ZONE_MAIN); } -void AbstractTabDeckEditor::actDecrementCardFromSideboard(CardInfoPtr info) +void AbstractTabDeckEditor::actDecrementCardFromSideboard(const ExactCard &card) { - emit decrementCard(info, DECK_ZONE_SIDE); + emit decrementCard(card, DECK_ZONE_SIDE); } -void AbstractTabDeckEditor::actSwapCard(CardInfoPtr info, QString zoneName) +void AbstractTabDeckEditor::actSwapCard(const ExactCard &card, const QString &zoneName) { - QString providerId = CardDatabaseManager::getInstance()->getSetInfoForCard(info).getUuid(); - QString collectorNumber = CardDatabaseManager::getInstance()->getSetInfoForCard(info).getProperty("num"); + QString providerId = card.getPrinting().getUuid(); + QString collectorNumber = card.getPrinting().getProperty("num"); - QModelIndex foundCard = deckDockWidget->deckModel->findCard(info->getName(), zoneName, providerId, collectorNumber); + QModelIndex foundCard = deckDockWidget->deckModel->findCard(card.getName(), zoneName, providerId, collectorNumber); if (!foundCard.isValid()) { - foundCard = deckDockWidget->deckModel->findCard(info->getName(), zoneName); + foundCard = deckDockWidget->deckModel->findCard(card.getName(), zoneName); } deckDockWidget->swapCard(foundCard); diff --git a/cockatrice/src/client/tabs/abstract_tab_deck_editor.h b/cockatrice/src/client/tabs/abstract_tab_deck_editor.h index 8179b99ed..7b52ff3b6 100644 --- a/cockatrice/src/client/tabs/abstract_tab_deck_editor.h +++ b/cockatrice/src/client/tabs/abstract_tab_deck_editor.h @@ -71,11 +71,11 @@ public: public slots: virtual void onDeckChanged(); virtual void onDeckModified(); - void updateCard(CardInfoPtr _card); - void actAddCard(CardInfoPtr info); - void actAddCardToSideboard(CardInfoPtr info); - void actDecrementCard(CardInfoPtr info); - void actDecrementCardFromSideboard(CardInfoPtr info); + void updateCard(const ExactCard &card); + void actAddCard(const ExactCard &card); + void actAddCardToSideboard(const ExactCard &card); + void actDecrementCard(const ExactCard &card); + void actDecrementCardFromSideboard(const ExactCard &card); void actOpenRecent(const QString &fileName); void filterTreeChanged(FilterTree *filterTree); void closeRequest(bool forced = false) override; @@ -85,7 +85,7 @@ public slots: signals: void openDeckEditor(const DeckLoader *deckLoader); void deckEditorClosing(AbstractTabDeckEditor *tab); - void decrementCard(CardInfoPtr card, QString zoneName); + void decrementCard(const ExactCard &card, QString zoneName); protected slots: // Deck Operations @@ -142,8 +142,8 @@ protected: bool isBlankNewDeck() const; // Helper functions for card actions - void addCardHelper(CardInfoPtr info, QString zoneName); - void actSwapCard(CardInfoPtr info, QString zoneName); + void addCardHelper(const ExactCard &card, QString zoneName); + void actSwapCard(const ExactCard &card, const QString &zoneName); virtual void openDeckFromFile(const QString &fileName, DeckOpenLocation deckOpenLocation); // UI Menu Elements diff --git a/cockatrice/src/client/tabs/tab_deck_editor.cpp b/cockatrice/src/client/tabs/tab_deck_editor.cpp index 1179c5a92..45762a76a 100644 --- a/cockatrice/src/client/tabs/tab_deck_editor.cpp +++ b/cockatrice/src/client/tabs/tab_deck_editor.cpp @@ -150,7 +150,8 @@ void TabDeckEditor::refreshShortcuts() void TabDeckEditor::showPrintingSelector() { - printingSelectorDockWidget->printingSelector->setCard(cardInfoDockWidget->cardInfo->getInfo(), DECK_ZONE_MAIN); + printingSelectorDockWidget->printingSelector->setCard(cardInfoDockWidget->cardInfo->getCard().getCardPtr(), + DECK_ZONE_MAIN); printingSelectorDockWidget->printingSelector->updateDisplay(); aPrintingSelectorDockVisible->setChecked(true); printingSelectorDockWidget->setVisible(true); diff --git a/cockatrice/src/client/tabs/visual_deck_editor/tab_deck_editor_visual.cpp b/cockatrice/src/client/tabs/visual_deck_editor/tab_deck_editor_visual.cpp index 7e3ce3c5b..960e5419f 100644 --- a/cockatrice/src/client/tabs/visual_deck_editor/tab_deck_editor_visual.cpp +++ b/cockatrice/src/client/tabs/visual_deck_editor/tab_deck_editor_visual.cpp @@ -153,15 +153,15 @@ QString TabDeckEditorVisual::getTabText() const return result; } -void TabDeckEditorVisual::changeModelIndexAndCardInfo(const CardInfoPtr &activeCard) +void TabDeckEditorVisual::changeModelIndexAndCardInfo(const ExactCard &activeCard) { updateCard(activeCard); changeModelIndexToCard(activeCard); } -void TabDeckEditorVisual::changeModelIndexToCard(const CardInfoPtr &activeCard) +void TabDeckEditorVisual::changeModelIndexToCard(const ExactCard &activeCard) { - QString cardName = activeCard->getName(); + QString cardName = activeCard.getName(); QModelIndex index = deckDockWidget->deckModel->findCard(cardName, DECK_ZONE_MAIN); if (!index.isValid()) { index = deckDockWidget->deckModel->findCard(cardName, DECK_ZONE_SIDE); @@ -174,9 +174,9 @@ void TabDeckEditorVisual::processMainboardCardClick(QMouseEvent *event, QString zoneName) { if (event->button() == Qt::LeftButton) { - actSwapCard(instance->getInfo(), zoneName); + actSwapCard(instance->getCard(), zoneName); } else if (event->button() == Qt::RightButton) { - actDecrementCard(instance->getInfo()); + actDecrementCard(instance->getCard()); } else if (event->button() == Qt::MiddleButton) { deckDockWidget->actRemoveCard(); } @@ -186,9 +186,9 @@ void TabDeckEditorVisual::processCardClickDatabaseDisplay(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *instance) { if (event->button() == Qt::LeftButton) { - actAddCard(instance->getInfo()); + actAddCard(instance->getCard()); } else if (event->button() == Qt::RightButton) { - actDecrementCard(instance->getInfo()); + actDecrementCard(instance->getCard()); } else if (event->button() == Qt::MiddleButton) { deckDockWidget->actRemoveCard(); } @@ -205,7 +205,8 @@ bool TabDeckEditorVisual::actSaveDeckAs() void TabDeckEditorVisual::showPrintingSelector() { - printingSelectorDockWidget->printingSelector->setCard(cardInfoDockWidget->cardInfo->getInfo(), DECK_ZONE_MAIN); + printingSelectorDockWidget->printingSelector->setCard(cardInfoDockWidget->cardInfo->getCard().getCardPtr(), + DECK_ZONE_MAIN); printingSelectorDockWidget->printingSelector->updateDisplay(); aPrintingSelectorDockVisible->setChecked(true); printingSelectorDockWidget->setVisible(true); diff --git a/cockatrice/src/client/tabs/visual_deck_editor/tab_deck_editor_visual.h b/cockatrice/src/client/tabs/visual_deck_editor/tab_deck_editor_visual.h index f4add316e..36bb8ef9a 100644 --- a/cockatrice/src/client/tabs/visual_deck_editor/tab_deck_editor_visual.h +++ b/cockatrice/src/client/tabs/visual_deck_editor/tab_deck_editor_visual.h @@ -34,8 +34,8 @@ public: explicit TabDeckEditorVisual(TabSupervisor *_tabSupervisor); void retranslateUi() override; QString getTabText() const override; - void changeModelIndexAndCardInfo(const CardInfoPtr &activeCard); - void changeModelIndexToCard(const CardInfoPtr &activeCard); + void changeModelIndexAndCardInfo(const ExactCard &activeCard); + void changeModelIndexToCard(const ExactCard &activeCard); void createDeckAnalyticsDock(); void createMenus() override; void createSearchAndDatabaseFrame(); diff --git a/cockatrice/src/client/tabs/visual_deck_editor/tab_deck_editor_visual_tab_widget.cpp b/cockatrice/src/client/tabs/visual_deck_editor/tab_deck_editor_visual_tab_widget.cpp index a34d7ad94..f0bf008dd 100644 --- a/cockatrice/src/client/tabs/visual_deck_editor/tab_deck_editor_visual_tab_widget.cpp +++ b/cockatrice/src/client/tabs/visual_deck_editor/tab_deck_editor_visual_tab_widget.cpp @@ -46,12 +46,12 @@ TabDeckEditorVisualTabWidget::TabDeckEditorVisualTabWidget(QWidget *parent, this->addNewTab(sampleHandWidget, tr("Sample Hand")); } -void TabDeckEditorVisualTabWidget::onCardChanged(CardInfoPtr activeCard) +void TabDeckEditorVisualTabWidget::onCardChanged(const ExactCard &activeCard) { emit cardChanged(activeCard); } -void TabDeckEditorVisualTabWidget::onCardChangedDatabaseDisplay(CardInfoPtr activeCard) +void TabDeckEditorVisualTabWidget::onCardChangedDatabaseDisplay(const ExactCard &activeCard) { emit cardChangedDatabaseDisplay(activeCard); } diff --git a/cockatrice/src/client/tabs/visual_deck_editor/tab_deck_editor_visual_tab_widget.h b/cockatrice/src/client/tabs/visual_deck_editor/tab_deck_editor_visual_tab_widget.h index c2454538a..37a17e7d2 100644 --- a/cockatrice/src/client/tabs/visual_deck_editor/tab_deck_editor_visual_tab_widget.h +++ b/cockatrice/src/client/tabs/visual_deck_editor/tab_deck_editor_visual_tab_widget.h @@ -37,14 +37,14 @@ public: VisualDeckEditorSampleHandWidget *sampleHandWidget; public slots: - void onCardChanged(CardInfoPtr activeCard); - void onCardChangedDatabaseDisplay(CardInfoPtr activeCard); + void onCardChanged(const ExactCard &activeCard); + void onCardChangedDatabaseDisplay(const ExactCard &activeCard); void onCardClickedDeckEditor(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *instance, QString zoneName); void onCardClickedDatabaseDisplay(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *instance); signals: - void cardChanged(CardInfoPtr activeCard); - void cardChangedDatabaseDisplay(CardInfoPtr activeCard); + void cardChanged(const ExactCard &activeCard); + void cardChangedDatabaseDisplay(const ExactCard &activeCard); void cardClicked(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *instance, QString zoneName); void cardClickedDatabaseDisplay(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *instance); diff --git a/cockatrice/src/client/ui/picture_loader/picture_loader.cpp b/cockatrice/src/client/ui/picture_loader/picture_loader.cpp index 5bf873cbd..8ee159cbf 100644 --- a/cockatrice/src/client/ui/picture_loader/picture_loader.cpp +++ b/cockatrice/src/client/ui/picture_loader/picture_loader.cpp @@ -108,14 +108,14 @@ void PictureLoader::getCardBackLoadingFailedPixmap(QPixmap &pixmap, QSize size) } } -void PictureLoader::getPixmap(QPixmap &pixmap, CardInfoPtr card, QSize size) +void PictureLoader::getPixmap(QPixmap &pixmap, const ExactCard &card, QSize size) { if (!card) { qCWarning(PictureLoaderLog) << "getPixmap called with null card!"; return; } - QString key = card->getPixmapCacheKey(); + QString key = card.getPixmapCacheKey(); QString sizeKey = key + QLatin1Char('_') + QString::number(size.width()) + "x" + QString::number(size.height()); if (QPixmapCache::find(sizeKey, &pixmap)) { @@ -132,7 +132,7 @@ void PictureLoader::getPixmap(QPixmap &pixmap, CardInfoPtr card, QSize size) QScreen *screen = qApp->primaryScreen(); qreal dpr = screen ? screen->devicePixelRatio() : 1.0; - qCDebug(PictureLoaderLog) << "Scaling cached image for" << card->getName(); + qCDebug(PictureLoaderLog) << "Scaling cached image for" << card.getName(); pixmap = bigPixmap.scaled(size * dpr, Qt::KeepAspectRatio, Qt::SmoothTransformation); pixmap.setDevicePixelRatio(dpr); @@ -141,36 +141,35 @@ void PictureLoader::getPixmap(QPixmap &pixmap, CardInfoPtr card, QSize size) } // add the card to the load queue - qCDebug(PictureLoaderLog) << "Enqueuing " << card->getName() << " for " << card->getPixmapCacheKey(); + qCDebug(PictureLoaderLog) << "Enqueuing " << card.getName() << " for " << card.getPixmapCacheKey(); getInstance().worker->enqueueImageLoad(card); } -void PictureLoader::imageLoaded(CardInfoPtr card, const QImage &image) +void PictureLoader::imageLoaded(const ExactCard &card, const QImage &image) { if (image.isNull()) { - qCDebug(PictureLoaderLog) << "Caching NULL pixmap for" << card->getName(); - QPixmapCache::insert(card->getPixmapCacheKey(), QPixmap()); + qCDebug(PictureLoaderLog) << "Caching NULL pixmap for" << card.getName(); + QPixmapCache::insert(card.getPixmapCacheKey(), QPixmap()); } else { - if (card->getUpsideDownArt()) { + if (card.getInfo().getUpsideDownArt()) { #if (QT_VERSION >= QT_VERSION_CHECK(6, 9, 0)) QImage mirrorImage = image.flipped(Qt::Horizontal | Qt::Vertical); #else QImage mirrorImage = image.mirrored(true, true); #endif - QPixmapCache::insert(card->getPixmapCacheKey(), QPixmap::fromImage(mirrorImage)); + QPixmapCache::insert(card.getPixmapCacheKey(), QPixmap::fromImage(mirrorImage)); } else { - QPixmapCache::insert(card->getPixmapCacheKey(), QPixmap::fromImage(image)); + QPixmapCache::insert(card.getPixmapCacheKey(), QPixmap::fromImage(image)); } } - card->emitPixmapUpdated(); -} + // imageLoaded should only be reached if the exactCard isn't already in cache. + // (plus there's a deduplication mechanism in PictureLoaderWorker) + // It should be safe to connect the CardInfo here without worrying about redundant connections. + connect(card.getCardPtr().data(), &QObject::destroyed, this, + [cacheKey = card.getPixmapCacheKey()] { QPixmapCache::remove(cacheKey); }); -void PictureLoader::clearPixmapCache(CardInfoPtr card) -{ - if (card) { - QPixmapCache::remove(card->getPixmapCacheKey()); - } + card.emitPixmapUpdated(); } void PictureLoader::clearPixmapCache() @@ -183,17 +182,17 @@ void PictureLoader::clearNetworkCache() getInstance().worker->clearNetworkCache(); } -void PictureLoader::cacheCardPixmaps(QList cards) +void PictureLoader::cacheCardPixmaps(const QList &cards) { QPixmap tmp; int max = qMin(cards.size(), CACHED_CARD_PER_DECK_MAX); for (int i = 0; i < max; ++i) { - const CardInfoPtr &card = cards.at(i); + const ExactCard &card = cards.at(i); if (!card) { continue; } - QString key = card->getPixmapCacheKey(); + QString key = card.getPixmapCacheKey(); if (QPixmapCache::find(key, &tmp)) { continue; } diff --git a/cockatrice/src/client/ui/picture_loader/picture_loader.h b/cockatrice/src/client/ui/picture_loader/picture_loader.h index 87ebfa862..43dde56c7 100644 --- a/cockatrice/src/client/ui/picture_loader/picture_loader.h +++ b/cockatrice/src/client/ui/picture_loader/picture_loader.h @@ -31,13 +31,12 @@ private: PictureLoaderStatusBar *statusBar; public: - static void getPixmap(QPixmap &pixmap, CardInfoPtr card, QSize size); + static void getPixmap(QPixmap &pixmap, const ExactCard &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); + static void cacheCardPixmaps(const QList &cards); static bool hasCustomArt(); public slots: @@ -48,6 +47,6 @@ private slots: void picsPathChanged(); public slots: - void imageLoaded(CardInfoPtr card, const QImage &image); + void imageLoaded(const ExactCard &card, const QImage &image); }; #endif diff --git a/cockatrice/src/client/ui/picture_loader/picture_loader_local.cpp b/cockatrice/src/client/ui/picture_loader/picture_loader_local.cpp index f2e8a0c6f..93de59a78 100644 --- a/cockatrice/src/client/ui/picture_loader/picture_loader_local.cpp +++ b/cockatrice/src/client/ui/picture_loader/picture_loader_local.cpp @@ -52,14 +52,12 @@ void PictureLoaderLocal::refreshIndex() * @param toLoad The card to load * @return The loaded image, or an empty QImage if loading failed. */ -QImage PictureLoaderLocal::tryLoad(const CardInfoPtr &toLoad) const +QImage PictureLoaderLocal::tryLoad(const ExactCard &toLoad) const { - CardSetPtr set = PictureToLoad::extractSetsSorted(toLoad).first(); + PrintingInfo setInstance = toLoad.getPrinting(); - PrintingInfo setInstance = CardDatabaseManager::getInstance()->getSetInfoForCard(toLoad); - - QString cardName = toLoad->getName(); - QString correctedCardName = toLoad->getCorrectedName(); + QString cardName = toLoad.getName(); + QString correctedCardName = toLoad.getInfo().getCorrectedName(); QString setName, collectorNumber, providerId; diff --git a/cockatrice/src/client/ui/picture_loader/picture_loader_local.h b/cockatrice/src/client/ui/picture_loader/picture_loader_local.h index 38b9fd0c3..a493c46df 100644 --- a/cockatrice/src/client/ui/picture_loader/picture_loader_local.h +++ b/cockatrice/src/client/ui/picture_loader/picture_loader_local.h @@ -1,7 +1,7 @@ #ifndef PICTURE_LOADER_LOCAL_H #define PICTURE_LOADER_LOCAL_H -#include "../../../game/cards/card_info.h" +#include "../../../game/cards/exact_card.h" #include #include @@ -20,7 +20,7 @@ class PictureLoaderLocal : public QObject public: explicit PictureLoaderLocal(QObject *parent); - QImage tryLoad(const CardInfoPtr &toLoad) const; + QImage tryLoad(const ExactCard &toLoad) const; private: QString picsPath, customPicsPath; diff --git a/cockatrice/src/client/ui/picture_loader/picture_loader_request_status_display_widget.cpp b/cockatrice/src/client/ui/picture_loader/picture_loader_request_status_display_widget.cpp index a792087d5..6403f576c 100644 --- a/cockatrice/src/client/ui/picture_loader/picture_loader_request_status_display_widget.cpp +++ b/cockatrice/src/client/ui/picture_loader/picture_loader_request_status_display_widget.cpp @@ -2,18 +2,18 @@ PictureLoaderRequestStatusDisplayWidget::PictureLoaderRequestStatusDisplayWidget(QWidget *parent, const QUrl &_url, - const CardInfoPtr &card, + const ExactCard &card, const QString &setName) : QWidget(parent) { layout = new QHBoxLayout(this); name = new QLabel(this); - name->setText(card->getName()); + name->setText(card.getName()); setShortname = new QLabel(this); setShortname->setText(setName); providerId = new QLabel(this); - providerId->setText(card->getProperty("uuid")); + providerId->setText(card.getPrinting().getUuid()); layout->addWidget(name); layout->addWidget(setShortname); diff --git a/cockatrice/src/client/ui/picture_loader/picture_loader_request_status_display_widget.h b/cockatrice/src/client/ui/picture_loader/picture_loader_request_status_display_widget.h index 46a809e47..79da7a8e4 100644 --- a/cockatrice/src/client/ui/picture_loader/picture_loader_request_status_display_widget.h +++ b/cockatrice/src/client/ui/picture_loader/picture_loader_request_status_display_widget.h @@ -12,7 +12,7 @@ class PictureLoaderRequestStatusDisplayWidget : public QWidget public: PictureLoaderRequestStatusDisplayWidget(QWidget *parent, const QUrl &url, - const CardInfoPtr &card, + const ExactCard &card, const QString &setName); void setFinished() diff --git a/cockatrice/src/client/ui/picture_loader/picture_loader_status_bar.cpp b/cockatrice/src/client/ui/picture_loader/picture_loader_status_bar.cpp index a2beeac1f..40104bb23 100644 --- a/cockatrice/src/client/ui/picture_loader/picture_loader_status_bar.cpp +++ b/cockatrice/src/client/ui/picture_loader/picture_loader_status_bar.cpp @@ -38,7 +38,7 @@ void PictureLoaderStatusBar::cleanOldEntries() } } -void PictureLoaderStatusBar::addQueuedImageLoad(const QUrl &url, const CardInfoPtr &card, const QString &setName) +void PictureLoaderStatusBar::addQueuedImageLoad(const QUrl &url, const ExactCard &card, const QString &setName) { loadLog->addSettingsWidget(new PictureLoaderRequestStatusDisplayWidget(loadLog, url, card, setName)); progressBar->setMaximum(progressBar->maximum() + 1); diff --git a/cockatrice/src/client/ui/picture_loader/picture_loader_status_bar.h b/cockatrice/src/client/ui/picture_loader/picture_loader_status_bar.h index 6f5111a34..d60279a97 100644 --- a/cockatrice/src/client/ui/picture_loader/picture_loader_status_bar.h +++ b/cockatrice/src/client/ui/picture_loader/picture_loader_status_bar.h @@ -15,7 +15,7 @@ public: explicit PictureLoaderStatusBar(QWidget *parent); public slots: - void addQueuedImageLoad(const QUrl &url, const CardInfoPtr &card, const QString &setName); + void addQueuedImageLoad(const QUrl &url, const ExactCard &card, const QString &setName); void addSuccessfulImageLoad(const QUrl &url); void cleanOldEntries(); diff --git a/cockatrice/src/client/ui/picture_loader/picture_loader_worker.cpp b/cockatrice/src/client/ui/picture_loader/picture_loader_worker.cpp index 32a8af5d8..b538f458b 100644 --- a/cockatrice/src/client/ui/picture_loader/picture_loader_worker.cpp +++ b/cockatrice/src/client/ui/picture_loader/picture_loader_worker.cpp @@ -129,21 +129,21 @@ bool PictureLoaderWorker::processSingleRequest() return false; } -void PictureLoaderWorker::enqueueImageLoad(const CardInfoPtr &card) +void PictureLoaderWorker::enqueueImageLoad(const ExactCard &card) { // Send call through a connection to ensure the handling is run on the pictureLoader thread emit imageLoadEnqueued(card); } -void PictureLoaderWorker::handleImageLoadEnqueued(const CardInfoPtr &card) +void PictureLoaderWorker::handleImageLoadEnqueued(const ExactCard &card) { // deduplicate loads for the same card - if (currentlyLoading.contains(card)) { + if (currentlyLoading.contains(card.getPixmapCacheKey())) { qCDebug(PictureLoaderWorkerLog()) - << "Skipping enqueued" << card->getName() << "because it's already being loaded"; + << "Skipping enqueued" << card.getName() << "because it's already being loaded"; return; } - currentlyLoading.insert(card); + currentlyLoading.insert(card.getPixmapCacheKey()); // try to load image from local first QImage image = localLoader->tryLoad(card); @@ -158,9 +158,9 @@ void PictureLoaderWorker::handleImageLoadEnqueued(const CardInfoPtr &card) /** * Called when image loading is done. Failures are indicated by an empty QImage. */ -void PictureLoaderWorker::handleImageLoaded(const CardInfoPtr &card, const QImage &image) +void PictureLoaderWorker::handleImageLoaded(const ExactCard &card, const QImage &image) { - currentlyLoading.remove(card); + currentlyLoading.remove(card.getPixmapCacheKey()); emit imageLoaded(card, image); } diff --git a/cockatrice/src/client/ui/picture_loader/picture_loader_worker.h b/cockatrice/src/client/ui/picture_loader/picture_loader_worker.h index f3a73afe2..f7a31baef 100644 --- a/cockatrice/src/client/ui/picture_loader/picture_loader_worker.h +++ b/cockatrice/src/client/ui/picture_loader/picture_loader_worker.h @@ -31,7 +31,7 @@ public: explicit PictureLoaderWorker(); ~PictureLoaderWorker() override; - void enqueueImageLoad(const CardInfoPtr &card); // Starts a thread for the image to be loaded + void enqueueImageLoad(const ExactCard &card); // Starts a thread for the image to be loaded void queueRequest(const QUrl &url, PictureLoaderWorkerWork *worker); // Queues network requests for load threads void clearNetworkCache(); @@ -39,7 +39,7 @@ public slots: QNetworkReply *makeRequest(const QUrl &url, PictureLoaderWorkerWork *workThread); void processQueuedRequests(); bool processSingleRequest(); - void handleImageLoaded(const CardInfoPtr &card, const QImage &image); + void handleImageLoaded(const ExactCard &card, const QImage &image); void cacheRedirect(const QUrl &originalUrl, const QUrl &redirectUrl); void removedCachedUrl(const QUrl &url); @@ -57,7 +57,7 @@ private: QTimer requestTimer; // Timer for refreshing request quota PictureLoaderLocal *localLoader; - QSet currentlyLoading; // for deduplication purposes + QSet currentlyLoading; // for deduplication purposes. Contains pixmapCacheKey QUrl getCachedRedirect(const QUrl &originalUrl) const; void loadRedirectCache(); @@ -66,12 +66,12 @@ private: private slots: void resetRequestQuota(); - void handleImageLoadEnqueued(const CardInfoPtr &card); + void handleImageLoadEnqueued(const ExactCard &card); signals: - void imageLoadEnqueued(const CardInfoPtr &card); - void imageLoaded(CardInfoPtr card, const QImage &image); - void imageRequestQueued(const QUrl &url, const CardInfoPtr &card, const QString &setName); + void imageLoadEnqueued(const ExactCard &card); + void imageLoaded(const ExactCard &card, const QImage &image); + void imageRequestQueued(const QUrl &url, const ExactCard &card, const QString &setName); void imageRequestSucceeded(const QUrl &url); }; diff --git a/cockatrice/src/client/ui/picture_loader/picture_loader_worker_work.cpp b/cockatrice/src/client/ui/picture_loader/picture_loader_worker_work.cpp index 5d6794ee1..1e7600a75 100644 --- a/cockatrice/src/client/ui/picture_loader/picture_loader_worker_work.cpp +++ b/cockatrice/src/client/ui/picture_loader/picture_loader_worker_work.cpp @@ -15,8 +15,8 @@ // Card back returned by gatherer when card is not found static const QStringList MD5_BLACKLIST = {"db0c48db407a907c16ade38de048a441"}; -PictureLoaderWorkerWork::PictureLoaderWorkerWork(const PictureLoaderWorker *worker, const CardInfoPtr &toLoad) - : QObject(nullptr), cardToDownload(toLoad), picDownload(SettingsCache::instance().getPicDownload()) +PictureLoaderWorkerWork::PictureLoaderWorkerWork(const PictureLoaderWorker *worker, const ExactCard &toLoad) + : QObject(nullptr), cardToDownload(PictureToLoad(toLoad)), picDownload(SettingsCache::instance().getPicDownload()) { // Hook up signals to the orchestrator connect(this, &PictureLoaderWorkerWork::requestImageDownload, worker, &PictureLoaderWorker::queueRequest); @@ -49,7 +49,7 @@ void PictureLoaderWorkerWork::startNextPicDownload() } else { QUrl url(picUrl); qCDebug(PictureLoaderWorkerWorkLog).nospace() - << "PictureLoader: [card: " << cardToDownload.getCard()->getCorrectedName() + << "PictureLoader: [card: " << cardToDownload.getCard().getInfo().getCorrectedName() << " set: " << cardToDownload.getSetName() << "]: Trying to fetch picture from url " << url.toDisplayString(); emit requestImageDownload(url, this); @@ -70,7 +70,7 @@ void PictureLoaderWorkerWork::picDownloadFailed() startNextPicDownload(); } else { qCWarning(PictureLoaderWorkerWorkLog).nospace() - << "PictureLoader: [card: " << cardToDownload.getCard()->getCorrectedName() + << "PictureLoader: [card: " << cardToDownload.getCard().getInfo().getCorrectedName() << " set: " << cardToDownload.getSetName() << "]: Picture NOT found, " << (picDownload ? "download failed" : "downloads disabled") << ", no more url combinations to try: BAILING OUT"; @@ -119,7 +119,7 @@ void PictureLoaderWorkerWork::handleFailedReply(const QNetworkReply *reply) if (isFromCache) { qCDebug(PictureLoaderWorkerWorkLog).nospace() - << "PictureLoader: [card: " << cardToDownload.getCard()->getName() + << "PictureLoader: [card: " << cardToDownload.getCard().getName() << " set: " << cardToDownload.getSetName() << "]: Removing corrupted cache file for url " << reply->url().toDisplayString() << " and retrying (" << reply->errorString() << ")"; @@ -128,7 +128,7 @@ void PictureLoaderWorkerWork::handleFailedReply(const QNetworkReply *reply) emit requestImageDownload(reply->url(), this); } else { qCDebug(PictureLoaderWorkerWorkLog).nospace() - << "PictureLoader: [card: " << cardToDownload.getCard()->getName() + << "PictureLoader: [card: " << cardToDownload.getCard().getName() << " set: " << cardToDownload.getSetName() << "]: " << (picDownload ? "Download" : "Cache search") << " failed for url " << reply->url().toDisplayString() << " (" << reply->errorString() << ")"; @@ -147,9 +147,9 @@ void PictureLoaderWorkerWork::handleSuccessfulReply(QNetworkReply *reply) statusCode == 308) { QUrl redirectUrl = reply->header(QNetworkRequest::LocationHeader).toUrl(); qCDebug(PictureLoaderWorkerWorkLog).nospace() - << "PictureLoader: [card: " << cardToDownload.getCard()->getName() - << " set: " << cardToDownload.getSetName() << "]: following " - << (isFromCache ? "cached redirect" : "redirect") << " to " << redirectUrl.toDisplayString(); + << "PictureLoader: [card: " << cardToDownload.getCard().getName() << " set: " << cardToDownload.getSetName() + << "]: following " << (isFromCache ? "cached redirect" : "redirect") << " to " + << redirectUrl.toDisplayString(); emit requestImageDownload(redirectUrl, this); return; } @@ -159,8 +159,7 @@ void PictureLoaderWorkerWork::handleSuccessfulReply(QNetworkReply *reply) if (imageIsBlackListed(picData)) { qCDebug(PictureLoaderWorkerWorkLog).nospace() - << "PictureLoader: [card: " << cardToDownload.getCard()->getName() - << " set: " << cardToDownload.getSetName() + << "PictureLoader: [card: " << cardToDownload.getCard().getName() << " set: " << cardToDownload.getSetName() << "]: Picture found, but blacklisted, will consider it as not found"; picDownloadFailed(); @@ -171,16 +170,16 @@ void PictureLoaderWorkerWork::handleSuccessfulReply(QNetworkReply *reply) if (image.isNull()) { qCDebug(PictureLoaderWorkerWorkLog).nospace() - << "PictureLoader: [card: " << cardToDownload.getCard()->getName() - << " set: " << cardToDownload.getSetName() << "]: Possible " << (isFromCache ? "cached" : "downloaded") - << " picture at " << reply->url().toDisplayString() << " could not be loaded: " << reply->errorString(); + << "PictureLoader: [card: " << cardToDownload.getCard().getName() << " set: " << cardToDownload.getSetName() + << "]: Possible " << (isFromCache ? "cached" : "downloaded") << " picture at " + << reply->url().toDisplayString() << " could not be loaded: " << reply->errorString(); picDownloadFailed(); } else { qCDebug(PictureLoaderWorkerWorkLog).nospace() - << "PictureLoader: [card: " << cardToDownload.getCard()->getName() - << " set: " << cardToDownload.getSetName() << "]: Image successfully " - << (isFromCache ? "loaded from cached" : "downloaded from") << " url " << reply->url().toDisplayString(); + << "PictureLoader: [card: " << cardToDownload.getCard().getName() << " set: " << cardToDownload.getSetName() + << "]: Image successfully " << (isFromCache ? "loaded from cached" : "downloaded from") << " url " + << reply->url().toDisplayString(); concludeImageLoad(image); } diff --git a/cockatrice/src/client/ui/picture_loader/picture_loader_worker_work.h b/cockatrice/src/client/ui/picture_loader/picture_loader_worker_work.h index bc49e7185..d03160463 100644 --- a/cockatrice/src/client/ui/picture_loader/picture_loader_worker_work.h +++ b/cockatrice/src/client/ui/picture_loader/picture_loader_worker_work.h @@ -25,7 +25,7 @@ class PictureLoaderWorkerWork : public QObject { Q_OBJECT public: - explicit PictureLoaderWorkerWork(const PictureLoaderWorker *worker, const CardInfoPtr &toLoad); + explicit PictureLoaderWorkerWork(const PictureLoaderWorker *worker, const ExactCard &toLoad); PictureToLoad cardToDownload; @@ -52,7 +52,7 @@ signals: * Failures are represented by an empty QImage. * Note that this object will delete itself as this signal is emitted. */ - void imageLoaded(CardInfoPtr card, const QImage &image); + void imageLoaded(const ExactCard &card, const QImage &image); /** * Emitted when a request did not return a 400 or 500 response diff --git a/cockatrice/src/client/ui/picture_loader/picture_to_load.cpp b/cockatrice/src/client/ui/picture_loader/picture_to_load.cpp index 96a858fac..f3af6f5e8 100644 --- a/cockatrice/src/client/ui/picture_loader/picture_to_load.cpp +++ b/cockatrice/src/client/ui/picture_loader/picture_to_load.cpp @@ -9,8 +9,8 @@ #include #include -PictureToLoad::PictureToLoad(CardInfoPtr _card) - : card(std::move(_card)), urlTemplates(SettingsCache::instance().downloads().getAllURLs()) +PictureToLoad::PictureToLoad(const ExactCard &_card) + : card(_card), urlTemplates(SettingsCache::instance().downloads().getAllURLs()) { if (card) { sortedSets = extractSetsSorted(card); @@ -25,10 +25,10 @@ PictureToLoad::PictureToLoad(CardInfoPtr _card) * * @return A list of sets. Will not be empty. */ -QList PictureToLoad::extractSetsSorted(const CardInfoPtr &card) +QList PictureToLoad::extractSetsSorted(const ExactCard &card) { QList sortedSets; - for (const auto &printings : card->getSets()) { + for (const auto &printings : card.getInfo().getSets()) { for (const auto &printing : printings) { sortedSets << printing.getSet(); } @@ -41,21 +41,45 @@ QList PictureToLoad::extractSetsSorted(const CardInfoPtr &card) // If the user hasn't disabled arts other than their personal preference... if (!SettingsCache::instance().getOverrideAllCardArtWithPersonalPreference()) { // If the pixmapCacheKey corresponds to a specific set, we have to try to load it first. - for (const auto &printings : card->getSets()) { - for (const auto &printing : printings) { - if (QLatin1String("card_") + card->getName() + QString("_") + QString(printing.getProperty("uuid")) == - card->getPixmapCacheKey()) { - long long setIndex = sortedSets.indexOf(printing.getSet()); - CardSetPtr setForCardProviderID = sortedSets.takeAt(setIndex); - sortedSets.prepend(setForCardProviderID); - } - } + qsizetype setIndex = sortedSets.indexOf(card.getPrinting().getSet()); + if (setIndex > 0) { // we don't need to move the set if it's already first + CardSetPtr setForCardProviderID = sortedSets.takeAt(setIndex); + sortedSets.prepend(setForCardProviderID); } } return sortedSets; } +/** + * Finds the PrintingInfo corresponding to the exactCards's card name that belongs to a given set and has the + * exactCards's providerId. + * If the set name is in the CardInfo, but no printings in that set match the card's providerId, then the first + * PrintingInfo for the set is returned. + * + * This method only exists to maintain existing behavior. + * TODO: check if going through all sets is still necessary after the ExactCard refactor. + * + * @param card The card to look in + * @param setName The set's short name + * @return A PrintingInfo, or a default-constructed PrintingInfo if the set name is not in the CardInfo. + */ +static PrintingInfo findPrintingForSet(const ExactCard &card, const QString &setName) +{ + SetToPrintingsMap setsToPrintings = card.getInfo().getSets(); + + if (!setsToPrintings.contains(setName)) + return PrintingInfo(); + + for (const auto &printing : setsToPrintings[setName]) { + if (printing.getUuid() == card.getPrinting().getUuid()) { + return printing; + } + } + + return setsToPrintings[setName][0]; +} + void PictureToLoad::populateSetUrls() { /* currentSetUrls is a list, populated each time a new set is requested for a particular card @@ -64,7 +88,7 @@ void PictureToLoad::populateSetUrls() currentSetUrls.clear(); if (card && currentSet) { - QString setCustomURL = card->getCustomPicURL(currentSet->getShortName()); + QString setCustomURL = findPrintingForSet(card, currentSet->getShortName()).getProperty("picurl"); if (!setCustomURL.isEmpty()) { currentSetUrls.append(setCustomURL); @@ -214,16 +238,16 @@ QString PictureToLoad::transformUrl(const QString &urlTemplate) const QString setName = getSetName(); // name - QString cardName = card->getName(); + QString cardName = card.getName(); transformMap["!name!"] = cardName; - transformMap["!name_lower!"] = card->getName().toLower(); - transformMap["!corrected_name!"] = card->getCorrectedName(); - transformMap["!corrected_name_lower!"] = card->getCorrectedName().toLower(); + transformMap["!name_lower!"] = card.getName().toLower(); + transformMap["!corrected_name!"] = card.getInfo().getCorrectedName(); + transformMap["!corrected_name_lower!"] = card.getInfo().getCorrectedName().toLower(); // card properties if (parse( - urlTemplate, "prop", cardName, setName, [&](const QString &name) { return card->getProperty(name); }, - transformMap)) { + urlTemplate, "prop", cardName, setName, + [&](const QString &name) { return card.getInfo().getProperty(name); }, transformMap)) { return QString(); } @@ -235,7 +259,8 @@ QString PictureToLoad::transformUrl(const QString &urlTemplate) const if (parse( urlTemplate, "set", cardName, setName, - [&](const QString &name) { return card->getSetProperty(set->getShortName(), name); }, transformMap)) { + [&](const QString &name) { return findPrintingForSet(card, set->getShortName()).getProperty(name); }, + transformMap)) { return QString(); } } diff --git a/cockatrice/src/client/ui/picture_loader/picture_to_load.h b/cockatrice/src/client/ui/picture_loader/picture_to_load.h index b9050abfb..a099ac071 100644 --- a/cockatrice/src/client/ui/picture_loader/picture_to_load.h +++ b/cockatrice/src/client/ui/picture_loader/picture_to_load.h @@ -1,7 +1,7 @@ #ifndef PICTURE_TO_LOAD_H #define PICTURE_TO_LOAD_H -#include "../../../game/cards/card_info.h" +#include "../../../game/cards/exact_card.h" #include @@ -10,7 +10,7 @@ inline Q_LOGGING_CATEGORY(PictureToLoadLog, "picture_loader.picture_to_load"); class PictureToLoad { private: - CardInfoPtr card; + ExactCard card; QList sortedSets; QList urlTemplates; QList currentSetUrls; @@ -18,16 +18,12 @@ private: CardSetPtr currentSet; public: - explicit PictureToLoad(CardInfoPtr _card = CardInfoPtr()); + explicit PictureToLoad(const ExactCard &_card); - CardInfoPtr getCard() const + const ExactCard &getCard() const { return card; } - void clear() - { - card.clear(); - } QString getCurrentUrl() const { return currentUrl; @@ -42,7 +38,7 @@ public: bool nextUrl(); void populateSetUrls(); - static QList extractSetsSorted(const CardInfoPtr &card); + static QList extractSetsSorted(const ExactCard &card); }; #endif // PICTURE_TO_LOAD_H diff --git a/cockatrice/src/client/ui/widgets/cards/card_group_display_widgets/card_group_display_widget.cpp b/cockatrice/src/client/ui/widgets/cards/card_group_display_widgets/card_group_display_widget.cpp index d260c391d..5a1b6dda3 100644 --- a/cockatrice/src/client/ui/widgets/cards/card_group_display_widgets/card_group_display_widget.cpp +++ b/cockatrice/src/client/ui/widgets/cards/card_group_display_widgets/card_group_display_widget.cpp @@ -99,7 +99,7 @@ void CardGroupDisplayWidget::onClick(QMouseEvent *event, CardInfoPictureWithText emit cardClicked(event, card); } -void CardGroupDisplayWidget::onHover(CardInfoPtr card) +void CardGroupDisplayWidget::onHover(const ExactCard &card) { emit cardHovered(card); } diff --git a/cockatrice/src/client/ui/widgets/cards/card_group_display_widgets/card_group_display_widget.h b/cockatrice/src/client/ui/widgets/cards/card_group_display_widgets/card_group_display_widget.h index e24b2b254..d9e851016 100644 --- a/cockatrice/src/client/ui/widgets/cards/card_group_display_widgets/card_group_display_widget.h +++ b/cockatrice/src/client/ui/widgets/cards/card_group_display_widgets/card_group_display_widget.h @@ -37,7 +37,7 @@ public: public slots: void onClick(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *card); - void onHover(CardInfoPtr card); + void onHover(const ExactCard &card); virtual QWidget *constructWidgetForIndex(int rowIndex); virtual void updateCardDisplays(); virtual void onCardAddition(const QModelIndex &parent, int first, int last); @@ -46,7 +46,7 @@ public slots: signals: void cardClicked(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *card); - void cardHovered(CardInfoPtr card); + void cardHovered(const ExactCard &card); void cleanupRequested(CardGroupDisplayWidget *cardGroupDisplayWidget); protected: diff --git a/cockatrice/src/client/ui/widgets/cards/card_info_display_widget.cpp b/cockatrice/src/client/ui/widgets/cards/card_info_display_widget.cpp index c9197c3a9..28209e6ec 100644 --- a/cockatrice/src/client/ui/widgets/cards/card_info_display_widget.cpp +++ b/cockatrice/src/client/ui/widgets/cards/card_info_display_widget.cpp @@ -12,7 +12,7 @@ #include CardInfoDisplayWidget::CardInfoDisplayWidget(const CardRef &cardRef, QWidget *parent, Qt::WindowFlags flags) - : QFrame(parent, flags), aspectRatio((qreal)CARD_HEIGHT / (qreal)CARD_WIDTH), info(nullptr) + : QFrame(parent, flags), aspectRatio((qreal)CARD_HEIGHT / (qreal)CARD_WIDTH) { setContentsMargins(3, 3, 3, 3); pic = new CardInfoPictureWidget(); @@ -43,32 +43,32 @@ CardInfoDisplayWidget::CardInfoDisplayWidget(const CardRef &cardRef, QWidget *pa resize(width(), sizeHint().height()); } -void CardInfoDisplayWidget::setCard(CardInfoPtr card) +void CardInfoDisplayWidget::setCard(const ExactCard &card) { - if (info) - disconnect(info.data(), nullptr, this, nullptr); - info = std::move(card); - if (info) - connect(info.data(), &QObject::destroyed, this, &CardInfoDisplayWidget::clear); + if (exactCard) + disconnect(exactCard.getCardPtr().data(), nullptr, this, nullptr); + exactCard = card; + if (exactCard) + connect(exactCard.getCardPtr().data(), &QObject::destroyed, this, &CardInfoDisplayWidget::clear); - text->setCard(info); - pic->setCard(info); + text->setCard(exactCard.getCardPtr()); + pic->setCard(exactCard); } void CardInfoDisplayWidget::setCard(const CardRef &cardRef) { setCard(CardDatabaseManager::getInstance()->guessCard(cardRef)); - if (info == nullptr) { + if (exactCard.isEmpty()) { text->setInvalidCardName(cardRef.name); } } void CardInfoDisplayWidget::setCard(AbstractCardItem *card) { - setCard(card->getInfo()); + setCard(card->getCard()); } void CardInfoDisplayWidget::clear() { - setCard((CardInfoPtr) nullptr); + setCard(ExactCard()); } diff --git a/cockatrice/src/client/ui/widgets/cards/card_info_display_widget.h b/cockatrice/src/client/ui/widgets/cards/card_info_display_widget.h index d114586cb..0df6081eb 100644 --- a/cockatrice/src/client/ui/widgets/cards/card_info_display_widget.h +++ b/cockatrice/src/client/ui/widgets/cards/card_info_display_widget.h @@ -1,7 +1,7 @@ #ifndef CARDINFOWIDGET_H #define CARDINFOWIDGET_H -#include "../../../../game/cards/card_info.h" +#include "../../../../game/cards/exact_card.h" #include "card_ref.h" #include @@ -18,7 +18,7 @@ class CardInfoDisplayWidget : public QFrame private: qreal aspectRatio; - CardInfoPtr info; + ExactCard exactCard; CardInfoPictureWidget *pic; CardInfoTextWidget *text; @@ -26,7 +26,7 @@ public: explicit CardInfoDisplayWidget(const CardRef &cardRef, QWidget *parent = nullptr, Qt::WindowFlags f = {}); public slots: - void setCard(CardInfoPtr card); + void setCard(const ExactCard &card); void setCard(const CardRef &cardRef); void setCard(AbstractCardItem *card); diff --git a/cockatrice/src/client/ui/widgets/cards/card_info_frame_widget.cpp b/cockatrice/src/client/ui/widgets/cards/card_info_frame_widget.cpp index f72f7a7f5..55018ad27 100644 --- a/cockatrice/src/client/ui/widgets/cards/card_info_frame_widget.cpp +++ b/cockatrice/src/client/ui/widgets/cards/card_info_frame_widget.cpp @@ -12,12 +12,13 @@ #include CardInfoFrameWidget::CardInfoFrameWidget(QWidget *parent) - : QTabWidget(parent), info(nullptr), viewTransformationButton(nullptr), cardTextOnly(false) + : QTabWidget(parent), viewTransformationButton(nullptr), cardTextOnly(false) { setContentsMargins(3, 3, 3, 3); pic = new CardInfoPictureWidget(); pic->setObjectName("pic"); - connect(pic, &CardInfoPictureWidget::cardChanged, this, qOverload(&CardInfoFrameWidget::setCard)); + connect(pic, &CardInfoPictureWidget::cardChanged, this, + qOverload(&CardInfoFrameWidget::setCard)); text = new CardInfoTextWidget(); text->setObjectName("text"); @@ -129,13 +130,9 @@ void CardInfoFrameWidget::setViewMode(int mode) SettingsCache::instance().setCardInfoViewMode(mode); } -static bool hasTransformation(const CardInfoPtr &info) +static bool hasTransformation(const CardInfo &info) { - if (!info) { - return false; - } - - for (const auto &cardRelation : info->getAllRelatedCards()) { + for (const auto &cardRelation : info.getAllRelatedCards()) { if (cardRelation->getDoesTransform()) { return true; } @@ -143,22 +140,22 @@ static bool hasTransformation(const CardInfoPtr &info) return false; } -void CardInfoFrameWidget::setCard(CardInfoPtr card) +void CardInfoFrameWidget::setCard(const ExactCard &card) { - if (info) { - disconnect(info.data(), nullptr, this, nullptr); + if (exactCard) { + disconnect(exactCard.getCardPtr().data(), nullptr, this, nullptr); } - info = std::move(card); + exactCard = card; - if (info) { - connect(info.data(), &QObject::destroyed, this, &CardInfoFrameWidget::clearCard); + if (exactCard) { + connect(exactCard.getCardPtr().data(), &QObject::destroyed, this, &CardInfoFrameWidget::clearCard); } - setViewTransformationButtonVisibility(hasTransformation(info)); + setViewTransformationButtonVisibility(hasTransformation(exactCard.getInfo())); - text->setCard(info); - pic->setCard(info); + text->setCard(exactCard.getCardPtr()); + pic->setCard(exactCard); } void CardInfoFrameWidget::setCard(const QString &cardName) @@ -174,14 +171,14 @@ void CardInfoFrameWidget::setCard(const CardRef &cardRef) void CardInfoFrameWidget::setCard(AbstractCardItem *card) { if (card) { - setCard(card->getInfo()); + setCard(card->getCard()); } } void CardInfoFrameWidget::viewTransformation() { - if (info) { - const auto &cardRelations = info->getAllRelatedCards(); + if (exactCard) { + const auto &cardRelations = exactCard.getInfo().getAllRelatedCards(); for (const auto &cardRelation : cardRelations) { if (cardRelation->getDoesTransform()) { setCard(cardRelation->getName()); @@ -193,5 +190,5 @@ void CardInfoFrameWidget::viewTransformation() void CardInfoFrameWidget::clearCard() { - setCard((CardInfoPtr) nullptr); + setCard(ExactCard()); } 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 e12cab33c..147ff85ce 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 @@ -1,7 +1,7 @@ #ifndef CARDFRAME_H #define CARDFRAME_H -#include "../../../../game/cards/card_info.h" +#include "../../../../game/cards/exact_card.h" #include "card_ref.h" #include @@ -17,7 +17,7 @@ class CardInfoFrameWidget : public QTabWidget { Q_OBJECT private: - CardInfoPtr info; + ExactCard exactCard; CardInfoPictureWidget *pic; CardInfoTextWidget *text; QPushButton *viewTransformationButton; @@ -38,14 +38,14 @@ public: }; explicit CardInfoFrameWidget(QWidget *parent = nullptr); - CardInfoPtr getInfo() + ExactCard getCard() { - return info; + return exactCard; } void retranslateUi(); public slots: - void setCard(CardInfoPtr card); + void setCard(const ExactCard &card); void setCard(const QString &cardName); void setCard(const CardRef &cardRef); void setCard(AbstractCardItem *card); diff --git a/cockatrice/src/client/ui/widgets/cards/card_info_picture_enlarged_widget.cpp b/cockatrice/src/client/ui/widgets/cards/card_info_picture_enlarged_widget.cpp index 775390182..0abc738c3 100644 --- a/cockatrice/src/client/ui/widgets/cards/card_info_picture_enlarged_widget.cpp +++ b/cockatrice/src/client/ui/widgets/cards/card_info_picture_enlarged_widget.cpp @@ -13,8 +13,7 @@ * * Sets the widget's window flags to keep it displayed as a tooltip overlay. */ -CardInfoPictureEnlargedWidget::CardInfoPictureEnlargedWidget(QWidget *parent) - : QWidget(parent), pixmapDirty(true), info(nullptr) +CardInfoPictureEnlargedWidget::CardInfoPictureEnlargedWidget(QWidget *parent) : QWidget(parent), pixmapDirty(true) { setWindowFlags(Qt::ToolTip); // Keeps this widget on top of everything setAttribute(Qt::WA_TranslucentBackground); @@ -35,8 +34,8 @@ CardInfoPictureEnlargedWidget::CardInfoPictureEnlargedWidget(QWidget *parent) */ void CardInfoPictureEnlargedWidget::loadPixmap(const QSize &size) { - if (info) { - PictureLoader::getPixmap(enlargedPixmap, info, size); + if (card) { + PictureLoader::getPixmap(enlargedPixmap, card, size); } else { PictureLoader::getCardBackPixmap(enlargedPixmap, size); } @@ -45,14 +44,14 @@ void CardInfoPictureEnlargedWidget::loadPixmap(const QSize &size) /** * @brief Sets the pixmap for the widget based on a provided card. - * @param card The card information to load. + * @param _card The card information to load. * @param size The desired size for the pixmap. * * Sets the widget's pixmap to the card image and resizes the widget to match the specified size. Triggers a repaint. */ -void CardInfoPictureEnlargedWidget::setCardPixmap(CardInfoPtr card, const QSize size) +void CardInfoPictureEnlargedWidget::setCardPixmap(const ExactCard &_card, const QSize size) { - info = std::move(card); + card = _card; loadPixmap(size); setFixedSize(size); // Set the widget size to the enlarged size diff --git a/cockatrice/src/client/ui/widgets/cards/card_info_picture_enlarged_widget.h b/cockatrice/src/client/ui/widgets/cards/card_info_picture_enlarged_widget.h index d65b0da69..0d1bf9c01 100644 --- a/cockatrice/src/client/ui/widgets/cards/card_info_picture_enlarged_widget.h +++ b/cockatrice/src/client/ui/widgets/cards/card_info_picture_enlarged_widget.h @@ -1,7 +1,7 @@ #ifndef CARD_PICTURE_ENLARGED_WIDGET_H #define CARD_PICTURE_ENLARGED_WIDGET_H -#include "../../../../game/cards/card_info.h" +#include "../../../../game/cards/exact_card.h" #include #include @@ -15,7 +15,7 @@ public: explicit CardInfoPictureEnlargedWidget(QWidget *parent = nullptr); // Sets the card pixmap to display - void setCardPixmap(CardInfoPtr card, QSize size); + void setCardPixmap(const ExactCard &_card, QSize size); protected: // Handles the painting event for the enlarged card @@ -28,8 +28,8 @@ private: // Tracks if the pixmap needs to be refreshed/redrawn bool pixmapDirty; - // Card information (card data pointer) - CardInfoPtr info; + // Card information + ExactCard card; // Loads the enlarged card pixmap void loadPixmap(const QSize &size); 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 dcd42d581..1d8aca5e0 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 @@ -31,8 +31,7 @@ * Initializes the widget with a minimum height and sets the pixmap to a dirty state for initial loading. */ CardInfoPictureWidget::CardInfoPictureWidget(QWidget *parent, const bool _hoverToZoomEnabled, const bool _raiseOnEnter) - : QWidget(parent), info(nullptr), pixmapDirty(true), hoverToZoomEnabled(_hoverToZoomEnabled), - raiseOnEnter(_raiseOnEnter) + : QWidget(parent), pixmapDirty(true), hoverToZoomEnabled(_hoverToZoomEnabled), raiseOnEnter(_raiseOnEnter) { setMinimumHeight(baseHeight); if (hoverToZoomEnabled) { @@ -77,16 +76,16 @@ CardInfoPictureWidget::~CardInfoPictureWidget() * Disconnects any existing signal connections from the previous card info and connects to the `pixmapUpdated` * signal of the new card to automatically update the pixmap when the card image changes. */ -void CardInfoPictureWidget::setCard(CardInfoPtr card) +void CardInfoPictureWidget::setCard(const ExactCard &card) { - if (info) { - disconnect(info.data(), nullptr, this, nullptr); + if (exactCard.getCardPtr()) { + disconnect(exactCard.getCardPtr().data(), nullptr, this, nullptr); } - info = std::move(card); + exactCard = card; - if (info) { - connect(info.data(), &CardInfo::pixmapUpdated, this, &CardInfoPictureWidget::updatePixmap); + if (exactCard.getCardPtr()) { + connect(exactCard.getCardPtr().data(), &CardInfo::pixmapUpdated, this, &CardInfoPictureWidget::updatePixmap); } updatePixmap(); @@ -158,8 +157,8 @@ void CardInfoPictureWidget::updatePixmap() void CardInfoPictureWidget::loadPixmap() { PictureLoader::getCardBackLoadingInProgressPixmap(resizedPixmap, size()); - if (info) { - PictureLoader::getPixmap(resizedPixmap, info, size()); + if (exactCard) { + PictureLoader::getPixmap(resizedPixmap, exactCard, size()); } else { PictureLoader::getCardBackLoadingFailedPixmap(resizedPixmap, size()); } @@ -188,7 +187,7 @@ void CardInfoPictureWidget::paintEvent(QPaintEvent *event) QPixmap transformedPixmap = resizedPixmap; // Default pixmap if (SettingsCache::instance().getAutoRotateSidewaysLayoutCards()) { - if (info && info->getLandscapeOrientation()) { + if (exactCard.getInfo().getLandscapeOrientation()) { // Rotate pixmap 90 degrees to the left QTransform transform; transform.rotate(90); @@ -257,7 +256,7 @@ void CardInfoPictureWidget::enterEvent(QEvent *event) } // Emit signal indicating a card is being hovered on - emit hoveredOnCard(info); + emit hoveredOnCard(exactCard); if (raiseOnEnter) { if (animation->state() == QAbstractAnimation::Running) { @@ -357,7 +356,7 @@ QMenu *CardInfoPictureWidget::createRightClickMenu() { auto *cardMenu = new QMenu(this); - if (!info) { + if (!exactCard) { return cardMenu; } @@ -371,7 +370,7 @@ QMenu *CardInfoPictureWidget::createViewRelatedCardsMenu() { auto viewRelatedCards = new QMenu(tr("View related cards")); - QList relatedCards = info->getAllRelatedCards(); + QList relatedCards = exactCard.getInfo().getAllRelatedCards(); auto relatedCardExists = [](const CardRelation *cardRelation) { return CardDatabaseManager::getInstance()->getCardInfo(cardRelation->getName()) != nullptr; @@ -388,7 +387,8 @@ QMenu *CardInfoPictureWidget::createViewRelatedCardsMenu() const auto &relatedCardName = relatedCard->getName(); QAction *viewCard = viewRelatedCards->addAction(relatedCardName); connect(viewCard, &QAction::triggered, this, [this, &relatedCardName] { - emit cardChanged(CardDatabaseManager::getInstance()->getCardInfo(relatedCardName)); + emit cardChanged( + CardDatabaseManager::getInstance()->getCard({relatedCardName, exactCard.getPrinting().getUuid()})); }); viewRelatedCards->addAction(viewCard); } @@ -428,14 +428,14 @@ QMenu *CardInfoPictureWidget::createAddToOpenDeckMenu() QAction *addCard = addCardMenu->addAction(tr("Mainboard")); connect(addCard, &QAction::triggered, this, [this, deckEditorTab] { - deckEditorTab->updateCard(info); - deckEditorTab->actAddCard(info); + deckEditorTab->updateCard(exactCard); + deckEditorTab->actAddCard(exactCard); }); QAction *addCardSideboard = addCardMenu->addAction(tr("Sideboard")); connect(addCardSideboard, &QAction::triggered, this, [this, deckEditorTab] { - deckEditorTab->updateCard(info); - deckEditorTab->actAddCardToSideboard(info); + deckEditorTab->updateCard(exactCard); + deckEditorTab->actAddCardToSideboard(exactCard); }); } @@ -450,12 +450,12 @@ QMenu *CardInfoPictureWidget::createAddToOpenDeckMenu() */ void CardInfoPictureWidget::showEnlargedPixmap() const { - if (!info) { + if (!exactCard) { return; } const QSize enlargedSize(static_cast(size().width() * 2), static_cast(size().width() * aspectRatio * 2)); - enlargedPixmapWidget->setCardPixmap(info, enlargedSize); + enlargedPixmapWidget->setCardPixmap(exactCard, enlargedSize); const QPoint cursorPos = QCursor::pos(); const QRect screenGeometry = QGuiApplication::screenAt(cursorPos)->geometry(); diff --git a/cockatrice/src/client/ui/widgets/cards/card_info_picture_widget.h b/cockatrice/src/client/ui/widgets/cards/card_info_picture_widget.h index 79de74526..38d5266f9 100644 --- a/cockatrice/src/client/ui/widgets/cards/card_info_picture_widget.h +++ b/cockatrice/src/client/ui/widgets/cards/card_info_picture_widget.h @@ -1,7 +1,7 @@ #ifndef CARD_INFO_PICTURE_H #define CARD_INFO_PICTURE_H -#include "../../../../game/cards/card_info.h" +#include "../../../../game/cards/exact_card.h" #include "card_info_picture_enlarged_widget.h" #include @@ -22,23 +22,23 @@ public: bool hoverToZoomEnabled = false, bool raiseOnEnter = false); ~CardInfoPictureWidget(); - CardInfoPtr getInfo() + ExactCard getCard() { - return info; + return exactCard; } [[nodiscard]] QSize sizeHint() const override; public slots: - void setCard(CardInfoPtr card); + void setCard(const ExactCard &card); void setScaleFactor(int scale); // New slot for scaling void setHoverToZoomEnabled(bool enabled); void setRaiseOnEnterEnabled(bool enabled); void updatePixmap(); signals: - void hoveredOnCard(CardInfoPtr hoveredCard); + void hoveredOnCard(const ExactCard &hoveredCard); void cardScaleFactorChanged(int _scale); - void cardChanged(CardInfoPtr card); + void cardChanged(const ExactCard &card); void cardClicked(); protected: @@ -62,7 +62,7 @@ protected: void showEnlargedPixmap() const; private: - CardInfoPtr info; + ExactCard exactCard; qreal magicTheGatheringCardAspectRatio = 1.396; qreal yuGiOhCardAspectRatio = 1.457; qreal aspectRatio = magicTheGatheringCardAspectRatio; diff --git a/cockatrice/src/client/ui/widgets/cards/deck_card_zone_display_widget.cpp b/cockatrice/src/client/ui/widgets/cards/deck_card_zone_display_widget.cpp index d6383f5e9..245a8b54d 100644 --- a/cockatrice/src/client/ui/widgets/cards/deck_card_zone_display_widget.cpp +++ b/cockatrice/src/client/ui/widgets/cards/deck_card_zone_display_widget.cpp @@ -137,7 +137,7 @@ void DeckCardZoneDisplayWidget::onClick(QMouseEvent *event, CardInfoPictureWithT { emit cardClicked(event, card, zoneName); } -void DeckCardZoneDisplayWidget::onHover(CardInfoPtr card) +void DeckCardZoneDisplayWidget::onHover(const ExactCard &card) { emit cardHovered(card); } @@ -181,10 +181,10 @@ QList DeckCardZoneDisplayWidget::getGroupCriteriaValueList() { QList groupCriteriaValues; - QList cardsInZone = deckListModel->getCardsAsCardInfoPtrsForZone(zoneName); + QList cardsInZone = deckListModel->getCardsForZone(zoneName); - for (CardInfoPtr cardInZone : cardsInZone) { - groupCriteriaValues.append(cardInZone->getProperty(activeGroupCriteria)); + for (const ExactCard &cardInZone : cardsInZone) { + groupCriteriaValues.append(cardInZone.getInfo().getProperty(activeGroupCriteria)); } groupCriteriaValues.removeDuplicates(); diff --git a/cockatrice/src/client/ui/widgets/cards/deck_card_zone_display_widget.h b/cockatrice/src/client/ui/widgets/cards/deck_card_zone_display_widget.h index 8a21ec3d3..27b0d132b 100644 --- a/cockatrice/src/client/ui/widgets/cards/deck_card_zone_display_widget.h +++ b/cockatrice/src/client/ui/widgets/cards/deck_card_zone_display_widget.h @@ -36,7 +36,7 @@ public: public slots: void onClick(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *card); - void onHover(CardInfoPtr card); + void onHover(const ExactCard &card); void cleanupInvalidCardGroup(CardGroupDisplayWidget *displayWidget); void constructAppropriateWidget(QPersistentModelIndex index); void displayCards(); @@ -49,7 +49,7 @@ public slots: signals: void cardClicked(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *card, QString zoneName); - void cardHovered(CardInfoPtr card); + void cardHovered(const ExactCard &card); void activeSortCriteriaChanged(QStringList activeSortCriteria); void requestCleanup(DeckCardZoneDisplayWidget *displayWidget); diff --git a/cockatrice/src/client/ui/widgets/deck_editor/deck_editor_card_info_dock_widget.cpp b/cockatrice/src/client/ui/widgets/deck_editor/deck_editor_card_info_dock_widget.cpp index 0fe4ae76d..3f12636a8 100644 --- a/cockatrice/src/client/ui/widgets/deck_editor/deck_editor_card_info_dock_widget.cpp +++ b/cockatrice/src/client/ui/widgets/deck_editor/deck_editor_card_info_dock_widget.cpp @@ -34,7 +34,7 @@ void DeckEditorCardInfoDockWidget::createCardInfoDock() connect(this, &QDockWidget::topLevelChanged, deckEditor, &AbstractTabDeckEditor::dockTopLevelChanged); } -void DeckEditorCardInfoDockWidget::updateCard(CardInfoPtr _card) +void DeckEditorCardInfoDockWidget::updateCard(const ExactCard &_card) { cardInfo->setCard(_card); } diff --git a/cockatrice/src/client/ui/widgets/deck_editor/deck_editor_card_info_dock_widget.h b/cockatrice/src/client/ui/widgets/deck_editor/deck_editor_card_info_dock_widget.h index 455df1e88..799e7512d 100644 --- a/cockatrice/src/client/ui/widgets/deck_editor/deck_editor_card_info_dock_widget.h +++ b/cockatrice/src/client/ui/widgets/deck_editor/deck_editor_card_info_dock_widget.h @@ -19,7 +19,7 @@ public: CardInfoFrameWidget *cardInfo; public slots: - void updateCard(CardInfoPtr _card); + void updateCard(const ExactCard &_card); }; #endif // DECK_EDITOR_CARD_INFO_DOCK_WIDGET_H diff --git a/cockatrice/src/client/ui/widgets/deck_editor/deck_editor_database_display_widget.cpp b/cockatrice/src/client/ui/widgets/deck_editor/deck_editor_database_display_widget.cpp index ee5750ca6..2f31dd228 100644 --- a/cockatrice/src/client/ui/widgets/deck_editor/deck_editor_database_display_widget.cpp +++ b/cockatrice/src/client/ui/widgets/deck_editor/deck_editor_database_display_widget.cpp @@ -15,11 +15,11 @@ #include #include -static bool canBeCommander(const CardInfoPtr &cardInfo) +static bool canBeCommander(const CardInfo &cardInfo) { - return ((cardInfo->getCardType().contains("Legendary", Qt::CaseInsensitive) && - cardInfo->getCardType().contains("Creature", Qt::CaseInsensitive))) || - cardInfo->getText().contains("can be your commander", Qt::CaseInsensitive); + return (cardInfo.getCardType().contains("Legendary", Qt::CaseInsensitive) && + cardInfo.getCardType().contains("Creature", Qt::CaseInsensitive)) || + cardInfo.getText().contains("can be your commander", Qt::CaseInsensitive); } DeckEditorDatabaseDisplayWidget::DeckEditorDatabaseDisplayWidget(AbstractTabDeckEditor *parent) @@ -136,42 +136,38 @@ void DeckEditorDatabaseDisplayWidget::clearAllDatabaseFilters() void DeckEditorDatabaseDisplayWidget::updateCard(const QModelIndex ¤t, const QModelIndex & /*previous*/) { const QString cardName = current.sibling(current.row(), 0).data().toString(); - const QString cardProviderID = CardDatabaseManager::getInstance()->getPreferredPrintingProviderId(cardName); if (!current.isValid()) { return; } if (!current.model()->hasChildren(current.sibling(current.row(), 0))) { - CardInfoPtr card = CardDatabaseManager::getInstance()->getCard({cardName, cardProviderID}); - if (!card) { - card = CardDatabaseManager::getInstance()->getCardInfo(cardName); - } + ExactCard card = CardDatabaseManager::getInstance()->getCard({cardName}); emit cardChanged(card); } } void DeckEditorDatabaseDisplayWidget::actAddCardToMainDeck() { - emit addCardToMainDeck(currentCardInfo()); + emit addCardToMainDeck(currentCard()); } void DeckEditorDatabaseDisplayWidget::actAddCardToSideboard() { - emit addCardToSideboard(currentCardInfo()); + emit addCardToSideboard(currentCard()); } void DeckEditorDatabaseDisplayWidget::actDecrementCardFromMainDeck() { - emit decrementCardFromMainDeck(currentCardInfo()); + emit decrementCardFromMainDeck(currentCard()); } void DeckEditorDatabaseDisplayWidget::actDecrementCardFromSideboard() { - emit decrementCardFromSideboard(currentCardInfo()); + emit decrementCardFromSideboard(currentCard()); } -CardInfoPtr DeckEditorDatabaseDisplayWidget::currentCardInfo() const +ExactCard DeckEditorDatabaseDisplayWidget::currentCard() const { const QModelIndex currentIndex = databaseView->selectionModel()->currentIndex(); if (!currentIndex.isValid()) { @@ -180,37 +176,37 @@ CardInfoPtr DeckEditorDatabaseDisplayWidget::currentCardInfo() const const QString cardName = currentIndex.sibling(currentIndex.row(), 0).data().toString(); - return CardDatabaseManager::getInstance()->getCardInfo(cardName); + return CardDatabaseManager::getInstance()->getCard({cardName}); } void DeckEditorDatabaseDisplayWidget::databaseCustomMenu(QPoint point) { QMenu menu; - const CardInfoPtr info = currentCardInfo(); + ExactCard card = currentCard(); - if (info) { + if (card) { // add to deck and sideboard options QAction *addToDeck, *addToSideboard, *selectPrinting, *edhRecCommander, *edhRecCard; addToDeck = menu.addAction(tr("Add to Deck")); addToSideboard = menu.addAction(tr("Add to Sideboard")); selectPrinting = menu.addAction(tr("Select Printing")); - if (canBeCommander(info)) { + if (canBeCommander(card.getInfo())) { edhRecCommander = menu.addAction(tr("Show on EDHRec (Commander)")); connect(edhRecCommander, &QAction::triggered, this, - [this, info] { deckEditor->getTabSupervisor()->addEdhrecTab(info, true); }); + [this, card] { deckEditor->getTabSupervisor()->addEdhrecTab(card.getCardPtr(), true); }); } edhRecCard = menu.addAction(tr("Show on EDHRec (Card)")); connect(addToDeck, &QAction::triggered, this, &DeckEditorDatabaseDisplayWidget::actAddCardToMainDeck); connect(addToSideboard, &QAction::triggered, this, &DeckEditorDatabaseDisplayWidget::actAddCardToSideboard); - connect(selectPrinting, &QAction::triggered, this, [this, info] { deckEditor->showPrintingSelector(); }); + connect(selectPrinting, &QAction::triggered, this, [this, card] { deckEditor->showPrintingSelector(); }); connect(edhRecCard, &QAction::triggered, this, - [this, info] { deckEditor->getTabSupervisor()->addEdhrecTab(info); }); + [this, card] { deckEditor->getTabSupervisor()->addEdhrecTab(card.getCardPtr()); }); // filling out the related cards submenu auto *relatedMenu = new QMenu(tr("Show Related cards")); menu.addMenu(relatedMenu); - auto relatedCards = info->getAllRelatedCards(); + auto relatedCards = card.getInfo().getAllRelatedCards(); if (relatedCards.isEmpty()) { relatedMenu->setDisabled(true); } else { diff --git a/cockatrice/src/client/ui/widgets/deck_editor/deck_editor_database_display_widget.h b/cockatrice/src/client/ui/widgets/deck_editor/deck_editor_database_display_widget.h index 4010a2954..053929bef 100644 --- a/cockatrice/src/client/ui/widgets/deck_editor/deck_editor_database_display_widget.h +++ b/cockatrice/src/client/ui/widgets/deck_editor/deck_editor_database_display_widget.h @@ -22,16 +22,16 @@ public: CardDatabaseDisplayModel *databaseDisplayModel; public slots: - CardInfoPtr currentCardInfo() const; + ExactCard currentCard() const; void setFilterTree(FilterTree *filterTree); void clearAllDatabaseFilters(); signals: - void addCardToMainDeck(CardInfoPtr card); - void addCardToSideboard(CardInfoPtr card); - void decrementCardFromMainDeck(CardInfoPtr card); - void decrementCardFromSideboard(CardInfoPtr card); - void cardChanged(CardInfoPtr _card); + void addCardToMainDeck(const ExactCard &card); + void addCardToSideboard(const ExactCard &card); + void decrementCardFromMainDeck(const ExactCard &card); + void decrementCardFromSideboard(const ExactCard &card); + void cardChanged(const ExactCard &_card); private: KeySignals searchKeySignals; diff --git a/cockatrice/src/client/ui/widgets/deck_editor/deck_editor_deck_dock_widget.cpp b/cockatrice/src/client/ui/widgets/deck_editor/deck_editor_deck_dock_widget.cpp index 35e50682c..9fae48e6c 100644 --- a/cockatrice/src/client/ui/widgets/deck_editor/deck_editor_deck_dock_widget.cpp +++ b/cockatrice/src/client/ui/widgets/deck_editor/deck_editor_deck_dock_widget.cpp @@ -209,7 +209,7 @@ void DeckEditorDeckDockWidget::createDeckDock() retranslateUi(); } -CardInfoPtr DeckEditorDeckDockWidget::getCurrentCard() +ExactCard DeckEditorDeckDockWidget::getCurrentCard() { QModelIndex current = deckView->selectionModel()->currentIndex(); if (!current.isValid()) @@ -227,7 +227,7 @@ CardInfoPtr DeckEditorDeckDockWidget::getCurrentCard() if (!current.model()->hasChildren(current.sibling(current.row(), 0))) { QString cardName = current.sibling(current.row(), 1).data().toString(); QString providerId = current.sibling(current.row(), 4).data().toString(); - if (CardInfoPtr selectedCard = CardDatabaseManager::getInstance()->getCard({cardName, providerId})) { + if (ExactCard selectedCard = CardDatabaseManager::getInstance()->getCard({cardName, providerId})) { return selectedCard; } } @@ -236,7 +236,7 @@ CardInfoPtr DeckEditorDeckDockWidget::getCurrentCard() void DeckEditorDeckDockWidget::updateCard(const QModelIndex /*¤t*/, const QModelIndex & /*previous*/) { - if (CardInfoPtr card = getCurrentCard()) { + if (ExactCard card = getCurrentCard()) { emit cardChanged(card); } } @@ -286,8 +286,7 @@ void DeckEditorDeckDockWidget::updateBannerCardComboBox() continue; for (int k = 0; k < currentCard->getNumber(); ++k) { - CardInfoPtr info = CardDatabaseManager::getInstance()->getCard(currentCard->toCardRef()); - if (info) { + if (CardDatabaseManager::getInstance()->getCard(currentCard->toCardRef())) { bannerCardSet.insert({currentCard->getName(), currentCard->getCardProviderId()}); } } @@ -472,26 +471,26 @@ bool DeckEditorDeckDockWidget::swapCard(const QModelIndex ¤tIndex) offsetCountAtIndex(currentIndex, -1); const QString otherZoneName = zoneName == DECK_ZONE_MAIN ? DECK_ZONE_SIDE : DECK_ZONE_MAIN; - // Third argument (true) says create the card no matter what, even if not in DB - QModelIndex newCardIndex = deckModel->addCard( - cardName, CardDatabaseManager::getInstance()->getSpecificPrinting({cardName, cardProviderID}), otherZoneName, - true); + ExactCard card = CardDatabaseManager::getInstance()->getCard({cardName, cardProviderID}); + QModelIndex newCardIndex = card ? deckModel->addCard(card, otherZoneName) + // Third argument (true) says create the card no matter what, even if not in DB + : deckModel->addPreferredPrintingCard(cardName, otherZoneName, true); recursiveExpand(newCardIndex); return true; } -void DeckEditorDeckDockWidget::actDecrementCard(CardInfoPtr info, QString zoneName) +void DeckEditorDeckDockWidget::actDecrementCard(const ExactCard &card, QString zoneName) { - if (!info) + if (!card) return; - if (info->getIsToken()) + if (card.getInfo().getIsToken()) zoneName = DECK_ZONE_TOKENS; - QString providerId = CardDatabaseManager::getInstance()->getSetInfoForCard(info).getUuid(); - QString collectorNumber = CardDatabaseManager::getInstance()->getSetInfoForCard(info).getProperty("num"); + QString providerId = card.getPrinting().getUuid(); + QString collectorNumber = card.getPrinting().getProperty("num"); - QModelIndex idx = deckModel->findCard(info->getName(), zoneName, providerId, collectorNumber); + QModelIndex idx = deckModel->findCard(card.getName(), zoneName, providerId, collectorNumber); if (!idx.isValid()) { return; } @@ -564,7 +563,6 @@ void DeckEditorDeckDockWidget::offsetCountAtIndex(const QModelIndex &idx, int of void DeckEditorDeckDockWidget::decklistCustomMenu(QPoint point) { QMenu menu; - const CardInfoPtr info = getCurrentCard(); QAction *selectPrinting = menu.addAction(tr("Select Printing")); diff --git a/cockatrice/src/client/ui/widgets/deck_editor/deck_editor_deck_dock_widget.h b/cockatrice/src/client/ui/widgets/deck_editor/deck_editor_deck_dock_widget.h index 27364a662..0530b87a0 100644 --- a/cockatrice/src/client/ui/widgets/deck_editor/deck_editor_deck_dock_widget.h +++ b/cockatrice/src/client/ui/widgets/deck_editor/deck_editor_deck_dock_widget.h @@ -24,7 +24,7 @@ public: QTreeView *deckView; QComboBox *bannerCardComboBox; void createDeckDock(); - CardInfoPtr getCurrentCard(); + ExactCard getCurrentCard(); void retranslateUi(); QString getDeckName() { @@ -42,7 +42,7 @@ public slots: DeckLoader *getDeckList(); void actIncrement(); bool swapCard(const QModelIndex &idx); - void actDecrementCard(CardInfoPtr info, QString zoneName); + void actDecrementCard(const ExactCard &card, QString zoneName); void actDecrementSelection(); void actSwapCard(); void actRemoveCard(); @@ -54,7 +54,7 @@ signals: void hashChanged(); void deckChanged(); void deckModified(); - void cardChanged(CardInfoPtr _card); + void cardChanged(const ExactCard &_card); private: AbstractTabDeckEditor *deckEditor; 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 index 331212f13..5b67ae727 100644 --- 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 @@ -16,17 +16,15 @@ * @param deckView Pointer to the QTreeView for the deck display. * @param cardSizeSlider Pointer to the QSlider used for dynamic font resizing. * @param rootCard The root card for the widget. - * @param printingInfo The printing information for the card. */ AllZonesCardAmountWidget::AllZonesCardAmountWidget(QWidget *parent, AbstractTabDeckEditor *deckEditor, DeckListModel *deckModel, QTreeView *deckView, QSlider *cardSizeSlider, - CardInfoPtr rootCard, - PrintingInfo printingInfo) + const ExactCard &rootCard) : QWidget(parent), deckEditor(deckEditor), deckModel(deckModel), deckView(deckView), cardSizeSlider(cardSizeSlider), - rootCard(rootCard), printingInfo(printingInfo) + rootCard(rootCard) { layout = new QVBoxLayout(this); layout->setAlignment(Qt::AlignHCenter); @@ -35,11 +33,11 @@ AllZonesCardAmountWidget::AllZonesCardAmountWidget(QWidget *parent, setContentsMargins(5, 5, 5, 5); // Padding around the text zoneLabelMainboard = new ShadowBackgroundLabel(this, tr("Mainboard")); - buttonBoxMainboard = new CardAmountWidget(this, deckEditor, deckModel, deckView, cardSizeSlider, rootCard, - printingInfo, DECK_ZONE_MAIN); + buttonBoxMainboard = + new CardAmountWidget(this, deckEditor, deckModel, deckView, cardSizeSlider, rootCard, DECK_ZONE_MAIN); zoneLabelSideboard = new ShadowBackgroundLabel(this, tr("Sideboard")); - buttonBoxSideboard = new CardAmountWidget(this, deckEditor, deckModel, deckView, cardSizeSlider, rootCard, - printingInfo, DECK_ZONE_SIDE); + buttonBoxSideboard = + new CardAmountWidget(this, deckEditor, deckModel, deckView, cardSizeSlider, rootCard, DECK_ZONE_SIDE); layout->addWidget(zoneLabelMainboard, 0, Qt::AlignHCenter | Qt::AlignBottom); layout->addWidget(buttonBoxMainboard, 0, Qt::AlignHCenter | Qt::AlignTop); 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 index ba2c2ce2e..f206bd7d6 100644 --- 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 @@ -16,8 +16,7 @@ public: DeckListModel *deckModel, QTreeView *deckView, QSlider *cardSizeSlider, - CardInfoPtr rootCard, - PrintingInfo printingInfo); + const ExactCard &rootCard); int getMainboardAmount(); int getSideboardAmount(); #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) @@ -35,8 +34,7 @@ private: DeckListModel *deckModel; QTreeView *deckView; QSlider *cardSizeSlider; - CardInfoPtr rootCard; - PrintingInfo printingInfo; + ExactCard rootCard; QLabel *zoneLabelMainboard; CardAmountWidget *buttonBoxMainboard; QLabel *zoneLabelSideboard; 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 index 04822a4ed..62b6031fd 100644 --- a/cockatrice/src/client/ui/widgets/printing_selector/card_amount_widget.cpp +++ b/cockatrice/src/client/ui/widgets/printing_selector/card_amount_widget.cpp @@ -12,7 +12,6 @@ * @param deckView Pointer to the QTreeView displaying the deck. * @param cardSizeSlider Pointer to the QSlider for adjusting font size. * @param rootCard The root card to manage within the widget. - * @param printingInfo Printing info for the root card. * @param zoneName The zone name (e.g., DECK_ZONE_MAIN or DECK_ZONE_SIDE). */ CardAmountWidget::CardAmountWidget(QWidget *parent, @@ -20,11 +19,10 @@ CardAmountWidget::CardAmountWidget(QWidget *parent, DeckListModel *deckModel, QTreeView *deckView, QSlider *cardSizeSlider, - CardInfoPtr &rootCard, - PrintingInfo &printingInfo, + const ExactCard &rootCard, const QString &zoneName) : QWidget(parent), deckEditor(deckEditor), deckModel(deckModel), deckView(deckView), cardSizeSlider(cardSizeSlider), - rootCard(rootCard), printingInfo(printingInfo), zoneName(zoneName), hovered(false) + rootCard(rootCard), zoneName(zoneName), hovered(false) { layout = new QHBoxLayout(this); layout->setContentsMargins(0, 0, 0, 0); @@ -142,18 +140,18 @@ void CardAmountWidget::updateCardCount() */ void CardAmountWidget::addPrinting(const QString &zone) { - auto newCardIndex = deckModel->addCard(rootCard->getName(), printingInfo, zone); + auto newCardIndex = deckModel->addCard(rootCard, zone); recursiveExpand(newCardIndex); - QModelIndex find_card = deckModel->findCard(rootCard->getName(), zone); + QModelIndex find_card = deckModel->findCard(rootCard.getName(), zone); if (find_card.isValid() && find_card != newCardIndex) { auto amount = deckModel->data(find_card, Qt::DisplayRole); for (int i = 0; i < amount.toInt() - 1; i++) { - deckModel->addCard(rootCard->getName(), printingInfo, zone); + deckModel->addCard(rootCard, zone); } deckModel->removeRow(find_card.row(), find_card.parent()); } - newCardIndex = - deckModel->findCard(rootCard->getName(), zone, printingInfo.getUuid(), printingInfo.getProperty("num")); + newCardIndex = deckModel->findCard(rootCard.getName(), zone, rootCard.getPrinting().getUuid(), + rootCard.getPrinting().getProperty("num")); deckView->setCurrentIndex(newCardIndex); deckView->setFocus(Qt::FocusReason::MouseFocusReason); deckEditor->setModified(true); @@ -235,8 +233,8 @@ void CardAmountWidget::offsetCountAtIndex(const QModelIndex &idx, int offset) */ void CardAmountWidget::decrementCardHelper(const QString &zone) { - QModelIndex idx = - deckModel->findCard(rootCard->getName(), zone, printingInfo.getUuid(), printingInfo.getProperty("num")); + QModelIndex idx = deckModel->findCard(rootCard.getName(), zone, rootCard.getPrinting().getUuid(), + rootCard.getPrinting().getProperty("num")); offsetCountAtIndex(idx, -1); deckEditor->setModified(true); } @@ -249,7 +247,7 @@ void CardAmountWidget::decrementCardHelper(const QString &zone) */ int CardAmountWidget::countCardsInZone(const QString &deckZone) { - if (printingInfo.getUuid().isEmpty()) { + if (rootCard.getPrinting().getUuid().isEmpty()) { return 0; // Cards without uuids/providerIds CANNOT match another card, they are undefined for us. } @@ -286,7 +284,7 @@ int CardAmountWidget::countCardsInZone(const QString &deckZone) } for (int k = 0; k < currentCard->getNumber(); ++k) { - if (currentCard->getCardProviderId() == printingInfo.getProperty("uuid")) { + if (currentCard->getCardProviderId() == rootCard.getPrinting().getProperty("uuid")) { count++; } } 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 index 6761befca..678bbbe76 100644 --- a/cockatrice/src/client/ui/widgets/printing_selector/card_amount_widget.h +++ b/cockatrice/src/client/ui/widgets/printing_selector/card_amount_widget.h @@ -22,8 +22,7 @@ public: DeckListModel *deckModel, QTreeView *deckView, QSlider *cardSizeSlider, - CardInfoPtr &rootCard, - PrintingInfo &printingInfo, + const ExactCard &rootCard, const QString &zoneName); int countCardsInZone(const QString &deckZone); @@ -40,8 +39,7 @@ private: DeckListModel *deckModel; QTreeView *deckView; QSlider *cardSizeSlider; - CardInfoPtr rootCard; - PrintingInfo printingInfo; + ExactCard rootCard; QString zoneName; QHBoxLayout *layout; DynamicFontSizePushButton *incrementButton; diff --git a/cockatrice/src/client/ui/widgets/printing_selector/printing_selector.cpp b/cockatrice/src/client/ui/widgets/printing_selector/printing_selector.cpp index 978d67811..0a4a30ece 100644 --- a/cockatrice/src/client/ui/widgets/printing_selector/printing_selector.cpp +++ b/cockatrice/src/client/ui/widgets/printing_selector/printing_selector.cpp @@ -218,9 +218,9 @@ void PrintingSelector::getAllSetsForCurrentCard() connect(widgetLoadingBufferTimer, &QTimer::timeout, this, [=, this]() mutable { for (int i = 0; i < BATCH_SIZE && currentIndex < printingsToUse.size(); ++i, ++currentIndex) { - auto *cardDisplayWidget = new PrintingSelectorCardDisplayWidget(this, deckEditor, deckModel, deckView, - cardSizeWidget->getSlider(), selectedCard, - printingsToUse[currentIndex], currentZone); + ExactCard card = ExactCard(selectedCard, printingsToUse[currentIndex]); + auto *cardDisplayWidget = new PrintingSelectorCardDisplayWidget( + this, deckEditor, deckModel, deckView, cardSizeWidget->getSlider(), card, currentZone); flowWidget->addWidget(cardDisplayWidget); cardDisplayWidget->clampSetNameToPicture(); connect(cardDisplayWidget, &PrintingSelectorCardDisplayWidget::cardPreferenceChanged, this, 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 index 877cff2d5..0da80b522 100644 --- 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 @@ -24,7 +24,6 @@ * @param _deckView The QTreeView instance displaying the deck. * @param _cardSizeSlider The slider controlling the size of the displayed card. * @param _rootCard The root card object, representing the card to be displayed. - * @param _printingInfo The printing info for the card being displayed. * @param _currentZone The current zone in which the card is located. */ PrintingSelectorCardDisplayWidget::PrintingSelectorCardDisplayWidget(QWidget *parent, @@ -32,28 +31,27 @@ PrintingSelectorCardDisplayWidget::PrintingSelectorCardDisplayWidget(QWidget *pa DeckListModel *_deckModel, QTreeView *_deckView, QSlider *_cardSizeSlider, - CardInfoPtr _rootCard, - const PrintingInfo &_printingInfo, + const ExactCard &_rootCard, QString &_currentZone) : QWidget(parent), deckEditor(_deckEditor), deckModel(_deckModel), deckView(_deckView), - cardSizeSlider(_cardSizeSlider), rootCard(std::move(_rootCard)), printingInfo(_printingInfo), - currentZone(_currentZone) + cardSizeSlider(_cardSizeSlider), rootCard(_rootCard), currentZone(_currentZone) { layout = new QVBoxLayout(this); setLayout(layout); setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); // Create the overlay widget for the card display - overlayWidget = new PrintingSelectorCardOverlayWidget(this, deckEditor, deckModel, deckView, cardSizeSlider, - rootCard, _printingInfo); + overlayWidget = + new PrintingSelectorCardOverlayWidget(this, deckEditor, deckModel, deckView, cardSizeSlider, rootCard); connect(overlayWidget, &PrintingSelectorCardOverlayWidget::cardPreferenceChanged, this, [this]() { emit cardPreferenceChanged(); }); + CardSetPtr set = rootCard.getPrinting().getSet(); + // Create the widget to display the set name and collector's number - const QString combinedSetName = - QString(_printingInfo.getSet()->getLongName() + " (" + _printingInfo.getSet()->getShortName() + ")"); + QString combinedSetName = QString(set->getLongName() + " (" + set->getShortName() + ")"); setNameAndCollectorsNumberDisplayWidget = new SetNameAndCollectorsNumberDisplayWidget( - this, combinedSetName, _printingInfo.getProperty("num"), cardSizeSlider); + this, combinedSetName, rootCard.getPrinting().getProperty("num"), cardSizeSlider); // Add the widgets to the layout layout->addWidget(overlayWidget, 0, Qt::AlignHCenter); 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 index 4bda0541a..73bcda966 100644 --- 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 @@ -20,8 +20,7 @@ public: DeckListModel *_deckModel, QTreeView *_deckView, QSlider *_cardSizeSlider, - CardInfoPtr _rootCard, - const PrintingInfo &_printingInfo, + const ExactCard &_rootCard, QString &_currentZone); public slots: @@ -37,9 +36,7 @@ private: DeckListModel *deckModel; QTreeView *deckView; QSlider *cardSizeSlider; - CardInfoPtr rootCard; - CardInfoPtr setCard; - PrintingInfo printingInfo; + ExactCard rootCard; QString currentZone; PrintingSelectorCardOverlayWidget *overlayWidget; }; 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 index e1a074528..647ca2054 100644 --- 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 @@ -22,17 +22,15 @@ * @param _deckView The QTreeView instance displaying the deck. * @param _cardSizeSlider The slider controlling the size of the card. * @param _rootCard The root card object that contains information about the card. - * @param _printingInfo The printing-specific information for the card being displayed. */ PrintingSelectorCardOverlayWidget::PrintingSelectorCardOverlayWidget(QWidget *parent, AbstractTabDeckEditor *_deckEditor, DeckListModel *_deckModel, QTreeView *_deckView, QSlider *_cardSizeSlider, - CardInfoPtr _rootCard, - const PrintingInfo &_printingInfo) + const ExactCard &_rootCard) : QWidget(parent), deckEditor(_deckEditor), deckModel(_deckModel), deckView(_deckView), - cardSizeSlider(_cardSizeSlider), rootCard(std::move(_rootCard)), printingInfo(_printingInfo) + cardSizeSlider(_cardSizeSlider), rootCard(_rootCard) { // Set up the main layout auto *mainLayout = new QVBoxLayout(this); @@ -44,13 +42,12 @@ PrintingSelectorCardOverlayWidget::PrintingSelectorCardOverlayWidget(QWidget *pa cardInfoPicture = new CardInfoPictureWidget(this); cardInfoPicture->setMinimumSize(0, 0); cardInfoPicture->setScaleFactor(cardSizeSlider->value()); - setCard = CardDatabaseManager::getInstance()->getCard({rootCard->getName(), _printingInfo.getUuid()}); - cardInfoPicture->setCard(setCard); + cardInfoPicture->setCard(_rootCard); mainLayout->addWidget(cardInfoPicture); // Add AllZonesCardAmountWidget allZonesCardAmountWidget = - new AllZonesCardAmountWidget(this, deckEditor, deckModel, deckView, cardSizeSlider, setCard, _printingInfo); + new AllZonesCardAmountWidget(this, deckEditor, deckModel, deckView, cardSizeSlider, _rootCard); allZonesCardAmountWidget->raise(); // Ensure it's on top of the picture // Set initial visibility based on amounts @@ -119,7 +116,7 @@ void PrintingSelectorCardOverlayWidget::enterEvent(QEvent *event) #endif { QWidget::enterEvent(event); - deckEditor->updateCard(setCard); + deckEditor->updateCard(rootCard); // Check if either mainboard or sideboard amount is greater than 0 if (allZonesCardAmountWidget->getMainboardAmount() > 0 || allZonesCardAmountWidget->getSideboardAmount() > 0) { @@ -170,19 +167,20 @@ void PrintingSelectorCardOverlayWidget::customMenu(QPoint point) menu.addMenu(preferenceMenu); const auto &preferredProviderId = - SettingsCache::instance().cardOverrides().getCardPreferenceOverride(rootCard->getName()); - const auto &cardProviderId = printingInfo.getUuid(); + SettingsCache::instance().cardOverrides().getCardPreferenceOverride(rootCard.getName()); + const auto &cardProviderId = rootCard.getPrinting().getUuid(); if (preferredProviderId.isEmpty() || preferredProviderId != cardProviderId) { auto *pinAction = preferenceMenu->addAction(tr("Pin Printing")); - connect(pinAction, &QAction::triggered, this, [this, cardProviderId]() { - SettingsCache::instance().cardOverrides().setCardPreferenceOverride({rootCard->getName(), cardProviderId}); + connect(pinAction, &QAction::triggered, this, [this] { + SettingsCache::instance().cardOverrides().setCardPreferenceOverride( + {rootCard.getName(), rootCard.getPrinting().getUuid()}); emit cardPreferenceChanged(); }); } else { auto *unpinAction = preferenceMenu->addAction(tr("Unpin Printing")); - connect(unpinAction, &QAction::triggered, this, [this, cardProviderId]() { - SettingsCache::instance().cardOverrides().deleteCardPreferenceOverride(rootCard->getName()); + connect(unpinAction, &QAction::triggered, this, [this] { + SettingsCache::instance().cardOverrides().deleteCardPreferenceOverride(rootCard.getName()); emit cardPreferenceChanged(); }); } @@ -190,7 +188,7 @@ void PrintingSelectorCardOverlayWidget::customMenu(QPoint point) // filling out the related cards submenu auto *relatedMenu = new QMenu(tr("Show Related cards")); menu.addMenu(relatedMenu); - auto relatedCards = rootCard->getAllRelatedCards(); + auto relatedCards = rootCard.getInfo().getAllRelatedCards(); if (relatedCards.isEmpty()) { relatedMenu->setDisabled(true); } else { @@ -198,7 +196,7 @@ void PrintingSelectorCardOverlayWidget::customMenu(QPoint point) const QString &relatedCardName = rel->getName(); QAction *relatedCard = relatedMenu->addAction(relatedCardName); connect(relatedCard, &QAction::triggered, deckEditor, [this, relatedCardName] { - deckEditor->updateCard(CardDatabaseManager::getInstance()->getCardInfo(relatedCardName)); + deckEditor->updateCard(CardDatabaseManager::getInstance()->getCard({relatedCardName})); deckEditor->showPrintingSelector(); }); } 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 index 5d9a8c93d..24fc3d002 100644 --- 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 @@ -19,8 +19,7 @@ public: DeckListModel *_deckModel, QTreeView *_deckView, QSlider *_cardSizeSlider, - CardInfoPtr _rootCard, - const PrintingInfo &_printingInfo); + const ExactCard &_rootCard); protected: void resizeEvent(QResizeEvent *event) override; @@ -43,9 +42,7 @@ private: DeckListModel *deckModel; QTreeView *deckView; QSlider *cardSizeSlider; - CardInfoPtr rootCard; - CardInfoPtr setCard; - PrintingInfo printingInfo; + ExactCard rootCard; }; #endif // PRINTING_SELECTOR_CARD_OVERLAY_WIDGET_H diff --git a/cockatrice/src/client/ui/widgets/visual_database_display/visual_database_display_widget.cpp b/cockatrice/src/client/ui/widgets/visual_database_display/visual_database_display_widget.cpp index 962cdb4bf..e660aa91c 100644 --- a/cockatrice/src/client/ui/widgets/visual_database_display/visual_database_display_widget.cpp +++ b/cockatrice/src/client/ui/widgets/visual_database_display/visual_database_display_widget.cpp @@ -29,7 +29,7 @@ VisualDatabaseDisplayWidget::VisualDatabaseDisplayWidget(QWidget *parent, : QWidget(parent), deckEditor(_deckEditor), databaseModel(database_model), databaseDisplayModel(database_display_model) { - cards = new QList; + cards = new QList; connect(databaseDisplayModel, &CardDatabaseDisplayModel::modelDirty, this, &VisualDatabaseDisplayWidget::modelDirty); @@ -183,12 +183,12 @@ void VisualDatabaseDisplayWidget::onClick(QMouseEvent *event, CardInfoPictureWit emit cardClickedDatabaseDisplay(event, instance); } -void VisualDatabaseDisplayWidget::onHover(const CardInfoPtr &hoveredCard) +void VisualDatabaseDisplayWidget::onHover(const ExactCard &hoveredCard) { emit cardHoveredDatabaseDisplay(hoveredCard); } -void VisualDatabaseDisplayWidget::addCard(const CardInfoPtr &cardToAdd) +void VisualDatabaseDisplayWidget::addCard(const ExactCard &cardToAdd) { cards->append(cardToAdd); auto *display = new CardInfoPictureWithTextOverlayWidget(flowWidget, false); @@ -233,11 +233,11 @@ void VisualDatabaseDisplayWidget::populateCards() SetToPrintingsMap setMap = info->getSets(); if (setMap.contains(setFilter->term())) { for (PrintingInfo printing : setMap[setFilter->term()]) { - addCard(CardDatabaseManager::getInstance()->getCard({name.toString(), printing.getUuid()})); + addCard(ExactCard(info, printing)); } } } else { - addCard(info); + addCard(CardDatabaseManager::getInstance()->getPreferredCard(info)); } } else { qCDebug(VisualDatabaseDisplayLog) << "Card not found in database!"; @@ -298,11 +298,11 @@ void VisualDatabaseDisplayWidget::loadNextPage() SetToPrintingsMap setMap = info->getSets(); if (setMap.contains(setFilter->term())) { for (PrintingInfo printing : setMap[setFilter->term()]) { - addCard(CardDatabaseManager::getInstance()->getCard({name.toString(), printing.getUuid()})); + addCard(ExactCard(info, printing)); } } } else { - addCard(info); + addCard(CardDatabaseManager::getInstance()->getPreferredCard(info)); } } else { qCDebug(VisualDatabaseDisplayLog) << "Card " << name.toString() << " not found in database!"; @@ -335,7 +335,9 @@ void VisualDatabaseDisplayWidget::sortCardList(const QStringList &properties, Qt::SortOrder order = Qt::AscendingOrder) const { CardInfoComparator comparator(properties, order); - std::sort(cards->begin(), cards->end(), comparator); + std::sort(cards->begin(), cards->end(), [comparator](const ExactCard &a, const ExactCard &b) { + return comparator(a.getCardPtr(), b.getCardPtr()); + }); } void VisualDatabaseDisplayWidget::databaseDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) diff --git a/cockatrice/src/client/ui/widgets/visual_database_display/visual_database_display_widget.h b/cockatrice/src/client/ui/widgets/visual_database_display/visual_database_display_widget.h index 8f0cdba97..9b729069f 100644 --- a/cockatrice/src/client/ui/widgets/visual_database_display/visual_database_display_widget.h +++ b/cockatrice/src/client/ui/widgets/visual_database_display/visual_database_display_widget.h @@ -58,12 +58,12 @@ public slots: signals: void cardClickedDatabaseDisplay(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *instance); - void cardHoveredDatabaseDisplay(CardInfoPtr hoveredCard); + void cardHoveredDatabaseDisplay(const ExactCard &hoveredCard); protected slots: void onClick(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *instance); - void onHover(const CardInfoPtr &hoveredCard); - void addCard(const CardInfoPtr &cardToAdd); + void onHover(const ExactCard &hoveredCard); + void addCard(const ExactCard &cardToAdd); void databaseDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight); void wheelEvent(QWheelEvent *event) override; void modelDirty() const; @@ -87,7 +87,7 @@ private: CardDatabaseModel *databaseModel; CardDatabaseDisplayModel *databaseDisplayModel; QTreeView *databaseView; - QList *cards; + QList *cards; QVBoxLayout *mainLayout; QScrollArea *scrollArea; FlowWidget *flowWidget; diff --git a/cockatrice/src/client/ui/widgets/visual_deck_editor/visual_deck_editor_sample_hand_widget.cpp b/cockatrice/src/client/ui/widgets/visual_deck_editor/visual_deck_editor_sample_hand_widget.cpp index efa755a11..7f58530e3 100644 --- a/cockatrice/src/client/ui/widgets/visual_deck_editor/visual_deck_editor_sample_hand_widget.cpp +++ b/cockatrice/src/client/ui/widgets/visual_deck_editor/visual_deck_editor_sample_hand_widget.cpp @@ -38,7 +38,7 @@ VisualDeckEditorSampleHandWidget::VisualDeckEditorSampleHandWidget(QWidget *pare cardSizeWidget = new CardSizeWidget(this, flowWidget); layout->addWidget(cardSizeWidget); - for (CardInfoPtr card : getRandomCards(handSizeSpinBox->value())) { + for (const ExactCard &card : getRandomCards(handSizeSpinBox->value())) { auto displayWidget = new CardInfoPictureWidget(this); displayWidget->setCard(card); displayWidget->setScaleFactor(cardSizeWidget->getSlider()->value()); @@ -64,7 +64,7 @@ void VisualDeckEditorSampleHandWidget::setDeckModel(DeckListModel *deckModel) void VisualDeckEditorSampleHandWidget::updateDisplay() { flowWidget->clearLayout(); - for (CardInfoPtr card : getRandomCards(handSizeSpinBox->value())) { + for (const ExactCard &card : getRandomCards(handSizeSpinBox->value())) { auto displayWidget = new CardInfoPictureWidget(this); displayWidget->setCard(card); displayWidget->setScaleFactor(cardSizeWidget->getSlider()->value()); @@ -74,10 +74,10 @@ void VisualDeckEditorSampleHandWidget::updateDisplay() } } -QList VisualDeckEditorSampleHandWidget::getRandomCards(int amountToGet) +QList VisualDeckEditorSampleHandWidget::getRandomCards(int amountToGet) { - QList mainDeckCards; - QList randomCards; + QList mainDeckCards; + QList randomCards; if (!deckListModel) return randomCards; DeckList *decklist = deckListModel->getDeckList(); @@ -101,9 +101,9 @@ QList VisualDeckEditorSampleHandWidget::getRandomCards(int amountTo continue; for (int k = 0; k < currentCard->getNumber(); ++k) { - CardInfoPtr info = CardDatabaseManager::getInstance()->getCard(currentCard->toCardRef()); - if (info) { - mainDeckCards.append(info); + ExactCard card = CardDatabaseManager::getInstance()->getCard(currentCard->toCardRef()); + if (card) { + mainDeckCards.append(card); } } } @@ -124,7 +124,7 @@ QList VisualDeckEditorSampleHandWidget::getRandomCards(int amountTo } std::sort(randomCards.begin(), randomCards.end(), - [](const CardInfoPtr &a, const CardInfoPtr &b) { return a->getCmc() < b->getCmc(); }); + [](const ExactCard &a, const ExactCard &b) { return a.getInfo().getCmc() < b.getInfo().getCmc(); }); return randomCards; } diff --git a/cockatrice/src/client/ui/widgets/visual_deck_editor/visual_deck_editor_sample_hand_widget.h b/cockatrice/src/client/ui/widgets/visual_deck_editor/visual_deck_editor_sample_hand_widget.h index ba09a978e..8facff557 100644 --- a/cockatrice/src/client/ui/widgets/visual_deck_editor/visual_deck_editor_sample_hand_widget.h +++ b/cockatrice/src/client/ui/widgets/visual_deck_editor/visual_deck_editor_sample_hand_widget.h @@ -14,7 +14,7 @@ class VisualDeckEditorSampleHandWidget : public QWidget Q_OBJECT public: VisualDeckEditorSampleHandWidget(QWidget *parent, DeckListModel *deckListModel); - QList getRandomCards(int amountToGet); + QList getRandomCards(int amountToGet); public slots: void updateDisplay(); diff --git a/cockatrice/src/client/ui/widgets/visual_deck_editor/visual_deck_editor_widget.cpp b/cockatrice/src/client/ui/widgets/visual_deck_editor/visual_deck_editor_widget.cpp index 8cfb02f0f..bf8d8f023 100644 --- a/cockatrice/src/client/ui/widgets/visual_deck_editor/visual_deck_editor_widget.cpp +++ b/cockatrice/src/client/ui/widgets/visual_deck_editor/visual_deck_editor_widget.cpp @@ -42,7 +42,7 @@ VisualDeckEditorWidget::VisualDeckEditorWidget(QWidget *parent, DeckListModel *_ if (!searchBar->hasFocus()) return; - CardInfoPtr card = CardDatabaseManager::getInstance()->getCardInfo(searchBar->text()); + ExactCard card = CardDatabaseManager::getInstance()->getCard({searchBar->text()}); if (card) { emit cardAdditionRequested(card); } @@ -103,7 +103,7 @@ VisualDeckEditorWidget::VisualDeckEditorWidget(QWidget *parent, DeckListModel *_ // Search button functionality searchPushButton = new QPushButton(this); connect(searchPushButton, &QPushButton::clicked, this, [=, this]() { - CardInfoPtr card = CardDatabaseManager::getInstance()->getCardInfo(searchBar->text()); + ExactCard card = CardDatabaseManager::getInstance()->getCard({searchBar->text()}); if (card) { emit cardAdditionRequested(card); } @@ -342,7 +342,7 @@ void VisualDeckEditorWidget::decklistDataChanged(QModelIndex topLeft, QModelInde updateZoneWidgets(); } -void VisualDeckEditorWidget::onHover(CardInfoPtr hoveredCard) +void VisualDeckEditorWidget::onHover(const ExactCard &hoveredCard) { emit activeCardChanged(hoveredCard); } diff --git a/cockatrice/src/client/ui/widgets/visual_deck_editor/visual_deck_editor_widget.h b/cockatrice/src/client/ui/widgets/visual_deck_editor/visual_deck_editor_widget.h index 6f43d624c..01e810eef 100644 --- a/cockatrice/src/client/ui/widgets/visual_deck_editor/visual_deck_editor_widget.h +++ b/cockatrice/src/client/ui/widgets/visual_deck_editor/visual_deck_editor_widget.h @@ -48,15 +48,15 @@ public slots: void constructZoneWidgetsFromDeckListModel(); signals: - void activeCardChanged(CardInfoPtr activeCard); + void activeCardChanged(const ExactCard &activeCard); void activeGroupCriteriaChanged(QString activeGroupCriteria); void activeSortCriteriaChanged(QStringList activeSortCriteria); void cardClicked(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *instance, QString zoneName); - void cardAdditionRequested(CardInfoPtr card); + void cardAdditionRequested(const ExactCard &card); void displayTypeChanged(DisplayType displayType); protected slots: - void onHover(CardInfoPtr hoveredCard); + void onHover(const ExactCard &hoveredCard); void onCardClick(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *instance, QString zoneName); void actChangeActiveGroupCriteria(); void actChangeActiveSortCriteria(); diff --git a/cockatrice/src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_widget.cpp b/cockatrice/src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_widget.cpp index f9e4f0c85..29c536d67 100644 --- a/cockatrice/src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_widget.cpp +++ b/cockatrice/src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_widget.cpp @@ -75,7 +75,7 @@ void DeckPreviewWidget::initializeUi(const bool deckLoadSuccess) return; } auto bannerCard = deckLoader->getBannerCard().name.isEmpty() - ? CardInfoPtr() + ? ExactCard() : CardDatabaseManager::getInstance()->getCard(deckLoader->getBannerCard()); bannerCardDisplayWidget->setCard(bannerCard); diff --git a/cockatrice/src/deck/deck_list_model.cpp b/cockatrice/src/deck/deck_list_model.cpp index b24ae42c7..4ae041c5d 100644 --- a/cockatrice/src/deck/deck_list_model.cpp +++ b/cockatrice/src/deck/deck_list_model.cpp @@ -367,36 +367,40 @@ QModelIndex DeckListModel::findCard(const QString &cardName, QModelIndex DeckListModel::addPreferredPrintingCard(const QString &cardName, const QString &zoneName, bool abAddAnyway) { - return addCard(cardName, CardDatabaseManager::getInstance()->getPreferredPrinting(cardName), zoneName, abAddAnyway); -} + ExactCard card = CardDatabaseManager::getInstance()->getCard({cardName}); -QModelIndex DeckListModel::addCard(const QString &cardName, - const PrintingInfo &printingInfo, - const QString &zoneName, - bool abAddAnyway) -{ - CardInfoPtr cardInfo = CardDatabaseManager::getInstance()->getCard({cardName, printingInfo.getUuid()}); - - if (cardInfo == nullptr) { + if (!card) { if (abAddAnyway) { // We need to keep this card added no matter what // This is usually called from tab_deck_editor // So we'll create a new CardInfo with the name // and default values for all fields - cardInfo = CardInfo::newInstance(cardName); + card = ExactCard(CardInfo::newInstance(cardName)); } else { return {}; } } + return addCard(card, zoneName); +} + +QModelIndex DeckListModel::addCard(const ExactCard &card, const QString &zoneName) +{ + if (!card) { + return {}; + } + InnerDecklistNode *zoneNode = createNodeIfNeeded(zoneName, root); + CardInfoPtr cardInfo = card.getCardPtr(); + PrintingInfo printingInfo = card.getPrinting(); + QString groupCriteria = getGroupCriteriaForCard(cardInfo); InnerDecklistNode *groupNode = createNodeIfNeeded(groupCriteria, zoneNode); const QModelIndex parentIndex = nodeToIndex(groupNode); auto *cardNode = dynamic_cast(groupNode->findCardChildByNameProviderIdAndNumber( - cardName, printingInfo.getUuid(), printingInfo.getProperty("num"))); + card.getName(), printingInfo.getUuid(), printingInfo.getProperty("num"))); const auto cardSetName = printingInfo.getSet().isNull() ? "" : printingInfo.getSet()->getCorrectedShortName(); if (!cardNode) { @@ -538,9 +542,9 @@ void DeckListModel::setDeckList(DeckLoader *_deck) rebuildTree(); } -QList DeckListModel::getCardsAsCardInfoPtrs() const +QList DeckListModel::getCards() const { - QList cards; + QList cards; DeckList *decklist = getDeckList(); if (!decklist) { return cards; @@ -558,9 +562,9 @@ QList DeckListModel::getCardsAsCardInfoPtrs() const if (!currentCard) continue; for (int k = 0; k < currentCard->getNumber(); ++k) { - CardInfoPtr info = CardDatabaseManager::getInstance()->getCard(currentCard->toCardRef()); - if (info) { - cards.append(info); + ExactCard card = CardDatabaseManager::getInstance()->getCard(currentCard->toCardRef()); + if (card) { + cards.append(card); } else { qDebug() << "Card not found in database!"; } @@ -570,9 +574,9 @@ QList DeckListModel::getCardsAsCardInfoPtrs() const return cards; } -QList DeckListModel::getCardsAsCardInfoPtrsForZone(QString zoneName) const +QList DeckListModel::getCardsForZone(const QString &zoneName) const { - QList cards; + QList cards; DeckList *decklist = getDeckList(); if (!decklist) { return cards; @@ -591,9 +595,9 @@ QList DeckListModel::getCardsAsCardInfoPtrsForZone(QString zoneName if (!currentCard) continue; for (int k = 0; k < currentCard->getNumber(); ++k) { - CardInfoPtr info = CardDatabaseManager::getInstance()->getCard(currentCard->toCardRef()); - if (info) { - cards.append(info); + ExactCard card = CardDatabaseManager::getInstance()->getCard(currentCard->toCardRef()); + if (card) { + cards.append(card); } else { qDebug() << "Card not found in database!"; } diff --git a/cockatrice/src/deck/deck_list_model.h b/cockatrice/src/deck/deck_list_model.h index 84fd0c05a..cb074a55c 100644 --- a/cockatrice/src/deck/deck_list_model.h +++ b/cockatrice/src/deck/deck_list_model.h @@ -1,7 +1,7 @@ #ifndef DECKLISTMODEL_H #define DECKLISTMODEL_H -#include "../game/cards/card_info.h" +#include "../game/cards/exact_card.h" #include "decklist.h" #include @@ -111,10 +111,7 @@ public: const QString &providerId = "", const QString &cardNumber = "") const; QModelIndex addPreferredPrintingCard(const QString &cardName, const QString &zoneName, bool abAddAnyway); - QModelIndex addCard(const ::QString &cardName, - const PrintingInfo &printingInfo, - const QString &zoneName, - bool abAddAnyway = false); + QModelIndex addCard(const ExactCard &card, const QString &zoneName); int findSortedInsertRow(InnerDecklistNode *parent, CardInfoPtr cardInfo) const; void sort(int column, Qt::SortOrder order) override; void cleanList(); @@ -123,8 +120,8 @@ public: return deckList; } void setDeckList(DeckLoader *_deck); - QList getCardsAsCardInfoPtrs() const; - QList getCardsAsCardInfoPtrsForZone(QString zoneName) const; + QList getCards() const; + QList getCardsForZone(const QString &zoneName) const; QList *getZones() const; void setActiveGroupCriteria(DeckListModelGroupCriteria newCriteria); diff --git a/cockatrice/src/deck/deck_loader.cpp b/cockatrice/src/deck/deck_loader.cpp index 3f51935e7..965e71c56 100644 --- a/cockatrice/src/deck/deck_loader.cpp +++ b/cockatrice/src/deck/deck_loader.cpp @@ -594,9 +594,9 @@ QString DeckLoader::getCardZoneFromName(QString cardName, QString currentZoneNam QString DeckLoader::getCompleteCardName(const QString &cardName) const { if (CardDatabaseManager::getInstance()) { - CardInfoPtr temp = CardDatabaseManager::getInstance()->guessCard({cardName}); + ExactCard temp = CardDatabaseManager::getInstance()->guessCard({cardName}); if (temp) { - return temp->getName(); + return temp.getName(); } } diff --git a/cockatrice/src/dialogs/dlg_create_token.cpp b/cockatrice/src/dialogs/dlg_create_token.cpp index 14adaa48a..2f37c7be6 100644 --- a/cockatrice/src/dialogs/dlg_create_token.cpp +++ b/cockatrice/src/dialogs/dlg_create_token.cpp @@ -198,7 +198,7 @@ void DlgCreateToken::tokenSelectionChanged(const QModelIndex ¤t, const QMo annotationEdit->setText(""); } - pic->setCard(cardInfo); + pic->setCard(CardDatabaseManager::getInstance()->getPreferredCard(cardInfo)); } void DlgCreateToken::updateSearchFieldWithoutUpdatingFilter(const QString &newValue) const diff --git a/cockatrice/src/dialogs/dlg_select_set_for_cards.cpp b/cockatrice/src/dialogs/dlg_select_set_for_cards.cpp index c4261e3dc..8e139bdff 100644 --- a/cockatrice/src/dialogs/dlg_select_set_for_cards.cpp +++ b/cockatrice/src/dialogs/dlg_select_set_for_cards.cpp @@ -152,8 +152,9 @@ void DlgSelectSetForCards::actOK() continue; } model->removeRow(find_card.row(), find_card.parent()); - model->addCard(card, CardDatabaseManager::getInstance()->getSpecificPrinting(card, modifiedSet, ""), - DECK_ZONE_MAIN); + CardInfoPtr cardInfo = CardDatabaseManager::getInstance()->getCardInfo(card); + PrintingInfo printing = CardDatabaseManager::getInstance()->getSpecificPrinting(card, modifiedSet, ""); + model->addCard(ExactCard(cardInfo, printing), DECK_ZONE_MAIN); } } accept(); @@ -290,17 +291,17 @@ void DlgSelectSetForCards::updateCardLists() if (!found) { // The card was not in any selected set - CardInfoPtr infoPtr = CardDatabaseManager::getInstance()->getCardInfo(currentCard->getName()); + ExactCard card = CardDatabaseManager::getInstance()->getCard({currentCard->getName()}); CardInfoPictureWidget *picture_widget = new CardInfoPictureWidget(uneditedCardsFlowWidget); - picture_widget->setCard(infoPtr); + picture_widget->setCard(card); uneditedCardsFlowWidget->addWidget(picture_widget); } else { - CardInfoPtr infoPtr = CardDatabaseManager::getInstance()->getCard( + ExactCard card = CardDatabaseManager::getInstance()->getCard( {currentCard->getName(), CardDatabaseManager::getInstance() ->getSpecificPrinting(currentCard->getName(), foundSetName, "") .getUuid()}); CardInfoPictureWidget *picture_widget = new CardInfoPictureWidget(modifiedCardsFlowWidget); - picture_widget->setCard(infoPtr); + picture_widget->setCard(card); modifiedCardsFlowWidget->addWidget(picture_widget); } } diff --git a/cockatrice/src/game/board/abstract_card_item.cpp b/cockatrice/src/game/board/abstract_card_item.cpp index fa74db3c9..12c180da9 100644 --- a/cockatrice/src/game/board/abstract_card_item.cpp +++ b/cockatrice/src/game/board/abstract_card_item.cpp @@ -57,22 +57,29 @@ void AbstractCardItem::pixmapUpdated() void AbstractCardItem::refreshCardInfo() { - info = CardDatabaseManager::getInstance()->getCard(cardRef); + exactCard = CardDatabaseManager::getInstance()->getCard(cardRef); - if (!info && !cardRef.name.isEmpty()) { - QVariantHash properties = QVariantHash(); - - info = CardInfo::newInstance(cardRef.name, "", true, QVariantHash(), QList(), - QList(), SetToPrintingsMap(), false, false, -1, false); + if (!exactCard && !cardRef.name.isEmpty()) { + auto info = CardInfo::newInstance(cardRef.name, "", true, {}, {}, {}, {}, false, false, -1, false); + exactCard = ExactCard(info); } - if (info.data()) { - connect(info.data(), &CardInfo::pixmapUpdated, this, &AbstractCardItem::pixmapUpdated); + if (exactCard) { + connect(exactCard.getCardPtr().data(), &CardInfo::pixmapUpdated, this, &AbstractCardItem::pixmapUpdated); } cacheBgColor(); update(); } +/** + * Convenience method to get the CardInfo of the exactCard + * @return A const reference to the CardInfo, or an empty CardInfo if card was null + */ +const CardInfo &AbstractCardItem::getCardInfo() const +{ + return exactCard.getInfo(); +} + void AbstractCardItem::setRealZValue(qreal _zValue) { realZValue = _zValue; @@ -116,7 +123,7 @@ void AbstractCardItem::paintPicture(QPainter *painter, const QSizeF &translatedS } else { // don't even spend time trying to load the picture if our size is too small if (translatedSize.width() > 10) { - PictureLoader::getPixmap(translatedPixmap, info, translatedSize.toSize()); + PictureLoader::getPixmap(translatedPixmap, exactCard, translatedSize.toSize()); if (translatedPixmap.isNull()) paintImage = false; } else { @@ -191,8 +198,8 @@ void AbstractCardItem::setCardRef(const CardRef &_cardRef) } emit deleteCardInfoPopup(cardRef.name); - if (info) { - disconnect(info.data(), nullptr, this, nullptr); + if (exactCard) { + disconnect(exactCard.getCardPtr().data(), nullptr, this, nullptr); } cardRef = _cardRef; @@ -224,8 +231,7 @@ void AbstractCardItem::cacheBgColor() { QChar colorChar; if (color.isEmpty()) { - if (info) - colorChar = info->getColorChar(); + colorChar = exactCard.getInfo().getColorChar(); } else { colorChar = color.at(0); } diff --git a/cockatrice/src/game/board/abstract_card_item.h b/cockatrice/src/game/board/abstract_card_item.h index 1a64676fe..72f641345 100644 --- a/cockatrice/src/game/board/abstract_card_item.h +++ b/cockatrice/src/game/board/abstract_card_item.h @@ -1,7 +1,7 @@ #ifndef ABSTRACTCARDITEM_H #define ABSTRACTCARDITEM_H -#include "../cards/card_info.h" +#include "../cards/exact_card.h" #include "arrow_target.h" #include "card_ref.h" @@ -14,7 +14,7 @@ class AbstractCardItem : public ArrowTarget { Q_OBJECT protected: - CardInfoPtr info; + ExactCard exactCard; int id; CardRef cardRef; bool tapped; @@ -58,10 +58,11 @@ public: QSizeF getTranslatedSize(QPainter *painter) const; void paintPicture(QPainter *painter, const QSizeF &translatedSize, int angle); void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override; - CardInfoPtr getInfo() const + ExactCard getCard() const { - return info; + return exactCard; } + const CardInfo &getCardInfo() const; int getId() const { return id; diff --git a/cockatrice/src/game/board/arrow_item.cpp b/cockatrice/src/game/board/arrow_item.cpp index 4caebdda0..ff44a7ae6 100644 --- a/cockatrice/src/game/board/arrow_item.cpp +++ b/cockatrice/src/game/board/arrow_item.cpp @@ -237,10 +237,10 @@ void ArrowDragItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) } if (startZone->getName().compare("hand") == 0) { startCard->playCard(false); - CardInfoPtr ci = startCard->getInfo(); - if (ci && (((!SettingsCache::instance().getPlayToStack() && ci->getTableRow() == 3) || - ((SettingsCache::instance().getPlayToStack() && ci->getTableRow() != 0) && - startCard->getZone()->getName().toStdString() != "stack")))) + CardInfoPtr ci = startCard->getCard().getCardPtr(); + if (ci && ((!SettingsCache::instance().getPlayToStack() && ci->getTableRow() == 3) || + (SettingsCache::instance().getPlayToStack() && ci->getTableRow() != 0 && + startCard->getZone()->getName().toStdString() != "stack"))) cmd.set_start_zone("stack"); else cmd.set_start_zone(SettingsCache::instance().getPlayToStack() ? "stack" : "table"); diff --git a/cockatrice/src/game/board/card_item.cpp b/cockatrice/src/game/board/card_item.cpp index 0e4504dd7..c1d50b2ba 100644 --- a/cockatrice/src/game/board/card_item.cpp +++ b/cockatrice/src/game/board/card_item.cpp @@ -107,7 +107,7 @@ void CardItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, painter->save(); transformPainter(painter, translatedSize, tapAngle); - if (!getFaceDown() && info && pt == info->getPowTough()) { + if (!getFaceDown() && pt == exactCard.getInfo().getPowTough()) { painter->setPen(Qt::white); } else { painter->setPen(QColor(255, 150, 0)); // dark orange diff --git a/cockatrice/src/game/board/card_list.cpp b/cockatrice/src/game/board/card_list.cpp index 0355bf6bd..7ad6e3b30 100644 --- a/cockatrice/src/game/board/card_list.cpp +++ b/cockatrice/src/game/board/card_list.cpp @@ -77,12 +77,12 @@ void CardList::sortBy(const QList &option) * @param c The card info * @param appendAtEnd For multicolor cards, whether to also append the entire color string at the end. */ -static QString getColorSortString(CardInfoPtr c, bool appendAtEnd) +static QString getColorSortString(const CardInfo &c, bool appendAtEnd) { - QString colors = c->getColors(); + QString colors = c.getColors(); switch (colors.size()) { case 0: { - if (c->getCardType().contains("Land")) { + if (c.getCardType().contains("Land")) { return "a_land"; } else { return "b_colorless"; @@ -119,33 +119,36 @@ std::function CardList::getExtractorFor(SortOption option) case NoSort: return [](CardItem *) { return ""; }; case SortByMainType: - return [](CardItem *c) { return c->getInfo() ? c->getInfo()->getMainCardType() : ""; }; + return [](CardItem *c) { return c->getCardInfo().getMainCardType(); }; case SortByManaValue: // getCmc returns the int as a string. We pad with 0's so that string comp also works on it - return [](CardItem *c) { return c->getInfo() ? c->getInfo()->getCmc().rightJustified(4, '0') : ""; }; + return [](CardItem *c) { return c->getCard() ? c->getCardInfo().getCmc().rightJustified(4, '0') : ""; }; case SortByColorGrouping: - return [](CardItem *c) { return c->getInfo() ? getColorSortString(c->getInfo(), false) : ""; }; + return [](CardItem *c) { return c->getCard() ? getColorSortString(c->getCardInfo(), false) : ""; }; case SortByName: return [](CardItem *c) { return c->getName(); }; case SortByType: - return [](CardItem *c) { return c->getInfo() ? c->getInfo()->getCardType() : ""; }; + return [](CardItem *c) { return c->getCardInfo().getCardType(); }; case SortByManaCost: return [](CardItem *c) { - auto info = c->getInfo(); - if (!info) - return QString(""); + if (!c->getCard()) { + return QString(); + } + + auto info = c->getCardInfo(); // calculation copied from CardDatabaseModel. // we pad the cmc and also append the mana cost to the end so same cmc cards still have a sort order - return QString("%1%2").arg(info->getCmc(), 4, QChar('0')).arg(info->getManaCost()); + return QString("%1%2").arg(info.getCmc(), 4, QChar('0')).arg(info.getManaCost()); }; case SortByColors: - return [](CardItem *c) { return c->getInfo() ? getColorSortString(c->getInfo(), true) : ""; }; + return [](CardItem *c) { return c->getCard() ? getColorSortString(c->getCardInfo(), true) : ""; }; case SortByPt: // do the same padding trick as above - return [](CardItem *c) { return c->getInfo() ? c->getInfo()->getPowTough().rightJustified(10, '0') : ""; }; + return + [](CardItem *c) { return c->getCard() ? c->getCardInfo().getPowTough().rightJustified(10, '0') : ""; }; case SortBySet: - return [](CardItem *c) { return c->getInfo() ? c->getInfo()->getSetsNames() : ""; }; + return [](CardItem *c) { return c->getCardInfo().getSetsNames(); }; case SortByPrinting: return [](CardItem *c) { return c->getProviderId(); }; } diff --git a/cockatrice/src/game/cards/card_database.cpp b/cockatrice/src/game/cards/card_database.cpp index b32ed03d0..884919308 100644 --- a/cockatrice/src/game/cards/card_database.cpp +++ b/cockatrice/src/game/cards/card_database.cpp @@ -110,11 +110,10 @@ void CardDatabase::removeCard(CardInfoPtr card) } /** - * Looks up the generic cardInfo (the CardInfoPtr that does not refer to a specific printing) corresponding to the - * cardName. + * Looks up the cardInfo corresponding to the cardName. * * @param cardName The card name to look up - * @return A generic CardInfoPtr, or null if not corresponding CardInfo is found. + * @return A CardInfoPtr, or null if not corresponding CardInfo is found. */ CardInfoPtr CardDatabase::getCardInfo(const QString &cardName) const { @@ -122,10 +121,10 @@ CardInfoPtr CardDatabase::getCardInfo(const QString &cardName) const } /** - * Looks up the generic cardInfos (the CardInfoPtr that does not refer to a specific printing) for a list of card names. + * Looks up the cardInfos for a list of card names. * * @param cardNames The card names to look up - * @return A List of generic CardInfoPtr. Any failed lookups will be ignored and dropped from the resulting list + * @return A List of CardInfoPtr. Any failed lookups will be ignored and dropped from the resulting list */ QList CardDatabase::getCardInfos(const QStringList &cardNames) const { @@ -140,48 +139,46 @@ QList CardDatabase::getCardInfos(const QStringList &cardNames) cons } /** - * Looks up the CardInfoPtrs corresponding to the CardRefs + * Looks up the cards corresponding to the CardRefs. + * If the providerId is empty, will default to the preferred printing. + * If providerId is given but not found, the PrintingInfo will be empty. * - * @param cardRefs The cards to look up. If providerId is empty for an entry, will look up the generic CardInfo for that - * entry's cardName. - * @return A list of specific printings of cards. Any failed lookups will be ignored and dropped from the resulting - * list. + * @param cardRefs The cards to look up. If providerId is empty for an entry, will default to the preferred printing for + * that entry. If providerId is given but not found, the PrintingInfo will be empty for that entry. + * @return A list of cards. Any failed lookups will be ignored and dropped from the resulting list. */ -QList CardDatabase::getCards(const QList &cardRefs) const +QList CardDatabase::getCards(const QList &cardRefs) const { - QList cardInfos; + QList cards; for (const auto &cardRef : cardRefs) { - CardInfoPtr ptr = getCard(cardRef); - if (ptr) - cardInfos.append(ptr); + ExactCard card = getCard(cardRef); + if (card) + cards.append(card); } - return cardInfos; + return cards; } /** - * Looks up the CardInfoPtr corresponding to the CardRef + * Looks up the card corresponding to the CardRef. + * If the providerId is empty, will default to the preferred printing. + * If providerId is given but not found, the PrintingInfo will be empty. * - * @param cardRef The card to look up. If providerId is empty, will look up the generic CardInfo for the cardName. - * @return A specific printing of a card, or null if not found. + * @param cardRef The card to look up. + * @return A specific printing of a card, or empty if not found. */ -CardInfoPtr CardDatabase::getCard(const CardRef &cardRef) const +ExactCard CardDatabase::getCard(const CardRef &cardRef) const { auto info = getCardInfo(cardRef.name); - if (cardRef.providerId.isNull() || cardRef.providerId.isEmpty() || info.isNull()) { - return info; - } - - PrintingInfo printing = findPrintingWithId(info, cardRef.providerId); - - if (!printing.getSet()) { + if (info.isNull()) { return {}; } - CardInfoPtr cardFromSpecificSet = info->clone(); - cardFromSpecificSet->setPixmapCacheKey(QLatin1String("card_") + QString(info->getName()) + QString("_") + - QString(printing.getProperty("uuid"))); - return cardFromSpecificSet; + if (cardRef.providerId.isEmpty() || cardRef.providerId.isNull()) { + return ExactCard(info, getPreferredPrinting(info)); + } + + return ExactCard(info, findPrintingWithId(info, cardRef.providerId)); } CardInfoPtr CardDatabase::getCardBySimpleName(const QString &cardName) const @@ -190,14 +187,16 @@ CardInfoPtr CardDatabase::getCardBySimpleName(const QString &cardName) const } /** - * Looks up the CardInfoPtr by CardRef, simplifying the name if required. + * Looks up the card by CardRef, simplifying the name if required. + * If the providerId is empty, will default to the preferred printing. + * If providerId is given but not found, the PrintingInfo will be empty. * - * @param cardRef The card to look up. If providerId is empty, will look up the generic CardInfo for the cardName. - * @return A specific printing of a card, or null if not found. + * @param cardRef The card to look up. + * @return A specific printing of a card, or empty if not found. */ -CardInfoPtr CardDatabase::guessCard(const CardRef &cardRef) const +ExactCard CardDatabase::guessCard(const CardRef &cardRef) const { - CardInfoPtr temp = getCard(cardRef); + CardInfoPtr temp = getCardInfo(cardRef.name); if (temp == nullptr) { // get card by simple name instead temp = getCardBySimpleName(cardRef.name); @@ -206,7 +205,12 @@ CardInfoPtr CardDatabase::guessCard(const CardRef &cardRef) const temp = getCardBySimpleName(simpleCardName); } } - return temp; // returns nullptr if not found + + if (cardRef.providerId.isEmpty() || cardRef.providerId.isNull()) { + return ExactCard(temp, getPreferredPrinting(temp)); + } + + return ExactCard(temp, findPrintingWithId(temp, cardRef.providerId)); } CardSetPtr CardDatabase::getSet(const QString &setName) @@ -303,8 +307,6 @@ LoadStatus CardDatabase::loadCardDatabases() // AFTER all the cards have been loaded - // Refresh the pixmap cache keys for all cards by setting them to the UUID of the preferred printing - refreshPreferredPrintings(); // resolve the reverse-related tags refreshCachedReverseRelatedCards(); @@ -321,12 +323,25 @@ LoadStatus CardDatabase::loadCardDatabases() return loadStatus; } -void CardDatabase::refreshPreferredPrintings() +/** + * Gets the card representing the preferred printing of the cardInfo + * + * @param cardInfo The cardInfo to find the preferred printing for + * @return A specific printing of a card + */ +ExactCard CardDatabase::getPreferredCard(const CardInfoPtr &cardInfo) const { - for (const CardInfoPtr &card : cards) { - card->setPixmapCacheKey(QLatin1String("card_") + QString(card->getName()) + QString("_") + - QString(getPreferredPrintingProviderId(card->getName()))); + return ExactCard(cardInfo, getPreferredPrinting(cardInfo)); +} + +PrintingInfo CardDatabase::getSpecificPrinting(const CardRef &cardRef) const +{ + CardInfoPtr cardInfo = getCardInfo(cardRef.name); + if (!cardInfo) { + return PrintingInfo(nullptr); } + + return findPrintingWithId(cardInfo, cardRef.providerId); } /** @@ -387,16 +402,6 @@ PrintingInfo CardDatabase::getPreferredPrinting(const CardInfoPtr &cardInfo) con return PrintingInfo(nullptr); } -PrintingInfo CardDatabase::getSpecificPrinting(const CardRef &cardRef) const -{ - CardInfoPtr cardInfo = getCardInfo(cardRef.name); - if (!cardInfo) { - return PrintingInfo(nullptr); - } - - return findPrintingWithId(cardInfo, cardRef.providerId); -} - PrintingInfo CardDatabase::getSpecificPrinting(const QString &cardName, const QString &setShortName, const QString &collectorNumber) const @@ -453,25 +458,6 @@ bool CardDatabase::isPreferredPrinting(const CardRef &cardRef) const return cardRef.providerId == getPreferredPrintingProviderId(cardRef.name); } -PrintingInfo CardDatabase::getSetInfoForCard(const CardInfoPtr &_card) -{ - const SetToPrintingsMap &setMap = _card->getSets(); - if (setMap.empty()) { - return PrintingInfo(nullptr); - } - - for (const auto &printings : setMap) { - for (const auto &cardInfoForSet : printings) { - if (QLatin1String("card_") + _card->getName() + QString("_") + cardInfoForSet.getUuid() == - _card->getPixmapCacheKey()) { - return cardInfoForSet; - } - } - } - - return PrintingInfo(nullptr); -} - void CardDatabase::refreshCachedReverseRelatedCards() { for (const CardInfoPtr &card : cards) diff --git a/cockatrice/src/game/cards/card_database.h b/cockatrice/src/game/cards/card_database.h index 975cda4bb..8b1b2926f 100644 --- a/cockatrice/src/game/cards/card_database.h +++ b/cockatrice/src/game/cards/card_database.h @@ -2,7 +2,7 @@ #define CARDDATABASE_H #include "../common/card_ref.h" -#include "card_info.h" +#include "exact_card.h" #include #include @@ -69,8 +69,10 @@ public: [[nodiscard]] CardInfoPtr getCardInfo(const QString &cardName) const; [[nodiscard]] QList getCardInfos(const QStringList &cardNames) const; - QList getCards(const QList &cardRefs) const; - [[nodiscard]] CardInfoPtr getCard(const CardRef &cardRef) const; + QList getCards(const QList &cardRefs) const; + [[nodiscard]] ExactCard getCard(const CardRef &cardRef) const; + + [[nodiscard]] ExactCard getPreferredCard(const CardInfoPtr &cardInfo) const; static PrintingInfo findPrintingWithId(const CardInfoPtr &cardInfo, const QString &providerId); [[nodiscard]] PrintingInfo getPreferredPrinting(const QString &cardName) const; @@ -81,7 +83,7 @@ public: QString getPreferredPrintingProviderId(const QString &cardName) const; bool isPreferredPrinting(const CardRef &cardRef) const; - [[nodiscard]] CardInfoPtr guessCard(const CardRef &cardRef) const; + [[nodiscard]] ExactCard guessCard(const CardRef &cardRef) const; /* * Get a card by its simple name. The name will be simplified in this @@ -90,7 +92,6 @@ public: [[nodiscard]] CardInfoPtr getCardBySimpleName(const QString &cardName) const; CardSetPtr getSet(const QString &setName); - static PrintingInfo getSetInfoForCard(const CardInfoPtr &_card); const CardNameMap &getCardList() const { return cards; @@ -111,7 +112,6 @@ public: public slots: LoadStatus loadCardDatabases(); - void refreshPreferredPrintings(); void addCard(CardInfoPtr card); void addSet(CardSetPtr set); protected slots: diff --git a/cockatrice/src/game/cards/card_info.cpp b/cockatrice/src/game/cards/card_info.cpp index c10b7e6d9..f5424cd4d 100644 --- a/cockatrice/src/game/cards/card_info.cpp +++ b/cockatrice/src/game/cards/card_info.cpp @@ -242,17 +242,11 @@ CardInfo::CardInfo(const QString &_name, reverseRelatedCards(_reverseRelatedCards), setsToPrintings(std::move(_sets)), cipt(_cipt), landscapeOrientation(_landscapeOrientation), tableRow(_tableRow), upsideDownArt(_upsideDownArt) { - pixmapCacheKey = QLatin1String("card_") + name; simpleName = CardInfo::simplifyName(name); refreshCachedSetNames(); } -CardInfo::~CardInfo() -{ - PictureLoader::clearPixmapCache(smartThis); -} - CardInfoPtr CardInfo::newInstance(const QString &_name) { return newInstance(_name, QString(), false, QVariantHash(), QList(), QList(), diff --git a/cockatrice/src/game/cards/card_info.h b/cockatrice/src/game/cards/card_info.h index 0aeff5752..33ed569d5 100644 --- a/cockatrice/src/game/cards/card_info.h +++ b/cockatrice/src/game/cards/card_info.h @@ -148,7 +148,7 @@ public: class PrintingInfo { public: - explicit PrintingInfo(const CardSetPtr &_set = QSharedPointer(nullptr)); + explicit PrintingInfo(const CardSetPtr &_set = nullptr); ~PrintingInfo() = default; bool operator==(const PrintingInfo &other) const @@ -191,8 +191,6 @@ private: QString name; // The name without punctuation or capitalization, for better card name recognition. QString simpleName; - // The key used to identify this card in the cache - QString pixmapCacheKey; // card text QString text; // whether this is not a "real" card but a token @@ -228,14 +226,13 @@ public: int _tableRow, bool _upsideDownArt); CardInfo(const CardInfo &other) - : QObject(other.parent()), name(other.name), simpleName(other.simpleName), pixmapCacheKey(other.pixmapCacheKey), - text(other.text), isToken(other.isToken), properties(other.properties), relatedCards(other.relatedCards), + : QObject(other.parent()), name(other.name), simpleName(other.simpleName), text(other.text), + isToken(other.isToken), properties(other.properties), relatedCards(other.relatedCards), reverseRelatedCards(other.reverseRelatedCards), reverseRelatedCardsToMe(other.reverseRelatedCardsToMe), setsToPrintings(other.setsToPrintings), setsNames(other.setsNames), cipt(other.cipt), landscapeOrientation(other.landscapeOrientation), tableRow(other.tableRow), upsideDownArt(other.upsideDownArt) { } - ~CardInfo() override; static CardInfoPtr newInstance(const QString &_name); @@ -273,14 +270,6 @@ public: { return simpleName; } - void setPixmapCacheKey(QString _pixmapCacheKey) - { - pixmapCacheKey = _pixmapCacheKey; - } - const QString &getPixmapCacheKey() const - { - return pixmapCacheKey; - } const QString &getText() const { @@ -321,20 +310,6 @@ public: { return setsNames; } - QString getSetProperty(const QString &setName, const QString &propertyName) const - { - if (!setsToPrintings.contains(setName)) - return ""; - - for (const auto &set : setsToPrintings[setName]) { - if (QLatin1String("card_") + this->getName() + QString("_") + QString(set.getProperty("uuid")) == - this->getPixmapCacheKey()) { - return set.getProperty(propertyName); - } - } - - return setsToPrintings[setName][0].getProperty(propertyName); - } // related cards const QList &getRelatedCards() const @@ -397,18 +372,9 @@ public: const QString getPowTough() const; void setPowTough(const QString &value); - // methods using per-set properties - QString getCustomPicURL(const QString &set) const - { - return getSetProperty(set, "picurl"); - } QString getCorrectedName() const; void addToSet(const CardSetPtr &_set, PrintingInfo _info = PrintingInfo()); void combineLegalities(const QVariantHash &props); - void emitPixmapUpdated() - { - emit pixmapUpdated(); - } void refreshCachedSetNames(); /** @@ -418,7 +384,11 @@ public: static QString simplifyName(const QString &name); signals: - void pixmapUpdated(); + /** + * Emit this when a pixmap for this card finishes loading. + * @param printing The specific printing the pixmap is for. + */ + void pixmapUpdated(const PrintingInfo &printing); void cardInfoChanged(CardInfoPtr card); }; diff --git a/cockatrice/src/game/cards/exact_card.cpp b/cockatrice/src/game/cards/exact_card.cpp new file mode 100644 index 000000000..fbd60071e --- /dev/null +++ b/cockatrice/src/game/cards/exact_card.cpp @@ -0,0 +1,79 @@ +#include "exact_card.h" + +/** + * Default constructor. + * This will set the CardInfoPtr to null. + * The printing will be the default-constructed PrintingInfo. + */ +ExactCard::ExactCard() +{ +} + +/** + * @param _card The card. Can be null. + * @param _printing The printing. Can be empty. + */ +ExactCard::ExactCard(const CardInfoPtr &_card, const PrintingInfo &_printing) : card(_card), printing(_printing) +{ +} + +bool ExactCard::operator==(const ExactCard &other) const +{ + return this->card == other.card && this->printing == other.printing; +} + +/** + * Convenience method to safely get the card's name. + * @return The name in the CardInfo, or an empty string if card is null + */ +QString ExactCard::getName() const +{ + return card.isNull() ? "" : card->getName(); +} + +/** + * Gets a view of the underlying cardInfoPtr. + * @return A const reference to the CardInfo, or an empty CardInfo if card is null + */ +const CardInfo &ExactCard::getInfo() const +{ + if (card.isNull()) { + static CardInfoPtr emptyCard = CardInfo::newInstance(""); + return *emptyCard; + } + return *card; +} + +/** + * The key used to identify this exact printing in the cache + */ +QString ExactCard::getPixmapCacheKey() const +{ + QString uuid = printing.getUuid(); + QString suffix = uuid.isEmpty() ? "" : "_" + uuid; + return QLatin1String("card_") + card->getName() + suffix; +} + +/** + * Checks if the card is null or empty. + */ +bool ExactCard::isEmpty() const +{ + return card.isNull() || card->getName().isEmpty(); +} + +/** + * Returns true if isEmpty() is false + */ +ExactCard::operator bool() const +{ + return !isEmpty(); +} + +/** + * Gets the CardInfo to emit the pixmapUpdated signal + */ +void ExactCard::emitPixmapUpdated() const +{ + emit card->pixmapUpdated(printing); +} \ No newline at end of file diff --git a/cockatrice/src/game/cards/exact_card.h b/cockatrice/src/game/cards/exact_card.h new file mode 100644 index 000000000..a962ea076 --- /dev/null +++ b/cockatrice/src/game/cards/exact_card.h @@ -0,0 +1,46 @@ +#ifndef EXACT_CARD_H +#define EXACT_CARD_H + +#include "card_info.h" + +/** + * Identifies the card along with its exact printing + */ +class ExactCard +{ + CardInfoPtr card; + PrintingInfo printing; + +public: + ExactCard(); + explicit ExactCard(const CardInfoPtr &_card, const PrintingInfo &_printing = PrintingInfo()); + + /** + * Gets the CardInfoPtr. Can be null. + */ + CardInfoPtr getCardPtr() const + { + return card; + } + + /** + * Gets the PrintingInfo. Can be empty. + */ + PrintingInfo getPrinting() const + { + return printing; + } + + bool operator==(const ExactCard &other) const; + + QString getName() const; + const CardInfo &getInfo() const; + QString getPixmapCacheKey() const; + + bool isEmpty() const; + explicit operator bool() const; + + void emitPixmapUpdated() const; +}; + +#endif // EXACT_CARD_H diff --git a/cockatrice/src/game/deckview/deck_view.cpp b/cockatrice/src/game/deckview/deck_view.cpp index 1a5c0aea0..9be1c556e 100644 --- a/cockatrice/src/game/deckview/deck_view.cpp +++ b/cockatrice/src/game/deckview/deck_view.cpp @@ -217,13 +217,13 @@ void DeckViewCardContainer::paint(QPainter *painter, const QStyleOptionGraphicsI void DeckViewCardContainer::addCard(DeckViewCard *card) { cards.append(card); - cardsByType.insert(card->getInfo() ? card->getInfo()->getMainCardType() : "", card); + cardsByType.insert(card->getCard().isEmpty() ? "" : card->getCardInfo().getMainCardType(), card); } void DeckViewCardContainer::removeCard(DeckViewCard *card) { cards.removeOne(card); - cardsByType.remove(card->getInfo() ? card->getInfo()->getMainCardType() : "", card); + cardsByType.remove(card->getCard().isEmpty() ? "" : card->getCardInfo().getMainCardType(), card); } QList> DeckViewCardContainer::getRowsAndCols() const diff --git a/cockatrice/src/game/player/player.cpp b/cockatrice/src/game/player/player.cpp index 04b70d015..4a83a9ae0 100644 --- a/cockatrice/src/game/player/player.cpp +++ b/cockatrice/src/game/player/player.cpp @@ -1488,7 +1488,7 @@ void Player::moveOneCardUntil(CardItem *card) { moveTopCardTimer->stop(); - const bool isMatch = card && movingCardsUntilFilter.check(card->getInfo()); + const bool isMatch = card && movingCardsUntilFilter.check(card->getCard().getCardPtr()); if (isMatch && movingCardsUntilAutoPlay) { // Directly calling playCard will deadlock, since we are already in the middle of processing an event. @@ -1849,12 +1849,12 @@ void Player::actCreateToken() lastTokenInfo = dlg.getTokenInfo(); - CardInfoPtr correctedCard = CardDatabaseManager::getInstance()->guessCard({lastTokenInfo.name}); + ExactCard correctedCard = CardDatabaseManager::getInstance()->guessCard({lastTokenInfo.name}); if (correctedCard) { - lastTokenInfo.name = correctedCard->getName(); - lastTokenTableRow = TableZone::clampValidTableRow(2 - correctedCard->getTableRow()); + lastTokenInfo.name = correctedCard.getName(); + lastTokenTableRow = TableZone::clampValidTableRow(2 - correctedCard.getInfo().getTableRow()); if (lastTokenInfo.pt.isEmpty()) { - lastTokenInfo.pt = correctedCard->getPowTough(); + lastTokenInfo.pt = correctedCard.getInfo().getPowTough(); } } @@ -1904,7 +1904,7 @@ void Player::actCreateRelatedCard() } auto *action = static_cast(sender()); // If there is a better way of passing a CardRelation through a QAction, please add it here. - auto relatedCards = sourceCard->getInfo()->getAllRelatedCards(); + auto relatedCards = sourceCard->getCardInfo().getAllRelatedCards(); CardRelation *cardRelation = relatedCards.at(action->data().toInt()); /* @@ -1912,9 +1912,9 @@ void Player::actCreateRelatedCard() * then let's allow it to be created via "create another token" */ if (createRelatedFromRelation(sourceCard, cardRelation) && cardRelation->getCanCreateAnother()) { - CardInfoPtr cardInfo = + ExactCard cardInfo = CardDatabaseManager::getInstance()->getCard({cardRelation->getName(), sourceCard->getProviderId()}); - setLastToken(cardInfo); + setLastToken(cardInfo.getCardPtr()); } } @@ -1925,7 +1925,7 @@ void Player::actCreateAllRelatedCards() return; } - auto relatedCards = sourceCard->getInfo()->getAllRelatedCards(); + auto relatedCards = sourceCard->getCardInfo().getAllRelatedCards(); if (relatedCards.isEmpty()) { return; } @@ -2259,9 +2259,9 @@ void Player::eventCreateToken(const Event_CreateToken &event) if (!QString::fromStdString(event.pt()).isEmpty()) { card->setPT(QString::fromStdString(event.pt())); } else if (!event.face_down()) { - CardInfoPtr dbCard = card->getInfo(); + ExactCard dbCard = card->getCard(); if (dbCard) { - card->setPT(dbCard->getPowTough()); + card->setPT(dbCard.getInfo().getPowTough()); } } card->setColor(QString::fromStdString(event.color())); @@ -2895,12 +2895,14 @@ void Player::playCard(CardItem *card, bool faceDown) CardToMove *cardToMove = cmd.mutable_cards_to_move()->add_card(); cardToMove->set_card_id(card->getId()); - CardInfoPtr info = card->getInfo(); - if (!info) { + ExactCard exactCard = card->getCard(); + if (!exactCard) { return; } - int tableRow = info->getTableRow(); + const CardInfo &info = exactCard.getInfo(); + + int tableRow = info.getTableRow(); bool playToStack = SettingsCache::instance().getPlayToStack(); QString currentZone = card->getZone()->getName(); if (currentZone == "stack" && tableRow == 3) { @@ -2913,13 +2915,13 @@ void Player::playCard(CardItem *card, bool faceDown) cmd.set_x(-1); cmd.set_y(0); } else { - tableRow = faceDown ? 2 : info->getTableRow(); + tableRow = faceDown ? 2 : info.getTableRow(); QPoint gridPoint = QPoint(-1, TableZone::clampValidTableRow(2 - tableRow)); cardToMove->set_face_down(faceDown); if (!faceDown) { - cardToMove->set_pt(info->getPowTough().toStdString()); + cardToMove->set_pt(info.getPowTough().toStdString()); } - cardToMove->set_tapped(!faceDown && info->getCipt()); + cardToMove->set_tapped(!faceDown && info.getCipt()); if (tableRow != 3) cmd.set_target_zone("table"); cmd.set_x(gridPoint.x()); @@ -2945,12 +2947,14 @@ void Player::playCardToTable(const CardItem *card, bool faceDown) CardToMove *cardToMove = cmd.mutable_cards_to_move()->add_card(); cardToMove->set_card_id(card->getId()); - CardInfoPtr info = card->getInfo(); - if (!info) { + ExactCard exactCard = card->getCard(); + if (!exactCard) { return; } - int tableRow = faceDown ? 2 : info->getTableRow(); + const CardInfo &info = exactCard.getInfo(); + + int tableRow = faceDown ? 2 : info.getTableRow(); // default instant/sorcery cards to the noncreatures row if (tableRow > 2) { tableRow = 1; @@ -2959,9 +2963,9 @@ void Player::playCardToTable(const CardItem *card, bool faceDown) QPoint gridPoint = QPoint(-1, TableZone::clampValidTableRow(2 - tableRow)); cardToMove->set_face_down(faceDown); if (!faceDown) { - cardToMove->set_pt(info->getPowTough().toStdString()); + cardToMove->set_pt(info.getPowTough().toStdString()); } - cardToMove->set_tapped(!faceDown && info->getCipt()); + cardToMove->set_tapped(!faceDown && info.getCipt()); cmd.set_target_zone("table"); cmd.set_x(gridPoint.x()); cmd.set_y(gridPoint.y()); @@ -3280,9 +3284,9 @@ void Player::cardMenuAction() cmd->set_card_id(card->getId()); cmd->set_face_down(!card->getFaceDown()); if (card->getFaceDown()) { - CardInfoPtr ci = card->getInfo(); - if (ci) { - cmd->set_pt(ci->getPowTough().toStdString()); + ExactCard ec = card->getCard(); + if (ec) { + cmd->set_pt(ec.getInfo().getPowTough().toStdString()); } } commandList.append(cmd); @@ -3468,9 +3472,9 @@ void Player::actResetPT() auto *card = static_cast(item); QString ptString; if (!card->getFaceDown()) { // leave the pt empty if the card is face down - CardInfoPtr info = card->getInfo(); - if (info) { - ptString = info->getPowTough(); + ExactCard ec = card->getCard(); + if (ec) { + ptString = ec.getInfo().getPowTough(); } } if (ptString == card->getPT()) { @@ -4077,13 +4081,13 @@ void Player::addRelatedCardView(const CardItem *card, QMenu *cardMenu) if (!card || !cardMenu) { return; } - auto cardInfo = card->getInfo(); - if (!cardInfo) { + auto exactCard = card->getCard(); + if (!exactCard) { return; } bool atLeastOneGoodRelationFound = false; - QList relatedCards = cardInfo->getAllRelatedCards(); + QList relatedCards = exactCard.getInfo().getAllRelatedCards(); for (const CardRelation *cardRelation : relatedCards) { CardInfoPtr relatedCard = CardDatabaseManager::getInstance()->getCardInfo(cardRelation->getName()); if (relatedCard != nullptr) { @@ -4096,17 +4100,14 @@ void Player::addRelatedCardView(const CardItem *card, QMenu *cardMenu) return; } - const auto ¤tCardSet = CardDatabase::getSetInfoForCard(cardInfo); - cardMenu->addSeparator(); auto viewRelatedCards = new QMenu(tr("View related cards")); cardMenu->addMenu(viewRelatedCards); for (const CardRelation *relatedCard : relatedCards) { QString relatedCardName = relatedCard->getName(); + CardRef cardRef = {relatedCardName, exactCard.getPrinting().getUuid()}; QAction *viewCard = viewRelatedCards->addAction(relatedCardName); - connect(viewCard, &QAction::triggered, game, [this, relatedCardName, currentCardSet] { - game->viewCardInfo({relatedCardName, currentCardSet.getUuid()}); - }); + connect(viewCard, &QAction::triggered, game, [this, cardRef] { game->viewCardInfo(cardRef); }); } } @@ -4115,36 +4116,34 @@ void Player::addRelatedCardActions(const CardItem *card, QMenu *cardMenu) if (!card || !cardMenu) { return; } - auto cardInfo = card->getInfo(); - if (!cardInfo) { + auto exactCard = card->getCard(); + if (!exactCard) { return; } - QList relatedCards = cardInfo->getAllRelatedCards(); + QList relatedCards = exactCard.getInfo().getAllRelatedCards(); if (relatedCards.isEmpty()) { return; } - const auto ¤tCardSet = CardDatabase::getSetInfoForCard(cardInfo); - cardMenu->addSeparator(); int index = 0; QAction *createRelatedCards = nullptr; for (const CardRelation *cardRelation : relatedCards) { - CardInfoPtr relatedCard = - CardDatabaseManager::getInstance()->getCard({cardRelation->getName(), currentCardSet.getUuid()}); - if (relatedCard == nullptr) { - relatedCard = CardDatabaseManager::getInstance()->getCardInfo(cardRelation->getName()); + ExactCard relatedCard = + CardDatabaseManager::getInstance()->getCard({cardRelation->getName(), exactCard.getPrinting().getUuid()}); + if (!relatedCard) { + relatedCard = CardDatabaseManager::getInstance()->getCard({cardRelation->getName()}); } - if (relatedCard == nullptr) { + if (!relatedCard) { continue; } QString relatedCardName; - if (relatedCard->getPowTough().size() > 0) { - relatedCardName = relatedCard->getPowTough() + " " + relatedCard->getName(); // "n/n name" + if (relatedCard.getInfo().getPowTough().size() > 0) { + relatedCardName = relatedCard.getInfo().getPowTough() + " " + relatedCard.getName(); // "n/n name" } else { - relatedCardName = relatedCard->getName(); // "name" + relatedCardName = relatedCard.getName(); // "name" } QString text = tr("Token: "); diff --git a/cockatrice/src/game/zones/table_zone.cpp b/cockatrice/src/game/zones/table_zone.cpp index cee782560..a42bcdb18 100644 --- a/cockatrice/src/game/zones/table_zone.cpp +++ b/cockatrice/src/game/zones/table_zone.cpp @@ -140,9 +140,9 @@ void TableZone::handleDropEventByGrid(const QList &dragItems, ctm->set_card_id(item->getId()); ctm->set_face_down(item->getFaceDown()); if (startZone->getName() != name && !item->getFaceDown()) { - const auto &info = item->getItem()->getInfo(); - if (info) { - ctm->set_pt(info->getPowTough().toStdString()); + const auto &card = item->getItem()->getCard(); + if (card) { + ctm->set_pt(card.getInfo().getPowTough().toStdString()); } } } diff --git a/cockatrice/src/game/zones/view_zone.cpp b/cockatrice/src/game/zones/view_zone.cpp index 90361b7d8..213b60f2c 100644 --- a/cockatrice/src/game/zones/view_zone.cpp +++ b/cockatrice/src/game/zones/view_zone.cpp @@ -152,7 +152,7 @@ void ZoneViewZone::reorganizeCards() // filter cards CardList cardsToDisplay = CardList(cards.getContentsKnown()); for (auto card : cards) { - if (filterString.check(card->getInfo())) { + if (filterString.check(card->getCard().getCardPtr())) { card->show(); cardsToDisplay.append(card); } else { diff --git a/dbconverter/CMakeLists.txt b/dbconverter/CMakeLists.txt index a51a6d734..a2ce75a31 100644 --- a/dbconverter/CMakeLists.txt +++ b/dbconverter/CMakeLists.txt @@ -10,6 +10,7 @@ set(dbconverter_SOURCES ../cockatrice/src/game/cards/card_database_parser/cockatrice_xml_3.cpp ../cockatrice/src/game/cards/card_database_parser/cockatrice_xml_4.cpp ../cockatrice/src/game/cards/card_info.cpp + ../cockatrice/src/game/cards/exact_card.cpp ../cockatrice/src/settings/settings_manager.cpp ${VERSION_STRING_CPP} ) diff --git a/oracle/CMakeLists.txt b/oracle/CMakeLists.txt index 79d2ae45a..5a76f3274 100644 --- a/oracle/CMakeLists.txt +++ b/oracle/CMakeLists.txt @@ -17,16 +17,7 @@ set(oracle_SOURCES src/pagetemplates.cpp src/parsehelpers.cpp src/qt-json/json.cpp - ../cockatrice/src/game/cards/card_database.cpp - ../cockatrice/src/game/cards/card_database_manager.cpp ../cockatrice/src/game/cards/card_info.cpp - ../cockatrice/src/client/ui/picture_loader/picture_loader.cpp - ../cockatrice/src/client/ui/picture_loader/picture_loader_local.cpp - ../cockatrice/src/client/ui/picture_loader/picture_loader_request_status_display_widget.cpp - ../cockatrice/src/client/ui/picture_loader/picture_loader_status_bar.cpp - ../cockatrice/src/client/ui/picture_loader/picture_loader_worker.cpp - ../cockatrice/src/client/ui/picture_loader/picture_loader_worker_work.cpp - ../cockatrice/src/client/ui/picture_loader/picture_to_load.cpp ../cockatrice/src/client/ui/widgets/quick_settings/settings_button_widget.cpp ../cockatrice/src/client/ui/widgets/quick_settings/settings_popup_widget.cpp ../cockatrice/src/game/cards/card_database_parser/card_database_parser.cpp diff --git a/tests/carddatabase/CMakeLists.txt b/tests/carddatabase/CMakeLists.txt index 1f9139ff6..4b82e2fb6 100644 --- a/tests/carddatabase/CMakeLists.txt +++ b/tests/carddatabase/CMakeLists.txt @@ -23,6 +23,7 @@ add_executable( ../../cockatrice/src/game/cards/card_database_parser/cockatrice_xml_3.cpp ../../cockatrice/src/game/cards/card_database_parser/cockatrice_xml_4.cpp ../../cockatrice/src/game/cards/card_info.cpp + ../../cockatrice/src/game/cards/exact_card.cpp ../../cockatrice/src/settings/settings_manager.cpp carddatabase_test.cpp mocks.cpp @@ -37,6 +38,7 @@ add_executable( ../../cockatrice/src/game/cards/card_database_parser/cockatrice_xml_3.cpp ../../cockatrice/src/game/cards/card_database_parser/cockatrice_xml_4.cpp ../../cockatrice/src/game/cards/card_info.cpp + ../../cockatrice/src/game/cards/exact_card.cpp ../../cockatrice/src/game/filters/filter_card.cpp ../../cockatrice/src/game/filters/filter_string.cpp ../../cockatrice/src/game/filters/filter_tree.cpp