diff --git a/cockatrice/src/setsmodel.cpp b/cockatrice/src/setsmodel.cpp index 1ae6a376..2941ab75 100644 --- a/cockatrice/src/setsmodel.cpp +++ b/cockatrice/src/setsmodel.cpp @@ -252,3 +252,37 @@ QStringList SetsModel::mimeTypes() const { return QStringList() << "application/x-cockatricecardset"; } + +SetsDisplayModel::SetsDisplayModel(QObject *parent) : QSortFilterProxyModel(parent) +{ + setFilterCaseSensitivity(Qt::CaseInsensitive); + setSortCaseSensitivity(Qt::CaseInsensitive); +} + +void SetsDisplayModel::fetchMore(const QModelIndex &index) +{ + int itemsToFetch = sourceModel()->rowCount(index); + + beginInsertRows(QModelIndex(), 0, itemsToFetch - 1); + + endInsertRows(); +} + +bool SetsDisplayModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const +{ + auto typeIndex = sourceModel()->index(sourceRow, SetsModel::SetTypeCol, sourceParent); + auto nameIndex = sourceModel()->index(sourceRow, SetsModel::LongNameCol, sourceParent); + auto shortNameIndex = sourceModel()->index(sourceRow, SetsModel::ShortNameCol, sourceParent); + + return (sourceModel()->data(typeIndex).toString().contains(filterRegExp()) || + sourceModel()->data(nameIndex).toString().contains(filterRegExp()) || + sourceModel()->data(shortNameIndex).toString().contains(filterRegExp())); +} + +bool SetsDisplayModel::lessThan(const QModelIndex &left, const QModelIndex &right) const +{ + QString leftString = sourceModel()->data(left, SetsModel::SortRole).toString(); + QString rightString = sourceModel()->data(right, SetsModel::SortRole).toString(); + + return QString::localeAwareCompare(leftString, rightString) < 0; +} diff --git a/cockatrice/src/setsmodel.h b/cockatrice/src/setsmodel.h index eae9a003..470ef031 100644 --- a/cockatrice/src/setsmodel.h +++ b/cockatrice/src/setsmodel.h @@ -5,6 +5,7 @@ #include #include #include +#include class SetsProxyModel; @@ -80,4 +81,16 @@ public: void restore(CardDatabase *db); }; +class SetsDisplayModel : public QSortFilterProxyModel +{ + Q_OBJECT +public: + SetsDisplayModel(QObject *parent = NULL); + +protected: + bool lessThan(const QModelIndex &left, const QModelIndex &right) const override; + bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override; + void fetchMore(const QModelIndex &index) override; +}; + #endif diff --git a/cockatrice/src/window_sets.cpp b/cockatrice/src/window_sets.cpp index f3c967bf..b230a025 100644 --- a/cockatrice/src/window_sets.cpp +++ b/cockatrice/src/window_sets.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -15,7 +16,8 @@ #include #include #include -#include + +#define SORT_RESET -1 WndSets::WndSets(QWidget *parent) : QMainWindow(parent) { @@ -53,16 +55,35 @@ WndSets::WndSets(QWidget *parent) : QMainWindow(parent) connect(aBottom, SIGNAL(triggered()), this, SLOT(actBottom())); setsEditToolBar->addAction(aBottom); + // search field + searchField = new QLineEdit; + searchField->setObjectName("searchEdit"); + searchField->setPlaceholderText(tr("Search by set name, code, or type")); + searchField->addAction(QPixmap("theme:icons/search"), QLineEdit::LeadingPosition); + searchField->setClearButtonEnabled(true); + setFocusProxy(searchField); + + defaultSortButton = new QPushButton(tr("Default order")); + defaultSortButton->setToolTip(tr("Restore original art priority order")); + + connect(defaultSortButton, SIGNAL(clicked()), this, SLOT(actRestoreOriginalOrder())); + + filterBox = new QHBoxLayout; + filterBox->addWidget(searchField); + filterBox->addWidget(defaultSortButton); + // view model = new SetsModel(db, this); + displayModel = new SetsDisplayModel(this); + displayModel->setSourceModel(model); + displayModel->setDynamicSortFilter(false); view = new QTreeView; - view->setModel(model); + view->setModel(displayModel); view->setAlternatingRowColors(true); view->setUniformRowHeights(true); view->setAllColumnsShowFocus(true); view->setSortingEnabled(true); - view->setSelectionMode(QAbstractItemView::SingleSelection); view->setSelectionBehavior(QAbstractItemView::SelectRows); view->setSelectionMode(QAbstractItemView::ExtendedSelection); @@ -72,6 +93,7 @@ WndSets::WndSets(QWidget *parent) : QMainWindow(parent) view->setDragDropMode(QAbstractItemView::InternalMove); view->header()->setSectionResizeMode(QHeaderView::Stretch); + view->header()->setSectionResizeMode(SetsModel::EnabledCol, QHeaderView::ResizeToContents); view->header()->setSectionResizeMode(SetsModel::LongNameCol, QHeaderView::ResizeToContents); view->sortByColumn(SetsModel::SortKeyCol, Qt::AscendingOrder); @@ -79,6 +101,8 @@ WndSets::WndSets(QWidget *parent) : QMainWindow(parent) view->setColumnHidden(SetsModel::IsKnownCol, true); view->setRootIsDecorated(false); + connect(view->header(), SIGNAL(sectionClicked(int)), this, SLOT(actSort(int))); + // bottom buttons enableAllButton = new QPushButton(tr("Enable all sets")); disableAllButton = new QPushButton(tr("Disable all sets")); @@ -91,6 +115,9 @@ WndSets::WndSets(QWidget *parent) : QMainWindow(parent) connect(disableSomeButton, SIGNAL(clicked()), this, SLOT(actDisableSome())); connect(view->selectionModel(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)), this, SLOT(actToggleButtons(const QItemSelection &, const QItemSelection &))); + connect(searchField, SIGNAL(textChanged(const QString &)), displayModel, SLOT(setFilterRegExp(const QString &))); + connect(view->header(), SIGNAL(sortIndicatorChanged(int, Qt::SortOrder)), this, SLOT(actDisableSortButtons(int))); + connect(searchField, SIGNAL(textChanged(const QString &)), this, SLOT(actDisableResetButton(const QString &))); labNotes = new QLabel; labNotes->setWordWrap(true); @@ -106,19 +133,30 @@ WndSets::WndSets(QWidget *parent) : QMainWindow(parent) tr("CUSTOM Folder") + "
  • " + tr("Enabled Sets (Top to Bottom)") + "
  • " + tr("Disabled Sets (Top to Bottom)") + "
  • "); + sortWarning = new QLabel; + sortWarning->setWordWrap(true); + sortWarning->setText( + "" + tr("Warning: ") + "
    " + + tr("While the set list is sorted by any of the columns, custom art priority setting is disabled.") + "
    " + + tr("To disable sorting click on the same column header again until this message disappears.")); + sortWarning->setStyleSheet("QLabel { background-color:red;}"); + sortWarning->setVisible(false); + buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); connect(buttonBox, SIGNAL(accepted()), this, SLOT(actSave())); connect(buttonBox, SIGNAL(rejected()), this, SLOT(actRestore())); mainLayout = new QGridLayout; - mainLayout->addWidget(setsEditToolBar, 0, 0, 1, 1); - mainLayout->addWidget(view, 0, 1, 1, 2); - mainLayout->addWidget(enableAllButton, 1, 1); - mainLayout->addWidget(disableAllButton, 1, 2); - mainLayout->addWidget(enableSomeButton, 1, 1); - mainLayout->addWidget(disableSomeButton, 1, 2); - mainLayout->addWidget(labNotes, 2, 1, 1, 2); - mainLayout->addWidget(buttonBox, 3, 1, 1, 2); + mainLayout->addWidget(setsEditToolBar, 1, 0, 2, 1); + mainLayout->addLayout(filterBox, 0, 1, 1, 2); + mainLayout->addWidget(view, 1, 1, 1, 2); + mainLayout->addWidget(enableAllButton, 2, 1); + mainLayout->addWidget(disableAllButton, 2, 2); + mainLayout->addWidget(enableSomeButton, 2, 1); + mainLayout->addWidget(disableSomeButton, 2, 2); + mainLayout->addWidget(sortWarning, 3, 1, 1, 2); + mainLayout->addWidget(labNotes, 4, 1, 1, 2); + mainLayout->addWidget(buttonBox, 5, 1, 1, 2); mainLayout->setColumnStretch(1, 1); mainLayout->setColumnStretch(2, 1); @@ -173,6 +211,61 @@ void WndSets::actRestore() close(); } +void WndSets::actRestoreOriginalOrder() +{ + view->header()->setSortIndicator(SORT_RESET, Qt::DescendingOrder); + model->sort(model->ReleaseDateCol, Qt::DescendingOrder); + sortWarning->setVisible(false); +} + +void WndSets::actDisableResetButton(const QString &filterString) +{ + if (filterString.isEmpty()) { + defaultSortButton->setEnabled(true); + } else { + defaultSortButton->setEnabled(false); + } +} + +void WndSets::actSort(int index) +{ + if (sortIndex != index) { + view->sortByColumn(index, Qt::AscendingOrder); + sortOrder = Qt::AscendingOrder; + sortIndex = index; + sortWarning->setVisible(true); + } else { + if (sortOrder == Qt::AscendingOrder) { + view->sortByColumn(index, Qt::DescendingOrder); + sortOrder = Qt::DescendingOrder; + sortIndex = index; + sortWarning->setVisible(true); + } else { + view->header()->setSortIndicator(SORT_RESET, Qt::DescendingOrder); + sortIndex = -1; + sortWarning->setVisible(false); + } + } +} + +void WndSets::actDisableSortButtons(int index) +{ + if (index != SORT_RESET) { + view->setDragEnabled(false); + actToggleButtons(QItemSelection(), QItemSelection()); + disconnect(view->selectionModel(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)), + this, SLOT(actToggleButtons(const QItemSelection &, const QItemSelection &))); + } else { + actToggleButtons(view->selectionModel()->selection(), QItemSelection()); + connect(view->selectionModel(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)), this, + SLOT(actToggleButtons(const QItemSelection &, const QItemSelection &))); + if (!view->selectionModel()->selection().empty()) { + view->scrollTo(view->selectionModel()->selectedRows().first()); + } + view->setDragEnabled(true); + } +} + void WndSets::actToggleButtons(const QItemSelection &selected, const QItemSelection &) { bool disabled = selected.empty(); @@ -187,7 +280,7 @@ void WndSets::actToggleButtons(const QItemSelection &selected, const QItemSelect void WndSets::selectRows(QSet rows) { - foreach (int i, rows) { + for (auto i : rows) { QModelIndex idx = model->index(i, 0); view->selectionModel()->select(idx, QItemSelectionModel::Select | QItemSelectionModel::Rows); view->scrollTo(idx, QAbstractItemView::EnsureVisible); @@ -208,16 +301,18 @@ void WndSets::actEnableSome() { QModelIndexList rows = view->selectionModel()->selectedRows(); - foreach (QModelIndex i, rows) - model->toggleRow(i.row(), true); + for (auto i : rows) { + model->toggleRow(displayModel->mapToSource(i).row(), true); + } } void WndSets::actDisableSome() { QModelIndexList rows = view->selectionModel()->selectedRows(); - foreach (QModelIndex i, rows) - model->toggleRow(i.row(), false); + for (auto i : rows) { + model->toggleRow(displayModel->mapToSource(i).row(), false); + } } void WndSets::actUp() @@ -229,13 +324,13 @@ void WndSets::actUp() if (rows.empty()) return; - foreach (QModelIndex i, rows) { - int oldRow = i.row(); - int newRow = oldRow - 1; - if (oldRow <= 0) + for (auto i : rows) { + if (i.row() <= 0) continue; + int oldRow = displayModel->mapToSource(i).row(); + int newRow = i.row() - 1; - model->swapRows(oldRow, newRow); + model->swapRows(oldRow, displayModel->mapToSource(displayModel->index(newRow, 0)).row()); newRows.insert(newRow); } @@ -251,13 +346,13 @@ void WndSets::actDown() if (rows.empty()) return; - foreach (QModelIndex i, rows) { - int oldRow = i.row(); - int newRow = oldRow + 1; - if (oldRow >= model->rowCount() - 1) + for (auto i : rows) { + if (i.row() >= displayModel->rowCount() - 1) continue; + int oldRow = displayModel->mapToSource(i).row(); + int newRow = i.row() + 1; - model->swapRows(oldRow, newRow); + model->swapRows(oldRow, displayModel->mapToSource(displayModel->index(newRow, 0)).row()); newRows.insert(newRow); } @@ -275,7 +370,7 @@ void WndSets::actTop() return; for (int i = 0; i < rows.length(); i++) { - int oldRow = rows.at(i).row(); + int oldRow = displayModel->mapToSource(rows.at(i)).row(); if (oldRow <= 0) { newRow++; @@ -300,7 +395,7 @@ void WndSets::actBottom() return; for (int i = 0; i < rows.length(); i++) { - int oldRow = rows.at(i).row(); + int oldRow = displayModel->mapToSource(rows.at(i)).row(); if (oldRow >= newRow) { newRow--; diff --git a/cockatrice/src/window_sets.h b/cockatrice/src/window_sets.h index bf02428d..99a6f1a7 100644 --- a/cockatrice/src/window_sets.h +++ b/cockatrice/src/window_sets.h @@ -4,11 +4,13 @@ #include #include #include +#include #include #include class SetsModel; class SetsProxyModel; +class SetsDisplayModel; class QPushButton; class CardDatabase; class QItemSelection; @@ -19,14 +21,20 @@ class WndSets : public QMainWindow Q_OBJECT private: SetsModel *model; + SetsDisplayModel *displayModel; QTreeView *view; QPushButton *toggleAllButton, *toggleSelectedButton; QPushButton *enableAllButton, *disableAllButton, *enableSomeButton, *disableSomeButton; + QPushButton *defaultSortButton; QAction *aUp, *aDown, *aBottom, *aTop; QToolBar *setsEditToolBar; QDialogButtonBox *buttonBox; - QLabel *labNotes; + QLabel *labNotes, *searchLabel, *sortWarning; + QLineEdit *searchField; QGridLayout *mainLayout; + QHBoxLayout *filterBox; + int sortIndex; + Qt::SortOrder sortOrder; void rebuildMainLayout(int actionToTake); enum { @@ -52,6 +60,10 @@ private slots: void actTop(); void actBottom(); void actToggleButtons(const QItemSelection &selected, const QItemSelection &deselected); + void actDisableSortButtons(int index); + void actRestoreOriginalOrder(); + void actDisableResetButton(const QString &filterText); + void actSort(int index); }; #endif