From 863e437d4c8387c4d98aaf6e4a121aec6c7a776c Mon Sep 17 00:00:00 2001 From: sylvanbasilisk Date: Fri, 17 Jan 2014 10:06:45 +0000 Subject: [PATCH] added filter builder widget and filter tree filter builder takes filter options from user, then adds completed filters to the filter tree. the filter tree does not currently do anything. in the future it will filter the cards in the database view. --- cockatrice/CMakeLists.txt | 8 + cockatrice/src/cardfilter.cpp | 31 ++++ cockatrice/src/cardfilter.h | 39 +++++ cockatrice/src/cardinfowidget.cpp | 4 - cockatrice/src/filterbuilder.cpp | 83 ++++++++++ cockatrice/src/filterbuilder.h | 37 +++++ cockatrice/src/filterlist.cpp | 160 +++++++++++++++++++ cockatrice/src/filterlist.h | 123 ++++++++++++++ cockatrice/src/filterlistmodel.cpp | 247 +++++++++++++++++++++++++++++ cockatrice/src/filterlistmodel.h | 41 +++++ cockatrice/src/tab_deck_editor.cpp | 95 ++++++++--- cockatrice/src/tab_deck_editor.h | 5 + 12 files changed, 847 insertions(+), 26 deletions(-) create mode 100644 cockatrice/src/cardfilter.cpp create mode 100644 cockatrice/src/cardfilter.h create mode 100644 cockatrice/src/filterbuilder.cpp create mode 100644 cockatrice/src/filterbuilder.h create mode 100644 cockatrice/src/filterlist.cpp create mode 100644 cockatrice/src/filterlist.h create mode 100644 cockatrice/src/filterlistmodel.cpp create mode 100644 cockatrice/src/filterlistmodel.h diff --git a/cockatrice/CMakeLists.txt b/cockatrice/CMakeLists.txt index 50e7eba8..97f771a9 100644 --- a/cockatrice/CMakeLists.txt +++ b/cockatrice/CMakeLists.txt @@ -34,6 +34,10 @@ SET(cockatrice_SOURCES src/dlg_load_remote_deck.cpp src/cardinfowidget.cpp src/cardframe.cpp + src/filterbuilder.cpp + src/cardfilter.cpp + src/filterlistmodel.cpp + src/filterlist.cpp src/messagelogwidget.cpp src/zoneviewzone.cpp src/zoneviewwidget.cpp @@ -112,6 +116,10 @@ SET(cockatrice_HEADERS src/dlg_load_remote_deck.h src/cardinfowidget.h src/cardframe.h + src/filterbuilder.h + src/cardfilter.h + src/filterlistmodel.h + src/filterlist.h src/messagelogwidget.h src/zoneviewzone.h src/zoneviewwidget.h diff --git a/cockatrice/src/cardfilter.cpp b/cockatrice/src/cardfilter.cpp new file mode 100644 index 00000000..d6fe790e --- /dev/null +++ b/cockatrice/src/cardfilter.cpp @@ -0,0 +1,31 @@ +#include "cardfilter.h" + +const char *CardFilter::typeName(Type t) +{ + switch(t) { + case TypeAnd: + return "and"; + case TypeOr: + return "or"; + case TypeAndNot: + return "and not"; + case TypeOrNot: + return "or not"; + default: + return ""; + } +} + +const char *CardFilter::attrName(Attr a) +{ + switch(a) { + case AttrName: + return "name"; + case AttrType: + return "type"; + case AttrColor: + return "color"; + default: + return ""; + } +} diff --git a/cockatrice/src/cardfilter.h b/cockatrice/src/cardfilter.h new file mode 100644 index 00000000..67395c2d --- /dev/null +++ b/cockatrice/src/cardfilter.h @@ -0,0 +1,39 @@ +#ifndef CARDFILTER_H +#define CARDFILTER_H + +#include + +class CardFilter { +public: + enum Type { + TypeAnd = 0, + TypeOr, + TypeAndNot, + TypeOrNot, + TypeEnd + }; + + enum Attr { + AttrName = 0, + AttrType, + AttrColor, + AttrEnd + }; + +private: + enum Type t; + enum Attr a; + QString trm; + +public: + CardFilter(QString term, Type type, Attr attr) : trm(term), t(type), a(attr) {}; + + Type type() const { return t; } + const QString &term() const { return trm; } + Attr attr() const { return a; } + + static const char *typeName(Type t); + static const char *attrName(Attr a); +}; + +#endif diff --git a/cockatrice/src/cardinfowidget.cpp b/cockatrice/src/cardinfowidget.cpp index 61b35453..708da01c 100644 --- a/cockatrice/src/cardinfowidget.cpp +++ b/cockatrice/src/cardinfowidget.cpp @@ -69,10 +69,6 @@ CardInfoWidget::CardInfoWidget(ResizeMode _mode, const QString &cardName, QWidge grid->addWidget(textLabel, row, 0, -1, 2); grid->setRowStretch(row, 1); grid->setColumnStretch(1, 1); - } else { - /*grid->addWidget(cardPicture, 0, 0); - grid->setRowStretch(0, 1); - grid->setColumnStretch(0, 1);*/ } retranslateUi(); diff --git a/cockatrice/src/filterbuilder.cpp b/cockatrice/src/filterbuilder.cpp new file mode 100644 index 00000000..53b93144 --- /dev/null +++ b/cockatrice/src/filterbuilder.cpp @@ -0,0 +1,83 @@ +#include "filterbuilder.h" + +#include +#include +#include +#include + +#include "cardfilter.h" + +FilterBuilder::FilterBuilder(QWidget *parent) + : QFrame(parent) +{ + int i; + + QVBoxLayout *layout = new QVBoxLayout; + QHBoxLayout *addFilter = new QHBoxLayout; + + filterCombo = new QComboBox; + for(i = 0; i < CardFilter::AttrEnd; i++) + filterCombo->addItem( + CardFilter::attrName(static_cast(i)), QVariant(i)); + + typeCombo = new QComboBox; + for(i = 0; i < CardFilter::TypeEnd; i++) + typeCombo->addItem( + CardFilter::typeName(static_cast(i)), QVariant(i)); + + QPushButton *ok = new QPushButton("+"); + ok->setMaximumSize(20, 20); + + addFilter->addWidget(ok); + addFilter->addWidget(typeCombo); + addFilter->addWidget(filterCombo, Qt::AlignLeft); + + edit = new QLineEdit; + edit->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + layout->addLayout(addFilter); + layout->addWidget(edit); + + setFrameStyle(QFrame::Plain | QFrame::Box); + layout->setAlignment(Qt::AlignTop); + setLayout(layout); + + connect(ok, SIGNAL(released()), this, SLOT(add_released())); + fltr = NULL; +} + +FilterBuilder::~FilterBuilder() +{ + destroyFilter(); +} + +void FilterBuilder::destroyFilter() +{ + if(fltr) + delete fltr; +} + +static int comboCurrentIntData(const QComboBox *combo) +{ + return combo->itemData(combo->currentIndex()).toInt(); +} + +void FilterBuilder::add_released() +{ + QString txt; + + txt = edit->text(); + if(txt.length() < 1) + return; + + destroyFilter(); + fltr = new CardFilter(txt, + static_cast(comboCurrentIntData(typeCombo)), + static_cast(comboCurrentIntData(filterCombo))); + emit add(fltr); +} + +bool FilterBuilder::filter(const CardFilter *f) const +{ + f = fltr; + return false; +} diff --git a/cockatrice/src/filterbuilder.h b/cockatrice/src/filterbuilder.h new file mode 100644 index 00000000..2762ba28 --- /dev/null +++ b/cockatrice/src/filterbuilder.h @@ -0,0 +1,37 @@ +#ifndef FILTERBUILDER_H +#define FILTERBUILDER_H + +#include + +class QCheckBox; +class QComboBox; +class QLineEdit; +class CardFilter; + +class FilterBuilder : public QFrame { + Q_OBJECT + +private: + QComboBox *typeCombo; + QComboBox *filterCombo; + QLineEdit *edit; + CardFilter *fltr; + + void destroyFilter(); + +public: + FilterBuilder(QWidget *parent = 0); + ~FilterBuilder(); + + bool filter(const CardFilter *f) const; + +signals: + void add(const CardFilter *f); + +public slots: +private slots: + void add_released(); +protected: +}; + +#endif diff --git a/cockatrice/src/filterlist.cpp b/cockatrice/src/filterlist.cpp new file mode 100644 index 00000000..35d7a0fc --- /dev/null +++ b/cockatrice/src/filterlist.cpp @@ -0,0 +1,160 @@ +#include "filterlist.h" +#include "CardFilter.h" + +#include + +LogicMap::~LogicMap() +{ + while(!isEmpty()) + delete takeFirst(); +} + +FilterItemList *LogicMap::typeList(CardFilter::Type type) +{ + LogicMap::iterator i; + int count; + + count = 0; + for(i = begin(); i != end(); i++) { + if ((*i)->type == type) + break; + count++; + } + if (i == end()) { + p->preInsertChild(this, count); + i = insert(i, new FilterItemList(type, this)); + p->postInsertChild(this, count); + } + + return *i; +} + +FilterListNode *LogicMap::parent() const +{ + return p; +} + +FilterListNode *LogicMap::nodeAt(int i) const +{ + return ((size() > i)? at(i) : NULL); +} + +void LogicMap::deleteAt(int i) +{ + delete takeAt(i); +} + +int LogicMap::index() const +{ + return p->indexOf(this); +} + +FilterListNode *FilterItemList::nodeAt(int i) const +{ + return ((size() > i)? at(i) : NULL); +} + +void FilterItemList::deleteAt(int i) { + delete takeAt(i); +} + +FilterItemList::~FilterItemList() +{ + while(!isEmpty()) + delete takeFirst(); +} + +FilterList::~FilterList() +{ + while(!logicAttrs.isEmpty()) { + delete logicAttrs.takeFirst(); + } +} + +LogicMap *FilterList::attrLogicMap(CardFilter::Attr attr) +{ + QList::iterator i; + int count; + + count = 0; + for(i = logicAttrs.begin(); i != logicAttrs.end(); i++) { + if((*i)->attr == attr) + break; + count++; + } + + if(i == logicAttrs.end()) { + preInsertChild(this, count); + i = logicAttrs.insert(i, new LogicMap(attr, this)); + postInsertChild(this, count); + } + + return *i; +} + +FilterItemList *FilterList::attrTypeList(CardFilter::Attr attr, + CardFilter::Type type) +{ + return attrLogicMap(attr)->typeList(type); +} + +int FilterList::findTermIndex(CardFilter::Attr attr, CardFilter::Type type, + const QString &term) +{ + FilterItemList *fis; + int i; + + fis = attrTypeList(attr, type); + for(i = 0; i < fis->count(); i++) + if((fis->at(i))->term == term) + return i; + + return -1; +} + +int FilterList::findTermIndex(const CardFilter *f) +{ + return findTermIndex(f->attr(), f->type(), f->term()); +} + +FilterListNode *FilterList::termNode(CardFilter::Attr attr, CardFilter::Type type, + const QString &term) +{ + FilterItemList *fis; + FilterItem *fi; + int i, count; + + fis = attrTypeList(attr, type); + i = findTermIndex(attr, type, term); + if(i < 0) { + fi = new FilterItem(term, fis); + count = fis->childCount(); + preInsertChild(fis, count); + fis->append(fi); + postInsertChild(fis, count); + return fi; + } + + return fis->at(i); +} + +FilterListNode *FilterList::termNode(const CardFilter *f) +{ + return termNode(f->attr(), f->type(), f->term()); +} + +FilterListNode *FilterList::attrTypeNode(CardFilter::Attr attr, + CardFilter::Type type) +{ + return attrTypeList(attr, type); +} + +int FilterList::count(CardFilter::Attr attr, CardFilter::Type type) +{ + return attrTypeList(attr, type)->count(); +} + +int FilterList::count(const CardFilter *f) +{ + return count(f->attr(), f->type()); +} diff --git a/cockatrice/src/filterlist.h b/cockatrice/src/filterlist.h new file mode 100644 index 00000000..aed58f7d --- /dev/null +++ b/cockatrice/src/filterlist.h @@ -0,0 +1,123 @@ +#ifndef FILTERLIST_H +#define FILTERLIST_H + +#include +#include +#include + +#include "cardfilter.h" + +class FilterListNode { +private: + bool enabled; +public: + FilterListNode() : enabled(true) {} + virtual bool isEnabled() const { return enabled; } + virtual void enable() { enabled = true; } + virtual void disable() { enabled = false; } + virtual FilterListNode *parent() const { return NULL; } + virtual FilterListNode *nodeAt(int i) const { return NULL; } + virtual void deleteAt(int i) {} + virtual int childCount() const { return 0; } + virtual int index() const { return -1; } + virtual QString text() const { return ""; } + virtual bool isLeaf() const { return false; } + virtual const char *textCStr() const { return text().toStdString().c_str(); } +}; + +class FilterItemList; +class FilterList; +class LogicMap + : public QList + , public FilterListNode { +private: + FilterList *const p; +public: + const CardFilter::Attr attr; + + LogicMap(CardFilter::Attr a, FilterList *parent) + : attr(a), p(parent) {} + ~LogicMap(); + FilterItemList *typeList(CardFilter::Type type); + virtual FilterListNode *parent() const; + virtual FilterListNode *nodeAt(int i) const; + virtual void deleteAt(int i); + virtual int childCount() const { return size(); } + virtual int index() const; + virtual QString text() const { return QString(CardFilter::attrName(attr)); } +}; + +class FilterItem; +class FilterItemList + : public QList + , public FilterListNode { +private: + LogicMap *const p; +public: + const CardFilter::Type type; + FilterItemList(CardFilter::Type t, LogicMap *parent) + : type(t), p(parent) {} + ~FilterItemList(); + CardFilter::Attr attr() const { return p->attr; } + virtual FilterListNode *parent() const { return p; } + virtual FilterListNode *nodeAt(int i) const; + virtual void deleteAt(int i); + virtual int childCount() const { return size(); } + virtual int index() const { return p->indexOf((FilterItemList *) this); } + virtual QString text() const { return QString(CardFilter::typeName(type)); } +}; + +class FilterItem : public FilterListNode { +private: + FilterItemList *const p; +public: + const QString term; + + FilterItem(QString trm, FilterItemList *parent) + : p(parent), term(trm) {} + + CardFilter::Attr attr() const { return p->attr(); } + CardFilter::Type type() const { return p->type; } + virtual FilterListNode *parent() const { return p; } + virtual int index() const { return p->indexOf((FilterItem *)this); } + virtual QString text() const { return term; } + virtual bool isLeaf() const { return true; } +}; + +class FilterList : public QObject, public FilterListNode { + Q_OBJECT + +signals: + void preInsertRow(const FilterListNode *parent, int i) const; + void postInsertRow(const FilterListNode *parent, int i) const; + +private: + QList logicAttrs; + + LogicMap *attrLogicMap(CardFilter::Attr attr); + FilterItemList *attrTypeList(CardFilter::Attr attr, + CardFilter::Type type); + +public: + ~FilterList(); + int indexOf(const LogicMap *val) const { return logicAttrs.indexOf((LogicMap *) val); } + int findTermIndex(CardFilter::Attr attr, CardFilter::Type type, + const QString &term); + int findTermIndex(const CardFilter *f); + FilterListNode *termNode(CardFilter::Attr attr, CardFilter::Type type, + const QString &term); + FilterListNode *termNode(const CardFilter *f); + FilterListNode *attrTypeNode(CardFilter::Attr attr, + CardFilter::Type type); + int count(CardFilter::Attr attr, CardFilter::Type type); + int count(const CardFilter *f); + virtual FilterListNode *nodeAt(int i) const { return ((logicAttrs.size() > i)? logicAttrs.at(i) : NULL); } + virtual void deleteAt(int i) { delete logicAttrs.takeAt(i); } + virtual int childCount() const { return logicAttrs.size(); } + virtual QString text() const { return QString("root"); } + virtual int index() const { return 0; } + void preInsertChild(const FilterListNode *p, int i) const { emit preInsertRow(p, i); } + void postInsertChild(const FilterListNode *p, int i) const { emit postInsertRow(p, i); } +}; + +#endif diff --git a/cockatrice/src/filterlistmodel.cpp b/cockatrice/src/filterlistmodel.cpp new file mode 100644 index 00000000..6bd84809 --- /dev/null +++ b/cockatrice/src/filterlistmodel.cpp @@ -0,0 +1,247 @@ +#include +#include "filterlistmodel.h" +#include "filterlist.h" +#include "cardfilter.h" + +FilterListModel::FilterListModel(QObject *parent) + : QAbstractItemModel(parent) +{ + filterList = new FilterList; + connect(filterList, + SIGNAL(preInsertRow(const FilterListNode *, int)), + this, SLOT(proxyBeginInsertRow(const FilterListNode *, int))); + connect(filterList, + SIGNAL(postInsertRow(const FilterListNode *, int)), + this, SLOT(proxyEndInsertRow(const FilterListNode *, int))); +} + +FilterListModel::~FilterListModel() +{ + delete filterList; +} + +void FilterListModel::proxyBeginInsertRow(const FilterListNode *node, int i) +{ + int idx; + + idx = node->index(); + if(idx >= 0) + beginInsertRows(createIndex(idx, 0, (void *) node), i, i); +} + +void FilterListModel::proxyEndInsertRow(const FilterListNode *node, int) +{ + int idx; + + idx = node->index(); + if(idx >= 0) + endInsertRows(); +} + +FilterListNode *FilterListModel::indexToNode(const QModelIndex &idx) const +{ + void *ip; + FilterListNode *node; + + if(!idx.isValid()) + return filterList; + + ip = idx.internalPointer(); + if(ip == NULL) + return filterList; + + node = static_cast(ip); + return node; +} + +void FilterListModel::addFilter(const CardFilter *f) +{ + emit layoutAboutToBeChanged(); + filterList->termNode(f); + emit layoutChanged(); +} + +int FilterListModel::rowCount(const QModelIndex &parent) const +{ + const FilterListNode *node; + int result; + + if(parent.column() > 0) + return 0; + + node = indexToNode(parent); + if(node) + result = node->childCount(); + else + result = 0; + + return result; +} + +int FilterListModel::columnCount(const QModelIndex &/*parent*/) const +{ + return 1; +} + +QVariant FilterListModel::data(const QModelIndex &index, int role) const +{ + const FilterListNode *node; + + if (!index.isValid()) + return QVariant(); + if (index.column() >= columnCount()) + return QVariant(); + + node = indexToNode(index); + if(node == NULL) + return QVariant(); + + switch (role) { + case Qt::FontRole: + if(!node->isLeaf()) { + QFont f; + f.setBold(true); + return f; + } + break; + case Qt::DisplayRole: + case Qt::EditRole: + case Qt::ToolTipRole: + case Qt::StatusTipRole: + case Qt::WhatsThisRole: + return node->text(); + case Qt::CheckStateRole: + if(node->isEnabled()) + return Qt::Checked; + else + return Qt::Unchecked; + default: + return QVariant(); + } + + return QVariant(); +} + +bool FilterListModel::setData(const QModelIndex &index, + const QVariant &value, int role) +{ + FilterListNode *node; + + if (!index.isValid()) + return false; + if (index.column() >= columnCount()) + return false; + if (role != Qt::CheckStateRole ) + return false; + + node = indexToNode(index); + if(node == NULL || node == filterList) + return false; + + Qt::CheckState state = static_cast(value.toInt()); + if(state == Qt::Checked) + node->enable(); + else + node->disable(); + + emit dataChanged(index, index); + return true; +} + +Qt::ItemFlags FilterListModel::flags(const QModelIndex &index) const +{ + const FilterListNode *node; + Qt::ItemFlags result; + + if (!index.isValid()) + return 0; + + node = indexToNode(index); + if(node == NULL) + return 0; + + result = Qt::ItemIsEnabled; + if(node == filterList) + return result; + + result |= Qt::ItemIsSelectable; + result |= Qt::ItemIsUserCheckable; + + return result; +} + +QModelIndex FilterListModel::nodeIndex(const FilterListNode *node, int row, int column) const +{ + FilterListNode *child; + + if (column > 0 || row >= node->childCount()) + return QModelIndex(); + + child = node->nodeAt(row); + return createIndex(row, column, child); +} + +QModelIndex FilterListModel::index(int row, int column, + const QModelIndex &parent) const +{ + const FilterListNode *node; + + if (!hasIndex(row, column, parent)) + return QModelIndex(); + + node = indexToNode(parent); + if(node == NULL) + return QModelIndex(); + + return nodeIndex(node, row, column); +} + +QModelIndex FilterListModel::parent(const QModelIndex &ind) const +{ + const FilterListNode *node; + FilterListNode *parent; + int row; + QModelIndex idx; + + if (!ind.isValid()) + return QModelIndex(); + + node = indexToNode(ind); + if(node == NULL || node == filterList) + return QModelIndex(); + + parent = node->parent(); + if(parent) { + row = parent->index(); + if(row < 0) + return QModelIndex(); + idx = createIndex(row, 0, parent); + return idx; + } + + return QModelIndex(); +} + +bool FilterListModel::removeRows(int row, int count, const QModelIndex & parent) +{ + FilterListNode *node; + int i, last; + + last = row+count-1; + if (!parent.isValid() || count < 1 || row < 0) + return false; + + node = indexToNode(parent); + if(node == NULL || last >= node->childCount()) + return false; + + beginRemoveRows(parent, row, last); + for(i = 0; i < count; i++) + node->deleteAt(row); + endRemoveRows(); + + if(node != filterList && node->childCount() < 1) + return removeRow(parent.row(), parent.parent()); + + return true; +} diff --git a/cockatrice/src/filterlistmodel.h b/cockatrice/src/filterlistmodel.h new file mode 100644 index 00000000..de25f452 --- /dev/null +++ b/cockatrice/src/filterlistmodel.h @@ -0,0 +1,41 @@ +#ifndef FILTERLISTMODEL_H +#define FILTERLISTMODEL_H + +#include + +class FilterList; +class CardFilter; +class FilterListNode; + +class FilterListModel : public QAbstractItemModel { + Q_OBJECT +private: + FilterList *filterList; + +public slots: + void addFilter(const CardFilter *f); + +private slots: + void proxyBeginInsertRow(const FilterListNode *, int); + void proxyEndInsertRow(const FilterListNode *node, int i); + +private: + FilterListNode *indexToNode(const QModelIndex &idx) const; + QModelIndex nodeIndex(const FilterListNode *node, int row, int column) const; + +public: + FilterListModel(QObject *parent = 0); + ~FilterListModel(); + int rowCount(const QModelIndex &parent = QModelIndex()) const; + int columnCount(const QModelIndex &/*parent*/ = QModelIndex()) const; + QVariant data(const QModelIndex &index, int role) const; + bool setData(const QModelIndex &index, const QVariant &value, + int role = Qt::EditRole); + Qt::ItemFlags flags(const QModelIndex &index) const; + QModelIndex parent(const QModelIndex &ind) const; + QModelIndex index(int row, int column, + const QModelIndex &parent) const; + bool removeRows(int row, int count, const QModelIndex & parent); +}; + +#endif diff --git a/cockatrice/src/tab_deck_editor.cpp b/cockatrice/src/tab_deck_editor.cpp index 9ec0cac2..a7aded4c 100644 --- a/cockatrice/src/tab_deck_editor.cpp +++ b/cockatrice/src/tab_deck_editor.cpp @@ -41,10 +41,13 @@ #include #include #include "cardframe.h" +#include "filterbuilder.h" #include "carditem.h" #include "carddatabase.h" #include "main.h" #include "settingscache.h" +#include "filterlistmodel.h" +#include "filterlist.h" void SearchLineEdit::keyPressEvent(QKeyEvent *event) { @@ -131,28 +134,25 @@ TabDeckEditor::TabDeckEditor(TabSupervisor *_tabSupervisor, QWidget *parent) grid->addWidget(nameLabel, 0, 0); grid->addWidget(nameEdit, 0, 1); - /*grid->addWidget(commentsLabel, 1, 0); - grid->addWidget(commentsEdit, 1, 1);*/ - grid->addWidget(hashLabel1, 2, 0); grid->addWidget(hashLabel, 2, 1); - // Update price - aUpdatePrices = new QAction(QString(), this); - aUpdatePrices->setIcon(QIcon(":/resources/icon_update.png")); - connect(aUpdatePrices, SIGNAL(triggered()), this, SLOT(actUpdatePrices())); + // Update price + aUpdatePrices = new QAction(QString(), this); + aUpdatePrices->setIcon(QIcon(":/resources/icon_update.png")); + connect(aUpdatePrices, SIGNAL(triggered()), this, SLOT(actUpdatePrices())); if (!settingsCache->getPriceTagFeature()) aUpdatePrices->setVisible(false); - - QToolBar *deckToolBar = new QToolBar; - deckToolBar->setOrientation(Qt::Vertical); - deckToolBar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); - deckToolBar->setIconSize(QSize(24, 24)); - deckToolBar->addAction(aUpdatePrices); - QHBoxLayout *deckToolbarLayout = new QHBoxLayout; - deckToolbarLayout->addStretch(); - deckToolbarLayout->addWidget(deckToolBar); - deckToolbarLayout->addStretch(); + + QToolBar *deckToolBar = new QToolBar; + deckToolBar->setOrientation(Qt::Vertical); + deckToolBar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + deckToolBar->setIconSize(QSize(24, 24)); + deckToolBar->addAction(aUpdatePrices); + QHBoxLayout *deckToolbarLayout = new QHBoxLayout; + deckToolbarLayout->addStretch(); + deckToolbarLayout->addWidget(deckToolBar); + deckToolbarLayout->addStretch(); QVBoxLayout *deckFrame = new QVBoxLayout; deckFrame->addLayout(grid); @@ -168,7 +168,30 @@ TabDeckEditor::TabDeckEditor(TabSupervisor *_tabSupervisor, QWidget *parent) searchAndButtons->addLayout(verticalToolBarLayout, 0, 0); searchAndButtons->addLayout(searchLayout, 0, 1); botFrame->addLayout(searchAndButtons); - botFrame->addWidget(databaseView); + + filterModel = new FilterListModel(); + filterView = new QTreeView; + filterView->setModel(filterModel); + filterView->setMaximumWidth(250); + filterView->setUniformRowHeights(true); + filterView->setHeaderHidden(true); + filterView->setExpandsOnDoubleClick(false); + filterView->setContextMenuPolicy(Qt::CustomContextMenu); + connect(filterModel, SIGNAL(layoutChanged()), filterView, SLOT(expandAll())); + connect(filterView, SIGNAL(customContextMenuRequested(const QPoint &)), + this, SLOT(filterViewCustomContextMenu(const QPoint &))); + FilterBuilder *filterBuilder = new FilterBuilder; + filterBuilder->setMaximumWidth(250); + connect(filterBuilder, SIGNAL(add(const CardFilter *)), filterModel, SLOT(addFilter(const CardFilter *))); + + QVBoxLayout *filter = new QVBoxLayout; + filter->addWidget(filterBuilder, 0, Qt::AlignTop); + filter->addWidget(filterView); + + QHBoxLayout *dbFrame = new QHBoxLayout; + dbFrame->addLayout(filter); + dbFrame->addWidget(databaseView); + botFrame->addLayout(dbFrame); QVBoxLayout *mainLayout = new QVBoxLayout; mainLayout->addLayout(topFrame, 10); @@ -234,16 +257,16 @@ TabDeckEditor::TabDeckEditor(TabSupervisor *_tabSupervisor, QWidget *parent) aAddCard->setIcon(QIcon(":/resources/arrow_right_green.svg")); connect(aAddCard, SIGNAL(triggered()), this, SLOT(actAddCard())); aAddCardToSideboard = new QAction(QString(), this); - aAddCardToSideboard->setIcon(QIcon(":/resources/add_to_sideboard.svg")); + aAddCardToSideboard->setIcon(QIcon(":/resources/add_to_sideboard.svg")); connect(aAddCardToSideboard, SIGNAL(triggered()), this, SLOT(actAddCardToSideboard())); aRemoveCard = new QAction(QString(), this); - aRemoveCard->setIcon(QIcon(":/resources/remove_row.svg")); + aRemoveCard->setIcon(QIcon(":/resources/remove_row.svg")); connect(aRemoveCard, SIGNAL(triggered()), this, SLOT(actRemoveCard())); aIncrement = new QAction(QString(), this); - aIncrement->setIcon(QIcon(":/resources/increment.svg")); + aIncrement->setIcon(QIcon(":/resources/increment.svg")); connect(aIncrement, SIGNAL(triggered()), this, SLOT(actIncrement())); aDecrement = new QAction(QString(), this); - aDecrement->setIcon(QIcon(":/resources/decrement.svg")); + aDecrement->setIcon(QIcon(":/resources/decrement.svg")); connect(aDecrement, SIGNAL(triggered()), this, SLOT(actDecrement())); verticalToolBar->addAction(aAddCard); @@ -632,3 +655,31 @@ void TabDeckEditor::setModified(bool _modified) modified = _modified; emit tabTextChanged(this, getTabText()); } + +void TabDeckEditor::filterViewCustomContextMenu(const QPoint &point) { + QMenu menu; + QAction *action; + QModelIndex idx; + + idx = filterView->indexAt(point); + if(!idx.isValid()) + return; + + action = menu.addAction(QString("delete")); + action->setData(point); + connect(&menu, SIGNAL(triggered(QAction *)), + this, SLOT(filterRemove(QAction *))); + menu.exec(filterView->mapToGlobal(point)); +} + +void TabDeckEditor::filterRemove(QAction *action) { + QPoint point; + QModelIndex idx; + + point = action->data().toPoint(); + idx = filterView->indexAt(point); + if(!idx.isValid()) + return; + + filterModel->removeRow(idx.row(), idx.parent()); +} diff --git a/cockatrice/src/tab_deck_editor.h b/cockatrice/src/tab_deck_editor.h index 9580aceb..716f6ade 100644 --- a/cockatrice/src/tab_deck_editor.h +++ b/cockatrice/src/tab_deck_editor.h @@ -16,6 +16,7 @@ class DlgCardSearch; class QLabel; class DeckLoader; class Response; +class FilterListModel; class SearchLineEdit : public QLineEdit { private: @@ -61,6 +62,8 @@ private slots: void finishedUpdatingPrices(); void saveDeckRemoteFinished(const Response &r); + void filterViewCustomContextMenu(const QPoint &point); + void filterRemove(QAction *action); private: void addCardHelper(QString zoneName); void recursiveExpand(const QModelIndex &index); @@ -81,6 +84,8 @@ private: QLabel *hashLabel1; QLabel *hashLabel; DlgCardSearch *dlgCardSearch; + FilterListModel *filterModel; + QTreeView *filterView; QMenu *deckMenu, *dbMenu; QAction *aNewDeck, *aLoadDeck, *aSaveDeck, *aSaveDeckAs, *aLoadDeckFromClipboard, *aSaveDeckToClipboard, *aPrintDeck, *aAnalyzeDeck, *aClose;