From 686645c1e4053527ab651d6ecf5a039d047c3138 Mon Sep 17 00:00:00 2001 From: RickyRister <42636155+RickyRister@users.noreply.github.com> Date: Mon, 13 Jan 2025 23:00:09 -0800 Subject: [PATCH] refactor DeckViewContainer into own file (#5455) * cut-and-paste * remove some includes * move refreshShortcuts * move deck_view into src/game/deckview * move deck_view_container to src/game/deckview * fix build failure --- cockatrice/CMakeLists.txt | 3 +- cockatrice/src/client/tabs/tab_game.cpp | 500 ++++-------------- cockatrice/src/client/tabs/tab_game.h | 63 +-- .../src/{deck => game/deckview}/deck_view.cpp | 7 +- .../src/{deck => game/deckview}/deck_view.h | 2 +- .../src/game/deckview/deck_view_container.cpp | 307 +++++++++++ .../src/game/deckview/deck_view_container.h | 80 +++ 7 files changed, 495 insertions(+), 467 deletions(-) rename cockatrice/src/{deck => game/deckview}/deck_view.cpp (99%) rename cockatrice/src/{deck => game/deckview}/deck_view.h (98%) create mode 100644 cockatrice/src/game/deckview/deck_view_container.cpp create mode 100644 cockatrice/src/game/deckview/deck_view_container.h diff --git a/cockatrice/CMakeLists.txt b/cockatrice/CMakeLists.txt index f7159d615..73b835bdd 100644 --- a/cockatrice/CMakeLists.txt +++ b/cockatrice/CMakeLists.txt @@ -34,7 +34,6 @@ set(cockatrice_SOURCES src/deck/deck_loader.cpp src/deck/deck_list_model.cpp src/deck/deck_stats_interface.cpp - src/deck/deck_view.cpp src/dialogs/dlg_connect.cpp src/dialogs/dlg_create_token.cpp src/dialogs/dlg_create_game.cpp @@ -57,6 +56,8 @@ set(cockatrice_SOURCES src/dialogs/dlg_update.cpp src/dialogs/dlg_view_log.cpp src/dialogs/dlg_load_deck.cpp + src/game/deckview/deck_view.cpp + src/game/deckview/deck_view_container.cpp src/game/filters/filter_string.cpp src/game/filters/filter_builder.cpp src/game/filters/filter_tree.cpp diff --git a/cockatrice/src/client/tabs/tab_game.cpp b/cockatrice/src/client/tabs/tab_game.cpp index 89c07b02c..919880603 100644 --- a/cockatrice/src/client/tabs/tab_game.cpp +++ b/cockatrice/src/client/tabs/tab_game.cpp @@ -1,22 +1,17 @@ #include "tab_game.h" #include "../../client/ui/widgets/cards/card_info_frame_widget.h" -#include "../../deck/deck_loader.h" -#include "../../deck/deck_view.h" #include "../../dialogs/dlg_create_game.h" -#include "../../dialogs/dlg_load_deck.h" -#include "../../dialogs/dlg_load_remote_deck.h" -#include "../../dialogs/dlg_manage_sets.h" #include "../../game/board/arrow_item.h" #include "../../game/cards/card_database.h" #include "../../game/cards/card_database_manager.h" #include "../../game/cards/card_item.h" +#include "../../game/deckview/deck_view_container.h" #include "../../game/game_scene.h" #include "../../game/game_view.h" #include "../../game/player/player.h" #include "../../game/player/player_list_widget.h" -#include "../../game/zones/view_zone.h" -#include "../../game/zones/view_zone_widget.h" +#include "../../game/zones/card_zone.h" #include "../../main.h" #include "../../server/message_log_widget.h" #include "../../server/pending_command.h" @@ -29,16 +24,12 @@ #include "../ui/window_main.h" #include "get_pb_extension.h" #include "pb/command_concede.pb.h" -#include "pb/command_deck_select.pb.h" #include "pb/command_delete_arrow.pb.h" #include "pb/command_game_say.pb.h" #include "pb/command_leave_game.pb.h" #include "pb/command_next_turn.pb.h" -#include "pb/command_ready_start.pb.h" #include "pb/command_reverse_turn.pb.h" #include "pb/command_set_active_phase.pb.h" -#include "pb/command_set_sideboard_lock.pb.h" -#include "pb/command_set_sideboard_plan.pb.h" #include "pb/context_connection_state_changed.pb.h" #include "pb/context_deck_select.pb.h" #include "pb/context_ping_changed.pb.h" @@ -56,7 +47,6 @@ #include "pb/event_set_active_player.pb.h" #include "pb/game_event_container.pb.h" #include "pb/game_replay.pb.h" -#include "pb/response_deck_download.pb.h" #include "tab_supervisor.h" #include "trice_limits.h" @@ -74,393 +64,6 @@ #include #include #include -#include - -ToggleButton::ToggleButton(QWidget *parent) : QPushButton(parent), state(false) -{ -} - -void ToggleButton::paintEvent(QPaintEvent *event) -{ - QPushButton::paintEvent(event); - - QPainter painter(this); - QPen pen; - pen.setWidth(3); - pen.setJoinStyle(Qt::MiterJoin); - pen.setColor(state ? Qt::green : Qt::red); - painter.setPen(pen); - painter.drawRect(QRect(1, 1, width() - 3, height() - 3)); -} - -void ToggleButton::setState(bool _state) -{ - state = _state; - emit stateChanged(); - update(); -} - -DeckViewContainer::DeckViewContainer(int _playerId, TabGame *parent) - : QWidget(nullptr), parentGame(parent), playerId(_playerId) -{ - loadLocalButton = new QPushButton; - loadRemoteButton = new QPushButton; - unloadDeckButton = new QPushButton; - unloadDeckButton->setEnabled(false); - readyStartButton = new ToggleButton; - readyStartButton->setEnabled(false); - forceStartGameButton = new QPushButton; - forceStartGameButton->setEnabled(parent->isHost()); - sideboardLockButton = new ToggleButton; - sideboardLockButton->setEnabled(false); - - connect(loadLocalButton, SIGNAL(clicked()), this, SLOT(loadLocalDeck())); - connect(readyStartButton, SIGNAL(clicked()), this, SLOT(readyStart())); - connect(unloadDeckButton, &QPushButton::clicked, this, &DeckViewContainer::unloadDeck); - connect(forceStartGameButton, &QPushButton::clicked, this, &DeckViewContainer::forceStart); - connect(sideboardLockButton, SIGNAL(clicked()), this, SLOT(sideboardLockButtonClicked())); - connect(sideboardLockButton, SIGNAL(stateChanged()), this, SLOT(updateSideboardLockButtonText())); - - if (parentGame->getIsLocalGame()) { - loadRemoteButton->setEnabled(false); - } else { - connect(loadRemoteButton, SIGNAL(clicked()), this, SLOT(loadRemoteDeck())); - } - - auto *buttonHBox = new QHBoxLayout; - buttonHBox->addWidget(loadLocalButton); - buttonHBox->addWidget(loadRemoteButton); - buttonHBox->addWidget(unloadDeckButton); - buttonHBox->addWidget(readyStartButton); - buttonHBox->addWidget(sideboardLockButton); - if (forceStartGameButton->isEnabled()) { - buttonHBox->addWidget(forceStartGameButton); - forceStartGameButton->setEnabled(false); - } - buttonHBox->setContentsMargins(0, 0, 0, 0); - buttonHBox->addStretch(); - - deckView = new DeckView; - connect(deckView, SIGNAL(newCardAdded(AbstractCardItem *)), this, SIGNAL(newCardAdded(AbstractCardItem *))); - connect(deckView, SIGNAL(sideboardPlanChanged()), this, SLOT(sideboardPlanChanged())); - deckView->setVisible(false); - - visualDeckStorageWidget = new VisualDeckStorageWidget(this); - connect(visualDeckStorageWidget, &VisualDeckStorageWidget::deckPreviewDoubleClicked, this, - &DeckViewContainer::replaceDeckStorageWithDeckView); - - deckViewLayout = new QVBoxLayout; - deckViewLayout->addLayout(buttonHBox); - deckViewLayout->addWidget(deckView); - deckViewLayout->addWidget(visualDeckStorageWidget); - deckViewLayout->setContentsMargins(0, 0, 0, 0); - setLayout(deckViewLayout); - - retranslateUi(); - connect(&SettingsCache::instance().shortcuts(), SIGNAL(shortCutChanged()), this, SLOT(refreshShortcuts())); - refreshShortcuts(); -} - -void DeckViewContainer::retranslateUi() -{ - loadLocalButton->setText(tr("Load deck...")); - loadRemoteButton->setText(tr("Load remote deck...")); - unloadDeckButton->setText(tr("Unload deck")); - readyStartButton->setText(tr("Ready to start")); - forceStartGameButton->setText(tr("Force start")); - updateSideboardLockButtonText(); -} - -void DeckViewContainer::setButtonsVisible(bool _visible) -{ - loadLocalButton->setVisible(_visible); - loadRemoteButton->setVisible(_visible); - readyStartButton->setVisible(_visible); - forceStartGameButton->setVisible(_visible); - sideboardLockButton->setVisible(_visible); -} - -void DeckViewContainer::updateSideboardLockButtonText() -{ - if (sideboardLockButton->getState()) { - sideboardLockButton->setText(tr("Sideboard unlocked")); - } else { - sideboardLockButton->setText(tr("Sideboard locked")); - } - // setting text on a button removes its shortcut - ShortcutsSettings &shortcuts = SettingsCache::instance().shortcuts(); - sideboardLockButton->setShortcut(shortcuts.getSingleShortcut("DeckViewContainer/sideboardLockButton")); -} - -void DeckViewContainer::refreshShortcuts() -{ - ShortcutsSettings &shortcuts = SettingsCache::instance().shortcuts(); - loadLocalButton->setShortcut(shortcuts.getSingleShortcut("DeckViewContainer/loadLocalButton")); - loadRemoteButton->setShortcut(shortcuts.getSingleShortcut("DeckViewContainer/loadRemoteButton")); - readyStartButton->setShortcut(shortcuts.getSingleShortcut("DeckViewContainer/readyStartButton")); - sideboardLockButton->setShortcut(shortcuts.getSingleShortcut("DeckViewContainer/sideboardLockButton")); -} - -void TabGame::refreshShortcuts() -{ - ShortcutsSettings &shortcuts = SettingsCache::instance().shortcuts(); - for (int i = 0; i < phaseActions.size(); ++i) { - QAction *temp = phaseActions.at(i); - switch (i) { - case 0: - temp->setShortcuts(shortcuts.getShortcut("Player/phase0")); - break; - case 1: - temp->setShortcuts(shortcuts.getShortcut("Player/phase1")); - break; - case 2: - temp->setShortcuts(shortcuts.getShortcut("Player/phase2")); - break; - case 3: - temp->setShortcuts(shortcuts.getShortcut("Player/phase3")); - break; - case 4: - temp->setShortcuts(shortcuts.getShortcut("Player/phase4")); - break; - case 5: - temp->setShortcuts(shortcuts.getShortcut("Player/phase5")); - break; - case 6: - temp->setShortcuts(shortcuts.getShortcut("Player/phase6")); - break; - case 7: - temp->setShortcuts(shortcuts.getShortcut("Player/phase7")); - break; - case 8: - temp->setShortcuts(shortcuts.getShortcut("Player/phase8")); - break; - case 9: - temp->setShortcuts(shortcuts.getShortcut("Player/phase9")); - break; - case 10: - temp->setShortcuts(shortcuts.getShortcut("Player/phase10")); - break; - default:; - } - } - - if (aNextPhase) { - aNextPhase->setShortcuts(shortcuts.getShortcut("Player/aNextPhase")); - } - if (aNextPhaseAction) { - aNextPhaseAction->setShortcuts(shortcuts.getShortcut("Player/aNextPhaseAction")); - } - if (aNextTurn) { - aNextTurn->setShortcuts(shortcuts.getShortcut("Player/aNextTurn")); - } - if (aReverseTurn) { - aReverseTurn->setShortcuts(shortcuts.getShortcut("Player/aReverseTurn")); - } - if (aRemoveLocalArrows) { - aRemoveLocalArrows->setShortcuts(shortcuts.getShortcut("Player/aRemoveLocalArrows")); - } - if (aRotateViewCW) { - aRotateViewCW->setShortcuts(shortcuts.getShortcut("Player/aRotateViewCW")); - } - if (aRotateViewCCW) { - aRotateViewCCW->setShortcuts(shortcuts.getShortcut("Player/aRotateViewCCW")); - } - if (aConcede) { - aConcede->setShortcuts(shortcuts.getShortcut("Player/aConcede")); - } - if (aLeaveGame) { - aLeaveGame->setShortcuts(shortcuts.getShortcut("Player/aLeaveGame")); - } - if (aCloseReplay) { - aCloseReplay->setShortcuts(shortcuts.getShortcut("Player/aCloseReplay")); - } - if (aResetLayout) { - aResetLayout->setShortcuts(shortcuts.getShortcut("Player/aResetLayout")); - } - if (aFocusChat) { - aFocusChat->setShortcuts(shortcuts.getShortcut("Player/aFocusChat")); - } - if (aReplaySkipForward) { - aReplaySkipForward->setShortcuts(shortcuts.getShortcut("Replays/aSkipForward")); - } - if (aReplaySkipBackward) { - aReplaySkipBackward->setShortcuts(shortcuts.getShortcut("Replays/aSkipBackward")); - } - if (aReplaySkipForwardBig) { - aReplaySkipForwardBig->setShortcuts(shortcuts.getShortcut("Replays/aSkipForwardBig")); - } - if (aReplaySkipBackwardBig) { - aReplaySkipBackwardBig->setShortcuts(shortcuts.getShortcut("Replays/aSkipBackwardBig")); - } - if (replayPlayButton) { - replayPlayButton->setShortcut(shortcuts.getSingleShortcut("Replays/playButton")); - } - if (replayFastForwardButton) { - replayFastForwardButton->setShortcut(shortcuts.getSingleShortcut("Replays/fastForwardButton")); - } -} - -void DeckViewContainer::replaceDeckStorageWithDeckView(QMouseEvent *event, DeckPreviewWidget *instance) -{ - Q_UNUSED(event); - QString deckString = instance->deckLoader->writeToString_Native(); - - if (deckString.length() > MAX_FILE_LENGTH) { - 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); - readyStartButton->setEnabled(false); - readyStartButton->setState(false); - sideboardLockButton->setEnabled(false); - sideboardLockButton->setState(false); - forceStartGameButton->setEnabled(false); - setReadyStart(false); -} - -void DeckViewContainer::loadLocalDeck() -{ - DlgLoadDeck dialog(this); - if (!dialog.exec()) - return; - - loadDeckFromFile(dialog.selectedFiles().at(0)); -} - -void DeckViewContainer::loadDeckFromFile(const QString &filePath) -{ - DeckLoader::FileFormat fmt = DeckLoader::getFormatFromName(filePath); - QString deckString; - DeckLoader deck; - - bool error = !deck.loadFromFile(filePath, fmt, true); - 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); -} - -void DeckViewContainer::loadRemoteDeck() -{ - DlgLoadRemoteDeck dlg(parentGame->getClientForPlayer(playerId), this); - if (dlg.exec()) { - Command_DeckSelect cmd; - cmd.set_deck_id(dlg.getDeckId()); - PendingCommand *pend = parentGame->prepareGameCommand(cmd); - connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this, - SLOT(deckSelectFinished(const Response &))); - parentGame->sendGameCommand(pend, playerId); - } -} - -void DeckViewContainer::deckSelectFinished(const Response &r) -{ - const Response_DeckDownload &resp = r.GetExtension(Response_DeckDownload::ext); - DeckLoader newDeck(QString::fromStdString(resp.deck())); - // 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() -{ - Command_ReadyStart cmd; - cmd.set_ready(!readyStartButton->getState()); - parentGame->sendGameCommand(cmd, playerId); -} - -void DeckViewContainer::forceStart() -{ - Command_ReadyStart cmd; - cmd.set_force_start(true); - cmd.set_ready(true); - parentGame->sendGameCommand(cmd, playerId); -} - -void DeckViewContainer::sideboardLockButtonClicked() -{ - Command_SetSideboardLock cmd; - cmd.set_locked(sideboardLockButton->getState()); - - parentGame->sendGameCommand(cmd, playerId); -} - -void DeckViewContainer::sideboardPlanChanged() -{ - Command_SetSideboardPlan cmd; - const QList &newPlan = deckView->getSideboardPlan(); - for (const auto &i : newPlan) - cmd.add_move_list()->CopyFrom(i); - parentGame->sendGameCommand(cmd, playerId); -} - -void DeckViewContainer::setReadyStart(bool ready) -{ - readyStartButton->setState(ready); - deckView->setLocked(ready || !sideboardLockButton->getState()); - sideboardLockButton->setEnabled(!readyStartButton->getState() && readyStartButton->isEnabled()); -} - -/** - * Sets the ready start to true, then sends the ready command so the server responds to the update - */ -void DeckViewContainer::readyAndUpdate() -{ - setReadyStart(true); - - Command_ReadyStart cmd; - cmd.set_ready(true); - parentGame->sendGameCommand(cmd, playerId); -} - -void DeckViewContainer::setSideboardLocked(bool locked) -{ - sideboardLockButton->setState(!locked); - deckView->setLocked(readyStartButton->getState() || !sideboardLockButton->getState()); - if (locked) - deckView->resetSideboardPlan(); -} - -void DeckViewContainer::setDeck(const DeckLoader &deck) -{ - deckView->setDeck(deck); - readyStartButton->setEnabled(true); - sideboardLockButton->setState(false); - sideboardLockButton->setEnabled(true); - forceStartGameButton->setEnabled(true); -} TabGame::TabGame(TabSupervisor *_tabSupervisor, GameReplay *_replay) : Tab(_tabSupervisor), secondsElapsed(0), hostId(-1), localPlayerId(-1), @@ -702,6 +305,105 @@ void TabGame::retranslateUi() scene->retranslateUi(); } +void TabGame::refreshShortcuts() +{ + ShortcutsSettings &shortcuts = SettingsCache::instance().shortcuts(); + for (int i = 0; i < phaseActions.size(); ++i) { + QAction *temp = phaseActions.at(i); + switch (i) { + case 0: + temp->setShortcuts(shortcuts.getShortcut("Player/phase0")); + break; + case 1: + temp->setShortcuts(shortcuts.getShortcut("Player/phase1")); + break; + case 2: + temp->setShortcuts(shortcuts.getShortcut("Player/phase2")); + break; + case 3: + temp->setShortcuts(shortcuts.getShortcut("Player/phase3")); + break; + case 4: + temp->setShortcuts(shortcuts.getShortcut("Player/phase4")); + break; + case 5: + temp->setShortcuts(shortcuts.getShortcut("Player/phase5")); + break; + case 6: + temp->setShortcuts(shortcuts.getShortcut("Player/phase6")); + break; + case 7: + temp->setShortcuts(shortcuts.getShortcut("Player/phase7")); + break; + case 8: + temp->setShortcuts(shortcuts.getShortcut("Player/phase8")); + break; + case 9: + temp->setShortcuts(shortcuts.getShortcut("Player/phase9")); + break; + case 10: + temp->setShortcuts(shortcuts.getShortcut("Player/phase10")); + break; + default:; + } + } + + if (aNextPhase) { + aNextPhase->setShortcuts(shortcuts.getShortcut("Player/aNextPhase")); + } + if (aNextPhaseAction) { + aNextPhaseAction->setShortcuts(shortcuts.getShortcut("Player/aNextPhaseAction")); + } + if (aNextTurn) { + aNextTurn->setShortcuts(shortcuts.getShortcut("Player/aNextTurn")); + } + if (aReverseTurn) { + aReverseTurn->setShortcuts(shortcuts.getShortcut("Player/aReverseTurn")); + } + if (aRemoveLocalArrows) { + aRemoveLocalArrows->setShortcuts(shortcuts.getShortcut("Player/aRemoveLocalArrows")); + } + if (aRotateViewCW) { + aRotateViewCW->setShortcuts(shortcuts.getShortcut("Player/aRotateViewCW")); + } + if (aRotateViewCCW) { + aRotateViewCCW->setShortcuts(shortcuts.getShortcut("Player/aRotateViewCCW")); + } + if (aConcede) { + aConcede->setShortcuts(shortcuts.getShortcut("Player/aConcede")); + } + if (aLeaveGame) { + aLeaveGame->setShortcuts(shortcuts.getShortcut("Player/aLeaveGame")); + } + if (aCloseReplay) { + aCloseReplay->setShortcuts(shortcuts.getShortcut("Player/aCloseReplay")); + } + if (aResetLayout) { + aResetLayout->setShortcuts(shortcuts.getShortcut("Player/aResetLayout")); + } + if (aFocusChat) { + aFocusChat->setShortcuts(shortcuts.getShortcut("Player/aFocusChat")); + } + if (aReplaySkipForward) { + aReplaySkipForward->setShortcuts(shortcuts.getShortcut("Replays/aSkipForward")); + } + if (aReplaySkipBackward) { + aReplaySkipBackward->setShortcuts(shortcuts.getShortcut("Replays/aSkipBackward")); + } + if (aReplaySkipForwardBig) { + aReplaySkipForwardBig->setShortcuts(shortcuts.getShortcut("Replays/aSkipForwardBig")); + } + if (aReplaySkipBackwardBig) { + aReplaySkipBackwardBig->setShortcuts(shortcuts.getShortcut("Replays/aSkipBackwardBig")); + } + if (replayPlayButton) { + replayPlayButton->setShortcut(shortcuts.getSingleShortcut("Replays/playButton")); + } + if (replayFastForwardButton) { + replayFastForwardButton->setShortcut(shortcuts.getSingleShortcut("Replays/fastForwardButton")); + } +} + void TabGame::closeRequest(bool forced) { if (!forced && !leaveGame()) { diff --git a/cockatrice/src/client/tabs/tab_game.h b/cockatrice/src/client/tabs/tab_game.h index 0d81a4605..4e59712c6 100644 --- a/cockatrice/src/client/tabs/tab_game.h +++ b/cockatrice/src/client/tabs/tab_game.h @@ -10,19 +10,17 @@ #include #include -#include +class DeckViewContainer; class AbstractClient; class CardDatabase; class GameView; -class DeckView; class GameScene; class CardInfoFrameWidget; class MessageLogWidget; class QTimer; class QSplitter; class QLabel; -class QPushButton; class QToolButton; class QMenu; class ZoneViewLayout; @@ -52,7 +50,6 @@ class Event_ReverseTurn; class CardZone; class AbstractCardItem; class CardItem; -class TabGame; class DeckLoader; class QVBoxLayout; class QHBoxLayout; @@ -63,64 +60,6 @@ class LineEditCompleter; class QDockWidget; class QStackedWidget; -class ToggleButton : public QPushButton -{ - Q_OBJECT -private: - bool state; -signals: - void stateChanged(); - -public: - explicit ToggleButton(QWidget *parent = nullptr); - bool getState() const - { - return state; - } - void setState(bool _state); - -protected: - void paintEvent(QPaintEvent *event) override; -}; - -class DeckViewContainer : public QWidget -{ - Q_OBJECT -private: - QVBoxLayout *deckViewLayout; - QPushButton *loadLocalButton, *loadRemoteButton, *unloadDeckButton, *forceStartGameButton; - ToggleButton *readyStartButton, *sideboardLockButton; - DeckView *deckView; - VisualDeckStorageWidget *visualDeckStorageWidget; - TabGame *parentGame; - int playerId; -private slots: - void replaceDeckStorageWithDeckView(QMouseEvent *event, DeckPreviewWidget *instance); - void loadLocalDeck(); - void loadRemoteDeck(); - void unloadDeck(); - void readyStart(); - void forceStart(); - void deckSelectFinished(const Response &r); - void sideboardPlanChanged(); - void sideboardLockButtonClicked(); - void updateSideboardLockButtonText(); - void refreshShortcuts(); -signals: - void newCardAdded(AbstractCardItem *card); - void notIdle(); - -public: - DeckViewContainer(int _playerId, TabGame *parent); - void retranslateUi(); - void setButtonsVisible(bool _visible); - void setReadyStart(bool ready); - void readyAndUpdate(); - void setSideboardLocked(bool locked); - void setDeck(const DeckLoader &deck); - void loadDeckFromFile(const QString &filePath); -}; - class TabGame : public Tab { Q_OBJECT diff --git a/cockatrice/src/deck/deck_view.cpp b/cockatrice/src/game/deckview/deck_view.cpp similarity index 99% rename from cockatrice/src/deck/deck_view.cpp rename to cockatrice/src/game/deckview/deck_view.cpp index fff52fd49..5d1e5a158 100644 --- a/cockatrice/src/deck/deck_view.cpp +++ b/cockatrice/src/game/deckview/deck_view.cpp @@ -1,9 +1,8 @@ #include "deck_view.h" -#include "../client/ui/theme_manager.h" -#include "../game/cards/card_database.h" -#include "../main.h" -#include "../settings/cache_settings.h" +#include "../../client/ui/theme_manager.h" +#include "../../game/cards/card_database.h" +#include "../../settings/cache_settings.h" #include "decklist.h" #include diff --git a/cockatrice/src/deck/deck_view.h b/cockatrice/src/game/deckview/deck_view.h similarity index 98% rename from cockatrice/src/deck/deck_view.h rename to cockatrice/src/game/deckview/deck_view.h index 88bbfdf39..9026c64cf 100644 --- a/cockatrice/src/deck/deck_view.h +++ b/cockatrice/src/game/deckview/deck_view.h @@ -1,7 +1,7 @@ #ifndef DECKVIEW_H #define DECKVIEW_H -#include "../game/cards/abstract_card_drag_item.h" +#include "../../game/cards/abstract_card_drag_item.h" #include "pb/move_card_to_zone.pb.h" #include diff --git a/cockatrice/src/game/deckview/deck_view_container.cpp b/cockatrice/src/game/deckview/deck_view_container.cpp new file mode 100644 index 000000000..bcea3bba1 --- /dev/null +++ b/cockatrice/src/game/deckview/deck_view_container.cpp @@ -0,0 +1,307 @@ +#include "deck_view_container.h" + +#include "../../client/tabs/tab_game.h" +#include "../../client/ui/picture_loader/picture_loader.h" +#include "../../deck/deck_loader.h" +#include "../../dialogs/dlg_load_deck.h" +#include "../../dialogs/dlg_load_remote_deck.h" +#include "../../server/pending_command.h" +#include "../../settings/cache_settings.h" +#include "../cards/card_database.h" +#include "../cards/card_database_manager.h" +#include "../game_scene.h" +#include "deck_view.h" +#include "pb/command_deck_select.pb.h" +#include "pb/command_ready_start.pb.h" +#include "pb/command_set_sideboard_lock.pb.h" +#include "pb/command_set_sideboard_plan.pb.h" +#include "pb/response_deck_download.pb.h" +#include "trice_limits.h" + +#include +#include +#include +#include + +ToggleButton::ToggleButton(QWidget *parent) : QPushButton(parent), state(false) +{ +} + +void ToggleButton::paintEvent(QPaintEvent *event) +{ + QPushButton::paintEvent(event); + + QPainter painter(this); + QPen pen; + pen.setWidth(3); + pen.setJoinStyle(Qt::MiterJoin); + pen.setColor(state ? Qt::green : Qt::red); + painter.setPen(pen); + painter.drawRect(QRect(1, 1, width() - 3, height() - 3)); +} + +void ToggleButton::setState(bool _state) +{ + state = _state; + emit stateChanged(); + update(); +} + +DeckViewContainer::DeckViewContainer(int _playerId, TabGame *parent) + : QWidget(nullptr), parentGame(parent), playerId(_playerId) +{ + loadLocalButton = new QPushButton; + loadRemoteButton = new QPushButton; + unloadDeckButton = new QPushButton; + unloadDeckButton->setEnabled(false); + readyStartButton = new ToggleButton; + readyStartButton->setEnabled(false); + forceStartGameButton = new QPushButton; + forceStartGameButton->setEnabled(parent->isHost()); + sideboardLockButton = new ToggleButton; + sideboardLockButton->setEnabled(false); + + connect(loadLocalButton, SIGNAL(clicked()), this, SLOT(loadLocalDeck())); + connect(readyStartButton, SIGNAL(clicked()), this, SLOT(readyStart())); + connect(unloadDeckButton, &QPushButton::clicked, this, &DeckViewContainer::unloadDeck); + connect(forceStartGameButton, &QPushButton::clicked, this, &DeckViewContainer::forceStart); + connect(sideboardLockButton, SIGNAL(clicked()), this, SLOT(sideboardLockButtonClicked())); + connect(sideboardLockButton, SIGNAL(stateChanged()), this, SLOT(updateSideboardLockButtonText())); + + if (parentGame->getIsLocalGame()) { + loadRemoteButton->setEnabled(false); + } else { + connect(loadRemoteButton, SIGNAL(clicked()), this, SLOT(loadRemoteDeck())); + } + + auto *buttonHBox = new QHBoxLayout; + buttonHBox->addWidget(loadLocalButton); + buttonHBox->addWidget(loadRemoteButton); + buttonHBox->addWidget(unloadDeckButton); + buttonHBox->addWidget(readyStartButton); + buttonHBox->addWidget(sideboardLockButton); + if (forceStartGameButton->isEnabled()) { + buttonHBox->addWidget(forceStartGameButton); + forceStartGameButton->setEnabled(false); + } + buttonHBox->setContentsMargins(0, 0, 0, 0); + buttonHBox->addStretch(); + + deckView = new DeckView; + connect(deckView, SIGNAL(newCardAdded(AbstractCardItem *)), this, SIGNAL(newCardAdded(AbstractCardItem *))); + connect(deckView, SIGNAL(sideboardPlanChanged()), this, SLOT(sideboardPlanChanged())); + deckView->setVisible(false); + + visualDeckStorageWidget = new VisualDeckStorageWidget(this); + connect(visualDeckStorageWidget, &VisualDeckStorageWidget::deckPreviewDoubleClicked, this, + &DeckViewContainer::replaceDeckStorageWithDeckView); + + deckViewLayout = new QVBoxLayout; + deckViewLayout->addLayout(buttonHBox); + deckViewLayout->addWidget(deckView); + deckViewLayout->addWidget(visualDeckStorageWidget); + deckViewLayout->setContentsMargins(0, 0, 0, 0); + setLayout(deckViewLayout); + + retranslateUi(); + connect(&SettingsCache::instance().shortcuts(), SIGNAL(shortCutChanged()), this, SLOT(refreshShortcuts())); + refreshShortcuts(); +} + +void DeckViewContainer::retranslateUi() +{ + loadLocalButton->setText(tr("Load deck...")); + loadRemoteButton->setText(tr("Load remote deck...")); + unloadDeckButton->setText(tr("Unload deck")); + readyStartButton->setText(tr("Ready to start")); + forceStartGameButton->setText(tr("Force start")); + updateSideboardLockButtonText(); +} + +void DeckViewContainer::setButtonsVisible(bool _visible) +{ + loadLocalButton->setVisible(_visible); + loadRemoteButton->setVisible(_visible); + readyStartButton->setVisible(_visible); + forceStartGameButton->setVisible(_visible); + sideboardLockButton->setVisible(_visible); +} + +void DeckViewContainer::updateSideboardLockButtonText() +{ + if (sideboardLockButton->getState()) { + sideboardLockButton->setText(tr("Sideboard unlocked")); + } else { + sideboardLockButton->setText(tr("Sideboard locked")); + } + // setting text on a button removes its shortcut + ShortcutsSettings &shortcuts = SettingsCache::instance().shortcuts(); + sideboardLockButton->setShortcut(shortcuts.getSingleShortcut("DeckViewContainer/sideboardLockButton")); +} + +void DeckViewContainer::refreshShortcuts() +{ + ShortcutsSettings &shortcuts = SettingsCache::instance().shortcuts(); + loadLocalButton->setShortcut(shortcuts.getSingleShortcut("DeckViewContainer/loadLocalButton")); + loadRemoteButton->setShortcut(shortcuts.getSingleShortcut("DeckViewContainer/loadRemoteButton")); + readyStartButton->setShortcut(shortcuts.getSingleShortcut("DeckViewContainer/readyStartButton")); + sideboardLockButton->setShortcut(shortcuts.getSingleShortcut("DeckViewContainer/sideboardLockButton")); +} + +void DeckViewContainer::replaceDeckStorageWithDeckView(QMouseEvent *event, DeckPreviewWidget *instance) +{ + Q_UNUSED(event); + QString deckString = instance->deckLoader->writeToString_Native(); + + if (deckString.length() > MAX_FILE_LENGTH) { + 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); +} + +void DeckViewContainer::unloadDeck() +{ + deckView->setVisible(false); + visualDeckStorageWidget->setVisible(true); + deckViewLayout->update(); + unloadDeckButton->setEnabled(false); + readyStartButton->setEnabled(false); + readyStartButton->setState(false); + sideboardLockButton->setEnabled(false); + sideboardLockButton->setState(false); + forceStartGameButton->setEnabled(false); + setReadyStart(false); +} + +void DeckViewContainer::loadLocalDeck() +{ + DlgLoadDeck dialog(this); + if (!dialog.exec()) + return; + + loadDeckFromFile(dialog.selectedFiles().at(0)); +} + +void DeckViewContainer::loadDeckFromFile(const QString &filePath) +{ + DeckLoader::FileFormat fmt = DeckLoader::getFormatFromName(filePath); + QString deckString; + DeckLoader deck; + + bool error = !deck.loadFromFile(filePath, fmt, true); + 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); +} + +void DeckViewContainer::loadRemoteDeck() +{ + DlgLoadRemoteDeck dlg(parentGame->getClientForPlayer(playerId), this); + if (dlg.exec()) { + Command_DeckSelect cmd; + cmd.set_deck_id(dlg.getDeckId()); + PendingCommand *pend = parentGame->prepareGameCommand(cmd); + connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this, + SLOT(deckSelectFinished(const Response &))); + parentGame->sendGameCommand(pend, playerId); + } +} + +void DeckViewContainer::deckSelectFinished(const Response &r) +{ + const Response_DeckDownload &resp = r.GetExtension(Response_DeckDownload::ext); + DeckLoader newDeck(QString::fromStdString(resp.deck())); + // 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() +{ + Command_ReadyStart cmd; + cmd.set_ready(!readyStartButton->getState()); + parentGame->sendGameCommand(cmd, playerId); +} + +void DeckViewContainer::forceStart() +{ + Command_ReadyStart cmd; + cmd.set_force_start(true); + cmd.set_ready(true); + parentGame->sendGameCommand(cmd, playerId); +} + +void DeckViewContainer::sideboardLockButtonClicked() +{ + Command_SetSideboardLock cmd; + cmd.set_locked(sideboardLockButton->getState()); + + parentGame->sendGameCommand(cmd, playerId); +} + +void DeckViewContainer::sideboardPlanChanged() +{ + Command_SetSideboardPlan cmd; + const QList &newPlan = deckView->getSideboardPlan(); + for (const auto &i : newPlan) + cmd.add_move_list()->CopyFrom(i); + parentGame->sendGameCommand(cmd, playerId); +} + +void DeckViewContainer::setReadyStart(bool ready) +{ + readyStartButton->setState(ready); + deckView->setLocked(ready || !sideboardLockButton->getState()); + sideboardLockButton->setEnabled(!readyStartButton->getState() && readyStartButton->isEnabled()); +} + +/** + * Sets the ready start to true, then sends the ready command so the server responds to the update + */ +void DeckViewContainer::readyAndUpdate() +{ + setReadyStart(true); + + Command_ReadyStart cmd; + cmd.set_ready(true); + parentGame->sendGameCommand(cmd, playerId); +} + +void DeckViewContainer::setSideboardLocked(bool locked) +{ + sideboardLockButton->setState(!locked); + deckView->setLocked(readyStartButton->getState() || !sideboardLockButton->getState()); + if (locked) + deckView->resetSideboardPlan(); +} + +void DeckViewContainer::setDeck(const DeckLoader &deck) +{ + deckView->setDeck(deck); + readyStartButton->setEnabled(true); + sideboardLockButton->setState(false); + sideboardLockButton->setEnabled(true); + forceStartGameButton->setEnabled(true); +} \ No newline at end of file diff --git a/cockatrice/src/game/deckview/deck_view_container.h b/cockatrice/src/game/deckview/deck_view_container.h new file mode 100644 index 000000000..9565b7e75 --- /dev/null +++ b/cockatrice/src/game/deckview/deck_view_container.h @@ -0,0 +1,80 @@ +#ifndef DECK_VIEW_CONTAINER_H +#define DECK_VIEW_CONTAINER_H + +#include "../../deck/deck_loader.h" + +#include + +class QVBoxLayout; +class AbstractCardItem; +class VisualDeckStorageWidget; +class DeckPreviewWidget; +class Response; +class TabGame; +class DeckView; + +/** + * Custom QButton implementation in order to have the red/green toggling square around the button + */ +class ToggleButton : public QPushButton +{ + Q_OBJECT +private: + bool state; +signals: + void stateChanged(); + +public: + explicit ToggleButton(QWidget *parent = nullptr); + bool getState() const + { + return state; + } + void setState(bool _state); + +protected: + void paintEvent(QPaintEvent *event) override; +}; + +/** + * This widget contains the deck selection view that is used before a game begins. + */ +class DeckViewContainer : public QWidget +{ + Q_OBJECT +private: + QVBoxLayout *deckViewLayout; + QPushButton *loadLocalButton, *loadRemoteButton, *unloadDeckButton, *forceStartGameButton; + ToggleButton *readyStartButton, *sideboardLockButton; + DeckView *deckView; + VisualDeckStorageWidget *visualDeckStorageWidget; + TabGame *parentGame; + int playerId; +private slots: + void replaceDeckStorageWithDeckView(QMouseEvent *event, DeckPreviewWidget *instance); + void loadLocalDeck(); + void loadRemoteDeck(); + void unloadDeck(); + void readyStart(); + void forceStart(); + void deckSelectFinished(const Response &r); + void sideboardPlanChanged(); + void sideboardLockButtonClicked(); + void updateSideboardLockButtonText(); + void refreshShortcuts(); +signals: + void newCardAdded(AbstractCardItem *card); + void notIdle(); + +public: + DeckViewContainer(int _playerId, TabGame *parent); + void retranslateUi(); + void setButtonsVisible(bool _visible); + void setReadyStart(bool ready); + void readyAndUpdate(); + void setSideboardLocked(bool locked); + void setDeck(const DeckLoader &deck); + void loadDeckFromFile(const QString &filePath); +}; + +#endif // DECK_VIEW_CONTAINER_H