mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-06-30 10:33:54 -07:00
New visual deck storage (#5290)
* Add TabDeckStorageVisual * Visual Deck Storage * Add BannerCard to .cod format, use it in the visual deck storage widget. * Show filename instead of deckname if deck name is empty. * Lint. * Don't delint cmake list through hooks. * Add deck loading functionality. * Open Decks on double click, not single click. * Void event for now. * Fix build issue with overload? * Fix build issue with overload? * Include QDebug. * Turn the tab into a widget. * Move the signals down to the widget, move the connections and slots up to the parent widgets. * No banner card equals an empty CardInfoPtr. * Add an option to sort by filename or last modified. * Flip last modified comparison. * Lint. * Don't open decks twice in the storage tab. * Fix unload deck not working by showing/hiding widgets instead of adding/removing to layout. * Add a search bar. * Add a card size slider. * Lint. * Lint. * Lint. * Fix settings mocks. * No need to QDebug. * No need to QDebug. * Member variable. * Member variable. * Non-lambda. * Change set to list conversion. * Specify overload. * Include MouseEvent * Adjust font size dynamically. * Add an option to show the visual deck storage on database load. * Fix the close button not working on the tab, add an option to launch the visual deck storage tab to Cockatrice menu. * Override virtual functions. * Correct tab text. * Add a setting to remember last used sorting order for visual deck storage widget. * Update banner card combo box correctly. * Fix mocks. --------- Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de> Co-authored-by: Zach H <zahalpern+github@gmail.com>
This commit is contained in:
parent
7496e79e8c
commit
62f7c7f9ce
30 changed files with 834 additions and 31 deletions
|
|
@ -160,6 +160,10 @@ set(cockatrice_SOURCES
|
||||||
src/client/ui/window_main.cpp
|
src/client/ui/window_main.cpp
|
||||||
src/game/zones/view_zone_widget.cpp
|
src/game/zones/view_zone_widget.cpp
|
||||||
src/game/zones/view_zone.cpp
|
src/game/zones/view_zone.cpp
|
||||||
|
src/client/tabs/visual_deck_storage/tab_deck_storage_visual.cpp
|
||||||
|
src/client/ui/widgets/cards/deck_preview_card_picture_widget.cpp
|
||||||
|
src/client/ui/widgets/visual_deck_storage/visual_deck_storage_widget.cpp
|
||||||
|
src/client/ui/widgets/visual_deck_storage/visual_deck_storage_search_widget.cpp
|
||||||
${VERSION_STRING_CPP}
|
${VERSION_STRING_CPP}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,8 @@
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QClipboard>
|
#include <QClipboard>
|
||||||
#include <QCloseEvent>
|
#include <QCloseEvent>
|
||||||
|
#include <QComboBox>
|
||||||
|
#include <QDebug>
|
||||||
#include <QDesktopServices>
|
#include <QDesktopServices>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QDockWidget>
|
#include <QDockWidget>
|
||||||
|
|
@ -95,6 +97,16 @@ void TabDeckEditor::createDeckDock()
|
||||||
commentsEdit->setObjectName("commentsEdit");
|
commentsEdit->setObjectName("commentsEdit");
|
||||||
commentsLabel->setBuddy(commentsEdit);
|
commentsLabel->setBuddy(commentsEdit);
|
||||||
connect(commentsEdit, SIGNAL(textChanged()), this, SLOT(updateComments()));
|
connect(commentsEdit, SIGNAL(textChanged()), this, SLOT(updateComments()));
|
||||||
|
bannerCardLabel = new QLabel();
|
||||||
|
bannerCardLabel->setObjectName("bannerCardLabel");
|
||||||
|
bannerCardLabel->setText(tr("Banner Card"));
|
||||||
|
bannerCardComboBox = new QComboBox(this);
|
||||||
|
connect(deckModel, &DeckListModel::dataChanged, this, [this]() {
|
||||||
|
// Delay the update to avoid race conditions
|
||||||
|
QTimer::singleShot(100, this, &TabDeckEditor::updateBannerCardComboBox);
|
||||||
|
});
|
||||||
|
connect(bannerCardComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
|
||||||
|
&TabDeckEditor::setBannerCard);
|
||||||
|
|
||||||
aIncrement = new QAction(QString(), this);
|
aIncrement = new QAction(QString(), this);
|
||||||
aIncrement->setIcon(QPixmap("theme:icons/increment"));
|
aIncrement->setIcon(QPixmap("theme:icons/increment"));
|
||||||
|
|
@ -128,6 +140,9 @@ void TabDeckEditor::createDeckDock()
|
||||||
upperLayout->addWidget(commentsLabel, 1, 0);
|
upperLayout->addWidget(commentsLabel, 1, 0);
|
||||||
upperLayout->addWidget(commentsEdit, 1, 1);
|
upperLayout->addWidget(commentsEdit, 1, 1);
|
||||||
|
|
||||||
|
upperLayout->addWidget(bannerCardLabel, 2, 0);
|
||||||
|
upperLayout->addWidget(bannerCardComboBox, 2, 1);
|
||||||
|
|
||||||
hashLabel1 = new QLabel();
|
hashLabel1 = new QLabel();
|
||||||
hashLabel1->setObjectName("hashLabel1");
|
hashLabel1->setObjectName("hashLabel1");
|
||||||
auto *hashSizePolicy = new QSizePolicy();
|
auto *hashSizePolicy = new QSizePolicy();
|
||||||
|
|
@ -802,6 +817,71 @@ void TabDeckEditor::updateComments()
|
||||||
setSaveStatus(true);
|
setSaveStatus(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TabDeckEditor::updateBannerCardComboBox()
|
||||||
|
{
|
||||||
|
// Store the current text of the combo box
|
||||||
|
QString currentText = bannerCardComboBox->currentText();
|
||||||
|
|
||||||
|
// Block signals temporarily
|
||||||
|
bool wasBlocked = bannerCardComboBox->blockSignals(true);
|
||||||
|
|
||||||
|
// Clear the existing items in the combo box
|
||||||
|
bannerCardComboBox->clear();
|
||||||
|
|
||||||
|
// Prepare the new items with deduplication
|
||||||
|
QSet<QString> bannerCardSet;
|
||||||
|
InnerDecklistNode *listRoot = deckModel->getDeckList()->getRoot();
|
||||||
|
for (int i = 0; i < listRoot->size(); i++) {
|
||||||
|
InnerDecklistNode *currentZone = dynamic_cast<InnerDecklistNode *>(listRoot->at(i));
|
||||||
|
for (int j = 0; j < currentZone->size(); j++) {
|
||||||
|
DecklistCardNode *currentCard = dynamic_cast<DecklistCardNode *>(currentZone->at(j));
|
||||||
|
if (!currentCard)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (int k = 0; k < currentCard->getNumber(); ++k) {
|
||||||
|
CardInfoPtr info = CardDatabaseManager::getInstance()->getCard(currentCard->getName());
|
||||||
|
if (info) {
|
||||||
|
bannerCardSet.insert(currentCard->getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert the QSet to a sorted QStringList
|
||||||
|
QStringList bannerCardChoices;
|
||||||
|
for (const QString &entry : bannerCardSet) {
|
||||||
|
bannerCardChoices.append(entry);
|
||||||
|
}
|
||||||
|
bannerCardChoices.sort(Qt::CaseInsensitive);
|
||||||
|
|
||||||
|
// Populate the combo box with new items
|
||||||
|
bannerCardComboBox->addItems(bannerCardChoices);
|
||||||
|
|
||||||
|
// Try to restore the previous selection by finding the currentText
|
||||||
|
int restoredIndex = bannerCardComboBox->findText(currentText);
|
||||||
|
if (restoredIndex != -1) {
|
||||||
|
bannerCardComboBox->setCurrentIndex(restoredIndex);
|
||||||
|
} else {
|
||||||
|
// Add a placeholder "-" and set it as the current selection
|
||||||
|
int bannerIndex = bannerCardComboBox->findText(deckModel->getDeckList()->getBannerCard());
|
||||||
|
if (bannerIndex != -1) {
|
||||||
|
bannerCardComboBox->setCurrentIndex(bannerIndex);
|
||||||
|
} else {
|
||||||
|
bannerCardComboBox->insertItem(0, "-");
|
||||||
|
bannerCardComboBox->setCurrentIndex(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restore the previous signal blocking state
|
||||||
|
bannerCardComboBox->blockSignals(wasBlocked);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TabDeckEditor::setBannerCard(int /* changedIndex */)
|
||||||
|
{
|
||||||
|
qDebug() << "Banner card was set to: " << bannerCardComboBox->currentText();
|
||||||
|
deckModel->getDeckList()->setBannerCard(bannerCardComboBox->currentText());
|
||||||
|
}
|
||||||
|
|
||||||
void TabDeckEditor::updateCardInfo(CardInfoPtr _card)
|
void TabDeckEditor::updateCardInfo(CardInfoPtr _card)
|
||||||
{
|
{
|
||||||
cardInfo->setCard(_card);
|
cardInfo->setCard(_card);
|
||||||
|
|
@ -941,6 +1021,7 @@ void TabDeckEditor::actLoadDeck()
|
||||||
|
|
||||||
QString fileName = dialog.selectedFiles().at(0);
|
QString fileName = dialog.selectedFiles().at(0);
|
||||||
openDeckFromFile(fileName, deckOpenLocation);
|
openDeckFromFile(fileName, deckOpenLocation);
|
||||||
|
updateBannerCardComboBox();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabDeckEditor::actOpenRecent(const QString &fileName)
|
void TabDeckEditor::actOpenRecent(const QString &fileName)
|
||||||
|
|
@ -966,6 +1047,10 @@ void TabDeckEditor::openDeckFromFile(const QString &fileName, DeckOpenLocation d
|
||||||
auto *l = new DeckLoader;
|
auto *l = new DeckLoader;
|
||||||
if (l->loadFromFile(fileName, fmt)) {
|
if (l->loadFromFile(fileName, fmt)) {
|
||||||
SettingsCache::instance().recents().updateRecentlyOpenedDeckPaths(fileName);
|
SettingsCache::instance().recents().updateRecentlyOpenedDeckPaths(fileName);
|
||||||
|
updateBannerCardComboBox();
|
||||||
|
if (!l->getBannerCard().isEmpty()) {
|
||||||
|
bannerCardComboBox->setCurrentIndex(bannerCardComboBox->findText(l->getBannerCard()));
|
||||||
|
}
|
||||||
if (deckOpenLocation == NEW_TAB) {
|
if (deckOpenLocation == NEW_TAB) {
|
||||||
emit openDeckEditor(l);
|
emit openDeckEditor(l);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1429,10 +1514,14 @@ void TabDeckEditor::actDecrement()
|
||||||
|
|
||||||
void TabDeckEditor::setDeck(DeckLoader *_deck)
|
void TabDeckEditor::setDeck(DeckLoader *_deck)
|
||||||
{
|
{
|
||||||
|
qDebug() << " ORIGINAL BANNER CARD " << _deck->getBannerCard();
|
||||||
deckModel->setDeckList(_deck);
|
deckModel->setDeckList(_deck);
|
||||||
|
|
||||||
nameEdit->setText(deckModel->getDeckList()->getName());
|
nameEdit->setText(deckModel->getDeckList()->getName());
|
||||||
commentsEdit->setText(deckModel->getDeckList()->getComments());
|
commentsEdit->setText(deckModel->getDeckList()->getComments());
|
||||||
|
qDebug() << deckModel->getDeckList()->getBannerCard() << " was the banner card";
|
||||||
|
bannerCardComboBox->setCurrentText(deckModel->getDeckList()->getBannerCard());
|
||||||
|
updateBannerCardComboBox();
|
||||||
updateHash();
|
updateHash();
|
||||||
deckModel->sort(deckView->header()->sortIndicatorSection(), deckView->header()->sortIndicatorOrder());
|
deckModel->sort(deckView->header()->sortIndicatorSection(), deckView->header()->sortIndicatorOrder());
|
||||||
deckView->expandAll();
|
deckView->expandAll();
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ class DeckLoader;
|
||||||
class Response;
|
class Response;
|
||||||
class FilterTreeModel;
|
class FilterTreeModel;
|
||||||
class FilterBuilder;
|
class FilterBuilder;
|
||||||
|
class QComboBox;
|
||||||
class QGroupBox;
|
class QGroupBox;
|
||||||
class QMessageBox;
|
class QMessageBox;
|
||||||
class QHBoxLayout;
|
class QHBoxLayout;
|
||||||
|
|
@ -35,6 +36,8 @@ class TabDeckEditor : public Tab
|
||||||
private slots:
|
private slots:
|
||||||
void updateName(const QString &name);
|
void updateName(const QString &name);
|
||||||
void updateComments();
|
void updateComments();
|
||||||
|
void updateBannerCardComboBox();
|
||||||
|
void setBannerCard(int);
|
||||||
void updateHash();
|
void updateHash();
|
||||||
void updateCardInfoLeft(const QModelIndex ¤t, const QModelIndex &previous);
|
void updateCardInfoLeft(const QModelIndex ¤t, const QModelIndex &previous);
|
||||||
void updateCardInfoRight(const QModelIndex ¤t, const QModelIndex &previous);
|
void updateCardInfoRight(const QModelIndex ¤t, const QModelIndex &previous);
|
||||||
|
|
@ -129,6 +132,8 @@ private:
|
||||||
LineEditUnfocusable *nameEdit;
|
LineEditUnfocusable *nameEdit;
|
||||||
QLabel *commentsLabel;
|
QLabel *commentsLabel;
|
||||||
QTextEdit *commentsEdit;
|
QTextEdit *commentsEdit;
|
||||||
|
QLabel *bannerCardLabel;
|
||||||
|
QComboBox *bannerCardComboBox;
|
||||||
QLabel *hashLabel1;
|
QLabel *hashLabel1;
|
||||||
LineEditUnfocusable *hashLabel;
|
LineEditUnfocusable *hashLabel;
|
||||||
FilterTreeModel *filterModel;
|
FilterTreeModel *filterModel;
|
||||||
|
|
|
||||||
|
|
@ -105,6 +105,8 @@ DeckViewContainer::DeckViewContainer(int _playerId, TabGame *parent)
|
||||||
{
|
{
|
||||||
loadLocalButton = new QPushButton;
|
loadLocalButton = new QPushButton;
|
||||||
loadRemoteButton = new QPushButton;
|
loadRemoteButton = new QPushButton;
|
||||||
|
unloadDeckButton = new QPushButton;
|
||||||
|
unloadDeckButton->setEnabled(false);
|
||||||
readyStartButton = new ToggleButton;
|
readyStartButton = new ToggleButton;
|
||||||
readyStartButton->setEnabled(false);
|
readyStartButton->setEnabled(false);
|
||||||
forceStartGameButton = new QPushButton;
|
forceStartGameButton = new QPushButton;
|
||||||
|
|
@ -114,6 +116,7 @@ DeckViewContainer::DeckViewContainer(int _playerId, TabGame *parent)
|
||||||
|
|
||||||
connect(loadLocalButton, SIGNAL(clicked()), this, SLOT(loadLocalDeck()));
|
connect(loadLocalButton, SIGNAL(clicked()), this, SLOT(loadLocalDeck()));
|
||||||
connect(readyStartButton, SIGNAL(clicked()), this, SLOT(readyStart()));
|
connect(readyStartButton, SIGNAL(clicked()), this, SLOT(readyStart()));
|
||||||
|
connect(unloadDeckButton, &QPushButton::clicked, this, &DeckViewContainer::unloadDeck);
|
||||||
connect(forceStartGameButton, &QPushButton::clicked, this, &DeckViewContainer::forceStart);
|
connect(forceStartGameButton, &QPushButton::clicked, this, &DeckViewContainer::forceStart);
|
||||||
connect(sideboardLockButton, SIGNAL(clicked()), this, SLOT(sideboardLockButtonClicked()));
|
connect(sideboardLockButton, SIGNAL(clicked()), this, SLOT(sideboardLockButtonClicked()));
|
||||||
connect(sideboardLockButton, SIGNAL(stateChanged()), this, SLOT(updateSideboardLockButtonText()));
|
connect(sideboardLockButton, SIGNAL(stateChanged()), this, SLOT(updateSideboardLockButtonText()));
|
||||||
|
|
@ -127,6 +130,7 @@ DeckViewContainer::DeckViewContainer(int _playerId, TabGame *parent)
|
||||||
auto *buttonHBox = new QHBoxLayout;
|
auto *buttonHBox = new QHBoxLayout;
|
||||||
buttonHBox->addWidget(loadLocalButton);
|
buttonHBox->addWidget(loadLocalButton);
|
||||||
buttonHBox->addWidget(loadRemoteButton);
|
buttonHBox->addWidget(loadRemoteButton);
|
||||||
|
buttonHBox->addWidget(unloadDeckButton);
|
||||||
buttonHBox->addWidget(readyStartButton);
|
buttonHBox->addWidget(readyStartButton);
|
||||||
buttonHBox->addWidget(sideboardLockButton);
|
buttonHBox->addWidget(sideboardLockButton);
|
||||||
if (forceStartGameButton->isEnabled()) {
|
if (forceStartGameButton->isEnabled()) {
|
||||||
|
|
@ -134,13 +138,20 @@ DeckViewContainer::DeckViewContainer(int _playerId, TabGame *parent)
|
||||||
}
|
}
|
||||||
buttonHBox->setContentsMargins(0, 0, 0, 0);
|
buttonHBox->setContentsMargins(0, 0, 0, 0);
|
||||||
buttonHBox->addStretch();
|
buttonHBox->addStretch();
|
||||||
|
|
||||||
deckView = new DeckView;
|
deckView = new DeckView;
|
||||||
connect(deckView, SIGNAL(newCardAdded(AbstractCardItem *)), this, SIGNAL(newCardAdded(AbstractCardItem *)));
|
connect(deckView, SIGNAL(newCardAdded(AbstractCardItem *)), this, SIGNAL(newCardAdded(AbstractCardItem *)));
|
||||||
connect(deckView, SIGNAL(sideboardPlanChanged()), this, SLOT(sideboardPlanChanged()));
|
connect(deckView, SIGNAL(sideboardPlanChanged()), this, SLOT(sideboardPlanChanged()));
|
||||||
|
deckView->setVisible(false);
|
||||||
|
|
||||||
auto *deckViewLayout = new QVBoxLayout;
|
visualDeckStorageWidget = new VisualDeckStorageWidget(this);
|
||||||
|
connect(visualDeckStorageWidget, &VisualDeckStorageWidget::imageDoubleClicked, this,
|
||||||
|
&DeckViewContainer::replaceDeckStorageWithDeckView);
|
||||||
|
|
||||||
|
deckViewLayout = new QVBoxLayout;
|
||||||
deckViewLayout->addLayout(buttonHBox);
|
deckViewLayout->addLayout(buttonHBox);
|
||||||
deckViewLayout->addWidget(deckView);
|
deckViewLayout->addWidget(deckView);
|
||||||
|
deckViewLayout->addWidget(visualDeckStorageWidget);
|
||||||
deckViewLayout->setContentsMargins(0, 0, 0, 0);
|
deckViewLayout->setContentsMargins(0, 0, 0, 0);
|
||||||
setLayout(deckViewLayout);
|
setLayout(deckViewLayout);
|
||||||
|
|
||||||
|
|
@ -153,6 +164,7 @@ void DeckViewContainer::retranslateUi()
|
||||||
{
|
{
|
||||||
loadLocalButton->setText(tr("Load deck..."));
|
loadLocalButton->setText(tr("Load deck..."));
|
||||||
loadRemoteButton->setText(tr("Load remote deck..."));
|
loadRemoteButton->setText(tr("Load remote deck..."));
|
||||||
|
unloadDeckButton->setText(tr("Unload deck..."));
|
||||||
readyStartButton->setText(tr("Ready to start"));
|
readyStartButton->setText(tr("Ready to start"));
|
||||||
forceStartGameButton->setText(tr("Force start"));
|
forceStartGameButton->setText(tr("Force start"));
|
||||||
updateSideboardLockButtonText();
|
updateSideboardLockButtonText();
|
||||||
|
|
@ -287,6 +299,44 @@ void TabGame::refreshShortcuts()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DeckViewContainer::replaceDeckStorageWithDeckView(QMouseEvent *event, DeckPreviewCardPictureWidget *instance)
|
||||||
|
{
|
||||||
|
Q_UNUSED(event);
|
||||||
|
QString fileName = instance->filePath;
|
||||||
|
DeckLoader::FileFormat fmt = DeckLoader::getFormatFromName(fileName);
|
||||||
|
QString deckString;
|
||||||
|
DeckLoader deck;
|
||||||
|
|
||||||
|
bool error = !deck.loadFromFile(fileName, fmt);
|
||||||
|
if (!error) {
|
||||||
|
deckString = deck.writeToString_Native();
|
||||||
|
error = deckString.length() > MAX_FILE_LENGTH;
|
||||||
|
}
|
||||||
|
if (error) {
|
||||||
|
QMessageBox::critical(this, tr("Error"), tr("The selected file could not be loaded."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Command_DeckSelect cmd;
|
||||||
|
cmd.set_deck(deckString.toStdString());
|
||||||
|
PendingCommand *pend = parentGame->prepareGameCommand(cmd);
|
||||||
|
connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this,
|
||||||
|
SLOT(deckSelectFinished(const Response &)));
|
||||||
|
parentGame->sendGameCommand(pend, playerId);
|
||||||
|
visualDeckStorageWidget->setVisible(false);
|
||||||
|
deckView->setVisible(true);
|
||||||
|
deckViewLayout->update();
|
||||||
|
unloadDeckButton->setEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeckViewContainer::unloadDeck()
|
||||||
|
{
|
||||||
|
deckView->setVisible(false);
|
||||||
|
visualDeckStorageWidget->setVisible(true);
|
||||||
|
deckViewLayout->update();
|
||||||
|
unloadDeckButton->setEnabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
void DeckViewContainer::loadLocalDeck()
|
void DeckViewContainer::loadLocalDeck()
|
||||||
{
|
{
|
||||||
DlgLoadDeck dialog(this);
|
DlgLoadDeck dialog(this);
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include "../../client/tearoff_menu.h"
|
#include "../../client/tearoff_menu.h"
|
||||||
#include "../../game/player/player.h"
|
#include "../../game/player/player.h"
|
||||||
|
#include "../ui/widgets/visual_deck_storage/visual_deck_storage_widget.h"
|
||||||
#include "pb/event_leave.pb.h"
|
#include "pb/event_leave.pb.h"
|
||||||
#include "pb/serverinfo_game.pb.h"
|
#include "pb/serverinfo_game.pb.h"
|
||||||
#include "tab.h"
|
#include "tab.h"
|
||||||
|
|
@ -86,14 +87,18 @@ class DeckViewContainer : public QWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
private:
|
private:
|
||||||
QPushButton *loadLocalButton, *loadRemoteButton, *forceStartGameButton;
|
QVBoxLayout *deckViewLayout;
|
||||||
|
QPushButton *loadLocalButton, *loadRemoteButton, *unloadDeckButton, *forceStartGameButton;
|
||||||
ToggleButton *readyStartButton, *sideboardLockButton;
|
ToggleButton *readyStartButton, *sideboardLockButton;
|
||||||
DeckView *deckView;
|
DeckView *deckView;
|
||||||
|
VisualDeckStorageWidget *visualDeckStorageWidget;
|
||||||
TabGame *parentGame;
|
TabGame *parentGame;
|
||||||
int playerId;
|
int playerId;
|
||||||
private slots:
|
private slots:
|
||||||
|
void replaceDeckStorageWithDeckView(QMouseEvent *event, DeckPreviewCardPictureWidget *instance);
|
||||||
void loadLocalDeck();
|
void loadLocalDeck();
|
||||||
void loadRemoteDeck();
|
void loadRemoteDeck();
|
||||||
|
void unloadDeck();
|
||||||
void readyStart();
|
void readyStart();
|
||||||
void forceStart();
|
void forceStart();
|
||||||
void deckSelectFinished(const Response &r);
|
void deckSelectFinished(const Response &r);
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@
|
||||||
#include "tab_replays.h"
|
#include "tab_replays.h"
|
||||||
#include "tab_room.h"
|
#include "tab_room.h"
|
||||||
#include "tab_server.h"
|
#include "tab_server.h"
|
||||||
|
#include "visual_deck_storage/tab_deck_storage_visual.h"
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
@ -504,6 +505,15 @@ TabDeckEditor *TabSupervisor::addDeckEditorTab(const DeckLoader *deckToOpen)
|
||||||
return tab;
|
return tab;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TabDeckStorageVisual *TabSupervisor::addVisualDeckStorageTab()
|
||||||
|
{
|
||||||
|
TabDeckStorageVisual *tab = new TabDeckStorageVisual(this, client);
|
||||||
|
int tabIndex = myAddTab(tab);
|
||||||
|
addCloseButtonToTab(tab, tabIndex);
|
||||||
|
setCurrentWidget(tab);
|
||||||
|
return tab;
|
||||||
|
}
|
||||||
|
|
||||||
void TabSupervisor::deckEditorClosed(TabDeckEditor *tab)
|
void TabSupervisor::deckEditorClosed(TabDeckEditor *tab)
|
||||||
{
|
{
|
||||||
if (tab == currentWidget())
|
if (tab == currentWidget())
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include "../../deck/deck_loader.h"
|
#include "../../deck/deck_loader.h"
|
||||||
#include "../../server/chat_view/user_list_proxy.h"
|
#include "../../server/chat_view/user_list_proxy.h"
|
||||||
|
#include "visual_deck_storage/tab_deck_storage_visual.h"
|
||||||
|
|
||||||
#include <QAbstractButton>
|
#include <QAbstractButton>
|
||||||
#include <QCommonStyle>
|
#include <QCommonStyle>
|
||||||
|
|
@ -130,6 +131,7 @@ signals:
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
TabDeckEditor *addDeckEditorTab(const DeckLoader *deckToOpen);
|
TabDeckEditor *addDeckEditorTab(const DeckLoader *deckToOpen);
|
||||||
|
TabDeckStorageVisual *addVisualDeckStorageTab();
|
||||||
void openReplay(GameReplay *replay);
|
void openReplay(GameReplay *replay);
|
||||||
void maximizeMainWindow();
|
void maximizeMainWindow();
|
||||||
private slots:
|
private slots:
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,104 @@
|
||||||
|
#include "tab_deck_storage_visual.h"
|
||||||
|
|
||||||
|
#include "../../../game/cards/card_database_model.h"
|
||||||
|
#include "../tab_supervisor.h"
|
||||||
|
#include "pb/command_deck_del.pb.h"
|
||||||
|
|
||||||
|
#include <QAction>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QDirIterator>
|
||||||
|
#include <QFileSystemModel>
|
||||||
|
#include <QHBoxLayout>
|
||||||
|
#include <QInputDialog>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QMouseEvent>
|
||||||
|
#include <QScreen>
|
||||||
|
#include <QToolBar>
|
||||||
|
#include <QTreeView>
|
||||||
|
|
||||||
|
class FlowLayout;
|
||||||
|
TabDeckStorageVisual::TabDeckStorageVisual(TabSupervisor *_tabSupervisor, AbstractClient *_client)
|
||||||
|
: Tab(_tabSupervisor), client(_client)
|
||||||
|
{
|
||||||
|
deck_list_model = new DeckListModel(this);
|
||||||
|
deck_list_model->setObjectName("visualDeckModel");
|
||||||
|
|
||||||
|
QWidget *container = new QWidget(this);
|
||||||
|
QVBoxLayout *layout = new QVBoxLayout(container);
|
||||||
|
container->setLayout(layout);
|
||||||
|
this->setCentralWidget(container);
|
||||||
|
|
||||||
|
leftToolBar = new QToolBar;
|
||||||
|
leftToolBar->setOrientation(Qt::Horizontal);
|
||||||
|
leftToolBar->setIconSize(QSize(32, 32));
|
||||||
|
QHBoxLayout *leftToolBarLayout = new QHBoxLayout(this);
|
||||||
|
leftToolBarLayout->addStretch();
|
||||||
|
leftToolBarLayout->addWidget(leftToolBar);
|
||||||
|
leftToolBarLayout->addStretch();
|
||||||
|
|
||||||
|
aOpenLocalDeck = new QAction(this);
|
||||||
|
aOpenLocalDeck->setIcon(QPixmap("theme:icons/pencil"));
|
||||||
|
connect(aOpenLocalDeck, SIGNAL(triggered()), this, SLOT(actOpenLocalDeck()));
|
||||||
|
aDeleteLocalDeck = new QAction(this);
|
||||||
|
aDeleteLocalDeck->setIcon(QPixmap("theme:icons/remove_row"));
|
||||||
|
connect(aDeleteLocalDeck, SIGNAL(triggered()), this, SLOT(actDeleteLocalDeck()));
|
||||||
|
|
||||||
|
connect(this, &TabDeckStorageVisual::openDeckEditor, tabSupervisor, &TabSupervisor::addDeckEditorTab);
|
||||||
|
|
||||||
|
leftToolBar->addAction(aOpenLocalDeck);
|
||||||
|
leftToolBar->addAction(aDeleteLocalDeck);
|
||||||
|
|
||||||
|
visualDeckStorageWidget = new VisualDeckStorageWidget(this);
|
||||||
|
connect(visualDeckStorageWidget, &VisualDeckStorageWidget::imageDoubleClicked, this,
|
||||||
|
&TabDeckStorageVisual::actOpenLocalDeck);
|
||||||
|
|
||||||
|
// layout->addWidget(leftToolBar);
|
||||||
|
layout->addWidget(visualDeckStorageWidget);
|
||||||
|
|
||||||
|
retranslateUi();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TabDeckStorageVisual::closeRequest()
|
||||||
|
{
|
||||||
|
this->close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TabDeckStorageVisual::retranslateUi()
|
||||||
|
{
|
||||||
|
aOpenLocalDeck->setText(tr("Open in deck editor"));
|
||||||
|
aDeleteLocalDeck->setText(tr("Delete"));
|
||||||
|
}
|
||||||
|
|
||||||
|
QString TabDeckStorageVisual::getTargetPath() const
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void TabDeckStorageVisual::actOpenLocalDeck(QMouseEvent *event, DeckPreviewCardPictureWidget *instance)
|
||||||
|
{
|
||||||
|
(void)event;
|
||||||
|
DeckLoader deckLoader;
|
||||||
|
if (!deckLoader.loadFromFile(instance->filePath, DeckLoader::CockatriceFormat))
|
||||||
|
return;
|
||||||
|
|
||||||
|
emit openDeckEditor(&deckLoader);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TabDeckStorageVisual::actDeleteLocalDeck()
|
||||||
|
{
|
||||||
|
QModelIndex curLeft = localDirView->selectionModel()->currentIndex();
|
||||||
|
if (localDirModel->isDir(curLeft))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (QMessageBox::warning(this, tr("Delete local file"),
|
||||||
|
tr("Are you sure you want to delete \"%1\"?").arg(localDirModel->fileName(curLeft)),
|
||||||
|
QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes)
|
||||||
|
return;
|
||||||
|
|
||||||
|
localDirModel->remove(curLeft);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TabDeckStorageVisual::cardUpdateFinished(int exitCode, QProcess::ExitStatus exitStatus)
|
||||||
|
{
|
||||||
|
qDebug() << "Card update process finished with exit code:" << exitCode << "and exit status:" << exitStatus;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
#ifndef TAB_DECK_STORAGE_VISUAL_H
|
||||||
|
#define TAB_DECK_STORAGE_VISUAL_H
|
||||||
|
|
||||||
|
#include "../../../deck/deck_list_model.h"
|
||||||
|
#include "../../../deck/deck_view.h"
|
||||||
|
#include "../../ui/widgets/cards/deck_preview_card_picture_widget.h"
|
||||||
|
#include "../../ui/widgets/visual_deck_storage/visual_deck_storage_widget.h"
|
||||||
|
#include "../tab.h"
|
||||||
|
|
||||||
|
#include <QProcess>
|
||||||
|
|
||||||
|
class AbstractClient;
|
||||||
|
class QTreeView;
|
||||||
|
class QFileSystemModel;
|
||||||
|
class QToolBar;
|
||||||
|
class QTreeWidget;
|
||||||
|
class QTreeWidgetItem;
|
||||||
|
class QGroupBox;
|
||||||
|
class CommandContainer;
|
||||||
|
class Response;
|
||||||
|
class DeckLoader;
|
||||||
|
|
||||||
|
class TabDeckStorageVisual final : public Tab
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
TabDeckStorageVisual(TabSupervisor *_tabSupervisor, AbstractClient *_client);
|
||||||
|
|
||||||
|
void retranslateUi() override;
|
||||||
|
QString getTabText() const override
|
||||||
|
{
|
||||||
|
return tr("Visual Deck storage");
|
||||||
|
}
|
||||||
|
public slots:
|
||||||
|
void cardUpdateFinished(int exitCode, QProcess::ExitStatus exitStatus);
|
||||||
|
void closeRequest() override;
|
||||||
|
void actOpenLocalDeck(QMouseEvent *event, DeckPreviewCardPictureWidget *instance);
|
||||||
|
void actDeleteLocalDeck();
|
||||||
|
signals:
|
||||||
|
void openDeckEditor(const DeckLoader *deckLoader);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QWidget *container;
|
||||||
|
QHBoxLayout *layout;
|
||||||
|
AbstractClient *client;
|
||||||
|
QTreeView *localDirView;
|
||||||
|
QFileSystemModel *localDirModel;
|
||||||
|
QToolBar *leftToolBar;
|
||||||
|
QGroupBox *leftGroupBox;
|
||||||
|
VisualDeckStorageWidget *visualDeckStorageWidget;
|
||||||
|
DeckListModel *deck_list_model;
|
||||||
|
QAction *aOpenLocalDeck, *aDeleteLocalDeck;
|
||||||
|
QString getTargetPath() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -96,16 +96,12 @@ void CardInfoPictureWithTextOverlayWidget::paintEvent(QPaintEvent *event)
|
||||||
// Call the base class's paintEvent to draw the card image
|
// Call the base class's paintEvent to draw the card image
|
||||||
CardInfoPictureWidget::paintEvent(event);
|
CardInfoPictureWidget::paintEvent(event);
|
||||||
|
|
||||||
// Now add the custom text overlay on top of the image
|
// If no overlay text, skip drawing the text
|
||||||
if (overlayText.isEmpty()) {
|
if (overlayText.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
QStylePainter painter(this);
|
|
||||||
|
|
||||||
// Set text properties
|
QStylePainter painter(this);
|
||||||
QFont font = painter.font();
|
|
||||||
font.setPointSize(fontSize);
|
|
||||||
painter.setFont(font);
|
|
||||||
|
|
||||||
// Get the pixmap from the base class using the getter
|
// Get the pixmap from the base class using the getter
|
||||||
const QPixmap &pixmap = getResizedPixmap();
|
const QPixmap &pixmap = getResizedPixmap();
|
||||||
|
|
@ -118,13 +114,34 @@ void CardInfoPictureWithTextOverlayWidget::paintEvent(QPaintEvent *event)
|
||||||
const QPoint topLeft{(width() - scaledSize.width()) / 2, (height() - scaledSize.height()) / 2};
|
const QPoint topLeft{(width() - scaledSize.width()) / 2, (height() - scaledSize.height()) / 2};
|
||||||
const QRect pixmapRect(topLeft, scaledSize);
|
const QRect pixmapRect(topLeft, scaledSize);
|
||||||
|
|
||||||
// Prepare text wrapping
|
// Calculate the optimal font size
|
||||||
const QFontMetrics fontMetrics(font);
|
QFont font = painter.font();
|
||||||
const int lineHeight = fontMetrics.height();
|
int optimalFontSize = fontSize; // Start with the user-defined font size
|
||||||
const int textWidth = pixmapRect.width();
|
const QFontMetrics baseMetrics(font);
|
||||||
QString wrappedText;
|
int textWidth = pixmapRect.width();
|
||||||
|
|
||||||
// Break the text into multiple lines to fit within the pixmap width
|
// Reduce the font size until the text fits within the pixmap's width
|
||||||
|
do {
|
||||||
|
font.setPointSize(optimalFontSize);
|
||||||
|
QFontMetrics fm(font);
|
||||||
|
int currentWidth = 0;
|
||||||
|
for (const QString &word : overlayText.split(' ')) {
|
||||||
|
currentWidth = std::max(currentWidth, fm.horizontalAdvance(word));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentWidth <= textWidth) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
--optimalFontSize;
|
||||||
|
} while (optimalFontSize > 1);
|
||||||
|
|
||||||
|
// Apply the calculated font size
|
||||||
|
painter.setFont(font);
|
||||||
|
|
||||||
|
// Wrap the text to fit within the pixmap width
|
||||||
|
const QFontMetrics fontMetrics(font);
|
||||||
|
QString wrappedText;
|
||||||
QString currentLine;
|
QString currentLine;
|
||||||
QStringList words = overlayText.split(' ');
|
QStringList words = overlayText.split(' ');
|
||||||
for (const QString &word : words) {
|
for (const QString &word : words) {
|
||||||
|
|
@ -141,13 +158,22 @@ void CardInfoPictureWithTextOverlayWidget::paintEvent(QPaintEvent *event)
|
||||||
wrappedText += currentLine;
|
wrappedText += currentLine;
|
||||||
|
|
||||||
// Calculate total text block height
|
// Calculate total text block height
|
||||||
const int totalTextHeight = static_cast<int>(wrappedText.count('\n')) * lineHeight + lineHeight;
|
int totalTextHeight = wrappedText.count('\n') * fontMetrics.height() + fontMetrics.height();
|
||||||
|
|
||||||
|
// Adjust font size if the total text height exceeds the pixmap height
|
||||||
|
while (totalTextHeight > pixmapRect.height() && optimalFontSize > 1) {
|
||||||
|
--optimalFontSize;
|
||||||
|
font.setPointSize(optimalFontSize);
|
||||||
|
painter.setFont(font);
|
||||||
|
const QFontMetrics newMetrics(font);
|
||||||
|
totalTextHeight = wrappedText.count('\n') * newMetrics.height() + newMetrics.height();
|
||||||
|
}
|
||||||
|
|
||||||
// Set up the text layout options
|
// Set up the text layout options
|
||||||
QTextOption textOption;
|
QTextOption textOption;
|
||||||
textOption.setAlignment(textAlignment);
|
textOption.setAlignment(textAlignment);
|
||||||
|
|
||||||
// Create a text rectangle centered within the pixmap rect
|
// Create a text rectangle centered vertically within the pixmap rect
|
||||||
auto textRect = QRect(pixmapRect.left(), pixmapRect.top(), pixmapRect.width(), totalTextHeight);
|
auto textRect = QRect(pixmapRect.left(), pixmapRect.top(), pixmapRect.width(), totalTextHeight);
|
||||||
textRect.moveTop((pixmapRect.height() - totalTextHeight) / 2 + pixmapRect.top());
|
textRect.moveTop((pixmapRect.height() - totalTextHeight) / 2 + pixmapRect.top());
|
||||||
|
|
||||||
|
|
@ -169,7 +195,6 @@ void CardInfoPictureWithTextOverlayWidget::drawOutlinedText(QPainter &painter,
|
||||||
const QString &text,
|
const QString &text,
|
||||||
const QTextOption &textOption) const
|
const QTextOption &textOption) const
|
||||||
{
|
{
|
||||||
// Draw the black outline (outlineColor)
|
|
||||||
painter.setPen(outlineColor);
|
painter.setPen(outlineColor);
|
||||||
for (int dx = -1; dx <= 1; ++dx) {
|
for (int dx = -1; dx <= 1; ++dx) {
|
||||||
for (int dy = -1; dy <= 1; ++dy) {
|
for (int dy = -1; dy <= 1; ++dy) {
|
||||||
|
|
@ -180,7 +205,7 @@ void CardInfoPictureWithTextOverlayWidget::drawOutlinedText(QPainter &painter,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw the main text (textColor)
|
// Draw the main text
|
||||||
painter.setPen(textColor);
|
painter.setPen(textColor);
|
||||||
painter.drawText(textRect, text, textOption);
|
painter.drawText(textRect, text, textOption);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
#include <QSize>
|
#include <QSize>
|
||||||
#include <QTextOption>
|
#include <QTextOption>
|
||||||
|
|
||||||
class CardInfoPictureWithTextOverlayWidget final : public CardInfoPictureWidget
|
class CardInfoPictureWithTextOverlayWidget : public CardInfoPictureWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
#include "card_size_widget.h"
|
#include "card_size_widget.h"
|
||||||
|
|
||||||
#include "../../../../settings/cache_settings.h"
|
#include "../../../../settings/cache_settings.h"
|
||||||
|
#include "../printing_selector/printing_selector.h"
|
||||||
|
#include "../visual_deck_storage/visual_deck_storage_widget.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @class CardSizeWidget
|
* @class CardSizeWidget
|
||||||
|
|
@ -40,7 +42,12 @@ CardSizeWidget::CardSizeWidget(QWidget *parent, FlowWidget *flowWidget, int defa
|
||||||
*/
|
*/
|
||||||
void CardSizeWidget::updateCardSizeSetting(int newValue)
|
void CardSizeWidget::updateCardSizeSetting(int newValue)
|
||||||
{
|
{
|
||||||
SettingsCache::instance().setPrintingSelectorCardSize(newValue);
|
// Check the type of the parent widget
|
||||||
|
if ((parent = qobject_cast<PrintingSelector *>(parentWidget()))) {
|
||||||
|
SettingsCache::instance().setPrintingSelectorCardSize(newValue);
|
||||||
|
} else if ((parent = qobject_cast<VisualDeckStorageWidget *>(parentWidget()))) {
|
||||||
|
SettingsCache::instance().setVisualDeckStorageCardSize(newValue);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -15,11 +15,11 @@ class CardSizeWidget : public QWidget
|
||||||
public:
|
public:
|
||||||
explicit CardSizeWidget(QWidget *parent, FlowWidget *flowWidget = nullptr, int defaultValue = 100);
|
explicit CardSizeWidget(QWidget *parent, FlowWidget *flowWidget = nullptr, int defaultValue = 100);
|
||||||
[[nodiscard]] QSlider *getSlider() const;
|
[[nodiscard]] QSlider *getSlider() const;
|
||||||
|
QWidget *parent;
|
||||||
public slots:
|
public slots:
|
||||||
static void updateCardSizeSetting(int newValue);
|
void updateCardSizeSetting(int newValue);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QWidget *parent;
|
|
||||||
FlowWidget *flowWidget;
|
FlowWidget *flowWidget;
|
||||||
QHBoxLayout *cardSizeLayout;
|
QHBoxLayout *cardSizeLayout;
|
||||||
QLabel *cardSizeLabel;
|
QLabel *cardSizeLabel;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
#include "deck_preview_card_picture_widget.h"
|
||||||
|
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QFontMetrics>
|
||||||
|
#include <QMouseEvent>
|
||||||
|
#include <QPainterPath>
|
||||||
|
#include <QStylePainter>
|
||||||
|
#include <QTextOption>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Constructs a CardPictureWithTextOverlay widget.
|
||||||
|
* @param parent The parent widget.
|
||||||
|
* @param hoverToZoomEnabled If this widget will spawn a larger widget when hovered over.
|
||||||
|
* @param textColor The color of the overlay text.
|
||||||
|
* @param outlineColor The color of the outline around the text.
|
||||||
|
* @param fontSize The font size of the overlay text.
|
||||||
|
* @param alignment The alignment of the text within the overlay.
|
||||||
|
*
|
||||||
|
* Sets the widget's size policy and default border style.
|
||||||
|
*/
|
||||||
|
DeckPreviewCardPictureWidget::DeckPreviewCardPictureWidget(QWidget *parent,
|
||||||
|
const bool hoverToZoomEnabled,
|
||||||
|
const QColor &textColor,
|
||||||
|
const QColor &outlineColor,
|
||||||
|
const int fontSize,
|
||||||
|
const Qt::Alignment alignment)
|
||||||
|
: CardInfoPictureWithTextOverlayWidget(parent, hoverToZoomEnabled, textColor, outlineColor, fontSize, alignment)
|
||||||
|
{
|
||||||
|
singleClickTimer = new QTimer(this);
|
||||||
|
singleClickTimer->setSingleShot(true);
|
||||||
|
connect(singleClickTimer, &QTimer::timeout, this, [this]() { emit imageClicked(lastMouseEvent, this); });
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeckPreviewCardPictureWidget::mousePressEvent(QMouseEvent *event)
|
||||||
|
{
|
||||||
|
if (event->button() == Qt::LeftButton) {
|
||||||
|
lastMouseEvent = event;
|
||||||
|
singleClickTimer->start(QApplication::doubleClickInterval());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeckPreviewCardPictureWidget::mouseDoubleClickEvent(QMouseEvent *event)
|
||||||
|
{
|
||||||
|
if (event->button() == Qt::LeftButton) {
|
||||||
|
singleClickTimer->stop(); // Prevent single-click logic
|
||||||
|
emit imageDoubleClicked(lastMouseEvent, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeckPreviewCardPictureWidget::setFilePath(const QString &_filePath)
|
||||||
|
{
|
||||||
|
filePath = _filePath;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
#ifndef DECK_PREVIEW_CARD_PICTURE_WIDGET_H
|
||||||
|
#define DECK_PREVIEW_CARD_PICTURE_WIDGET_H
|
||||||
|
|
||||||
|
#include "card_info_picture_with_text_overlay_widget.h"
|
||||||
|
|
||||||
|
#include <QColor>
|
||||||
|
#include <QSize>
|
||||||
|
#include <QTextOption>
|
||||||
|
|
||||||
|
class DeckPreviewCardPictureWidget final : public CardInfoPictureWithTextOverlayWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit DeckPreviewCardPictureWidget(QWidget *parent = nullptr,
|
||||||
|
bool hoverToZoomEnabled = false,
|
||||||
|
const QColor &textColor = Qt::white,
|
||||||
|
const QColor &outlineColor = Qt::black,
|
||||||
|
int fontSize = 12,
|
||||||
|
Qt::Alignment alignment = Qt::AlignCenter);
|
||||||
|
|
||||||
|
QString filePath;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void imageClicked(QMouseEvent *event, DeckPreviewCardPictureWidget *instance);
|
||||||
|
void imageDoubleClicked(QMouseEvent *event, DeckPreviewCardPictureWidget *instance);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void setFilePath(const QString &filePath);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QTimer *singleClickTimer;
|
||||||
|
QMouseEvent *lastMouseEvent = nullptr; // Store the last mouse event
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void mousePressEvent(QMouseEvent *event) override;
|
||||||
|
void mouseDoubleClickEvent(QMouseEvent *event) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // DECK_PREVIEW_CARD_PICTURE_WIDGET_H
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
#include "visual_deck_storage_search_widget.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Constructs a PrintingSelectorCardSearchWidget for searching cards by set name or set code.
|
||||||
|
*
|
||||||
|
* This widget provides a search bar that allows users to search for cards by either their set name
|
||||||
|
* or set code. It uses a debounced timer to trigger the search action after the user stops typing.
|
||||||
|
*
|
||||||
|
* @param parent The parent PrintingSelector widget that will handle the search results.
|
||||||
|
*/
|
||||||
|
VisualDeckStorageSearchWidget::VisualDeckStorageSearchWidget(VisualDeckStorageWidget *parent) : parent(parent)
|
||||||
|
{
|
||||||
|
layout = new QHBoxLayout(this);
|
||||||
|
setLayout(layout);
|
||||||
|
|
||||||
|
searchBar = new QLineEdit(this);
|
||||||
|
searchBar->setPlaceholderText(tr("Search by filename"));
|
||||||
|
layout->addWidget(searchBar);
|
||||||
|
|
||||||
|
// Add a debounce timer for the search bar to limit frequent updates
|
||||||
|
searchDebounceTimer = new QTimer(this);
|
||||||
|
searchDebounceTimer->setSingleShot(true);
|
||||||
|
connect(searchBar, &QLineEdit::textChanged, this, [this]() {
|
||||||
|
searchDebounceTimer->start(300); // 300ms debounce
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(searchDebounceTimer, &QTimer::timeout, parent, &VisualDeckStorageWidget::refreshBannerCards);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retrieves the current text in the search bar.
|
||||||
|
*
|
||||||
|
* @return The text entered by the user in the search bar.
|
||||||
|
*/
|
||||||
|
QString VisualDeckStorageSearchWidget::getSearchText()
|
||||||
|
{
|
||||||
|
return searchBar->text();
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList VisualDeckStorageSearchWidget::filterFiles(const QStringList &files, const QString &searchText)
|
||||||
|
{
|
||||||
|
if (searchText.isEmpty() || searchText.isNull()) {
|
||||||
|
return files;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList filteredFiles;
|
||||||
|
|
||||||
|
for (const auto &file : files) {
|
||||||
|
QFileInfo fileInfo(file);
|
||||||
|
QString fileName = fileInfo.fileName().toLower();
|
||||||
|
|
||||||
|
if (fileName.contains(searchText.toLower())) {
|
||||||
|
filteredFiles << file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return filteredFiles;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
#ifndef VISUAL_DECK_STORAGE_SEARCH_WIDGET_H
|
||||||
|
#define VISUAL_DECK_STORAGE_SEARCH_WIDGET_H
|
||||||
|
|
||||||
|
#include "visual_deck_storage_widget.h"
|
||||||
|
|
||||||
|
#include <QHBoxLayout>
|
||||||
|
#include <QLineEdit>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
|
class VisualDeckStorageWidget;
|
||||||
|
class VisualDeckStorageSearchWidget : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit VisualDeckStorageSearchWidget(VisualDeckStorageWidget *parent);
|
||||||
|
QString getSearchText();
|
||||||
|
QStringList filterFiles(const QStringList &files, const QString &searchText);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QHBoxLayout *layout;
|
||||||
|
VisualDeckStorageWidget *parent;
|
||||||
|
QLineEdit *searchBar;
|
||||||
|
QTimer *searchDebounceTimer;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // VISUAL_DECK_STORAGE_SEARCH_WIDGET_H
|
||||||
|
|
@ -0,0 +1,121 @@
|
||||||
|
#include "visual_deck_storage_widget.h"
|
||||||
|
|
||||||
|
#include "../../../../deck/deck_loader.h"
|
||||||
|
#include "../../../../game/cards/card_database_manager.h"
|
||||||
|
#include "../../../../settings/cache_settings.h"
|
||||||
|
#include "visual_deck_storage_search_widget.h"
|
||||||
|
|
||||||
|
#include <QComboBox>
|
||||||
|
#include <QDirIterator>
|
||||||
|
#include <QMouseEvent>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
|
VisualDeckStorageWidget::VisualDeckStorageWidget(QWidget *parent) : QWidget(parent), sortOrder(Alphabetical)
|
||||||
|
{
|
||||||
|
deckListModel = new DeckListModel(this);
|
||||||
|
deckListModel->setObjectName("visualDeckModel");
|
||||||
|
|
||||||
|
layout = new QVBoxLayout();
|
||||||
|
setLayout(layout);
|
||||||
|
|
||||||
|
// ComboBox for sorting options
|
||||||
|
sortComboBox = new QComboBox(this);
|
||||||
|
sortComboBox->addItem("Sort Alphabetically (Filename)", Alphabetical);
|
||||||
|
sortComboBox->addItem("Sort by Last Modified", ByLastModified);
|
||||||
|
sortComboBox->setCurrentIndex(SettingsCache::instance().getVisualDeckStorageSortingOrder());
|
||||||
|
|
||||||
|
searchWidget = new VisualDeckStorageSearchWidget(this);
|
||||||
|
|
||||||
|
// Add combo box to the main layout
|
||||||
|
layout->addWidget(sortComboBox);
|
||||||
|
layout->addWidget(searchWidget);
|
||||||
|
|
||||||
|
flowWidget = new FlowWidget(this, Qt::ScrollBarAlwaysOff, Qt::ScrollBarAsNeeded);
|
||||||
|
layout->addWidget(flowWidget);
|
||||||
|
|
||||||
|
cardSizeWidget = new CardSizeWidget(this, flowWidget, SettingsCache::instance().getVisualDeckStorageCardSize());
|
||||||
|
layout->addWidget(cardSizeWidget);
|
||||||
|
|
||||||
|
// Connect sorting change signal to refresh the file list
|
||||||
|
connect(sortComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
|
||||||
|
&VisualDeckStorageWidget::updateSortOrder);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VisualDeckStorageWidget::showEvent(QShowEvent *event)
|
||||||
|
{
|
||||||
|
QWidget::showEvent(event);
|
||||||
|
updateSortOrder();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VisualDeckStorageWidget::updateSortOrder()
|
||||||
|
{
|
||||||
|
sortOrder = static_cast<SortOrder>(sortComboBox->currentData().toInt());
|
||||||
|
SettingsCache::instance().setVisualDeckStorageSortingOrder(sortComboBox->currentData().toInt());
|
||||||
|
refreshBannerCards(); // Refresh the banner cards with the new sort order
|
||||||
|
}
|
||||||
|
|
||||||
|
void VisualDeckStorageWidget::imageClickedEvent(QMouseEvent *event, DeckPreviewCardPictureWidget *instance)
|
||||||
|
{
|
||||||
|
emit imageClicked(event, instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VisualDeckStorageWidget::imageDoubleClickedEvent(QMouseEvent *event, DeckPreviewCardPictureWidget *instance)
|
||||||
|
{
|
||||||
|
emit imageDoubleClicked(event, instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VisualDeckStorageWidget::refreshBannerCards()
|
||||||
|
{
|
||||||
|
QStringList allFiles;
|
||||||
|
|
||||||
|
// QDirIterator with QDir::Files and QDir::NoSymLinks ensures only files are listed (no directories or symlinks)
|
||||||
|
QDirIterator it(SettingsCache::instance().getDeckPath(), QDir::Files | QDir::NoSymLinks,
|
||||||
|
QDirIterator::Subdirectories);
|
||||||
|
|
||||||
|
while (it.hasNext()) {
|
||||||
|
allFiles << it.next(); // Add each file path to the list
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort files based on the current sort order
|
||||||
|
std::sort(allFiles.begin(), allFiles.end(), [this](const QString &file1, const QString &file2) {
|
||||||
|
QFileInfo info1(file1);
|
||||||
|
QFileInfo info2(file2);
|
||||||
|
|
||||||
|
switch (sortOrder) {
|
||||||
|
case Alphabetical:
|
||||||
|
return info1.fileName().toLower() < info2.fileName().toLower();
|
||||||
|
case ByLastModified:
|
||||||
|
return info1.lastModified() > info2.lastModified();
|
||||||
|
}
|
||||||
|
|
||||||
|
return false; // Default case
|
||||||
|
});
|
||||||
|
|
||||||
|
auto filteredFiles = searchWidget->filterFiles(allFiles, searchWidget->getSearchText());
|
||||||
|
|
||||||
|
flowWidget->clearLayout(); // Clear existing widgets in the flow layout
|
||||||
|
|
||||||
|
foreach (const QString &file, filteredFiles) {
|
||||||
|
auto deckLoader = new DeckLoader();
|
||||||
|
deckLoader->loadFromFile(file, DeckLoader::CockatriceFormat);
|
||||||
|
deckListModel->setDeckList(new DeckLoader(*deckLoader));
|
||||||
|
|
||||||
|
auto *display = new DeckPreviewCardPictureWidget(flowWidget, false);
|
||||||
|
auto bannerCard = deckLoader->getBannerCard().isEmpty()
|
||||||
|
? CardInfoPtr()
|
||||||
|
: CardDatabaseManager::getInstance()->getCard(deckLoader->getBannerCard());
|
||||||
|
display->setCard(bannerCard);
|
||||||
|
display->setOverlayText(deckLoader->getName().isEmpty() ? QFileInfo(deckLoader->getLastFileName()).fileName()
|
||||||
|
: deckLoader->getName());
|
||||||
|
display->setFontSize(24);
|
||||||
|
display->setFilePath(deckLoader->getLastFileName());
|
||||||
|
|
||||||
|
connect(display, &DeckPreviewCardPictureWidget::imageClicked, this,
|
||||||
|
&VisualDeckStorageWidget::imageClickedEvent);
|
||||||
|
connect(display, &DeckPreviewCardPictureWidget::imageDoubleClicked, this,
|
||||||
|
&VisualDeckStorageWidget::imageDoubleClickedEvent);
|
||||||
|
connect(cardSizeWidget->getSlider(), &QSlider::valueChanged, display, &CardInfoPictureWidget::setScaleFactor);
|
||||||
|
display->setScaleFactor(cardSizeWidget->getSlider()->value());
|
||||||
|
flowWidget->addWidget(display);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
#ifndef VISUAL_DECK_STORAGE_WIDGET_H
|
||||||
|
#define VISUAL_DECK_STORAGE_WIDGET_H
|
||||||
|
|
||||||
|
#include "../../../../deck/deck_list_model.h"
|
||||||
|
#include "../../../../deck/deck_view.h"
|
||||||
|
#include "../../../ui/widgets/cards/deck_preview_card_picture_widget.h"
|
||||||
|
#include "../../../ui/widgets/general/layout_containers/flow_widget.h"
|
||||||
|
#include "../cards/card_size_widget.h"
|
||||||
|
#include "visual_deck_storage_search_widget.h"
|
||||||
|
|
||||||
|
#include <QComboBox>
|
||||||
|
#include <QFileSystemModel>
|
||||||
|
|
||||||
|
class VisualDeckStorageSearchWidget;
|
||||||
|
class VisualDeckStorageWidget final : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit VisualDeckStorageWidget(QWidget *parent);
|
||||||
|
void retranslateUi();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void imageClickedEvent(QMouseEvent *event, DeckPreviewCardPictureWidget *instance);
|
||||||
|
void imageDoubleClickedEvent(QMouseEvent *event, DeckPreviewCardPictureWidget *instance);
|
||||||
|
void refreshBannerCards(); // Refresh the display of cards based on the current sorting option
|
||||||
|
void showEvent(QShowEvent *event) override;
|
||||||
|
void updateSortOrder();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void imageClicked(QMouseEvent *event, DeckPreviewCardPictureWidget *instance);
|
||||||
|
void imageDoubleClicked(QMouseEvent *event, DeckPreviewCardPictureWidget *instance);
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum SortOrder
|
||||||
|
{
|
||||||
|
Alphabetical,
|
||||||
|
ByLastModified
|
||||||
|
};
|
||||||
|
|
||||||
|
QVBoxLayout *layout;
|
||||||
|
FlowWidget *flowWidget;
|
||||||
|
DeckListModel *deckListModel;
|
||||||
|
QMap<QString, DeckViewCardContainer *> cardContainers;
|
||||||
|
|
||||||
|
SortOrder sortOrder; // Current sorting option
|
||||||
|
QComboBox *sortComboBox;
|
||||||
|
VisualDeckStorageSearchWidget *searchWidget;
|
||||||
|
CardSizeWidget *cardSizeWidget;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // VISUAL_DECK_STORAGE_WIDGET_H
|
||||||
|
|
@ -290,6 +290,11 @@ void MainWindow::actDeckEditor()
|
||||||
tabSupervisor->addDeckEditorTab(nullptr);
|
tabSupervisor->addDeckEditorTab(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::actVisualDeckStorage()
|
||||||
|
{
|
||||||
|
tabSupervisor->addVisualDeckStorageTab();
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::actFullScreen(bool checked)
|
void MainWindow::actFullScreen(bool checked)
|
||||||
{
|
{
|
||||||
if (checked)
|
if (checked)
|
||||||
|
|
@ -660,6 +665,7 @@ void MainWindow::retranslateUi()
|
||||||
aSinglePlayer->setText(tr("Start &local game..."));
|
aSinglePlayer->setText(tr("Start &local game..."));
|
||||||
aWatchReplay->setText(tr("&Watch replay..."));
|
aWatchReplay->setText(tr("&Watch replay..."));
|
||||||
aDeckEditor->setText(tr("&Deck editor"));
|
aDeckEditor->setText(tr("&Deck editor"));
|
||||||
|
aVisualDeckStorage->setText(tr("&Visual Deck storage"));
|
||||||
aFullScreen->setText(tr("&Full screen"));
|
aFullScreen->setText(tr("&Full screen"));
|
||||||
aRegister->setText(tr("&Register to server..."));
|
aRegister->setText(tr("&Register to server..."));
|
||||||
aForgotPassword->setText(tr("&Restore password..."));
|
aForgotPassword->setText(tr("&Restore password..."));
|
||||||
|
|
@ -707,6 +713,8 @@ void MainWindow::createActions()
|
||||||
connect(aWatchReplay, SIGNAL(triggered()), this, SLOT(actWatchReplay()));
|
connect(aWatchReplay, SIGNAL(triggered()), this, SLOT(actWatchReplay()));
|
||||||
aDeckEditor = new QAction(this);
|
aDeckEditor = new QAction(this);
|
||||||
connect(aDeckEditor, SIGNAL(triggered()), this, SLOT(actDeckEditor()));
|
connect(aDeckEditor, SIGNAL(triggered()), this, SLOT(actDeckEditor()));
|
||||||
|
aVisualDeckStorage = new QAction(this);
|
||||||
|
connect(aVisualDeckStorage, SIGNAL(triggered()), this, SLOT(actVisualDeckStorage()));
|
||||||
aFullScreen = new QAction(this);
|
aFullScreen = new QAction(this);
|
||||||
aFullScreen->setCheckable(true);
|
aFullScreen->setCheckable(true);
|
||||||
connect(aFullScreen, SIGNAL(toggled(bool)), this, SLOT(actFullScreen(bool)));
|
connect(aFullScreen, SIGNAL(toggled(bool)), this, SLOT(actFullScreen(bool)));
|
||||||
|
|
@ -794,6 +802,7 @@ void MainWindow::createMenus()
|
||||||
cockatriceMenu->addAction(aWatchReplay);
|
cockatriceMenu->addAction(aWatchReplay);
|
||||||
cockatriceMenu->addSeparator();
|
cockatriceMenu->addSeparator();
|
||||||
cockatriceMenu->addAction(aDeckEditor);
|
cockatriceMenu->addAction(aDeckEditor);
|
||||||
|
cockatriceMenu->addAction(aVisualDeckStorage);
|
||||||
cockatriceMenu->addSeparator();
|
cockatriceMenu->addSeparator();
|
||||||
cockatriceMenu->addAction(aFullScreen);
|
cockatriceMenu->addAction(aFullScreen);
|
||||||
cockatriceMenu->addSeparator();
|
cockatriceMenu->addSeparator();
|
||||||
|
|
@ -881,6 +890,11 @@ MainWindow::MainWindow(QWidget *parent)
|
||||||
|
|
||||||
connect(&SettingsCache::instance().shortcuts(), SIGNAL(shortCutChanged()), this, SLOT(refreshShortcuts()));
|
connect(&SettingsCache::instance().shortcuts(), SIGNAL(shortCutChanged()), this, SLOT(refreshShortcuts()));
|
||||||
refreshShortcuts();
|
refreshShortcuts();
|
||||||
|
|
||||||
|
if (SettingsCache::instance().getVisualDeckStorageShowOnLoad()) {
|
||||||
|
connect(CardDatabaseManager::getInstance(), SIGNAL(cardDatabaseLoadingFinished()), tabSupervisor,
|
||||||
|
SLOT(addVisualDeckStorageTab()));
|
||||||
|
}
|
||||||
connect(CardDatabaseManager::getInstance(), SIGNAL(cardDatabaseLoadingFailed()), this,
|
connect(CardDatabaseManager::getInstance(), SIGNAL(cardDatabaseLoadingFailed()), this,
|
||||||
SLOT(cardDatabaseLoadingFailed()));
|
SLOT(cardDatabaseLoadingFailed()));
|
||||||
connect(CardDatabaseManager::getInstance(), SIGNAL(cardDatabaseNewSetsFound(int, QStringList)), this,
|
connect(CardDatabaseManager::getInstance(), SIGNAL(cardDatabaseNewSetsFound(int, QStringList)), this,
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,7 @@ private slots:
|
||||||
void actSinglePlayer();
|
void actSinglePlayer();
|
||||||
void actWatchReplay();
|
void actWatchReplay();
|
||||||
void actDeckEditor();
|
void actDeckEditor();
|
||||||
|
void actVisualDeckStorage();
|
||||||
void actFullScreen(bool checked);
|
void actFullScreen(bool checked);
|
||||||
void actRegister();
|
void actRegister();
|
||||||
void actSettings();
|
void actSettings();
|
||||||
|
|
@ -131,10 +132,11 @@ private:
|
||||||
|
|
||||||
QList<QMenu *> tabMenus;
|
QList<QMenu *> tabMenus;
|
||||||
QMenu *cockatriceMenu, *dbMenu, *helpMenu, *trayIconMenu;
|
QMenu *cockatriceMenu, *dbMenu, *helpMenu, *trayIconMenu;
|
||||||
QAction *aConnect, *aDisconnect, *aSinglePlayer, *aWatchReplay, *aDeckEditor, *aFullScreen, *aSettings, *aExit,
|
QAction *aConnect, *aDisconnect, *aSinglePlayer, *aWatchReplay, *aDeckEditor, *aVisualDeckStorage, *aFullScreen,
|
||||||
*aAbout, *aTips, *aCheckCardUpdates, *aRegister, *aForgotPassword, *aUpdate, *aViewLog, *aManageSets,
|
*aSettings, *aExit, *aAbout, *aTips, *aCheckCardUpdates, *aRegister, *aForgotPassword, *aUpdate, *aViewLog,
|
||||||
*aEditTokens, *aOpenCustomFolder, *aOpenCustomsetsFolder, *aAddCustomSet, *aReloadCardDatabase, *aShow,
|
*aManageSets, *aEditTokens, *aOpenCustomFolder, *aOpenCustomsetsFolder, *aAddCustomSet, *aReloadCardDatabase,
|
||||||
*aOpenSettingsFolder;
|
*aShow, *aOpenSettingsFolder;
|
||||||
|
|
||||||
TabSupervisor *tabSupervisor;
|
TabSupervisor *tabSupervisor;
|
||||||
WndSets *wndSets;
|
WndSets *wndSets;
|
||||||
RemoteClient *client;
|
RemoteClient *client;
|
||||||
|
|
|
||||||
|
|
@ -346,8 +346,13 @@ AppearanceSettingsPage::AppearanceSettingsPage()
|
||||||
showShortcutsCheckBox.setChecked(settings.getShowShortcuts());
|
showShortcutsCheckBox.setChecked(settings.getShowShortcuts());
|
||||||
connect(&showShortcutsCheckBox, &QCheckBox::QT_STATE_CHANGED, this, &AppearanceSettingsPage::showShortcutsChanged);
|
connect(&showShortcutsCheckBox, &QCheckBox::QT_STATE_CHANGED, this, &AppearanceSettingsPage::showShortcutsChanged);
|
||||||
|
|
||||||
|
showVisualDeckStorageOnLoadCheckBox.setChecked(settings.getVisualDeckStorageShowOnLoad());
|
||||||
|
connect(&showVisualDeckStorageOnLoadCheckBox, &QCheckBox::QT_STATE_CHANGED, &settings,
|
||||||
|
&SettingsCache::setVisualDeckStorageShowOnLoad);
|
||||||
|
|
||||||
auto *menuGrid = new QGridLayout;
|
auto *menuGrid = new QGridLayout;
|
||||||
menuGrid->addWidget(&showShortcutsCheckBox, 0, 0);
|
menuGrid->addWidget(&showShortcutsCheckBox, 0, 0);
|
||||||
|
menuGrid->addWidget(&showVisualDeckStorageOnLoadCheckBox, 1, 0);
|
||||||
|
|
||||||
menuGroupBox = new QGroupBox;
|
menuGroupBox = new QGroupBox;
|
||||||
menuGroupBox->setLayout(menuGrid);
|
menuGroupBox->setLayout(menuGrid);
|
||||||
|
|
@ -482,6 +487,7 @@ void AppearanceSettingsPage::retranslateUi()
|
||||||
|
|
||||||
menuGroupBox->setTitle(tr("Menu settings"));
|
menuGroupBox->setTitle(tr("Menu settings"));
|
||||||
showShortcutsCheckBox.setText(tr("Show keyboard shortcuts in right-click menus"));
|
showShortcutsCheckBox.setText(tr("Show keyboard shortcuts in right-click menus"));
|
||||||
|
showVisualDeckStorageOnLoadCheckBox.setText(tr("Show visual deck storage on database load"));
|
||||||
|
|
||||||
cardsGroupBox->setTitle(tr("Card rendering"));
|
cardsGroupBox->setTitle(tr("Card rendering"));
|
||||||
displayCardNamesCheckBox.setText(tr("Display card names on cards having a picture"));
|
displayCardNamesCheckBox.setText(tr("Display card names on cards having a picture"));
|
||||||
|
|
|
||||||
|
|
@ -95,6 +95,7 @@ private:
|
||||||
QLabel minPlayersForMultiColumnLayoutLabel;
|
QLabel minPlayersForMultiColumnLayoutLabel;
|
||||||
QLabel maxFontSizeForCardsLabel;
|
QLabel maxFontSizeForCardsLabel;
|
||||||
QCheckBox showShortcutsCheckBox;
|
QCheckBox showShortcutsCheckBox;
|
||||||
|
QCheckBox showVisualDeckStorageOnLoadCheckBox;
|
||||||
QCheckBox displayCardNamesCheckBox;
|
QCheckBox displayCardNamesCheckBox;
|
||||||
QCheckBox autoRotateSidewaysLayoutCardsCheckBox;
|
QCheckBox autoRotateSidewaysLayoutCardsCheckBox;
|
||||||
QCheckBox overrideAllCardArtWithPersonalPreferenceCheckBox;
|
QCheckBox overrideAllCardArtWithPersonalPreferenceCheckBox;
|
||||||
|
|
|
||||||
|
|
@ -117,14 +117,15 @@ public:
|
||||||
}
|
}
|
||||||
void clearFilterAll();
|
void clearFilterAll();
|
||||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
bool canFetchMore(const QModelIndex &parent) const override;
|
||||||
|
void fetchMore(const QModelIndex &parent) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool lessThan(const QModelIndex &left, const QModelIndex &right) const override;
|
bool lessThan(const QModelIndex &left, const QModelIndex &right) const override;
|
||||||
static int lessThanNumerically(const QString &left, const QString &right);
|
static int lessThanNumerically(const QString &left, const QString &right);
|
||||||
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
|
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
|
||||||
bool rowMatchesCardName(CardInfoPtr info) const;
|
bool rowMatchesCardName(CardInfoPtr info) const;
|
||||||
bool canFetchMore(const QModelIndex &parent) const override;
|
|
||||||
void fetchMore(const QModelIndex &parent) override;
|
|
||||||
private slots:
|
private slots:
|
||||||
void filterTreeChanged();
|
void filterTreeChanged();
|
||||||
/** Will translate all undesirable characters in DIRTYNAME according to the TABLE. */
|
/** Will translate all undesirable characters in DIRTYNAME according to the TABLE. */
|
||||||
|
|
|
||||||
|
|
@ -259,6 +259,9 @@ SettingsCache::SettingsCache()
|
||||||
settings->value("cards/printingselectorcardsizeslidervisible", true).toBool();
|
settings->value("cards/printingselectorcardsizeslidervisible", true).toBool();
|
||||||
printingSelectorNavigationButtonsVisible =
|
printingSelectorNavigationButtonsVisible =
|
||||||
settings->value("cards/printingselectornavigationbuttonsvisible", true).toBool();
|
settings->value("cards/printingselectornavigationbuttonsvisible", true).toBool();
|
||||||
|
visualDeckStorageCardSize = settings->value("cards/visualdeckstoragecardsize", 100).toInt();
|
||||||
|
visualDeckStorageShowOnLoad = settings->value("interface/visualdeckstorageshowonload", true).toBool();
|
||||||
|
visualDeckStorageSortingOrder = settings->value("interface/visualdeckstoragesortingorder", 0).toInt();
|
||||||
horizontalHand = settings->value("hand/horizontal", true).toBool();
|
horizontalHand = settings->value("hand/horizontal", true).toBool();
|
||||||
invertVerticalCoordinate = settings->value("table/invert_vertical", false).toBool();
|
invertVerticalCoordinate = settings->value("table/invert_vertical", false).toBool();
|
||||||
minPlayersForMultiColumnLayout = settings->value("interface/min_players_multicolumn", 4).toInt();
|
minPlayersForMultiColumnLayout = settings->value("interface/min_players_multicolumn", 4).toInt();
|
||||||
|
|
@ -609,6 +612,25 @@ void SettingsCache::setPrintingSelectorNavigationButtonsVisible(QT_STATE_CHANGED
|
||||||
emit printingSelectorNavigationButtonsVisibleChanged();
|
emit printingSelectorNavigationButtonsVisibleChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SettingsCache::setVisualDeckStorageSortingOrder(int _visualDeckStorageSortingOrder)
|
||||||
|
{
|
||||||
|
visualDeckStorageSortingOrder = _visualDeckStorageSortingOrder;
|
||||||
|
settings->setValue("interface/visualdeckstoragesortingorder", visualDeckStorageSortingOrder);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SettingsCache::setVisualDeckStorageCardSize(int _visualDeckStorageCardSize)
|
||||||
|
{
|
||||||
|
visualDeckStorageCardSize = _visualDeckStorageCardSize;
|
||||||
|
settings->setValue("cards/visualdeckstoragecardsize", visualDeckStorageCardSize);
|
||||||
|
emit visualDeckStorageCardSizeChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SettingsCache::setVisualDeckStorageShowOnLoad(QT_STATE_CHANGED_T _visualDeckStorageShowOnLoad)
|
||||||
|
{
|
||||||
|
visualDeckStorageShowOnLoad = _visualDeckStorageShowOnLoad;
|
||||||
|
settings->setValue("interface/visualdeckstorageshowonload", visualDeckStorageShowOnLoad);
|
||||||
|
}
|
||||||
|
|
||||||
void SettingsCache::setHorizontalHand(QT_STATE_CHANGED_T _horizontalHand)
|
void SettingsCache::setHorizontalHand(QT_STATE_CHANGED_T _horizontalHand)
|
||||||
{
|
{
|
||||||
horizontalHand = static_cast<bool>(_horizontalHand);
|
horizontalHand = static_cast<bool>(_horizontalHand);
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,7 @@ signals:
|
||||||
void printingSelectorSearchBarVisibleChanged();
|
void printingSelectorSearchBarVisibleChanged();
|
||||||
void printingSelectorCardSizeSliderVisibleChanged();
|
void printingSelectorCardSizeSliderVisibleChanged();
|
||||||
void printingSelectorNavigationButtonsVisibleChanged();
|
void printingSelectorNavigationButtonsVisibleChanged();
|
||||||
|
void visualDeckStorageCardSizeChanged();
|
||||||
void horizontalHandChanged();
|
void horizontalHandChanged();
|
||||||
void handJustificationChanged();
|
void handJustificationChanged();
|
||||||
void invertVerticalCoordinateChanged();
|
void invertVerticalCoordinateChanged();
|
||||||
|
|
@ -123,6 +124,9 @@ private:
|
||||||
bool printingSelectorSearchBarVisible;
|
bool printingSelectorSearchBarVisible;
|
||||||
bool printingSelectorCardSizeSliderVisible;
|
bool printingSelectorCardSizeSliderVisible;
|
||||||
bool printingSelectorNavigationButtonsVisible;
|
bool printingSelectorNavigationButtonsVisible;
|
||||||
|
int visualDeckStorageSortingOrder;
|
||||||
|
int visualDeckStorageCardSize;
|
||||||
|
bool visualDeckStorageShowOnLoad;
|
||||||
bool horizontalHand;
|
bool horizontalHand;
|
||||||
bool invertVerticalCoordinate;
|
bool invertVerticalCoordinate;
|
||||||
int minPlayersForMultiColumnLayout;
|
int minPlayersForMultiColumnLayout;
|
||||||
|
|
@ -369,6 +373,18 @@ public:
|
||||||
{
|
{
|
||||||
return printingSelectorNavigationButtonsVisible;
|
return printingSelectorNavigationButtonsVisible;
|
||||||
}
|
}
|
||||||
|
int getVisualDeckStorageSortingOrder() const
|
||||||
|
{
|
||||||
|
return visualDeckStorageSortingOrder;
|
||||||
|
}
|
||||||
|
int getVisualDeckStorageCardSize() const
|
||||||
|
{
|
||||||
|
return visualDeckStorageCardSize;
|
||||||
|
}
|
||||||
|
bool getVisualDeckStorageShowOnLoad() const
|
||||||
|
{
|
||||||
|
return visualDeckStorageShowOnLoad;
|
||||||
|
}
|
||||||
bool getHorizontalHand() const
|
bool getHorizontalHand() const
|
||||||
{
|
{
|
||||||
return horizontalHand;
|
return horizontalHand;
|
||||||
|
|
@ -677,6 +693,9 @@ public slots:
|
||||||
void setPrintingSelectorSearchBarVisible(QT_STATE_CHANGED_T _searchBarVisible);
|
void setPrintingSelectorSearchBarVisible(QT_STATE_CHANGED_T _searchBarVisible);
|
||||||
void setPrintingSelectorCardSizeSliderVisible(QT_STATE_CHANGED_T _cardSizeSliderVisible);
|
void setPrintingSelectorCardSizeSliderVisible(QT_STATE_CHANGED_T _cardSizeSliderVisible);
|
||||||
void setPrintingSelectorNavigationButtonsVisible(QT_STATE_CHANGED_T _navigationButtonsVisible);
|
void setPrintingSelectorNavigationButtonsVisible(QT_STATE_CHANGED_T _navigationButtonsVisible);
|
||||||
|
void setVisualDeckStorageSortingOrder(int _visualDeckStorageSortingOrder);
|
||||||
|
void setVisualDeckStorageCardSize(int _visualDeckStorageCardSize);
|
||||||
|
void setVisualDeckStorageShowOnLoad(QT_STATE_CHANGED_T _visualDeckStorageShowOnLoad);
|
||||||
void setHorizontalHand(QT_STATE_CHANGED_T _horizontalHand);
|
void setHorizontalHand(QT_STATE_CHANGED_T _horizontalHand);
|
||||||
void setInvertVerticalCoordinate(QT_STATE_CHANGED_T _invertVerticalCoordinate);
|
void setInvertVerticalCoordinate(QT_STATE_CHANGED_T _invertVerticalCoordinate);
|
||||||
void setMinPlayersForMultiColumnLayout(int _minPlayersForMultiColumnLayout);
|
void setMinPlayersForMultiColumnLayout(int _minPlayersForMultiColumnLayout);
|
||||||
|
|
|
||||||
|
|
@ -368,7 +368,7 @@ DeckList::DeckList()
|
||||||
|
|
||||||
// TODO: https://qt-project.org/doc/qt-4.8/qobject.html#no-copy-constructor-or-assignment-operator
|
// TODO: https://qt-project.org/doc/qt-4.8/qobject.html#no-copy-constructor-or-assignment-operator
|
||||||
DeckList::DeckList(const DeckList &other)
|
DeckList::DeckList(const DeckList &other)
|
||||||
: QObject(), name(other.name), comments(other.comments), deckHash(other.deckHash)
|
: QObject(), name(other.name), comments(other.comments), bannerCard(other.bannerCard), deckHash(other.deckHash)
|
||||||
{
|
{
|
||||||
root = new InnerDecklistNode(other.getRoot());
|
root = new InnerDecklistNode(other.getRoot());
|
||||||
|
|
||||||
|
|
@ -423,7 +423,10 @@ bool DeckList::readElement(QXmlStreamReader *xml)
|
||||||
name = xml->readElementText();
|
name = xml->readElementText();
|
||||||
else if (childName == "comments")
|
else if (childName == "comments")
|
||||||
comments = xml->readElementText();
|
comments = xml->readElementText();
|
||||||
else if (childName == "zone") {
|
else if (childName == "bannerCard") {
|
||||||
|
bannerCard = xml->readElementText();
|
||||||
|
qDebug() << "Deckloader found the banner card " << bannerCard;
|
||||||
|
} else if (childName == "zone") {
|
||||||
InnerDecklistNode *newZone = getZoneObjFromName(xml->attributes().value("name").toString());
|
InnerDecklistNode *newZone = getZoneObjFromName(xml->attributes().value("name").toString());
|
||||||
newZone->readElement(xml);
|
newZone->readElement(xml);
|
||||||
} else if (childName == "sideboard_plan") {
|
} else if (childName == "sideboard_plan") {
|
||||||
|
|
@ -444,6 +447,7 @@ void DeckList::write(QXmlStreamWriter *xml)
|
||||||
xml->writeAttribute("version", "1");
|
xml->writeAttribute("version", "1");
|
||||||
xml->writeTextElement("deckname", name);
|
xml->writeTextElement("deckname", name);
|
||||||
xml->writeTextElement("comments", comments);
|
xml->writeTextElement("comments", comments);
|
||||||
|
xml->writeTextElement("bannerCard", bannerCard);
|
||||||
|
|
||||||
for (int i = 0; i < root->size(); i++)
|
for (int i = 0; i < root->size(); i++)
|
||||||
root->at(i)->writeElement(xml);
|
root->at(i)->writeElement(xml);
|
||||||
|
|
|
||||||
|
|
@ -250,7 +250,7 @@ class DeckList : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
private:
|
private:
|
||||||
QString name, comments;
|
QString name, comments, bannerCard;
|
||||||
QString deckHash;
|
QString deckHash;
|
||||||
QMap<QString, SideboardPlan *> sideboardPlans;
|
QMap<QString, SideboardPlan *> sideboardPlans;
|
||||||
InnerDecklistNode *root;
|
InnerDecklistNode *root;
|
||||||
|
|
@ -279,6 +279,10 @@ public slots:
|
||||||
{
|
{
|
||||||
comments = _comments;
|
comments = _comments;
|
||||||
}
|
}
|
||||||
|
void setBannerCard(const QString &_bannerCard = QString())
|
||||||
|
{
|
||||||
|
bannerCard = _bannerCard;
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit DeckList();
|
explicit DeckList();
|
||||||
|
|
@ -293,6 +297,10 @@ public:
|
||||||
{
|
{
|
||||||
return comments;
|
return comments;
|
||||||
}
|
}
|
||||||
|
QString getBannerCard() const
|
||||||
|
{
|
||||||
|
return bannerCard;
|
||||||
|
}
|
||||||
QList<MoveCard_ToZone> getCurrentSideboardPlan();
|
QList<MoveCard_ToZone> getCurrentSideboardPlan();
|
||||||
void setCurrentSideboardPlan(const QList<MoveCard_ToZone> &plan);
|
void setCurrentSideboardPlan(const QList<MoveCard_ToZone> &plan);
|
||||||
const QMap<QString, SideboardPlan *> &getSideboardPlans() const
|
const QMap<QString, SideboardPlan *> &getSideboardPlans() const
|
||||||
|
|
|
||||||
|
|
@ -184,6 +184,15 @@ void SettingsCache::setPrintingSelectorCardSizeSliderVisible(QT_STATE_CHANGED_T
|
||||||
void SettingsCache::setPrintingSelectorNavigationButtonsVisible(QT_STATE_CHANGED_T /* _navigationButtonsVisible */)
|
void SettingsCache::setPrintingSelectorNavigationButtonsVisible(QT_STATE_CHANGED_T /* _navigationButtonsVisible */)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
void SettingsCache::setVisualDeckStorageSortingOrder(int /* _visualDeckStorageSortingOrder */)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void SettingsCache::setVisualDeckStorageCardSize(int /* _visualDeckStorageCardSize */)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void SettingsCache::setVisualDeckStorageShowOnLoad(QT_STATE_CHANGED_T /* _visualDeckStorageShowOnLoad */)
|
||||||
|
{
|
||||||
|
}
|
||||||
void SettingsCache::setHorizontalHand(QT_STATE_CHANGED_T /* _horizontalHand */)
|
void SettingsCache::setHorizontalHand(QT_STATE_CHANGED_T /* _horizontalHand */)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -188,6 +188,15 @@ void SettingsCache::setPrintingSelectorCardSizeSliderVisible(QT_STATE_CHANGED_T
|
||||||
void SettingsCache::setPrintingSelectorNavigationButtonsVisible(QT_STATE_CHANGED_T /* _navigationButtonsVisible */)
|
void SettingsCache::setPrintingSelectorNavigationButtonsVisible(QT_STATE_CHANGED_T /* _navigationButtonsVisible */)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
void SettingsCache::setVisualDeckStorageSortingOrder(int /* _visualDeckStorageSortingOrder */)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void SettingsCache::setVisualDeckStorageCardSize(int /* _visualDeckStorageCardSize */)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void SettingsCache::setVisualDeckStorageShowOnLoad(QT_STATE_CHANGED_T /* _visualDeckStorageShowOnLoad */)
|
||||||
|
{
|
||||||
|
}
|
||||||
void SettingsCache::setHorizontalHand(QT_STATE_CHANGED_T /* _horizontalHand */)
|
void SettingsCache::setHorizontalHand(QT_STATE_CHANGED_T /* _horizontalHand */)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue