mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-06-11 08:34:52 -07:00
Merge branch 'master' into tooomm-ci_updates
This commit is contained in:
commit
b8354e3bfc
154 changed files with 2192 additions and 1004 deletions
|
|
@ -1,4 +1,4 @@
|
|||
FROM fedora:40
|
||||
FROM fedora:42
|
||||
|
||||
RUN dnf install -y \
|
||||
ccache \
|
||||
|
|
@ -22,8 +22,8 @@ Available pre-compiled binaries for installation:
|
|||
• <kbd>Ubuntu 20.04 LTS</kbd> <sub><i>Focal Fossa</i></sub>
|
||||
• <kbd>Debian 12</kbd> <sub><i>Bookworm</i></sub>
|
||||
• <kbd>Debian 11</kbd> <sub><i>Bullseye</i></sub>
|
||||
• <kbd>Fedora 42</kbd>
|
||||
• <kbd>Fedora 41</kbd>
|
||||
• <kbd>Fedora 40</kbd>
|
||||
|
||||
<sub>We are also packaged in <kbd>Arch Linux</kbd>'s <a href="https://archlinux.org/packages/extra/x86_64/cockatrice">official extra repository</a>, courtesy of @FFY00.</sub>
|
||||
<sub>General Linux support is available via a <kbd>flatpak</kbd> package at <a href="https://flathub.org/apps/io.github.Cockatrice.cockatrice">Flathub</a>!</sub>
|
||||
|
|
|
|||
5
.github/workflows/desktop-build.yml
vendored
5
.github/workflows/desktop-build.yml
vendored
|
|
@ -9,6 +9,7 @@ on:
|
|||
- 'webclient/**'
|
||||
- '.github/workflows/web-*.yml'
|
||||
- '.github/workflows/translations-*.yml'
|
||||
- '.github/workflows/docker-release.yml'
|
||||
tags:
|
||||
- '*'
|
||||
pull_request:
|
||||
|
|
@ -101,12 +102,12 @@ jobs:
|
|||
package: DEB
|
||||
|
||||
- distro: Fedora
|
||||
version: 40
|
||||
version: 41
|
||||
package: RPM
|
||||
test: skip # Running tests on all distros is superfluous
|
||||
|
||||
- distro: Fedora
|
||||
version: 41
|
||||
version: 42
|
||||
package: RPM
|
||||
|
||||
- distro: Ubuntu
|
||||
|
|
|
|||
1
.github/workflows/desktop-lint.yml
vendored
1
.github/workflows/desktop-lint.yml
vendored
|
|
@ -7,6 +7,7 @@ on:
|
|||
- 'webclient/**'
|
||||
- '.github/workflows/web-*.yml'
|
||||
- '.github/workflows/translations-*.yml'
|
||||
- '.github/workflows/docker-release.yml'
|
||||
|
||||
jobs:
|
||||
format:
|
||||
|
|
|
|||
71
.github/workflows/docker-release.yml
vendored
Normal file
71
.github/workflows/docker-release.yml
vendored
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
name: Build Docker Image
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- '*Release*'
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- '.github/workflows/docker-release.yml'
|
||||
- 'CMakeLists.txt'
|
||||
- 'Dockerfile'
|
||||
- 'servatrice/**'
|
||||
- 'common/**'
|
||||
- 'cmake/**'
|
||||
- '!**.md'
|
||||
|
||||
jobs:
|
||||
docker:
|
||||
name: amd64 & arm64
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Docker metadata
|
||||
id: metadata
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: |
|
||||
ghcr.io/cockatrice/servatrice
|
||||
labels: |
|
||||
org.opencontainers.image.title=Servatrice
|
||||
org.opencontainers.image.url=https://cockatrice.github.io/
|
||||
org.opencontainers.image.description=Server for Cockatrice, a cross-platform virtual tabletop for multiplayer card games
|
||||
annotations: |
|
||||
org.opencontainers.image.title=Servatrice
|
||||
org.opencontainers.image.url=https://cockatrice.github.io/
|
||||
org.opencontainers.image.description=Server for Cockatrice, a cross-platform virtual tabletop for multiplayer card games
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
- name: Set up Docker buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
if: github.ref_type == 'tag'
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ github.token }}
|
||||
|
||||
- name: Build and push Docker image
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: ${{ github.ref_type == 'tag' }}
|
||||
tags: ${{ steps.metadata.outputs.tags }}
|
||||
labels: ${{ steps.metadata.outputs.labels }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
|
|
@ -16,7 +16,11 @@ RUN apt-get update && apt-get install -y\
|
|||
qt6-tools-dev \
|
||||
qt6-tools-dev-tools
|
||||
|
||||
COPY . /home/servatrice/code/
|
||||
COPY ./CMakeLists.txt ./LICENSE ./README.md /home/servatrice/code/
|
||||
COPY ./cmake /home/servatrice/code/cmake
|
||||
COPY ./common /home/servatrice/code/common
|
||||
COPY ./servatrice /home/servatrice/code/servatrice
|
||||
|
||||
WORKDIR /home/servatrice/code
|
||||
|
||||
WORKDIR build
|
||||
|
|
|
|||
18
README.md
18
README.md
|
|
@ -8,7 +8,7 @@
|
|||
<a href="#related-repositories">Related</a> <b>|</b>
|
||||
<a href="#community-resources-">Community</a> <b>|</b>
|
||||
<a href="#contribute">Contribute</a> <b>|</b>
|
||||
<a href="#build--">Build</a> <b>|</b>
|
||||
<a href="#build---">Build</a> <b>|</b>
|
||||
<a href="#run">Run</a>
|
||||
</p>
|
||||
|
||||
|
|
@ -38,8 +38,8 @@ Latest <kbd>stable</kbd> release:
|
|||
</pre><pre>
|
||||
Latest <kbd>beta</kbd> version:
|
||||
[](https://github.com/cockatrice/cockatrice/releases)  [](https://tooomm.github.io/github-release-stats/?username=Cockatrice&repository=Cockatrice&search=0) [](https://github.com/Cockatrice/Cockatrice/pulls?q=is%3Apr+is%3Aclosed)
|
||||
<sub><i>While incorporating the latest fixes and features, beta builds may not be stable and/or contain new bugs!</i></sub>
|
||||
<sub><b><i>Please report any findings when testing them!</i></b></sub>
|
||||
<sub><i>While incorporating the latest fixes and features, beta builds may not be stable or contain new bugs!</i></sub>
|
||||
<sub><b><i>Please report any findings and open new issues when testing them!</i></b></sub>
|
||||
</pre>
|
||||
|
||||
# Related Repositories
|
||||
|
|
@ -79,10 +79,11 @@ Cockatrice tries to use the [Google Developer Documentation Style Guide](https:/
|
|||
|
||||
<details>
|
||||
<summary><b>Kudos to our amazing contributors ❤️</b></summary>
|
||||
<br>
|
||||
<a href="https://github.com/Cockatrice/Cockatrice/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=Cockatrice/Cockatrice" />
|
||||
</a><br>
|
||||
<sub><i>Made with <a href="https://contrib.rocks">contrib.rocks</a>.</i></sub>
|
||||
<sub><i>Made with <a href="https://contrib.rocks">contrib.rocks</a></i></sub>
|
||||
</details>
|
||||
|
||||
### Translations [](https://transifex.com/cockatrice/cockatrice/)
|
||||
|
|
@ -92,7 +93,7 @@ Cockatrice uses Transifex to manage translations. You can help us bring <kbd>Coc
|
|||
Check out our [Translator FAQ](https://github.com/Cockatrice/Cockatrice/wiki/Translation-FAQ) for more information about getting invovled, and join a group of hundreds of others!<br>
|
||||
|
||||
|
||||
# Build [](https://github.com/Cockatrice/Cockatrice/actions/workflows/desktop-build.yml?query=branch%3Amaster+event%3Apush) [](https://github.com/Cockatrice/Cockatrice/actions/workflows/web-build.yml?query=branch%3Amaster+event%3Apush)
|
||||
# Build [](https://github.com/Cockatrice/Cockatrice/actions/workflows/desktop-build.yml?query=branch%3Amaster+event%3Apush) [](https://github.com/Cockatrice/Cockatrice/actions/workflows/docker-release.yml?query=branch%3Amaster+event%3Apush) [](https://github.com/Cockatrice/Cockatrice/actions/workflows/web-build.yml?query=branch%3Amaster+event%3Apush)
|
||||
|
||||
Dependencies: *(for minimum versions search our [CMake file](https://github.com/Cockatrice/Cockatrice/blob/master/CMakeLists.txt))*
|
||||
- [Qt](https://www.qt.io/developers/)
|
||||
|
|
@ -143,17 +144,16 @@ The following flags (with their non-default values) can be passed to `cmake`:
|
|||
|
||||
# Run
|
||||
|
||||
|
||||
<kbd>Cockatrice</kbd> is the game client<br>
|
||||
<kbd>Oracle</kbd> fetches card data<br>
|
||||
<kbd>Servatrice</kbd> is the server<br>
|
||||
|
||||
#### Docker
|
||||
|
||||
You can run an instance of <kbd>Servatrice</kbd> (the Cockatrice server) using [Docker](https://www.docker.com/resources/what-container/) and our Dockerfile.<br>
|
||||
You can build an image & deploy a <kbd>Servatrice</kbd> (Cockatrice server) container using [Docker](https://www.docker.com/resources/what-container/) and our Dockerfile yourself.<br>
|
||||
|
||||
For more information, have a look in our wiki section on [Setting up Servatrice](https://github.com/Cockatrice/Cockatrice/wiki/Setting-up-Servatrice#using-docker).<br>
|
||||
There, you'll also find more hints on our **docker-compose** file which will configure and run both a MySQL server and Servatrice.
|
||||
For more details, look into our wiki section on [Setting up Servatrice](https://github.com/Cockatrice/Cockatrice/wiki/Setting-up-Servatrice#using-docker).<br>
|
||||
You'll also find more hints on our **pre-build image** there, or the **docker-compose** file which will configure and run both a MySQL server and Servatrice.
|
||||
|
||||
|
||||
# License [](https://github.com/Cockatrice/Cockatrice/blob/master/LICENSE)
|
||||
|
|
|
|||
|
|
@ -24,7 +24,9 @@ set(cockatrice_SOURCES
|
|||
src/client/tabs/api/edhrec/display/commander/edhrec_commander_api_response_navigation_widget.cpp
|
||||
src/client/tabs/api/edhrec/display/card_prices/edhrec_api_response_card_prices_display_widget.cpp
|
||||
src/client/tabs/api/edhrec/display/cards/edhrec_api_response_card_details_display_widget.cpp
|
||||
src/client/tabs/api/edhrec/display/cards/edhrec_api_response_card_inclusion_display_widget.cpp
|
||||
src/client/tabs/api/edhrec/display/cards/edhrec_api_response_card_list_display_widget.cpp
|
||||
src/client/tabs/api/edhrec/display/cards/edhrec_api_response_card_synergy_display_widget.cpp
|
||||
src/client/tabs/api/edhrec/display/commander/edhrec_api_response_commander_details_display_widget.cpp
|
||||
src/client/tabs/api/edhrec/display/top_cards/edhrec_top_cards_api_response_display_widget.cpp
|
||||
src/client/tabs/api/edhrec/display/top_commander/edhrec_top_commanders_api_response_display_widget.cpp
|
||||
|
|
@ -99,6 +101,7 @@ set(cockatrice_SOURCES
|
|||
src/client/ui/widgets/general/display/dynamic_font_size_label.cpp
|
||||
src/client/ui/widgets/general/display/dynamic_font_size_push_button.cpp
|
||||
src/client/ui/widgets/general/display/labeled_input.cpp
|
||||
src/client/ui/widgets/general/display/percent_bar_widget.cpp
|
||||
src/client/ui/widgets/general/display/shadow_background_label.cpp
|
||||
src/client/ui/widgets/general/layout_containers/flow_widget.cpp
|
||||
src/client/ui/widgets/general/layout_containers/overlap_control_widget.cpp
|
||||
|
|
@ -132,6 +135,7 @@ set(cockatrice_SOURCES
|
|||
src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_tag_item_widget.cpp
|
||||
src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_widget.cpp
|
||||
src/client/ui/widgets/visual_deck_storage/visual_deck_storage_folder_display_widget.cpp
|
||||
src/client/ui/widgets/visual_deck_storage/visual_deck_storage_quick_settings_widget.cpp
|
||||
src/client/ui/widgets/visual_deck_storage/visual_deck_storage_search_widget.cpp
|
||||
src/client/ui/widgets/visual_deck_storage/visual_deck_storage_sort_widget.cpp
|
||||
src/client/ui/widgets/visual_deck_storage/visual_deck_storage_tag_filter_widget.cpp
|
||||
|
|
@ -165,13 +169,16 @@ set(cockatrice_SOURCES
|
|||
src/dialogs/dlg_tip_of_the_day.cpp
|
||||
src/dialogs/dlg_update.cpp
|
||||
src/dialogs/dlg_view_log.cpp
|
||||
src/game/board/abstract_card_drag_item.cpp
|
||||
src/game/board/abstract_card_item.cpp
|
||||
src/game/board/abstract_counter.cpp
|
||||
src/game/board/abstract_graphics_item.cpp
|
||||
src/game/board/arrow_item.cpp
|
||||
src/game/board/arrow_target.cpp
|
||||
src/game/board/card_drag_item.cpp
|
||||
src/game/board/card_item.cpp
|
||||
src/game/board/card_list.cpp
|
||||
src/game/board/counter_general.cpp
|
||||
src/game/cards/abstract_card_drag_item.cpp
|
||||
src/game/cards/abstract_card_item.cpp
|
||||
src/game/cards/card_completer_proxy_model.cpp
|
||||
src/game/cards/card_database.cpp
|
||||
src/game/cards/card_database_manager.cpp
|
||||
|
|
@ -179,10 +186,7 @@ set(cockatrice_SOURCES
|
|||
src/game/cards/card_database_parser/card_database_parser.cpp
|
||||
src/game/cards/card_database_parser/cockatrice_xml_3.cpp
|
||||
src/game/cards/card_database_parser/cockatrice_xml_4.cpp
|
||||
src/game/cards/card_drag_item.cpp
|
||||
src/game/cards/card_info.cpp
|
||||
src/game/cards/card_item.cpp
|
||||
src/game/cards/card_list.cpp
|
||||
src/game/cards/card_search_model.cpp
|
||||
src/game/deckview/deck_view.cpp
|
||||
src/game/deckview/deck_view_container.cpp
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ AbstractTabDeckEditor::AbstractTabDeckEditor(TabSupervisor *_tabSupervisor) : Ta
|
|||
printingSelectorDockWidget = new DeckEditorPrintingSelectorDockWidget(this);
|
||||
|
||||
connect(deckDockWidget, &DeckEditorDeckDockWidget::deckChanged, this, &AbstractTabDeckEditor::onDeckChanged);
|
||||
connect(deckDockWidget, &DeckEditorDeckDockWidget::deckModified, this, &AbstractTabDeckEditor::onDeckModified);
|
||||
connect(deckDockWidget, &DeckEditorDeckDockWidget::cardChanged, this, &AbstractTabDeckEditor::updateCard);
|
||||
connect(this, &AbstractTabDeckEditor::decrementCard, deckDockWidget, &DeckEditorDeckDockWidget::actDecrementCard);
|
||||
connect(databaseDisplayDockWidget, &DeckEditorDatabaseDisplayWidget::cardChanged, this,
|
||||
|
|
@ -77,6 +78,10 @@ void AbstractTabDeckEditor::updateCard(CardInfoPtr _card)
|
|||
}
|
||||
|
||||
void AbstractTabDeckEditor::onDeckChanged()
|
||||
{
|
||||
}
|
||||
|
||||
void AbstractTabDeckEditor::onDeckModified()
|
||||
{
|
||||
setModified(!isBlankNewDeck());
|
||||
deckMenu->setSaveStatus(!isBlankNewDeck());
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@ public:
|
|||
|
||||
public slots:
|
||||
virtual void onDeckChanged();
|
||||
virtual void onDeckModified();
|
||||
void updateCard(CardInfoPtr _card);
|
||||
void actAddCard(CardInfoPtr info);
|
||||
void actAddCardToSideboard(CardInfoPtr info);
|
||||
|
|
|
|||
|
|
@ -14,34 +14,18 @@ EdhrecApiResponseCardDetailsDisplayWidget::EdhrecApiResponseCardDetailsDisplayWi
|
|||
cardPictureWidget = new CardInfoPictureWidget(this);
|
||||
cardPictureWidget->setCard(CardDatabaseManager::getInstance()->guessCard(toDisplay.sanitized));
|
||||
|
||||
label = new QLabel(this);
|
||||
label->setText(toDisplay.name + "\n" + toDisplay.label);
|
||||
label->setAlignment(Qt::AlignHCenter);
|
||||
nameLabel = new QLabel(this);
|
||||
nameLabel->setText(toDisplay.name);
|
||||
nameLabel->setAlignment(Qt::AlignHCenter);
|
||||
|
||||
int inclusionRate = 0;
|
||||
// Set label color based on inclusion rate
|
||||
if (toDisplay.potentialDecks != 0) {
|
||||
inclusionRate = (toDisplay.numDecks * 100) / toDisplay.potentialDecks;
|
||||
}
|
||||
inclusionDisplayWidget = new EdhrecApiResponseCardInclusionDisplayWidget(this, toDisplay);
|
||||
|
||||
QColor labelColor;
|
||||
if (inclusionRate <= 30) {
|
||||
labelColor = QColor(255, 0, 0); // Red
|
||||
} else if (inclusionRate <= 60) {
|
||||
int red = 255 - ((inclusionRate - 30) * 2);
|
||||
int green = (inclusionRate - 30) * 4; // Adjust green to make the transition smoother
|
||||
labelColor = QColor(red, green, 0); // purple-ish
|
||||
} else if (inclusionRate <= 90) {
|
||||
int green = (inclusionRate - 60) * 5; // Increase green
|
||||
labelColor = QColor(100, green, 100); // Green shades
|
||||
} else {
|
||||
labelColor = QColor(100, 200, 100); // Dark Green
|
||||
}
|
||||
|
||||
label->setStyleSheet(QString("color: %1").arg(labelColor.name()));
|
||||
synergyDisplayWidget = new EdhrecApiResponseCardSynergyDisplayWidget(this, toDisplay);
|
||||
|
||||
layout->addWidget(nameLabel);
|
||||
layout->addWidget(cardPictureWidget);
|
||||
layout->addWidget(label);
|
||||
layout->addWidget(inclusionDisplayWidget);
|
||||
layout->addWidget(synergyDisplayWidget);
|
||||
|
||||
QWidget *currentParent = parentWidget();
|
||||
TabEdhRecMain *parentTab = nullptr;
|
||||
|
|
@ -54,8 +38,11 @@ EdhrecApiResponseCardDetailsDisplayWidget::EdhrecApiResponseCardDetailsDisplayWi
|
|||
}
|
||||
|
||||
if (parentTab) {
|
||||
cardPictureWidget->setScaleFactor(parentTab->getCardSizeSlider()->getSlider()->value());
|
||||
connect(cardPictureWidget, &CardInfoPictureWidget::cardClicked, this,
|
||||
&EdhrecApiResponseCardDetailsDisplayWidget::actRequestPageNavigation);
|
||||
connect(parentTab->getCardSizeSlider()->getSlider(), &QSlider::valueChanged, cardPictureWidget,
|
||||
&CardInfoPictureWidget::setScaleFactor);
|
||||
connect(this, &EdhrecApiResponseCardDetailsDisplayWidget::requestUrl, parentTab,
|
||||
&TabEdhRecMain::actNavigatePage);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
#include "../../../../../ui/widgets/cards/card_info_picture_widget.h"
|
||||
#include "../../api_response/cards/edhrec_api_response_card_details.h"
|
||||
#include "edhrec_api_response_card_inclusion_display_widget.h"
|
||||
#include "edhrec_api_response_card_synergy_display_widget.h"
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
|
|
@ -22,7 +24,9 @@ private:
|
|||
EdhrecApiResponseCardDetails toDisplay;
|
||||
QVBoxLayout *layout;
|
||||
CardInfoPictureWidget *cardPictureWidget;
|
||||
QLabel *label;
|
||||
QLabel *nameLabel;
|
||||
EdhrecApiResponseCardInclusionDisplayWidget *inclusionDisplayWidget;
|
||||
EdhrecApiResponseCardSynergyDisplayWidget *synergyDisplayWidget;
|
||||
};
|
||||
|
||||
#endif // EDHREC_COMMANDER_API_RESPONSE_CARD_DETAILS_DISPLAY_WIDGET_H
|
||||
|
|
|
|||
|
|
@ -0,0 +1,41 @@
|
|||
#include "edhrec_api_response_card_inclusion_display_widget.h"
|
||||
|
||||
EdhrecApiResponseCardInclusionDisplayWidget::EdhrecApiResponseCardInclusionDisplayWidget(
|
||||
QWidget *parent,
|
||||
const EdhrecApiResponseCardDetails &_toDisplay)
|
||||
: QWidget(parent), toDisplay(_toDisplay)
|
||||
{
|
||||
layout = new QVBoxLayout(this);
|
||||
setLayout(layout);
|
||||
|
||||
commanderLabel = new QLabel(this);
|
||||
commanderLabel->setAlignment(Qt::AlignCenter);
|
||||
amountLabel = new QLabel(this);
|
||||
amountLabel->setAlignment(Qt::AlignCenter);
|
||||
inclusionLabel = new QLabel(this);
|
||||
inclusionLabel->setAlignment(Qt::AlignCenter);
|
||||
percentBarWidget = new PercentBarWidget(this, toDisplay.inclusion / (toDisplay.potentialDecks / 100.0));
|
||||
|
||||
if (toDisplay.inclusion != 0 && toDisplay.potentialDecks != 0) {
|
||||
layout->addWidget(amountLabel);
|
||||
layout->addWidget(inclusionLabel);
|
||||
layout->addWidget(percentBarWidget);
|
||||
commanderLabel->hide();
|
||||
} else {
|
||||
amountLabel->hide();
|
||||
inclusionLabel->hide();
|
||||
percentBarWidget->hide();
|
||||
layout->addWidget(commanderLabel);
|
||||
}
|
||||
|
||||
retranslateUi();
|
||||
}
|
||||
|
||||
void EdhrecApiResponseCardInclusionDisplayWidget::retranslateUi()
|
||||
{
|
||||
commanderLabel->setText(toDisplay.label);
|
||||
amountLabel->setText(tr("In %1 decks").arg(QString::number(toDisplay.inclusion)));
|
||||
inclusionLabel->setText(tr("%1% of %2 decks")
|
||||
.arg(QString::number(toDisplay.inclusion / (toDisplay.potentialDecks / 100.0), 'f', 2),
|
||||
QString::number(toDisplay.potentialDecks)));
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
#ifndef EDHREC_API_RESPONSE_CARD_INCLUSION_DISPLAY_WIDGET_H
|
||||
#define EDHREC_API_RESPONSE_CARD_INCLUSION_DISPLAY_WIDGET_H
|
||||
|
||||
#include "../../../../../ui/widgets/general/display/percent_bar_widget.h"
|
||||
#include "../../api_response/cards/edhrec_api_response_card_details.h"
|
||||
|
||||
#include <QLabel>
|
||||
#include <QVBoxLayout>
|
||||
#include <QWidget>
|
||||
|
||||
class EdhrecApiResponseCardInclusionDisplayWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
EdhrecApiResponseCardInclusionDisplayWidget(QWidget *parent, const EdhrecApiResponseCardDetails &_toDisplay);
|
||||
void retranslateUi();
|
||||
|
||||
private:
|
||||
QVBoxLayout *layout;
|
||||
EdhrecApiResponseCardDetails toDisplay;
|
||||
QLabel *commanderLabel;
|
||||
QLabel *amountLabel;
|
||||
QLabel *inclusionLabel;
|
||||
PercentBarWidget *percentBarWidget;
|
||||
};
|
||||
|
||||
#endif // EDHREC_API_RESPONSE_CARD_INCLUSION_DISPLAY_WIDGET_H
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
#include "edhrec_api_response_card_synergy_display_widget.h"
|
||||
|
||||
EdhrecApiResponseCardSynergyDisplayWidget::EdhrecApiResponseCardSynergyDisplayWidget(
|
||||
QWidget *parent,
|
||||
const EdhrecApiResponseCardDetails &_toDisplay)
|
||||
: QWidget(parent), toDisplay(_toDisplay)
|
||||
{
|
||||
layout = new QVBoxLayout(this);
|
||||
setLayout(layout);
|
||||
|
||||
label = new QLabel(this);
|
||||
label->setAlignment(Qt::AlignCenter);
|
||||
percentBarWidget = new PercentBarWidget(this, toDisplay.synergy * 100.0);
|
||||
|
||||
if (toDisplay.synergy != 0) {
|
||||
layout->addWidget(label);
|
||||
layout->addWidget(percentBarWidget);
|
||||
} else {
|
||||
hide();
|
||||
}
|
||||
|
||||
retranslateUi();
|
||||
}
|
||||
|
||||
void EdhrecApiResponseCardSynergyDisplayWidget::retranslateUi()
|
||||
{
|
||||
label->setText(tr("%1% Synergy").arg(QString::number(toDisplay.synergy * 100.0, 'f', 1)));
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
#ifndef EDHREC_API_RESPONSE_CARD_SYNERGY_DISPLAY_WIDGET_H
|
||||
#define EDHREC_API_RESPONSE_CARD_SYNERGY_DISPLAY_WIDGET_H
|
||||
|
||||
#include "../../../../../ui/widgets/general/display/percent_bar_widget.h"
|
||||
#include "../../api_response/cards/edhrec_api_response_card_details.h"
|
||||
|
||||
#include <QLabel>
|
||||
#include <QVBoxLayout>
|
||||
#include <QWidget>
|
||||
|
||||
class EdhrecApiResponseCardSynergyDisplayWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
EdhrecApiResponseCardSynergyDisplayWidget(QWidget *parent, const EdhrecApiResponseCardDetails &_toDisplay);
|
||||
void retranslateUi();
|
||||
|
||||
private:
|
||||
QVBoxLayout *layout;
|
||||
EdhrecApiResponseCardDetails toDisplay;
|
||||
QLabel *label;
|
||||
PercentBarWidget *percentBarWidget;
|
||||
};
|
||||
|
||||
#endif // EDHREC_API_RESPONSE_CARD_SYNERGY_DISPLAY_WIDGET_H
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include "../../../../../../game/cards/card_database_manager.h"
|
||||
#include "../../../../../ui/widgets/cards/card_info_picture_widget.h"
|
||||
#include "../../tab_edhrec_main.h"
|
||||
#include "../card_prices/edhrec_api_response_card_prices_display_widget.h"
|
||||
|
||||
EdhrecCommanderResponseCommanderDetailsDisplayWidget::EdhrecCommanderResponseCommanderDetailsDisplayWidget(
|
||||
|
|
@ -16,6 +17,22 @@ EdhrecCommanderResponseCommanderDetailsDisplayWidget::EdhrecCommanderResponseCom
|
|||
commanderPicture = new CardInfoPictureWidget(this);
|
||||
commanderPicture->setCard(CardDatabaseManager::getInstance()->getCard(commanderDetails.getName()));
|
||||
|
||||
QWidget *currentParent = parentWidget();
|
||||
TabEdhRecMain *parentTab = nullptr;
|
||||
|
||||
while (currentParent) {
|
||||
if ((parentTab = qobject_cast<TabEdhRecMain *>(currentParent))) {
|
||||
break;
|
||||
}
|
||||
currentParent = currentParent->parentWidget();
|
||||
}
|
||||
|
||||
if (parentTab) {
|
||||
connect(parentTab->getCardSizeSlider()->getSlider(), &QSlider::valueChanged, commanderPicture,
|
||||
&CardInfoPictureWidget::setScaleFactor);
|
||||
commanderPicture->setScaleFactor(parentTab->getCardSizeSlider()->getSlider()->value());
|
||||
}
|
||||
|
||||
commanderDetails.debugPrint();
|
||||
|
||||
label = new QLabel(this);
|
||||
|
|
|
|||
|
|
@ -94,11 +94,18 @@ TabEdhRecMain::TabEdhRecMain(TabSupervisor *_tabSupervisor) : Tab(_tabSupervisor
|
|||
searchPushButton = new QPushButton(navigationContainer);
|
||||
connect(searchPushButton, &QPushButton::clicked, this, [=, this]() { doSearch(); });
|
||||
|
||||
settingsButton = new SettingsButtonWidget(this);
|
||||
|
||||
cardSizeSlider = new CardSizeWidget(this);
|
||||
|
||||
settingsButton->addSettingsWidget(cardSizeSlider);
|
||||
|
||||
navigationLayout->addWidget(cardsPushButton);
|
||||
navigationLayout->addWidget(topCommandersPushButton);
|
||||
navigationLayout->addWidget(tagsPushButton);
|
||||
navigationLayout->addWidget(searchBar);
|
||||
navigationLayout->addWidget(searchPushButton);
|
||||
navigationLayout->addWidget(settingsButton);
|
||||
|
||||
currentPageDisplay = new QWidget(container);
|
||||
currentPageLayout = new QVBoxLayout(currentPageDisplay);
|
||||
|
|
@ -349,7 +356,7 @@ void TabEdhRecMain::processAverageDeckResponse(QJsonObject reply)
|
|||
{
|
||||
EdhrecAverageDeckApiResponse deckData;
|
||||
deckData.fromJson(reply);
|
||||
tabSupervisor->addVisualDeckEditorTab(deckData.deck.deckLoader);
|
||||
tabSupervisor->openDeckInNewTab(deckData.deck.deckLoader);
|
||||
}
|
||||
|
||||
void TabEdhRecMain::prettyPrintJson(const QJsonValue &value, int indentLevel)
|
||||
|
|
|
|||
|
|
@ -2,7 +2,9 @@
|
|||
#define TAB_EDHREC_MAIN_H
|
||||
|
||||
#include "../../../../game/cards/card_database.h"
|
||||
#include "../../../ui/widgets/cards/card_size_widget.h"
|
||||
#include "../../../ui/widgets/general/layout_containers/flow_widget.h"
|
||||
#include "../../../ui/widgets/quick_settings/settings_button_widget.h"
|
||||
#include "../../tab.h"
|
||||
#include "display/commander/edhrec_commander_api_response_display_widget.h"
|
||||
|
||||
|
|
@ -25,6 +27,11 @@ public:
|
|||
return tr("EDHREC: ") + cardName;
|
||||
}
|
||||
|
||||
CardSizeWidget *getCardSizeSlider()
|
||||
{
|
||||
return cardSizeSlider;
|
||||
}
|
||||
|
||||
QNetworkAccessManager *networkManager;
|
||||
|
||||
public slots:
|
||||
|
|
@ -53,6 +60,8 @@ private:
|
|||
QPushButton *tagsPushButton;
|
||||
QLineEdit *searchBar;
|
||||
QPushButton *searchPushButton;
|
||||
SettingsButtonWidget *settingsButton;
|
||||
CardSizeWidget *cardSizeSlider;
|
||||
CardInfoPtr cardToQuery;
|
||||
EdhrecCommanderApiResponseDisplayWidget *displayWidget;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@
|
|||
#include "../../client/ui/widgets/cards/card_info_frame_widget.h"
|
||||
#include "../../dialogs/dlg_create_game.h"
|
||||
#include "../../game/board/arrow_item.h"
|
||||
#include "../../game/board/card_item.h"
|
||||
#include "../../game/cards/card_database.h"
|
||||
#include "../../game/cards/card_database_manager.h"
|
||||
#include "../../game/cards/card_item.h"
|
||||
#include "../../game/deckview/deck_view_container.h"
|
||||
#include "../../game/game_scene.h"
|
||||
#include "../../game/game_view.h"
|
||||
|
|
|
|||
|
|
@ -590,7 +590,7 @@ void TabSupervisor::actTabDeckStorage(bool checked)
|
|||
void TabSupervisor::openTabDeckStorage()
|
||||
{
|
||||
tabDeckStorage = new TabDeckStorage(this, client, userInfo);
|
||||
connect(tabDeckStorage, &TabDeckStorage::openDeckEditor, this, &TabSupervisor::addDeckEditorTab);
|
||||
connect(tabDeckStorage, &TabDeckStorage::openDeckEditor, this, &TabSupervisor::openDeckInNewTab);
|
||||
myAddTab(tabDeckStorage, aTabDeckStorage);
|
||||
connect(tabDeckStorage, &Tab::closed, this, [this] {
|
||||
tabDeckStorage = nullptr;
|
||||
|
|
@ -691,7 +691,7 @@ void TabSupervisor::gameJoined(const Event_GameJoined &event)
|
|||
auto *tab = new TabGame(this, QList<AbstractClient *>() << client, event, roomGameTypes);
|
||||
connect(tab, &TabGame::gameClosing, this, &TabSupervisor::gameLeft);
|
||||
connect(tab, &TabGame::openMessageDialog, this, &TabSupervisor::addMessageTab);
|
||||
connect(tab, &TabGame::openDeckEditor, this, &TabSupervisor::addDeckEditorTab);
|
||||
connect(tab, &TabGame::openDeckEditor, this, &TabSupervisor::openDeckInNewTab);
|
||||
myAddTab(tab);
|
||||
gameTabs.insert(event.game_info().game_id(), tab);
|
||||
setCurrentWidget(tab);
|
||||
|
|
@ -701,7 +701,7 @@ void TabSupervisor::localGameJoined(const Event_GameJoined &event)
|
|||
{
|
||||
auto *tab = new TabGame(this, localClients, event, QMap<int, QString>());
|
||||
connect(tab, &TabGame::gameClosing, this, &TabSupervisor::gameLeft);
|
||||
connect(tab, &TabGame::openDeckEditor, this, &TabSupervisor::addDeckEditorTab);
|
||||
connect(tab, &TabGame::openDeckEditor, this, &TabSupervisor::openDeckInNewTab);
|
||||
myAddTab(tab);
|
||||
gameTabs.insert(event.game_info().game_id(), tab);
|
||||
setCurrentWidget(tab);
|
||||
|
|
@ -807,6 +807,29 @@ void TabSupervisor::talkLeft(TabMessage *tab)
|
|||
removeTab(indexOf(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
|
||||
* @param deckToOpen The deck to open in the tab. Creates a copy of the DeckLoader instance.
|
||||
*/
|
||||
void TabSupervisor::openDeckInNewTab(const DeckLoader *deckToOpen)
|
||||
{
|
||||
int type = SettingsCache::instance().getDefaultDeckEditorType();
|
||||
switch (type) {
|
||||
case ClassicDeckEditor:
|
||||
addDeckEditorTab(deckToOpen);
|
||||
break;
|
||||
case VisualDeckEditor:
|
||||
addVisualDeckEditorTab(deckToOpen);
|
||||
break;
|
||||
default:
|
||||
qCWarning(TabSupervisorLog) << "Unknown DeckEditorType [" << type
|
||||
<< "]; opening ClassicDeckEditor as fallback";
|
||||
addDeckEditorTab(deckToOpen);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new deck editor tab
|
||||
* @param deckToOpen The deck to open in the tab. Creates a copy of the DeckLoader instance.
|
||||
|
|
|
|||
|
|
@ -75,6 +75,14 @@ protected:
|
|||
class TabSupervisor : public QTabWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum DeckEditorType
|
||||
{
|
||||
ClassicDeckEditor,
|
||||
VisualDeckEditor
|
||||
};
|
||||
|
||||
private:
|
||||
ServerInfo_User *userInfo;
|
||||
AbstractClient *client;
|
||||
|
|
@ -152,6 +160,7 @@ signals:
|
|||
void showWindowIfHidden();
|
||||
|
||||
public slots:
|
||||
void openDeckInNewTab(const DeckLoader *deckToOpen);
|
||||
TabDeckEditor *addDeckEditorTab(const DeckLoader *deckToOpen);
|
||||
TabDeckEditorVisual *addVisualDeckEditorTab(const DeckLoader *deckToOpen);
|
||||
TabVisualDatabaseDisplay *addVisualDatabaseDisplayTab();
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ void TabDeckEditorVisual::createCentralFrame()
|
|||
|
||||
void TabDeckEditorVisual::onDeckChanged()
|
||||
{
|
||||
AbstractTabDeckEditor::onDeckChanged();
|
||||
AbstractTabDeckEditor::onDeckModified();
|
||||
tabContainer->visualDeckView->decklistDataChanged(QModelIndex(), QModelIndex());
|
||||
tabContainer->deckAnalytics->refreshDisplays(deckDockWidget->deckModel);
|
||||
tabContainer->sampleHandWidget->setDeckModel(deckDockWidget->deckModel);
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
TabDeckStorageVisual::TabDeckStorageVisual(TabSupervisor *_tabSupervisor)
|
||||
: Tab(_tabSupervisor), visualDeckStorageWidget(new VisualDeckStorageWidget(this))
|
||||
{
|
||||
connect(this, &TabDeckStorageVisual::openDeckEditor, tabSupervisor, &TabSupervisor::addVisualDeckEditorTab);
|
||||
connect(this, &TabDeckStorageVisual::openDeckEditor, tabSupervisor, &TabSupervisor::openDeckInNewTab);
|
||||
connect(visualDeckStorageWidget, &VisualDeckStorageWidget::deckLoadRequested, this,
|
||||
&TabDeckStorageVisual::actOpenLocalDeck);
|
||||
connect(visualDeckStorageWidget, &VisualDeckStorageWidget::openDeckEditor, this,
|
||||
|
|
|
|||
|
|
@ -92,16 +92,9 @@ void TappedOutInterface::analyzeDeck(DeckList *deck)
|
|||
manager->post(request, data);
|
||||
}
|
||||
|
||||
struct CopyMainOrSide
|
||||
void TappedOutInterface::copyDeckSplitMainAndSide(DeckList &source, DeckList &mainboard, DeckList &sideboard)
|
||||
{
|
||||
CardDatabase &cardDatabase;
|
||||
DeckList &mainboard, &sideboard;
|
||||
|
||||
CopyMainOrSide(CardDatabase &_cardDatabase, DeckList &_mainboard, DeckList &_sideboard)
|
||||
: cardDatabase(_cardDatabase), mainboard(_mainboard), sideboard(_sideboard){};
|
||||
|
||||
void operator()(const InnerDecklistNode *node, const DecklistCardNode *card) const
|
||||
{
|
||||
auto copyMainOrSide = [this, &mainboard, &sideboard](const auto node, const auto card) {
|
||||
CardInfoPtr dbCard = cardDatabase.getCard(card->getName());
|
||||
if (!dbCard || dbCard->getIsToken())
|
||||
return;
|
||||
|
|
@ -112,11 +105,7 @@ struct CopyMainOrSide
|
|||
else
|
||||
addedCard = mainboard.addCard(card->getName(), node->getName());
|
||||
addedCard->setNumber(card->getNumber());
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
void TappedOutInterface::copyDeckSplitMainAndSide(DeckList &source, DeckList &mainboard, DeckList &sideboard)
|
||||
{
|
||||
CopyMainOrSide copyMainOrSide(cardDatabase, mainboard, sideboard);
|
||||
source.forEachCard(copyMainOrSide);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#include "picture_to_load.h"
|
||||
|
||||
#include "../../../settings/cache_settings.h"
|
||||
#include "../../../utility/card_set_comparator.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QDate>
|
||||
|
|
@ -20,7 +21,7 @@ PictureToLoad::PictureToLoad(CardInfoPtr _card)
|
|||
if (sortedSets.empty()) {
|
||||
sortedSets << CardSet::newInstance("", "", "", QDate());
|
||||
}
|
||||
std::sort(sortedSets.begin(), sortedSets.end(), SetDownloadPriorityComparator());
|
||||
std::sort(sortedSets.begin(), sortedSets.end(), SetPriorityComparator());
|
||||
|
||||
// If the user hasn't disabled arts other than their personal preference...
|
||||
if (!SettingsCache::instance().getOverrideAllCardArtWithPersonalPreference()) {
|
||||
|
|
|
|||
|
|
@ -10,24 +10,6 @@ inline Q_LOGGING_CATEGORY(PictureToLoadLog, "picture_loader.picture_to_load");
|
|||
class PictureToLoad
|
||||
{
|
||||
private:
|
||||
class SetDownloadPriorityComparator
|
||||
{
|
||||
public:
|
||||
/*
|
||||
* Returns true if a has higher download priority than b
|
||||
* Enabled sets have priority over disabled sets
|
||||
* Both groups follows the user-defined order
|
||||
*/
|
||||
inline bool operator()(const CardSetPtr &a, const CardSetPtr &b) const
|
||||
{
|
||||
if (a->getEnabled()) {
|
||||
return !b->getEnabled() || a->getSortKey() < b->getSortKey();
|
||||
} else {
|
||||
return !b->getEnabled() && a->getSortKey() < b->getSortKey();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
CardInfoPtr card;
|
||||
QList<CardSetPtr> sortedSets;
|
||||
QList<QString> urlTemplates;
|
||||
|
|
|
|||
|
|
@ -20,12 +20,17 @@ ManaSymbolWidget::ManaSymbolWidget(QWidget *parent, QString _symbol, bool _isAct
|
|||
&ManaSymbolWidget::updateOpacity);
|
||||
}
|
||||
|
||||
void ManaSymbolWidget::toggleSymbol()
|
||||
{
|
||||
setColorActive(!isActive);
|
||||
emit colorToggled(getSymbolChar(), isActive);
|
||||
}
|
||||
|
||||
void ManaSymbolWidget::setColorActive(bool active)
|
||||
{
|
||||
if (isActive != active) {
|
||||
isActive = active;
|
||||
updateOpacity();
|
||||
emit colorToggled(getSymbolChar(), isActive);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -46,9 +51,7 @@ void ManaSymbolWidget::mousePressEvent(QMouseEvent *event)
|
|||
{
|
||||
Q_UNUSED(event);
|
||||
if (mayBeToggled) {
|
||||
isActive = !isActive;
|
||||
updateOpacity();
|
||||
emit colorToggled(getSymbolChar(), isActive);
|
||||
toggleSymbol();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -63,7 +66,7 @@ void ManaSymbolWidget::loadManaIcon()
|
|||
QString filename = "theme:icons/mana/";
|
||||
|
||||
if (symbol == "W" || symbol == "U" || symbol == "B" || symbol == "R" || symbol == "G") {
|
||||
filename += symbol + ".svg";
|
||||
filename += symbol;
|
||||
}
|
||||
|
||||
manaIcon = QPixmap(filename);
|
||||
|
|
|
|||
|
|
@ -11,9 +11,13 @@ class ManaSymbolWidget : public QLabel
|
|||
|
||||
public:
|
||||
ManaSymbolWidget(QWidget *parent, QString symbol, bool isActive = true, bool mayBeToggled = false);
|
||||
void toggleSymbol();
|
||||
void setColorActive(bool active);
|
||||
void updateOpacity();
|
||||
bool isColorActive() const;
|
||||
bool isColorActive() const
|
||||
{
|
||||
return isActive;
|
||||
};
|
||||
QString getSymbol() const
|
||||
{
|
||||
return symbol;
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ CardGroupDisplayWidget::CardGroupDisplayWidget(QWidget *parent,
|
|||
banner = new BannerWidget(this, cardGroupCategory, Qt::Orientation::Vertical, bannerOpacity);
|
||||
|
||||
layout->addWidget(banner);
|
||||
updateCardDisplays();
|
||||
CardGroupDisplayWidget::updateCardDisplays();
|
||||
}
|
||||
|
||||
void CardGroupDisplayWidget::updateCardDisplays()
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#include "card_info_display_widget.h"
|
||||
|
||||
#include "../../../../game/board/card_item.h"
|
||||
#include "../../../../game/cards/card_database_manager.h"
|
||||
#include "../../../../game/cards/card_item.h"
|
||||
#include "../../../../main.h"
|
||||
#include "card_info_picture_widget.h"
|
||||
#include "card_info_text_widget.h"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#include "card_info_frame_widget.h"
|
||||
|
||||
#include "../../../../game/board/card_item.h"
|
||||
#include "../../../../game/cards/card_database_manager.h"
|
||||
#include "../../../../game/cards/card_item.h"
|
||||
#include "../../../../settings/cache_settings.h"
|
||||
#include "card_info_display_widget.h"
|
||||
#include "card_info_picture_widget.h"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#include "card_info_picture_widget.h"
|
||||
|
||||
#include "../../../../game/board/card_item.h"
|
||||
#include "../../../../game/cards/card_database_manager.h"
|
||||
#include "../../../../game/cards/card_item.h"
|
||||
#include "../../../../settings/cache_settings.h"
|
||||
#include "../../../tabs/tab_supervisor.h"
|
||||
#include "../../picture_loader/picture_loader.h"
|
||||
|
|
@ -64,6 +64,12 @@ CardInfoPictureWidget::CardInfoPictureWidget(QWidget *parent, const bool _hoverT
|
|||
});
|
||||
}
|
||||
|
||||
CardInfoPictureWidget::~CardInfoPictureWidget()
|
||||
{
|
||||
enlargedPixmapWidget->hide();
|
||||
enlargedPixmapWidget->deleteLater();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the card to be displayed and updates the pixmap.
|
||||
* @param card A shared pointer to the card information (CardInfoPtr).
|
||||
|
|
@ -341,6 +347,12 @@ void CardInfoPictureWidget::mousePressEvent(QMouseEvent *event)
|
|||
emit cardClicked();
|
||||
}
|
||||
|
||||
void CardInfoPictureWidget::hideEvent(QHideEvent *event)
|
||||
{
|
||||
enlargedPixmapWidget->hide();
|
||||
QWidget::hideEvent(event);
|
||||
}
|
||||
|
||||
QMenu *CardInfoPictureWidget::createRightClickMenu()
|
||||
{
|
||||
auto *cardMenu = new QMenu(this);
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ public:
|
|||
explicit CardInfoPictureWidget(QWidget *parent = nullptr,
|
||||
bool hoverToZoomEnabled = false,
|
||||
bool raiseOnEnter = false);
|
||||
~CardInfoPictureWidget();
|
||||
CardInfoPtr getInfo()
|
||||
{
|
||||
return info;
|
||||
|
|
@ -52,6 +53,7 @@ protected:
|
|||
void moveEvent(QMoveEvent *event) override;
|
||||
void mouseMoveEvent(QMouseEvent *event) override;
|
||||
void mousePressEvent(QMouseEvent *event) override;
|
||||
void hideEvent(QHideEvent *event) override;
|
||||
void loadPixmap();
|
||||
[[nodiscard]] const QPixmap &getResizedPixmap() const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#include "card_info_text_widget.h"
|
||||
|
||||
#include "../../../../game/cards/card_item.h"
|
||||
#include "../../../../game/board/card_item.h"
|
||||
#include "../../../../game/game_specific_terms.h"
|
||||
|
||||
#include <QGridLayout>
|
||||
|
|
|
|||
|
|
@ -34,14 +34,7 @@ CardSizeWidget::CardSizeWidget(QWidget *parent, FlowWidget *_flowWidget, int def
|
|||
|
||||
// Debounce setup
|
||||
debounceTimer.setSingleShot(true);
|
||||
connect(&debounceTimer, &QTimer::timeout, this, [this]() {
|
||||
// Check the type of the parent widget
|
||||
if (qobject_cast<PrintingSelector *>(parentWidget())) {
|
||||
SettingsCache::instance().setPrintingSelectorCardSize(pendingValue);
|
||||
} else if (qobject_cast<VisualDeckStorageWidget *>(parentWidget())) {
|
||||
SettingsCache::instance().setVisualDeckStorageCardSize(pendingValue);
|
||||
}
|
||||
});
|
||||
connect(&debounceTimer, &QTimer::timeout, this, [this] { emit cardSizeSettingUpdated(pendingValue); });
|
||||
|
||||
connect(cardSizeSlider, &QSlider::valueChanged, this, &CardSizeWidget::updateCardSizeSetting);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,9 +17,17 @@ public:
|
|||
explicit CardSizeWidget(QWidget *parent, FlowWidget *flowWidget = nullptr, int defaultValue = 100);
|
||||
[[nodiscard]] QSlider *getSlider() const;
|
||||
|
||||
public slots:
|
||||
private slots:
|
||||
void updateCardSizeSetting(int newValue);
|
||||
|
||||
signals:
|
||||
/**
|
||||
* Emitted when the slider value changes, but on a debounce timer.
|
||||
* Any parents that care about saving the value to settings should use this signal to indicate when to save the new
|
||||
* value to settings.
|
||||
*/
|
||||
void cardSizeSettingUpdated(int newValue);
|
||||
|
||||
private:
|
||||
QWidget *parent;
|
||||
FlowWidget *flowWidget;
|
||||
|
|
|
|||
|
|
@ -93,6 +93,8 @@ void DeckCardZoneDisplayWidget::addCardGroupIfItDoesNotExist()
|
|||
for (CardGroupDisplayWidget *cardGroupDisplayWidget : cardGroupsDisplayWidgets) {
|
||||
if (cardGroupDisplayWidget->cardGroupCategory == cardGroup) {
|
||||
found = true;
|
||||
cardGroupDisplayWidget->updateCardDisplays();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,14 +6,25 @@ DeckAnalyticsWidget::DeckAnalyticsWidget(QWidget *parent, DeckListModel *_deckLi
|
|||
mainLayout = new QVBoxLayout();
|
||||
setLayout(mainLayout);
|
||||
|
||||
scrollArea = new QScrollArea(this);
|
||||
scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
||||
scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
scrollArea->setWidgetResizable(true);
|
||||
mainLayout->addWidget(scrollArea);
|
||||
|
||||
container = new QWidget(scrollArea);
|
||||
containerLayout = new QVBoxLayout(container);
|
||||
container->setLayout(containerLayout);
|
||||
scrollArea->setWidget(container);
|
||||
|
||||
manaCurveWidget = new ManaCurveWidget(this, deckListModel);
|
||||
mainLayout->addWidget(manaCurveWidget);
|
||||
containerLayout->addWidget(manaCurveWidget);
|
||||
|
||||
manaDevotionWidget = new ManaDevotionWidget(this, deckListModel);
|
||||
mainLayout->addWidget(manaDevotionWidget);
|
||||
containerLayout->addWidget(manaDevotionWidget);
|
||||
|
||||
manaBaseWidget = new ManaBaseWidget(this, deckListModel);
|
||||
mainLayout->addWidget(manaBaseWidget);
|
||||
containerLayout->addWidget(manaBaseWidget);
|
||||
}
|
||||
|
||||
void DeckAnalyticsWidget::refreshDisplays(DeckListModel *_deckModel)
|
||||
|
|
|
|||
|
|
@ -8,9 +8,10 @@
|
|||
#include "mana_devotion_widget.h"
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QScrollArea>
|
||||
#include <QVBoxLayout>
|
||||
#include <QWidget>
|
||||
#include <decklist.h>
|
||||
#include <qscrollarea.h>
|
||||
|
||||
class DeckAnalyticsWidget : public QWidget
|
||||
{
|
||||
|
|
@ -26,6 +27,11 @@ private:
|
|||
DeckListModel *deckListModel;
|
||||
QVBoxLayout *mainLayout;
|
||||
|
||||
QWidget *container;
|
||||
QVBoxLayout *containerLayout;
|
||||
|
||||
QScrollArea *scrollArea;
|
||||
|
||||
ManaCurveWidget *manaCurveWidget;
|
||||
ManaDevotionWidget *manaDevotionWidget;
|
||||
ManaBaseWidget *manaBaseWidget;
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ void ManaCurveWidget::updateDisplay()
|
|||
// Add new widgets to the layout in sorted order
|
||||
for (const auto &entry : sortedManaCurve) {
|
||||
BarWidget *barWidget =
|
||||
new BarWidget(QString::number(entry.first), entry.second, highestEntry, QColor(11, 11, 11), this);
|
||||
new BarWidget(QString::number(entry.first), entry.second, highestEntry, QColor(122, 122, 122), this);
|
||||
barLayout->addWidget(barWidget);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -58,6 +58,28 @@ void DeckEditorDeckDockWidget::createDeckDock()
|
|||
nameEdit->setObjectName("nameEdit");
|
||||
nameLabel->setBuddy(nameEdit);
|
||||
connect(nameEdit, &LineEditUnfocusable::textChanged, this, &DeckEditorDeckDockWidget::updateName);
|
||||
|
||||
quickSettingsWidget = new SettingsButtonWidget(this);
|
||||
|
||||
showBannerCardCheckBox = new QCheckBox();
|
||||
showBannerCardCheckBox->setObjectName("showBannerCardCheckBox");
|
||||
showBannerCardCheckBox->setChecked(SettingsCache::instance().getDeckEditorBannerCardComboBoxVisible());
|
||||
connect(showBannerCardCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(),
|
||||
&SettingsCache::setDeckEditorBannerCardComboBoxVisible);
|
||||
connect(&SettingsCache::instance(), &SettingsCache::deckEditorBannerCardComboBoxVisibleChanged, this,
|
||||
&DeckEditorDeckDockWidget::updateShowBannerCardComboBox);
|
||||
|
||||
showTagsWidgetCheckBox = new QCheckBox();
|
||||
showTagsWidgetCheckBox->setObjectName("showTagsWidgetCheckBox");
|
||||
showTagsWidgetCheckBox->setChecked(SettingsCache::instance().getDeckEditorTagsWidgetVisible());
|
||||
connect(showTagsWidgetCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(),
|
||||
&SettingsCache::setDeckEditorTagsWidgetVisible);
|
||||
connect(&SettingsCache::instance(), &SettingsCache::deckEditorTagsWidgetVisibleChanged, this,
|
||||
&DeckEditorDeckDockWidget::updateShowTagsWidget);
|
||||
|
||||
quickSettingsWidget->addSettingsWidget(showBannerCardCheckBox);
|
||||
quickSettingsWidget->addSettingsWidget(showTagsWidgetCheckBox);
|
||||
|
||||
commentsLabel = new QLabel();
|
||||
commentsLabel->setObjectName("commentsLabel");
|
||||
commentsEdit = new QTextEdit;
|
||||
|
|
@ -69,6 +91,7 @@ void DeckEditorDeckDockWidget::createDeckDock()
|
|||
bannerCardLabel = new QLabel();
|
||||
bannerCardLabel->setObjectName("bannerCardLabel");
|
||||
bannerCardLabel->setText(tr("Banner Card"));
|
||||
bannerCardLabel->setHidden(!SettingsCache::instance().getDeckEditorBannerCardComboBoxVisible());
|
||||
bannerCardComboBox = new QComboBox(this);
|
||||
connect(deckModel, &DeckListModel::dataChanged, this, [this]() {
|
||||
// Delay the update to avoid race conditions
|
||||
|
|
@ -76,8 +99,10 @@ void DeckEditorDeckDockWidget::createDeckDock()
|
|||
});
|
||||
connect(bannerCardComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
|
||||
&DeckEditorDeckDockWidget::setBannerCard);
|
||||
bannerCardComboBox->setHidden(!SettingsCache::instance().getDeckEditorBannerCardComboBoxVisible());
|
||||
|
||||
deckTagsDisplayWidget = new DeckPreviewDeckTagsDisplayWidget(this, deckModel->getDeckList());
|
||||
deckTagsDisplayWidget->setHidden(!SettingsCache::instance().getDeckEditorTagsWidgetVisible());
|
||||
|
||||
aIncrement = new QAction(QString(), this);
|
||||
aIncrement->setIcon(QPixmap("theme:icons/increment"));
|
||||
|
|
@ -109,6 +134,7 @@ void DeckEditorDeckDockWidget::createDeckDock()
|
|||
|
||||
upperLayout->addWidget(nameLabel, 0, 0);
|
||||
upperLayout->addWidget(nameEdit, 0, 1);
|
||||
upperLayout->addWidget(quickSettingsWidget, 0, 2);
|
||||
|
||||
upperLayout->addWidget(commentsLabel, 1, 0);
|
||||
upperLayout->addWidget(commentsEdit, 1, 1);
|
||||
|
|
@ -202,19 +228,22 @@ void DeckEditorDeckDockWidget::updateCard(const QModelIndex /*¤t*/, const
|
|||
void DeckEditorDeckDockWidget::updateName(const QString &name)
|
||||
{
|
||||
deckModel->getDeckList()->setName(name);
|
||||
emit deckChanged();
|
||||
emit nameChanged();
|
||||
emit deckModified();
|
||||
}
|
||||
|
||||
void DeckEditorDeckDockWidget::updateComments()
|
||||
{
|
||||
deckModel->getDeckList()->setComments(commentsEdit->toPlainText());
|
||||
emit deckChanged();
|
||||
emit commentsChanged();
|
||||
emit deckModified();
|
||||
}
|
||||
|
||||
void DeckEditorDeckDockWidget::updateHash()
|
||||
{
|
||||
hashLabel->setText(deckModel->getDeckList()->getDeckHash());
|
||||
emit deckChanged();
|
||||
emit hashChanged();
|
||||
emit deckModified();
|
||||
}
|
||||
|
||||
void DeckEditorDeckDockWidget::updateBannerCardComboBox()
|
||||
|
|
@ -268,6 +297,10 @@ void DeckEditorDeckDockWidget::updateBannerCardComboBox()
|
|||
int restoredIndex = bannerCardComboBox->findText(currentText);
|
||||
if (restoredIndex != -1) {
|
||||
bannerCardComboBox->setCurrentIndex(restoredIndex);
|
||||
if (deckModel->getDeckList()->getBannerCard().second !=
|
||||
bannerCardComboBox->itemData(bannerCardComboBox->currentIndex()).toMap()["uuid"].toString()) {
|
||||
setBannerCard(restoredIndex);
|
||||
}
|
||||
} else {
|
||||
// Add a placeholder "-" and set it as the current selection
|
||||
int bannerIndex = bannerCardComboBox->findText(deckModel->getDeckList()->getBannerCard().first);
|
||||
|
|
@ -288,7 +321,18 @@ void DeckEditorDeckDockWidget::setBannerCard(int /* changedIndex */)
|
|||
QVariantMap itemData = bannerCardComboBox->itemData(bannerCardComboBox->currentIndex()).toMap();
|
||||
deckModel->getDeckList()->setBannerCard(
|
||||
QPair<QString, QString>(itemData["name"].toString(), itemData["uuid"].toString()));
|
||||
emit deckChanged();
|
||||
emit deckModified();
|
||||
}
|
||||
|
||||
void DeckEditorDeckDockWidget::updateShowBannerCardComboBox(const bool visible)
|
||||
{
|
||||
bannerCardLabel->setHidden(!visible);
|
||||
bannerCardComboBox->setHidden(!visible);
|
||||
}
|
||||
|
||||
void DeckEditorDeckDockWidget::updateShowTagsWidget(const bool visible)
|
||||
{
|
||||
deckTagsDisplayWidget->setHidden(!visible);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -325,8 +369,12 @@ void DeckEditorDeckDockWidget::cleanDeck()
|
|||
{
|
||||
deckModel->cleanList();
|
||||
nameEdit->setText(QString());
|
||||
emit nameChanged();
|
||||
commentsEdit->setText(QString());
|
||||
emit commentsChanged();
|
||||
hashLabel->setText(QString());
|
||||
emit hashChanged();
|
||||
emit deckModified();
|
||||
emit deckChanged();
|
||||
updateBannerCardComboBox();
|
||||
deckTagsDisplayWidget->connectDeckList(deckModel->getDeckList());
|
||||
|
|
@ -385,7 +433,7 @@ void DeckEditorDeckDockWidget::actSwapCard()
|
|||
deckView->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||
|
||||
if (isModified) {
|
||||
emit deckChanged();
|
||||
emit deckModified();
|
||||
}
|
||||
|
||||
update();
|
||||
|
|
@ -480,7 +528,7 @@ void DeckEditorDeckDockWidget::actRemoveCard()
|
|||
deckView->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||
|
||||
if (isModified) {
|
||||
emit deckChanged();
|
||||
emit deckModified();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -498,7 +546,7 @@ void DeckEditorDeckDockWidget::offsetCountAtIndex(const QModelIndex &idx, int of
|
|||
else
|
||||
deckModel->setData(numberIndex, new_count, Qt::EditRole);
|
||||
|
||||
emit deckChanged();
|
||||
emit deckModified();
|
||||
}
|
||||
|
||||
void DeckEditorDeckDockWidget::decklistCustomMenu(QPoint point)
|
||||
|
|
@ -526,6 +574,9 @@ void DeckEditorDeckDockWidget::retranslateUi()
|
|||
setWindowTitle(tr("Deck"));
|
||||
|
||||
nameLabel->setText(tr("Deck &name:"));
|
||||
quickSettingsWidget->setToolTip(tr("Banner Card/Tags Visibility Settings"));
|
||||
showBannerCardCheckBox->setText(tr("Show banner card selection menu"));
|
||||
showTagsWidgetCheckBox->setText(tr("Show tags selection menu"));
|
||||
commentsLabel->setText(tr("&Comments:"));
|
||||
hashLabel1->setText(tr("Hash:"));
|
||||
|
||||
|
|
|
|||
|
|
@ -49,7 +49,11 @@ public slots:
|
|||
void offsetCountAtIndex(const QModelIndex &idx, int offset);
|
||||
|
||||
signals:
|
||||
void nameChanged();
|
||||
void commentsChanged();
|
||||
void hashChanged();
|
||||
void deckChanged();
|
||||
void deckModified();
|
||||
void cardChanged(CardInfoPtr _card);
|
||||
|
||||
private:
|
||||
|
|
@ -57,6 +61,9 @@ private:
|
|||
KeySignals deckViewKeySignals;
|
||||
QLabel *nameLabel;
|
||||
LineEditUnfocusable *nameEdit;
|
||||
SettingsButtonWidget *quickSettingsWidget;
|
||||
QCheckBox *showBannerCardCheckBox;
|
||||
QCheckBox *showTagsWidgetCheckBox;
|
||||
QLabel *commentsLabel;
|
||||
QTextEdit *commentsEdit;
|
||||
QLabel *bannerCardLabel;
|
||||
|
|
@ -77,6 +84,8 @@ private slots:
|
|||
void setBannerCard(int);
|
||||
void updateHash();
|
||||
void refreshShortcuts();
|
||||
void updateShowBannerCardComboBox(bool visible);
|
||||
void updateShowTagsWidget(bool visible);
|
||||
};
|
||||
|
||||
#endif // DECK_EDITOR_DECK_DOCK_WIDGET_H
|
||||
|
|
|
|||
|
|
@ -0,0 +1,46 @@
|
|||
#include "percent_bar_widget.h"
|
||||
|
||||
PercentBarWidget::PercentBarWidget(QWidget *parent, double initialValue) : QWidget(parent), valueToDisplay(initialValue)
|
||||
{
|
||||
setMinimumSize(50, 10);
|
||||
}
|
||||
|
||||
void PercentBarWidget::paintEvent(QPaintEvent *event)
|
||||
{
|
||||
Q_UNUSED(event);
|
||||
|
||||
QPainter painter(this);
|
||||
QRect rect = this->rect();
|
||||
|
||||
const int midX = rect.width() / 2;
|
||||
const int height = rect.height();
|
||||
|
||||
// Draw background border (no fill)
|
||||
painter.setPen(QPen(Qt::black, 1));
|
||||
painter.setBrush(Qt::NoBrush);
|
||||
painter.drawRect(rect.adjusted(0, 0, -1, -1)); // Avoid right/bottom overflow
|
||||
|
||||
const double halfWidth = rect.width() / 2.0;
|
||||
|
||||
const int barLength = static_cast<int>((qAbs(valueToDisplay) / 100.0) * halfWidth);
|
||||
|
||||
QRect fillRect;
|
||||
if (valueToDisplay > 0.0) {
|
||||
fillRect = QRect(midX, 0, barLength, height);
|
||||
painter.fillRect(fillRect, Qt::green);
|
||||
} else if (valueToDisplay < 0.0) {
|
||||
fillRect = QRect(midX - barLength, 0, barLength, height);
|
||||
painter.fillRect(fillRect, Qt::red);
|
||||
}
|
||||
|
||||
// Draw center line at 0
|
||||
painter.fillRect(midX - 1, 0, 3, height, Qt::white);
|
||||
|
||||
// Draw tick marks every 10%
|
||||
const int tickHeight = 4;
|
||||
|
||||
for (int percent = -100; percent <= 100; percent += 10) {
|
||||
int x = midX + static_cast<int>((percent / 100.0) * halfWidth);
|
||||
painter.drawLine(x, height - tickHeight, x, height);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
#ifndef PERCENT_BAR_WIDGET_H
|
||||
#define PERCENT_BAR_WIDGET_H
|
||||
|
||||
#include <QColor>
|
||||
#include <QPainter>
|
||||
#include <QWidget>
|
||||
|
||||
class PercentBarWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit PercentBarWidget(QWidget *parent, double initialValue);
|
||||
|
||||
void setValue(double newValue)
|
||||
{
|
||||
valueToDisplay = qBound(-100.0, newValue, 100.0); // Clamp to [-100, 100]
|
||||
update(); // Trigger repaint
|
||||
}
|
||||
|
||||
double value() const
|
||||
{
|
||||
return valueToDisplay;
|
||||
}
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
|
||||
private:
|
||||
double valueToDisplay; // Ranges from -100 to 100
|
||||
};
|
||||
|
||||
#endif // PERCENT_BAR_WIDGET_H
|
||||
|
|
@ -70,6 +70,8 @@ PrintingSelector::PrintingSelector(QWidget *parent, AbstractTabDeckEditor *_deck
|
|||
|
||||
cardSizeWidget =
|
||||
new CardSizeWidget(displayOptionsWidget, flowWidget, SettingsCache::instance().getPrintingSelectorCardSize());
|
||||
connect(cardSizeWidget, &CardSizeWidget::cardSizeSettingUpdated, &SettingsCache::instance(),
|
||||
&SettingsCache::setPrintingSelectorCardSize);
|
||||
|
||||
displayOptionsWidget->addSettingsWidget(sortToolBar);
|
||||
displayOptionsWidget->addSettingsWidget(navigationCheckBox);
|
||||
|
|
|
|||
|
|
@ -27,9 +27,6 @@ VisualDatabaseDisplayColorFilterWidget::VisualDatabaseDisplayColorFilterWidget(Q
|
|||
|
||||
layout->addWidget(manaSymbol);
|
||||
|
||||
// Initialize the activeColors map
|
||||
activeColors[color] = false;
|
||||
|
||||
// Connect the color toggled signal
|
||||
connect(manaSymbol, &ManaSymbolWidget::colorToggled, this,
|
||||
&VisualDatabaseDisplayColorFilterWidget::handleColorToggled);
|
||||
|
|
@ -41,16 +38,8 @@ VisualDatabaseDisplayColorFilterWidget::VisualDatabaseDisplayColorFilterWidget(Q
|
|||
|
||||
// Connect the button's toggled signal
|
||||
connect(toggleButton, &QPushButton::toggled, this, &VisualDatabaseDisplayColorFilterWidget::updateFilterMode);
|
||||
connect(this, &VisualDatabaseDisplayColorFilterWidget::activeColorsChanged, this,
|
||||
&VisualDatabaseDisplayColorFilterWidget::updateColorFilter);
|
||||
connect(this, &VisualDatabaseDisplayColorFilterWidget::filterModeChanged, this,
|
||||
&VisualDatabaseDisplayColorFilterWidget::updateColorFilter);
|
||||
connect(filterModel, &FilterTreeModel::layoutChanged, this, [this]() {
|
||||
if (blockSync) {
|
||||
return; // Skip sync if we're blocking it
|
||||
}
|
||||
QTimer::singleShot(100, this, &VisualDatabaseDisplayColorFilterWidget::syncWithFilterModel);
|
||||
});
|
||||
connect(filterModel, &FilterTreeModel::layoutChanged, this,
|
||||
[this]() { QTimer::singleShot(100, this, &VisualDatabaseDisplayColorFilterWidget::syncWithFilterModel); });
|
||||
|
||||
// Call retranslateUi to set the initial text
|
||||
retranslateUi();
|
||||
|
|
@ -69,95 +58,94 @@ void VisualDatabaseDisplayColorFilterWidget::retranslateUi()
|
|||
toggleButton->setText(tr("Mode: Include/Exclude"));
|
||||
break;
|
||||
}
|
||||
|
||||
toggleButton->setToolTip(tr("Filter mode (AND/OR/NOT conjunctions of filters)"));
|
||||
}
|
||||
|
||||
void VisualDatabaseDisplayColorFilterWidget::handleColorToggled(QChar color, bool active)
|
||||
{
|
||||
activeColors[color] = active;
|
||||
emit activeColorsChanged(); // Notify listeners that the active colors have changed
|
||||
if (active) {
|
||||
addFilter(color);
|
||||
} else {
|
||||
removeFilter(color);
|
||||
}
|
||||
}
|
||||
|
||||
void VisualDatabaseDisplayColorFilterWidget::updateColorFilter()
|
||||
void VisualDatabaseDisplayColorFilterWidget::addFilter(QChar color)
|
||||
{
|
||||
blockSync = true;
|
||||
QString colorString = color;
|
||||
QString typeStr;
|
||||
|
||||
// Clear previous filters
|
||||
filterModel->blockSignals(true);
|
||||
filterModel->filterTree()->blockSignals(true);
|
||||
filterModel->clearFiltersOfType(CardFilter::Attr::AttrColor);
|
||||
// Remove previous filters
|
||||
|
||||
QSet<QString> selectedColors;
|
||||
QSet<QString> excludedColors;
|
||||
QList<const CardFilter *> allColorFilters = filterModel->getFiltersOfType(CardFilter::Attr::AttrColor);
|
||||
QList<const CardFilter *> matchingFilters;
|
||||
|
||||
// Collect active colors in the selected and excluded sets
|
||||
for (const auto &color : activeColors.keys()) {
|
||||
if (activeColors[color]) {
|
||||
selectedColors.insert(color); // Include this color
|
||||
} else {
|
||||
excludedColors.insert(color); // Exclude this color
|
||||
for (const CardFilter *filter : allColorFilters) {
|
||||
if (filter->term() == color) {
|
||||
matchingFilters.append(filter);
|
||||
}
|
||||
}
|
||||
|
||||
for (const CardFilter *filter : matchingFilters) {
|
||||
filterModel->removeFilter(filter);
|
||||
}
|
||||
|
||||
// Add actual filter
|
||||
|
||||
switch (currentMode) {
|
||||
case FilterMode::ExactMatch:
|
||||
// Exact Match Mode: Only selected colors are allowed
|
||||
if (!selectedColors.isEmpty()) {
|
||||
// Require all selected colors (TypeAnd)
|
||||
for (const auto &color : selectedColors) {
|
||||
QString colorString = color;
|
||||
filterModel->addFilter(
|
||||
new CardFilter(colorString, CardFilter::Type::TypeAnd, CardFilter::Attr::AttrColor));
|
||||
}
|
||||
|
||||
// Exclude all other colors
|
||||
QStringList allPossibleColors = {"W", "U", "B", "R", "G"};
|
||||
for (const auto &color : allPossibleColors) {
|
||||
if (!selectedColors.contains(color)) {
|
||||
QString colorString = color;
|
||||
filterModel->addFilter(
|
||||
new CardFilter(colorString, CardFilter::Type::TypeAndNot, CardFilter::Attr::AttrColor));
|
||||
}
|
||||
}
|
||||
}
|
||||
filterModel->addFilter(new CardFilter(colorString, CardFilter::Type::TypeAnd, CardFilter::Attr::AttrColor));
|
||||
break;
|
||||
|
||||
case FilterMode::Includes:
|
||||
// Includes Mode: Just include selected colors without restrictions
|
||||
for (const auto &color : selectedColors) {
|
||||
QString colorString = color;
|
||||
filterModel->addFilter(new CardFilter(colorString, CardFilter::Type::TypeOr,
|
||||
CardFilter::Attr::AttrColor)); // OR for selected colors
|
||||
}
|
||||
filterModel->addFilter(new CardFilter(colorString, CardFilter::Type::TypeOr, CardFilter::Attr::AttrColor));
|
||||
break;
|
||||
|
||||
case FilterMode::IncludeExclude:
|
||||
// Include/Exclude Mode: Include selected colors and exclude unselected colors
|
||||
for (const auto &color : selectedColors) {
|
||||
QString colorString = color;
|
||||
filterModel->addFilter(new CardFilter(colorString, CardFilter::Type::TypeOr,
|
||||
CardFilter::Attr::AttrColor)); // OR for selected colors
|
||||
}
|
||||
for (const auto &color : excludedColors) {
|
||||
QString colorString = color;
|
||||
filterModel->addFilter(new CardFilter(colorString, CardFilter::Type::TypeAndNot,
|
||||
CardFilter::Attr::AttrColor)); // AND NOT for excluded colors
|
||||
}
|
||||
filterModel->addFilter(new CardFilter(colorString, CardFilter::Type::TypeOr, CardFilter::Attr::AttrColor));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
filterModel->blockSignals(false);
|
||||
filterModel->filterTree()->blockSignals(false);
|
||||
void VisualDatabaseDisplayColorFilterWidget::removeFilter(QChar color)
|
||||
{
|
||||
QString colorString = color;
|
||||
|
||||
emit filterModel->filterTree()->changed();
|
||||
emit filterModel->layoutChanged();
|
||||
// Remove inclusion filters
|
||||
QList<const CardFilter *> allColorFilters = filterModel->getFiltersOfType(CardFilter::Attr::AttrColor);
|
||||
QList<const CardFilter *> matchingFilters;
|
||||
|
||||
blockSync = false;
|
||||
for (const CardFilter *filter : allColorFilters) {
|
||||
if (filter->term() == color) {
|
||||
matchingFilters.append(filter);
|
||||
}
|
||||
}
|
||||
|
||||
for (const CardFilter *filter : matchingFilters) {
|
||||
filterModel->removeFilter(filter);
|
||||
}
|
||||
|
||||
// Add exclusion filters if the mode demands it
|
||||
switch (currentMode) {
|
||||
case FilterMode::ExactMatch:
|
||||
filterModel->addFilter(
|
||||
new CardFilter(colorString, CardFilter::Type::TypeAndNot, CardFilter::Attr::AttrColor));
|
||||
break;
|
||||
|
||||
case FilterMode::IncludeExclude:
|
||||
filterModel->addFilter(
|
||||
new CardFilter(colorString, CardFilter::Type::TypeAndNot, CardFilter::Attr::AttrColor));
|
||||
break;
|
||||
|
||||
case FilterMode::Includes:
|
||||
// No exclusion in Includes mode
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void VisualDatabaseDisplayColorFilterWidget::updateFilterMode()
|
||||
{
|
||||
blockSync = true;
|
||||
|
||||
switch (currentMode) {
|
||||
case FilterMode::ExactMatch:
|
||||
currentMode = FilterMode::Includes; // Switch to Includes
|
||||
|
|
@ -170,59 +158,100 @@ void VisualDatabaseDisplayColorFilterWidget::updateFilterMode()
|
|||
break;
|
||||
}
|
||||
|
||||
retranslateUi(); // Update button text based on the mode
|
||||
emit filterModeChanged(currentMode); // Signal mode change
|
||||
updateColorFilter(); // Reapply the filter based on the new mode
|
||||
filterModel->blockSignals(true);
|
||||
filterModel->filterTree()->blockSignals(true);
|
||||
|
||||
blockSync = false;
|
||||
}
|
||||
|
||||
void VisualDatabaseDisplayColorFilterWidget::syncWithFilterModel()
|
||||
{
|
||||
blockSync = true;
|
||||
QSet<QString> currentFilters;
|
||||
|
||||
// Get current filters of type color
|
||||
for (const auto &filter : filterModel->getFiltersOfType(CardFilter::Attr::AttrColor)) {
|
||||
if (filter->type() == CardFilter::Type::TypeAnd || filter->type() == CardFilter::Type::TypeOr) {
|
||||
currentFilters.insert(filter->term());
|
||||
}
|
||||
}
|
||||
|
||||
QSet<QString> activeFilterList;
|
||||
|
||||
// Iterate over the activeColors map and collect the active colors as strings
|
||||
for (auto it = activeColors.constBegin(); it != activeColors.constEnd(); ++it) {
|
||||
if (it.value()) { // Only add active colors
|
||||
activeFilterList.insert(QString(it.key()));
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the filters in the model match the active filters
|
||||
if (currentFilters == activeFilterList) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove filters that are in the UI but not in the model
|
||||
for (const auto &color : activeFilterList) {
|
||||
if (!currentFilters.contains(color)) {
|
||||
activeColors[color[0]] = false; // Disable the color
|
||||
}
|
||||
}
|
||||
|
||||
// Add filters that are in the model but not in the UI
|
||||
for (const auto &color : currentFilters) {
|
||||
if (!activeFilterList.contains(color)) {
|
||||
activeColors[color[0]] = true; // Enable the color
|
||||
}
|
||||
}
|
||||
filterModel->clearFiltersOfType(CardFilter::Attr::AttrColor);
|
||||
|
||||
QList<ManaSymbolWidget *> manaSymbolWidgets = findChildren<ManaSymbolWidget *>();
|
||||
|
||||
for (ManaSymbolWidget *manaSymbolWidget : manaSymbolWidgets) {
|
||||
manaSymbolWidget->setColorActive(activeColors[manaSymbolWidget->getSymbolChar()]);
|
||||
handleColorToggled(manaSymbolWidget->getSymbolChar(), manaSymbolWidget->isColorActive());
|
||||
}
|
||||
|
||||
updateColorFilter();
|
||||
blockSync = false;
|
||||
}
|
||||
filterModel->blockSignals(false);
|
||||
filterModel->filterTree()->blockSignals(false);
|
||||
|
||||
emit filterModel->filterTree()->changed();
|
||||
emit filterModel->layoutChanged();
|
||||
|
||||
retranslateUi(); // Update button text based on the mode
|
||||
emit filterModeChanged(currentMode); // Signal mode change
|
||||
}
|
||||
|
||||
void VisualDatabaseDisplayColorFilterWidget::setManaSymbolActive(QChar color, bool active)
|
||||
{
|
||||
QList<ManaSymbolWidget *> manaSymbolWidgets = findChildren<ManaSymbolWidget *>();
|
||||
|
||||
for (ManaSymbolWidget *manaSymbolWidget : manaSymbolWidgets) {
|
||||
if (manaSymbolWidget->getSymbolChar() == color) {
|
||||
manaSymbolWidget->setColorActive(active);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QList<QChar> VisualDatabaseDisplayColorFilterWidget::getActiveColors()
|
||||
{
|
||||
QList<QChar> activeColors;
|
||||
QList<ManaSymbolWidget *> manaSymbolWidgets = findChildren<ManaSymbolWidget *>();
|
||||
|
||||
for (ManaSymbolWidget *manaSymbolWidget : manaSymbolWidgets) {
|
||||
if (manaSymbolWidget->isColorActive()) {
|
||||
activeColors.append(manaSymbolWidget->getSymbolChar());
|
||||
}
|
||||
}
|
||||
|
||||
return activeColors;
|
||||
}
|
||||
|
||||
void VisualDatabaseDisplayColorFilterWidget::syncWithFilterModel()
|
||||
{
|
||||
QList<const CardFilter *> allColorFilters = filterModel->getFiltersOfType(CardFilter::Attr::AttrColor);
|
||||
|
||||
QList<ManaSymbolWidget *> manaSymbolWidgets = findChildren<ManaSymbolWidget *>();
|
||||
|
||||
for (ManaSymbolWidget *manaSymbolWidget : manaSymbolWidgets) {
|
||||
bool found = false;
|
||||
for (const CardFilter *filter : allColorFilters) {
|
||||
if (manaSymbolWidget->getSymbolChar() == filter->term()) {
|
||||
switch (currentMode) {
|
||||
case FilterMode::ExactMatch:
|
||||
switch (filter->type()) {
|
||||
case CardFilter::Type::TypeAnd:
|
||||
setManaSymbolActive(filter->term().at(0), true);
|
||||
break;
|
||||
default:
|
||||
setManaSymbolActive(filter->term().at(0), false);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case FilterMode::Includes:
|
||||
switch (filter->type()) {
|
||||
case CardFilter::Type::TypeOr:
|
||||
setManaSymbolActive(filter->term().at(0), true);
|
||||
break;
|
||||
default:
|
||||
setManaSymbolActive(filter->term().at(0), false);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case FilterMode::IncludeExclude:
|
||||
switch (filter->type()) {
|
||||
case CardFilter::Type::TypeOr:
|
||||
setManaSymbolActive(filter->term().at(0), true);
|
||||
break;
|
||||
default:
|
||||
setManaSymbolActive(filter->term().at(0), false);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
setManaSymbolActive(manaSymbolWidget->getSymbolChar(), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,21 +43,21 @@ public:
|
|||
|
||||
signals:
|
||||
void filterModeChanged(FilterMode filterMode);
|
||||
void activeColorsChanged();
|
||||
|
||||
private slots:
|
||||
void handleColorToggled(QChar color, bool active);
|
||||
void updateColorFilter();
|
||||
void addFilter(QChar color);
|
||||
void removeFilter(QChar color);
|
||||
void updateFilterMode();
|
||||
void setManaSymbolActive(QChar color, bool active);
|
||||
QList<QChar> getActiveColors();
|
||||
void syncWithFilterModel();
|
||||
|
||||
private:
|
||||
FilterTreeModel *filterModel;
|
||||
QHBoxLayout *layout;
|
||||
QPushButton *toggleButton;
|
||||
QMap<QChar, bool> activeColors;
|
||||
FilterMode currentMode = FilterMode::Includes; // Default mode
|
||||
bool blockSync = false;
|
||||
};
|
||||
|
||||
#endif // VISUAL_DATABASE_DISPLAY_COLOR_FILTER_WIDGET_H
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ VisualDatabaseDisplayFilterSaveLoadWidget::VisualDatabaseDisplayFilterSaveLoadWi
|
|||
void VisualDatabaseDisplayFilterSaveLoadWidget::retranslateUi()
|
||||
{
|
||||
saveButton->setText(tr("Save Filter"));
|
||||
saveButton->setToolTip(tr("Save all currently applied filters to a file"));
|
||||
filenameInput->setPlaceholderText(tr("Enter filename..."));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -47,6 +47,14 @@ VisualDatabaseDisplayMainTypeFilterWidget::VisualDatabaseDisplayMainTypeFilterWi
|
|||
|
||||
createMainTypeButtons(); // Populate buttons initially
|
||||
updateFilterMode(false); // Initialize toggle button text
|
||||
|
||||
retranslateUi();
|
||||
}
|
||||
|
||||
void VisualDatabaseDisplayMainTypeFilterWidget::retranslateUi()
|
||||
{
|
||||
spinBox->setToolTip(tr("Do not display card main-types with less than this amount of cards in the database"));
|
||||
toggleButton->setToolTip(tr("Filter mode (AND/OR/NOT conjunctions of filters)"));
|
||||
}
|
||||
|
||||
void VisualDatabaseDisplayMainTypeFilterWidget::createMainTypeButtons()
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ class VisualDatabaseDisplayMainTypeFilterWidget : public QWidget
|
|||
Q_OBJECT
|
||||
public:
|
||||
explicit VisualDatabaseDisplayMainTypeFilterWidget(QWidget *parent, FilterTreeModel *filterModel);
|
||||
void retranslateUi();
|
||||
void createMainTypeButtons();
|
||||
void updateMainTypeButtonsVisibility();
|
||||
int getMaxMainTypeCount() const;
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ void VisualDatabaseDisplayNameFilterWidget::retranslateUi()
|
|||
{
|
||||
searchBox->setPlaceholderText(tr("Filter by name..."));
|
||||
loadFromDeckButton->setText(tr("Load from Deck"));
|
||||
loadFromDeckButton->setToolTip(tr("Apply all card names in currently loaded deck as exact match name filters"));
|
||||
}
|
||||
|
||||
void VisualDatabaseDisplayNameFilterWidget::actLoadFromDeck()
|
||||
|
|
|
|||
|
|
@ -3,12 +3,44 @@
|
|||
#include "../../../../game/cards/card_database_manager.h"
|
||||
#include "../../../../game/filters/filter_tree.h"
|
||||
#include "../../../../game/filters/filter_tree_model.h"
|
||||
#include "../../../../settings/cache_settings.h"
|
||||
|
||||
#include <QLineEdit>
|
||||
#include <QPushButton>
|
||||
#include <QTimer>
|
||||
#include <algorithm>
|
||||
|
||||
VisualDatabaseDisplayRecentSetFilterSettingsWidget::VisualDatabaseDisplayRecentSetFilterSettingsWidget(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
layout = new QHBoxLayout(this);
|
||||
setLayout(layout);
|
||||
|
||||
filterToMostRecentSetsCheckBox = new QCheckBox(this);
|
||||
filterToMostRecentSetsCheckBox->setChecked(
|
||||
SettingsCache::instance().getVisualDatabaseDisplayFilterToMostRecentSetsEnabled());
|
||||
connect(filterToMostRecentSetsCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(),
|
||||
&SettingsCache::setVisualDatabaseDisplayFilterToMostRecentSetsEnabled);
|
||||
|
||||
filterToMostRecentSetsAmount = new QSpinBox(this);
|
||||
filterToMostRecentSetsAmount->setMinimum(1);
|
||||
filterToMostRecentSetsAmount->setMaximum(100);
|
||||
filterToMostRecentSetsAmount->setValue(
|
||||
SettingsCache::instance().getVisualDatabaseDisplayFilterToMostRecentSetsAmount());
|
||||
connect(filterToMostRecentSetsAmount, QOverload<int>::of(&QSpinBox::valueChanged), &SettingsCache::instance(),
|
||||
&SettingsCache::setVisualDatabaseDisplayFilterToMostRecentSetsAmount);
|
||||
|
||||
layout->addWidget(filterToMostRecentSetsCheckBox);
|
||||
layout->addWidget(filterToMostRecentSetsAmount);
|
||||
|
||||
retranslateUi();
|
||||
}
|
||||
|
||||
void VisualDatabaseDisplayRecentSetFilterSettingsWidget::retranslateUi()
|
||||
{
|
||||
filterToMostRecentSetsCheckBox->setText(tr("Filter to most recent sets"));
|
||||
}
|
||||
|
||||
VisualDatabaseDisplaySetFilterWidget::VisualDatabaseDisplaySetFilterWidget(QWidget *parent,
|
||||
FilterTreeModel *_filterModel)
|
||||
: QWidget(parent), filterModel(_filterModel)
|
||||
|
|
@ -19,6 +51,14 @@ VisualDatabaseDisplaySetFilterWidget::VisualDatabaseDisplaySetFilterWidget(QWidg
|
|||
layout = new QVBoxLayout(this);
|
||||
setLayout(layout);
|
||||
|
||||
recentSetsSettingsWidget = new VisualDatabaseDisplayRecentSetFilterSettingsWidget(this);
|
||||
layout->addWidget(recentSetsSettingsWidget);
|
||||
|
||||
connect(&SettingsCache::instance(), &SettingsCache::visualDatabaseDisplayFilterToMostRecentSetsEnabledChanged, this,
|
||||
&VisualDatabaseDisplaySetFilterWidget::filterToRecentSets);
|
||||
connect(&SettingsCache::instance(), &SettingsCache::visualDatabaseDisplayFilterToMostRecentSetsAmountChanged, this,
|
||||
&VisualDatabaseDisplaySetFilterWidget::filterToRecentSets);
|
||||
|
||||
searchBox = new QLineEdit(this);
|
||||
searchBox->setPlaceholderText(tr("Search sets..."));
|
||||
layout->addWidget(searchBox);
|
||||
|
|
@ -36,24 +76,26 @@ VisualDatabaseDisplaySetFilterWidget::VisualDatabaseDisplaySetFilterWidget(QWidg
|
|||
connect(filterModel, &FilterTreeModel::layoutChanged, this,
|
||||
[this]() { QTimer::singleShot(100, this, &VisualDatabaseDisplaySetFilterWidget::syncWithFilterModel); });
|
||||
|
||||
createSetButtons(); // Populate buttons initially
|
||||
updateFilterMode(false); // Initialize toggle button text
|
||||
createSetButtons(); // Populate buttons initially
|
||||
retranslateUi();
|
||||
}
|
||||
|
||||
void VisualDatabaseDisplaySetFilterWidget::retranslateUi()
|
||||
{
|
||||
toggleButton->setText(exactMatchMode ? tr("Mode: Exact Match") : tr("Mode: Includes"));
|
||||
}
|
||||
|
||||
void VisualDatabaseDisplaySetFilterWidget::createSetButtons()
|
||||
{
|
||||
SetList shared_pointerses = CardDatabaseManager::getInstance()->getSetList();
|
||||
SetList allSets = CardDatabaseManager::getInstance()->getSetList();
|
||||
|
||||
// Sort by release date
|
||||
std::sort(shared_pointerses.begin(), shared_pointerses.end(),
|
||||
std::sort(allSets.begin(), allSets.end(),
|
||||
[](const auto &a, const auto &b) { return a->getReleaseDate() > b->getReleaseDate(); });
|
||||
|
||||
int setsToPreactivate = 10;
|
||||
int setsActivated = 0;
|
||||
|
||||
for (const auto &shared_pointer : shared_pointerses) {
|
||||
QString shortName = shared_pointer->getShortName();
|
||||
QString longName = shared_pointer->getLongName();
|
||||
for (const auto &set : allSets) {
|
||||
QString shortName = set->getShortName();
|
||||
QString longName = set->getLongName();
|
||||
|
||||
auto *button = new QPushButton(longName + " (" + shortName + ")", flowWidget);
|
||||
button->setCheckable(true);
|
||||
|
|
@ -66,14 +108,47 @@ void VisualDatabaseDisplaySetFilterWidget::createSetButtons()
|
|||
// Connect toggle signal
|
||||
connect(button, &QPushButton::toggled, this,
|
||||
[this, shortName](bool checked) { handleSetToggled(shortName, checked); });
|
||||
if (setsActivated < setsToPreactivate) {
|
||||
setsActivated++;
|
||||
activeSets[shortName] = true;
|
||||
button->setChecked(true);
|
||||
}
|
||||
}
|
||||
updateSetFilter();
|
||||
updateSetButtonsVisibility(); // Ensure visibility is updated initially
|
||||
|
||||
filterToRecentSets();
|
||||
}
|
||||
|
||||
void VisualDatabaseDisplaySetFilterWidget::filterToRecentSets()
|
||||
{
|
||||
if (SettingsCache::instance().getVisualDatabaseDisplayFilterToMostRecentSetsEnabled()) {
|
||||
for (auto set : activeSets.keys()) {
|
||||
activeSets[set] = false;
|
||||
}
|
||||
|
||||
SetList allSets = CardDatabaseManager::getInstance()->getSetList();
|
||||
|
||||
// Sort by release date
|
||||
std::sort(allSets.begin(), allSets.end(),
|
||||
[](const auto &a, const auto &b) { return a->getReleaseDate() > b->getReleaseDate(); });
|
||||
|
||||
int setsToPreactivate = SettingsCache::instance().getVisualDatabaseDisplayFilterToMostRecentSetsAmount();
|
||||
int setsActivated = 0;
|
||||
|
||||
for (const auto &set : allSets) {
|
||||
QString shortName = set->getShortName();
|
||||
QString longName = set->getLongName();
|
||||
|
||||
auto button = setButtons[shortName];
|
||||
|
||||
if (setsActivated < setsToPreactivate) {
|
||||
setsActivated++;
|
||||
activeSets[shortName] = true;
|
||||
button->blockSignals(true);
|
||||
button->setChecked(true);
|
||||
button->blockSignals(false);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
updateSetFilter();
|
||||
updateSetButtonsVisibility();
|
||||
}
|
||||
}
|
||||
|
||||
void VisualDatabaseDisplaySetFilterWidget::updateSetButtonsVisibility()
|
||||
|
|
@ -183,13 +258,15 @@ void VisualDatabaseDisplaySetFilterWidget::syncWithFilterModel()
|
|||
for (const auto &key : setButtons.keys()) {
|
||||
bool active = selectedSets.contains(key);
|
||||
activeSets[key] = active;
|
||||
setButtons[key]->blockSignals(true);
|
||||
setButtons[key]->setChecked(active);
|
||||
setButtons[key]->blockSignals(false);
|
||||
}
|
||||
}
|
||||
|
||||
void VisualDatabaseDisplaySetFilterWidget::updateFilterMode(bool checked)
|
||||
{
|
||||
exactMatchMode = checked;
|
||||
toggleButton->setText(exactMatchMode ? tr("Mode: Exact Match") : tr("Mode: Includes"));
|
||||
updateSetFilter();
|
||||
}
|
||||
retranslateUi();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,19 +4,36 @@
|
|||
#include "../../../../game/filters/filter_tree_model.h"
|
||||
#include "../general/layout_containers/flow_widget.h"
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QLineEdit>
|
||||
#include <QMap>
|
||||
#include <QPushButton>
|
||||
#include <QSpinBox>
|
||||
#include <QToolButton>
|
||||
#include <QVBoxLayout>
|
||||
#include <QWidget>
|
||||
|
||||
class VisualDatabaseDisplayRecentSetFilterSettingsWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
VisualDatabaseDisplayRecentSetFilterSettingsWidget(QWidget *parent);
|
||||
void retranslateUi();
|
||||
|
||||
private:
|
||||
QHBoxLayout *layout;
|
||||
QCheckBox *filterToMostRecentSetsCheckBox;
|
||||
QSpinBox *filterToMostRecentSetsAmount;
|
||||
};
|
||||
|
||||
class VisualDatabaseDisplaySetFilterWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit VisualDatabaseDisplaySetFilterWidget(QWidget *parent, FilterTreeModel *filterModel);
|
||||
void retranslateUi();
|
||||
void createSetButtons();
|
||||
void filterToRecentSets();
|
||||
void updateSetButtonsVisibility();
|
||||
void handleSetToggled(const QString &setShortName, bool active);
|
||||
|
||||
|
|
@ -28,6 +45,7 @@ private:
|
|||
FilterTreeModel *filterModel;
|
||||
QMap<QString, int> allMainCardTypesWithCount;
|
||||
QVBoxLayout *layout;
|
||||
VisualDatabaseDisplayRecentSetFilterSettingsWidget *recentSetsSettingsWidget;
|
||||
QLineEdit *searchBox;
|
||||
FlowWidget *flowWidget;
|
||||
QPushButton *toggleButton; // Mode switch button
|
||||
|
|
|
|||
|
|
@ -51,6 +51,14 @@ VisualDatabaseDisplaySubTypeFilterWidget::VisualDatabaseDisplaySubTypeFilterWidg
|
|||
|
||||
createSubTypeButtons(); // Populate buttons initially
|
||||
updateFilterMode(false); // Initialize the toggle button text
|
||||
|
||||
retranslateUi();
|
||||
}
|
||||
|
||||
void VisualDatabaseDisplaySubTypeFilterWidget::retranslateUi()
|
||||
{
|
||||
spinBox->setToolTip(tr("Do not display card sub-types with less than this amount of cards in the database"));
|
||||
toggleButton->setToolTip(tr("Filter mode (AND/OR/NOT conjunctions of filters)"));
|
||||
}
|
||||
|
||||
void VisualDatabaseDisplaySubTypeFilterWidget::createSubTypeButtons()
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ class VisualDatabaseDisplaySubTypeFilterWidget : public QWidget
|
|||
Q_OBJECT
|
||||
public:
|
||||
explicit VisualDatabaseDisplaySubTypeFilterWidget(QWidget *parent, FilterTreeModel *filterModel);
|
||||
void retranslateUi();
|
||||
void createSubTypeButtons();
|
||||
void updateSubTypeButtonsVisibility();
|
||||
int getMaxSubTypeCount() const;
|
||||
|
|
|
|||
|
|
@ -62,9 +62,6 @@ VisualDatabaseDisplayWidget::VisualDatabaseDisplayWidget(QWidget *parent,
|
|||
|
||||
filterModel = new FilterTreeModel();
|
||||
filterModel->setObjectName("filterModel");
|
||||
databaseDisplayModel->setFilterTree(filterModel->filterTree());
|
||||
|
||||
connect(filterModel, &FilterTreeModel::layoutChanged, this, &VisualDatabaseDisplayWidget::searchModelChanged);
|
||||
|
||||
searchKeySignals.setObjectName("searchKeySignals");
|
||||
connect(searchEdit, &QLineEdit::textChanged, this, &VisualDatabaseDisplayWidget::updateSearch);
|
||||
|
|
@ -144,11 +141,27 @@ VisualDatabaseDisplayWidget::VisualDatabaseDisplayWidget(QWidget *parent,
|
|||
|
||||
connect(debounceTimer, &QTimer::timeout, this, &VisualDatabaseDisplayWidget::searchModelChanged);
|
||||
|
||||
databaseDisplayModel->setFilterTree(filterModel->filterTree());
|
||||
|
||||
connect(filterModel, &FilterTreeModel::layoutChanged, this, &VisualDatabaseDisplayWidget::searchModelChanged);
|
||||
|
||||
loadCardsTimer = new QTimer(this);
|
||||
loadCardsTimer->setSingleShot(true); // Ensure it only fires once after the timeout
|
||||
|
||||
connect(loadCardsTimer, &QTimer::timeout, this, [this]() { loadCurrentPage(); });
|
||||
loadCardsTimer->start(5000);
|
||||
|
||||
retranslateUi();
|
||||
}
|
||||
|
||||
void VisualDatabaseDisplayWidget::retranslateUi()
|
||||
{
|
||||
clearFilterWidget->setToolTip(tr("Clear all filters"));
|
||||
|
||||
quickFilterSaveLoadWidget->setToolTip(tr("Save and load filters"));
|
||||
quickFilterNameWidget->setToolTip(tr("Filter by exact card name"));
|
||||
quickFilterSubTypeWidget->setToolTip(tr("Filter by card sub-type"));
|
||||
quickFilterSetWidget->setToolTip(tr("Filter by set"));
|
||||
}
|
||||
|
||||
void VisualDatabaseDisplayWidget::resizeEvent(QResizeEvent *event)
|
||||
|
|
@ -195,13 +208,30 @@ void VisualDatabaseDisplayWidget::populateCards()
|
|||
databaseDisplayModel->fetchMore(QModelIndex());
|
||||
}
|
||||
|
||||
QList<const CardFilter *> setFilters = filterModel->getFiltersOfType(CardFilter::AttrSet);
|
||||
const CardFilter *setFilter = nullptr;
|
||||
if (setFilters.length() == 1) {
|
||||
setFilter = setFilters.at(0);
|
||||
}
|
||||
|
||||
for (int row = start; row < end; ++row) {
|
||||
qCDebug(VisualDatabaseDisplayLog) << "Adding " << row;
|
||||
QModelIndex index = databaseDisplayModel->index(row, CardDatabaseModel::NameColumn);
|
||||
QVariant name = databaseDisplayModel->data(index, Qt::DisplayRole);
|
||||
qCDebug(VisualDatabaseDisplayLog) << name.toString();
|
||||
|
||||
if (CardInfoPtr info = CardDatabaseManager::getInstance()->getCard(name.toString())) {
|
||||
addCard(info);
|
||||
if (setFilter) {
|
||||
CardInfoPerSetMap setMap = info->getSets();
|
||||
if (setMap.contains(setFilter->term())) {
|
||||
for (CardInfoPerSet cardSetInstance : setMap[setFilter->term()]) {
|
||||
addCard(CardDatabaseManager::getInstance()->getCardByNameAndProviderId(
|
||||
name.toString(), cardSetInstance.getProperty("uuid")));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
addCard(info);
|
||||
}
|
||||
} else {
|
||||
qCDebug(VisualDatabaseDisplayLog) << "Card not found in database!";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ public:
|
|||
AbstractTabDeckEditor *deckEditor,
|
||||
CardDatabaseModel *database_model,
|
||||
CardDatabaseDisplayModel *database_display_model);
|
||||
void retranslateUi();
|
||||
|
||||
void adjustCardsPerPage();
|
||||
void populateCards();
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include "../../../../deck/deck_loader.h"
|
||||
#include "../../../../game/cards/card_database_manager.h"
|
||||
#include "../../../../settings/cache_settings.h"
|
||||
#include "../cards/card_info_picture_widget.h"
|
||||
|
||||
#include <random>
|
||||
|
|
@ -12,23 +13,45 @@ VisualDeckEditorSampleHandWidget::VisualDeckEditorSampleHandWidget(QWidget *pare
|
|||
layout = new QVBoxLayout(this);
|
||||
setLayout(layout);
|
||||
|
||||
resetAndHandSizeContainerWidget = new QWidget(this);
|
||||
resetAndHandSizeLayout = new QHBoxLayout(resetAndHandSizeContainerWidget);
|
||||
resetAndHandSizeContainerWidget->setLayout(resetAndHandSizeLayout);
|
||||
|
||||
resetButton = new QPushButton(this);
|
||||
connect(resetButton, SIGNAL(clicked()), this, SLOT(updateDisplay()));
|
||||
layout->addWidget(resetButton);
|
||||
resetAndHandSizeLayout->addWidget(resetButton);
|
||||
|
||||
flowWidget = new FlowWidget(this, Qt::Horizontal, Qt::ScrollBarAlwaysOff, Qt::ScrollBarAlwaysOff);
|
||||
handSizeSpinBox = new QSpinBox(this);
|
||||
handSizeSpinBox->setValue(SettingsCache::instance().getVisualDeckEditorSampleHandSize());
|
||||
handSizeSpinBox->setMinimum(1);
|
||||
connect(handSizeSpinBox, QOverload<int>::of(&QSpinBox::valueChanged), &SettingsCache::instance(),
|
||||
&SettingsCache::setVisualDeckEditorSampleHandSize);
|
||||
connect(handSizeSpinBox, QOverload<int>::of(&QSpinBox::valueChanged), this,
|
||||
&VisualDeckEditorSampleHandWidget::updateDisplay);
|
||||
resetAndHandSizeLayout->addWidget(handSizeSpinBox);
|
||||
|
||||
layout->addWidget(resetAndHandSizeContainerWidget);
|
||||
|
||||
flowWidget = new FlowWidget(this, Qt::Horizontal, Qt::ScrollBarAlwaysOff, Qt::ScrollBarAsNeeded);
|
||||
layout->addWidget(flowWidget);
|
||||
|
||||
for (CardInfoPtr card : getRandomCards(7)) {
|
||||
cardSizeWidget = new CardSizeWidget(this, flowWidget);
|
||||
layout->addWidget(cardSizeWidget);
|
||||
|
||||
for (CardInfoPtr card : getRandomCards(handSizeSpinBox->value())) {
|
||||
auto displayWidget = new CardInfoPictureWidget(this);
|
||||
displayWidget->setCard(card);
|
||||
displayWidget->setScaleFactor(cardSizeWidget->getSlider()->value());
|
||||
flowWidget->addWidget(displayWidget);
|
||||
}
|
||||
|
||||
retranslateUi();
|
||||
}
|
||||
|
||||
void VisualDeckEditorSampleHandWidget::retranslateUi()
|
||||
{
|
||||
resetButton->setText(tr("Reset"));
|
||||
resetButton->setText(tr("Draw a new sample hand"));
|
||||
handSizeSpinBox->setToolTip(tr("Sample hand size"));
|
||||
}
|
||||
|
||||
void VisualDeckEditorSampleHandWidget::setDeckModel(DeckListModel *deckModel)
|
||||
|
|
@ -41,9 +64,12 @@ void VisualDeckEditorSampleHandWidget::setDeckModel(DeckListModel *deckModel)
|
|||
void VisualDeckEditorSampleHandWidget::updateDisplay()
|
||||
{
|
||||
flowWidget->clearLayout();
|
||||
for (CardInfoPtr card : getRandomCards(7)) {
|
||||
for (CardInfoPtr card : getRandomCards(handSizeSpinBox->value())) {
|
||||
auto displayWidget = new CardInfoPictureWidget(this);
|
||||
displayWidget->setCard(card);
|
||||
displayWidget->setScaleFactor(cardSizeWidget->getSlider()->value());
|
||||
connect(cardSizeWidget->getSlider(), &QSlider::valueChanged, displayWidget,
|
||||
&CardInfoPictureWidget::setScaleFactor);
|
||||
flowWidget->addWidget(displayWidget);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
#ifndef VISUAL_DECK_EDITOR_SAMPLE_HAND_WIDGET_H
|
||||
#define VISUAL_DECK_EDITOR_SAMPLE_HAND_WIDGET_H
|
||||
|
||||
#include "../../../../client/ui/widgets/cards/card_size_widget.h"
|
||||
#include "../../../../deck/deck_list_model.h"
|
||||
#include "../general/layout_containers/flow_widget.h"
|
||||
|
||||
#include <QPushButton>
|
||||
#include <QSpinBox>
|
||||
#include <QWidget>
|
||||
|
||||
class VisualDeckEditorSampleHandWidget : public QWidget
|
||||
|
|
@ -22,8 +24,12 @@ public slots:
|
|||
private:
|
||||
DeckListModel *deckListModel;
|
||||
QVBoxLayout *layout;
|
||||
QWidget *resetAndHandSizeContainerWidget;
|
||||
QHBoxLayout *resetAndHandSizeLayout;
|
||||
QPushButton *resetButton;
|
||||
QSpinBox *handSizeSpinBox;
|
||||
FlowWidget *flowWidget;
|
||||
CardSizeWidget *cardSizeWidget;
|
||||
};
|
||||
|
||||
#endif // VISUAL_DECK_EDITOR_SAMPLE_HAND_WIDGET_H
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@ VisualDeckEditorWidget::VisualDeckEditorWidget(QWidget *parent, DeckListModel *_
|
|||
connect(deckListModel, &DeckListModel::dataChanged, this, &VisualDeckEditorWidget::decklistDataChanged);
|
||||
|
||||
// The Main Widget and Main Layout, which contain a single Widget: The Scroll Area
|
||||
setMinimumSize(0, 0);
|
||||
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
mainLayout = new QVBoxLayout(this);
|
||||
setLayout(mainLayout);
|
||||
|
|
@ -162,7 +161,7 @@ VisualDeckEditorWidget::VisualDeckEditorWidget(QWidget *parent, DeckListModel *_
|
|||
groupAndSortLayout->addWidget(sortCriteriaButton);
|
||||
groupAndSortLayout->addWidget(displayTypeButton);
|
||||
|
||||
scrollArea = new QScrollArea();
|
||||
scrollArea = new QScrollArea(this);
|
||||
scrollArea->setWidgetResizable(true);
|
||||
scrollArea->setMinimumSize(0, 0);
|
||||
|
||||
|
|
@ -191,7 +190,12 @@ void VisualDeckEditorWidget::retranslateUi()
|
|||
{
|
||||
sortLabel->setText(tr("Click and drag to change the sort order within the groups"));
|
||||
searchPushButton->setText(tr("Quick search and add card"));
|
||||
searchPushButton->setToolTip(tr("Search for closest match in the database (with auto-suggestions) and add "
|
||||
"preferred printing to the deck on pressing enter"));
|
||||
sortCriteriaButton->setToolTip(tr("Configure how cards are sorted within their groups"));
|
||||
displayTypeButton->setText(tr("Flat Layout"));
|
||||
displayTypeButton->setToolTip(
|
||||
tr("Change how cards are displayed within zones (i.e. overlapped or fully visible.)"));
|
||||
}
|
||||
|
||||
void VisualDeckEditorWidget::updateZoneWidgets()
|
||||
|
|
@ -227,6 +231,7 @@ void VisualDeckEditorWidget::addZoneIfDoesNotExist()
|
|||
for (DeckCardZoneDisplayWidget *displayWidget : cardZoneDisplayWidgets) {
|
||||
if (displayWidget->zoneName == zone) {
|
||||
found = true;
|
||||
displayWidget->displayCards();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ void DeckPreviewColorIdentityFilterWidget::retranslateUi()
|
|||
{
|
||||
// Set the toggle button text based on the current mode
|
||||
toggleButton->setText(exactMatchMode ? tr("Mode: Exact Match") : tr("Mode: Includes"));
|
||||
toggleButton->setToolTip(tr("Color identity filter mode (AND/OR/NOT conjunctions of filters)"));
|
||||
}
|
||||
|
||||
void DeckPreviewColorIdentityFilterWidget::handleColorToggled(QChar color, bool active)
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
#include <QVBoxLayout>
|
||||
|
||||
DeckPreviewTagDialog::DeckPreviewTagDialog(const QStringList &knownTags, const QStringList &activeTags, QWidget *parent)
|
||||
: QDialog(parent), activeTags_(activeTags)
|
||||
: QDialog(parent), activeTags(activeTags)
|
||||
{
|
||||
resize(400, 500);
|
||||
|
||||
|
|
@ -100,13 +100,13 @@ DeckPreviewTagDialog::DeckPreviewTagDialog(const QStringList &knownTags, const Q
|
|||
combinedTags.removeDuplicates();
|
||||
|
||||
// Main layout
|
||||
auto *mainLayout = new QVBoxLayout(this);
|
||||
mainLayout = new QVBoxLayout(this);
|
||||
|
||||
// Filter bar
|
||||
filterInput_ = new QLineEdit(this);
|
||||
mainLayout->addWidget(filterInput_);
|
||||
filterInput = new QLineEdit(this);
|
||||
mainLayout->addWidget(filterInput);
|
||||
|
||||
connect(filterInput_, &QLineEdit::textChanged, this, &DeckPreviewTagDialog::filterTags);
|
||||
connect(filterInput, &QLineEdit::textChanged, this, &DeckPreviewTagDialog::filterTags);
|
||||
|
||||
// Instruction label
|
||||
instructionLabel = new QLabel(this);
|
||||
|
|
@ -114,31 +114,34 @@ DeckPreviewTagDialog::DeckPreviewTagDialog(const QStringList &knownTags, const Q
|
|||
mainLayout->addWidget(instructionLabel);
|
||||
|
||||
// Tag list view
|
||||
tagListView_ = new QListWidget(this);
|
||||
mainLayout->addWidget(tagListView_);
|
||||
tagListView = new QListWidget(this);
|
||||
mainLayout->addWidget(tagListView);
|
||||
|
||||
// Populate combined tags
|
||||
for (const auto &tag : combinedTags) {
|
||||
auto *item = new QListWidgetItem(tagListView_);
|
||||
auto *item = new QListWidgetItem(tagListView);
|
||||
auto *tagWidget = new DeckPreviewTagItemWidget(tag, activeTags.contains(tag), this);
|
||||
tagListView_->addItem(item);
|
||||
tagListView_->setItemWidget(item, tagWidget);
|
||||
tagListView->addItem(item);
|
||||
tagListView->setItemWidget(item, tagWidget);
|
||||
|
||||
connect(tagWidget->checkBox(), &QCheckBox::toggled, this, &DeckPreviewTagDialog::onCheckboxStateChanged);
|
||||
}
|
||||
|
||||
// Add tag input layout
|
||||
auto *addTagLayout = new QHBoxLayout();
|
||||
newTagInput_ = new QLineEdit(this);
|
||||
addTagButton_ = new QPushButton(this);
|
||||
addTagLayout->addWidget(newTagInput_);
|
||||
addTagLayout->addWidget(addTagButton_);
|
||||
addTagLayout = new QHBoxLayout(this);
|
||||
newTagInput = new QLineEdit(this);
|
||||
addTagButton = new QPushButton(this);
|
||||
addTagButton->setEnabled(false);
|
||||
addTagLayout->addWidget(newTagInput);
|
||||
addTagLayout->addWidget(addTagButton);
|
||||
mainLayout->addLayout(addTagLayout);
|
||||
|
||||
connect(addTagButton_, &QPushButton::clicked, this, &DeckPreviewTagDialog::addTag);
|
||||
connect(addTagButton, &QPushButton::clicked, this, &DeckPreviewTagDialog::addTag);
|
||||
connect(newTagInput, &QLineEdit::textChanged, this,
|
||||
[this](const QString &text) { addTagButton->setEnabled(!text.trimmed().isEmpty()); });
|
||||
|
||||
// OK and Cancel buttons
|
||||
auto *buttonLayout = new QHBoxLayout();
|
||||
buttonLayout = new QHBoxLayout(this);
|
||||
okButton = new QPushButton(this);
|
||||
cancelButton = new QPushButton(this);
|
||||
buttonLayout->addStretch();
|
||||
|
|
@ -155,30 +158,30 @@ void DeckPreviewTagDialog::retranslateUi()
|
|||
{
|
||||
setWindowTitle(tr("Deck Tags Manager"));
|
||||
instructionLabel->setText(tr("Manage your deck tags. Check or uncheck tags as needed, or add new ones:"));
|
||||
newTagInput_->setPlaceholderText(tr("Add a new tag (e.g., Aggro️)"));
|
||||
addTagButton_->setText(tr("Add Tag"));
|
||||
filterInput_->setPlaceholderText(tr("Filter tags..."));
|
||||
newTagInput->setPlaceholderText(tr("Add a new tag (e.g., Aggro️)"));
|
||||
addTagButton->setText(tr("Add Tag"));
|
||||
filterInput->setPlaceholderText(tr("Filter tags..."));
|
||||
okButton->setText(tr("OK"));
|
||||
cancelButton->setText(tr("Cancel"));
|
||||
}
|
||||
|
||||
QStringList DeckPreviewTagDialog::getActiveTags() const
|
||||
{
|
||||
return activeTags_;
|
||||
return activeTags;
|
||||
}
|
||||
|
||||
void DeckPreviewTagDialog::addTag()
|
||||
{
|
||||
QString newTag = newTagInput_->text().trimmed();
|
||||
QString newTag = newTagInput->text().trimmed();
|
||||
if (newTag.isEmpty()) {
|
||||
QMessageBox::warning(this, tr("Invalid Input"), tr("Tag name cannot be empty!"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Prevent duplicate tags
|
||||
for (int i = 0; i < tagListView_->count(); ++i) {
|
||||
auto *item = tagListView_->item(i);
|
||||
auto *tagWidget = qobject_cast<DeckPreviewTagItemWidget *>(tagListView_->itemWidget(item));
|
||||
for (int i = 0; i < tagListView->count(); ++i) {
|
||||
auto *item = tagListView->item(i);
|
||||
auto *tagWidget = qobject_cast<DeckPreviewTagItemWidget *>(tagListView->itemWidget(item));
|
||||
if (tagWidget && tagWidget->checkBox()->text() == newTag) {
|
||||
QMessageBox::warning(this, tr("Duplicate Tag"), tr("This tag already exists."));
|
||||
return;
|
||||
|
|
@ -186,23 +189,23 @@ void DeckPreviewTagDialog::addTag()
|
|||
}
|
||||
|
||||
// Add the new tag
|
||||
auto *item = new QListWidgetItem(tagListView_);
|
||||
auto *item = new QListWidgetItem(tagListView);
|
||||
auto *tagWidget = new DeckPreviewTagItemWidget(newTag, true, this);
|
||||
tagListView_->addItem(item);
|
||||
tagListView_->setItemWidget(item, tagWidget);
|
||||
activeTags_.append(newTag);
|
||||
tagListView->addItem(item);
|
||||
tagListView->setItemWidget(item, tagWidget);
|
||||
activeTags.append(newTag);
|
||||
|
||||
connect(tagWidget->checkBox(), &QCheckBox::toggled, this, &DeckPreviewTagDialog::onCheckboxStateChanged);
|
||||
|
||||
// Clear the input field
|
||||
newTagInput_->clear();
|
||||
newTagInput->clear();
|
||||
}
|
||||
|
||||
void DeckPreviewTagDialog::filterTags(const QString &text)
|
||||
{
|
||||
for (int i = 0; i < tagListView_->count(); ++i) {
|
||||
auto *item = tagListView_->item(i);
|
||||
auto *tagWidget = qobject_cast<DeckPreviewTagItemWidget *>(tagListView_->itemWidget(item));
|
||||
for (int i = 0; i < tagListView->count(); ++i) {
|
||||
auto *item = tagListView->item(i);
|
||||
auto *tagWidget = qobject_cast<DeckPreviewTagItemWidget *>(tagListView->itemWidget(item));
|
||||
if (tagWidget) {
|
||||
bool matches = tagWidget->checkBox()->text().contains(text, Qt::CaseInsensitive);
|
||||
item->setHidden(!matches);
|
||||
|
|
@ -212,12 +215,12 @@ void DeckPreviewTagDialog::filterTags(const QString &text)
|
|||
|
||||
void DeckPreviewTagDialog::onCheckboxStateChanged()
|
||||
{
|
||||
activeTags_.clear();
|
||||
for (int i = 0; i < tagListView_->count(); ++i) {
|
||||
auto *item = tagListView_->item(i);
|
||||
auto *tagWidget = qobject_cast<DeckPreviewTagItemWidget *>(tagListView_->itemWidget(item));
|
||||
activeTags.clear();
|
||||
for (int i = 0; i < tagListView->count(); ++i) {
|
||||
auto *item = tagListView->item(i);
|
||||
auto *tagWidget = qobject_cast<DeckPreviewTagItemWidget *>(tagListView->itemWidget(item));
|
||||
if (tagWidget && tagWidget->checkBox()->isChecked()) {
|
||||
activeTags_.append(tagWidget->checkBox()->text());
|
||||
activeTags.append(tagWidget->checkBox()->text());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
#include <QListWidget>
|
||||
#include <QPushButton>
|
||||
#include <QStringList>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
class DeckPreviewTagDialog : public QDialog
|
||||
{
|
||||
|
|
@ -26,14 +27,17 @@ private slots:
|
|||
void retranslateUi();
|
||||
|
||||
private:
|
||||
QVBoxLayout *mainLayout;
|
||||
QLabel *instructionLabel;
|
||||
QListWidget *tagListView_;
|
||||
QLineEdit *filterInput_;
|
||||
QLineEdit *newTagInput_;
|
||||
QPushButton *addTagButton_;
|
||||
QListWidget *tagListView;
|
||||
QLineEdit *filterInput;
|
||||
QHBoxLayout *addTagLayout;
|
||||
QLineEdit *newTagInput;
|
||||
QPushButton *addTagButton;
|
||||
QHBoxLayout *buttonLayout;
|
||||
QPushButton *okButton;
|
||||
QPushButton *cancelButton;
|
||||
QStringList activeTags_;
|
||||
QStringList activeTags;
|
||||
};
|
||||
|
||||
#endif // DECK_PREVIEW_TAG_DIALOG_H
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
#include <QPainter>
|
||||
|
||||
DeckPreviewTagDisplayWidget::DeckPreviewTagDisplayWidget(QWidget *parent, const QString &_tagName)
|
||||
: QWidget(parent), tagName(_tagName), isSelected(false)
|
||||
: QWidget(parent), tagName(_tagName), state(TagState::NotSelected)
|
||||
{
|
||||
// Create layout
|
||||
auto *layout = new QHBoxLayout(this);
|
||||
|
|
@ -48,36 +48,58 @@ QSize DeckPreviewTagDisplayWidget::sizeHint() const
|
|||
|
||||
void DeckPreviewTagDisplayWidget::mousePressEvent(QMouseEvent *event)
|
||||
{
|
||||
if (event->button() == Qt::LeftButton) {
|
||||
setSelected(!isSelected);
|
||||
emit tagClicked();
|
||||
switch (event->button()) {
|
||||
case Qt::LeftButton:
|
||||
setState(TagState::Selected);
|
||||
break;
|
||||
case Qt::RightButton:
|
||||
setState(TagState::Excluded);
|
||||
break;
|
||||
case Qt::MiddleButton:
|
||||
setState(TagState::NotSelected);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
QWidget::mousePressEvent(event);
|
||||
}
|
||||
|
||||
void DeckPreviewTagDisplayWidget::setSelected(bool selected)
|
||||
{
|
||||
isSelected = selected;
|
||||
update(); // Trigger a repaint
|
||||
emit tagClicked();
|
||||
QWidget::mousePressEvent(event);
|
||||
}
|
||||
|
||||
void DeckPreviewTagDisplayWidget::paintEvent(QPaintEvent *event)
|
||||
{
|
||||
QPainter painter(this);
|
||||
|
||||
// Set background color
|
||||
QColor backgroundColor = isSelected ? QColor(173, 216, 230) : Qt::white;
|
||||
QColor backgroundColor;
|
||||
QColor borderColor;
|
||||
int borderWidth;
|
||||
|
||||
switch (state) {
|
||||
case TagState::Selected:
|
||||
backgroundColor = QColor(173, 216, 230); // Light blue
|
||||
borderColor = Qt::blue;
|
||||
borderWidth = 2;
|
||||
break;
|
||||
case TagState::Excluded:
|
||||
backgroundColor = QColor(255, 182, 193); // Light red/pink
|
||||
borderColor = Qt::red;
|
||||
borderWidth = 2;
|
||||
break;
|
||||
case TagState::NotSelected:
|
||||
default:
|
||||
backgroundColor = Qt::white;
|
||||
borderColor = Qt::gray;
|
||||
borderWidth = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
painter.setBrush(backgroundColor);
|
||||
painter.setPen(Qt::NoPen);
|
||||
|
||||
// Draw background
|
||||
painter.drawRect(rect());
|
||||
|
||||
// Draw border
|
||||
QColor borderColor = isSelected ? Qt::blue : Qt::gray;
|
||||
QPen borderPen(borderColor, isSelected ? 2 : 1);
|
||||
QPen borderPen(borderColor, borderWidth);
|
||||
painter.setPen(borderPen);
|
||||
painter.drawRect(rect().adjusted(0, 0, -1, -1)); // Adjust for pen width
|
||||
painter.drawRect(rect().adjusted(0, 0, -1, -1));
|
||||
|
||||
// Calculate font size based on widget height
|
||||
QFont font = painter.font();
|
||||
|
|
|
|||
|
|
@ -6,6 +6,13 @@
|
|||
#include <QString>
|
||||
#include <QWidget>
|
||||
|
||||
enum class TagState
|
||||
{
|
||||
NotSelected,
|
||||
Selected,
|
||||
Excluded
|
||||
};
|
||||
|
||||
class DeckPreviewTagDisplayWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
|
@ -22,16 +29,16 @@ public:
|
|||
{
|
||||
return tagName;
|
||||
}
|
||||
bool getSelected() const
|
||||
TagState getState() const
|
||||
{
|
||||
return isSelected;
|
||||
return state;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the selected state of the tag.
|
||||
* @param selected True if the tag is selected, false otherwise.
|
||||
*/
|
||||
void setSelected(bool selected);
|
||||
void setState(const TagState newState)
|
||||
{
|
||||
state = newState;
|
||||
update();
|
||||
};
|
||||
|
||||
signals:
|
||||
/**
|
||||
|
|
@ -61,7 +68,7 @@ private:
|
|||
QLabel *tagLabel; ///< Label for displaying the tag name.
|
||||
QPushButton *closeButton; ///< Button to close/remove the tag.
|
||||
QString tagName; ///< The name of the tag.
|
||||
bool isSelected; ///< Indicates whether the tag is selected.
|
||||
TagState state; ///< Indicates whether the tag is unselected, selected, or excluded.
|
||||
};
|
||||
|
||||
#endif // DECK_PREVIEW_TAG_DISPLAY_WIDGET_H
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
#include <QMessageBox>
|
||||
#include <QMouseEvent>
|
||||
#include <QSet>
|
||||
#include <QStandardItemModel>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
DeckPreviewWidget::DeckPreviewWidget(QWidget *_parent,
|
||||
|
|
@ -27,6 +28,8 @@ DeckPreviewWidget::DeckPreviewWidget(QWidget *_parent,
|
|||
deckLoader = new DeckLoader();
|
||||
deckLoader->setParent(this);
|
||||
connect(deckLoader, &DeckLoader::loadFinished, this, &DeckPreviewWidget::initializeUi);
|
||||
/* TODO: We shouldn't update the tags on *every* deck load, since it's kinda expensive. We should instead count how
|
||||
many deck loads have finished already and if we've loaded all decks and THEN load all the tags at once. */
|
||||
connect(deckLoader, &DeckLoader::loadFinished, visualDeckStorageWidget->tagFilterWidget,
|
||||
&VisualDeckStorageTagFilterWidget::refreshTags);
|
||||
deckLoader->loadFromFileAsync(filePath, DeckLoader::getFormatFromName(filePath), false);
|
||||
|
|
@ -194,6 +197,7 @@ void DeckPreviewWidget::updateBannerCardComboBox()
|
|||
|
||||
// Block signals temporarily
|
||||
bool wasBlocked = bannerCardComboBox->blockSignals(true);
|
||||
bannerCardComboBox->setUpdatesEnabled(false);
|
||||
|
||||
// Clear the existing items in the combo box
|
||||
bannerCardComboBox->clear();
|
||||
|
|
@ -209,12 +213,7 @@ void DeckPreviewWidget::updateBannerCardComboBox()
|
|||
continue;
|
||||
|
||||
for (int k = 0; k < currentCard->getNumber(); ++k) {
|
||||
CardInfoPtr info = CardDatabaseManager::getInstance()->getCardByNameAndProviderId(
|
||||
currentCard->getName(), currentCard->getCardProviderId());
|
||||
if (info) {
|
||||
bannerCardSet.insert(
|
||||
QPair<QString, QString>(currentCard->getName(), currentCard->getCardProviderId()));
|
||||
}
|
||||
bannerCardSet.insert(QPair<QString, QString>(currentCard->getName(), currentCard->getCardProviderId()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -226,14 +225,19 @@ void DeckPreviewWidget::updateBannerCardComboBox()
|
|||
return a.first.toLower() < b.first.toLower();
|
||||
});
|
||||
|
||||
for (const auto &pair : pairList) {
|
||||
QVariantMap dataMap;
|
||||
dataMap["name"] = pair.first;
|
||||
dataMap["uuid"] = pair.second;
|
||||
// This is *slightly* more performant than using addItem in a loop.
|
||||
|
||||
bannerCardComboBox->addItem(pair.first, dataMap);
|
||||
QStandardItemModel *model = new QStandardItemModel(pairList.size(), 1, bannerCardComboBox);
|
||||
|
||||
int row = 0;
|
||||
for (const auto &pair : pairList) {
|
||||
QStandardItem *item = new QStandardItem(pair.first);
|
||||
item->setData(QVariant::fromValue(pair), Qt::UserRole);
|
||||
model->setItem(row++, 0, item);
|
||||
}
|
||||
|
||||
bannerCardComboBox->setModel(model);
|
||||
|
||||
// Try to restore the previous selection by finding the currentText
|
||||
int restoredIndex = bannerCardComboBox->findText(currentText);
|
||||
if (restoredIndex != -1) {
|
||||
|
|
@ -251,15 +255,16 @@ void DeckPreviewWidget::updateBannerCardComboBox()
|
|||
|
||||
// Restore the previous signal blocking state
|
||||
bannerCardComboBox->blockSignals(wasBlocked);
|
||||
bannerCardComboBox->setUpdatesEnabled(true);
|
||||
}
|
||||
|
||||
void DeckPreviewWidget::setBannerCard(int /* changedIndex */)
|
||||
{
|
||||
QVariantMap itemData = bannerCardComboBox->itemData(bannerCardComboBox->currentIndex()).toMap();
|
||||
deckLoader->setBannerCard(QPair<QString, QString>(itemData["name"].toString(), itemData["uuid"].toString()));
|
||||
QVariant itemData = bannerCardComboBox->itemData(bannerCardComboBox->currentIndex());
|
||||
deckLoader->setBannerCard(QPair<QString, QString>(bannerCardComboBox->currentText(), itemData.toString()));
|
||||
deckLoader->saveToFile(filePath, DeckLoader::getFormatFromName(filePath));
|
||||
bannerCardDisplayWidget->setCard(CardDatabaseManager::getInstance()->getCardByNameAndProviderId(
|
||||
itemData["name"].toString(), itemData["uuid"].toString()));
|
||||
bannerCardComboBox->currentText(), itemData.toString()));
|
||||
}
|
||||
|
||||
void DeckPreviewWidget::imageClickedEvent(QMouseEvent *event, DeckPreviewCardPictureWidget *instance)
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@
|
|||
#include "../visual_deck_storage_widget.h"
|
||||
#include "deck_preview_deck_tags_display_widget.h"
|
||||
|
||||
#include <QAbstractItemView>
|
||||
#include <QApplication>
|
||||
#include <QComboBox>
|
||||
#include <QEvent>
|
||||
#include <QVBoxLayout>
|
||||
|
|
@ -74,7 +76,22 @@ protected:
|
|||
bool eventFilter(QObject *obj, QEvent *event) override
|
||||
{
|
||||
if (event->type() == QEvent::Wheel) {
|
||||
return true; // Blocks the event
|
||||
if (auto *combo = qobject_cast<QComboBox *>(obj)) {
|
||||
// If popup is not open, forward event to parent scroll area
|
||||
if (!combo->view()->isVisible()) {
|
||||
// Try to find a scrollable parent and manually send the event
|
||||
QWidget *parent = combo->parentWidget();
|
||||
while (parent) {
|
||||
if (auto *scroll = qobject_cast<QAbstractScrollArea *>(parent)) {
|
||||
QApplication::sendEvent(scroll->viewport(), event);
|
||||
return true; // Mark event as handled
|
||||
}
|
||||
parent = parent->parentWidget();
|
||||
}
|
||||
// If no scrollable parent found, just block
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return QObject::eventFilter(obj, event);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -90,9 +90,9 @@ void VisualDeckStorageFolderDisplayWidget::createWidgetsForFiles()
|
|||
&VisualDeckStorageWidget::deckLoadRequested);
|
||||
connect(display, &DeckPreviewWidget::openDeckEditor, visualDeckStorageWidget,
|
||||
&VisualDeckStorageWidget::openDeckEditor);
|
||||
connect(visualDeckStorageWidget->cardSizeWidget->getSlider(), &QSlider::valueChanged,
|
||||
connect(visualDeckStorageWidget->settings(), &VisualDeckStorageQuickSettingsWidget::cardSizeChanged,
|
||||
display->bannerCardDisplayWidget, &CardInfoPictureWidget::setScaleFactor);
|
||||
display->bannerCardDisplayWidget->setScaleFactor(visualDeckStorageWidget->cardSizeWidget->getSlider()->value());
|
||||
display->bannerCardDisplayWidget->setScaleFactor(visualDeckStorageWidget->settings()->getCardSize());
|
||||
allDecks.append(display);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,155 @@
|
|||
#include "visual_deck_storage_quick_settings_widget.h"
|
||||
|
||||
#include "../../../../settings/cache_settings.h"
|
||||
#include "visual_deck_storage_widget.h"
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QSpinBox>
|
||||
|
||||
VisualDeckStorageQuickSettingsWidget::VisualDeckStorageQuickSettingsWidget(QWidget *parent)
|
||||
: SettingsButtonWidget(parent)
|
||||
{
|
||||
// show folders checkbox
|
||||
showFoldersCheckBox = new QCheckBox(this);
|
||||
showFoldersCheckBox->setChecked(SettingsCache::instance().getVisualDeckStorageShowFolders());
|
||||
connect(showFoldersCheckBox, &QCheckBox::QT_STATE_CHANGED, this,
|
||||
&VisualDeckStorageQuickSettingsWidget::showFoldersChanged);
|
||||
connect(showFoldersCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(),
|
||||
&SettingsCache::setVisualDeckStorageShowFolders);
|
||||
|
||||
// show tag filter widget checkbox
|
||||
showTagFilterCheckBox = new QCheckBox(this);
|
||||
showTagFilterCheckBox->setChecked(SettingsCache::instance().getVisualDeckStorageShowTagFilter());
|
||||
connect(showTagFilterCheckBox, &QCheckBox::QT_STATE_CHANGED, this,
|
||||
&VisualDeckStorageQuickSettingsWidget::showTagFilterChanged);
|
||||
connect(showTagFilterCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(),
|
||||
&SettingsCache::setVisualDeckStorageShowTagFilter);
|
||||
|
||||
// show tags on DeckPreviewWidget checkbox
|
||||
showTagsOnDeckPreviewsCheckBox = new QCheckBox(this);
|
||||
showTagsOnDeckPreviewsCheckBox->setChecked(SettingsCache::instance().getVisualDeckStorageShowTagsOnDeckPreviews());
|
||||
connect(showTagsOnDeckPreviewsCheckBox, &QCheckBox::QT_STATE_CHANGED, this,
|
||||
&VisualDeckStorageQuickSettingsWidget::showTagsOnDeckPreviewsChanged);
|
||||
connect(showTagsOnDeckPreviewsCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(),
|
||||
&SettingsCache::setVisualDeckStorageShowTagsOnDeckPreviews);
|
||||
|
||||
// show banner card selector checkbox
|
||||
showBannerCardComboBoxCheckBox = new QCheckBox(this);
|
||||
showBannerCardComboBoxCheckBox->setChecked(SettingsCache::instance().getVisualDeckStorageShowBannerCardComboBox());
|
||||
connect(showBannerCardComboBoxCheckBox, &QCheckBox::QT_STATE_CHANGED, this,
|
||||
&VisualDeckStorageQuickSettingsWidget::showBannerCardComboBoxChanged);
|
||||
connect(showBannerCardComboBoxCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(),
|
||||
&SettingsCache::setVisualDeckStorageShowBannerCardComboBox);
|
||||
|
||||
// search folder names checkbox
|
||||
searchFolderNamesCheckBox = new QCheckBox(this);
|
||||
searchFolderNamesCheckBox->setChecked(SettingsCache::instance().getVisualDeckStorageSearchFolderNames());
|
||||
connect(searchFolderNamesCheckBox, &QCheckBox::QT_STATE_CHANGED, this,
|
||||
&VisualDeckStorageQuickSettingsWidget::searchFolderNamesChanged);
|
||||
connect(searchFolderNamesCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(),
|
||||
&SettingsCache::setVisualDeckStorageSearchFolderNames);
|
||||
|
||||
// draw unused color identities checkbox
|
||||
drawUnusedColorIdentitiesCheckBox = new QCheckBox(this);
|
||||
drawUnusedColorIdentitiesCheckBox->setChecked(
|
||||
SettingsCache::instance().getVisualDeckStorageDrawUnusedColorIdentities());
|
||||
connect(drawUnusedColorIdentitiesCheckBox, &QCheckBox::QT_STATE_CHANGED, this,
|
||||
&VisualDeckStorageQuickSettingsWidget::drawUnusedColorIdentitiesChanged);
|
||||
connect(drawUnusedColorIdentitiesCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(),
|
||||
&SettingsCache::setVisualDeckStorageDrawUnusedColorIdentities);
|
||||
|
||||
// color identity opacity selector
|
||||
auto unusedColorIdentityOpacityWidget = new QWidget(this);
|
||||
|
||||
unusedColorIdentitiesOpacityLabel = new QLabel(unusedColorIdentityOpacityWidget);
|
||||
unusedColorIdentitiesOpacitySpinBox = new QSpinBox(unusedColorIdentityOpacityWidget);
|
||||
|
||||
unusedColorIdentitiesOpacitySpinBox->setMinimum(0);
|
||||
unusedColorIdentitiesOpacitySpinBox->setMaximum(100);
|
||||
unusedColorIdentitiesOpacitySpinBox->setValue(
|
||||
SettingsCache::instance().getVisualDeckStorageUnusedColorIdentitiesOpacity());
|
||||
connect(unusedColorIdentitiesOpacitySpinBox, QOverload<int>::of(&QSpinBox::valueChanged), this,
|
||||
&VisualDeckStorageQuickSettingsWidget::unusedColorIdentitiesOpacityChanged);
|
||||
connect(unusedColorIdentitiesOpacitySpinBox, QOverload<int>::of(&QSpinBox::valueChanged),
|
||||
&SettingsCache::instance(), &SettingsCache::setVisualDeckStorageUnusedColorIdentitiesOpacity);
|
||||
|
||||
unusedColorIdentitiesOpacityLabel->setBuddy(unusedColorIdentitiesOpacitySpinBox);
|
||||
|
||||
auto unusedColorIdentityOpacityLayout = new QHBoxLayout(unusedColorIdentityOpacityWidget);
|
||||
unusedColorIdentityOpacityLayout->setContentsMargins(11, 0, 11, 0);
|
||||
unusedColorIdentityOpacityLayout->addWidget(unusedColorIdentitiesOpacityLabel);
|
||||
unusedColorIdentityOpacityLayout->addWidget(unusedColorIdentitiesOpacitySpinBox);
|
||||
|
||||
// card size slider
|
||||
cardSizeWidget = new CardSizeWidget(this, nullptr, SettingsCache::instance().getVisualDeckStorageCardSize());
|
||||
connect(cardSizeWidget->getSlider(), &QSlider::valueChanged, this,
|
||||
&VisualDeckStorageQuickSettingsWidget::cardSizeChanged);
|
||||
connect(cardSizeWidget, &CardSizeWidget::cardSizeSettingUpdated, &SettingsCache::instance(),
|
||||
&SettingsCache::setVisualDeckStorageCardSize);
|
||||
|
||||
// putting everything together
|
||||
this->addSettingsWidget(showFoldersCheckBox);
|
||||
this->addSettingsWidget(showTagFilterCheckBox);
|
||||
this->addSettingsWidget(showTagsOnDeckPreviewsCheckBox);
|
||||
this->addSettingsWidget(showBannerCardComboBoxCheckBox);
|
||||
this->addSettingsWidget(searchFolderNamesCheckBox);
|
||||
this->addSettingsWidget(drawUnusedColorIdentitiesCheckBox);
|
||||
this->addSettingsWidget(unusedColorIdentityOpacityWidget);
|
||||
this->addSettingsWidget(cardSizeWidget);
|
||||
|
||||
connect(&SettingsCache::instance(), &SettingsCache::langChanged, this,
|
||||
&VisualDeckStorageQuickSettingsWidget::retranslateUi);
|
||||
retranslateUi();
|
||||
}
|
||||
|
||||
void VisualDeckStorageQuickSettingsWidget::retranslateUi()
|
||||
{
|
||||
showFoldersCheckBox->setText(tr("Show Folders"));
|
||||
showTagFilterCheckBox->setText(tr("Show Tag Filter"));
|
||||
showTagsOnDeckPreviewsCheckBox->setText(tr("Show Tags On Deck Previews"));
|
||||
showBannerCardComboBoxCheckBox->setText(tr("Show Banner Card Selection Option"));
|
||||
searchFolderNamesCheckBox->setText(tr("Include Folder Names in Search"));
|
||||
drawUnusedColorIdentitiesCheckBox->setText(tr("Draw unused Color Identities"));
|
||||
unusedColorIdentitiesOpacityLabel->setText(tr("Unused Color Identities Opacity"));
|
||||
unusedColorIdentitiesOpacitySpinBox->setSuffix("%");
|
||||
}
|
||||
|
||||
bool VisualDeckStorageQuickSettingsWidget::getShowFolders() const
|
||||
{
|
||||
return showFoldersCheckBox->isChecked();
|
||||
}
|
||||
|
||||
bool VisualDeckStorageQuickSettingsWidget::getDrawUnusedColorIdentities() const
|
||||
{
|
||||
return drawUnusedColorIdentitiesCheckBox->isChecked();
|
||||
}
|
||||
|
||||
bool VisualDeckStorageQuickSettingsWidget::getShowBannerCardComboBox() const
|
||||
{
|
||||
return showBannerCardComboBoxCheckBox->isChecked();
|
||||
}
|
||||
|
||||
bool VisualDeckStorageQuickSettingsWidget::getShowTagFilter() const
|
||||
{
|
||||
return showTagFilterCheckBox->isChecked();
|
||||
}
|
||||
|
||||
bool VisualDeckStorageQuickSettingsWidget::getShowTagsOnDeckPreviews() const
|
||||
{
|
||||
return showTagsOnDeckPreviewsCheckBox->isChecked();
|
||||
}
|
||||
|
||||
bool VisualDeckStorageQuickSettingsWidget::getSearchFolderNames() const
|
||||
{
|
||||
return searchFolderNamesCheckBox->isChecked();
|
||||
}
|
||||
|
||||
int VisualDeckStorageQuickSettingsWidget::getUnusedColorIdentitiesOpacity() const
|
||||
{
|
||||
return unusedColorIdentitiesOpacitySpinBox->value();
|
||||
}
|
||||
|
||||
int VisualDeckStorageQuickSettingsWidget::getCardSize() const
|
||||
{
|
||||
return cardSizeWidget->getSlider()->value();
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
#ifndef VISUAL_DECK_STORAGE_QUICK_SETTINGS_WIDGET_H
|
||||
#define VISUAL_DECK_STORAGE_QUICK_SETTINGS_WIDGET_H
|
||||
|
||||
#include "../quick_settings/settings_button_widget.h"
|
||||
|
||||
class CardSizeWidget;
|
||||
class QLabel;
|
||||
class QSpinBox;
|
||||
class QCheckBox;
|
||||
|
||||
/**
|
||||
* The VDS's quick settings menu.
|
||||
* Manages the widgets in the quick settings menu dropdown, as well as syncing their values with SettingsCache.
|
||||
* The current values of the settings are exposed through getters and signals.
|
||||
*/
|
||||
class VisualDeckStorageQuickSettingsWidget : public SettingsButtonWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
QCheckBox *showFoldersCheckBox;
|
||||
QCheckBox *drawUnusedColorIdentitiesCheckBox;
|
||||
QCheckBox *showBannerCardComboBoxCheckBox;
|
||||
QCheckBox *showTagFilterCheckBox;
|
||||
QCheckBox *showTagsOnDeckPreviewsCheckBox;
|
||||
QCheckBox *searchFolderNamesCheckBox;
|
||||
QLabel *unusedColorIdentitiesOpacityLabel;
|
||||
QSpinBox *unusedColorIdentitiesOpacitySpinBox;
|
||||
CardSizeWidget *cardSizeWidget;
|
||||
|
||||
public:
|
||||
explicit VisualDeckStorageQuickSettingsWidget(QWidget *parent = nullptr);
|
||||
|
||||
void retranslateUi();
|
||||
|
||||
bool getShowFolders() const;
|
||||
bool getDrawUnusedColorIdentities() const;
|
||||
bool getShowBannerCardComboBox() const;
|
||||
bool getShowTagFilter() const;
|
||||
bool getShowTagsOnDeckPreviews() const;
|
||||
bool getSearchFolderNames() const;
|
||||
int getUnusedColorIdentitiesOpacity() const;
|
||||
int getCardSize() const;
|
||||
|
||||
signals:
|
||||
void showFoldersChanged(bool enabled);
|
||||
void drawUnusedColorIdentitiesChanged(bool enabled);
|
||||
void showBannerCardComboBoxChanged(bool enabled);
|
||||
void showTagFilterChanged(bool enabled);
|
||||
void showTagsOnDeckPreviewsChanged(bool enabled);
|
||||
void searchFolderNamesChanged(bool enabled);
|
||||
void unusedColorIdentitiesOpacityChanged(int opacity);
|
||||
void cardSizeChanged(int scale);
|
||||
};
|
||||
|
||||
#endif // VISUAL_DECK_STORAGE_QUICK_SETTINGS_WIDGET_H
|
||||
|
|
@ -33,57 +33,69 @@ void VisualDeckStorageTagFilterWidget::showEvent(QShowEvent *event)
|
|||
|
||||
void VisualDeckStorageTagFilterWidget::filterDecksBySelectedTags(const QList<DeckPreviewWidget *> &deckPreviews) const
|
||||
{
|
||||
// Collect selected tags from DeckPreviewTagDisplayWidget
|
||||
QStringList selectedTags;
|
||||
QStringList excludedTags;
|
||||
|
||||
// Collect selected and excluded tags
|
||||
for (DeckPreviewTagDisplayWidget *tagWidget : findChildren<DeckPreviewTagDisplayWidget *>()) {
|
||||
if (tagWidget->getSelected()) {
|
||||
selectedTags.append(tagWidget->getTagName());
|
||||
switch (tagWidget->getState()) {
|
||||
case TagState::Selected:
|
||||
selectedTags.append(tagWidget->getTagName());
|
||||
break;
|
||||
case TagState::Excluded:
|
||||
excludedTags.append(tagWidget->getTagName());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If no tags are selected, set all decks as visible
|
||||
if (selectedTags.isEmpty()) {
|
||||
// If no tags are selected or excluded, show all
|
||||
if (selectedTags.isEmpty() && excludedTags.isEmpty()) {
|
||||
for (DeckPreviewWidget *deckPreview : deckPreviews) {
|
||||
deckPreview->filteredByTags = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Filter DeckPreviewWidgets that contain all of the selected tags
|
||||
QList<DeckPreviewWidget *> filteredDecks;
|
||||
for (DeckPreviewWidget *deckPreview : deckPreviews) {
|
||||
QStringList deckTags = deckPreview->deckLoader->getTags();
|
||||
|
||||
// Check if all selectedTags are in deckTags
|
||||
bool allTagsPresent = std::all_of(selectedTags.begin(), selectedTags.end(),
|
||||
bool hasAllSelected = std::all_of(selectedTags.begin(), selectedTags.end(),
|
||||
[&deckTags](const QString &tag) { return deckTags.contains(tag); });
|
||||
|
||||
deckPreview->filteredByTags = !allTagsPresent;
|
||||
bool hasAnyExcluded = std::any_of(excludedTags.begin(), excludedTags.end(),
|
||||
[&deckTags](const QString &tag) { return deckTags.contains(tag); });
|
||||
|
||||
// Filter out if any excluded tag is present or if any selected tag is missing
|
||||
deckPreview->filteredByTags = !(hasAllSelected && !hasAnyExcluded);
|
||||
}
|
||||
}
|
||||
|
||||
void VisualDeckStorageTagFilterWidget::refreshTags()
|
||||
{
|
||||
QStringList allTags = gatherAllTags();
|
||||
removeTagsNotInList(gatherAllTags());
|
||||
addTagsIfNotPresent(gatherAllTags());
|
||||
QSet<QString> allTags = gatherAllTags();
|
||||
removeTagsNotInList(allTags);
|
||||
addTagsIfNotPresent(allTags);
|
||||
sortTags();
|
||||
}
|
||||
|
||||
void VisualDeckStorageTagFilterWidget::removeTagsNotInList(const QStringList &tags)
|
||||
void VisualDeckStorageTagFilterWidget::removeTagsNotInList(const QSet<QString> &tags)
|
||||
{
|
||||
// Iterate through all DeckPreviewTagDisplayWidgets
|
||||
auto *flowWidget = findChild<FlowWidget *>();
|
||||
|
||||
for (DeckPreviewTagDisplayWidget *tagWidget : findChildren<DeckPreviewTagDisplayWidget *>()) {
|
||||
// If the tag is not in the provided tags list, remove the widget
|
||||
if (!tags.contains(tagWidget->getTagName())) {
|
||||
auto *flowWidget = findChild<FlowWidget *>();
|
||||
const QString &tagName = tagWidget->getTagName();
|
||||
|
||||
// Keep the tag widget if it is either selected or excluded
|
||||
if (!tags.contains(tagName) && tagWidget->getState() == TagState::NotSelected) {
|
||||
flowWidget->removeWidget(tagWidget);
|
||||
tagWidget->deleteLater(); // Safely delete the widget
|
||||
tagWidget->deleteLater();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VisualDeckStorageTagFilterWidget::addTagsIfNotPresent(const QStringList &tags)
|
||||
void VisualDeckStorageTagFilterWidget::addTagsIfNotPresent(const QSet<QString> &tags)
|
||||
{
|
||||
for (const QString &tag : tags) {
|
||||
addTagIfNotPresent(tag);
|
||||
|
|
@ -136,20 +148,22 @@ void VisualDeckStorageTagFilterWidget::sortTags()
|
|||
}
|
||||
}
|
||||
|
||||
QStringList VisualDeckStorageTagFilterWidget::gatherAllTags()
|
||||
QSet<QString> VisualDeckStorageTagFilterWidget::gatherAllTags() const
|
||||
{
|
||||
QStringList allTags;
|
||||
QSet<QString> allTags;
|
||||
QList<DeckPreviewWidget *> deckWidgets = parent->findChildren<DeckPreviewWidget *>();
|
||||
|
||||
for (DeckPreviewWidget *widget : deckWidgets) {
|
||||
if (widget->checkVisibility()) {
|
||||
allTags << widget->deckLoader->getTags();
|
||||
for (const QString &tag : widget->deckLoader->getTags()) {
|
||||
allTags.insert(tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
return allTags;
|
||||
}
|
||||
|
||||
QStringList VisualDeckStorageTagFilterWidget::getAllKnownTags()
|
||||
QStringList VisualDeckStorageTagFilterWidget::getAllKnownTags() const
|
||||
{
|
||||
QStringList allTags;
|
||||
|
||||
|
|
|
|||
|
|
@ -10,16 +10,18 @@ class VisualDeckStorageTagFilterWidget : public QWidget
|
|||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit VisualDeckStorageTagFilterWidget(VisualDeckStorageWidget *_parent);
|
||||
QStringList gatherAllTags();
|
||||
void filterDecksBySelectedTags(const QList<DeckPreviewWidget *> &deckPreviews) const;
|
||||
void removeTagsNotInList(const QStringList &tags);
|
||||
void addTagsIfNotPresent(const QStringList &tags);
|
||||
VisualDeckStorageWidget *parent;
|
||||
|
||||
QSet<QString> gatherAllTags() const;
|
||||
void removeTagsNotInList(const QSet<QString> &tags);
|
||||
void addTagsIfNotPresent(const QSet<QString> &tags);
|
||||
void addTagIfNotPresent(const QString &tag);
|
||||
void sortTags();
|
||||
QStringList getAllKnownTags();
|
||||
VisualDeckStorageWidget *parent;
|
||||
|
||||
public:
|
||||
explicit VisualDeckStorageTagFilterWidget(VisualDeckStorageWidget *_parent);
|
||||
QStringList getAllKnownTags() const;
|
||||
void filterDecksBySelectedTags(const QList<DeckPreviewWidget *> &deckPreviews) const;
|
||||
|
||||
public slots:
|
||||
void refreshTags();
|
||||
|
|
|
|||
|
|
@ -41,79 +41,13 @@ VisualDeckStorageWidget::VisualDeckStorageWidget(QWidget *parent) : QWidget(pare
|
|||
refreshButton->setFixedSize(32, 32);
|
||||
connect(refreshButton, &QPushButton::clicked, this, &VisualDeckStorageWidget::refreshIfPossible);
|
||||
|
||||
// quick settings menu
|
||||
showFoldersCheckBox = new QCheckBox(this);
|
||||
showFoldersCheckBox->setChecked(SettingsCache::instance().getVisualDeckStorageShowFolders());
|
||||
connect(showFoldersCheckBox, &QCheckBox::QT_STATE_CHANGED, this, &VisualDeckStorageWidget::updateShowFolders);
|
||||
connect(showFoldersCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(),
|
||||
&SettingsCache::setVisualDeckStorageShowFolders);
|
||||
|
||||
tagFilterVisibilityCheckBox = new QCheckBox(this);
|
||||
tagFilterVisibilityCheckBox->setChecked(SettingsCache::instance().getVisualDeckStorageShowTagFilter());
|
||||
connect(tagFilterVisibilityCheckBox, &QCheckBox::QT_STATE_CHANGED, this,
|
||||
quickSettingsWidget = new VisualDeckStorageQuickSettingsWidget(this);
|
||||
connect(quickSettingsWidget, &VisualDeckStorageQuickSettingsWidget::showFoldersChanged, this,
|
||||
&VisualDeckStorageWidget::updateShowFolders);
|
||||
connect(quickSettingsWidget, &VisualDeckStorageQuickSettingsWidget::showTagFilterChanged, this,
|
||||
&VisualDeckStorageWidget::updateTagsVisibility);
|
||||
connect(tagFilterVisibilityCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(),
|
||||
&SettingsCache::setVisualDeckStorageShowTagFilter);
|
||||
|
||||
tagsOnWidgetsVisibilityCheckBox = new QCheckBox(this);
|
||||
tagsOnWidgetsVisibilityCheckBox->setChecked(SettingsCache::instance().getVisualDeckStorageShowTagsOnDeckPreviews());
|
||||
connect(tagsOnWidgetsVisibilityCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(),
|
||||
&SettingsCache::setVisualDeckStorageShowTagsOnDeckPreviews);
|
||||
|
||||
drawUnusedColorIdentitiesCheckBox = new QCheckBox(this);
|
||||
drawUnusedColorIdentitiesCheckBox->setChecked(
|
||||
SettingsCache::instance().getVisualDeckStorageDrawUnusedColorIdentities());
|
||||
connect(drawUnusedColorIdentitiesCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(),
|
||||
&SettingsCache::setVisualDeckStorageDrawUnusedColorIdentities);
|
||||
|
||||
bannerCardComboBoxVisibilityCheckBox = new QCheckBox(this);
|
||||
bannerCardComboBoxVisibilityCheckBox->setChecked(
|
||||
SettingsCache::instance().getVisualDeckStorageShowBannerCardComboBox());
|
||||
connect(bannerCardComboBoxVisibilityCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(),
|
||||
&SettingsCache::setVisualDeckStorageShowBannerCardComboBox);
|
||||
|
||||
searchFolderNamesCheckBox = new QCheckBox(this);
|
||||
searchFolderNamesCheckBox->setChecked(SettingsCache::instance().getVisualDeckStorageSearchFolderNames());
|
||||
connect(searchFolderNamesCheckBox, &QCheckBox::QT_STATE_CHANGED, this,
|
||||
connect(quickSettingsWidget, &VisualDeckStorageQuickSettingsWidget::searchFolderNamesChanged, this,
|
||||
&VisualDeckStorageWidget::updateSearchFilter);
|
||||
connect(searchFolderNamesCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(),
|
||||
&SettingsCache::setVisualDeckStorageSearchFolderNames);
|
||||
|
||||
// color identity opacity selector
|
||||
auto unusedColorIdentityOpacityWidget = new QWidget(this);
|
||||
|
||||
unusedColorIdentitiesOpacityLabel = new QLabel(unusedColorIdentityOpacityWidget);
|
||||
unusedColorIdentitiesOpacitySpinBox = new QSpinBox(unusedColorIdentityOpacityWidget);
|
||||
|
||||
unusedColorIdentitiesOpacitySpinBox->setMinimum(0);
|
||||
unusedColorIdentitiesOpacitySpinBox->setMaximum(100);
|
||||
unusedColorIdentitiesOpacitySpinBox->setValue(
|
||||
SettingsCache::instance().getVisualDeckStorageUnusedColorIdentitiesOpacity());
|
||||
connect(unusedColorIdentitiesOpacitySpinBox, QOverload<int>::of(&QSpinBox::valueChanged),
|
||||
&SettingsCache::instance(), &SettingsCache::setVisualDeckStorageUnusedColorIdentitiesOpacity);
|
||||
|
||||
unusedColorIdentitiesOpacityLabel->setBuddy(unusedColorIdentitiesOpacitySpinBox);
|
||||
|
||||
unusedColorIdentitiesOpacitySpinBox->setValue(
|
||||
SettingsCache::instance().getVisualDeckStorageUnusedColorIdentitiesOpacity());
|
||||
|
||||
auto unusedColorIdentityOpacityLayout = new QHBoxLayout(unusedColorIdentityOpacityWidget);
|
||||
unusedColorIdentityOpacityLayout->setContentsMargins(11, 0, 11, 0);
|
||||
unusedColorIdentityOpacityLayout->addWidget(unusedColorIdentitiesOpacityLabel);
|
||||
unusedColorIdentityOpacityLayout->addWidget(unusedColorIdentitiesOpacitySpinBox);
|
||||
|
||||
// card size slider
|
||||
cardSizeWidget = new CardSizeWidget(this, nullptr, SettingsCache::instance().getVisualDeckStorageCardSize());
|
||||
|
||||
quickSettingsWidget = new SettingsButtonWidget(this);
|
||||
quickSettingsWidget->addSettingsWidget(showFoldersCheckBox);
|
||||
quickSettingsWidget->addSettingsWidget(tagFilterVisibilityCheckBox);
|
||||
quickSettingsWidget->addSettingsWidget(tagsOnWidgetsVisibilityCheckBox);
|
||||
quickSettingsWidget->addSettingsWidget(bannerCardComboBoxVisibilityCheckBox);
|
||||
quickSettingsWidget->addSettingsWidget(searchFolderNamesCheckBox);
|
||||
quickSettingsWidget->addSettingsWidget(drawUnusedColorIdentitiesCheckBox);
|
||||
quickSettingsWidget->addSettingsWidget(unusedColorIdentityOpacityWidget);
|
||||
quickSettingsWidget->addSettingsWidget(cardSizeWidget);
|
||||
|
||||
searchAndSortLayout->addWidget(deckPreviewColorIdentityFilterWidget);
|
||||
searchAndSortLayout->addWidget(sortWidget);
|
||||
|
|
@ -186,14 +120,16 @@ void VisualDeckStorageWidget::retranslateUi()
|
|||
{
|
||||
databaseLoadIndicator->setText(tr("Loading database ..."));
|
||||
|
||||
showFoldersCheckBox->setText(tr("Show Folders"));
|
||||
tagFilterVisibilityCheckBox->setText(tr("Show Tag Filter"));
|
||||
tagsOnWidgetsVisibilityCheckBox->setText(tr("Show Tags On Deck Previews"));
|
||||
bannerCardComboBoxVisibilityCheckBox->setText(tr("Show Banner Card Selection Option"));
|
||||
searchFolderNamesCheckBox->setText(tr("Include Folder Names in Search"));
|
||||
drawUnusedColorIdentitiesCheckBox->setText(tr("Draw unused Color Identities"));
|
||||
unusedColorIdentitiesOpacityLabel->setText(tr("Unused Color Identities Opacity"));
|
||||
unusedColorIdentitiesOpacitySpinBox->setSuffix("%");
|
||||
refreshButton->setToolTip(tr("Refresh loaded files"));
|
||||
quickSettingsWidget->setToolTip(tr("Visual Deck Storage Settings"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a const pointer to the quick settings so that the values can be accessed.
|
||||
*/
|
||||
const VisualDeckStorageQuickSettingsWidget *VisualDeckStorageWidget::settings() const
|
||||
{
|
||||
return quickSettingsWidget;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -210,7 +146,7 @@ void VisualDeckStorageWidget::reapplySortAndFilters()
|
|||
void VisualDeckStorageWidget::createRootFolderWidget()
|
||||
{
|
||||
folderWidget = new VisualDeckStorageFolderDisplayWidget(this, this, SettingsCache::instance().getDeckPath(), false,
|
||||
showFoldersCheckBox->isChecked());
|
||||
quickSettingsWidget->getShowFolders());
|
||||
|
||||
scrollArea->setWidget(folderWidget); // this automatically destroys the old folderWidget
|
||||
scrollArea->widget()->setMaximumWidth(scrollArea->viewport()->width());
|
||||
|
|
@ -261,7 +197,7 @@ void VisualDeckStorageWidget::updateSearchFilter()
|
|||
{
|
||||
if (folderWidget) {
|
||||
searchWidget->filterWidgets(folderWidget->findChildren<DeckPreviewWidget *>(), searchWidget->getSearchText(),
|
||||
searchFolderNamesCheckBox->isChecked());
|
||||
quickSettingsWidget->getSearchFolderNames());
|
||||
folderWidget->updateVisibility();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
#include "deck_preview/deck_preview_color_identity_filter_widget.h"
|
||||
#include "deck_preview/deck_preview_widget.h"
|
||||
#include "visual_deck_storage_folder_display_widget.h"
|
||||
#include "visual_deck_storage_quick_settings_widget.h"
|
||||
#include "visual_deck_storage_search_widget.h"
|
||||
#include "visual_deck_storage_sort_widget.h"
|
||||
#include "visual_deck_storage_tag_filter_widget.h"
|
||||
|
|
@ -29,10 +30,11 @@ public:
|
|||
void refreshIfPossible();
|
||||
void retranslateUi();
|
||||
|
||||
CardSizeWidget *cardSizeWidget;
|
||||
VisualDeckStorageTagFilterWidget *tagFilterWidget;
|
||||
bool deckPreviewSelectionAnimationEnabled;
|
||||
|
||||
const VisualDeckStorageQuickSettingsWidget *settings() const;
|
||||
|
||||
public slots:
|
||||
void createRootFolderWidget(); // Refresh the display of cards based on the current sorting option
|
||||
void updateShowFolders(bool enabled);
|
||||
|
|
@ -60,15 +62,7 @@ private:
|
|||
VisualDeckStorageSearchWidget *searchWidget;
|
||||
DeckPreviewColorIdentityFilterWidget *deckPreviewColorIdentityFilterWidget;
|
||||
QToolButton *refreshButton;
|
||||
SettingsButtonWidget *quickSettingsWidget;
|
||||
QCheckBox *showFoldersCheckBox;
|
||||
QCheckBox *drawUnusedColorIdentitiesCheckBox;
|
||||
QCheckBox *bannerCardComboBoxVisibilityCheckBox;
|
||||
QCheckBox *tagFilterVisibilityCheckBox;
|
||||
QCheckBox *tagsOnWidgetsVisibilityCheckBox;
|
||||
QCheckBox *searchFolderNamesCheckBox;
|
||||
QLabel *unusedColorIdentitiesOpacityLabel;
|
||||
QSpinBox *unusedColorIdentitiesOpacitySpinBox;
|
||||
VisualDeckStorageQuickSettingsWidget *quickSettingsWidget;
|
||||
QScrollArea *scrollArea;
|
||||
VisualDeckStorageFolderDisplayWidget *folderWidget;
|
||||
|
||||
|
|
|
|||
|
|
@ -239,54 +239,33 @@ static QString getDomainForWebsite(DeckLoader::DecklistWebsite website)
|
|||
}
|
||||
}
|
||||
|
||||
// This struct is here to support the forEachCard function call, defined in decklist. It
|
||||
// requires a function to be called for each card, and passes an inner node and a card for
|
||||
// each card in the decklist.
|
||||
struct FormatDeckListForExport
|
||||
/**
|
||||
* Converts the card to the String that represents it in the decklist export
|
||||
*/
|
||||
static QString toDecklistExportString(const DecklistCardNode *card)
|
||||
{
|
||||
// Create refrences for the strings that will be passed in.
|
||||
QString &mainBoardCards;
|
||||
QString &sideBoardCards;
|
||||
// create main operator for struct, allowing the foreachcard to work.
|
||||
FormatDeckListForExport(QString &_mainBoardCards, QString &_sideBoardCards)
|
||||
: mainBoardCards(_mainBoardCards), sideBoardCards(_sideBoardCards){};
|
||||
QString cardString;
|
||||
// Get the number of cards and add the card name
|
||||
cardString += QString::number(card->getNumber());
|
||||
// Add a space between card num and name
|
||||
cardString += "%20";
|
||||
// Add card name
|
||||
cardString += card->getName();
|
||||
|
||||
void operator()(const InnerDecklistNode *node, const DecklistCardNode *card) const
|
||||
{
|
||||
// Get the card name
|
||||
CardInfoPtr dbCard = CardDatabaseManager::getInstance()->getCard(card->getName());
|
||||
if (!dbCard || dbCard->getIsToken()) {
|
||||
// If it's a token, we don't care about the card.
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if it's a sideboard card.
|
||||
if (node->getName() == DECK_ZONE_SIDE) {
|
||||
// Get the number of cards and add the card name
|
||||
sideBoardCards += QString::number(card->getNumber());
|
||||
// Add a space between card num and name
|
||||
sideBoardCards += "%20";
|
||||
// Add card name
|
||||
sideBoardCards += card->getName();
|
||||
// Add a return at the end of the card
|
||||
sideBoardCards += "%0A";
|
||||
} else // If it's a mainboard card, do the same thing, but for the mainboard card string
|
||||
{
|
||||
mainBoardCards += QString::number(card->getNumber());
|
||||
mainBoardCards += "%20";
|
||||
mainBoardCards += card->getName();
|
||||
if (!card->getCardSetShortName().isNull()) {
|
||||
mainBoardCards += "%20";
|
||||
mainBoardCards += "(" + card->getCardSetShortName() + ")";
|
||||
}
|
||||
if (!card->getCardCollectorNumber().isNull()) {
|
||||
mainBoardCards += "%20";
|
||||
mainBoardCards += card->getCardCollectorNumber();
|
||||
}
|
||||
mainBoardCards += "%0A";
|
||||
}
|
||||
if (!card->getCardSetShortName().isNull()) {
|
||||
cardString += "%20";
|
||||
cardString += "(" + card->getCardSetShortName() + ")";
|
||||
}
|
||||
};
|
||||
if (!card->getCardCollectorNumber().isNull()) {
|
||||
cardString += "%20";
|
||||
cardString += card->getCardCollectorNumber();
|
||||
}
|
||||
|
||||
// Add a return at the end of the card
|
||||
cardString += "%0A";
|
||||
|
||||
return cardString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Export deck to decklist function, called to format the deck in a way to be sent to a server
|
||||
|
|
@ -298,8 +277,25 @@ QString DeckLoader::exportDeckToDecklist(DecklistWebsite website)
|
|||
QString deckString = "https://" + getDomainForWebsite(website) + "/?";
|
||||
// Create two strings to pass to function
|
||||
QString mainBoardCards, sideBoardCards;
|
||||
// Set up the struct to call.
|
||||
FormatDeckListForExport formatDeckListForExport(mainBoardCards, sideBoardCards);
|
||||
|
||||
// Set up the function to call
|
||||
auto formatDeckListForExport = [&mainBoardCards, &sideBoardCards](const auto *node, const auto *card) {
|
||||
// Get the card name
|
||||
CardInfoPtr dbCard = CardDatabaseManager::getInstance()->getCard(card->getName());
|
||||
if (!dbCard || dbCard->getIsToken()) {
|
||||
// If it's a token, we don't care about the card.
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if it's a sideboard card.
|
||||
if (node->getName() == DECK_ZONE_SIDE) {
|
||||
sideBoardCards += toDecklistExportString(card);
|
||||
} else {
|
||||
// If it's a mainboard card, do the same thing, but for the mainboard card string
|
||||
mainBoardCards += toDecklistExportString(card);
|
||||
}
|
||||
};
|
||||
|
||||
// call our struct function for each card in the deck
|
||||
forEachCard(formatDeckListForExport);
|
||||
// Remove the extra return at the end of the last cards
|
||||
|
|
@ -316,17 +312,12 @@ QString DeckLoader::exportDeckToDecklist(DecklistWebsite website)
|
|||
return deckString;
|
||||
}
|
||||
|
||||
// This struct is here to support the forEachCard function call, defined in decklist.
|
||||
// It requires a function to be called for each card, and it will set the providerId.
|
||||
struct SetProviderId
|
||||
/**
|
||||
* Sets the providerId on each card in the decklist based on its set name and collector number.
|
||||
*/
|
||||
void DeckLoader::resolveSetNameAndNumberToProviderID()
|
||||
{
|
||||
// Main operator for struct, allowing the foreachcard to work.
|
||||
SetProviderId()
|
||||
{
|
||||
}
|
||||
|
||||
void operator()(const InnerDecklistNode *node, DecklistCardNode *card) const
|
||||
{
|
||||
auto setProviderId = [](const auto node, const auto card) {
|
||||
Q_UNUSED(node);
|
||||
// Retrieve the providerId based on setName and collectorNumber
|
||||
QString providerId =
|
||||
|
|
@ -336,50 +327,23 @@ struct SetProviderId
|
|||
|
||||
// Set the providerId on the card
|
||||
card->setCardProviderId(providerId);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* This function iterates through each card in the decklist and sets the providerId
|
||||
* on each card based on its set name and collector number.
|
||||
*/
|
||||
void DeckLoader::resolveSetNameAndNumberToProviderID()
|
||||
{
|
||||
// Set up the struct to call.
|
||||
SetProviderId setProviderId;
|
||||
|
||||
// Call the forEachCard method for each card in the deck
|
||||
forEachCard(setProviderId);
|
||||
}
|
||||
|
||||
// This struct is here to support the forEachCard function call, defined in decklist.
|
||||
// It requires a function to be called for each card, and it will set the providerId.
|
||||
struct ClearSetNameAndNumber
|
||||
{
|
||||
// Main operator for struct, allowing the foreachcard to work.
|
||||
ClearSetNameAndNumber()
|
||||
{
|
||||
}
|
||||
|
||||
void operator()(const InnerDecklistNode *node, DecklistCardNode *card) const
|
||||
{
|
||||
Q_UNUSED(node);
|
||||
// Set the providerId on the card
|
||||
card->setCardSetShortName(nullptr);
|
||||
card->setCardCollectorNumber(nullptr);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* This function iterates through each card in the decklist and sets the providerId
|
||||
* on each card based on its set name and collector number.
|
||||
* Clears the set name and numbers on each card in the decklist.
|
||||
*/
|
||||
void DeckLoader::clearSetNamesAndNumbers()
|
||||
{
|
||||
// Set up the struct to call.
|
||||
ClearSetNameAndNumber clearSetNameAndNumber;
|
||||
auto clearSetNameAndNumber = [](const auto node, auto card) {
|
||||
Q_UNUSED(node)
|
||||
// Set the providerId on the card
|
||||
card->setCardSetShortName(nullptr);
|
||||
card->setCardCollectorNumber(nullptr);
|
||||
};
|
||||
|
||||
// Call the forEachCard method for each card in the deck
|
||||
forEachCard(clearSetNameAndNumber);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -67,26 +67,15 @@ void DeckStatsInterface::analyzeDeck(DeckList *deck)
|
|||
manager->post(request, data);
|
||||
}
|
||||
|
||||
struct CopyIfNotAToken
|
||||
void DeckStatsInterface::copyDeckWithoutTokens(DeckList &source, DeckList &destination)
|
||||
{
|
||||
CardDatabase &cardDatabase;
|
||||
DeckList &destination;
|
||||
|
||||
CopyIfNotAToken(CardDatabase &_cardDatabase, DeckList &_destination)
|
||||
: cardDatabase(_cardDatabase), destination(_destination){};
|
||||
|
||||
void operator()(const InnerDecklistNode *node, const DecklistCardNode *card) const
|
||||
{
|
||||
auto copyIfNotAToken = [this, &destination](const auto node, const auto card) {
|
||||
CardInfoPtr dbCard = cardDatabase.getCard(card->getName());
|
||||
if (dbCard && !dbCard->getIsToken()) {
|
||||
DecklistCardNode *addedCard = destination.addCard(card->getName(), node->getName());
|
||||
addedCard->setNumber(card->getNumber());
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
void DeckStatsInterface::copyDeckWithoutTokens(DeckList &source, DeckList &destination)
|
||||
{
|
||||
CopyIfNotAToken copyIfNotAToken(cardDatabase, destination);
|
||||
source.forEachCard(copyIfNotAToken);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,6 +63,9 @@ DlgCreateToken::DlgCreateToken(const QStringList &_predefinedTokens, QWidget *pa
|
|||
destroyCheckBox = new QCheckBox(tr("&Destroy token when it leaves the table"));
|
||||
destroyCheckBox->setChecked(true);
|
||||
|
||||
faceDownCheckBox = new QCheckBox(tr("Create face-down (Only hides name)"));
|
||||
connect(faceDownCheckBox, &QCheckBox::toggled, this, &DlgCreateToken::faceDownCheckBoxToggled);
|
||||
|
||||
QGridLayout *grid = new QGridLayout;
|
||||
grid->addWidget(nameLabel, 0, 0);
|
||||
grid->addWidget(nameEdit, 0, 1);
|
||||
|
|
@ -73,6 +76,7 @@ DlgCreateToken::DlgCreateToken(const QStringList &_predefinedTokens, QWidget *pa
|
|||
grid->addWidget(annotationLabel, 3, 0);
|
||||
grid->addWidget(annotationEdit, 3, 1);
|
||||
grid->addWidget(destroyCheckBox, 4, 0, 1, 2);
|
||||
grid->addWidget(faceDownCheckBox, 5, 0, 1, 2);
|
||||
|
||||
QGroupBox *tokenDataGroupBox = new QGroupBox(tr("Token data"));
|
||||
tokenDataGroupBox->setLayout(grid);
|
||||
|
|
@ -155,6 +159,21 @@ void DlgCreateToken::closeEvent(QCloseEvent *event)
|
|||
SettingsCache::instance().setTokenDialogGeometry(saveGeometry());
|
||||
}
|
||||
|
||||
void DlgCreateToken::faceDownCheckBoxToggled(bool checked)
|
||||
{
|
||||
if (checked) {
|
||||
colorEdit->setCurrentIndex(6);
|
||||
colorEdit->setEnabled(false);
|
||||
ptEdit->clear();
|
||||
ptEdit->clearFocus();
|
||||
ptEdit->setEnabled(false);
|
||||
} else {
|
||||
colorEdit->setEnabled(true);
|
||||
ptEdit->setEnabled(true);
|
||||
annotationEdit->setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
void DlgCreateToken::tokenSelectionChanged(const QModelIndex ¤t, const QModelIndex & /*previous*/)
|
||||
{
|
||||
const QModelIndex realIndex = cardDatabaseDisplayModel->mapToSource(current);
|
||||
|
|
@ -230,5 +249,6 @@ TokenInfo DlgCreateToken::getTokenInfo() const
|
|||
.color = colorEdit->itemData(colorEdit->currentIndex()).toString(),
|
||||
.pt = ptEdit->text(),
|
||||
.annotation = annotationEdit->text(),
|
||||
.destroy = destroyCheckBox->isChecked()};
|
||||
.destroy = destroyCheckBox->isChecked(),
|
||||
.faceDown = faceDownCheckBox->isChecked()};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ struct TokenInfo
|
|||
QString pt;
|
||||
QString annotation;
|
||||
bool destroy = true;
|
||||
bool faceDown = false;
|
||||
};
|
||||
|
||||
class DlgCreateToken : public QDialog
|
||||
|
|
@ -36,6 +37,7 @@ public:
|
|||
protected:
|
||||
void closeEvent(QCloseEvent *event) override;
|
||||
private slots:
|
||||
void faceDownCheckBoxToggled(bool checked);
|
||||
void tokenSelectionChanged(const QModelIndex ¤t, const QModelIndex &previous);
|
||||
void updateSearch(const QString &search);
|
||||
void actChooseTokenFromAll(bool checked);
|
||||
|
|
@ -51,6 +53,7 @@ private:
|
|||
QComboBox *colorEdit;
|
||||
QLineEdit *nameEdit, *ptEdit, *annotationEdit;
|
||||
QCheckBox *destroyCheckBox;
|
||||
QCheckBox *faceDownCheckBox;
|
||||
QRadioButton *chooseTokenFromAllRadioButton, *chooseTokenFromDeckRadioButton;
|
||||
CardInfoPictureWidget *pic;
|
||||
QTreeView *chooseTokenView;
|
||||
|
|
|
|||
|
|
@ -161,7 +161,7 @@ void DlgEditTokens::actAddToken()
|
|||
}
|
||||
}
|
||||
|
||||
QString setName = CardDatabase::TOKENS_SETNAME;
|
||||
QString setName = CardSet::TOKENS_SETNAME;
|
||||
CardInfoPerSetMap sets;
|
||||
sets[setName].append(CardInfoPerSet(databaseModel->getDatabase()->getSet(setName)));
|
||||
CardInfoPtr card = CardInfo::newInstance(name, "", true, QVariantHash(), QList<CardRelation *>(),
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#include "../client/network/release_channel.h"
|
||||
#include "../client/network/spoiler_background_updater.h"
|
||||
#include "../client/sound_engine.h"
|
||||
#include "../client/tabs/tab_supervisor.h"
|
||||
#include "../client/ui/picture_loader/picture_loader.h"
|
||||
#include "../client/ui/theme_manager.h"
|
||||
#include "../deck/custom_line_edit.h"
|
||||
|
|
@ -629,6 +630,10 @@ UserInterfaceSettingsPage::UserInterfaceSettingsPage()
|
|||
connect(&closeEmptyCardViewCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(),
|
||||
&SettingsCache::setCloseEmptyCardView);
|
||||
|
||||
focusCardViewSearchBarCheckBox.setChecked(SettingsCache::instance().getFocusCardViewSearchBar());
|
||||
connect(&focusCardViewSearchBarCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(),
|
||||
&SettingsCache::setFocusCardViewSearchBar);
|
||||
|
||||
annotateTokensCheckBox.setChecked(SettingsCache::instance().getAnnotateTokens());
|
||||
connect(&annotateTokensCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(),
|
||||
&SettingsCache::setAnnotateTokens);
|
||||
|
|
@ -642,8 +647,9 @@ UserInterfaceSettingsPage::UserInterfaceSettingsPage()
|
|||
generalGrid->addWidget(&clickPlaysAllSelectedCheckBox, 1, 0);
|
||||
generalGrid->addWidget(&playToStackCheckBox, 2, 0);
|
||||
generalGrid->addWidget(&closeEmptyCardViewCheckBox, 3, 0);
|
||||
generalGrid->addWidget(&annotateTokensCheckBox, 4, 0);
|
||||
generalGrid->addWidget(&useTearOffMenusCheckBox, 5, 0);
|
||||
generalGrid->addWidget(&focusCardViewSearchBarCheckBox, 4, 0);
|
||||
generalGrid->addWidget(&annotateTokensCheckBox, 5, 0);
|
||||
generalGrid->addWidget(&useTearOffMenusCheckBox, 6, 0);
|
||||
|
||||
generalGroupBox = new QGroupBox;
|
||||
generalGroupBox->setLayout(generalGrid);
|
||||
|
|
@ -699,12 +705,20 @@ UserInterfaceSettingsPage::UserInterfaceSettingsPage()
|
|||
index == visualDeckStoragePromptForConversionIndexAlways);
|
||||
});
|
||||
|
||||
defaultDeckEditorTypeSelector.addItem(""); // these will be set in retranslateUI
|
||||
defaultDeckEditorTypeSelector.addItem("");
|
||||
defaultDeckEditorTypeSelector.setCurrentIndex(SettingsCache::instance().getDefaultDeckEditorType());
|
||||
connect(&defaultDeckEditorTypeSelector, QOverload<int>::of(&QComboBox::currentIndexChanged),
|
||||
&SettingsCache::instance(), &SettingsCache::setDefaultDeckEditorType);
|
||||
|
||||
auto *deckEditorGrid = new QGridLayout;
|
||||
deckEditorGrid->addWidget(&openDeckInNewTabCheckBox, 0, 0);
|
||||
deckEditorGrid->addWidget(&visualDeckStorageInGameCheckBox, 1, 0);
|
||||
deckEditorGrid->addWidget(&visualDeckStorageSelectionAnimationCheckBox, 2, 0);
|
||||
deckEditorGrid->addWidget(&visualDeckStoragePromptForConversionLabel, 3, 0);
|
||||
deckEditorGrid->addWidget(&visualDeckStoragePromptForConversionSelector, 3, 1);
|
||||
deckEditorGrid->addWidget(&defaultDeckEditorTypeLabel, 4, 0);
|
||||
deckEditorGrid->addWidget(&defaultDeckEditorTypeSelector, 4, 1);
|
||||
|
||||
deckEditorGroupBox = new QGroupBox;
|
||||
deckEditorGroupBox->setLayout(deckEditorGrid);
|
||||
|
|
@ -754,6 +768,7 @@ void UserInterfaceSettingsPage::retranslateUi()
|
|||
clickPlaysAllSelectedCheckBox.setText(tr("&Clicking plays all selected cards (instead of just the clicked card)"));
|
||||
playToStackCheckBox.setText(tr("&Play all nonlands onto the stack (not the battlefield) by default"));
|
||||
closeEmptyCardViewCheckBox.setText(tr("Close card view window when last card is removed"));
|
||||
focusCardViewSearchBarCheckBox.setText(tr("Auto focus search bar when card view window is opened"));
|
||||
annotateTokensCheckBox.setText(tr("Annotate card text on tokens"));
|
||||
useTearOffMenusCheckBox.setText(tr("Use tear-off menus, allowing right click menus to persist on screen"));
|
||||
notificationsGroupBox->setTitle(tr("Notifications settings"));
|
||||
|
|
@ -774,6 +789,9 @@ void UserInterfaceSettingsPage::retranslateUi()
|
|||
tr("ask to convert to .cod"));
|
||||
visualDeckStoragePromptForConversionSelector.setItemText(visualDeckStoragePromptForConversionIndexAlways,
|
||||
tr("always convert to .cod"));
|
||||
defaultDeckEditorTypeLabel.setText(tr("Default deck editor type"));
|
||||
defaultDeckEditorTypeSelector.setItemText(TabSupervisor::ClassicDeckEditor, tr("Classic Deck Editor"));
|
||||
defaultDeckEditorTypeSelector.setItemText(TabSupervisor::VisualDeckEditor, tr("Visual Deck Editor"));
|
||||
replayGroupBox->setTitle(tr("Replay settings"));
|
||||
rewindBufferingMsLabel.setText(tr("Buffer time for backwards skip via shortcut:"));
|
||||
rewindBufferingMsBox.setSuffix(" ms");
|
||||
|
|
|
|||
|
|
@ -147,6 +147,7 @@ private:
|
|||
QCheckBox clickPlaysAllSelectedCheckBox;
|
||||
QCheckBox playToStackCheckBox;
|
||||
QCheckBox closeEmptyCardViewCheckBox;
|
||||
QCheckBox focusCardViewSearchBarCheckBox;
|
||||
QCheckBox annotateTokensCheckBox;
|
||||
QCheckBox useTearOffMenusCheckBox;
|
||||
QCheckBox tapAnimationCheckBox;
|
||||
|
|
@ -155,6 +156,8 @@ private:
|
|||
QComboBox visualDeckStoragePromptForConversionSelector;
|
||||
QCheckBox visualDeckStorageInGameCheckBox;
|
||||
QCheckBox visualDeckStorageSelectionAnimationCheckBox;
|
||||
QLabel defaultDeckEditorTypeLabel;
|
||||
QComboBox defaultDeckEditorTypeSelector;
|
||||
QLabel rewindBufferingMsLabel;
|
||||
QSpinBox rewindBufferingMsBox;
|
||||
QGroupBox *generalGroupBox;
|
||||
|
|
|
|||
|
|
@ -3,23 +3,40 @@
|
|||
#include "../settings/cache_settings.h"
|
||||
#include "../utility/logger.h"
|
||||
|
||||
#include <QClipboard>
|
||||
#include <QPlainTextEdit>
|
||||
#include <QPushButton>
|
||||
#include <QRegularExpression>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
DlgViewLog::DlgViewLog(QWidget *parent) : QDialog(parent)
|
||||
{
|
||||
|
||||
logArea = new QPlainTextEdit;
|
||||
logArea->setReadOnly(true);
|
||||
|
||||
auto *mainLayout = new QVBoxLayout;
|
||||
mainLayout->setSpacing(3);
|
||||
mainLayout->setContentsMargins(20, 20, 20, 6);
|
||||
|
||||
mainLayout->addWidget(logArea);
|
||||
|
||||
auto *bottomLayout = new QHBoxLayout;
|
||||
|
||||
coClearLog = new QCheckBox;
|
||||
coClearLog->setText(tr("Clear log when closing"));
|
||||
coClearLog->setChecked(SettingsCache::instance().servers().getClearDebugLogStatus(false));
|
||||
connect(coClearLog, &QCheckBox::toggled, this, &DlgViewLog::actCheckBoxChanged);
|
||||
mainLayout->addWidget(coClearLog);
|
||||
|
||||
copyToClipboardButton = new QPushButton;
|
||||
copyToClipboardButton->setText(tr("Copy to clipboard"));
|
||||
copyToClipboardButton->setAutoDefault(false);
|
||||
connect(copyToClipboardButton, &QPushButton::clicked, this, &DlgViewLog::actCopyToClipboard);
|
||||
|
||||
bottomLayout->addWidget(coClearLog);
|
||||
bottomLayout->addStretch();
|
||||
bottomLayout->addWidget(copyToClipboardButton);
|
||||
|
||||
mainLayout->addLayout(bottomLayout);
|
||||
|
||||
setLayout(mainLayout);
|
||||
|
||||
|
|
@ -27,7 +44,7 @@ DlgViewLog::DlgViewLog(QWidget *parent) : QDialog(parent)
|
|||
resize(800, 500);
|
||||
|
||||
loadInitialLogBuffer();
|
||||
connect(&Logger::getInstance(), &Logger::logEntryAdded, this, &DlgViewLog::logEntryAdded);
|
||||
connect(&Logger::getInstance(), &Logger::logEntryAdded, this, &DlgViewLog::appendLogEntry);
|
||||
}
|
||||
|
||||
void DlgViewLog::actCheckBoxChanged(bool abNewValue)
|
||||
|
|
@ -35,16 +52,26 @@ void DlgViewLog::actCheckBoxChanged(bool abNewValue)
|
|||
SettingsCache::instance().servers().setClearDebugLogStatus(abNewValue);
|
||||
}
|
||||
|
||||
void DlgViewLog::actCopyToClipboard()
|
||||
{
|
||||
QApplication::clipboard()->setText(logArea->toPlainText());
|
||||
}
|
||||
|
||||
void DlgViewLog::loadInitialLogBuffer()
|
||||
{
|
||||
QList<QString> logBuffer = Logger::getInstance().getLogBuffer();
|
||||
for (const QString &message : logBuffer)
|
||||
logEntryAdded(message);
|
||||
appendLogEntry(message);
|
||||
}
|
||||
|
||||
void DlgViewLog::logEntryAdded(QString message)
|
||||
void DlgViewLog::appendLogEntry(const QString &message)
|
||||
{
|
||||
logArea->appendPlainText(message);
|
||||
static auto colorEscapeCodePattern = QRegularExpression("\033\\[\\d+m");
|
||||
|
||||
QString sanitizedMessage = message;
|
||||
sanitizedMessage.replace(colorEscapeCodePattern, "");
|
||||
|
||||
logArea->appendPlainText(sanitizedMessage);
|
||||
}
|
||||
|
||||
void DlgViewLog::closeEvent(QCloseEvent * /* event */)
|
||||
|
|
|
|||
|
|
@ -19,11 +19,13 @@ protected:
|
|||
private:
|
||||
QPlainTextEdit *logArea;
|
||||
QCheckBox *coClearLog;
|
||||
QPushButton *copyToClipboardButton;
|
||||
|
||||
void loadInitialLogBuffer();
|
||||
private slots:
|
||||
void logEntryAdded(QString message);
|
||||
void appendLogEntry(const QString &message);
|
||||
void actCheckBoxChanged(bool abNewValue);
|
||||
void actCopyToClipboard();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -39,6 +39,8 @@ AbstractCardDragItem::AbstractCardDragItem(AbstractCardItem *_item,
|
|||
prepareGeometryChange();
|
||||
update();
|
||||
});
|
||||
|
||||
connect(item, &QObject::destroyed, this, &AbstractCardDragItem::deleteLater);
|
||||
}
|
||||
|
||||
AbstractCardDragItem::~AbstractCardDragItem()
|
||||
|
|
@ -2,9 +2,9 @@
|
|||
|
||||
#include "../../client/ui/picture_loader/picture_loader.h"
|
||||
#include "../../settings/cache_settings.h"
|
||||
#include "../cards/card_database.h"
|
||||
#include "../cards/card_database_manager.h"
|
||||
#include "../game_scene.h"
|
||||
#include "card_database.h"
|
||||
#include "card_database_manager.h"
|
||||
|
||||
#include <QCursor>
|
||||
#include <QGraphicsScene>
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
#ifndef ABSTRACTCARDITEM_H
|
||||
#define ABSTRACTCARDITEM_H
|
||||
|
||||
#include "../board/arrow_target.h"
|
||||
#include "card_info.h"
|
||||
#include "../cards/card_info.h"
|
||||
#include "arrow_target.h"
|
||||
|
||||
class Player;
|
||||
|
||||
|
|
@ -3,10 +3,10 @@
|
|||
|
||||
#include "../../settings/cache_settings.h"
|
||||
#include "../cards/card_info.h"
|
||||
#include "../cards/card_item.h"
|
||||
#include "../player/player.h"
|
||||
#include "../player/player_target.h"
|
||||
#include "../zones/card_zone.h"
|
||||
#include "card_item.h"
|
||||
#include "color.h"
|
||||
#include "pb/command_attach_card.pb.h"
|
||||
#include "pb/command_create_arrow.pb.h"
|
||||
|
|
|
|||
|
|
@ -47,10 +47,25 @@ void CardDragItem::updatePosition(const QPointF &cursorScenePos)
|
|||
cursorZone = zoneViewZone;
|
||||
else if (cardZone)
|
||||
cursorZone = cardZone;
|
||||
if (!cursorZone)
|
||||
return;
|
||||
|
||||
// Always update the current zone, even if its null, to cancel the drag
|
||||
// instead of dropping cards into an non-intuitive location.
|
||||
currentZone = cursorZone;
|
||||
|
||||
if (!cursorZone) {
|
||||
// Avoid the cards getting stuck visually when not over
|
||||
// any zone.
|
||||
QPointF newPos = cursorScenePos - hotSpot;
|
||||
|
||||
if (newPos != pos()) {
|
||||
for (int i = 0; i < childDrags.size(); i++)
|
||||
childDrags[i]->setPos(newPos + childDrags[i]->getHotSpot());
|
||||
setPos(newPos);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
QPointF zonePos = currentZone->scenePos();
|
||||
QPointF cursorPosInZone = cursorScenePos - zonePos;
|
||||
|
||||
|
|
@ -2,14 +2,14 @@
|
|||
|
||||
#include "../../client/tabs/tab_game.h"
|
||||
#include "../../settings/cache_settings.h"
|
||||
#include "../board/arrow_item.h"
|
||||
#include "../cards/card_info.h"
|
||||
#include "../game_scene.h"
|
||||
#include "../player/player.h"
|
||||
#include "../zones/card_zone.h"
|
||||
#include "../zones/table_zone.h"
|
||||
#include "../zones/view_zone.h"
|
||||
#include "arrow_item.h"
|
||||
#include "card_drag_item.h"
|
||||
#include "card_info.h"
|
||||
#include "pb/serverinfo_card.pb.h"
|
||||
|
||||
#include <QApplication>
|
||||
|
|
@ -336,8 +336,7 @@ void CardItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
|||
if ((event->screenPos() - event->buttonDownScreenPos(Qt::LeftButton)).manhattanLength() <
|
||||
2 * QApplication::startDragDistance())
|
||||
return;
|
||||
if (zone->getIsView()) {
|
||||
const ZoneViewZone *view = static_cast<const ZoneViewZone *>(zone);
|
||||
if (const ZoneViewZone *view = qobject_cast<const ZoneViewZone *>(zone)) {
|
||||
if (view->getRevealZone() && !view->getWriteableRevealZone())
|
||||
return;
|
||||
} else if (!owner->getLocalOrJudge())
|
||||
|
|
@ -394,10 +393,8 @@ void CardItem::playCard(bool faceDown)
|
|||
*/
|
||||
static bool isUnwritableRevealZone(CardZone *zone)
|
||||
{
|
||||
if (zone && zone->getIsView()) {
|
||||
if (auto *view = static_cast<ZoneViewZone *>(zone)) {
|
||||
return view->getRevealZone() && !view->getWriteableRevealZone();
|
||||
}
|
||||
if (auto *view = qobject_cast<ZoneViewZone *>(zone)) {
|
||||
return view->getRevealZone() && !view->getWriteableRevealZone();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
#include "card_list.h"
|
||||
|
||||
#include "card_info.h"
|
||||
#include "../cards/card_info.h"
|
||||
#include "card_item.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
|
@ -16,8 +16,6 @@
|
|||
#include <algorithm>
|
||||
#include <utility>
|
||||
|
||||
const char *CardDatabase::TOKENS_SETNAME = "TK";
|
||||
|
||||
CardDatabase::CardDatabase(QObject *parent) : QObject(parent), loadStatus(NotLoaded)
|
||||
{
|
||||
qRegisterMetaType<CardInfoPtr>("CardInfoPtr");
|
||||
|
|
@ -386,9 +384,10 @@ CardInfoPerSet CardDatabase::getSpecificSetForCard(const QString &cardName,
|
|||
|
||||
for (const auto &cardInfoPerSetList : setMap) {
|
||||
for (auto &cardInfoForSet : cardInfoPerSetList) {
|
||||
if (cardInfoForSet.getPtr()->getShortName() == setShortName &&
|
||||
cardInfoForSet.getProperty("num") == collectorNumber) {
|
||||
return cardInfoForSet;
|
||||
if (cardInfoForSet.getPtr()->getShortName() == setShortName) {
|
||||
if (cardInfoForSet.getProperty("num") == collectorNumber || collectorNumber.isEmpty()) {
|
||||
return cardInfoForSet;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -559,16 +558,15 @@ void CardDatabase::notifyEnabledSetsChanged()
|
|||
|
||||
bool CardDatabase::saveCustomTokensToFile()
|
||||
{
|
||||
QString fileName =
|
||||
SettingsCache::instance().getCustomCardDatabasePath() + "/" + CardDatabase::TOKENS_SETNAME + ".xml";
|
||||
QString fileName = SettingsCache::instance().getCustomCardDatabasePath() + "/" + CardSet::TOKENS_SETNAME + ".xml";
|
||||
|
||||
SetNameMap tmpSets;
|
||||
CardSetPtr customTokensSet = getSet(CardDatabase::TOKENS_SETNAME);
|
||||
tmpSets.insert(CardDatabase::TOKENS_SETNAME, customTokensSet);
|
||||
CardSetPtr customTokensSet = getSet(CardSet::TOKENS_SETNAME);
|
||||
tmpSets.insert(CardSet::TOKENS_SETNAME, customTokensSet);
|
||||
|
||||
CardNameMap tmpCards;
|
||||
for (const CardInfoPtr &card : cards) {
|
||||
if (card->getSets().contains(CardDatabase::TOKENS_SETNAME)) {
|
||||
if (card->getSets().contains(CardSet::TOKENS_SETNAME)) {
|
||||
tmpCards.insert(card->getName(), card);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,8 +61,6 @@ private:
|
|||
*removeCardMutex = new QBasicMutex();
|
||||
|
||||
public:
|
||||
static const char *TOKENS_SETNAME;
|
||||
|
||||
explicit CardDatabase(QObject *parent = nullptr);
|
||||
~CardDatabase() override;
|
||||
void clear();
|
||||
|
|
|
|||
|
|
@ -387,7 +387,7 @@ TokenEditModel::TokenEditModel(QObject *parent) : CardDatabaseDisplayModel(paren
|
|||
bool TokenEditModel::filterAcceptsRow(int sourceRow, const QModelIndex & /*sourceParent*/) const
|
||||
{
|
||||
CardInfoPtr info = static_cast<CardDatabaseModel *>(sourceModel())->getCard(sourceRow);
|
||||
return info->getIsToken() && info->getSets().contains(CardDatabase::TOKENS_SETNAME) && rowMatchesCardName(info);
|
||||
return info->getIsToken() && info->getSets().contains(CardSet::TOKENS_SETNAME) && rowMatchesCardName(info);
|
||||
}
|
||||
|
||||
int TokenEditModel::rowCount(const QModelIndex &parent) const
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@
|
|||
#include <algorithm>
|
||||
#include <utility>
|
||||
|
||||
const char *CardSet::TOKENS_SETNAME = "TK";
|
||||
|
||||
CardSet::CardSet(const QString &_shortName,
|
||||
const QString &_longName,
|
||||
const QString &_setType,
|
||||
|
|
@ -289,8 +291,12 @@ QString CardInfo::getCorrectedName() const
|
|||
|
||||
void CardInfo::addToSet(const CardSetPtr &_set, const CardInfoPerSet _info)
|
||||
{
|
||||
_set->append(smartThis);
|
||||
sets[_set->getShortName()].append(_info);
|
||||
if (!_set->contains(smartThis)) {
|
||||
_set->append(smartThis);
|
||||
}
|
||||
if (!sets[_set->getShortName()].contains(_info)) {
|
||||
sets[_set->getShortName()].append(_info);
|
||||
}
|
||||
|
||||
refreshCachedSetNames();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,6 +43,8 @@ public:
|
|||
PriorityLowest = 100,
|
||||
};
|
||||
|
||||
static const char *TOKENS_SETNAME;
|
||||
|
||||
private:
|
||||
QString shortName, longName;
|
||||
unsigned int sortKey;
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue