mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-07-08 17:13:57 -07:00
Merge branch 'master' into tooomm-qt5
This commit is contained in:
commit
c3f8ca5aee
14 changed files with 187 additions and 188 deletions
|
|
@ -1,5 +0,0 @@
|
||||||
---
|
|
||||||
exclude_paths:
|
|
||||||
- '**/translations/*.ts'
|
|
||||||
|
|
||||||
# codacy config documentation: https://support.codacy.com/hc/en-us/articles/115002130625-Codacy-Configuration-File
|
|
||||||
7
.github/workflows/desktop-build.yml
vendored
7
.github/workflows/desktop-build.yml
vendored
|
|
@ -271,7 +271,6 @@ jobs:
|
||||||
override_target: 13
|
override_target: 13
|
||||||
package_suffix: "-macOS13_Intel"
|
package_suffix: "-macOS13_Intel"
|
||||||
qt_version: 6.11.0
|
qt_version: 6.11.0
|
||||||
qt_arch: clang_64
|
|
||||||
qt_modules: qtimageformats qtmultimedia qtwebsockets
|
qt_modules: qtimageformats qtmultimedia qtwebsockets
|
||||||
soc: Intel
|
soc: Intel
|
||||||
type: Release
|
type: Release
|
||||||
|
|
@ -287,7 +286,6 @@ jobs:
|
||||||
make_package: 1
|
make_package: 1
|
||||||
package_suffix: "-macOS14"
|
package_suffix: "-macOS14"
|
||||||
qt_version: 6.11.0
|
qt_version: 6.11.0
|
||||||
qt_arch: clang_64
|
|
||||||
qt_modules: qtimageformats qtmultimedia qtwebsockets
|
qt_modules: qtimageformats qtmultimedia qtwebsockets
|
||||||
soc: Apple
|
soc: Apple
|
||||||
type: Release
|
type: Release
|
||||||
|
|
@ -303,7 +301,6 @@ jobs:
|
||||||
make_package: 1
|
make_package: 1
|
||||||
package_suffix: "-macOS15"
|
package_suffix: "-macOS15"
|
||||||
qt_version: 6.11.0
|
qt_version: 6.11.0
|
||||||
qt_arch: clang_64
|
|
||||||
qt_modules: qtimageformats qtmultimedia qtwebsockets
|
qt_modules: qtimageformats qtmultimedia qtwebsockets
|
||||||
soc: Apple
|
soc: Apple
|
||||||
type: Release
|
type: Release
|
||||||
|
|
@ -317,7 +314,6 @@ jobs:
|
||||||
ccache_eviction_age: 7d
|
ccache_eviction_age: 7d
|
||||||
cmake_generator: Ninja
|
cmake_generator: Ninja
|
||||||
qt_version: 6.11.0
|
qt_version: 6.11.0
|
||||||
qt_arch: clang_64
|
|
||||||
qt_modules: qtimageformats qtmultimedia qtwebsockets
|
qt_modules: qtimageformats qtmultimedia qtwebsockets
|
||||||
soc: Apple
|
soc: Apple
|
||||||
type: Debug
|
type: Debug
|
||||||
|
|
@ -333,7 +329,6 @@ jobs:
|
||||||
make_package: 1
|
make_package: 1
|
||||||
package_suffix: "-Win10"
|
package_suffix: "-Win10"
|
||||||
qt_version: 6.11.0
|
qt_version: 6.11.0
|
||||||
qt_arch: win64_msvc2022_64
|
|
||||||
qt_modules: qtimageformats qtmultimedia qtwebsockets
|
qt_modules: qtimageformats qtmultimedia qtwebsockets
|
||||||
type: Release
|
type: Release
|
||||||
|
|
||||||
|
|
@ -398,7 +393,6 @@ jobs:
|
||||||
if: matrix.os == 'macOS' && steps.restore_qt.outputs.cache-hit != 'true'
|
if: matrix.os == 'macOS' && steps.restore_qt.outputs.cache-hit != 'true'
|
||||||
uses: jurplel/install-qt-action@v4
|
uses: jurplel/install-qt-action@v4
|
||||||
with:
|
with:
|
||||||
arch: ${{ matrix.qt_arch }}
|
|
||||||
cache: false
|
cache: false
|
||||||
dir: ${{ github.workspace }}
|
dir: ${{ github.workspace }}
|
||||||
modules: ${{ matrix.qt_modules }}
|
modules: ${{ matrix.qt_modules }}
|
||||||
|
|
@ -421,7 +415,6 @@ jobs:
|
||||||
with:
|
with:
|
||||||
# Qt 6.11.0 only works with aqtinstall directly from git until aqtinstall 3.4 is released
|
# Qt 6.11.0 only works with aqtinstall directly from git until aqtinstall 3.4 is released
|
||||||
aqtsource: git+https://github.com/miurahr/aqtinstall.git
|
aqtsource: git+https://github.com/miurahr/aqtinstall.git
|
||||||
arch: ${{ matrix.qt_arch }}
|
|
||||||
cache: true
|
cache: true
|
||||||
modules: ${{ matrix.qt_modules }}
|
modules: ${{ matrix.qt_modules }}
|
||||||
version: ${{ steps.resolve_qt_version.outputs.version }}
|
version: ${{ steps.resolve_qt_version.outputs.version }}
|
||||||
|
|
|
||||||
7
.github/workflows/docker-release.yml
vendored
7
.github/workflows/docker-release.yml
vendored
|
|
@ -56,8 +56,9 @@ jobs:
|
||||||
- name: "Set up Docker buildx"
|
- name: "Set up Docker buildx"
|
||||||
uses: docker/setup-buildx-action@v4
|
uses: docker/setup-buildx-action@v4
|
||||||
|
|
||||||
- name: "Login to GitHub Container Registry"
|
- name: "Login to GitHub Container Registry (GHCR)"
|
||||||
if: contains(github.event.release.tag_name, 'Release') && github.event.release.target_commitish == 'master'
|
if: github.event_name == 'release' && github.event.release.prerelease == false
|
||||||
|
id: login
|
||||||
uses: docker/login-action@v4
|
uses: docker/login-action@v4
|
||||||
with:
|
with:
|
||||||
password: ${{ github.token }}
|
password: ${{ github.token }}
|
||||||
|
|
@ -73,5 +74,5 @@ jobs:
|
||||||
context: .
|
context: .
|
||||||
labels: ${{ steps.metadata.outputs.labels }}
|
labels: ${{ steps.metadata.outputs.labels }}
|
||||||
platforms: linux/amd64,linux/arm64
|
platforms: linux/amd64,linux/arm64
|
||||||
push: ${{ github.ref_type == 'tag' }}
|
push: ${{ steps.login.outcome == 'success' }}
|
||||||
tags: ${{ steps.metadata.outputs.tags }}
|
tags: ${{ steps.metadata.outputs.tags }}
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,6 @@ set(cockatrice_SOURCES
|
||||||
src/game/game_state.cpp
|
src/game/game_state.cpp
|
||||||
src/game_graphics/game_view.cpp
|
src/game_graphics/game_view.cpp
|
||||||
src/game_graphics/hand_counter.cpp
|
src/game_graphics/hand_counter.cpp
|
||||||
src/game/selection_subtype_tally.cpp
|
|
||||||
src/game_graphics/log/message_log_widget.cpp
|
src/game_graphics/log/message_log_widget.cpp
|
||||||
src/game/phase.cpp
|
src/game/phase.cpp
|
||||||
src/game_graphics/phases_toolbar.cpp
|
src/game_graphics/phases_toolbar.cpp
|
||||||
|
|
@ -99,6 +98,8 @@ set(cockatrice_SOURCES
|
||||||
src/game_graphics/player/menu/say_menu.cpp
|
src/game_graphics/player/menu/say_menu.cpp
|
||||||
src/game_graphics/player/menu/sideboard_menu.cpp
|
src/game_graphics/player/menu/sideboard_menu.cpp
|
||||||
src/game_graphics/player/menu/utility_menu.cpp
|
src/game_graphics/player/menu/utility_menu.cpp
|
||||||
|
src/game_graphics/tally/subtype_tally.cpp
|
||||||
|
src/game_graphics/tally/tally.cpp
|
||||||
src/game/player/player_actions.cpp
|
src/game/player/player_actions.cpp
|
||||||
src/game_graphics/player/player_area.cpp
|
src/game_graphics/player/player_area.cpp
|
||||||
src/game_graphics/player/player_dialogs.cpp
|
src/game_graphics/player/player_dialogs.cpp
|
||||||
|
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
||||||
#ifndef SELECTION_SUBTYPE_TALLY_H
|
|
||||||
#define SELECTION_SUBTYPE_TALLY_H
|
|
||||||
|
|
||||||
#include <QList>
|
|
||||||
#include <QString>
|
|
||||||
|
|
||||||
class CardItem;
|
|
||||||
|
|
||||||
/** @brief A single subtype (e.g., "Goblin", "Warrior") with its occurrence count. */
|
|
||||||
struct SubtypeEntry
|
|
||||||
{
|
|
||||||
QString name; ///< The subtype name
|
|
||||||
int count; ///< Number of selected cards with this subtype
|
|
||||||
|
|
||||||
bool operator==(const SubtypeEntry &other) const
|
|
||||||
{
|
|
||||||
return name == other.name && count == other.count;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Extracts and tallies subtypes from selected cards.
|
|
||||||
*/
|
|
||||||
namespace SelectionSubtypeTally
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @brief Parses card type lines and counts each subtype occurrence.
|
|
||||||
*
|
|
||||||
* Skips face-down cards and cards without type info.
|
|
||||||
* @param cards The list of selected card items to analyze.
|
|
||||||
* @return Entries sorted by count ascending, then alphabetically.
|
|
||||||
*/
|
|
||||||
QList<SubtypeEntry> countSubtypes(const QList<CardItem *> &cards);
|
|
||||||
} // namespace SelectionSubtypeTally
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
#include "game_view.h"
|
#include "game_view.h"
|
||||||
|
|
||||||
#include "../client/settings/cache_settings.h"
|
#include "../client/settings/cache_settings.h"
|
||||||
#include "../game/selection_subtype_tally.h"
|
|
||||||
#include "game_scene.h"
|
#include "game_scene.h"
|
||||||
|
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
|
|
@ -79,12 +78,12 @@ GameView::GameView(GameScene *scene, QWidget *parent) : QGraphicsView(scene, par
|
||||||
totalCountLabel->setStyleSheet(totalCountLabelStyle);
|
totalCountLabel->setStyleSheet(totalCountLabelStyle);
|
||||||
totalCountLabel->hide();
|
totalCountLabel->hide();
|
||||||
|
|
||||||
subtypeTallyContainer = new QWidget(this);
|
tallyContainer = new QWidget(this);
|
||||||
subtypeTallyContainer->setStyleSheet(subtypeTallyLabelStyle);
|
tallyContainer->setStyleSheet(subtypeTallyLabelStyle);
|
||||||
subtypeTallyLayout = new QGridLayout(subtypeTallyContainer);
|
tallyLayout = new QGridLayout(tallyContainer);
|
||||||
subtypeTallyLayout->setContentsMargins(2, 2, 2, 2);
|
tallyLayout->setContentsMargins(2, 2, 2, 2);
|
||||||
subtypeTallyLayout->setSpacing(2);
|
tallyLayout->setSpacing(2);
|
||||||
subtypeTallyContainer->hide();
|
tallyContainer->hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameView::resizeEvent(QResizeEvent *event)
|
void GameView::resizeEvent(QResizeEvent *event)
|
||||||
|
|
@ -177,14 +176,14 @@ void GameView::refreshShortcuts()
|
||||||
SettingsCache::instance().shortcuts().getShortcut("Player/aCloseMostRecentZoneView"));
|
SettingsCache::instance().shortcuts().getShortcut("Player/aCloseMostRecentZoneView"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameView::clearSubtypeLabels()
|
void GameView::clearTallyLabels()
|
||||||
{
|
{
|
||||||
QtUtils::clearLayoutRec(subtypeTallyLayout);
|
QtUtils::clearLayoutRec(tallyLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
QSize GameView::rebuildSubtypeLabels(const QList<SubtypeEntry> &entries)
|
QSize GameView::rebuildTallyLabels(const QList<TallyRow> &entries)
|
||||||
{
|
{
|
||||||
clearSubtypeLabels();
|
clearTallyLabels();
|
||||||
|
|
||||||
const QString nameStyle = QStringLiteral("color: white; font-size: 12px; background: transparent;");
|
const QString nameStyle = QStringLiteral("color: white; font-size: 12px; background: transparent;");
|
||||||
const QString countStyle =
|
const QString countStyle =
|
||||||
|
|
@ -195,16 +194,16 @@ QSize GameView::rebuildSubtypeLabels(const QList<SubtypeEntry> &entries)
|
||||||
int maxCountWidth = 0;
|
int maxCountWidth = 0;
|
||||||
|
|
||||||
int row = 0;
|
int row = 0;
|
||||||
for (const SubtypeEntry &entry : entries) {
|
for (const TallyRow &entry : entries) {
|
||||||
auto *nameLabel = new QLabel(entry.name, subtypeTallyContainer);
|
auto *nameLabel = new QLabel(entry.name, tallyContainer);
|
||||||
nameLabel->setStyleSheet(nameStyle);
|
nameLabel->setStyleSheet(nameStyle);
|
||||||
nameLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
|
nameLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
|
||||||
subtypeTallyLayout->addWidget(nameLabel, row, 0);
|
tallyLayout->addWidget(nameLabel, row, 0);
|
||||||
|
|
||||||
auto *countLabel = new QLabel(QString::number(entry.count), subtypeTallyContainer);
|
auto *countLabel = new QLabel(entry.value, tallyContainer);
|
||||||
countLabel->setStyleSheet(countStyle);
|
countLabel->setStyleSheet(countStyle);
|
||||||
countLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
|
countLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
|
||||||
subtypeTallyLayout->addWidget(countLabel, row, 1);
|
tallyLayout->addWidget(countLabel, row, 1);
|
||||||
|
|
||||||
QSize nameSize = nameLabel->sizeHint();
|
QSize nameSize = nameLabel->sizeHint();
|
||||||
QSize countSize = countLabel->sizeHint();
|
QSize countSize = countLabel->sizeHint();
|
||||||
|
|
@ -215,9 +214,9 @@ QSize GameView::rebuildSubtypeLabels(const QList<SubtypeEntry> &entries)
|
||||||
++row;
|
++row;
|
||||||
}
|
}
|
||||||
|
|
||||||
int spacing = subtypeTallyLayout->spacing();
|
int spacing = tallyLayout->spacing();
|
||||||
int margins = subtypeTallyLayout->contentsMargins().left() + subtypeTallyLayout->contentsMargins().right();
|
int margins = tallyLayout->contentsMargins().left() + tallyLayout->contentsMargins().right();
|
||||||
int verticalMargins = subtypeTallyLayout->contentsMargins().top() + subtypeTallyLayout->contentsMargins().bottom();
|
int verticalMargins = tallyLayout->contentsMargins().top() + tallyLayout->contentsMargins().bottom();
|
||||||
|
|
||||||
int width = maxNameWidth + spacing + maxCountWidth + margins;
|
int width = maxNameWidth + spacing + maxCountWidth + margins;
|
||||||
int height = totalHeight + (row - 1) * spacing + verticalMargins;
|
int height = totalHeight + (row - 1) * spacing + verticalMargins;
|
||||||
|
|
@ -247,29 +246,26 @@ void GameView::updateTotalSelectionCount(const QSize &viewSize)
|
||||||
totalCountLabel->show();
|
totalCountLabel->show();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!SettingsCache::instance().getShowSubtypeSelectionTally() || count <= 1) {
|
TallyType tallyType =
|
||||||
subtypeTallyContainer->hide();
|
SettingsCache::instance().getShowSubtypeSelectionTally() ? TallyType::Subtypes : TallyType::None;
|
||||||
cachedSubtypeEntries.clear();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
GameScene *gameScene = static_cast<GameScene *>(scene());
|
GameScene *gameScene = static_cast<GameScene *>(scene());
|
||||||
QList<SubtypeEntry> entries = SelectionSubtypeTally::countSubtypes(gameScene->selectedCards());
|
QList<TallyRow> entries = Tally::compute(gameScene->selectedCards(), tallyType);
|
||||||
|
|
||||||
if (entries.isEmpty()) {
|
if (entries.isEmpty() || count <= 1) {
|
||||||
subtypeTallyContainer->hide();
|
tallyContainer->hide();
|
||||||
cachedSubtypeEntries.clear();
|
cachedTallyRows.clear();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only rebuild labels if entries changed
|
// Only rebuild labels if entries changed
|
||||||
QSize containerSize;
|
QSize containerSize;
|
||||||
if (entries != cachedSubtypeEntries) {
|
if (entries != cachedTallyRows) {
|
||||||
cachedSubtypeEntries = entries;
|
cachedTallyRows = entries;
|
||||||
containerSize = rebuildSubtypeLabels(entries);
|
containerSize = rebuildTallyLabels(entries);
|
||||||
subtypeTallyContainer->resize(containerSize);
|
tallyContainer->resize(containerSize);
|
||||||
} else {
|
} else {
|
||||||
containerSize = subtypeTallyContainer->size();
|
containerSize = tallyContainer->size();
|
||||||
}
|
}
|
||||||
|
|
||||||
int x = availableWidth - containerSize.width() - kMarginInPixels;
|
int x = availableWidth - containerSize.width() - kMarginInPixels;
|
||||||
|
|
@ -283,8 +279,8 @@ void GameView::updateTotalSelectionCount(const QSize &viewSize)
|
||||||
|
|
||||||
y = qMax(kMarginInPixels, y);
|
y = qMax(kMarginInPixels, y);
|
||||||
|
|
||||||
subtypeTallyContainer->move(x, y);
|
tallyContainer->move(x, y);
|
||||||
subtypeTallyContainer->show();
|
tallyContainer->show();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
#ifndef GAMEVIEW_H
|
#ifndef GAMEVIEW_H
|
||||||
#define GAMEVIEW_H
|
#define GAMEVIEW_H
|
||||||
|
|
||||||
#include "../game/selection_subtype_tally.h"
|
#include "tally/tally.h"
|
||||||
|
|
||||||
#include <QGraphicsView>
|
#include <QGraphicsView>
|
||||||
|
|
||||||
|
|
@ -24,13 +24,13 @@ private:
|
||||||
QRubberBand *rubberBand;
|
QRubberBand *rubberBand;
|
||||||
QLabel *dragCountLabel;
|
QLabel *dragCountLabel;
|
||||||
QLabel *totalCountLabel;
|
QLabel *totalCountLabel;
|
||||||
QWidget *subtypeTallyContainer;
|
QWidget *tallyContainer;
|
||||||
QGridLayout *subtypeTallyLayout;
|
QGridLayout *tallyLayout;
|
||||||
QPointF selectionOrigin;
|
QPointF selectionOrigin;
|
||||||
QList<SubtypeEntry> cachedSubtypeEntries; ///< Cached entries to avoid redundant rebuilds
|
QList<TallyRow> cachedTallyRows; ///< Cached entries to avoid redundant rebuilds
|
||||||
|
|
||||||
QSize rebuildSubtypeLabels(const QList<SubtypeEntry> &entries);
|
QSize rebuildTallyLabels(const QList<TallyRow> &entries);
|
||||||
void clearSubtypeLabels();
|
void clearTallyLabels();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void resizeEvent(QResizeEvent *event) override;
|
void resizeEvent(QResizeEvent *event) override;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
#include "selection_subtype_tally.h"
|
#include "subtype_tally.h"
|
||||||
|
|
||||||
#include "../game_graphics/board/card_item.h"
|
#include "../board/card_item.h"
|
||||||
|
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
@ -19,12 +19,19 @@ QStringList extractSubtypesFromFace(const QString &faceType)
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @brief A single subtype (e.g., "Goblin", "Warrior") with its occurrence count. */
|
||||||
|
struct SubtypeEntry
|
||||||
|
{
|
||||||
|
QString name;
|
||||||
|
int count;
|
||||||
|
};
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
namespace SelectionSubtypeTally
|
namespace SubtypeTally
|
||||||
{
|
{
|
||||||
|
|
||||||
QList<SubtypeEntry> countSubtypes(const QList<CardItem *> &cards)
|
QList<TallyRow> countSubtypes(const QList<CardItem *> &cards)
|
||||||
{
|
{
|
||||||
QMap<QString, int> subtypeCounts;
|
QMap<QString, int> subtypeCounts;
|
||||||
|
|
||||||
|
|
@ -58,7 +65,13 @@ QList<SubtypeEntry> countSubtypes(const QList<CardItem *> &cards)
|
||||||
return a.name < b.name;
|
return a.name < b.name;
|
||||||
});
|
});
|
||||||
|
|
||||||
return entries;
|
// convert entries into TallyRows
|
||||||
|
QList<TallyRow> rows;
|
||||||
|
rows.reserve(entries.size()); // for backwards compatibility with Qt5
|
||||||
|
std::transform(entries.begin(), entries.end(), std::back_inserter(rows),
|
||||||
|
[](const SubtypeEntry &e) { return TallyRow{e.name, QString::number(e.count)}; });
|
||||||
|
|
||||||
|
return rows;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace SelectionSubtypeTally
|
} // namespace SubtypeTally
|
||||||
26
cockatrice/src/game_graphics/tally/subtype_tally.h
Normal file
26
cockatrice/src/game_graphics/tally/subtype_tally.h
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
#ifndef COCKATRICE_SUBTYPE_TALLY_H
|
||||||
|
#define COCKATRICE_SUBTYPE_TALLY_H
|
||||||
|
|
||||||
|
#include "tally.h"
|
||||||
|
|
||||||
|
#include <QList>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
class CardItem;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Extracts and tallies subtypes from selected cards.
|
||||||
|
*/
|
||||||
|
namespace SubtypeTally
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @brief Parses card type lines and counts each subtype occurrence.
|
||||||
|
*
|
||||||
|
* Skips face-down cards and cards without type info.
|
||||||
|
* @param cards The list of selected card items to analyze.
|
||||||
|
* @return Entries sorted by count ascending, then alphabetically.
|
||||||
|
*/
|
||||||
|
QList<TallyRow> countSubtypes(const QList<CardItem *> &cards);
|
||||||
|
} // namespace SubtypeTally
|
||||||
|
|
||||||
|
#endif
|
||||||
14
cockatrice/src/game_graphics/tally/tally.cpp
Normal file
14
cockatrice/src/game_graphics/tally/tally.cpp
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
#include "tally.h"
|
||||||
|
|
||||||
|
#include "subtype_tally.h"
|
||||||
|
|
||||||
|
QList<TallyRow> Tally::compute(const QList<CardItem *> &cards, const TallyType type)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case TallyType::None:
|
||||||
|
return {};
|
||||||
|
case TallyType::Subtypes:
|
||||||
|
return SubtypeTally::countSubtypes(cards);
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
40
cockatrice/src/game_graphics/tally/tally.h
Normal file
40
cockatrice/src/game_graphics/tally/tally.h
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
#ifndef COCKATRICE_TALLY_H
|
||||||
|
#define COCKATRICE_TALLY_H
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
class CardItem;
|
||||||
|
|
||||||
|
/** @brief A single row of the tally output. */
|
||||||
|
struct TallyRow
|
||||||
|
{
|
||||||
|
QString name; ///< The row name (displayed on the left)
|
||||||
|
QString value; ///< Value for the row (displayed on the right)
|
||||||
|
|
||||||
|
bool operator==(const TallyRow &) const = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The tally type
|
||||||
|
*/
|
||||||
|
enum class TallyType
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
Subtypes,
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace Tally
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Analyzes the selected cards according to the tally type and builds the resulting tally rows.
|
||||||
|
* This forwards the cards to the code for that tally type.
|
||||||
|
*
|
||||||
|
* @param cards The list of selected card items to analyze.
|
||||||
|
* @param type The type of tally to do
|
||||||
|
* @return Rows sorted in top-to-bottom display order
|
||||||
|
*/
|
||||||
|
QList<TallyRow> compute(const QList<CardItem *> &cards, TallyType type);
|
||||||
|
|
||||||
|
} // namespace Tally
|
||||||
|
|
||||||
|
#endif // COCKATRICE_TALLY_H
|
||||||
|
|
@ -436,103 +436,35 @@ void UserContextMenu::showContextMenu(const QPoint &pos,
|
||||||
QAction *actionClicked = menu->exec(pos);
|
QAction *actionClicked = menu->exec(pos);
|
||||||
if (actionClicked == nullptr) {
|
if (actionClicked == nullptr) {
|
||||||
} else if (actionClicked == aDetails) {
|
} else if (actionClicked == aDetails) {
|
||||||
auto *infoWidget =
|
execDetails(userName);
|
||||||
new UserInfoBox(client, false, static_cast<QWidget *>(parent()),
|
|
||||||
Qt::Dialog | Qt::WindowTitleHint | Qt::CustomizeWindowHint | Qt::WindowCloseButtonHint);
|
|
||||||
infoWidget->setAttribute(Qt::WA_DeleteOnClose);
|
|
||||||
infoWidget->updateInfo(userName);
|
|
||||||
} else if (actionClicked == aChat) {
|
} else if (actionClicked == aChat) {
|
||||||
emit openMessageDialog(userName, true);
|
execChat(userName);
|
||||||
} else if (actionClicked == aShowGames) {
|
} else if (actionClicked == aShowGames) {
|
||||||
Command_GetGamesOfUser cmd;
|
execShowGames(userName);
|
||||||
cmd.set_user_name(userName.toStdString());
|
|
||||||
|
|
||||||
PendingCommand *pend = client->prepareSessionCommand(cmd);
|
|
||||||
connect(pend, &PendingCommand::finished, this, &UserContextMenu::gamesOfUserReceived);
|
|
||||||
|
|
||||||
client->sendCommand(pend);
|
|
||||||
} else if (actionClicked == aAddToBuddyList) {
|
} else if (actionClicked == aAddToBuddyList) {
|
||||||
Command_AddToList cmd;
|
execAddToBuddy(userName);
|
||||||
cmd.set_list("buddy");
|
|
||||||
cmd.set_user_name(userName.toStdString());
|
|
||||||
|
|
||||||
client->sendCommand(client->prepareSessionCommand(cmd));
|
|
||||||
} else if (actionClicked == aRemoveFromBuddyList) {
|
} else if (actionClicked == aRemoveFromBuddyList) {
|
||||||
Command_RemoveFromList cmd;
|
execRemoveFromBuddy(userName);
|
||||||
cmd.set_list("buddy");
|
|
||||||
cmd.set_user_name(userName.toStdString());
|
|
||||||
|
|
||||||
client->sendCommand(client->prepareSessionCommand(cmd));
|
|
||||||
} else if (actionClicked == aAddToIgnoreList) {
|
} else if (actionClicked == aAddToIgnoreList) {
|
||||||
Command_AddToList cmd;
|
execAddToIgnore(userName);
|
||||||
cmd.set_list("ignore");
|
|
||||||
cmd.set_user_name(userName.toStdString());
|
|
||||||
|
|
||||||
client->sendCommand(client->prepareSessionCommand(cmd));
|
|
||||||
} else if (actionClicked == aRemoveFromIgnoreList) {
|
} else if (actionClicked == aRemoveFromIgnoreList) {
|
||||||
Command_RemoveFromList cmd;
|
execRemoveFromIgnore(userName);
|
||||||
cmd.set_list("ignore");
|
|
||||||
cmd.set_user_name(userName.toStdString());
|
|
||||||
|
|
||||||
client->sendCommand(client->prepareSessionCommand(cmd));
|
|
||||||
} else if (actionClicked == aKick) {
|
} else if (actionClicked == aKick) {
|
||||||
auto result = QMessageBox::question(static_cast<QWidget *>(parent()), tr("Kick Player"),
|
execKick(playerId);
|
||||||
tr("Are you sure you want to kick this player from the game?"),
|
|
||||||
QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
|
|
||||||
if (result == QMessageBox::Yes) {
|
|
||||||
Command_KickFromGame cmd;
|
|
||||||
cmd.set_player_id(playerId);
|
|
||||||
|
|
||||||
game->getGameEventHandler()->sendGameCommand(cmd);
|
|
||||||
}
|
|
||||||
} else if (actionClicked == aBan) {
|
} else if (actionClicked == aBan) {
|
||||||
Command_GetUserInfo cmd;
|
execBan(userName);
|
||||||
cmd.set_user_name(userName.toStdString());
|
|
||||||
|
|
||||||
PendingCommand *pend = client->prepareSessionCommand(cmd);
|
|
||||||
connect(pend, &PendingCommand::finished, this, &UserContextMenu::banUser_processUserInfoResponse);
|
|
||||||
client->sendCommand(pend);
|
|
||||||
} else if (actionClicked == aPromoteToMod || actionClicked == aDemoteFromMod) {
|
} else if (actionClicked == aPromoteToMod || actionClicked == aDemoteFromMod) {
|
||||||
Command_AdjustMod cmd;
|
execAdjustMod(userName, actionClicked == aPromoteToMod);
|
||||||
cmd.set_user_name(userName.toStdString());
|
|
||||||
cmd.set_should_be_mod(actionClicked == aPromoteToMod);
|
|
||||||
|
|
||||||
PendingCommand *pend = client->prepareAdminCommand(cmd);
|
|
||||||
connect(pend, &PendingCommand::finished, this, &UserContextMenu::adjustMod_processUserResponse);
|
|
||||||
client->sendCommand(pend);
|
|
||||||
} else if (actionClicked == aPromoteToJudge || actionClicked == aDemoteFromJudge) {
|
} else if (actionClicked == aPromoteToJudge || actionClicked == aDemoteFromJudge) {
|
||||||
Command_AdjustMod cmd;
|
execAdjustJudge(userName, actionClicked == aPromoteToJudge);
|
||||||
cmd.set_user_name(userName.toStdString());
|
|
||||||
cmd.set_should_be_judge(actionClicked == aPromoteToJudge);
|
|
||||||
|
|
||||||
PendingCommand *pend = client->prepareAdminCommand(cmd);
|
|
||||||
connect(pend, &PendingCommand::finished, this, &UserContextMenu::adjustMod_processUserResponse);
|
|
||||||
client->sendCommand(pend);
|
|
||||||
} else if (actionClicked == aBanHistory) {
|
} else if (actionClicked == aBanHistory) {
|
||||||
Command_GetBanHistory cmd;
|
execBanHistory(userName);
|
||||||
cmd.set_user_name(userName.toStdString());
|
|
||||||
PendingCommand *pend = client->prepareModeratorCommand(cmd);
|
|
||||||
connect(pend, &PendingCommand::finished, this, &UserContextMenu::banUserHistory_processResponse);
|
|
||||||
client->sendCommand(pend);
|
|
||||||
} else if (actionClicked == aWarnUser) {
|
} else if (actionClicked == aWarnUser) {
|
||||||
Command_GetUserInfo cmd;
|
execWarn(userName);
|
||||||
cmd.set_user_name(userName.toStdString());
|
|
||||||
PendingCommand *pend = client->prepareSessionCommand(cmd);
|
|
||||||
connect(pend, &PendingCommand::finished, this, &UserContextMenu::warnUser_processUserInfoResponse);
|
|
||||||
client->sendCommand(pend);
|
|
||||||
} else if (actionClicked == aWarnHistory) {
|
} else if (actionClicked == aWarnHistory) {
|
||||||
Command_GetWarnHistory cmd;
|
execWarnHistory(userName);
|
||||||
cmd.set_user_name(userName.toStdString());
|
|
||||||
PendingCommand *pend = client->prepareModeratorCommand(cmd);
|
|
||||||
connect(pend, &PendingCommand::finished, this, &UserContextMenu::warnUserHistory_processResponse);
|
|
||||||
client->sendCommand(pend);
|
|
||||||
} else if (actionClicked == aGetAdminNotes) {
|
} else if (actionClicked == aGetAdminNotes) {
|
||||||
Command_GetAdminNotes cmd;
|
execAdminNotes(userName);
|
||||||
cmd.set_user_name(userName.toStdString());
|
|
||||||
auto *pend = client->prepareModeratorCommand(cmd);
|
|
||||||
connect(pend, &PendingCommand::finished, this, &UserContextMenu::getAdminNotes_processResponse);
|
|
||||||
client->sendCommand(pend);
|
|
||||||
|
|
||||||
} else if (actionClicked == aCopyToClipBoard) {
|
} else if (actionClicked == aCopyToClipBoard) {
|
||||||
QClipboard *clipboard = QGuiApplication::clipboard();
|
QClipboard *clipboard = QGuiApplication::clipboard();
|
||||||
clipboard->setText(deckHash);
|
clipboard->setText(deckHash);
|
||||||
|
|
@ -597,6 +529,19 @@ void UserContextMenu::execRemoveFromIgnore(const QString &userName)
|
||||||
client->sendCommand(client->prepareSessionCommand(cmd));
|
client->sendCommand(client->prepareSessionCommand(cmd));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UserContextMenu::execKick(int playerId)
|
||||||
|
{
|
||||||
|
auto result = QMessageBox::question(static_cast<QWidget *>(parent()), tr("Kick Player"),
|
||||||
|
tr("Are you sure you want to kick this player from the game?"),
|
||||||
|
QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
|
||||||
|
if (result == QMessageBox::Yes) {
|
||||||
|
Command_KickFromGame cmd;
|
||||||
|
cmd.set_player_id(playerId);
|
||||||
|
|
||||||
|
game->getGameEventHandler()->sendGameCommand(cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void UserContextMenu::execBan(const QString &userName)
|
void UserContextMenu::execBan(const QString &userName)
|
||||||
{
|
{
|
||||||
Command_GetUserInfo cmd;
|
Command_GetUserInfo cmd;
|
||||||
|
|
@ -642,11 +587,20 @@ void UserContextMenu::execAdminNotes(const QString &userName)
|
||||||
client->sendCommand(pend);
|
client->sendCommand(pend);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UserContextMenu::execAdjustMod(const QString &userName, bool shouldBeMod, bool shouldBeJudge)
|
void UserContextMenu::execAdjustMod(const QString &userName, bool shouldBeMod)
|
||||||
{
|
{
|
||||||
Command_AdjustMod cmd;
|
Command_AdjustMod cmd;
|
||||||
cmd.set_user_name(userName.toStdString());
|
cmd.set_user_name(userName.toStdString());
|
||||||
cmd.set_should_be_mod(shouldBeMod);
|
cmd.set_should_be_mod(shouldBeMod);
|
||||||
|
PendingCommand *pend = client->prepareAdminCommand(cmd);
|
||||||
|
connect(pend, &PendingCommand::finished, this, &UserContextMenu::adjustMod_processUserResponse);
|
||||||
|
client->sendCommand(pend);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UserContextMenu::execAdjustJudge(const QString &userName, bool shouldBeJudge)
|
||||||
|
{
|
||||||
|
Command_AdjustMod cmd;
|
||||||
|
cmd.set_user_name(userName.toStdString());
|
||||||
cmd.set_should_be_judge(shouldBeJudge);
|
cmd.set_should_be_judge(shouldBeJudge);
|
||||||
PendingCommand *pend = client->prepareAdminCommand(cmd);
|
PendingCommand *pend = client->prepareAdminCommand(cmd);
|
||||||
connect(pend, &PendingCommand::finished, this, &UserContextMenu::adjustMod_processUserResponse);
|
connect(pend, &PendingCommand::finished, this, &UserContextMenu::adjustMod_processUserResponse);
|
||||||
|
|
|
||||||
|
|
@ -89,12 +89,14 @@ public:
|
||||||
void execRemoveFromBuddy(const QString &userName);
|
void execRemoveFromBuddy(const QString &userName);
|
||||||
void execAddToIgnore(const QString &userName);
|
void execAddToIgnore(const QString &userName);
|
||||||
void execRemoveFromIgnore(const QString &userName);
|
void execRemoveFromIgnore(const QString &userName);
|
||||||
|
void execKick(int playerId);
|
||||||
void execBan(const QString &userName);
|
void execBan(const QString &userName);
|
||||||
void execWarn(const QString &userName);
|
void execWarn(const QString &userName);
|
||||||
void execBanHistory(const QString &userName);
|
void execBanHistory(const QString &userName);
|
||||||
void execWarnHistory(const QString &userName);
|
void execWarnHistory(const QString &userName);
|
||||||
void execAdminNotes(const QString &userName);
|
void execAdminNotes(const QString &userName);
|
||||||
void execAdjustMod(const QString &userName, bool shouldBeMod, bool shouldBeJudge);
|
void execAdjustMod(const QString &userName, bool shouldBeMod);
|
||||||
|
void execAdjustJudge(const QString &userName, bool shouldBeJudge);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -703,13 +703,13 @@ void UserListWidget::connectPopupSignals()
|
||||||
connect(m_userInfoPopup, &UserInfoPopup::warnHistoryRequested, userContextMenu, &UserContextMenu::execWarnHistory);
|
connect(m_userInfoPopup, &UserInfoPopup::warnHistoryRequested, userContextMenu, &UserContextMenu::execWarnHistory);
|
||||||
connect(m_userInfoPopup, &UserInfoPopup::adminNotesRequested, userContextMenu, &UserContextMenu::execAdminNotes);
|
connect(m_userInfoPopup, &UserInfoPopup::adminNotesRequested, userContextMenu, &UserContextMenu::execAdminNotes);
|
||||||
connect(m_userInfoPopup, &UserInfoPopup::promoteToModRequested, this,
|
connect(m_userInfoPopup, &UserInfoPopup::promoteToModRequested, this,
|
||||||
[this](const QString &n) { userContextMenu->execAdjustMod(n, true, false); });
|
[this](const QString &n) { userContextMenu->execAdjustMod(n, true); });
|
||||||
connect(m_userInfoPopup, &UserInfoPopup::demoteFromModRequested, this,
|
connect(m_userInfoPopup, &UserInfoPopup::demoteFromModRequested, this,
|
||||||
[this](const QString &n) { userContextMenu->execAdjustMod(n, false, false); });
|
[this](const QString &n) { userContextMenu->execAdjustMod(n, false); });
|
||||||
connect(m_userInfoPopup, &UserInfoPopup::promoteToJudgeRequested, this,
|
connect(m_userInfoPopup, &UserInfoPopup::promoteToJudgeRequested, this,
|
||||||
[this](const QString &n) { userContextMenu->execAdjustMod(n, false, true); });
|
[this](const QString &n) { userContextMenu->execAdjustJudge(n, true); });
|
||||||
connect(m_userInfoPopup, &UserInfoPopup::demoteFromJudgeRequested, this,
|
connect(m_userInfoPopup, &UserInfoPopup::demoteFromJudgeRequested, this,
|
||||||
[this](const QString &n) { userContextMenu->execAdjustMod(n, false, false); });
|
[this](const QString &n) { userContextMenu->execAdjustJudge(n, false); });
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UserListWidget::eventFilter(QObject *obj, QEvent *event)
|
bool UserListWidget::eventFilter(QObject *obj, QEvent *event)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue