From 7bed1dc908accc39733031cd6f06409541eb0809 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20Br=C3=BCbach?= Date: Wed, 18 Jun 2025 22:33:55 +0200 Subject: [PATCH] Background and buttons and styles. --- cockatrice/cockatrice.qrc | 2 + .../ui/widgets/general/home_styled_button.cpp | 97 +++++++++++++++---- .../ui/widgets/general/home_styled_button.h | 8 +- .../client/ui/widgets/general/home_widget.cpp | 97 ++++++++++++++++--- .../client/ui/widgets/general/home_widget.h | 2 + 5 files changed, 173 insertions(+), 33 deletions(-) diff --git a/cockatrice/cockatrice.qrc b/cockatrice/cockatrice.qrc index 67cde480e..88d1e62dc 100644 --- a/cockatrice/cockatrice.qrc +++ b/cockatrice/cockatrice.qrc @@ -47,6 +47,8 @@ resources/icons/mana/U.svg resources/icons/mana/W.svg + resources/backgrounds/home.png + resources/config/general.svg resources/config/appearance.svg resources/config/interface.svg diff --git a/cockatrice/src/client/ui/widgets/general/home_styled_button.cpp b/cockatrice/src/client/ui/widgets/general/home_styled_button.cpp index 975dd6c5d..e9a29c3ad 100644 --- a/cockatrice/src/client/ui/widgets/general/home_styled_button.cpp +++ b/cockatrice/src/client/ui/widgets/general/home_styled_button.cpp @@ -1,25 +1,82 @@ #include "home_styled_button.h" -HomeStyledButton::HomeStyledButton(const QString &text, QWidget *parent) : QPushButton(text, parent) +#include +#include +#include + +HomeStyledButton::HomeStyledButton(const QString &text, QPair _gradientColors, QWidget *parent) + : QPushButton(text, parent), gradientColors(_gradientColors) { 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); - } -)"); + setMinimumHeight(100); // or higher if needed + setStyleSheet(generateButtonStylesheet(gradientColors)); } + +QString HomeStyledButton::generateButtonStylesheet(const QPair &colors) +{ + QColor base1 = colors.first; + QColor base2 = colors.second; + + QColor hover1 = base1.lighter(120); // 20% lighter + QColor hover2 = base2.lighter(120); + + QColor pressed1 = base1.darker(130); // 30% darker + QColor pressed2 = base2.darker(130); + + return QString(R"( + QPushButton { + font-size: 34px; + padding: 30px; + color: white; + border: 2px solid %1; + border-radius: 6px; + background: qlineargradient(x1:0, y1:1, x2:0, y2:0, + stop:0 %2, stop:1 %3); + } + QPushButton:hover { + background: qlineargradient(x1:0, y1:1, x2:0, y2:0, + stop:0 %4, stop:1 %5); + } + QPushButton:pressed { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 %6, stop:1 %7); + } + )") + .arg(base1.name()) // border color + .arg(base1.name()) // normal gradient start + .arg(base2.name()) // normal gradient end + .arg(hover1.name()) // hover start + .arg(hover2.name()) // hover end + .arg(pressed1.name()) // pressed start + .arg(pressed2.name()); // pressed end +} + +void HomeStyledButton::paintEvent(QPaintEvent *event) +{ + QString originalText = text(); + setText(""); // Prevent QPushButton from drawing the text + + QPushButton::paintEvent(event); // Draw background, borders, etc. + + setText(originalText); // Restore text for internal logic + + QPainter painter(this); + painter.setRenderHint(QPainter::Antialiasing); + painter.setRenderHint(QPainter::TextAntialiasing); + + QFont font = this->font(); + font.setBold(true); + painter.setFont(font); + + QFontMetrics fm(font); + QSize textSize = fm.size(Qt::TextSingleLine, originalText); + QPointF center((width() - textSize.width()) / 2.0, (height() + textSize.height() / 2.0) / 2.0); + + QPainterPath path; + path.addText(center, font, originalText); + + painter.setPen(QPen(Qt::black, 2.0, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); + painter.setBrush(Qt::white); + painter.drawPath(path); +} + diff --git a/cockatrice/src/client/ui/widgets/general/home_styled_button.h b/cockatrice/src/client/ui/widgets/general/home_styled_button.h index 5020e61a5..2b71dbe7f 100644 --- a/cockatrice/src/client/ui/widgets/general/home_styled_button.h +++ b/cockatrice/src/client/ui/widgets/general/home_styled_button.h @@ -10,7 +10,13 @@ class HomeStyledButton : public QPushButton { Q_OBJECT public: - HomeStyledButton(const QString &text, QWidget *parent = nullptr); + HomeStyledButton(const QString &text, QPair gradientColors, QWidget *parent = nullptr); + QString generateButtonStylesheet(const QPair &colors); +public slots: + void paintEvent(QPaintEvent *event) override; + +private: + QPair gradientColors; }; #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 index 956d3d5e1..5791a590a 100644 --- a/cockatrice/src/client/ui/widgets/general/home_widget.cpp +++ b/cockatrice/src/client/ui/widgets/general/home_widget.cpp @@ -4,6 +4,7 @@ #include "home_styled_button.h" #include +#include #include #include @@ -12,6 +13,8 @@ HomeWidget::HomeWidget(QWidget *parent, TabSupervisor *_tabSupervisor) { layout = new QGridLayout(this); + gradientColors = extractDominantColors(background); + 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); @@ -32,6 +35,7 @@ QGroupBox *HomeWidget::createSettingsButtonGroup(const QString &title) QGroupBox { font-size: 20px; color: white; /* Title text color */ + background: transparent; } QGroupBox::title { @@ -42,7 +46,7 @@ QGroupBox *HomeWidget::createSettingsButtonGroup(const QString &title) )"); QVBoxLayout *layout = new QVBoxLayout; layout->setAlignment(Qt::AlignHCenter); // Center widgets horizontally - layout->addWidget(new HomeStyledButton("Settings")); + layout->addWidget(new HomeStyledButton("Settings", gradientColors)); box->setLayout(layout); return box; } @@ -54,6 +58,7 @@ QGroupBox *HomeWidget::createUpdatesButtonGroup(const QString &title) QGroupBox { font-size: 20px; color: white; /* Title text color */ + background: transparent; } QGroupBox::title { @@ -64,7 +69,7 @@ QGroupBox *HomeWidget::createUpdatesButtonGroup(const QString &title) )"); QVBoxLayout *layout = new QVBoxLayout; layout->setAlignment(Qt::AlignHCenter); // Center widgets horizontally - layout->addWidget(new HomeStyledButton("Updates")); + layout->addWidget(new HomeStyledButton("Updates", gradientColors)); box->setLayout(layout); return box; } @@ -76,6 +81,7 @@ QGroupBox *HomeWidget::createNavigationButtonGroup(const QString &title) QGroupBox { font-size: 20px; color: white; /* Title text color */ + background: transparent; } QGroupBox::title { @@ -87,20 +93,24 @@ QGroupBox *HomeWidget::createNavigationButtonGroup(const QString &title) box->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); QVBoxLayout *layout = new QVBoxLayout; layout->setAlignment(Qt::AlignHCenter); // Center widgets horizontally - auto replaybutton = new HomeStyledButton("View Replays"); + auto replaybutton = new HomeStyledButton("View Replays", gradientColors); connect(replaybutton, &QPushButton::clicked, tabSupervisor, [this] { tabSupervisor->actTabReplays(true); }); layout->addWidget(replaybutton); - auto edhrecButton = new HomeStyledButton("Browse EDHRec"); + auto edhrecButton = new HomeStyledButton("Browse EDHRec", gradientColors); connect(edhrecButton, &QPushButton::clicked, tabSupervisor, &TabSupervisor::addEdhrecMainTab); layout->addWidget(edhrecButton); - auto visualDatabaseDisplayButton = new HomeStyledButton("Browse Card Database"); + auto visualDatabaseDisplayButton = new HomeStyledButton("Browse Card Database", gradientColors); connect(visualDatabaseDisplayButton, &QPushButton::clicked, tabSupervisor, &TabSupervisor::addVisualDatabaseDisplayTab); layout->addWidget(visualDatabaseDisplayButton); - auto visualDeckStorageButton = new HomeStyledButton("Browse Decks"); + auto visualDeckStorageButton = new HomeStyledButton("Browse Decks", gradientColors); connect(visualDeckStorageButton, &QPushButton::clicked, tabSupervisor, [this] { tabSupervisor->actTabVisualDeckStorage(true); }); layout->addWidget(visualDeckStorageButton); + auto visualDeckEditorButton = new HomeStyledButton("Create New Deck", gradientColors); + connect(visualDeckEditorButton, &QPushButton::clicked, tabSupervisor, + [this] { tabSupervisor->addVisualDeckEditorTab(nullptr); }); + layout->addWidget(visualDeckEditorButton); box->setLayout(layout); return box; } @@ -112,6 +122,7 @@ QGroupBox *HomeWidget::createPlayButtonGroup(const QString &title) QGroupBox { font-size: 20px; color: white; /* Title text color */ + background: transparent; } QGroupBox::title { @@ -124,27 +135,89 @@ QGroupBox *HomeWidget::createPlayButtonGroup(const QString &title) QVBoxLayout *layout = new QVBoxLayout; layout->setAlignment(Qt::AlignHCenter); // Center widgets horizontally - auto connectButton = new HomeStyledButton("Connect"); + auto connectButton = new HomeStyledButton("Connect", gradientColors); layout->addWidget(connectButton, 1); // stretch factor 1 - auto playButton = new HomeStyledButton("Play"); + auto playButton = new HomeStyledButton("Play", gradientColors); layout->addWidget(playButton, 1); box->setLayout(layout); return box; } +QPair HomeWidget::extractDominantColors(const QPixmap &pixmap) +{ + // Step 1: Downscale image for performance + QImage image = pixmap.toImage() + .scaled(64, 64, Qt::KeepAspectRatio, Qt::SmoothTransformation) + .convertToFormat(QImage::Format_RGB32); + + QMap colorCount; + + // Step 2: Count quantized colors + for (int y = 0; y < image.height(); ++y) { + const QRgb *scanLine = reinterpret_cast(image.scanLine(y)); + for (int x = 0; x < image.width(); ++x) { + QColor color = QColor::fromRgb(scanLine[x]); + + int r = color.red() & 0xF0; + int g = color.green() & 0xF0; + int b = color.blue() & 0xF0; + + QRgb quantized = qRgb(r, g, b); + colorCount[quantized]++; + } + } + + // Step 3: Sort by frequency + QVector> sortedColors; + for (auto it = colorCount.constBegin(); it != colorCount.constEnd(); ++it) { + sortedColors.append(qMakePair(it.key(), it.value())); + } + + std::sort(sortedColors.begin(), sortedColors.end(), + [](const QPair &a, const QPair &b) { return a.second > b.second; }); + + // Step 4: Pick top two distinct colors + QColor first = QColor(sortedColors.value(0).first); + QColor second = first; + + for (int i = 1; i < sortedColors.size(); ++i) { + QColor candidate = QColor(sortedColors[i].first); + if (candidate != first) { + second = candidate; + break; + } + } + + return QPair(first, second); +} + void HomeWidget::paintEvent(QPaintEvent *event) { QPainter painter(this); - // Draw background to fill the widget - painter.drawPixmap(rect(), background); + // Draw zoomed background + QSize widgetSize = size(); + QSize bgSize = background.size(); + QSize scaledSize = bgSize.scaled(widgetSize, Qt::KeepAspectRatioByExpanding); + QPoint topLeft((widgetSize.width() - scaledSize.width()) / 2, (widgetSize.height() - scaledSize.height()) / 2); + painter.drawPixmap(topLeft, + background.scaled(scaledSize, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation)); - // Draw overlay image centered + // Draw translucent black overlay with rounded corners + QRectF overlayRect(5, 5, width() - 10, height() - 10); // 5px inset + QPainterPath roundedRectPath; + roundedRectPath.addRoundedRect(overlayRect, 20, 20); // 20px corner radius + + QColor semiTransparentBlack(0, 0, 0, static_cast(255 * 0.33)); // 33% opacity + painter.setRenderHint(QPainter::Antialiasing); + painter.fillPath(roundedRectPath, semiTransparentBlack); + + // Draw centered overlay image 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 + QWidget::paintEvent(event); } \ 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 index d94110b33..048605b7c 100644 --- a/cockatrice/src/client/ui/widgets/general/home_widget.h +++ b/cockatrice/src/client/ui/widgets/general/home_widget.h @@ -17,6 +17,7 @@ public: QGroupBox *createUpdatesButtonGroup(const QString &title); QGroupBox *createNavigationButtonGroup(const QString &title); QGroupBox *createPlayButtonGroup(const QString &title); + QPair extractDominantColors(const QPixmap &pixmap); public slots: void paintEvent(QPaintEvent *event) override; @@ -26,6 +27,7 @@ private: TabSupervisor *tabSupervisor; QPixmap background; QPixmap overlay; + QPair gradientColors; }; #endif // HOME_WIDGET_H