Merge branch 'master' into tooomm-qt5

This commit is contained in:
tooomm 2026-04-15 20:37:45 +02:00 committed by GitHub
commit 14618bc2ce
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
114 changed files with 4069 additions and 3286 deletions

View file

@ -1,8 +1,9 @@
#include "abstract_game.h"
#include "../interface/widgets/tabs/tab_game.h"
#include "player/player.h"
AbstractGame::AbstractGame(TabGame *_tab) : tab(_tab)
AbstractGame::AbstractGame(TabGame *_tab) : QObject(_tab), tab(_tab)
{
gameMetaInfo = new GameMetaInfo(this);
gameEventHandler = new GameEventHandler(this);

View file

@ -10,7 +10,7 @@
#include <libcockatrice/protocol/pb/command_reveal_cards.pb.h>
PlayerMenu::PlayerMenu(Player *_player) : player(_player)
PlayerMenu::PlayerMenu(Player *_player) : QObject(_player), player(_player)
{
playerMenu = new TearOffMenu();

View file

@ -37,7 +37,7 @@ private slots:
void refreshShortcuts();
public:
PlayerMenu(Player *player);
explicit PlayerMenu(Player *player);
/// Lifecycle methods: delegate to all managedComponents, plus counters separately via player->getCounters().
void retranslateUi();

View file

@ -3,6 +3,7 @@
#include "../../interface/widgets/tabs/tab_game.h"
#include "../../interface/widgets/utility/get_text_with_max.h"
#include "../board/card_item.h"
#include "../client/settings/card_counter_settings.h"
#include "../dialogs/dlg_move_top_cards_until.h"
#include "../dialogs/dlg_roll_dice.h"
#include "../zones/hand_zone.h"
@ -27,13 +28,15 @@
#include <libcockatrice/protocol/pb/command_shuffle.pb.h>
#include <libcockatrice/protocol/pb/command_undo_draw.pb.h>
#include <libcockatrice/protocol/pb/context_move_card.pb.h>
#include <libcockatrice/utility/expression.h>
#include <libcockatrice/utility/trice_limits.h>
#include <libcockatrice/utility/zone_names.h>
// milliseconds in between triggers of the move top cards until action
static constexpr int MOVE_TOP_CARD_UNTIL_INTERVAL = 100;
PlayerActions::PlayerActions(Player *_player) : player(_player), lastTokenTableRow(0), movingCardsUntil(false)
PlayerActions::PlayerActions(Player *_player)
: QObject(_player), player(_player), lastTokenTableRow(0), movingCardsUntil(false)
{
moveTopCardTimer = new QTimer(this);
moveTopCardTimer->setInterval(MOVE_TOP_CARD_UNTIL_INTERVAL);
@ -1568,23 +1571,34 @@ void PlayerActions::actCardCounterTrigger()
break;
}
case 11: { // set counter with dialog
bool ok;
player->setDialogSemaphore(true);
int oldValue = 0;
if (player->getGameScene()->selectedItems().size() == 1) {
auto *card = static_cast<CardItem *>(player->getGameScene()->selectedItems().first());
oldValue = card->getCounters().value(counterId, 0);
// If a single card is selected, we show the old value in the dialog. Otherwise, we show "x"
QList<QGraphicsItem *> sel = player->getGameScene()->selectedItems();
QString oldValueForDlg = "x";
if (sel.size() == 1) {
auto *card = dynamic_cast<CardItem *>(sel.first());
oldValueForDlg = QString::number(card->getCounters().value(counterId, 0));
}
int number = QInputDialog::getInt(player->getGame()->getTab(), tr("Set counters"), tr("Number:"), oldValue,
0, MAX_COUNTERS_ON_CARD, 1, &ok);
auto &cardCounterSettings = SettingsCache::instance().cardCounters();
QString counterName = cardCounterSettings.displayName(counterId);
AbstractCounterDialog dialog(counterName, oldValueForDlg, player->getGame()->getTab());
int ok = dialog.exec();
player->setDialogSemaphore(false);
if (player->clearCardsToDelete() || !ok) {
return;
}
for (const auto &item : player->getGameScene()->selectedItems()) {
auto *card = static_cast<CardItem *>(item);
for (const auto &item : sel) {
auto *card = dynamic_cast<CardItem *>(item);
int oldValue = card->getCounters().value(counterId, 0);
Expression exp(oldValue);
int number = static_cast<int>(exp.parse(dialog.textValue()));
auto *cmd = new Command_SetCardCounter;
cmd->set_zone(card->getZone()->getName().toStdString());
cmd->set_card_id(card->getId());

View file

@ -32,7 +32,7 @@
#include <libcockatrice/protocol/pb/event_shuffle.pb.h>
#include <libcockatrice/utility/zone_names.h>
PlayerEventHandler::PlayerEventHandler(Player *_player) : player(_player)
PlayerEventHandler::PlayerEventHandler(Player *_player) : QObject(_player), player(_player)
{
}
@ -60,7 +60,6 @@ void PlayerEventHandler::eventShuffle(const Event_Shuffle &event)
// we want to close empty views as well
if (length == 0 || length > absStart) { // note this assumes views always start at the top of the library
view->close();
break;
}
} else {
qWarning() << zone->getName() << "of" << player->getPlayerInfo()->getName() << "holds empty zoneview!";
@ -595,4 +594,4 @@ void PlayerEventHandler::processGameEvent(GameEvent::GameEventType type,
qWarning() << "unhandled game event" << type;
}
}
}
}

View file

@ -28,6 +28,7 @@ CardPictureLoader::CardPictureLoader() : QObject(nullptr)
connect(&SettingsCache::instance(), &SettingsCache::picDownloadChanged, this,
&CardPictureLoader::picDownloadChanged);
qRegisterMetaType<ExactCard>();
connect(worker, &CardPictureLoaderWorker::imageLoaded, this, &CardPictureLoader::imageLoaded);
statusBar = new CardPictureLoaderStatusBar(nullptr);

View file

@ -13,6 +13,7 @@
#include <QPrinter>
#include <QTextCursor>
#include <libcockatrice/deck_list/deck_list.h>
#include <optional>
inline Q_LOGGING_CATEGORY(DeckLoaderLog, "deck_loader");

View file

@ -12,6 +12,7 @@
#include <QMap>
#include <QPixmap>
#include <libcockatrice/network/server/remote/user_level.h>
#include <optional>
inline Q_LOGGING_CATEGORY(PixelMapGeneratorLog, "pixel_map_generator");

View file

@ -91,6 +91,10 @@ struct PaletteColorInfo
ThemeManager::ThemeManager(QObject *parent) : QObject(parent)
{
defaultStyleName = qApp->style()->objectName();
// FIXME workaround for windows11 style being broken
if (defaultStyleName == "windows11") {
defaultStyleName = "windowsvista";
}
ensureThemeDirectoryExists();
#if (QT_VERSION >= QT_VERSION_CHECK(6, 5, 0))
connect(QGuiApplication::styleHints(), &QStyleHints::colorSchemeChanged, this, &ThemeManager::themeChangedSlot);
@ -179,7 +183,7 @@ QBrush ThemeManager::loadExtraBrush(QString fileName, QBrush &fallbackBrush)
static inline QPalette createDarkGreenFusionPalette()
{
QPalette p;
QPalette p = QStyleFactory::create("Fusion")->standardPalette();
// ---------- Core backgrounds ----------
p.setColor(QPalette::Window, QColor(30, 30, 30)); // #ff1e1e1e
@ -248,7 +252,7 @@ static inline QPalette createDarkGreenFusionPalette()
static inline QPalette createLightGreenFusionPalette()
{
QPalette p;
QPalette p = QStyleFactory::create("Fusion")->standardPalette();
// ---------- Core backgrounds ----------
p.setColor(QPalette::Window, QColor(240, 240, 240)); // #fff0f0f0
@ -332,13 +336,15 @@ void ThemeManager::themeChangedSlot()
}
if (themeName == FUSION_THEME_NAME) {
qApp->setStyle(QStyleFactory::create("Fusion"));
QStyle *fusionStyle = QStyleFactory::create("Fusion");
qApp->setStyle(fusionStyle);
#if (QT_VERSION >= QT_VERSION_CHECK(6, 5, 0))
QPalette palette;
// Start from Fusion's own palette so dark mode is handled correctly,
// then apply any tweaks on top of it.
QPalette palette = fusionStyle->standardPalette();
if (QGuiApplication::styleHints()->colorScheme() == Qt::ColorScheme::Dark) {
palette.setColor(QPalette::AlternateBase, QColor(53, 53, 53));
}
qApp->setPalette(palette);
#endif
} else if (themeName == FUSION_THEME_NAME_LIGHT) {
@ -348,7 +354,7 @@ void ThemeManager::themeChangedSlot()
qApp->setStyle(QStyleFactory::create("Fusion"));
qApp->setPalette(createDarkGreenFusionPalette());
} else {
qApp->setStyle(defaultStyleName); // setting the style also sets the palette
qApp->setStyle(QStyleFactory::create(defaultStyleName)); // setting the style also sets the palette
}
if (dirPath.isEmpty()) {

View file

@ -339,11 +339,9 @@ void CardInfoPictureWidget::mousePressEvent(QMouseEvent *event)
QWidget::mousePressEvent(event);
if (event->button() == Qt::RightButton) {
createRightClickMenu()->popup(QCursor::pos());
} else {
emit cardClicked();
}
emit cardClicked();
emit cardClicked(event);
}
void CardInfoPictureWidget::hideEvent(QHideEvent *event)

View file

@ -43,7 +43,7 @@ signals:
void hoveredOnCard(const ExactCard &hoveredCard);
void cardScaleFactorChanged(int _scale);
void cardChanged(const ExactCard &card);
void cardClicked();
void cardClicked(QMouseEvent *event);
protected:
void resizeEvent(QResizeEvent *event) override;

View file

@ -20,7 +20,6 @@ ResizablePanel::ResizablePanel(const QString &_typeId, AbstractAnalyticsPanelWid
frame = new QFrame(this);
frame->setFrameShape(QFrame::Box);
frame->setLineWidth(2);
frame->setStyleSheet("border: none;");
auto *frameLayout = new QVBoxLayout(frame);
frameLayout->setContentsMargins(0, 0, 0, 0);
@ -30,15 +29,13 @@ ResizablePanel::ResizablePanel(const QString &_typeId, AbstractAnalyticsPanelWid
frameLayout->addWidget(analyticsPanel);
dropIndicator = new QFrame(frame);
dropIndicator->setStyleSheet("background-color: #3daee9;");
dropIndicator->setFixedHeight(3);
dropIndicator->hide(); // hidden by default
dropIndicator->raise(); // make sure it's above children
selectionOverlay = new QFrame(frame);
selectionOverlay->setStyleSheet("background-color: rgba(61,174,233,50);"); // semi-transparent blue
selectionOverlay->hide(); // hidden by default
selectionOverlay->raise(); // make sure it is above children
selectionOverlay->hide(); // hidden by default
selectionOverlay->raise(); // make sure it is above children
selectionOverlay->setAttribute(Qt::WA_TransparentForMouseEvents);
// Bottom bar with drag button and resize handle
@ -51,24 +48,41 @@ ResizablePanel::ResizablePanel(const QString &_typeId, AbstractAnalyticsPanelWid
dragButton = new QPushButton("", bottomBar);
dragButton->setFixedSize(40, 8);
dragButton->setCursor(Qt::OpenHandCursor);
dragButton->setStyleSheet("QPushButton { "
"background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #4a4a4a, stop:1 #3a3a3a); "
"border: none; color: #888; font-size: 10px; }"
"QPushButton:hover { background: #5a5a5a; }");
bottomLayout->addWidget(dragButton);
// Resize handle fills the rest
resizeHandle = new QWidget(bottomBar);
resizeHandle->setFixedHeight(8);
resizeHandle->setCursor(Qt::SizeVerCursor);
resizeHandle->setStyleSheet("background: qlineargradient(x1:0, y1:0, x2:0, y2:1, "
"stop:0 #3a3a3a, stop:1 #2a2a2a);");
bottomLayout->addWidget(resizeHandle, 1);
frameLayout->addWidget(bottomBar);
mainLayout->addWidget(frame);
const QPalette &pal = QApplication::palette();
QColor mid = pal.color(QPalette::Mid);
QColor dark = pal.color(QPalette::Dark);
QColor midLight = pal.color(QPalette::Midlight);
QColor shadow = pal.color(QPalette::Shadow);
QColor placeholderText = pal.color(QPalette::PlaceholderText);
frame->setStyleSheet("QFrame { border: none; }");
dropIndicator->setStyleSheet("QFrame { background-color: #3daee9; }");
selectionOverlay->setStyleSheet("QFrame { background-color: rgba(61,174,233,50); }");
dragButton->setStyleSheet(QString("QPushButton { "
"background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 %1, stop:1 %2); "
"border: none; color: %3; font-size: 10px; }"
"QPushButton:hover { background: %4; }")
.arg(mid.name(), dark.name(), placeholderText.name(), midLight.name()));
resizeHandle->setStyleSheet(QString("QWidget { background: qlineargradient(x1:0, y1:0, x2:0, y2:1, "
"stop:0 %1, stop:1 %2); }")
.arg(dark.name(), shadow.name()));
// Set size policy
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);

View file

@ -1775,7 +1775,7 @@ DlgSettings::DlgSettings(QWidget *parent) : QDialog(parent)
contentsWidget->setSpacing(5);
pagesWidget = new QStackedWidget;
pagesWidget->addWidget(new GeneralSettingsPage);
pagesWidget->addWidget(makeScrollable(new GeneralSettingsPage));
pagesWidget->addWidget(makeScrollable(new AppearanceSettingsPage));
pagesWidget->addWidget(makeScrollable(new UserInterfaceSettingsPage));
pagesWidget->addWidget(new DeckEditorSettingsPage);

View file

@ -3,6 +3,7 @@
#include "../../../../../general/display/background_plate_widget.h"
#include "../../tab_edhrec_main.h"
#include <QMouseEvent>
#include <libcockatrice/card/database/card_database_manager.h>
EdhrecApiResponseCardDetailsDisplayWidget::EdhrecApiResponseCardDetailsDisplayWidget(
@ -48,7 +49,7 @@ EdhrecApiResponseCardDetailsDisplayWidget::EdhrecApiResponseCardDetailsDisplayWi
if (parentTab) {
cardPictureWidget->setScaleFactor(parentTab->getCardSizeSlider()->getSlider()->value());
connect(cardPictureWidget, &CardInfoPictureWidget::cardClicked, this,
&EdhrecApiResponseCardDetailsDisplayWidget::actRequestPageNavigation);
&EdhrecApiResponseCardDetailsDisplayWidget::mousePressEvent);
connect(parentTab->getCardSizeSlider()->getSlider(), &QSlider::valueChanged, cardPictureWidget,
&CardInfoPictureWidget::setScaleFactor);
connect(this, &EdhrecApiResponseCardDetailsDisplayWidget::requestUrl, parentTab,
@ -59,7 +60,9 @@ EdhrecApiResponseCardDetailsDisplayWidget::EdhrecApiResponseCardDetailsDisplayWi
void EdhrecApiResponseCardDetailsDisplayWidget::mousePressEvent(QMouseEvent *event)
{
QWidget::mousePressEvent(event);
actRequestPageNavigation();
if (event->button() == Qt::LeftButton) {
actRequestPageNavigation();
}
}
void EdhrecApiResponseCardDetailsDisplayWidget::enterEvent(QEnterEvent *event)

View file

@ -30,6 +30,8 @@
#include <libcockatrice/protocol/pb/response_replay_get_code.pb.h>
#include <libcockatrice/protocol/pending_command.h>
inline Q_LOGGING_CATEGORY(TabReplaysLog, "replays_tab");
TabReplays::TabReplays(TabSupervisor *_tabSupervisor, AbstractClient *_client, const ServerInfo_User *currentUserInfo)
: Tab(_tabSupervisor), client(_client)
{
@ -265,9 +267,11 @@ void TabReplays::actOpenLocalReplay()
f.close();
GameReplay *replay = new GameReplay;
replay->ParseFromArray(_data.data(), _data.size());
emit openReplay(replay);
if (replay->ParseFromArray(_data.data(), _data.size())) {
emit openReplay(replay);
} else {
qCWarning(TabReplaysLog) << "could not parse replay!";
}
}
}
@ -379,9 +383,12 @@ void TabReplays::openRemoteReplayFinished(const Response &r)
const Response_ReplayDownload &resp = r.GetExtension(Response_ReplayDownload::ext);
GameReplay *replay = new GameReplay;
replay->ParseFromString(resp.replay_data());
if (replay->ParseFromString(resp.replay_data())) {
emit openReplay(replay);
emit openReplay(replay);
} else {
qCWarning(TabReplaysLog) << "could not parse remote replay!";
}
}
void TabReplays::actDownload()

View file

@ -84,6 +84,7 @@
const QString MainWindow::appName = "Cockatrice";
const QStringList MainWindow::fileNameFilters = QStringList() << QObject::tr("Cockatrice card database (*.xml)")
<< QObject::tr("All files (*.*)");
inline Q_LOGGING_CATEGORY(MainWindowLog, "main_window");
/**
* Replaces the tab-specific menus that are shown in the menuBar.
@ -277,9 +278,11 @@ void MainWindow::actWatchReplay()
file.close();
replay = new GameReplay;
replay->ParseFromArray(buf.data(), buf.size());
tabSupervisor->openReplay(replay);
if (replay->ParseFromArray(buf.data(), buf.size())) {
tabSupervisor->openReplay(replay);
} else {
qCWarning(MainWindowLog) << "failed to parse replay!";
}
}
void MainWindow::localGameEnded()