mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-03-21 17:55:21 -05:00
Home tab to replace generic deck editor on startup (#6114)
Some checks are pending
Build Desktop / Configure (push) Waiting to run
Build Desktop / ${{matrix.distro}} ${{matrix.version}} (Debian, DEB, 13) (push) Blocked by required conditions
Build Desktop / ${{matrix.distro}} ${{matrix.version}} (Debian, DEB, skip, 11) (push) Blocked by required conditions
Build Desktop / ${{matrix.distro}} ${{matrix.version}} (Debian, DEB, skip, 12) (push) Blocked by required conditions
Build Desktop / ${{matrix.distro}} ${{matrix.version}} (Fedora, RPM, 42) (push) Blocked by required conditions
Build Desktop / ${{matrix.distro}} ${{matrix.version}} (Fedora, RPM, skip, 41) (push) Blocked by required conditions
Build Desktop / ${{matrix.distro}} ${{matrix.version}} (Ubuntu, DEB, 24.04) (push) Blocked by required conditions
Build Desktop / ${{matrix.distro}} ${{matrix.version}} (Ubuntu, DEB, skip, 22.04) (push) Blocked by required conditions
Build Desktop / ${{matrix.distro}} ${{matrix.version}} (yes, Arch, skip) (push) Blocked by required conditions
Build Desktop / macOS ${{matrix.target}}${{ matrix.soc == 'Intel' && ' Intel' || '' }}${{ matrix.type == 'Debug' && ' Debug' || '' }} (1, macos-13, Intel, 13, Release, 14.3.1) (push) Blocked by required conditions
Build Desktop / macOS ${{matrix.target}}${{ matrix.soc == 'Intel' && ' Intel' || '' }}${{ matrix.type == 'Debug' && ' Debug' || '' }} (1, macos-14, Apple, 14, Release, 15.4) (push) Blocked by required conditions
Build Desktop / macOS ${{matrix.target}}${{ matrix.soc == 'Intel' && ' Intel' || '' }}${{ matrix.type == 'Debug' && ' Debug' || '' }} (1, macos-15, Apple, 15, Release, 16.2) (push) Blocked by required conditions
Build Desktop / macOS ${{matrix.target}}${{ matrix.soc == 'Intel' && ' Intel' || '' }}${{ matrix.type == 'Debug' && ' Debug' || '' }} (macos-15, Apple, 15, Debug, 16.2) (push) Blocked by required conditions
Build Desktop / Windows ${{matrix.target}} (msvc2019_64, 5.15.*, 7) (push) Blocked by required conditions
Build Desktop / Windows ${{matrix.target}} (msvc2019_64, qtimageformats qtmultimedia qtwebsockets, 6.6.*, 10) (push) Blocked by required conditions
Build Docker Image / amd64 & arm64 (push) Waiting to run
Some checks are pending
Build Desktop / Configure (push) Waiting to run
Build Desktop / ${{matrix.distro}} ${{matrix.version}} (Debian, DEB, 13) (push) Blocked by required conditions
Build Desktop / ${{matrix.distro}} ${{matrix.version}} (Debian, DEB, skip, 11) (push) Blocked by required conditions
Build Desktop / ${{matrix.distro}} ${{matrix.version}} (Debian, DEB, skip, 12) (push) Blocked by required conditions
Build Desktop / ${{matrix.distro}} ${{matrix.version}} (Fedora, RPM, 42) (push) Blocked by required conditions
Build Desktop / ${{matrix.distro}} ${{matrix.version}} (Fedora, RPM, skip, 41) (push) Blocked by required conditions
Build Desktop / ${{matrix.distro}} ${{matrix.version}} (Ubuntu, DEB, 24.04) (push) Blocked by required conditions
Build Desktop / ${{matrix.distro}} ${{matrix.version}} (Ubuntu, DEB, skip, 22.04) (push) Blocked by required conditions
Build Desktop / ${{matrix.distro}} ${{matrix.version}} (yes, Arch, skip) (push) Blocked by required conditions
Build Desktop / macOS ${{matrix.target}}${{ matrix.soc == 'Intel' && ' Intel' || '' }}${{ matrix.type == 'Debug' && ' Debug' || '' }} (1, macos-13, Intel, 13, Release, 14.3.1) (push) Blocked by required conditions
Build Desktop / macOS ${{matrix.target}}${{ matrix.soc == 'Intel' && ' Intel' || '' }}${{ matrix.type == 'Debug' && ' Debug' || '' }} (1, macos-14, Apple, 14, Release, 15.4) (push) Blocked by required conditions
Build Desktop / macOS ${{matrix.target}}${{ matrix.soc == 'Intel' && ' Intel' || '' }}${{ matrix.type == 'Debug' && ' Debug' || '' }} (1, macos-15, Apple, 15, Release, 16.2) (push) Blocked by required conditions
Build Desktop / macOS ${{matrix.target}}${{ matrix.soc == 'Intel' && ' Intel' || '' }}${{ matrix.type == 'Debug' && ' Debug' || '' }} (macos-15, Apple, 15, Debug, 16.2) (push) Blocked by required conditions
Build Desktop / Windows ${{matrix.target}} (msvc2019_64, 5.15.*, 7) (push) Blocked by required conditions
Build Desktop / Windows ${{matrix.target}} (msvc2019_64, qtimageformats qtmultimedia qtwebsockets, 6.6.*, 10) (push) Blocked by required conditions
Build Docker Image / amd64 & arm64 (push) Waiting to run
This commit is contained in:
parent
22c8268f02
commit
93c15c8151
|
|
@ -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
|
||||
|
|
@ -84,6 +85,7 @@ set(cockatrice_SOURCES
|
|||
src/client/ui/widgets/cards/card_group_display_widgets/overlapped_card_group_display_widget.cpp
|
||||
src/client/ui/widgets/cards/card_info_display_widget.cpp
|
||||
src/client/ui/widgets/cards/card_info_frame_widget.cpp
|
||||
src/client/ui/widgets/cards/card_info_picture_art_crop_widget.cpp
|
||||
src/client/ui/widgets/cards/card_info_picture_enlarged_widget.cpp
|
||||
src/client/ui/widgets/cards/card_info_picture_widget.cpp
|
||||
src/client/ui/widgets/cards/card_info_picture_with_text_overlay_widget.cpp
|
||||
|
|
@ -100,6 +102,9 @@ 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/background_sources.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
|
||||
|
|
|
|||
|
|
@ -47,6 +47,8 @@
|
|||
<file>resources/icons/mana/U.svg</file>
|
||||
<file>resources/icons/mana/W.svg</file>
|
||||
|
||||
<file>resources/backgrounds/home.png</file>
|
||||
|
||||
<file>resources/config/general.svg</file>
|
||||
<file>resources/config/appearance.svg</file>
|
||||
<file>resources/config/interface.svg</file>
|
||||
|
|
|
|||
BIN
cockatrice/resources/backgrounds/home.png
Normal file
BIN
cockatrice/resources/backgrounds/home.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 MiB |
14
cockatrice/src/client/tabs/tab_home.cpp
Normal file
14
cockatrice/src/client/tabs/tab_home.cpp
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
#include "tab_home.h"
|
||||
|
||||
#include <QGroupBox>
|
||||
#include <QPushButton>
|
||||
|
||||
TabHome::TabHome(TabSupervisor *_tabSupervisor, AbstractClient *_client) : Tab(_tabSupervisor), client(_client)
|
||||
{
|
||||
homeWidget = new HomeWidget(this, tabSupervisor);
|
||||
setCentralWidget(homeWidget);
|
||||
}
|
||||
|
||||
void TabHome::retranslateUi()
|
||||
{
|
||||
}
|
||||
29
cockatrice/src/client/tabs/tab_home.h
Normal file
29
cockatrice/src/client/tabs/tab_home.h
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
#ifndef TAB_HOME_H
|
||||
#define TAB_HOME_H
|
||||
|
||||
#include "../../server/abstract_client.h"
|
||||
#include "../ui/widgets/general/home_widget.h"
|
||||
#include "tab.h"
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <qgroupbox.h>
|
||||
|
||||
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
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -735,6 +740,17 @@ void TabSupervisor::roomLeft(TabRoom *tab)
|
|||
removeTab(indexOf(tab));
|
||||
}
|
||||
|
||||
void TabSupervisor::switchToFirstAvailableNetworkTab()
|
||||
{
|
||||
if (!roomTabs.isEmpty()) {
|
||||
setCurrentWidget(roomTabs.first());
|
||||
} else if (tabServer) {
|
||||
setCurrentWidget(tabServer);
|
||||
} else {
|
||||
openTabServer();
|
||||
}
|
||||
}
|
||||
|
||||
void TabSupervisor::openReplay(GameReplay *replay)
|
||||
{
|
||||
auto *replayTab = new TabGame(this, replay);
|
||||
|
|
@ -796,6 +812,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
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ class AbstractClient;
|
|||
class Tab;
|
||||
class TabServer;
|
||||
class TabRoom;
|
||||
class TabHome;
|
||||
class TabGame;
|
||||
class TabDeckStorage;
|
||||
class TabReplays;
|
||||
|
|
@ -167,15 +168,16 @@ public slots:
|
|||
TabEdhRecMain *addEdhrecMainTab();
|
||||
TabEdhRec *addEdhrecTab(const CardInfoPtr &cardToQuery, bool isCommander = false);
|
||||
void openReplay(GameReplay *replay);
|
||||
void switchToFirstAvailableNetworkTab();
|
||||
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 +201,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);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,41 @@
|
|||
#include "card_info_picture_art_crop_widget.h"
|
||||
|
||||
#include "../../picture_loader/picture_loader.h"
|
||||
|
||||
CardInfoPictureArtCropWidget::CardInfoPictureArtCropWidget(QWidget *parent)
|
||||
: CardInfoPictureWidget(parent, false, false)
|
||||
{
|
||||
hide();
|
||||
}
|
||||
|
||||
QPixmap CardInfoPictureArtCropWidget::getProcessedBackground(const QSize &targetSize)
|
||||
{
|
||||
// Load the full-resolution card image, not a pre-scaled one
|
||||
QPixmap fullResPixmap;
|
||||
if (getCard()) {
|
||||
PictureLoader::getPixmap(fullResPixmap, getCard(), QSize(745, 1040)); // or a high default size
|
||||
} else {
|
||||
PictureLoader::getCardBackPixmap(fullResPixmap, QSize(745, 1040));
|
||||
}
|
||||
|
||||
// Fail-safe if loading failed
|
||||
if (fullResPixmap.isNull()) {
|
||||
return QPixmap(targetSize);
|
||||
}
|
||||
|
||||
const QSize sz = fullResPixmap.size();
|
||||
|
||||
int marginX = sz.width() * 0.07;
|
||||
int topMargin = sz.height() * 0.11;
|
||||
int bottomMargin = sz.height() * 0.45;
|
||||
|
||||
QRect foilRect(marginX, topMargin, sz.width() - 2 * marginX, sz.height() - topMargin - bottomMargin);
|
||||
|
||||
foilRect = foilRect.intersected(fullResPixmap.rect()); // always clamp to source bounds
|
||||
|
||||
// Crop first, then scale for best quality
|
||||
QPixmap cropped = fullResPixmap.copy(foilRect);
|
||||
QPixmap scaled = cropped.scaled(targetSize, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation);
|
||||
|
||||
return scaled;
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
#ifndef CARD_INFO_PICTURE_ART_CROP_WIDGET_H
|
||||
#define CARD_INFO_PICTURE_ART_CROP_WIDGET_H
|
||||
|
||||
#include "card_info_picture_widget.h"
|
||||
|
||||
class CardInfoPictureArtCropWidget : public CardInfoPictureWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit CardInfoPictureArtCropWidget(QWidget *parent = nullptr);
|
||||
|
||||
// Returns a processed (cropped & scaled) version of the pixmap
|
||||
QPixmap getProcessedBackground(const QSize &targetSize);
|
||||
};
|
||||
|
||||
#endif // CARD_INFO_PICTURE_ART_CROP_WIDGET_H
|
||||
|
|
@ -65,8 +65,10 @@ CardInfoPictureWidget::CardInfoPictureWidget(QWidget *parent, const bool _hoverT
|
|||
|
||||
CardInfoPictureWidget::~CardInfoPictureWidget()
|
||||
{
|
||||
enlargedPixmapWidget->hide();
|
||||
enlargedPixmapWidget->deleteLater();
|
||||
if (enlargedPixmapWidget) {
|
||||
enlargedPixmapWidget->hide();
|
||||
enlargedPixmapWidget->deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ private:
|
|||
bool hoverToZoomEnabled;
|
||||
bool raiseOnEnter;
|
||||
int hoverActivateThresholdInMs = 500;
|
||||
CardInfoPictureEnlargedWidget *enlargedPixmapWidget;
|
||||
CardInfoPictureEnlargedWidget *enlargedPixmapWidget = nullptr;
|
||||
int enlargedPixmapOffset = 10;
|
||||
QTimer *hoverTimer;
|
||||
QPropertyAnimation *animation;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
#include "background_sources.h"
|
||||
|
||||
// Required so moc generates Q_OBJECT macros
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
#ifndef COCKATRICE_BACKGROUND_SOURCES_H
|
||||
#define COCKATRICE_BACKGROUND_SOURCES_H
|
||||
|
||||
#include <QList>
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
|
||||
class BackgroundSources
|
||||
{
|
||||
Q_GADGET
|
||||
public:
|
||||
enum Type
|
||||
{
|
||||
Theme,
|
||||
RandomCardArt,
|
||||
DeckFileArt
|
||||
};
|
||||
Q_ENUM(Type)
|
||||
|
||||
struct Entry
|
||||
{
|
||||
Type type;
|
||||
const char *id; // stable ID for settings
|
||||
const char *trKey; // key for translation
|
||||
};
|
||||
|
||||
static QList<Entry> all()
|
||||
{
|
||||
return {{Theme, "theme", QT_TR_NOOP("Theme")},
|
||||
{RandomCardArt, "random_card_art", QT_TR_NOOP("Art crop of random card")},
|
||||
{DeckFileArt, "deck_file_art", QT_TR_NOOP("Art crop of background.cod deck file")}};
|
||||
}
|
||||
|
||||
static QString toId(Type type)
|
||||
{
|
||||
for (const auto &e : all()) {
|
||||
if (e.type == type)
|
||||
return e.id;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
static Type fromId(const QString &id)
|
||||
{
|
||||
for (const auto &e : all()) {
|
||||
if (id == e.id)
|
||||
return e.type;
|
||||
}
|
||||
return Theme; // default
|
||||
}
|
||||
|
||||
static QString toDisplay(Type type)
|
||||
{
|
||||
for (const auto &e : all()) {
|
||||
if (e.type == type)
|
||||
return QObject::tr(e.trKey);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
#endif // COCKATRICE_BACKGROUND_SOURCES_H
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
#include "home_styled_button.h"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QPainterPath>
|
||||
#include <qgraphicseffect.h>
|
||||
|
||||
HomeStyledButton::HomeStyledButton(const QString &text, QPair<QColor, QColor> _gradientColors, QWidget *parent)
|
||||
: QPushButton(text, parent), gradientColors(_gradientColors)
|
||||
{
|
||||
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
setMinimumHeight(50);
|
||||
setStyleSheet(generateButtonStylesheet(gradientColors));
|
||||
}
|
||||
|
||||
void HomeStyledButton::updateStylesheet(const QPair<QColor, QColor> &colors)
|
||||
{
|
||||
gradientColors = colors;
|
||||
setStyleSheet(generateButtonStylesheet(gradientColors));
|
||||
}
|
||||
|
||||
QString HomeStyledButton::generateButtonStylesheet(const QPair<QColor, QColor> &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: 20px;
|
||||
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);
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
//
|
||||
// Created by ascor on 6/15/25.
|
||||
//
|
||||
|
||||
#ifndef HOME_STYLED_BUTTON_H
|
||||
#define HOME_STYLED_BUTTON_H
|
||||
#include <QPushButton>
|
||||
|
||||
class HomeStyledButton : public QPushButton
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
HomeStyledButton(const QString &text, QPair<QColor, QColor> gradientColors, QWidget *parent = nullptr);
|
||||
void updateStylesheet(const QPair<QColor, QColor> &colors);
|
||||
QString generateButtonStylesheet(const QPair<QColor, QColor> &colors);
|
||||
public slots:
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
|
||||
private:
|
||||
QPair<QColor, QColor> gradientColors;
|
||||
};
|
||||
|
||||
#endif // HOME_STYLED_BUTTON_H
|
||||
298
cockatrice/src/client/ui/widgets/general/home_widget.cpp
Normal file
298
cockatrice/src/client/ui/widgets/general/home_widget.cpp
Normal file
|
|
@ -0,0 +1,298 @@
|
|||
#include "home_widget.h"
|
||||
|
||||
#include "../../../../game/cards/card_database_manager.h"
|
||||
#include "../../../../server/remote/remote_client.h"
|
||||
#include "../../../../settings/cache_settings.h"
|
||||
#include "../../../tabs/tab_supervisor.h"
|
||||
#include "../../window_main.h"
|
||||
#include "background_sources.h"
|
||||
#include "home_styled_button.h"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QPainterPath>
|
||||
#include <QPushButton>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
HomeWidget::HomeWidget(QWidget *parent, TabSupervisor *_tabSupervisor)
|
||||
: QWidget(parent), tabSupervisor(_tabSupervisor), background("theme:backgrounds/home"), overlay("theme:cockatrice")
|
||||
{
|
||||
setAttribute(Qt::WA_OpaquePaintEvent);
|
||||
layout = new QGridLayout(this);
|
||||
|
||||
backgroundSourceCard = new CardInfoPictureArtCropWidget(this);
|
||||
backgroundSourceDeck = new DeckLoader();
|
||||
|
||||
backgroundSourceDeck->loadFromFile(SettingsCache::instance().getDeckPath() + "background.cod",
|
||||
DeckLoader::CockatriceFormat, false);
|
||||
|
||||
gradientColors = extractDominantColors(background);
|
||||
|
||||
layout->addWidget(createButtons(), 1, 1, Qt::AlignVCenter | Qt::AlignHCenter);
|
||||
|
||||
layout->setRowStretch(0, 1);
|
||||
layout->setRowStretch(2, 1);
|
||||
layout->setColumnStretch(0, 1);
|
||||
layout->setColumnStretch(2, 1);
|
||||
|
||||
setLayout(layout);
|
||||
|
||||
cardChangeTimer = new QTimer(this);
|
||||
connect(cardChangeTimer, &QTimer::timeout, this, &HomeWidget::updateRandomCard);
|
||||
|
||||
initializeBackgroundFromSource();
|
||||
|
||||
updateConnectButton(tabSupervisor->getClient()->getStatus());
|
||||
|
||||
connect(tabSupervisor->getClient(), &RemoteClient::statusChanged, this, &HomeWidget::updateConnectButton);
|
||||
connect(&SettingsCache::instance(), &SettingsCache::homeTabBackgroundSourceChanged, this,
|
||||
&HomeWidget::initializeBackgroundFromSource);
|
||||
}
|
||||
|
||||
void HomeWidget::initializeBackgroundFromSource()
|
||||
{
|
||||
if (CardDatabaseManager::getInstance()->getLoadStatus() != LoadStatus::Ok) {
|
||||
connect(CardDatabaseManager::getInstance(), &CardDatabase::cardDatabaseLoadingFinished, this,
|
||||
&HomeWidget::initializeBackgroundFromSource);
|
||||
return;
|
||||
}
|
||||
|
||||
auto backgroundSourceType = BackgroundSources::fromId(SettingsCache::instance().getHomeTabBackgroundSource());
|
||||
|
||||
cardChangeTimer->stop();
|
||||
|
||||
switch (backgroundSourceType) {
|
||||
case BackgroundSources::Theme:
|
||||
background = QPixmap("theme:backgrounds/home");
|
||||
updateButtonsToBackgroundColor();
|
||||
update();
|
||||
break;
|
||||
case BackgroundSources::RandomCardArt:
|
||||
cardChangeTimer->start(SettingsCache::instance().getHomeTabBackgroundShuffleFrequency() * 1000);
|
||||
break;
|
||||
case BackgroundSources::DeckFileArt:
|
||||
backgroundSourceDeck->loadFromFile(SettingsCache::instance().getDeckPath() + "background.cod",
|
||||
DeckLoader::CockatriceFormat, false);
|
||||
cardChangeTimer->start(SettingsCache::instance().getHomeTabBackgroundShuffleFrequency() * 1000);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void HomeWidget::updateRandomCard()
|
||||
{
|
||||
auto backgroundSourceType = BackgroundSources::fromId(SettingsCache::instance().getHomeTabBackgroundSource());
|
||||
|
||||
ExactCard newCard;
|
||||
|
||||
switch (backgroundSourceType) {
|
||||
case BackgroundSources::Theme:
|
||||
break;
|
||||
case BackgroundSources::RandomCardArt:
|
||||
do {
|
||||
newCard = CardDatabaseManager::getInstance()->getRandomCard();
|
||||
} while (newCard == backgroundSourceCard->getCard());
|
||||
break;
|
||||
case BackgroundSources::DeckFileArt:
|
||||
QList<CardRef> cardRefs = backgroundSourceDeck->getCardRefList();
|
||||
ExactCard oldCard = backgroundSourceCard->getCard();
|
||||
|
||||
if (!cardRefs.empty()) {
|
||||
if (cardRefs.size() == 1) {
|
||||
newCard = CardDatabaseManager::getInstance()->getCard(cardRefs.first());
|
||||
} else {
|
||||
// Keep picking until different
|
||||
do {
|
||||
int idx = QRandomGenerator::global()->bounded(cardRefs.size());
|
||||
newCard = CardDatabaseManager::getInstance()->getCard(cardRefs.at(idx));
|
||||
} while (newCard == oldCard);
|
||||
}
|
||||
} else {
|
||||
do {
|
||||
newCard = CardDatabaseManager::getInstance()->getRandomCard();
|
||||
} while (newCard == oldCard);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!newCard)
|
||||
return;
|
||||
|
||||
connect(newCard.getCardPtr().data(), &CardInfo::pixmapUpdated, this, &HomeWidget::updateBackgroundProperties);
|
||||
backgroundSourceCard->setCard(newCard);
|
||||
background = backgroundSourceCard->getProcessedBackground(size());
|
||||
}
|
||||
|
||||
void HomeWidget::updateBackgroundProperties()
|
||||
{
|
||||
background = backgroundSourceCard->getProcessedBackground(size());
|
||||
updateButtonsToBackgroundColor();
|
||||
update(); // Triggers repaint
|
||||
}
|
||||
|
||||
void HomeWidget::updateButtonsToBackgroundColor()
|
||||
{
|
||||
gradientColors = extractDominantColors(background);
|
||||
for (HomeStyledButton *button : findChildren<HomeStyledButton *>()) {
|
||||
button->updateStylesheet(gradientColors);
|
||||
button->update();
|
||||
}
|
||||
}
|
||||
|
||||
QGroupBox *HomeWidget::createButtons()
|
||||
{
|
||||
QGroupBox *box = new QGroupBox(this);
|
||||
box->setStyleSheet(R"(
|
||||
QGroupBox {
|
||||
font-size: 20px;
|
||||
color: white; /* Title text color */
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
QGroupBox::title {
|
||||
color: white;
|
||||
subcontrol-origin: margin;
|
||||
subcontrol-position: top center; /* or top left / right */
|
||||
}
|
||||
)");
|
||||
box->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
QVBoxLayout *boxLayout = new QVBoxLayout;
|
||||
boxLayout->setAlignment(Qt::AlignHCenter);
|
||||
|
||||
QLabel *logoLabel = new QLabel;
|
||||
logoLabel->setPixmap(overlay.scaledToWidth(200, Qt::SmoothTransformation));
|
||||
logoLabel->setAlignment(Qt::AlignCenter);
|
||||
boxLayout->addWidget(logoLabel);
|
||||
boxLayout->addSpacing(25);
|
||||
|
||||
connectButton = new HomeStyledButton("Connect/Play", gradientColors);
|
||||
boxLayout->addWidget(connectButton, 1);
|
||||
|
||||
auto visualDeckEditorButton = new HomeStyledButton(tr("Create New Deck"), gradientColors);
|
||||
connect(visualDeckEditorButton, &QPushButton::clicked, tabSupervisor,
|
||||
[this] { tabSupervisor->addVisualDeckEditorTab(nullptr); });
|
||||
boxLayout->addWidget(visualDeckEditorButton);
|
||||
auto visualDeckStorageButton = new HomeStyledButton(tr("Browse Decks"), gradientColors);
|
||||
connect(visualDeckStorageButton, &QPushButton::clicked, tabSupervisor,
|
||||
[this] { tabSupervisor->actTabVisualDeckStorage(true); });
|
||||
boxLayout->addWidget(visualDeckStorageButton);
|
||||
auto visualDatabaseDisplayButton = new HomeStyledButton(tr("Browse Card Database"), gradientColors);
|
||||
connect(visualDatabaseDisplayButton, &QPushButton::clicked, tabSupervisor,
|
||||
&TabSupervisor::addVisualDatabaseDisplayTab);
|
||||
boxLayout->addWidget(visualDatabaseDisplayButton);
|
||||
auto edhrecButton = new HomeStyledButton(tr("Browse EDHRec"), gradientColors);
|
||||
connect(edhrecButton, &QPushButton::clicked, tabSupervisor, &TabSupervisor::addEdhrecMainTab);
|
||||
boxLayout->addWidget(edhrecButton);
|
||||
auto replaybutton = new HomeStyledButton(tr("View Replays"), gradientColors);
|
||||
connect(replaybutton, &QPushButton::clicked, tabSupervisor, [this] { tabSupervisor->actTabReplays(true); });
|
||||
boxLayout->addWidget(replaybutton);
|
||||
if (qobject_cast<MainWindow *>(tabSupervisor->parentWidget())) {
|
||||
auto exitButton = new HomeStyledButton(tr("Quit"), gradientColors);
|
||||
connect(exitButton, &QPushButton::clicked, qobject_cast<MainWindow *>(tabSupervisor->parentWidget()),
|
||||
&MainWindow::actExit);
|
||||
boxLayout->addWidget(exitButton);
|
||||
}
|
||||
|
||||
box->setLayout(boxLayout);
|
||||
return box;
|
||||
}
|
||||
|
||||
void HomeWidget::updateConnectButton(const ClientStatus status)
|
||||
{
|
||||
connectButton->disconnect();
|
||||
switch (status) {
|
||||
case StatusConnecting:
|
||||
connectButton->setText(tr("Connecting..."));
|
||||
connectButton->setEnabled(false);
|
||||
break;
|
||||
case StatusDisconnected:
|
||||
connectButton->setText(tr("Connect"));
|
||||
connectButton->setEnabled(true);
|
||||
connect(connectButton, &QPushButton::clicked, qobject_cast<MainWindow *>(tabSupervisor->parentWidget()),
|
||||
&MainWindow::actConnect);
|
||||
break;
|
||||
case StatusLoggedIn:
|
||||
connectButton->setText(tr("Play"));
|
||||
connectButton->setEnabled(true);
|
||||
connect(connectButton, &QPushButton::clicked, tabSupervisor,
|
||||
&TabSupervisor::switchToFirstAvailableNetworkTab);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
QPair<QColor, QColor> HomeWidget::extractDominantColors(const QPixmap &pixmap)
|
||||
{
|
||||
if (SettingsCache::instance().getThemeName() == "Default" &&
|
||||
SettingsCache::instance().getHomeTabBackgroundSource() == BackgroundSources::toId(BackgroundSources::Theme)) {
|
||||
return QPair<QColor, QColor>(QColor::fromRgb(20, 140, 60), QColor::fromRgb(120, 200, 80));
|
||||
}
|
||||
|
||||
// Step 1: Downscale image for performance
|
||||
QImage image = pixmap.toImage()
|
||||
.scaled(64, 64, Qt::KeepAspectRatio, Qt::SmoothTransformation)
|
||||
.convertToFormat(QImage::Format_RGB32);
|
||||
|
||||
QMap<QRgb, int> colorCount;
|
||||
|
||||
// Step 2: Count quantized colors
|
||||
for (int y = 0; y < image.height(); ++y) {
|
||||
const QRgb *scanLine = reinterpret_cast<const QRgb *>(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<QPair<QRgb, int>> 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<QRgb, int> &a, const QPair<QRgb, int> &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<QColor, QColor>(first, second);
|
||||
}
|
||||
|
||||
void HomeWidget::paintEvent(QPaintEvent *event)
|
||||
{
|
||||
QPainter painter(this);
|
||||
|
||||
background = background.scaled(size(), Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation);
|
||||
|
||||
// Draw already-scaled background centered
|
||||
QSize widgetSize = size();
|
||||
QSize bgSize = background.size();
|
||||
QPoint topLeft((widgetSize.width() - bgSize.width()) / 2, (widgetSize.height() - bgSize.height()) / 2);
|
||||
|
||||
painter.drawPixmap(topLeft, background);
|
||||
|
||||
// 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<int>(255 * 0.33)); // 33% opacity
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
painter.fillPath(roundedRectPath, semiTransparentBlack);
|
||||
|
||||
QWidget::paintEvent(event);
|
||||
}
|
||||
42
cockatrice/src/client/ui/widgets/general/home_widget.h
Normal file
42
cockatrice/src/client/ui/widgets/general/home_widget.h
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
#ifndef HOME_WIDGET_H
|
||||
#define HOME_WIDGET_H
|
||||
#include "../../../../server/abstract_client.h"
|
||||
#include "../../../tabs/tab_supervisor.h"
|
||||
#include "../cards/card_info_picture_art_crop_widget.h"
|
||||
#include "home_styled_button.h"
|
||||
|
||||
#include <QGridLayout>
|
||||
#include <QGroupBox>
|
||||
#include <QWidget>
|
||||
|
||||
class HomeWidget : public QWidget
|
||||
{
|
||||
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
HomeWidget(QWidget *parent, TabSupervisor *tabSupervisor);
|
||||
void updateRandomCard();
|
||||
QPair<QColor, QColor> extractDominantColors(const QPixmap &pixmap);
|
||||
|
||||
public slots:
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
void initializeBackgroundFromSource();
|
||||
void updateBackgroundProperties();
|
||||
void updateButtonsToBackgroundColor();
|
||||
QGroupBox *createButtons();
|
||||
void updateConnectButton(const ClientStatus status);
|
||||
|
||||
private:
|
||||
QGridLayout *layout;
|
||||
QTimer *cardChangeTimer;
|
||||
TabSupervisor *tabSupervisor;
|
||||
QPixmap background;
|
||||
CardInfoPictureArtCropWidget *backgroundSourceCard = nullptr;
|
||||
DeckLoader *backgroundSourceDeck;
|
||||
QPixmap overlay;
|
||||
QPair<QColor, QColor> gradientColors;
|
||||
HomeStyledButton *connectButton;
|
||||
};
|
||||
|
||||
#endif // HOME_WIDGET_H
|
||||
|
|
@ -59,6 +59,8 @@ public slots:
|
|||
void actCheckCardUpdatesBackground();
|
||||
void actCheckServerUpdates();
|
||||
void actCheckClientUpdates();
|
||||
void actConnect();
|
||||
void actExit();
|
||||
private slots:
|
||||
void updateTabMenu(const QList<QMenu *> &newMenuList);
|
||||
void statusChanged(ClientStatus _status);
|
||||
|
|
@ -77,14 +79,12 @@ private slots:
|
|||
void localGameEnded();
|
||||
void pixmapCacheSizeChanged(int newSizeInMBs);
|
||||
void notifyUserAboutUpdate();
|
||||
void actConnect();
|
||||
void actDisconnect();
|
||||
void actSinglePlayer();
|
||||
void actWatchReplay();
|
||||
void actFullScreen(bool checked);
|
||||
void actRegister();
|
||||
void actSettings();
|
||||
void actExit();
|
||||
void actForgotPasswordRequest();
|
||||
void actAbout();
|
||||
void actTips();
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include "../client/tabs/tab_supervisor.h"
|
||||
#include "../client/ui/picture_loader/picture_loader.h"
|
||||
#include "../client/ui/theme_manager.h"
|
||||
#include "../client/ui/widgets/general/background_sources.h"
|
||||
#include "../deck/custom_line_edit.h"
|
||||
#include "../game/cards/card_database.h"
|
||||
#include "../game/cards/card_database_manager.h"
|
||||
|
|
@ -424,10 +425,36 @@ AppearanceSettingsPage::AppearanceSettingsPage()
|
|||
connect(&themeBox, qOverload<int>(&QComboBox::currentIndexChanged), this, &AppearanceSettingsPage::themeBoxChanged);
|
||||
connect(&openThemeButton, &QPushButton::clicked, this, &AppearanceSettingsPage::openThemeLocation);
|
||||
|
||||
for (const auto &entry : BackgroundSources::all()) {
|
||||
homeTabBackgroundSourceBox.addItem(QObject::tr(entry.trKey), QVariant::fromValue(entry.type));
|
||||
}
|
||||
|
||||
QString homeTabBackgroundSource = SettingsCache::instance().getHomeTabBackgroundSource();
|
||||
int homeTabBackgroundSourceId =
|
||||
homeTabBackgroundSourceBox.findData(BackgroundSources::fromId(homeTabBackgroundSource));
|
||||
if (homeTabBackgroundSourceId != -1) {
|
||||
homeTabBackgroundSourceBox.setCurrentIndex(homeTabBackgroundSourceId);
|
||||
}
|
||||
|
||||
connect(&homeTabBackgroundSourceBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [this]() {
|
||||
auto type = homeTabBackgroundSourceBox.currentData().value<BackgroundSources::Type>();
|
||||
SettingsCache::instance().setHomeTabBackgroundSource(BackgroundSources::toId(type));
|
||||
});
|
||||
|
||||
homeTabBackgroundShuffleFrequencySpinBox.setRange(0, 3600);
|
||||
homeTabBackgroundShuffleFrequencySpinBox.setSuffix(tr(" seconds"));
|
||||
homeTabBackgroundShuffleFrequencySpinBox.setValue(SettingsCache::instance().getHomeTabBackgroundShuffleFrequency());
|
||||
connect(&homeTabBackgroundShuffleFrequencySpinBox, qOverload<int>(&QSpinBox::valueChanged),
|
||||
&SettingsCache::instance(), &SettingsCache::setHomeTabBackgroundShuffleFrequency);
|
||||
|
||||
auto *themeGrid = new QGridLayout;
|
||||
themeGrid->addWidget(&themeLabel, 0, 0);
|
||||
themeGrid->addWidget(&themeBox, 0, 1);
|
||||
themeGrid->addWidget(&openThemeButton, 1, 1);
|
||||
themeGrid->addWidget(&homeTabBackgroundSourceLabel, 2, 0);
|
||||
themeGrid->addWidget(&homeTabBackgroundSourceBox, 2, 1);
|
||||
themeGrid->addWidget(&homeTabBackgroundShuffleFrequencyLabel, 3, 0);
|
||||
themeGrid->addWidget(&homeTabBackgroundShuffleFrequencySpinBox, 3, 1);
|
||||
|
||||
themeGroupBox = new QGroupBox;
|
||||
themeGroupBox->setLayout(themeGrid);
|
||||
|
|
@ -656,6 +683,8 @@ void AppearanceSettingsPage::retranslateUi()
|
|||
themeGroupBox->setTitle(tr("Theme settings"));
|
||||
themeLabel.setText(tr("Current theme:"));
|
||||
openThemeButton.setText(tr("Open themes folder"));
|
||||
homeTabBackgroundSourceLabel.setText(tr("Home tab background source:"));
|
||||
homeTabBackgroundShuffleFrequencyLabel.setText(tr("Home tab background shuffle frequency:"));
|
||||
|
||||
menuGroupBox->setTitle(tr("Menu settings"));
|
||||
showShortcutsCheckBox.setText(tr("Show keyboard shortcuts in right-click menus"));
|
||||
|
|
|
|||
|
|
@ -107,6 +107,10 @@ private:
|
|||
QLabel themeLabel;
|
||||
QComboBox themeBox;
|
||||
QPushButton openThemeButton;
|
||||
QLabel homeTabBackgroundSourceLabel;
|
||||
QComboBox homeTabBackgroundSourceBox;
|
||||
QLabel homeTabBackgroundShuffleFrequencyLabel;
|
||||
QSpinBox homeTabBackgroundShuffleFrequencySpinBox;
|
||||
QLabel minPlayersForMultiColumnLayoutLabel;
|
||||
QLabel maxFontSizeForCardsLabel;
|
||||
QCheckBox showShortcutsCheckBox;
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
#include <QMessageBox>
|
||||
#include <QRegularExpression>
|
||||
#include <algorithm>
|
||||
#include <qrandom.h>
|
||||
#include <utility>
|
||||
|
||||
CardDatabase::CardDatabase(QObject *parent) : QObject(parent), loadStatus(NotLoaded)
|
||||
|
|
@ -213,6 +214,19 @@ ExactCard CardDatabase::guessCard(const CardRef &cardRef) const
|
|||
return ExactCard(temp, findPrintingWithId(temp, cardRef.providerId));
|
||||
}
|
||||
|
||||
ExactCard CardDatabase::getRandomCard()
|
||||
{
|
||||
if (cards.isEmpty())
|
||||
return {};
|
||||
|
||||
const auto keys = cards.keys();
|
||||
int randomIndex = QRandomGenerator::global()->bounded(keys.size());
|
||||
const QString &randomKey = keys.at(randomIndex);
|
||||
CardInfoPtr randomCard = getCardInfo(randomKey);
|
||||
|
||||
return ExactCard{randomCard, getPreferredPrinting(randomCard)};
|
||||
}
|
||||
|
||||
CardSetPtr CardDatabase::getSet(const QString &setName)
|
||||
{
|
||||
if (sets.contains(setName)) {
|
||||
|
|
|
|||
|
|
@ -85,6 +85,7 @@ public:
|
|||
ExactCard getCardFromSameSet(const QString &cardName, const PrintingInfo &otherPrinting) const;
|
||||
|
||||
[[nodiscard]] ExactCard guessCard(const CardRef &cardRef) const;
|
||||
[[nodiscard]] ExactCard getRandomCard();
|
||||
|
||||
/*
|
||||
* Get a card by its simple name. The name will be simplified in this
|
||||
|
|
@ -98,6 +99,7 @@ public:
|
|||
return cards;
|
||||
}
|
||||
SetList getSetList() const;
|
||||
CardInfoPtr getCardFromMap(const CardNameMap &cardMap, const QString &cardName) const;
|
||||
LoadStatus loadFromFile(const QString &fileName);
|
||||
bool saveCustomTokensToFile();
|
||||
QStringList getAllMainCardTypes() const;
|
||||
|
|
|
|||
|
|
@ -217,6 +217,9 @@ SettingsCache::SettingsCache()
|
|||
|
||||
themeName = settings->value("theme/name").toString();
|
||||
|
||||
homeTabBackgroundSource = settings->value("home/background", "themed").toString();
|
||||
homeTabBackgroundShuffleFrequency = settings->value("home/background/shuffleTimer", 0).toInt();
|
||||
|
||||
tabVisualDeckStorageOpen = settings->value("tabs/visualDeckStorage", true).toBool();
|
||||
tabServerOpen = settings->value("tabs/server", true).toBool();
|
||||
tabAccountOpen = settings->value("tabs/account", true).toBool();
|
||||
|
|
@ -550,6 +553,20 @@ void SettingsCache::setThemeName(const QString &_themeName)
|
|||
emit themeChanged();
|
||||
}
|
||||
|
||||
void SettingsCache::setHomeTabBackgroundSource(const QString &_backgroundSource)
|
||||
{
|
||||
homeTabBackgroundSource = _backgroundSource;
|
||||
settings->setValue("home/background", homeTabBackgroundSource);
|
||||
emit homeTabBackgroundSourceChanged();
|
||||
}
|
||||
|
||||
void SettingsCache::setHomeTabBackgroundShuffleFrequency(int _frequency)
|
||||
{
|
||||
homeTabBackgroundShuffleFrequency = _frequency;
|
||||
settings->setValue("home/background/shuffleTimer", homeTabBackgroundShuffleFrequency);
|
||||
emit homeTabBackgroundShuffleFrequencyChanged();
|
||||
}
|
||||
|
||||
void SettingsCache::setTabVisualDeckStorageOpen(bool value)
|
||||
{
|
||||
tabVisualDeckStorageOpen = value;
|
||||
|
|
|
|||
|
|
@ -135,6 +135,8 @@ signals:
|
|||
void picsPathChanged();
|
||||
void cardDatabasePathChanged();
|
||||
void themeChanged();
|
||||
void homeTabBackgroundSourceChanged();
|
||||
void homeTabBackgroundShuffleFrequencyChanged();
|
||||
void picDownloadChanged();
|
||||
void showStatusBarChanged(bool state);
|
||||
void displayCardNamesChanged();
|
||||
|
|
@ -195,7 +197,7 @@ private:
|
|||
QByteArray setsDialogGeometry;
|
||||
QString lang;
|
||||
QString deckPath, filtersPath, replaysPath, picsPath, redirectCachePath, customPicsPath, cardDatabasePath,
|
||||
customCardDatabasePath, themesPath, spoilerDatabasePath, tokenDatabasePath, themeName;
|
||||
customCardDatabasePath, themesPath, spoilerDatabasePath, tokenDatabasePath, themeName, homeTabBackgroundSource;
|
||||
bool tabVisualDeckStorageOpen, tabServerOpen, tabAccountOpen, tabDeckStorageOpen, tabReplaysOpen, tabAdminOpen,
|
||||
tabLogOpen;
|
||||
bool checkUpdatesOnStartup;
|
||||
|
|
@ -208,6 +210,7 @@ private:
|
|||
bool notifyAboutNewVersion;
|
||||
bool showTipsOnStartup;
|
||||
QList<int> seenTips;
|
||||
int homeTabBackgroundShuffleFrequency;
|
||||
bool mbDownloadSpoilers;
|
||||
int updateReleaseChannel;
|
||||
int maxFontSize;
|
||||
|
|
@ -385,6 +388,14 @@ public:
|
|||
{
|
||||
return themeName;
|
||||
}
|
||||
QString getHomeTabBackgroundSource() const
|
||||
{
|
||||
return homeTabBackgroundSource;
|
||||
}
|
||||
int getHomeTabBackgroundShuffleFrequency() const
|
||||
{
|
||||
return homeTabBackgroundShuffleFrequency;
|
||||
}
|
||||
bool getTabVisualDeckStorageOpen() const
|
||||
{
|
||||
return tabVisualDeckStorageOpen;
|
||||
|
|
@ -947,6 +958,8 @@ public slots:
|
|||
void setSpoilerDatabasePath(const QString &_spoilerDatabasePath);
|
||||
void setTokenDatabasePath(const QString &_tokenDatabasePath);
|
||||
void setThemeName(const QString &_themeName);
|
||||
void setHomeTabBackgroundSource(const QString &_backgroundSource);
|
||||
void setHomeTabBackgroundShuffleFrequency(int _frequency);
|
||||
void setTabVisualDeckStorageOpen(bool value);
|
||||
void setTabServerOpen(bool value);
|
||||
void setTabAccountOpen(bool value);
|
||||
|
|
|
|||
|
|
@ -136,6 +136,12 @@ void SettingsCache::setTokenDatabasePath(const QString & /* _tokenDatabasePath *
|
|||
void SettingsCache::setThemeName(const QString & /* _themeName */)
|
||||
{
|
||||
}
|
||||
void SettingsCache::setHomeTabBackgroundSource(const QString & /* _backgroundSource */)
|
||||
{
|
||||
}
|
||||
void SettingsCache::setHomeTabBackgroundShuffleFrequency(int /* frequency */)
|
||||
{
|
||||
}
|
||||
void SettingsCache::setTabVisualDeckStorageOpen(bool /*value*/)
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -140,6 +140,12 @@ void SettingsCache::setTokenDatabasePath(const QString & /* _tokenDatabasePath *
|
|||
void SettingsCache::setThemeName(const QString & /* _themeName */)
|
||||
{
|
||||
}
|
||||
void SettingsCache::setHomeTabBackgroundSource(const QString & /* _backgroundSource */)
|
||||
{
|
||||
}
|
||||
void SettingsCache::setHomeTabBackgroundShuffleFrequency(int /* frequency */)
|
||||
{
|
||||
}
|
||||
void SettingsCache::setTabVisualDeckStorageOpen(bool /*value*/)
|
||||
{
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user