Visual deck storage v2 (#5427)

* Restore some button states (ready/sideboard locked) to sensible defaults when unloading a deck.

* Update last loaded timestamp in decklist file and then restore original last modified timestamp if a user requests a deck load.

* Add some todos.

* Loading a deck from local file dialog should swap out scenes, enable unload button.

* Lint.

* Shuffle some classes and signals around.

* More sort options, sort widgets directly.

* Banner cards should respect providerIds.

* Properly updateSortOrder on load.

* Add the color identity to the Deck Preview Widget.

* Properly set sort indices.

* Change replace visualDeckStorageWidget with deckView to be in deckSelectFinished so that it also works on remote deck load.

* Include settings for unused color identities display.

* Change opacity scaling.

* Overload for Qt.

* Lint.

* Lint.

* Include QMouseEvent

* Template because MacOs.

* Include a quick filter for color identities.

* Include a quick filter for color identities.

* Save some space.

* Refactor DeckPreviewWidgets to reside in their own folder.

* Add Deck Loader logging category.

* Introduce a tagging system.

* Add some more default tags.

* Even more default tags.

* Lint.

* Lint a comma.

* Remove extra set of braces.

* Lint some stuff.

* Refresh banner cards when tags are added.

* Lint.

* Wrestle with Qt Checkboxes.

* Lint.

* Adjust some sizes, relayout.

* Address comments.

* Lint.

* Reorder kindred types.

* Add a search bar for tags.

* Remove close button (for now) and change "Add tags ..." to "Edit tags ..."

* Retranslate window title for Deck Tag Manager Dialog.

* Style tag addition widget to be consistent.

* Lint.

* Override paintEvent.

* Override sizeHint

---------

Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
This commit is contained in:
BruebachL 2025-01-12 23:46:22 +01:00 committed by GitHub
parent 9bd024d39f
commit dd8ac14f99
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
46 changed files with 1899 additions and 153 deletions

View file

@ -823,7 +823,7 @@ void TabDeckEditor::updateBannerCardComboBox()
bannerCardComboBox->clear();
// Prepare the new items with deduplication
QSet<QString> bannerCardSet;
QSet<QPair<QString, QString>> bannerCardSet;
InnerDecklistNode *listRoot = deckModel->getDeckList()->getRoot();
for (int i = 0; i < listRoot->size(); i++) {
InnerDecklistNode *currentZone = dynamic_cast<InnerDecklistNode *>(listRoot->at(i));
@ -833,23 +833,30 @@ void TabDeckEditor::updateBannerCardComboBox()
continue;
for (int k = 0; k < currentCard->getNumber(); ++k) {
CardInfoPtr info = CardDatabaseManager::getInstance()->getCard(currentCard->getName());
CardInfoPtr info = CardDatabaseManager::getInstance()->getCardByNameAndProviderId(
currentCard->getName(), currentCard->getCardProviderId());
if (info) {
bannerCardSet.insert(currentCard->getName());
bannerCardSet.insert(
QPair<QString, QString>(currentCard->getName(), currentCard->getCardProviderId()));
}
}
}
}
// Convert the QSet to a sorted QStringList
QStringList bannerCardChoices;
for (const QString &entry : bannerCardSet) {
bannerCardChoices.append(entry);
}
bannerCardChoices.sort(Qt::CaseInsensitive);
QList<QPair<QString, QString>> pairList = bannerCardSet.values();
// Populate the combo box with new items
bannerCardComboBox->addItems(bannerCardChoices);
// Sort QList by the first() element of the QPair
std::sort(pairList.begin(), pairList.end(), [](const QPair<QString, QString> &a, const QPair<QString, QString> &b) {
return a.first.toLower() < b.first.toLower();
});
for (const auto &pair : pairList) {
QVariantMap dataMap;
dataMap["name"] = pair.first;
dataMap["uuid"] = pair.second;
bannerCardComboBox->addItem(pair.first, dataMap);
}
// Try to restore the previous selection by finding the currentText
int restoredIndex = bannerCardComboBox->findText(currentText);
@ -857,7 +864,7 @@ void TabDeckEditor::updateBannerCardComboBox()
bannerCardComboBox->setCurrentIndex(restoredIndex);
} else {
// Add a placeholder "-" and set it as the current selection
int bannerIndex = bannerCardComboBox->findText(deckModel->getDeckList()->getBannerCard());
int bannerIndex = bannerCardComboBox->findText(deckModel->getDeckList()->getBannerCard().first);
if (bannerIndex != -1) {
bannerCardComboBox->setCurrentIndex(bannerIndex);
} else {
@ -872,8 +879,8 @@ void TabDeckEditor::updateBannerCardComboBox()
void TabDeckEditor::setBannerCard(int /* changedIndex */)
{
qDebug() << "Banner card was set to: " << bannerCardComboBox->currentText();
deckModel->getDeckList()->setBannerCard(bannerCardComboBox->currentText());
QVariantMap data = bannerCardComboBox->itemData(bannerCardComboBox->currentIndex()).toMap();
deckModel->getDeckList()->setBannerCard(QPair<QString, QString>(data["name"].toString(), data["uuid"].toString()));
}
void TabDeckEditor::updateCardInfo(CardInfoPtr _card)
@ -1043,11 +1050,11 @@ void TabDeckEditor::openDeckFromFile(const QString &fileName, DeckOpenLocation d
DeckLoader::FileFormat fmt = DeckLoader::getFormatFromName(fileName);
auto *l = new DeckLoader;
if (l->loadFromFile(fileName, fmt)) {
if (l->loadFromFile(fileName, fmt, true)) {
SettingsCache::instance().recents().updateRecentlyOpenedDeckPaths(fileName);
updateBannerCardComboBox();
if (!l->getBannerCard().isEmpty()) {
bannerCardComboBox->setCurrentIndex(bannerCardComboBox->findText(l->getBannerCard()));
if (!l->getBannerCard().first.isEmpty()) {
bannerCardComboBox->setCurrentIndex(bannerCardComboBox->findText(l->getBannerCard().first));
}
if (deckOpenLocation == NEW_TAB) {
emit openDeckEditor(l);
@ -1542,13 +1549,13 @@ void TabDeckEditor::actDecrement()
void TabDeckEditor::setDeck(DeckLoader *_deck)
{
qDebug() << " ORIGINAL BANNER CARD " << _deck->getBannerCard();
qDebug() << " ORIGINAL BANNER CARD " << _deck->getBannerCard().first;
deckModel->setDeckList(_deck);
nameEdit->setText(deckModel->getDeckList()->getName());
commentsEdit->setText(deckModel->getDeckList()->getComments());
qDebug() << deckModel->getDeckList()->getBannerCard() << " was the banner card";
bannerCardComboBox->setCurrentText(deckModel->getDeckList()->getBannerCard());
bannerCardComboBox->setCurrentText(deckModel->getDeckList()->getBannerCard().first);
updateBannerCardComboBox();
updateHash();
deckModel->sort(deckView->header()->sortIndicatorSection(), deckView->header()->sortIndicatorOrder());

View file

@ -203,7 +203,7 @@ void TabDeckStorage::actOpenLocalDeck()
QString filePath = localDirModel->filePath(curLeft);
DeckLoader deckLoader;
if (!deckLoader.loadFromFile(filePath, DeckLoader::CockatriceFormat))
if (!deckLoader.loadFromFile(filePath, DeckLoader::CockatriceFormat, true))
continue;
SettingsCache::instance().recents().updateRecentlyOpenedDeckPaths(filePath);

View file

@ -145,7 +145,7 @@ DeckViewContainer::DeckViewContainer(int _playerId, TabGame *parent)
deckView->setVisible(false);
visualDeckStorageWidget = new VisualDeckStorageWidget(this);
connect(visualDeckStorageWidget, &VisualDeckStorageWidget::imageDoubleClicked, this,
connect(visualDeckStorageWidget, &VisualDeckStorageWidget::deckPreviewDoubleClicked, this,
&DeckViewContainer::replaceDeckStorageWithDeckView);
deckViewLayout = new QVBoxLayout;
@ -299,20 +299,12 @@ void TabGame::refreshShortcuts()
}
}
void DeckViewContainer::replaceDeckStorageWithDeckView(QMouseEvent *event, DeckPreviewCardPictureWidget *instance)
void DeckViewContainer::replaceDeckStorageWithDeckView(QMouseEvent *event, DeckPreviewWidget *instance)
{
Q_UNUSED(event);
QString fileName = instance->filePath;
DeckLoader::FileFormat fmt = DeckLoader::getFormatFromName(fileName);
QString deckString;
DeckLoader deck;
QString deckString = instance->deckLoader->writeToString_Native();
bool error = !deck.loadFromFile(fileName, fmt);
if (!error) {
deckString = deck.writeToString_Native();
error = deckString.length() > MAX_FILE_LENGTH;
}
if (error) {
if (deckString.length() > MAX_FILE_LENGTH) {
QMessageBox::critical(this, tr("Error"), tr("The selected file could not be loaded."));
return;
}
@ -335,6 +327,11 @@ void DeckViewContainer::unloadDeck()
visualDeckStorageWidget->setVisible(true);
deckViewLayout->update();
unloadDeckButton->setEnabled(false);
readyStartButton->setEnabled(false);
readyStartButton->setState(false);
sideboardLockButton->setEnabled(false);
sideboardLockButton->setState(false);
setReadyStart(false);
}
void DeckViewContainer::loadLocalDeck()
@ -352,7 +349,7 @@ void DeckViewContainer::loadDeckFromFile(const QString &filePath)
QString deckString;
DeckLoader deck;
bool error = !deck.loadFromFile(filePath, fmt);
bool error = !deck.loadFromFile(filePath, fmt, true);
if (!error) {
deckString = deck.writeToString_Native();
error = deckString.length() > MAX_FILE_LENGTH;
@ -390,6 +387,9 @@ void DeckViewContainer::deckSelectFinished(const Response &r)
// TODO CHANGE THIS TO BE SELECTED BY UUID
PictureLoader::cacheCardPixmaps(CardDatabaseManager::getInstance()->getCards(newDeck.getCardList()));
setDeck(newDeck);
deckView->setVisible(true);
visualDeckStorageWidget->setVisible(false);
unloadDeckButton->setEnabled(true);
}
void DeckViewContainer::readyStart()

View file

@ -95,7 +95,7 @@ private:
TabGame *parentGame;
int playerId;
private slots:
void replaceDeckStorageWithDeckView(QMouseEvent *event, DeckPreviewCardPictureWidget *instance);
void replaceDeckStorageWithDeckView(QMouseEvent *event, DeckPreviewWidget *instance);
void loadLocalDeck();
void loadRemoteDeck();
void unloadDeck();

View file

@ -49,7 +49,7 @@ TabDeckStorageVisual::TabDeckStorageVisual(TabSupervisor *_tabSupervisor, Abstra
leftToolBar->addAction(aDeleteLocalDeck);
visualDeckStorageWidget = new VisualDeckStorageWidget(this);
connect(visualDeckStorageWidget, &VisualDeckStorageWidget::imageDoubleClicked, this,
connect(visualDeckStorageWidget, &VisualDeckStorageWidget::deckPreviewDoubleClicked, this,
&TabDeckStorageVisual::actOpenLocalDeck);
// layout->addWidget(leftToolBar);
@ -74,11 +74,11 @@ QString TabDeckStorageVisual::getTargetPath() const
return {};
}
void TabDeckStorageVisual::actOpenLocalDeck(QMouseEvent *event, DeckPreviewCardPictureWidget *instance)
void TabDeckStorageVisual::actOpenLocalDeck(QMouseEvent *event, DeckPreviewWidget *instance)
{
(void)event;
DeckLoader deckLoader;
if (!deckLoader.loadFromFile(instance->filePath, DeckLoader::CockatriceFormat))
if (!deckLoader.loadFromFile(instance->filePath, DeckLoader::CockatriceFormat, true))
return;
emit openDeckEditor(&deckLoader);

View file

@ -33,8 +33,8 @@ public:
}
public slots:
void cardUpdateFinished(int exitCode, QProcess::ExitStatus exitStatus);
void closeRequest(bool forced = false) override;
void actOpenLocalDeck(QMouseEvent *event, DeckPreviewCardPictureWidget *instance);
void closeRequest(bool forced) override;
void actOpenLocalDeck(QMouseEvent *event, DeckPreviewWidget *instance);
void actDeleteLocalDeck();
signals:
void openDeckEditor(const DeckLoader *deckLoader);