diff --git a/cockatrice/CMakeLists.txt b/cockatrice/CMakeLists.txt index 84b331f0f..18df9795f 100644 --- a/cockatrice/CMakeLists.txt +++ b/cockatrice/CMakeLists.txt @@ -157,6 +157,7 @@ set(cockatrice_SOURCES src/game/filters/filter_string.cpp src/game/filters/filter_tree.cpp src/game/filters/filter_tree_model.cpp + src/game/filters/syntax_help.cpp src/game/game_scene.cpp src/game/game_selector.cpp src/game/game_view.cpp diff --git a/cockatrice/src/client/ui/widgets/deck_editor/deck_editor_database_display_widget.cpp b/cockatrice/src/client/ui/widgets/deck_editor/deck_editor_database_display_widget.cpp index 94c6609be..0374503bc 100644 --- a/cockatrice/src/client/ui/widgets/deck_editor/deck_editor_database_display_widget.cpp +++ b/cockatrice/src/client/ui/widgets/deck_editor/deck_editor_database_display_widget.cpp @@ -1,6 +1,7 @@ #include "deck_editor_database_display_widget.h" #include "../../../../game/cards/card_database_manager.h" +#include "../../../../game/filters/syntax_help.h" #include "../../../../settings/cache_settings.h" #include "../../../tabs/abstract_tab_deck_editor.h" #include "../../../tabs/tab_supervisor.h" @@ -56,7 +57,7 @@ DeckEditorDatabaseDisplayWidget::DeckEditorDatabaseDisplayWidget(AbstractTabDeck &DeckEditorDatabaseDisplayWidget::actAddCardToSideboard); connect(&searchKeySignals, &KeySignals::onCtrlEnter, this, &DeckEditorDatabaseDisplayWidget::actAddCardToSideboard); connect(&searchKeySignals, &KeySignals::onCtrlC, this, &DeckEditorDatabaseDisplayWidget::copyDatabaseCellContents); - connect(help, &QAction::triggered, this, &DeckEditorDatabaseDisplayWidget::showSearchSyntaxHelp); + connect(help, &QAction::triggered, this, [this] { createSearchSyntaxHelpWindow(searchEdit); }); databaseModel = new CardDatabaseModel(CardDatabaseManager::getInstance(), true, this); databaseModel->setObjectName("databaseModel"); @@ -234,42 +235,6 @@ void DeckEditorDatabaseDisplayWidget::saveDbHeaderState() SettingsCache::instance().layouts().setDeckEditorDbHeaderState(databaseView->header()->saveState()); } -void DeckEditorDatabaseDisplayWidget::showSearchSyntaxHelp() -{ - - QFile file("theme:help/search.md"); - - if (!file.open(QFile::ReadOnly | QFile::Text)) { - return; - } - - QTextStream in(&file); - QString text = in.readAll(); - file.close(); - - // Poor Markdown Converter - auto opts = QRegularExpression::MultilineOption; - text = text.replace(QRegularExpression("^(###)(.*)", opts), "

\\2

") - .replace(QRegularExpression("^(##)(.*)", opts), "

\\2

") - .replace(QRegularExpression("^(#)(.*)", opts), "

\\2

") - .replace(QRegularExpression("^------*", opts), "
") - .replace(QRegularExpression(R"(\[([^[]+)\]\(([^\)]+)\))", opts), R"(\1)"); - - auto browser = new QTextBrowser; - browser->setParent(this, Qt::Window | Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowMinMaxButtonsHint | - Qt::WindowCloseButtonHint | Qt::WindowFullscreenButtonHint); - browser->setWindowTitle("Search Help"); - browser->setReadOnly(true); - browser->setMinimumSize({500, 600}); - - QString sheet = QString("a { text-decoration: underline; color: rgb(71,158,252) };"); - browser->document()->setDefaultStyleSheet(sheet); - - browser->setHtml(text); - connect(browser, &QTextBrowser::anchorClicked, [this](const QUrl &link) { searchEdit->setText(link.fragment()); }); - browser->show(); -} - void DeckEditorDatabaseDisplayWidget::setFilterTree(FilterTree *filterTree) { databaseDisplayModel->setFilterTree(filterTree); diff --git a/cockatrice/src/client/ui/widgets/deck_editor/deck_editor_database_display_widget.h b/cockatrice/src/client/ui/widgets/deck_editor/deck_editor_database_display_widget.h index 9022a2cb7..4010a2954 100644 --- a/cockatrice/src/client/ui/widgets/deck_editor/deck_editor_database_display_widget.h +++ b/cockatrice/src/client/ui/widgets/deck_editor/deck_editor_database_display_widget.h @@ -42,7 +42,6 @@ private: QWidget *centralWidget; private slots: - void showSearchSyntaxHelp(); void retranslateUi(); void updateSearch(const QString &search); void updateCard(const QModelIndex ¤t, const QModelIndex &); diff --git a/cockatrice/src/game/filters/syntax_help.cpp b/cockatrice/src/game/filters/syntax_help.cpp new file mode 100644 index 000000000..a4eaf9112 --- /dev/null +++ b/cockatrice/src/game/filters/syntax_help.cpp @@ -0,0 +1,62 @@ +#include "syntax_help.h" + +#include +#include +#include + +/** + * Creates the card search syntax help window + * + * @return the QTextBrowser + */ +static QTextBrowser *createBrowser() +{ + QFile file("theme:help/search.md"); + + if (!file.open(QFile::ReadOnly | QFile::Text)) { + return nullptr; + } + + QTextStream in(&file); + QString text = in.readAll(); + file.close(); + + // Poor Markdown Converter + auto opts = QRegularExpression::MultilineOption; + text = text.replace(QRegularExpression("^(###)(.*)", opts), "

\\2

") + .replace(QRegularExpression("^(##)(.*)", opts), "

\\2

") + .replace(QRegularExpression("^(#)(.*)", opts), "

\\2

") + .replace(QRegularExpression("^------*", opts), "
") + .replace(QRegularExpression(R"(\[([^[]+)\]\(([^\)]+)\))", opts), R"(\1)"); + + auto browser = new QTextBrowser(); + browser->setParent(nullptr, Qt::Window | Qt::WindowTitleHint | Qt::WindowSystemMenuHint | + Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint | + Qt::WindowFullscreenButtonHint); + browser->setWindowTitle("Search Help"); + browser->setReadOnly(true); + browser->setMinimumSize({500, 600}); + + QString sheet = QString("a { text-decoration: underline; color: rgb(71,158,252) };"); + browser->document()->setDefaultStyleSheet(sheet); + browser->setHtml(text); + + browser->show(); + + return browser; +} + +/** + * Creates the card search syntax help window and connects its anchorClicked signal to the given QLineEdit. + * The window will automatically close when the QLineEdit is destroyed. + * + * @return the QTextBrowser + */ +QTextBrowser *createSearchSyntaxHelpWindow(QLineEdit *lineEdit) +{ + auto browser = createBrowser(); + QObject::connect(browser, &QTextBrowser::anchorClicked, + [lineEdit](const QUrl &link) { lineEdit->setText(link.fragment()); }); + QObject::connect(lineEdit, &QObject::destroyed, browser, &QTextBrowser::close); + return browser; +} \ No newline at end of file diff --git a/cockatrice/src/game/filters/syntax_help.h b/cockatrice/src/game/filters/syntax_help.h new file mode 100644 index 000000000..4016e02bb --- /dev/null +++ b/cockatrice/src/game/filters/syntax_help.h @@ -0,0 +1,9 @@ +#ifndef SEARCH_SYNTAX_HELP_H +#define SEARCH_SYNTAX_HELP_H + +#include +#include + +QTextBrowser *createSearchSyntaxHelpWindow(QLineEdit *lineEdit); + +#endif // SEARCH_SYNTAX_HELP_H diff --git a/cockatrice/src/game/game_view.cpp b/cockatrice/src/game/game_view.cpp index 7ce9dda3e..969e26e14 100644 --- a/cockatrice/src/game/game_view.cpp +++ b/cockatrice/src/game/game_view.cpp @@ -11,7 +11,7 @@ GameView::GameView(GameScene *scene, QWidget *parent) : QGraphicsView(scene, par { setBackgroundBrush(QBrush(QColor(0, 0, 0))); setRenderHints(QPainter::TextAntialiasing | QPainter::Antialiasing); - setFocusPolicy(Qt::NoFocus); + setFocusPolicy(Qt::ClickFocus); setViewportUpdateMode(BoundingRectViewportUpdate); connect(scene, &GameScene::sceneRectChanged, this, &GameView::updateSceneRect); diff --git a/cockatrice/src/game/zones/view_zone.cpp b/cockatrice/src/game/zones/view_zone.cpp index 9e9ba6e81..793f90918 100644 --- a/cockatrice/src/game/zones/view_zone.cpp +++ b/cockatrice/src/game/zones/view_zone.cpp @@ -148,7 +148,16 @@ void ZoneViewZone::updateCardIds(CardAction action) // Because of boundingRect(), this function must not be called before the zone was added to a scene. void ZoneViewZone::reorganizeCards() { - CardList cardsToDisplay(cards); + // filter cards + CardList cardsToDisplay = CardList(cards.getContentsKnown()); + for (auto card : cards) { + if (filterString.check(card->getInfo())) { + card->show(); + cardsToDisplay.append(card); + } else { + card->hide(); + } + } // sort cards QList sortOptions; @@ -263,6 +272,12 @@ ZoneViewZone::GridSize ZoneViewZone::positionCardsForDisplay(CardList &cards, Ca } } +void ZoneViewZone::setFilterString(const QString &_filterString) +{ + filterString = FilterString(_filterString); + reorganizeCards(); +} + void ZoneViewZone::setGroupBy(CardList::SortOption _groupBy) { groupBy = _groupBy; diff --git a/cockatrice/src/game/zones/view_zone.h b/cockatrice/src/game/zones/view_zone.h index 3c69317aa..84fbe5ce6 100644 --- a/cockatrice/src/game/zones/view_zone.h +++ b/cockatrice/src/game/zones/view_zone.h @@ -1,6 +1,7 @@ #ifndef ZONEVIEWERZONE_H #define ZONEVIEWERZONE_H +#include "../filters/filter_string.h" #include "select_zone.h" #include @@ -35,6 +36,7 @@ private: int minRows, numberCards; CardZone *origZone; bool revealZone, writeableRevealZone; + FilterString filterString = FilterString(""); CardList::SortOption groupBy, sortBy; bool pileView; bool isReversed; @@ -96,6 +98,7 @@ public: } public slots: void close(); + void setFilterString(const QString &_filterString); void setGroupBy(CardList::SortOption _groupBy); void setSortBy(CardList::SortOption _sortBy); void setPileView(int _pileView); diff --git a/cockatrice/src/game/zones/view_zone_widget.cpp b/cockatrice/src/game/zones/view_zone_widget.cpp index 7dd21b9d5..85a91afdf 100644 --- a/cockatrice/src/game/zones/view_zone_widget.cpp +++ b/cockatrice/src/game/zones/view_zone_widget.cpp @@ -1,7 +1,9 @@ #include "view_zone_widget.h" +#include "../../client/ui/pixel_map_generator.h" #include "../../settings/cache_settings.h" #include "../cards/card_item.h" +#include "../filters/syntax_help.h" #include "../game_scene.h" #include "../player/player.h" #include "pb/command_shuffle.pb.h" @@ -41,9 +43,24 @@ ZoneViewWidget::ZoneViewWidget(Player *_player, setFlag(ItemIgnoresTransformations); QGraphicsLinearLayout *vbox = new QGraphicsLinearLayout(Qt::Vertical); + vbox->setSpacing(2); // If the number is < 0, then it means that we can give the option to make the area sorted if (numberCards < 0) { + // search edit + searchEdit.setFocusPolicy(Qt::ClickFocus); + searchEdit.setPlaceholderText(tr("Search by card name (or search expressions)")); + searchEdit.setClearButtonEnabled(true); + searchEdit.addAction(loadColorAdjustedPixmap("theme:icons/search"), QLineEdit::LeadingPosition); + auto help = searchEdit.addAction(QPixmap("theme:icons/info"), QLineEdit::TrailingPosition); + + connect(help, &QAction::triggered, this, [this] { createSearchSyntaxHelpWindow(&searchEdit); }); + + QGraphicsProxyWidget *searchEditProxy = new QGraphicsProxyWidget; + searchEditProxy->setWidget(&searchEdit); + searchEditProxy->setZValue(2000000007); + vbox->addItem(searchEditProxy); + // top row QGraphicsLinearLayout *hTopRow = new QGraphicsLinearLayout(Qt::Horizontal); @@ -128,6 +145,8 @@ ZoneViewWidget::ZoneViewWidget(Player *_player, if (CardList::NoSort == static_cast(groupBySelector.currentData().toInt())) { pileViewCheckBox.setEnabled(false); } + + connect(&searchEdit, &QLineEdit::textChanged, zone, &ZoneViewZone::setFilterString); } setLayout(vbox); diff --git a/cockatrice/src/game/zones/view_zone_widget.h b/cockatrice/src/game/zones/view_zone_widget.h index 177bcb92a..04662ebc9 100644 --- a/cockatrice/src/game/zones/view_zone_widget.h +++ b/cockatrice/src/game/zones/view_zone_widget.h @@ -7,6 +7,7 @@ #include #include #include +#include class QLabel; class QPushButton; @@ -47,6 +48,8 @@ private: QPushButton *closeButton; QScrollBar *scrollBar; ScrollableGraphicsProxyWidget *scrollBarProxy; + + QLineEdit searchEdit; QComboBox groupBySelector; QComboBox sortBySelector; QCheckBox shuffleCheckBox;