[Client] Add tournament UI for creating and following lobby tournaments

Wires the tournament protocol into the client:
- DlgCreateGame gains a tournament checkbox with a games-per-match
  settings sub-dialog; both values are sent with Command_CreateGame and
  mirrored in the join-info variant of the dialog
- TournamentWidget renders live standings (with deck-submission state)
  and pairings for the local player's perspective, and asks to open the
  current match game via openMatchGameRequested()
- TournamentTabGameExtension attaches an overview page to TabGame's
  stacked views, mirrors phase and submission progress onto a deck-view
  status strip, and provides round-trip navigation between game view and
  standings; hosts get an in-game settings dialog during deck building
- Open-match falls back to joining as spectator through TabSupervisor;
  sub-games now return to their parent tab on close, falling back to
  the normal leave-game flow when the parent is gone
This commit is contained in:
Lukas Brübach 2026-08-24 12:04:00 +02:00 • committed by GitHub
parent 8f6d18df10
commit c5fd10087a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 719 additions and 3 deletions

View file

@ -0,0 +1,57 @@
#ifndef TOURNAMENT_TAB_GAME_EXTENSION_H
#define TOURNAMENT_TAB_GAME_EXTENSION_H
#include <QObject>
#include <QPointer>
#include <libcockatrice/protocol/pb/event_tournament_state.pb.h>
class QLabel;
class QPushButton;
class QWidget;
class TournamentWidget;
class TabGame;
/**
* @class TournamentTabGameExtension
* @ingroup GameViews
* @brief Attaches tournament behavior to a TabGame hosting a tournament hub game.
*
* Owns the tournament overview page inside the tab's stacked main widget,
* mirrors tournament state onto the always-visible deck-view status strip,
* and routes user intents (open match game, change settings, switch pages)
* between the two views.
*/
class TournamentTabGameExtension : public QObject
{
Q_OBJECT
public:
explicit TournamentTabGameExtension(TabGame *parent);
void initializeTournamentMode();
void retranslateUi();
private slots:
void onTournamentStateChanged(const Event_TournamentState &state);
void showTournamentSettingsDialog();
void showOverviewPage();
void showDeckViewPage();
void openMatchGame(int gameId);
private:
void connectSignals();
[[nodiscard]] bool isLocalPlayerHost() const;
void updateDeckViewStrip(const Event_TournamentState &state);
void updateNavigationButtons(const Event_TournamentState &state);
QPointer<TabGame> tabGame;
TournamentWidget *tournamentWidget = nullptr;
QWidget *tournamentOverviewWidget = nullptr;
QPushButton *backToGameButton = nullptr;
QPushButton *standingsButton = nullptr;
QPushButton *settingsButton = nullptr;
QLabel *deckViewStatusLabel = nullptr;
Event_TournamentState::TournamentPhase lastKnownPhase = Event_TournamentState::PHASE_DECK_BUILDING;
bool hasLastKnownPhase = false;
};
#endif // TOURNAMENT_TAB_GAME_EXTENSION_H