From aa5a6222fd0f3736ddc1c826f9e6b35068270ea9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20Br=C3=BCbach?= Date: Sun, 15 Jun 2025 17:01:00 +0200 Subject: [PATCH] Home screen. Took 2 hours 18 minutes Took 9 seconds Took 23 seconds --- cockatrice/CMakeLists.txt | 3 + cockatrice/src/client/tabs/tab_home.cpp | 14 ++ cockatrice/src/client/tabs/tab_home.h | 29 ++++ cockatrice/src/client/tabs/tab_supervisor.cpp | 13 ++ cockatrice/src/client/tabs/tab_supervisor.h | 6 +- .../ui/widgets/general/home_styled_button.cpp | 25 +++ .../ui/widgets/general/home_styled_button.h | 16 ++ .../client/ui/widgets/general/home_widget.cpp | 150 ++++++++++++++++++ .../client/ui/widgets/general/home_widget.h | 31 ++++ 9 files changed, 285 insertions(+), 2 deletions(-) create mode 100644 cockatrice/src/client/tabs/tab_home.cpp create mode 100644 cockatrice/src/client/tabs/tab_home.h create mode 100644 cockatrice/src/client/ui/widgets/general/home_styled_button.cpp create mode 100644 cockatrice/src/client/ui/widgets/general/home_styled_button.h create mode 100644 cockatrice/src/client/ui/widgets/general/home_widget.cpp create mode 100644 cockatrice/src/client/ui/widgets/general/home_widget.h diff --git a/cockatrice/CMakeLists.txt b/cockatrice/CMakeLists.txt index 01ae93962..0aba9e226 100644 --- a/cockatrice/CMakeLists.txt +++ b/cockatrice/CMakeLists.txt @@ -50,6 +50,7 @@ set(cockatrice_SOURCES src/client/tabs/tab_deck_editor.cpp src/client/tabs/tab_deck_storage.cpp src/client/tabs/tab_game.cpp + src/client/tabs/tab_home.cpp src/client/tabs/tab_logs.cpp src/client/tabs/tab_message.cpp src/client/tabs/tab_replays.cpp @@ -100,6 +101,8 @@ set(cockatrice_SOURCES src/client/ui/widgets/deck_editor/deck_editor_deck_dock_widget.cpp src/client/ui/widgets/deck_editor/deck_editor_filter_dock_widget.cpp src/client/ui/widgets/deck_editor/deck_editor_printing_selector_dock_widget.cpp + src/client/ui/widgets/general/home_styled_button.cpp + src/client/ui/widgets/general/home_widget.cpp src/client/ui/widgets/general/display/banner_widget.cpp src/client/ui/widgets/general/display/bar_widget.cpp src/client/ui/widgets/general/display/dynamic_font_size_label.cpp diff --git a/cockatrice/src/client/tabs/tab_home.cpp b/cockatrice/src/client/tabs/tab_home.cpp new file mode 100644 index 000000000..a44945315 --- /dev/null +++ b/cockatrice/src/client/tabs/tab_home.cpp @@ -0,0 +1,14 @@ +#include "tab_home.h" + +#include +#include + +TabHome::TabHome(TabSupervisor *_tabSupervisor, AbstractClient *_client) : Tab(_tabSupervisor), client(_client) +{ + homeWidget = new HomeWidget(this, tabSupervisor); + setCentralWidget(homeWidget); +} + +void TabHome::retranslateUi() +{ +} diff --git a/cockatrice/src/client/tabs/tab_home.h b/cockatrice/src/client/tabs/tab_home.h new file mode 100644 index 000000000..6af35c1b5 --- /dev/null +++ b/cockatrice/src/client/tabs/tab_home.h @@ -0,0 +1,29 @@ +#ifndef TAB_HOME_H +#define TAB_HOME_H + +#include "../game_logic/abstract_client.h" +#include "../ui/widgets/general/home_widget.h" +#include "tab.h" + +#include +#include + +class AbstractClient; + +class TabHome : public Tab +{ + Q_OBJECT +private: + AbstractClient *client; + HomeWidget *homeWidget; + +public: + TabHome(TabSupervisor *_tabSupervisor, AbstractClient *_client); + void retranslateUi() override; + QString getTabText() const override + { + return tr("Home"); + } +}; + +#endif // TAB_HOME_H diff --git a/cockatrice/src/client/tabs/tab_supervisor.cpp b/cockatrice/src/client/tabs/tab_supervisor.cpp index 9e834071c..0843c9f30 100644 --- a/cockatrice/src/client/tabs/tab_supervisor.cpp +++ b/cockatrice/src/client/tabs/tab_supervisor.cpp @@ -21,6 +21,7 @@ #include "tab_deck_editor.h" #include "tab_deck_storage.h" #include "tab_game.h" +#include "tab_home.h" #include "tab_logs.h" #include "tab_message.h" #include "tab_replays.h" @@ -312,7 +313,9 @@ static void checkAndTrigger(QAction *checkableAction, bool checked) */ void TabSupervisor::initStartupTabs() { + auto homeTab = addHomeTab(); addDeckEditorTab(nullptr); + setCurrentWidget(homeTab); if (SettingsCache::instance().getTabVisualDeckStorageOpen()) { openTabVisualDeckStorage(); @@ -501,6 +504,8 @@ void TabSupervisor::actTabVisualDeckStorage(bool checked) if (checked && !tabVisualDeckStorage) { openTabVisualDeckStorage(); setCurrentWidget(tabVisualDeckStorage); + } else if (checked && tabVisualDeckStorage) { + setCurrentWidget(tabVisualDeckStorage); } else if (!checked && tabVisualDeckStorage) { tabVisualDeckStorage->closeRequest(); } @@ -796,6 +801,14 @@ void TabSupervisor::talkLeft(TabMessage *tab) removeTab(indexOf(tab)); } +TabHome *TabSupervisor::addHomeTab() +{ + auto *tab = new TabHome(this, client); + myAddTab(tab); + setCurrentWidget(tab); + return tab; +} + /** * Creates a new deck editor tab and loads the deck into it. * Creates either a classic or visual deck editor tab depending on settings diff --git a/cockatrice/src/client/tabs/tab_supervisor.h b/cockatrice/src/client/tabs/tab_supervisor.h index 1c367043e..24cd2c012 100644 --- a/cockatrice/src/client/tabs/tab_supervisor.h +++ b/cockatrice/src/client/tabs/tab_supervisor.h @@ -26,6 +26,7 @@ class AbstractClient; class Tab; class TabServer; class TabRoom; +class TabHome; class TabGame; class TabDeckStorage; class TabReplays; @@ -168,14 +169,14 @@ public slots: TabEdhRec *addEdhrecTab(const CardInfoPtr &cardToQuery, bool isCommander = false); void openReplay(GameReplay *replay); void maximizeMainWindow(); + void actTabVisualDeckStorage(bool checked); + void actTabReplays(bool checked); private slots: void refreshShortcuts(); - void actTabVisualDeckStorage(bool checked); void actTabServer(bool checked); void actTabAccount(bool checked); void actTabDeckStorage(bool checked); - void actTabReplays(bool checked); void actTabAdmin(bool checked); void actTabLog(bool checked); @@ -199,6 +200,7 @@ private slots: void processUserLeft(const QString &userName); void processUserJoined(const ServerInfo_User &userInfo); void talkLeft(TabMessage *tab); + TabHome *addHomeTab(); void deckEditorClosed(AbstractTabDeckEditor *tab); void tabUserEvent(bool globalEvent); void updateTabText(Tab *tab, const QString &newTabText); diff --git a/cockatrice/src/client/ui/widgets/general/home_styled_button.cpp b/cockatrice/src/client/ui/widgets/general/home_styled_button.cpp new file mode 100644 index 000000000..975dd6c5d --- /dev/null +++ b/cockatrice/src/client/ui/widgets/general/home_styled_button.cpp @@ -0,0 +1,25 @@ +#include "home_styled_button.h" + +HomeStyledButton::HomeStyledButton(const QString &text, QWidget *parent) : QPushButton(text, parent) +{ + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + setStyleSheet(R"( + QPushButton { + font-size: 16px; + padding: 10px; + color: black; + border: 1px solid #0b5e2e; + border-radius: 6px; + background: qlineargradient(x1:0, y1:1, x2:0, y2:0, + stop:0 #92de58, stop:1 #139740); + } + QPushButton:hover { + background: qlineargradient(x1:0, y1:1, x2:0, y2:0, + stop:0 #aaf57a, stop:1 #1bb24e); + } + QPushButton:pressed { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #139740, stop:1 #0a4d23); + } +)"); +} diff --git a/cockatrice/src/client/ui/widgets/general/home_styled_button.h b/cockatrice/src/client/ui/widgets/general/home_styled_button.h new file mode 100644 index 000000000..5020e61a5 --- /dev/null +++ b/cockatrice/src/client/ui/widgets/general/home_styled_button.h @@ -0,0 +1,16 @@ +// +// Created by ascor on 6/15/25. +// + +#ifndef HOME_STYLED_BUTTON_H +#define HOME_STYLED_BUTTON_H +#include + +class HomeStyledButton : public QPushButton +{ + Q_OBJECT +public: + HomeStyledButton(const QString &text, QWidget *parent = nullptr); +}; + +#endif // HOME_STYLED_BUTTON_H diff --git a/cockatrice/src/client/ui/widgets/general/home_widget.cpp b/cockatrice/src/client/ui/widgets/general/home_widget.cpp new file mode 100644 index 000000000..956d3d5e1 --- /dev/null +++ b/cockatrice/src/client/ui/widgets/general/home_widget.cpp @@ -0,0 +1,150 @@ +#include "home_widget.h" + +#include "../../../tabs/tab_supervisor.h" +#include "home_styled_button.h" + +#include +#include +#include + +HomeWidget::HomeWidget(QWidget *parent, TabSupervisor *_tabSupervisor) + : QWidget(parent), tabSupervisor(_tabSupervisor), background("theme:backgrounds/home"), overlay("theme:cockatrice") +{ + layout = new QGridLayout(this); + + layout->addWidget(createSettingsButtonGroup("Settings"), 0, 0, Qt::AlignTop | Qt::AlignLeft); + layout->addWidget(createUpdatesButtonGroup("Updates"), 0, 2, Qt::AlignTop | Qt::AlignRight); + layout->addWidget(createNavigationButtonGroup("Navigation"), 2, 0, Qt::AlignBottom | Qt::AlignLeft); + layout->addWidget(createPlayButtonGroup("Play"), 2, 2, Qt::AlignBottom | Qt::AlignRight); + + layout->setRowStretch(0, 1); + layout->setRowStretch(2, 1); + layout->setColumnStretch(0, 1); + layout->setColumnStretch(2, 1); + + setLayout(layout); +} + +QGroupBox *HomeWidget::createSettingsButtonGroup(const QString &title) +{ + QGroupBox *box = new QGroupBox(title); + box->setStyleSheet(R"( + QGroupBox { + font-size: 20px; + color: white; /* Title text color */ + } + + QGroupBox::title { + color: white; + subcontrol-origin: margin; + subcontrol-position: top center; /* or top left / right */ + } +)"); + QVBoxLayout *layout = new QVBoxLayout; + layout->setAlignment(Qt::AlignHCenter); // Center widgets horizontally + layout->addWidget(new HomeStyledButton("Settings")); + box->setLayout(layout); + return box; +} + +QGroupBox *HomeWidget::createUpdatesButtonGroup(const QString &title) +{ + QGroupBox *box = new QGroupBox(title); + box->setStyleSheet(R"( + QGroupBox { + font-size: 20px; + color: white; /* Title text color */ + } + + QGroupBox::title { + color: white; + subcontrol-origin: margin; + subcontrol-position: top center; /* or top left / right */ + } +)"); + QVBoxLayout *layout = new QVBoxLayout; + layout->setAlignment(Qt::AlignHCenter); // Center widgets horizontally + layout->addWidget(new HomeStyledButton("Updates")); + box->setLayout(layout); + return box; +} + +QGroupBox *HomeWidget::createNavigationButtonGroup(const QString &title) +{ + QGroupBox *box = new QGroupBox(title); + box->setStyleSheet(R"( + QGroupBox { + font-size: 20px; + color: white; /* Title text color */ + } + + QGroupBox::title { + color: white; + subcontrol-origin: margin; + subcontrol-position: top center; /* or top left / right */ + } +)"); + box->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + QVBoxLayout *layout = new QVBoxLayout; + layout->setAlignment(Qt::AlignHCenter); // Center widgets horizontally + auto replaybutton = new HomeStyledButton("View Replays"); + connect(replaybutton, &QPushButton::clicked, tabSupervisor, [this] { tabSupervisor->actTabReplays(true); }); + layout->addWidget(replaybutton); + auto edhrecButton = new HomeStyledButton("Browse EDHRec"); + connect(edhrecButton, &QPushButton::clicked, tabSupervisor, &TabSupervisor::addEdhrecMainTab); + layout->addWidget(edhrecButton); + auto visualDatabaseDisplayButton = new HomeStyledButton("Browse Card Database"); + connect(visualDatabaseDisplayButton, &QPushButton::clicked, tabSupervisor, + &TabSupervisor::addVisualDatabaseDisplayTab); + layout->addWidget(visualDatabaseDisplayButton); + auto visualDeckStorageButton = new HomeStyledButton("Browse Decks"); + connect(visualDeckStorageButton, &QPushButton::clicked, tabSupervisor, + [this] { tabSupervisor->actTabVisualDeckStorage(true); }); + layout->addWidget(visualDeckStorageButton); + box->setLayout(layout); + return box; +} + +QGroupBox *HomeWidget::createPlayButtonGroup(const QString &title) +{ + QGroupBox *box = new QGroupBox(title); + box->setStyleSheet(R"( + QGroupBox { + font-size: 20px; + color: white; /* Title text color */ + } + + QGroupBox::title { + color: white; + subcontrol-origin: margin; + subcontrol-position: top center; /* or top left / right */ + } +)"); + box->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + QVBoxLayout *layout = new QVBoxLayout; + layout->setAlignment(Qt::AlignHCenter); // Center widgets horizontally + + auto connectButton = new HomeStyledButton("Connect"); + layout->addWidget(connectButton, 1); // stretch factor 1 + + auto playButton = new HomeStyledButton("Play"); + layout->addWidget(playButton, 1); + + box->setLayout(layout); + return box; +} + +void HomeWidget::paintEvent(QPaintEvent *event) +{ + QPainter painter(this); + + // Draw background to fill the widget + painter.drawPixmap(rect(), background); + + // Draw overlay image centered + QSize overlaySize = overlay.size(); + QPoint center((width() - overlaySize.width()) / 2, (height() - overlaySize.height()) / 2); + painter.drawPixmap(center, overlay); + + QWidget::paintEvent(event); // optional, depending on behavior +} \ No newline at end of file diff --git a/cockatrice/src/client/ui/widgets/general/home_widget.h b/cockatrice/src/client/ui/widgets/general/home_widget.h new file mode 100644 index 000000000..d94110b33 --- /dev/null +++ b/cockatrice/src/client/ui/widgets/general/home_widget.h @@ -0,0 +1,31 @@ +#ifndef HOME_WIDGET_H +#define HOME_WIDGET_H +#include "../../../tabs/tab_supervisor.h" + +#include +#include +#include + +class HomeWidget : public QWidget +{ + + Q_OBJECT + +public: + HomeWidget(QWidget *parent, TabSupervisor *tabSupervisor); + QGroupBox *createSettingsButtonGroup(const QString &title); + QGroupBox *createUpdatesButtonGroup(const QString &title); + QGroupBox *createNavigationButtonGroup(const QString &title); + QGroupBox *createPlayButtonGroup(const QString &title); + +public slots: + void paintEvent(QPaintEvent *event) override; + +private: + QGridLayout *layout; + TabSupervisor *tabSupervisor; + QPixmap background; + QPixmap overlay; +}; + +#endif // HOME_WIDGET_H