Edhrec tab (#5512)

---------

Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
Co-authored-by: Zach H <zahalpern+github@gmail.com>
This commit is contained in:
BruebachL 2025-01-25 23:29:27 +01:00 committed by GitHub
parent aee68f8b00
commit 4d791f4d7a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
37 changed files with 1468 additions and 28 deletions

View file

@ -81,6 +81,7 @@ set(cockatrice_SOURCES
src/utility/logger.cpp
src/client/ui/widgets/cards/card_info_picture_enlarged_widget.cpp
src/client/ui/widgets/cards/card_info_picture_with_text_overlay_widget.cpp
src/client/ui/widgets/general/display/banner_widget.cpp
src/client/ui/widgets/general/display/labeled_input.cpp
src/client/ui/widgets/general/display/dynamic_font_size_label.cpp
src/client/ui/widgets/general/display/dynamic_font_size_push_button.cpp
@ -149,6 +150,19 @@ set(cockatrice_SOURCES
src/client/tabs/tab_room.cpp
src/client/tabs/tab_server.cpp
src/client/tabs/tab_supervisor.cpp
src/client/tabs/api/edhrec/tab_edhrec.cpp
src/client/tabs/api/edhrec/edhrec_commander_api_response_display_widget.cpp
src/client/tabs/api/edhrec/edhrec_commander_api_response_card_details_display_widget.cpp
src/client/tabs/api/edhrec/edhrec_commander_api_response_card_list_display_widget.cpp
src/client/tabs/api/edhrec/edhrec_commander_api_response_commander_details_display_widget.cpp
src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_archidekt_links.cpp
src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_average_deck_statistics.cpp
src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_card_details.cpp
src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_card_list.cpp
src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_card_container.cpp
src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_card_prices.cpp
src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_commander_details.cpp
src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response.cpp
src/game/zones/table_zone.cpp
src/client/tapped_out_interface.cpp
src/client/ui/theme_manager.cpp

View file

@ -0,0 +1,45 @@
#include "edhrec_commander_api_response.h"
#include <QDebug>
#include <QJsonArray>
void EdhrecCommanderApiResponse::fromJson(const QJsonObject &json)
{
// Parse the collapsed DeckStatistics
deckStats.fromJson(json);
// Parse Archidekt section
QJsonArray archidektJson = json.value("archidekt").toArray();
archidekt.fromJson(archidektJson);
// Parse other fields
similar = json.value("similar").toObject();
header = json.value("header").toString();
panels = json.value("panels").toObject();
description = json.value("description").toString();
QJsonObject containerJson = json.value("container").toObject();
container.fromJson(containerJson);
}
void EdhrecCommanderApiResponse::debugPrint() const
{
qDebug() << "Deck Statistics:";
qDebug() << " Creature:" << deckStats.creature;
qDebug() << " Instant:" << deckStats.instant;
qDebug() << " Sorcery:" << deckStats.sorcery;
qDebug() << " Artifact:" << deckStats.artifact;
qDebug() << " Enchantment:" << deckStats.enchantment;
qDebug() << " Battle:" << deckStats.battle;
qDebug() << " Planeswalker:" << deckStats.planeswalker;
qDebug() << " Land:" << deckStats.land;
qDebug() << " Basic:" << deckStats.basic;
qDebug() << " Nonbasic:" << deckStats.nonbasic;
archidekt.debugPrint();
qDebug() << "Similar:" << similar;
qDebug() << "Header:" << header;
qDebug() << "Panels:" << panels;
qDebug() << "Description:" << description;
container.debugPrint();
}

View file

@ -0,0 +1,28 @@
#ifndef DECKDATA_H
#define DECKDATA_H
#include "edhrec_commander_api_response_archidekt_links.h"
#include "edhrec_commander_api_response_average_deck_statistics.h"
#include "edhrec_commander_api_response_card_container.h"
#include <QDebug>
#include <QJsonObject>
#include <QString>
// Represents the main structure of the JSON
class EdhrecCommanderApiResponse
{
public:
EdhrecCommanderApiResponseAverageDeckStatistics deckStats;
EdhrecCommanderApiResponseArchidektLinks archidekt;
QJsonObject similar;
QString header;
QJsonObject panels;
QString description;
EdhrecCommanderApiResponseCardContainer container;
void fromJson(const QJsonObject &json);
void debugPrint() const;
};
#endif // DECKDATA_H

View file

@ -0,0 +1,43 @@
#include "edhrec_commander_api_response_archidekt_links.h"
#include <QDebug>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
void EdhrecCommanderApiResponseArchidektLink::fromJson(const QJsonObject &json)
{
c = json.value("c").toString();
f = json.value("f").toInt(0);
q = json.value("q").toInt(0);
u = json.value("u").toString();
}
void EdhrecCommanderApiResponseArchidektLink::debugPrint() const
{
qDebug() << " C:" << c;
qDebug() << " F:" << f;
qDebug() << " Q:" << q;
qDebug() << " U:" << u;
}
void EdhrecCommanderApiResponseArchidektLinks::fromJson(const QJsonArray &json)
{
entries.clear();
for (const QJsonValue &value : json) {
if (value.isObject()) {
QJsonObject entryJson = value.toObject();
EdhrecCommanderApiResponseArchidektLink entry;
entry.fromJson(entryJson);
entries.append(entry);
}
}
}
void EdhrecCommanderApiResponseArchidektLinks::debugPrint() const
{
qDebug() << "Archidekt Entries:";
for (const auto &entry : entries) {
entry.debugPrint();
}
}

View file

@ -0,0 +1,32 @@
#ifndef ARCHIDEKTENTRY_H
#define ARCHIDEKTENTRY_H
#include <QDebug>
#include <QJsonObject>
#include <QString>
#include <QVector>
// Represents a single Archidekt entry
class EdhrecCommanderApiResponseArchidektLink
{
public:
QString c;
int f = 0;
int q = 0;
QString u;
void fromJson(const QJsonObject &json);
void debugPrint() const;
};
// Represents the Archidekt section as a list of entries
class EdhrecCommanderApiResponseArchidektLinks
{
public:
QVector<EdhrecCommanderApiResponseArchidektLink> entries;
void fromJson(const QJsonArray &json);
void debugPrint() const;
};
#endif // ARCHIDEKTENTRY_H

View file

@ -0,0 +1,15 @@
#include "edhrec_commander_api_response_average_deck_statistics.h"
void EdhrecCommanderApiResponseAverageDeckStatistics::fromJson(const QJsonObject &json)
{
creature = json.value("creature").toInt(0);
instant = json.value("instant").toInt(0);
sorcery = json.value("sorcery").toInt(0);
artifact = json.value("artifact").toInt(0);
enchantment = json.value("enchantment").toInt(0);
battle = json.value("battle").toInt(0);
planeswalker = json.value("planeswalker").toInt(0);
land = json.value("land").toInt(0);
basic = json.value("basic").toInt(0);
nonbasic = json.value("nonbasic").toInt(0);
}

View file

@ -0,0 +1,22 @@
#ifndef AVERAGE_DECK_STATISTICS_H
#define AVERAGE_DECK_STATISTICS_H
#include <QJsonObject>
// Represents the typical deck statistics (collapsed section)
struct EdhrecCommanderApiResponseAverageDeckStatistics
{
int creature = 0;
int instant = 0;
int sorcery = 0;
int artifact = 0;
int enchantment = 0;
int battle = 0;
int planeswalker = 0;
int land = 0;
int basic = 0;
int nonbasic = 0;
void fromJson(const QJsonObject &json);
};
#endif // AVERAGE_DECK_STATISTICS_H

View file

@ -0,0 +1,49 @@
#include "edhrec_commander_api_response_card_container.h"
#include <QDebug>
#include <QJsonArray>
#include <QJsonObject>
void EdhrecCommanderApiResponseCardContainer::fromJson(const QJsonObject &json)
{
// Parse breadcrumb
QJsonArray breadcrumbArray = json.value("breadcrumb").toArray();
for (const QJsonValue &breadcrumbValue : breadcrumbArray) {
breadcrumb.push_back(breadcrumbValue.toObject());
}
description = json.value("description").toString();
QJsonObject jsonDict = json.value("json_dict").toObject();
card.fromJson(jsonDict.value("card").toObject());
QJsonArray cardlistsArray = jsonDict.value("cardlists").toArray();
for (const QJsonValue &cardlistValue : cardlistsArray) {
QJsonObject cardlistObj = cardlistValue.toObject();
QJsonArray cardviewsArray = cardlistObj.value("cardviews").toArray();
EdhrecCommanderApiResponseCardList cardView;
cardView.fromJson(cardlistValue.toObject());
cardlists.push_back(cardView);
}
keywords = json.value("keywords").toString();
title = json.value("title").toString();
}
void EdhrecCommanderApiResponseCardContainer::debugPrint() const
{
qDebug() << "Breadcrumb:";
for (const auto &breadcrumbEntry : breadcrumb) {
qDebug() << breadcrumbEntry;
}
qDebug() << "Description:" << description;
card.debugPrint();
qDebug() << "Cardlists:";
for (const auto &cardlist : cardlists) {
cardlist.debugPrint();
}
qDebug() << "Keywords:" << keywords;
qDebug() << "Title:" << title;
}

View file

@ -0,0 +1,60 @@
#ifndef CONTAINER_ENTRY_H
#define CONTAINER_ENTRY_H
#include "edhrec_commander_api_response_card_list.h"
#include "edhrec_commander_api_response_commander_details.h"
#include <QDebug>
#include <QJsonArray>
#include <QJsonObject>
#include <QString>
#include <QVector>
class EdhrecCommanderApiResponseCardContainer
{
public:
// Constructor
EdhrecCommanderApiResponseCardContainer() = default;
// Parse deck-related data from JSON
void fromJson(const QJsonObject &json);
// Debug method for logging
void debugPrint() const;
// Getter methods for deck container
const QString &getDescription() const
{
return description;
}
const QVector<QJsonObject> &getBreadcrumb() const
{
return breadcrumb;
}
const EdhrecCommanderApiResponseCommanderDetails &getCommanderDetails() const
{
return card;
}
const QVector<EdhrecCommanderApiResponseCardList> &getCardlists() const
{
return cardlists;
}
const QString &getKeywords() const
{
return keywords;
}
const QString &getTitle() const
{
return title;
}
private:
QString description;
QVector<QJsonObject> breadcrumb;
EdhrecCommanderApiResponseCommanderDetails card;
QVector<EdhrecCommanderApiResponseCardList> cardlists;
QString keywords;
QString title;
};
#endif // CONTAINER_ENTRY_H

View file

@ -0,0 +1,36 @@
#include "edhrec_commander_api_response_card_details.h"
#include <QDebug>
EdhrecCommanderApiResponseCardDetails::EdhrecCommanderApiResponseCardDetails()
: synergy(0.0), inclusion(0), numDecks(0), potentialDecks(0)
{
}
void EdhrecCommanderApiResponseCardDetails::fromJson(const QJsonObject &json)
{
// Parse the fields from the JSON object
name = json.value("name").toString();
sanitized = json.value("sanitized").toString();
sanitizedWo = json.value("sanitized_wo").toString();
url = json.value("url").toString();
synergy = json.value("synergy").toDouble(0.0);
inclusion = json.value("inclusion").toInt(0);
label = json.value("label").toString();
numDecks = json.value("num_decks").toInt(0);
potentialDecks = json.value("potential_decks").toInt(0);
}
void EdhrecCommanderApiResponseCardDetails::debugPrint() const
{
// Print out all the fields for debugging
qDebug() << "Name:" << name;
qDebug() << "Sanitized:" << sanitized;
qDebug() << "Sanitized Wo:" << sanitizedWo;
qDebug() << "URL:" << url;
qDebug() << "Synergy:" << synergy;
qDebug() << "Inclusion:" << inclusion;
qDebug() << "Label:" << label;
qDebug() << "Num Decks:" << numDecks;
qDebug() << "Potential Decks:" << potentialDecks;
}

View file

@ -0,0 +1,29 @@
#ifndef CARD_VIEW_H
#define CARD_VIEW_H
#include <QJsonObject>
#include <QString>
class EdhrecCommanderApiResponseCardDetails
{
public:
QString name;
QString sanitized;
QString sanitizedWo;
QString url;
double synergy;
int inclusion;
QString label;
int numDecks;
int potentialDecks;
EdhrecCommanderApiResponseCardDetails();
// Method to populate the object from a JSON object
void fromJson(const QJsonObject &json);
// Debug method to print out the data
void debugPrint() const;
};
#endif // CARD_VIEW_H

View file

@ -0,0 +1,33 @@
#include "edhrec_commander_api_response_card_list.h"
#include <QDebug>
EdhrecCommanderApiResponseCardList::EdhrecCommanderApiResponseCardList()
{
}
void EdhrecCommanderApiResponseCardList::fromJson(const QJsonObject &json)
{
// Parse the header from the JSON object
header = json.value("header").toString();
// Parse the cardviews array and populate cardViews
QJsonArray cardviewsArray = json.value("cardviews").toArray();
for (const QJsonValue &value : cardviewsArray) {
QJsonObject cardviewObj = value.toObject();
EdhrecCommanderApiResponseCardDetails cardView;
cardView.fromJson(cardviewObj);
cardViews.append(cardView);
}
}
void EdhrecCommanderApiResponseCardList::debugPrint() const
{
// Print out the header
qDebug() << "Header:" << header;
// Print out all the CardView objects
for (const EdhrecCommanderApiResponseCardDetails &cardView : cardViews) {
cardView.debugPrint();
}
}

View file

@ -0,0 +1,27 @@
#ifndef CARD_LIST_H
#define CARD_LIST_H
#include "edhrec_commander_api_response_card_details.h"
#include <QJsonArray>
#include <QJsonObject>
#include <QList>
#include <QString>
class EdhrecCommanderApiResponseCardList
{
public:
QString header;
QList<EdhrecCommanderApiResponseCardDetails> cardViews;
// Default constructor
EdhrecCommanderApiResponseCardList();
// Method to populate the object from a JSON object
void fromJson(const QJsonObject &json);
// Debug method to print out the data
void debugPrint() const;
};
#endif // CARD_LIST_H

View file

@ -0,0 +1,31 @@
#include "edhrec_commander_api_response_card_prices.h"
#include <QDebug>
void CardPrices::fromJson(const QJsonObject &json)
{
// Parse prices from various sources
cardhoarder = json.value("cardhoarder").toObject();
cardkingdom = json.value("cardkingdom").toObject();
cardmarket = json.value("cardmarket").toObject();
face2face = json.value("face2face").toObject();
manapool = json.value("manapool").toObject();
mtgstocks = json.value("mtgstocks").toObject();
scg = json.value("scg").toObject();
tcgl = json.value("tcgl").toObject();
tcgplayer = json.value("tcgplayer").toObject();
}
void CardPrices::debugPrint() const
{
qDebug() << "Card Prices:";
qDebug() << "Cardhoarder:" << cardhoarder;
qDebug() << "Cardkingdom:" << cardkingdom;
qDebug() << "Cardmarket:" << cardmarket;
qDebug() << "Face2Face:" << face2face;
qDebug() << "Manapool:" << manapool;
qDebug() << "Mtgstocks:" << mtgstocks;
qDebug() << "SCG:" << scg;
qDebug() << "TCGL:" << tcgl;
qDebug() << "Tcgplayer:" << tcgplayer;
}

View file

@ -0,0 +1,66 @@
#ifndef EDHREC_COMMANDER_API_RESPONSE_CARD_PRICES_H
#define EDHREC_COMMANDER_API_RESPONSE_CARD_PRICES_H
#include <QJsonObject>
class CardPrices
{
public:
// Constructor
CardPrices() = default;
// Parse prices from JSON
void fromJson(const QJsonObject &json);
void debugPrint() const;
// Getter methods for card prices
const QJsonObject &getCardhoarder() const
{
return cardhoarder;
}
const QJsonObject &getCardkingdom() const
{
return cardkingdom;
}
const QJsonObject &getCardmarket() const
{
return cardmarket;
}
const QJsonObject &getFace2face() const
{
return face2face;
}
const QJsonObject &getManapool() const
{
return manapool;
}
const QJsonObject &getMtgstocks() const
{
return mtgstocks;
}
const QJsonObject &getScg() const
{
return scg;
}
const QJsonObject &getTcgl() const
{
return tcgl;
}
const QJsonObject &getTcgplayer() const
{
return tcgplayer;
}
private:
QJsonObject cardhoarder;
QJsonObject cardkingdom;
QJsonObject cardmarket;
QJsonObject face2face;
QJsonObject manapool;
QJsonObject mtgstocks;
QJsonObject scg;
QJsonObject tcgl;
QJsonObject tcgplayer;
};
#endif // EDHREC_COMMANDER_API_RESPONSE_CARD_PRICES_H

View file

@ -0,0 +1,90 @@
#include "edhrec_commander_api_response_commander_details.h"
#include <QDebug>
void EdhrecCommanderApiResponseCommanderDetails::fromJson(const QJsonObject &json)
{
// Parse card-related data
aetherhubUri = json.value("aetherhub_uri").toString();
archidektUri = json.value("archidekt_uri").toString();
cmc = json.value("cmc").toInt(0);
colorIdentity = json.value("color_identity").toArray();
combos = json.value("combos").toBool(false);
deckstatsUri = json.value("deckstats_uri").toString();
// Parse image URIs
QJsonArray imageUrisArray = json.value("image_uris").toArray();
for (const QJsonValue &imageValue : imageUrisArray) {
QJsonObject imageObject = imageValue.toObject();
imageUris.push_back(imageObject.value("normal").toString());
imageUris.push_back(imageObject.value("art_crop").toString());
}
inclusion = json.value("inclusion").toInt(0);
isCommander = json.value("is_commander").toBool(false);
label = json.value("label").toString();
layout = json.value("layout").toString();
legalCommander = json.value("legal_commander").toBool(false);
moxfieldUri = json.value("moxfield_uri").toString();
mtggoldfishUri = json.value("mtggoldfish_uri").toString();
name = json.value("name").toString();
names = json.value("names").toArray();
numDecks = json.value("num_decks").toInt(0);
potentialDecks = json.value("potential_decks").toInt(0);
precon = json.value("precon").toString();
// Parse prices
prices.fromJson(json.value("prices").toObject());
primaryType = json.value("primary_type").toString();
rarity = json.value("rarity").toString();
salt = json.value("salt").toDouble(0.0);
sanitized = json.value("sanitized").toString();
sanitizedWo = json.value("sanitized_wo").toString();
scryfallUri = json.value("scryfall_uri").toString();
spellbookUri = json.value("spellbook_uri").toString();
type = json.value("type").toString();
url = json.value("url").toString();
}
void EdhrecCommanderApiResponseCommanderDetails::debugPrint() const
{
qDebug() << "Card Data:";
qDebug() << "Aetherhub URI:" << aetherhubUri;
qDebug() << "Archidekt URI:" << archidektUri;
qDebug() << "CMC:" << cmc;
qDebug() << "Color Identity:" << colorIdentity;
qDebug() << "Combos:" << combos;
qDebug() << "Deckstats URI:" << deckstatsUri;
qDebug() << "Image URIs:";
for (const auto &uri : imageUris) {
qDebug() << uri;
}
qDebug() << "Inclusion:" << inclusion;
qDebug() << "Is Commander:" << isCommander;
qDebug() << "Label:" << label;
qDebug() << "Layout:" << layout;
qDebug() << "Legal Commander:" << legalCommander;
qDebug() << "Moxfield URI:" << moxfieldUri;
qDebug() << "MTGGoldfish URI:" << mtggoldfishUri;
qDebug() << "Name:" << name;
qDebug() << "Names:" << names;
qDebug() << "Number of Decks:" << numDecks;
qDebug() << "Potential Decks:" << potentialDecks;
qDebug() << "Precon:" << precon;
// Print the prices using the debugPrint method from CardPrices
prices.debugPrint();
qDebug() << "Primary Type:" << primaryType;
qDebug() << "Rarity:" << rarity;
qDebug() << "Salt:" << salt;
qDebug() << "Sanitized:" << sanitized;
qDebug() << "Sanitized WO:" << sanitizedWo;
qDebug() << "Scryfall URI:" << scryfallUri;
qDebug() << "Spellbook URI:" << spellbookUri;
qDebug() << "Type:" << type;
qDebug() << "URL:" << url;
}

View file

@ -0,0 +1,173 @@
#ifndef EDHREC_COMMANDER_API_RESPONSE_COMMANDER_DETAILS_H
#define EDHREC_COMMANDER_API_RESPONSE_COMMANDER_DETAILS_H
#include "edhrec_commander_api_response_card_prices.h"
#include <QJsonArray>
#include <QJsonObject>
#include <QString>
#include <QVector>
class EdhrecCommanderApiResponseCommanderDetails
{
public:
// Constructor
EdhrecCommanderApiResponseCommanderDetails() = default;
// Parse card-related data from JSON
void fromJson(const QJsonObject &json);
// Debug method for logging
void debugPrint() const;
// Getters for the card data
const QString &getAetherhubUri() const
{
return aetherhubUri;
}
const QString &getArchidektUri() const
{
return archidektUri;
}
int getCmc() const
{
return cmc;
}
const QJsonArray &getColorIdentity() const
{
return colorIdentity;
}
bool isCombos() const
{
return combos;
}
const QString &getDeckstatsUri() const
{
return deckstatsUri;
}
const QVector<QString> &getImageUris() const
{
return imageUris;
}
int getInclusion() const
{
return inclusion;
}
bool getIsCommander() const
{
return isCommander;
}
const QString &getLabel() const
{
return label;
}
const QString &getLayout() const
{
return layout;
}
bool getLegalCommander() const
{
return legalCommander;
}
const QString &getMoxfieldUri() const
{
return moxfieldUri;
}
const QString &getMtggoldfishUri() const
{
return mtggoldfishUri;
}
const QString &getName() const
{
return name;
}
const QJsonArray &getNames() const
{
return names;
}
int getNumDecks() const
{
return numDecks;
}
int getPotentialDecks() const
{
return potentialDecks;
}
const QString &getPrecon() const
{
return precon;
}
const CardPrices &getPrices() const
{
return prices;
}
const QString &getPrimaryType() const
{
return primaryType;
}
const QString &getRarity() const
{
return rarity;
}
double getSalt() const
{
return salt;
}
const QString &getSanitized() const
{
return sanitized;
}
const QString &getSanitizedWo() const
{
return sanitizedWo;
}
const QString &getScryfallUri() const
{
return scryfallUri;
}
const QString &getSpellbookUri() const
{
return spellbookUri;
}
const QString &getType() const
{
return type;
}
const QString &getUrl() const
{
return url;
}
private:
QString aetherhubUri;
QString archidektUri;
int cmc = 0;
QJsonArray colorIdentity;
bool combos = false;
QString deckstatsUri;
QVector<QString> imageUris;
int inclusion = 0;
bool isCommander = false;
QString label;
QString layout;
bool legalCommander = false;
QString moxfieldUri;
QString mtggoldfishUri;
QString name;
QJsonArray names;
int numDecks = 0;
int potentialDecks = 0;
QString precon;
CardPrices prices;
QString primaryType;
QString rarity;
double salt = 0.0;
QString sanitized;
QString sanitizedWo;
QString scryfallUri;
QString spellbookUri;
QString type;
QString url;
};
#endif // EDHREC_COMMANDER_API_RESPONSE_COMMANDER_DETAILS_H

View file

@ -0,0 +1,41 @@
#include "edhrec_commander_api_response_card_details_display_widget.h"
#include "../../../../game/cards/card_database_manager.h"
EdhrecCommanderApiResponseCardDetailsDisplayWidget::EdhrecCommanderApiResponseCardDetailsDisplayWidget(
QWidget *parent,
const EdhrecCommanderApiResponseCardDetails &_toDisplay)
: QWidget(parent), toDisplay(_toDisplay)
{
layout = new QVBoxLayout(this);
setLayout(layout);
cardPictureWidget = new CardInfoPictureWidget(this);
cardPictureWidget->setCard(CardDatabaseManager::getInstance()->getCard(toDisplay.name));
label = new QLabel(this);
label->setText(toDisplay.name + "\n" + toDisplay.label);
label->setAlignment(Qt::AlignHCenter);
// Set label color based on inclusion rate
int inclusionRate = (toDisplay.numDecks * 100) / toDisplay.potentialDecks;
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()));
layout->addWidget(cardPictureWidget);
layout->addWidget(label);
}

View file

@ -0,0 +1,26 @@
#ifndef EDHREC_COMMANDER_API_RESPONSE_CARD_DETAILS_DISPLAY_WIDGET_H
#define EDHREC_COMMANDER_API_RESPONSE_CARD_DETAILS_DISPLAY_WIDGET_H
#include "../../../ui/widgets/cards/card_info_picture_widget.h"
#include "api_response/edhrec_commander_api_response_card_details.h"
#include <QHBoxLayout>
#include <QLabel>
#include <QWidget>
class EdhrecCommanderApiResponseCardDetailsDisplayWidget : public QWidget
{
Q_OBJECT
public:
explicit EdhrecCommanderApiResponseCardDetailsDisplayWidget(
QWidget *parent,
const EdhrecCommanderApiResponseCardDetails &_toDisplay);
private:
EdhrecCommanderApiResponseCardDetails toDisplay;
QVBoxLayout *layout;
CardInfoPictureWidget *cardPictureWidget;
QLabel *label;
};
#endif // EDHREC_COMMANDER_API_RESPONSE_CARD_DETAILS_DISPLAY_WIDGET_H

View file

@ -0,0 +1,34 @@
#include "edhrec_commander_api_response_card_list_display_widget.h"
#include "../../../ui/widgets/general/display/banner_widget.h"
#include "edhrec_commander_api_response_card_details_display_widget.h"
#include <QLabel>
EdhrecCommanderApiResponseCardListDisplayWidget::EdhrecCommanderApiResponseCardListDisplayWidget(
QWidget *parent,
EdhrecCommanderApiResponseCardList toDisplay)
: QWidget(parent)
{
layout = new QVBoxLayout(this);
setLayout(layout);
header = new BannerWidget(this, toDisplay.header);
flowWidget = new FlowWidget(this, Qt::Horizontal, Qt::ScrollBarAlwaysOff, Qt::ScrollBarAlwaysOff);
header->setBuddy(flowWidget);
foreach (EdhrecCommanderApiResponseCardDetails card_detail, toDisplay.cardViews) {
auto widget = new EdhrecCommanderApiResponseCardDetailsDisplayWidget(flowWidget, card_detail);
flowWidget->addWidget(widget);
}
layout->addWidget(header);
layout->addWidget(flowWidget);
}
void EdhrecCommanderApiResponseCardListDisplayWidget::resizeEvent(QResizeEvent *event)
{
QWidget::resizeEvent(event);
qDebug() << event->size();
}

View file

@ -0,0 +1,30 @@
#ifndef EDHREC_COMMANDER_API_RESPONSE_CARD_LIST_DISPLAY_WIDGET_H
#define EDHREC_COMMANDER_API_RESPONSE_CARD_LIST_DISPLAY_WIDGET_H
#include "../../../ui/widgets/general/display/banner_widget.h"
#include "../../../ui/widgets/general/layout_containers/flow_widget.h"
#include "api_response/edhrec_commander_api_response_card_list.h"
#include <QResizeEvent>
#include <QVBoxLayout>
#include <QWidget>
class EdhrecCommanderApiResponseCardListDisplayWidget : public QWidget
{
Q_OBJECT
public:
explicit EdhrecCommanderApiResponseCardListDisplayWidget(QWidget *parent,
EdhrecCommanderApiResponseCardList toDisplay);
void resizeEvent(QResizeEvent *event) override;
[[nodiscard]] QString getBannerText() const
{
return header->getText();
};
private:
QVBoxLayout *layout;
BannerWidget *header;
FlowWidget *flowWidget;
};
#endif // EDHREC_COMMANDER_API_RESPONSE_CARD_LIST_DISPLAY_WIDGET_H

View file

@ -0,0 +1,36 @@
#include "edhrec_commander_api_response_commander_details_display_widget.h"
#include "../../../../game/cards/card_database_manager.h"
#include "../../../ui/widgets/cards/card_info_picture_widget.h"
#include <QLabel>
EdhrecCommanderResponseCommanderDetailsDisplayWidget::EdhrecCommanderResponseCommanderDetailsDisplayWidget(
QWidget *parent,
const EdhrecCommanderApiResponseCommanderDetails &_commanderDetails)
: QWidget(parent), commanderDetails(_commanderDetails)
{
layout = new QVBoxLayout(this);
setLayout(layout);
commanderPicture = new CardInfoPictureWidget(this);
commanderPicture->setCard(CardDatabaseManager::getInstance()->getCard(commanderDetails.getName()));
commanderDetails.debugPrint();
label = new QLabel(this);
label->setAlignment(Qt::AlignCenter);
salt = new QLabel(this);
salt->setAlignment(Qt::AlignCenter);
layout->addWidget(commanderPicture);
layout->addWidget(label);
layout->addWidget(salt);
retranslateUi();
}
void EdhrecCommanderResponseCommanderDetailsDisplayWidget::retranslateUi()
{
label->setText(commanderDetails.getLabel());
salt->setText(tr("Salt: ") + QString::number(commanderDetails.getSalt()));
}

View file

@ -0,0 +1,28 @@
#ifndef EDHREC_COMMANDER_API_RESPONSE_COMMANDER_DETAILS_DISPLAY_WIDGET_H
#define EDHREC_COMMANDER_API_RESPONSE_COMMANDER_DETAILS_DISPLAY_WIDGET_H
#include "../../../ui/widgets/cards/card_info_picture_widget.h"
#include "api_response/edhrec_commander_api_response_commander_details.h"
#include <QLabel>
#include <QVBoxLayout>
#include <QWidget>
class EdhrecCommanderResponseCommanderDetailsDisplayWidget : public QWidget
{
Q_OBJECT
public:
explicit EdhrecCommanderResponseCommanderDetailsDisplayWidget(
QWidget *parent,
const EdhrecCommanderApiResponseCommanderDetails &_commanderDetails);
void retranslateUi();
private:
QLabel *label;
QLabel *salt;
QVBoxLayout *layout;
CardInfoPictureWidget *commanderPicture;
EdhrecCommanderApiResponseCommanderDetails commanderDetails;
};
#endif // EDHREC_COMMANDER_API_RESPONSE_COMMANDER_DETAILS_DISPLAY_WIDGET_H

View file

@ -0,0 +1,102 @@
#include "edhrec_commander_api_response_display_widget.h"
#include "../../../ui/widgets/cards/card_info_picture_widget.h"
#include "api_response/edhrec_commander_api_response.h"
#include "edhrec_commander_api_response_card_list_display_widget.h"
#include "edhrec_commander_api_response_commander_details_display_widget.h"
#include <QListView>
#include <QResizeEvent>
#include <QScrollArea>
#include <QSplitter>
#include <QStringListModel>
EdhrecCommanderApiResponseDisplayWidget::EdhrecCommanderApiResponseDisplayWidget(QWidget *parent,
EdhrecCommanderApiResponse response)
: QWidget(parent)
{
layout = new QHBoxLayout(this);
setLayout(layout);
cardDisplayLayout = new QVBoxLayout(this);
// Create a QSplitter to hold the ListView and ScrollArea holding CardListdisplayWidgets side by side
auto splitter = new QSplitter(this);
splitter->setOrientation(Qt::Horizontal);
auto listView = new QListView(splitter);
listView->setMinimumWidth(50);
listView->setMaximumWidth(150);
auto listModel = new QStringListModel(this);
QStringList widgetNames;
// Add commander details
auto commanderPicture =
new EdhrecCommanderResponseCommanderDetailsDisplayWidget(this, response.container.getCommanderDetails());
cardDisplayLayout->addWidget(commanderPicture);
widgetNames.append("Commander Details");
// Add card list widgets
auto edhrec_commander_api_response_card_lists = response.container.getCardlists();
for (const EdhrecCommanderApiResponseCardList &card_list : edhrec_commander_api_response_card_lists) {
auto cardListDisplayWidget = new EdhrecCommanderApiResponseCardListDisplayWidget(this, card_list);
cardDisplayLayout->addWidget(cardListDisplayWidget);
widgetNames.append(cardListDisplayWidget->getBannerText());
}
// Create a QScrollArea to hold the card display widgets
scrollArea = new QScrollArea(splitter);
scrollArea->setWidgetResizable(true);
scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
// Set the cardDisplayLayout inside the scroll area
auto scrollWidget = new QWidget(scrollArea);
scrollWidget->setLayout(cardDisplayLayout);
connect(splitter, &QSplitter::splitterMoved, this, &EdhrecCommanderApiResponseDisplayWidget::onSplitterChange);
scrollArea->setWidget(scrollWidget);
// Configure the list view
listModel->setStringList(widgetNames);
listView->setModel(listModel);
listView->setEditTriggers(QAbstractItemView::NoEditTriggers);
// Connect the list view to ensure the corresponding widget is visible
connect(listView, &QListView::clicked, this, [this](const QModelIndex &index) {
int widgetIndex = index.row();
qDebug() << "clicked: " << widgetIndex;
auto targetWidget = cardDisplayLayout->itemAt(widgetIndex)->widget();
if (targetWidget) {
qDebug() << "Found targetWidget" << targetWidget;
// Attempt to cast the parent to QScrollArea
auto scrollArea = qobject_cast<QScrollArea *>(this->scrollArea); // Use the scroll area instance
if (scrollArea) {
qDebug() << "ScrollArea" << scrollArea;
scrollArea->ensureWidgetVisible(targetWidget);
}
}
});
// Add splitter to the main layout
splitter->addWidget(listView);
splitter->addWidget(scrollArea);
layout->addWidget(splitter);
}
void EdhrecCommanderApiResponseDisplayWidget::onSplitterChange()
{
scrollArea->widget()->resize(scrollArea->size());
}
void EdhrecCommanderApiResponseDisplayWidget::resizeEvent(QResizeEvent *event)
{
QWidget::resizeEvent(event);
qDebug() << event->size();
layout->invalidate();
layout->activate();
layout->update();
if (scrollArea && scrollArea->widget()) {
scrollArea->widget()->resize(event->size());
}
}

View file

@ -0,0 +1,27 @@
#ifndef EDHREC_COMMANDER_API_RESPONSE_DISPLAY_WIDGET_H
#define EDHREC_COMMANDER_API_RESPONSE_DISPLAY_WIDGET_H
#include "api_response/edhrec_commander_api_response.h"
#include <QScrollArea>
#include <QVBoxLayout>
#include <QWidget>
class EdhrecCommanderApiResponseDisplayWidget : public QWidget
{
Q_OBJECT
public:
explicit EdhrecCommanderApiResponseDisplayWidget(QWidget *parent, EdhrecCommanderApiResponse response);
void resizeEvent(QResizeEvent *event) override;
public slots:
void onSplitterChange();
private:
QHBoxLayout *layout;
QVBoxLayout *cardDisplayLayout;
QScrollArea *scrollArea;
};
#endif // EDHREC_COMMANDER_API_RESPONSE_DISPLAY_WIDGET_H

View file

@ -0,0 +1,112 @@
#include "tab_edhrec.h"
#include "api_response/edhrec_commander_api_response.h"
#include "edhrec_commander_api_response_display_widget.h"
#include <QDebug>
#include <QHBoxLayout>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QRegularExpression>
#include <QResizeEvent>
TabEdhRec::TabEdhRec(TabSupervisor *_tabSupervisor) : Tab(_tabSupervisor)
{
networkManager = new QNetworkAccessManager(this);
#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
networkManager->setTransferTimeout(); // Use Qt's default timeout
#endif
networkManager->setRedirectPolicy(QNetworkRequest::ManualRedirectPolicy);
connect(networkManager, SIGNAL(finished(QNetworkReply *)), this, SLOT(processApiJson(QNetworkReply *)));
}
void TabEdhRec::retranslateUi()
{
}
void TabEdhRec::setCard(CardInfoPtr _cardToQuery, bool isCommander)
{
cardToQuery = _cardToQuery;
if (!cardToQuery) {
qDebug() << "Invalid card information provided.";
return;
}
QString cardName = cardToQuery->getName();
QString formattedName = cardName.toLower().replace(" ", "-").remove(QRegularExpression("[^a-z0-9\\-]"));
QString url;
if (isCommander) {
url = QString("https://json.edhrec.com/pages/commanders/%1.json").arg(formattedName);
} else {
url = QString("https://json.edhrec.com/pages/cards/%1.json").arg(formattedName);
}
QNetworkRequest request{QUrl(url)};
networkManager->get(request);
}
void TabEdhRec::processApiJson(QNetworkReply *reply)
{
if (reply->error() != QNetworkReply::NoError) {
qDebug() << "Network error occurred:" << reply->errorString();
reply->deleteLater();
return;
}
QByteArray responseData = reply->readAll();
QJsonDocument jsonDoc = QJsonDocument::fromJson(responseData);
if (!jsonDoc.isObject()) {
qDebug() << "Invalid JSON response received.";
reply->deleteLater();
return;
}
QJsonObject jsonObj = jsonDoc.object();
// qDebug() << jsonObj;
EdhrecCommanderApiResponse deckData;
deckData.fromJson(jsonObj);
displayWidget = new EdhrecCommanderApiResponseDisplayWidget(this, deckData);
// flowWidget->addWidget(displayWidget);
setCentralWidget(displayWidget);
reply->deleteLater();
update();
}
void TabEdhRec::prettyPrintJson(const QJsonValue &value, int indentLevel)
{
const QString indent(indentLevel * 2, ' '); // Adjust spacing as needed for pretty printing
if (value.isObject()) {
QJsonObject obj = value.toObject();
for (auto it = obj.begin(); it != obj.end(); ++it) {
qDebug().noquote() << indent + it.key() + ":";
prettyPrintJson(it.value(), indentLevel + 1);
}
} else if (value.isArray()) {
QJsonArray array = value.toArray();
for (int i = 0; i < array.size(); ++i) {
qDebug().noquote() << indent + QString("[%1]:").arg(i);
prettyPrintJson(array[i], indentLevel + 1);
}
} else if (value.isString()) {
qDebug().noquote() << indent + "\"" + value.toString() + "\"";
} else if (value.isDouble()) {
qDebug().noquote() << indent + QString::number(value.toDouble());
} else if (value.isBool()) {
qDebug().noquote() << indent + (value.toBool() ? "true" : "false");
} else if (value.isNull()) {
qDebug().noquote() << indent + "null";
}
}

View file

@ -0,0 +1,37 @@
#ifndef TAB_EDHREC_H
#define TAB_EDHREC_H
#include "../../../../game/cards/card_database.h"
#include "../../../ui/widgets/general/layout_containers/flow_widget.h"
#include "../../tab.h"
#include "edhrec_commander_api_response_display_widget.h"
#include <QHBoxLayout>
#include <QNetworkAccessManager>
class TabEdhRec : public Tab
{
Q_OBJECT
public:
explicit TabEdhRec(TabSupervisor *_tabSupervisor);
void retranslateUi() override;
QString getTabText() const override
{
auto cardName = cardToQuery.isNull() ? QString() : cardToQuery->getName();
return tr("EDHREC: ") + cardName;
}
QNetworkAccessManager *networkManager;
public slots:
void processApiJson(QNetworkReply *reply);
void prettyPrintJson(const QJsonValue &value, int indentLevel);
void setCard(CardInfoPtr _cardToQuery, bool isCommander = false);
private:
CardInfoPtr cardToQuery;
EdhrecCommanderApiResponseDisplayWidget *displayWidget;
};
#endif // TAB_EDHREC_H

View file

@ -51,6 +51,13 @@
#include <QUrl>
#include <QVBoxLayout>
static bool canBeCommander(const CardInfoPtr &cardInfo)
{
return ((cardInfo->getCardType().contains("Legendary", Qt::CaseInsensitive) &&
cardInfo->getCardType().contains("Creature", Qt::CaseInsensitive))) ||
cardInfo->getText().contains("can be your commander", Qt::CaseInsensitive);
}
void TabDeckEditor::createDeckDock()
{
deckModel = new DeckListModel(this);
@ -540,31 +547,40 @@ void TabDeckEditor::databaseCustomMenu(QPoint point)
QMenu menu;
const CardInfoPtr info = currentCardInfo();
// add to deck and sideboard options
QAction *addToDeck, *addToSideboard, *selectPrinting;
addToDeck = menu.addAction(tr("Add to Deck"));
addToSideboard = menu.addAction(tr("Add to Sideboard"));
selectPrinting = menu.addAction(tr("Select Printing"));
connect(addToDeck, SIGNAL(triggered()), this, SLOT(actAddCard()));
connect(addToSideboard, SIGNAL(triggered()), this, SLOT(actAddCardToSideboard()));
connect(selectPrinting, &QAction::triggered, this, [this, info] { this->showPrintingSelector(); });
// filling out the related cards submenu
auto *relatedMenu = new QMenu(tr("Show Related cards"));
menu.addMenu(relatedMenu);
auto relatedCards = info->getAllRelatedCards();
if (relatedCards.isEmpty()) {
relatedMenu->setDisabled(true);
} else {
for (const CardRelation *rel : relatedCards) {
const QString &relatedCardName = rel->getName();
QAction *relatedCard = relatedMenu->addAction(relatedCardName);
connect(relatedCard, &QAction::triggered, cardInfo,
[this, relatedCardName] { cardInfo->setCard(relatedCardName); });
if (info) {
// add to deck and sideboard options
QAction *addToDeck, *addToSideboard, *selectPrinting, *edhRecCommander, *edhRecCard;
addToDeck = menu.addAction(tr("Add to Deck"));
addToSideboard = menu.addAction(tr("Add to Sideboard"));
selectPrinting = menu.addAction(tr("Select Printing"));
if (canBeCommander(info)) {
edhRecCommander = menu.addAction(tr("Show on EDHREC (Commander)"));
connect(edhRecCommander, &QAction::triggered, this,
[this, info] { this->tabSupervisor->addEdhrecTab(info, true); });
}
edhRecCard = menu.addAction(tr("Show on EDHREC (Card)"));
connect(addToDeck, SIGNAL(triggered()), this, SLOT(actAddCard()));
connect(addToSideboard, SIGNAL(triggered()), this, SLOT(actAddCardToSideboard()));
connect(selectPrinting, &QAction::triggered, this, [this, info] { this->showPrintingSelector(); });
connect(edhRecCard, &QAction::triggered, this, [this, info] { this->tabSupervisor->addEdhrecTab(info); });
// filling out the related cards submenu
auto *relatedMenu = new QMenu(tr("Show Related cards"));
menu.addMenu(relatedMenu);
auto relatedCards = info->getAllRelatedCards();
if (relatedCards.isEmpty()) {
relatedMenu->setDisabled(true);
} else {
for (const CardRelation *rel : relatedCards) {
const QString &relatedCardName = rel->getName();
QAction *relatedCard = relatedMenu->addAction(relatedCardName);
connect(relatedCard, &QAction::triggered, cardInfo,
[this, relatedCardName] { cardInfo->setCard(relatedCardName); });
}
}
menu.exec(databaseView->mapToGlobal(point));
}
menu.exec(databaseView->mapToGlobal(point));
}
void TabDeckEditor::decklistCustomMenu(QPoint point)
@ -1383,9 +1399,8 @@ QModelIndexList TabDeckEditor::getSelectedCardNodes() const
return selectedRows;
}
void TabDeckEditor::addCardHelper(QString zoneName)
void TabDeckEditor::addCardHelper(const CardInfoPtr info, QString zoneName)
{
const CardInfoPtr info = currentCardInfo();
if (!info)
return;
if (info->getIsToken())
@ -1461,13 +1476,13 @@ void TabDeckEditor::actAddCard()
if (QApplication::keyboardModifiers() & Qt::ControlModifier)
actAddCardToSideboard();
else
addCardHelper(DECK_ZONE_MAIN);
addCardHelper(currentCardInfo(), DECK_ZONE_MAIN);
setSaveStatus(true);
}
void TabDeckEditor::actAddCardToSideboard()
{
addCardHelper(DECK_ZONE_SIDE);
addCardHelper(currentCardInfo(), DECK_ZONE_SIDE);
setSaveStatus(true);
}

View file

@ -110,7 +110,6 @@ private:
bool isBlankNewDeck() const;
CardInfoPtr currentCardInfo() const;
void addCardHelper(QString zoneName);
void offsetCountAtIndex(const QModelIndex &idx, int offset);
void decrementCardHelper(QString zoneName);
bool swapCard(const QModelIndex &idx);
@ -179,6 +178,7 @@ public:
void createMenus();
void createCentralFrame();
void updateCardInfo(CardInfoPtr _card);
void addCardHelper(CardInfoPtr info, QString zoneName);
public slots:
void closeRequest(bool forced = false) override;

View file

@ -707,6 +707,18 @@ TabDeckEditor *TabSupervisor::addDeckEditorTab(const DeckLoader *deckToOpen)
return tab;
}
TabEdhRec *TabSupervisor::addEdhrecTab(const CardInfoPtr &cardToQuery, bool isCommander)
{
auto *tab = new TabEdhRec(this);
if (cardToQuery) {
tab->setCard(cardToQuery, isCommander);
}
myAddTab(tab);
setCurrentWidget(tab);
return tab;
}
void TabSupervisor::deckEditorClosed(TabDeckEditor *tab)
{
if (tab == currentWidget())

View file

@ -3,6 +3,7 @@
#include "../../deck/deck_loader.h"
#include "../../server/user/user_list_proxy.h"
#include "api/edhrec/tab_edhrec.h"
#include "visual_deck_storage/tab_deck_storage_visual.h"
#include <QAbstractButton>
@ -131,6 +132,10 @@ public:
{
return roomTabs;
}
QList<TabDeckEditor *> getDeckEditorTabs() const
{
return deckEditorTabs;
}
bool getAdminLocked() const;
bool closeRequest();
bool switchToGameTabIfAlreadyExists(const int gameId);
@ -143,6 +148,7 @@ signals:
public slots:
TabDeckEditor *addDeckEditorTab(const DeckLoader *deckToOpen);
TabEdhRec *addEdhrecTab(const CardInfoPtr &cardToQuery, bool isCommander = false);
void openReplay(GameReplay *replay);
void maximizeMainWindow();
private slots:

View file

@ -151,6 +151,9 @@ void CardInfoFrameWidget::setCard(CardInfoPtr card)
disconnect(info.data(), nullptr, this, nullptr);
}
if (viewTransformationButton) {
viewTransformationButton->setVisible(false);
}
info = std::move(card);
if (info) {

View file

@ -3,7 +3,10 @@
#include "../../../../game/cards/card_database_manager.h"
#include "../../../../game/cards/card_item.h"
#include "../../../../settings/cache_settings.h"
#include "../../../tabs/tab_deck_editor.h"
#include "../../../tabs/tab_supervisor.h"
#include "../../picture_loader/picture_loader.h"
#include "../../window_main.h"
#include <QMenu>
#include <QMouseEvent>
@ -254,7 +257,31 @@ QMenu *CardInfoPictureWidget::createRightClickMenu()
}
auto viewRelatedCards = new QMenu(tr("View related cards"));
auto addToOpenDeckMenu = new QMenu(tr("Add card to deck"));
cardMenu->addMenu(viewRelatedCards);
cardMenu->addMenu(addToOpenDeckMenu);
auto *mainWindow = qobject_cast<MainWindow *>(window());
QList<TabDeckEditor *> deckEditorTabs = mainWindow->getTabSupervisor()->getDeckEditorTabs();
for (auto &deckEditorTab : deckEditorTabs) {
auto *addCardMenu = new QMenu(tr("Add card to") + " " + deckEditorTab->getTabText());
QAction *addCard = new QAction(this);
addCard->setText(tr("Mainboard"));
connect(addCard, &QAction::triggered, this, [this, deckEditorTab] {
deckEditorTab->updateCardInfo(info);
deckEditorTab->addCardHelper(info, DECK_ZONE_MAIN);
});
QAction *addCardSideboard = new QAction(this);
addCardSideboard->setText(tr("Sideboard"));
connect(addCardSideboard, &QAction::triggered, this, [this, deckEditorTab] {
deckEditorTab->updateCardInfo(info);
deckEditorTab->addCardHelper(info, DECK_ZONE_SIDE);
});
addCardMenu->addAction(addCard);
addCardMenu->addAction(addCardSideboard);
addToOpenDeckMenu->addMenu(addCardMenu);
}
bool atLeastOneGoodRelationFound = false;
QList<CardRelation *> relatedCards = info->getAllRelatedCards();

View file

@ -0,0 +1,63 @@
#include "banner_widget.h"
#include <QLinearGradient>
#include <QMouseEvent>
#include <QPainter>
#include <QVBoxLayout>
BannerWidget::BannerWidget(QWidget *parent, const QString &text, Qt::Orientation orientation, int transparency)
: QWidget(parent), gradientOrientation(orientation), transparency(qBound(0, transparency, 100))
{
// Create the banner label and set properties
bannerLabel = new QLabel(text, this);
bannerLabel->setAlignment(Qt::AlignCenter);
bannerLabel->setStyleSheet("font-size: 24px; font-weight: bold; color: white;");
// Layout to center the banner label
QVBoxLayout *layout = new QVBoxLayout(this);
layout->addWidget(bannerLabel);
layout->setContentsMargins(0, 20, 0, 20); // Space for the gradient
setLayout(layout);
// Set minimum height for the widget
setMinimumHeight(100);
connect(this, &BannerWidget::buddyVisibilityChanged, this, &BannerWidget::toggleBuddyVisibility);
}
void BannerWidget::mousePressEvent(QMouseEvent *event)
{
QWidget::mousePressEvent(event);
emit buddyVisibilityChanged();
}
void BannerWidget::toggleBuddyVisibility() const
{
if (buddy) {
buddy->setVisible(!buddy->isVisible());
}
}
void BannerWidget::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);
QPainter painter(this);
// Calculate alpha based on transparency percentage
int alpha = (255 * transparency) / 100;
// Determine gradient direction
QLinearGradient gradient;
if (gradientOrientation == Qt::Vertical) {
gradient = QLinearGradient(rect().topLeft(), rect().bottomLeft());
} else {
gradient = QLinearGradient(rect().topLeft(), rect().topRight());
}
// Set neutral gradient colors with calculated transparency
gradient.setColorAt(0, QColor(200, 200, 200, alpha)); // Light grey with alpha
gradient.setColorAt(1, QColor(100, 100, 100, alpha / 1.5)); // Darker grey, slightly more transparent
// Fill the widget background with the gradient
painter.fillRect(rect(), gradient);
}

View file

@ -0,0 +1,40 @@
#ifndef BANNER_WIDGET_H
#define BANNER_WIDGET_H
#include <QLabel>
#include <QWidget>
class BannerWidget : public QWidget
{
Q_OBJECT
public:
explicit BannerWidget(QWidget *parent,
const QString &text,
Qt::Orientation orientation = Qt::Vertical,
int transparency = 80);
void mousePressEvent(QMouseEvent *event) override;
void setBuddy(QWidget *_buddy)
{
buddy = _buddy;
}
QString getText() const
{
return bannerLabel->text();
}
protected:
void paintEvent(QPaintEvent *event) override;
private:
QLabel *bannerLabel;
Qt::Orientation gradientOrientation;
int transparency; // Transparency percentage for the gradient
QWidget *buddy;
signals:
void buddyVisibilityChanged();
private slots:
void toggleBuddyVisibility() const;
};
#endif // BANNER_WIDGET_H

View file

@ -123,6 +123,8 @@ void FlowWidget::resizeEvent(QResizeEvent *event)
{
QWidget::resizeEvent(event);
qCDebug(FlowWidgetSizeLog) << event->size();
// Trigger the layout to recalculate
if (flowLayout != nullptr) {
flowLayout->invalidate(); // Marks the layout as dirty and requires recalculation
@ -131,6 +133,7 @@ void FlowWidget::resizeEvent(QResizeEvent *event)
// Ensure the scroll area and its content adjust correctly
if (scrollArea != nullptr && scrollArea->widget() != nullptr) {
qCDebug(FlowWidgetSizeLog) << "Got a scrollarea: " << scrollArea->widget()->size();
scrollArea->widget()->adjustSize();
} else {
container->adjustSize();

View file

@ -163,6 +163,11 @@ public:
}
~MainWindow() override;
TabSupervisor *getTabSupervisor() const
{
return tabSupervisor;
}
protected:
void closeEvent(QCloseEvent *event) override;
void changeEvent(QEvent *event) override;