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;