mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2025-12-21 14:50:26 -08:00
Compare commits
1 Commits
2024-12-20
...
2024-12-20
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
91d2485940 |
@@ -81,9 +81,9 @@ if(NOT DEFINED GIT_TAG_RELEASENAME)
|
||||
set(GIT_TAG_RELEASENAME "Rings of the Wild")
|
||||
endif()
|
||||
|
||||
# Use c++17 for all targets
|
||||
# Use c++20 for all targets
|
||||
set(CMAKE_CXX_STANDARD
|
||||
17
|
||||
20
|
||||
CACHE STRING "C++ ISO Standard"
|
||||
)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||
@@ -140,8 +140,8 @@ endif()
|
||||
|
||||
# Define proper compilation flags
|
||||
if(MSVC)
|
||||
# Visual Studio: Disable Warning C4251, C++17 compatibility, Multi-threaded Builds, Warn Detection, Unwind Semantics
|
||||
set(CMAKE_CXX_FLAGS "/wd4251 /Zc:__cplusplus /std:c++17 /permissive- /W4 /MP /EHsc")
|
||||
# Visual Studio: Disable Warning C4251, C++20 compatibility, Multi-threaded Builds, Warn Detection, Unwind Semantics
|
||||
set(CMAKE_CXX_FLAGS "/wd4251 /Zc:__cplusplus /std:c++20 /permissive- /W4 /MP /EHsc")
|
||||
# Visual Studio: Maximum Optimization, Multi-threaded DLL
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "/Ox /MD")
|
||||
# Visual Studio: No Optimization, Multi-threaded Debug DLL, Debug Symbols
|
||||
@@ -158,7 +158,7 @@ elseif(CMAKE_COMPILER_IS_GNUCXX)
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++17")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++20")
|
||||
endif()
|
||||
|
||||
set(ADDITIONAL_DEBUG_FLAGS
|
||||
|
||||
@@ -1535,6 +1535,6 @@ void TabDeckEditor::showSearchSyntaxHelp()
|
||||
browser->document()->setDefaultStyleSheet(sheet);
|
||||
|
||||
browser->setHtml(text);
|
||||
connect(browser, &QTextBrowser::anchorClicked, [=](const QUrl &link) { searchEdit->setText(link.fragment()); });
|
||||
connect(browser, &QTextBrowser::anchorClicked, [this](const QUrl &link) { searchEdit->setText(link.fragment()); });
|
||||
browser->show();
|
||||
}
|
||||
|
||||
@@ -1742,22 +1742,22 @@ void TabGame::createReplayDock()
|
||||
aReplaySkipForward = new QAction(timelineWidget);
|
||||
timelineWidget->addAction(aReplaySkipForward);
|
||||
connect(aReplaySkipForward, &QAction::triggered, this,
|
||||
[=]() { timelineWidget->skipByAmount(ReplayTimelineWidget::SMALL_SKIP_MS); });
|
||||
[this] { timelineWidget->skipByAmount(ReplayTimelineWidget::SMALL_SKIP_MS); });
|
||||
|
||||
aReplaySkipBackward = new QAction(timelineWidget);
|
||||
timelineWidget->addAction(aReplaySkipBackward);
|
||||
connect(aReplaySkipBackward, &QAction::triggered, this,
|
||||
[=]() { timelineWidget->skipByAmount(-ReplayTimelineWidget::SMALL_SKIP_MS); });
|
||||
[this] { timelineWidget->skipByAmount(-ReplayTimelineWidget::SMALL_SKIP_MS); });
|
||||
|
||||
aReplaySkipForwardBig = new QAction(timelineWidget);
|
||||
timelineWidget->addAction(aReplaySkipForwardBig);
|
||||
connect(aReplaySkipForwardBig, &QAction::triggered, this,
|
||||
[=]() { timelineWidget->skipByAmount(ReplayTimelineWidget::BIG_SKIP_MS); });
|
||||
[this] { timelineWidget->skipByAmount(ReplayTimelineWidget::BIG_SKIP_MS); });
|
||||
|
||||
aReplaySkipBackwardBig = new QAction(timelineWidget);
|
||||
timelineWidget->addAction(aReplaySkipBackwardBig);
|
||||
connect(aReplaySkipBackwardBig, &QAction::triggered, this,
|
||||
[=]() { timelineWidget->skipByAmount(-ReplayTimelineWidget::BIG_SKIP_MS); });
|
||||
[this] { timelineWidget->skipByAmount(-ReplayTimelineWidget::BIG_SKIP_MS); });
|
||||
|
||||
// buttons
|
||||
replayPlayButton = new QToolButton;
|
||||
|
||||
@@ -7,23 +7,23 @@
|
||||
class TearOffMenu : public QMenu
|
||||
{
|
||||
public:
|
||||
TearOffMenu(const QString &title, QWidget *parent = nullptr) : QMenu(title, parent)
|
||||
explicit TearOffMenu(const QString &title, QWidget *parent = nullptr) : QMenu(title, parent)
|
||||
{
|
||||
connect(&SettingsCache::instance(), &SettingsCache::useTearOffMenusChanged, this,
|
||||
[=](bool state) { setTearOffEnabled(state); });
|
||||
[this](const bool state) { setTearOffEnabled(state); });
|
||||
setTearOffEnabled(SettingsCache::instance().getUseTearOffMenus());
|
||||
}
|
||||
|
||||
TearOffMenu(QWidget *parent = nullptr) : QMenu(parent)
|
||||
explicit TearOffMenu(QWidget *parent = nullptr) : QMenu(parent)
|
||||
{
|
||||
connect(&SettingsCache::instance(), &SettingsCache::useTearOffMenusChanged, this,
|
||||
[=](bool state) { setTearOffEnabled(state); });
|
||||
[this](const bool state) { setTearOffEnabled(state); });
|
||||
setTearOffEnabled(SettingsCache::instance().getUseTearOffMenus());
|
||||
}
|
||||
|
||||
TearOffMenu *addTearOffMenu(const QString &title)
|
||||
{
|
||||
TearOffMenu *menu = new TearOffMenu(title, this);
|
||||
auto *menu = new TearOffMenu(title, this);
|
||||
addMenu(menu);
|
||||
return menu;
|
||||
}
|
||||
|
||||
@@ -175,7 +175,7 @@ void PrintingSelector::getAllSetsForCurrentCard()
|
||||
// Defer widget creation
|
||||
currentIndex = 0;
|
||||
|
||||
connect(widgetLoadingBufferTimer, &QTimer::timeout, this, [=]() mutable {
|
||||
connect(widgetLoadingBufferTimer, &QTimer::timeout, this, [=, this]() mutable {
|
||||
for (int i = 0; i < BATCH_SIZE && currentIndex < setsToUse.size(); ++i, ++currentIndex) {
|
||||
auto *cardDisplayWidget = new PrintingSelectorCardDisplayWidget(this, deckEditor, deckModel, deckView,
|
||||
cardSizeWidget->getSlider(), selectedCard,
|
||||
|
||||
@@ -26,7 +26,9 @@ OracleQuery <- 'o' [:] RegexString
|
||||
CMCQuery <- ('cmc'/'mv') ws? NumericExpression
|
||||
PowerQuery <- [Pp] 'ow' 'er'? ws? NumericExpression
|
||||
ToughnessQuery <- [Tt] 'ou' 'ghness'? ws? NumericExpression
|
||||
RarityQuery <- [rR] ':' RegexString
|
||||
|
||||
RarityQuery <- [rR] ':' Rarity
|
||||
Rarity <- [Cc] 'ommon'? / [Uu] 'ncommon'? / [Rr] 'are'? / [Mm] 'ythic'? / [Ss] 'pecial'? / [a-zA-Z] [a-z]*
|
||||
|
||||
FormatQuery <- 'f' ':' Format / Legality ':' Format
|
||||
Format <- [a-zA-Z] [a-z]*
|
||||
@@ -42,10 +44,11 @@ ColorQuery <- [cC] 'olor'? <[iI]?> <[:!]> ColorEx*
|
||||
|
||||
FieldQuery <- String [:] RegexString / String ws? NumericExpression
|
||||
|
||||
NonDoubleQuoteUnlessEscaped <- !["]. / '\"'.
|
||||
NonSingleQuoteUnlessEscaped <- ![']. / "\'".
|
||||
NonDoubleQuoteUnlessEscaped <- '\\\"'. / !["].
|
||||
NonSingleQuoteUnlessEscaped <- "\\\'". / !['].
|
||||
UnescapedStringListPart <- !['":<>=! ].
|
||||
String <- UnescapedStringListPart+ / ["] <NonDoubleQuoteUnlessEscaped*> ["] / ['] <NonSingleQuoteUnlessEscaped*> [']
|
||||
SingleApostropheString <- (UnescapedStringListPart+ ws*)* ['] (UnescapedStringListPart+ ws*)*
|
||||
String <- UnescapedStringListPart+ / ["] <NonDoubleQuoteUnlessEscaped*> ["] / ['] <NonSingleQuoteUnlessEscaped*> ['] / SingleApostropheString
|
||||
StringValue <- String / [(] StringList [)]
|
||||
StringList <- StringListString (ws? [,] ws? StringListString)*
|
||||
StringListString <- UnescapedStringListPart+
|
||||
@@ -58,78 +61,92 @@ CompactStringSet <- StringListString ([,+] StringListString)+
|
||||
NumericExpression <- NumericOperator ws? NumericValue
|
||||
NumericOperator <- [=:] / <[><!][=]?>
|
||||
NumericValue <- [0-9]+
|
||||
|
||||
)");
|
||||
|
||||
std::once_flag init;
|
||||
|
||||
static void setupParserRules()
|
||||
{
|
||||
auto passthru = [](const peg::SemanticValues &sv) -> Filter { return !sv.empty() ? sv[0].get<Filter>() : nullptr; };
|
||||
auto passthru = [](const peg::SemanticValues &sv) -> Filter {
|
||||
return !sv.empty() ? std::any_cast<Filter>(sv[0]) : nullptr;
|
||||
};
|
||||
|
||||
search["Start"] = passthru;
|
||||
search["QueryPartList"] = [](const peg::SemanticValues &sv) -> Filter {
|
||||
return [=](CardData x) {
|
||||
for (int i = 0; i < static_cast<int>(sv.size()); ++i) {
|
||||
if (!sv[i].get<Filter>()(x))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return [=](const CardData &x) {
|
||||
auto matchesFilter = [&x](const std::any &query) { return std::any_cast<Filter>(query)(x); };
|
||||
return std::all_of(sv.begin(), sv.end(), matchesFilter);
|
||||
};
|
||||
};
|
||||
search["ComplexQueryPart"] = [](const peg::SemanticValues &sv) -> Filter {
|
||||
return [=](CardData x) {
|
||||
for (int i = 0; i < static_cast<int>(sv.size()); ++i) {
|
||||
if (sv[i].get<Filter>()(x))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return [=](const CardData &x) {
|
||||
auto matchesFilter = [&x](const std::any &query) { return std::any_cast<Filter>(query)(x); };
|
||||
return std::any_of(sv.begin(), sv.end(), matchesFilter);
|
||||
};
|
||||
};
|
||||
search["SomewhatComplexQueryPart"] = passthru;
|
||||
search["QueryPart"] = passthru;
|
||||
search["NotQuery"] = [](const peg::SemanticValues &sv) -> Filter {
|
||||
Filter dependent = sv[0].get<Filter>();
|
||||
return [=](CardData x) -> bool { return !dependent(x); };
|
||||
const auto dependent = std::any_cast<Filter>(sv[0]);
|
||||
return [=](const CardData &x) -> bool { return !dependent(x); };
|
||||
};
|
||||
search["TypeQuery"] = [](const peg::SemanticValues &sv) -> Filter {
|
||||
StringMatcher matcher = sv[0].get<StringMatcher>();
|
||||
return [=](CardData x) -> bool { return matcher(x->getCardType()); };
|
||||
const auto matcher = std::any_cast<StringMatcher>(sv[0]);
|
||||
return [=](const CardData &x) -> bool { return matcher(x->getCardType()); };
|
||||
};
|
||||
search["SetQuery"] = [](const peg::SemanticValues &sv) -> Filter {
|
||||
StringMatcher matcher = sv[0].get<StringMatcher>();
|
||||
return [=](CardData x) -> bool {
|
||||
for (const auto &set : x->getSets().keys()) {
|
||||
if (matcher(set))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
auto matcher = std::any_cast<StringMatcher>(sv[0]);
|
||||
return [=](const CardData &x) -> bool {
|
||||
QList<QString> sets = x->getSets().keys();
|
||||
|
||||
auto matchesSet = [&matcher](const QString &set) { return matcher(set); };
|
||||
return std::any_of(sets.begin(), sets.end(), matchesSet);
|
||||
};
|
||||
};
|
||||
search["Rarity"] = [](const peg::SemanticValues &sv) -> QString {
|
||||
switch (tolower(std::string(sv.sv())[0])) {
|
||||
case 'c':
|
||||
return "common";
|
||||
case 'u':
|
||||
return "uncommon";
|
||||
case 'r':
|
||||
return "rare";
|
||||
case 'm':
|
||||
return "mythic";
|
||||
case 's':
|
||||
return "special";
|
||||
default:
|
||||
return QString::fromStdString(std::string(sv.sv()));
|
||||
}
|
||||
};
|
||||
search["RarityQuery"] = [](const peg::SemanticValues &sv) -> Filter {
|
||||
StringMatcher matcher = sv[0].get<StringMatcher>();
|
||||
const auto rarity = std::any_cast<QString>(sv[0]);
|
||||
return [=](const CardData &x) -> bool {
|
||||
for (const auto &cardInfoPerSetList : x->getSets().values()) {
|
||||
for (const auto &set : cardInfoPerSetList) {
|
||||
if (matcher(set.getProperty("rarity")))
|
||||
return true;
|
||||
QList<CardInfoPerSet> infos;
|
||||
for (const auto &setsValue : x->getSets().values()) {
|
||||
for (const auto &cardInfoPerSet : setsValue) {
|
||||
infos.append(cardInfoPerSet);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
auto matchesRarity = [&rarity](const CardInfoPerSet &info) { return rarity == info.getProperty("rarity"); };
|
||||
return std::any_of(infos.begin(), infos.end(), matchesRarity);
|
||||
};
|
||||
};
|
||||
|
||||
search["FormatQuery"] = [](const peg::SemanticValues &sv) -> Filter {
|
||||
if (sv.choice() == 0) {
|
||||
QString format = sv[0].get<QString>();
|
||||
return [=](CardData x) -> bool { return x->getProperty(QString("format-%1").arg(format)) == "legal"; };
|
||||
} else {
|
||||
QString format = sv[1].get<QString>();
|
||||
QString legality = sv[0].get<QString>();
|
||||
return [=](CardData x) -> bool { return x->getProperty(QString("format-%1").arg(format)) == legality; };
|
||||
const auto format = std::any_cast<QString>(sv[0]);
|
||||
return
|
||||
[=](const CardData &x) -> bool { return x->getProperty(QString("format-%1").arg(format)) == "legal"; };
|
||||
}
|
||||
|
||||
const auto format = std::any_cast<QString>(sv[1]);
|
||||
const auto legality = std::any_cast<QString>(sv[0]);
|
||||
return [=](const CardData &x) -> bool { return x->getProperty(QString("format-%1").arg(format)) == legality; };
|
||||
};
|
||||
search["Legality"] = [](const peg::SemanticValues &sv) -> QString {
|
||||
switch (tolower(sv.str()[0])) {
|
||||
switch (tolower(std::string(sv.sv())[0])) {
|
||||
case 'l':
|
||||
return "legal";
|
||||
case 'b':
|
||||
@@ -142,8 +159,8 @@ static void setupParserRules()
|
||||
};
|
||||
|
||||
search["Format"] = [](const peg::SemanticValues &sv) -> QString {
|
||||
if (sv.length() == 1) {
|
||||
switch (tolower(sv.str()[0])) {
|
||||
if (sv.size() == 1) {
|
||||
switch (tolower(std::string(sv.sv())[0])) {
|
||||
case 'm':
|
||||
return "modern";
|
||||
case 's':
|
||||
@@ -159,193 +176,191 @@ static void setupParserRules()
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
} else {
|
||||
return QString::fromStdString(sv.str()).toLower();
|
||||
}
|
||||
|
||||
return QString::fromStdString(std::string(sv.sv())).toLower();
|
||||
};
|
||||
search["StringValue"] = [](const peg::SemanticValues &sv) -> StringMatcher {
|
||||
if (sv.choice() == 0) {
|
||||
auto target = sv[0].get<QString>();
|
||||
const auto target = std::any_cast<QString>(sv[0]);
|
||||
return [=](const QString &s) { return s.split(" ").contains(target, Qt::CaseInsensitive); };
|
||||
} else {
|
||||
auto target = sv[0].get<QStringList>();
|
||||
}
|
||||
|
||||
const auto target = std::any_cast<QStringList>(sv[0]);
|
||||
return [=](const QString &s) {
|
||||
for (const QString &str : target) {
|
||||
if (s.split(" ").contains(str, Qt::CaseInsensitive)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
auto containsString = [&s](const QString &str) { return s.split(" ").contains(str, Qt::CaseInsensitive); };
|
||||
return std::any_of(target.begin(), target.end(), containsString);
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
search["String"] = [](const peg::SemanticValues &sv) -> QString {
|
||||
if (sv.choice() == 0) {
|
||||
return QString::fromStdString(sv.str());
|
||||
} else {
|
||||
return QString::fromStdString(sv.token(0));
|
||||
return QString::fromStdString(std::string(sv.sv()));
|
||||
}
|
||||
|
||||
return QString::fromStdString(std::string(sv.token(0)));
|
||||
};
|
||||
search["FlexStringValue"] = [](const peg::SemanticValues &sv) -> StringMatcher {
|
||||
if (sv.choice() != 1) {
|
||||
auto target = sv[0].get<QStringList>();
|
||||
const auto target = std::any_cast<QStringList>(sv[0]);
|
||||
return [=](const QString &s) {
|
||||
for (const QString &str : target) {
|
||||
if (s.split(" ").contains(str, Qt::CaseInsensitive)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
auto containsString = [&s](const QString &str) {
|
||||
return s.split(" ").contains(str, Qt::CaseInsensitive);
|
||||
};
|
||||
} else {
|
||||
auto target = sv[0].get<QString>();
|
||||
return std::any_of(target.begin(), target.end(), containsString);
|
||||
};
|
||||
}
|
||||
|
||||
const auto target = std::any_cast<QString>(sv[0]);
|
||||
return [=](const QString &s) { return s.split(" ").contains(target, Qt::CaseInsensitive); };
|
||||
}
|
||||
};
|
||||
search["CompactStringSet"] = search["StringList"] = [](const peg::SemanticValues &sv) -> QStringList {
|
||||
search["CompactStringSet"] = [](const peg::SemanticValues &sv) -> QStringList {
|
||||
QStringList result;
|
||||
for (int i = 0; i < static_cast<int>(sv.size()); ++i) {
|
||||
result.append(sv[i].get<QString>());
|
||||
for (const auto &i : sv) {
|
||||
result.append(std::any_cast<QString>(i));
|
||||
}
|
||||
return result;
|
||||
};
|
||||
search["StringList"] = [](const peg::SemanticValues &sv) -> QStringList {
|
||||
QStringList result;
|
||||
for (const auto &i : sv) {
|
||||
result.append(std::any_cast<QString>(i));
|
||||
}
|
||||
return result;
|
||||
};
|
||||
search["StringListString"] = [](const peg::SemanticValues &sv) -> QString {
|
||||
return QString::fromStdString(sv.str());
|
||||
return QString::fromStdString(std::string(sv.sv()));
|
||||
};
|
||||
|
||||
search["NumericExpression"] = [](const peg::SemanticValues &sv) -> NumberMatcher {
|
||||
auto arg = sv[1].get<int>();
|
||||
auto op = sv[0].get<QString>();
|
||||
const auto arg = std::any_cast<int>(sv[1]);
|
||||
const auto op = std::any_cast<QString>(sv[0]);
|
||||
|
||||
if (op == ">")
|
||||
return [=](int s) { return s > arg; };
|
||||
return [=](const int s) { return s > arg; };
|
||||
if (op == ">=")
|
||||
return [=](int s) { return s >= arg; };
|
||||
return [=](const int s) { return s >= arg; };
|
||||
if (op == "<")
|
||||
return [=](int s) { return s < arg; };
|
||||
return [=](const int s) { return s < arg; };
|
||||
if (op == "<=")
|
||||
return [=](int s) { return s <= arg; };
|
||||
return [=](const int s) { return s <= arg; };
|
||||
if (op == "=")
|
||||
return [=](int s) { return s == arg; };
|
||||
return [=](const int s) { return s == arg; };
|
||||
if (op == ":")
|
||||
return [=](int s) { return s == arg; };
|
||||
return [=](const int s) { return s == arg; };
|
||||
if (op == "!=")
|
||||
return [=](int s) { return s != arg; };
|
||||
return [=](const int s) { return s != arg; };
|
||||
return [](int) { return false; };
|
||||
};
|
||||
|
||||
search["NumericValue"] = [](const peg::SemanticValues &sv) -> int {
|
||||
return QString::fromStdString(sv.str()).toInt();
|
||||
return QString::fromStdString(std::string(sv.sv())).toInt();
|
||||
};
|
||||
|
||||
search["NumericOperator"] = [](const peg::SemanticValues &sv) -> QString {
|
||||
return QString::fromStdString(sv.str());
|
||||
return QString::fromStdString(std::string(sv.sv()));
|
||||
};
|
||||
|
||||
search["RegexString"] = [](const peg::SemanticValues &sv) -> StringMatcher {
|
||||
auto target = sv[0].get<QString>();
|
||||
auto target = std::any_cast<QString>(sv[0]);
|
||||
return [=](const QString &s) {
|
||||
auto sanitizedTarget = QString(target);
|
||||
sanitizedTarget.replace("\\\"", "\"");
|
||||
sanitizedTarget.replace("\\'", "'");
|
||||
return s.QString::contains(sanitizedTarget, Qt::CaseInsensitive);
|
||||
return s.contains(sanitizedTarget, Qt::CaseInsensitive);
|
||||
};
|
||||
};
|
||||
|
||||
search["OracleQuery"] = [](const peg::SemanticValues &sv) -> Filter {
|
||||
StringMatcher matcher = sv[0].get<StringMatcher>();
|
||||
return [=](CardData x) { return matcher(x->getText()); };
|
||||
const auto matcher = std::any_cast<StringMatcher>(sv[0]);
|
||||
return [=](const CardData &x) { return matcher(x->getText()); };
|
||||
};
|
||||
|
||||
search["ColorQuery"] = [](const peg::SemanticValues &sv) -> Filter {
|
||||
QString parts;
|
||||
for (int i = 0; i < static_cast<int>(sv.size()); ++i) {
|
||||
parts += sv[i].get<char>();
|
||||
for (const auto &i : sv) {
|
||||
parts += std::any_cast<char>(i);
|
||||
}
|
||||
bool idenity = sv.tokens[0].first[0] != 'i';
|
||||
if (sv.tokens[1].first[0] == ':') {
|
||||
return [=](CardData x) {
|
||||
QString match = idenity ? x->getColors() : x->getProperty("coloridentity");
|
||||
const bool identity = sv.tokens[0][0] != 'i';
|
||||
if (sv.tokens[1][0] == ':') {
|
||||
return [=](const CardData &x) {
|
||||
QString match = identity ? x->getColors() : x->getProperty("coloridentity");
|
||||
if (parts.contains("m") && match.length() < 2) {
|
||||
return false;
|
||||
} else if (parts == "m") {
|
||||
}
|
||||
if (parts == "m") {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (parts.contains("c") && match.length() == 0)
|
||||
return true;
|
||||
|
||||
for (const auto &i : match) {
|
||||
if (parts.contains(i))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
auto containsColor = [&parts](const QString &s) { return parts.contains(s); };
|
||||
return std::any_of(match.begin(), match.end(), containsColor);
|
||||
};
|
||||
} else {
|
||||
return [=](CardData x) {
|
||||
QString match = idenity ? x->getColors() : x->getProperty("colorIdentity");
|
||||
if (parts.contains("m") && match.length() < 2)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (parts.contains("c") && match.length() != 0)
|
||||
return [=](const CardData &x) {
|
||||
QString match = identity ? x->getColors() : x->getProperty("colorIdentity");
|
||||
if (parts.contains("m") && match.length() < 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (parts.contains("c") && match.length() != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const auto &part : parts) {
|
||||
if (!match.contains(part))
|
||||
if (!match.contains(part)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto &i : match) {
|
||||
if (!parts.contains(i))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
auto containsColor = [&parts](const QString &s) { return parts.contains(s); };
|
||||
return std::all_of(match.begin(), match.end(), containsColor);
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
search["CMCQuery"] = [](const peg::SemanticValues &sv) -> Filter {
|
||||
NumberMatcher matcher = sv[0].get<NumberMatcher>();
|
||||
return [=](CardData x) -> bool { return matcher(x->getProperty("cmc").toInt()); };
|
||||
const auto matcher = std::any_cast<NumberMatcher>(sv[0]);
|
||||
return [=](const CardData &x) -> bool { return matcher(x->getProperty("cmc").toInt()); };
|
||||
};
|
||||
search["PowerQuery"] = [](const peg::SemanticValues &sv) -> Filter {
|
||||
NumberMatcher matcher = sv[0].get<NumberMatcher>();
|
||||
return [=](CardData x) -> bool { return matcher(x->getPowTough().split("/")[0].toInt()); };
|
||||
const auto matcher = std::any_cast<NumberMatcher>(sv[0]);
|
||||
return [=](const CardData &x) -> bool { return matcher(x->getPowTough().split("/")[0].toInt()); };
|
||||
};
|
||||
search["ToughnessQuery"] = [](const peg::SemanticValues &sv) -> Filter {
|
||||
NumberMatcher matcher = sv[0].get<NumberMatcher>();
|
||||
return [=](CardData x) -> bool {
|
||||
const auto matcher = std::any_cast<NumberMatcher>(sv[0]);
|
||||
return [=](const CardData &x) -> bool {
|
||||
auto parts = x->getPowTough().split("/");
|
||||
return matcher(parts.length() == 2 ? parts[1].toInt() : 0);
|
||||
};
|
||||
};
|
||||
search["FieldQuery"] = [](const peg::SemanticValues &sv) -> Filter {
|
||||
QString field = sv[0].get<QString>();
|
||||
const auto field = std::any_cast<QString>(sv[0]);
|
||||
if (sv.choice() == 0) {
|
||||
StringMatcher matcher = sv[1].get<StringMatcher>();
|
||||
return [=](CardData x) -> bool { return x->hasProperty(field) ? matcher(x->getProperty(field)) : false; };
|
||||
} else {
|
||||
NumberMatcher matcher = sv[1].get<NumberMatcher>();
|
||||
return [=](CardData x) -> bool {
|
||||
return x->hasProperty(field) ? matcher(x->getProperty(field).toInt()) : false;
|
||||
};
|
||||
const auto matcher = std::any_cast<StringMatcher>(sv[1]);
|
||||
return [=](const CardData &x) -> bool { return x->hasProperty(field) && matcher(x->getProperty(field)); };
|
||||
}
|
||||
|
||||
const auto matcher = std::any_cast<NumberMatcher>(sv[1]);
|
||||
return
|
||||
[=](const CardData &x) -> bool { return x->hasProperty(field) && matcher(x->getProperty(field).toInt()); };
|
||||
};
|
||||
search["GenericQuery"] = [](const peg::SemanticValues &sv) -> Filter {
|
||||
StringMatcher matcher = sv[0].get<StringMatcher>();
|
||||
return [=](CardData x) { return matcher(x->getName()); };
|
||||
const auto matcher = std::any_cast<StringMatcher>(sv[0]);
|
||||
return [=](const CardData &x) { return matcher(x->getName()); };
|
||||
};
|
||||
|
||||
search["Color"] = [](const peg::SemanticValues &sv) -> char { return "WUBRGU"[sv.choice()]; };
|
||||
search["ColorEx"] = [](const peg::SemanticValues &sv) -> char {
|
||||
return sv.choice() == 0 ? sv[0].get<char>() : *sv.c_str();
|
||||
return sv.choice() == 0 ? std::any_cast<char>(sv[0]) : *std::string(sv.sv()).c_str();
|
||||
};
|
||||
}
|
||||
|
||||
FilterString::FilterString()
|
||||
{
|
||||
result = [](CardData) -> bool { return false; };
|
||||
result = [](const CardData &) -> bool { return false; };
|
||||
_error = "Not initialized";
|
||||
}
|
||||
|
||||
@@ -358,16 +373,16 @@ FilterString::FilterString(const QString &expr)
|
||||
_error = QString();
|
||||
|
||||
if (ba.isEmpty()) {
|
||||
result = [](CardData) -> bool { return true; };
|
||||
result = [](const CardData &) -> bool { return true; };
|
||||
return;
|
||||
}
|
||||
|
||||
search.log = [&](size_t /*ln*/, size_t col, const std::string &msg) {
|
||||
search.set_logger([&](size_t /*ln*/, size_t col, const std::string &msg) {
|
||||
_error = QString("Error at position %1: %2").arg(col).arg(QString::fromStdString(msg));
|
||||
};
|
||||
});
|
||||
|
||||
if (!search.parse(ba.data(), result)) {
|
||||
qDebug().nospace() << "FilterString error for " << expr << "; " << qPrintable(_error);
|
||||
result = [](CardData) -> bool { return false; };
|
||||
result = [](const CardData &) -> bool { return false; };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,7 +138,7 @@ ZoneViewWidget::ZoneViewWidget(Player *_player,
|
||||
// QLabel sizes aren't taken into account until the widget is rendered.
|
||||
// Force refresh after 1ms to fix glitchy rendering with long QLabels.
|
||||
auto *lastResizeBeforeVisibleTimer = new QTimer(this);
|
||||
connect(lastResizeBeforeVisibleTimer, &QTimer::timeout, this, [=] {
|
||||
connect(lastResizeBeforeVisibleTimer, &QTimer::timeout, this, [=, this] {
|
||||
resizeToZoneContents();
|
||||
disconnect(lastResizeBeforeVisibleTimer);
|
||||
lastResizeBeforeVisibleTimer->deleteLater();
|
||||
|
||||
@@ -253,7 +253,7 @@ void UserInfoBox::actPassword()
|
||||
connect(pend,
|
||||
// we need qoverload here in order to select the right version of this function
|
||||
QOverload<const Response &, const CommandContainer &, const QVariant &>::of(&PendingCommand::finished),
|
||||
this, [=](const Response &response, const CommandContainer &, const QVariant &) {
|
||||
this, [=, this](const Response &response, const CommandContainer &, const QVariant &) {
|
||||
if (response.response_code() == Response::RespOk) {
|
||||
changePassword(oldPassword, newPassword);
|
||||
} else {
|
||||
|
||||
@@ -51,9 +51,9 @@ double Expression::eval(const peg::Ast &ast)
|
||||
{
|
||||
const auto &nodes = ast.nodes;
|
||||
if (ast.name == "NUMBER") {
|
||||
return stod(ast.token);
|
||||
return stod(std::string(ast.token));
|
||||
} else if (ast.name == "FUNCTION") {
|
||||
QString name = QString::fromStdString(nodes[0]->token);
|
||||
QString name = QString::fromStdString(std::string(nodes[0]->token));
|
||||
if (!fns.contains(name))
|
||||
return 0;
|
||||
return fns[name](eval(*nodes[1]));
|
||||
|
||||
5014
common/lib/peglib.h
5014
common/lib/peglib.h
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user