diff --git a/cockatrice/src/filterlist.cpp b/cockatrice/src/filterlist.cpp index eaae7d1c..9a4b3a71 100644 --- a/cockatrice/src/filterlist.cpp +++ b/cockatrice/src/filterlist.cpp @@ -4,17 +4,48 @@ #include -LogicMap::~LogicMap() +template +FilterListNode *FilterListInnerNode::nodeAt(int i) const { - while(!isEmpty()) - delete takeFirst(); + return ((childNodes.size() > i)? childNodes.at(i) : NULL); +} + +template +void FilterListInnerNode::deleteAt(int i) +{ + preRemoveChild(this, i); + delete childNodes.takeAt(i); + postRemoveChild(this, i); + nodeChanged(); +} + +template +int FilterListInnerNode::childIndex(const FilterListNode *node) const +{ + FilterListNode *unconst; + T downcasted; + + /* to do the dynamic cast to T we will lose const'ness, but we can + * trust QList::indexOf */ + unconst = (FilterListNode *) node; + downcasted = dynamic_cast(unconst); + if(downcasted == NULL) + return -1; + return childNodes.indexOf(downcasted); +} + +template +FilterListInnerNode::~FilterListInnerNode() +{ + while(!childNodes.isEmpty()) + delete childNodes.takeFirst(); } const FilterItemList *LogicMap::findTypeList(CardFilter::Type type) const { - LogicMap::const_iterator i; + QList::const_iterator i; - for(i = constBegin(); i != constEnd(); i++) + for(i = childNodes.constBegin(); i != childNodes.constEnd(); i++) if ((*i)->type == type) return *i; @@ -23,19 +54,20 @@ const FilterItemList *LogicMap::findTypeList(CardFilter::Type type) const FilterItemList *LogicMap::typeList(CardFilter::Type type) { - LogicMap::iterator i; + QList::iterator i; int count; count = 0; - for(i = begin(); i != end(); i++) { + for(i = childNodes.begin(); i != childNodes.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); + if (i == childNodes.end()) { + preInsertChild(this, count); + i = childNodes.insert(i, new FilterItemList(type, this)); + postInsertChild(this, count); + nodeChanged(); } return *i; @@ -46,142 +78,81 @@ FilterListNode *LogicMap::parent() const return p; } -FilterListNode *LogicMap::nodeAt(int i) const +int FilterItemList::termIndex(const QString &term) 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) + for(i = 0; i < childNodes.count(); i++) + if((childNodes.at(i))->term == term) return i; return -1; } -int FilterList::findTermIndex(const CardFilter *f) +FilterListNode *FilterItemList::termNode(const QString &term) { - 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; + FilterItem *fi; - fis = attrTypeList(attr, type); - i = findTermIndex(attr, type, term); + i = termIndex(term); if(i < 0) { - fi = new FilterItem(term, fis); - count = fis->childCount(); - preInsertChild(fis, count); - fis->append(fi); - postInsertChild(fis, count); + fi = new FilterItem(term, this); + count = childNodes.count(); + preInsertChild(this, count); + childNodes.append(fi); + postInsertChild(this, count); + nodeChanged(); return fi; } - return fis->at(i); + return childNodes.at(i); } -FilterListNode *FilterList::termNode(const CardFilter *f) +bool FilterItemList::testTypeAnd(const CardInfo *info, CardFilter::Attr attr) const { - return termNode(f->attr(), f->type(), f->term()); + QList::const_iterator i; + + for(i = childNodes.constBegin(); i != childNodes.constEnd(); i++) + if (!(*i)->acceptCardAttr(info, attr)) + return false; + + return true; } -FilterListNode *FilterList::attrTypeNode(CardFilter::Attr attr, - CardFilter::Type type) +bool FilterItemList::testTypeAndNot(const CardInfo *info, CardFilter::Attr attr) const { - return attrTypeList(attr, type); + // if any one in the list is true, return false + return !testTypeOr(info, attr); } -int FilterList::count(CardFilter::Attr attr, CardFilter::Type type) +bool FilterItemList::testTypeOr(const CardInfo *info, CardFilter::Attr attr) const { - return attrTypeList(attr, type)->count(); + QList::const_iterator i; + + for(i = childNodes.constBegin(); i != childNodes.constEnd(); i++) + if ((*i)->acceptCardAttr(info, attr)) + return true; + + return false; } -int FilterList::count(const CardFilter *f) +bool FilterItemList::testTypeOrNot(const CardInfo *info, CardFilter::Attr attr) const { - return count(f->attr(), f->type()); + // if any one in the list is false, return true + return !testTypeAnd(info, attr); } -bool FilterList::acceptName(const CardInfo *info, const QString &term) const +bool FilterItem::acceptName(const CardInfo *info) const { return info->getName().contains(term, Qt::CaseInsensitive); } -bool FilterList::acceptType(const CardInfo *info, const QString &term) const +bool FilterItem::acceptType(const CardInfo *info) const { return info->getCardType().contains(term, Qt::CaseInsensitive); } -bool FilterList::acceptColor(const CardInfo *info, const QString &term) const +bool FilterItem::acceptColor(const CardInfo *info) const { QStringList::const_iterator i; bool status; @@ -196,12 +167,12 @@ bool FilterList::acceptColor(const CardInfo *info, const QString &term) const return status; } -bool FilterList::acceptText(const CardInfo *info, const QString &term) const +bool FilterItem::acceptText(const CardInfo *info) const { return info->getText().contains(term, Qt::CaseInsensitive); } -bool FilterList::acceptSet(const CardInfo *info, const QString &term) const +bool FilterItem::acceptSet(const CardInfo *info) const { SetList::const_iterator i; bool status; @@ -217,34 +188,36 @@ bool FilterList::acceptSet(const CardInfo *info, const QString &term) const return status; } -bool FilterList::acceptManaCost(const CardInfo *info, const QString &term) const +bool FilterItem::acceptManaCost(const CardInfo *info) const { return (info->getManaCost() == term); } -bool FilterList::acceptCardAttr(const CardInfo *info, const QString &term, - CardFilter::Attr attr) const +bool FilterItem::acceptCardAttr(const CardInfo *info, CardFilter::Attr attr) const { bool status; + if(!isEnabled()) + return true; + switch(attr) { case CardFilter::AttrName: - status = acceptName(info, term); + status = acceptName(info); break; case CardFilter::AttrType: - status = acceptType(info, term); + status = acceptType(info); break; case CardFilter::AttrColor: - status = acceptColor(info, term); + status = acceptColor(info); break; case CardFilter::AttrText: - status = acceptText(info, term); + status = acceptText(info); break; case CardFilter::AttrSet: - status = acceptSet(info, term); + status = acceptSet(info); break; case CardFilter::AttrManaCost: - status = acceptManaCost(info, term); + status = acceptManaCost(info); break; default: status = true; /* ignore this attribute */ @@ -253,84 +226,104 @@ bool FilterList::acceptCardAttr(const CardInfo *info, const QString &term, return status; } -bool FilterList::testTypeAnd(const CardInfo *info, CardFilter::Attr attr, - const FilterItemList *fil) const +/* need to define these here to make QT happy, otherwise + * moc doesnt find some of the FilterListInnerNode symbols. + */ +FilterList::FilterList() {} +FilterList::~FilterList() {} + +LogicMap *FilterList::attrLogicMap(CardFilter::Attr attr) { - FilterItemList::const_iterator i; + QList::iterator i; + int count; - for(i = fil->constBegin(); i != fil->constEnd(); i++) - if(!acceptCardAttr(info, (*i)->term, attr)) - return false; + count = 0; + for(i = childNodes.begin(); i != childNodes.end(); i++) { + if((*i)->attr == attr) + break; + count++; + } - return true; + if(i == childNodes.end()) { + preInsertChild(this, count); + i = childNodes.insert(i, new LogicMap(attr, this)); + postInsertChild(this, count); + nodeChanged(); + } + + return *i; } -bool FilterList::testTypeAndNot(const CardInfo *info, CardFilter::Attr attr, - const FilterItemList *fil) const +FilterItemList *FilterList::attrTypeList(CardFilter::Attr attr, + CardFilter::Type type) { - FilterItemList::const_iterator i; - - for(i = fil->constBegin(); i != fil->constEnd(); i++) - if(acceptCardAttr(info, (*i)->term, attr)) - return false; - - return true; + return attrLogicMap(attr)->typeList(type); } -bool FilterList::testTypeOr(const CardInfo *info, CardFilter::Attr attr, - const FilterItemList *filOr, - const FilterItemList *filOrNot) const +int FilterList::findTermIndex(CardFilter::Attr attr, CardFilter::Type type, + const QString &term) { - FilterItemList::const_iterator i; - bool status; + attrTypeList(attr, type)->termIndex(term); +} - if(filOr == NULL && filOrNot == NULL) - return true; +int FilterList::findTermIndex(const CardFilter *f) +{ + return findTermIndex(f->attr(), f->type(), f->term()); +} - status = false; - if (filOr != NULL) - for(i = filOr->constBegin(); i != filOr->constEnd(); i++) - if(acceptCardAttr(info, (*i)->term, attr)) { - status = true; - break; - } - if (status != true && filOrNot != NULL) - for(i = filOrNot->constBegin(); i != filOrNot->constEnd(); i++) - if(!acceptCardAttr(info, (*i)->term, attr)) { - status = true; - break; - } +FilterListNode *FilterList::termNode(CardFilter::Attr attr, CardFilter::Type type, + const QString &term) +{ + return attrTypeList(attr, type)->termNode(term); +} - return status; +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); } bool FilterList::testAttr(const CardInfo *info, const LogicMap *lm) const { + const FilterItemList *fil; bool status; - const FilterItemList *fil, *fil2; + + status = true; fil = lm->findTypeList(CardFilter::TypeAnd); - if (fil != NULL && !testTypeAnd(info, lm->attr, fil)) + if (fil != NULL && fil->isEnabled() && !fil->testTypeAnd(info, lm->attr)) return false; fil = lm->findTypeList(CardFilter::TypeAndNot); - if (fil != NULL && !testTypeAndNot(info, lm->attr, fil)) + if (fil != NULL && fil->isEnabled() && !fil->testTypeAndNot(info, lm->attr)) return false; fil = lm->findTypeList(CardFilter::TypeOr); - fil2 = lm->findTypeList(CardFilter::TypeOrNot); - if (!testTypeOr(info, lm->attr, fil, fil2)) - return false; + if (fil != NULL && fil->isEnabled()) { + status = false; + // if this is true we can return because it is OR'd with the OrNot list + if (fil->testTypeOr(info, lm->attr)) + return true; + } - return true; + fil = lm->findTypeList(CardFilter::TypeOrNot); + if (fil != NULL && fil->isEnabled() && fil->testTypeOrNot(info, lm->attr)) + return true; + + return status; } bool FilterList::acceptsCard(const CardInfo *info) const { QList::const_iterator i; - for(i = logicAttrs.constBegin(); i != logicAttrs.constEnd(); i++) - if(!testAttr(info, *i)) + for(i = childNodes.constBegin(); i != childNodes.constEnd(); i++) + if ((*i)->isEnabled() && !testAttr(info, *i)) return false; return true; diff --git a/cockatrice/src/filterlist.h b/cockatrice/src/filterlist.h index 98b885bc..20f78984 100644 --- a/cockatrice/src/filterlist.h +++ b/cockatrice/src/filterlist.h @@ -15,45 +15,71 @@ private: public: FilterListNode() : enabled(true) {} virtual bool isEnabled() const { return enabled; } - virtual void enable() { enabled = true; } - virtual void disable() { enabled = false; } + virtual void enable() { enabled = true; nodeChanged(); } + virtual void disable() { enabled = false; nodeChanged(); } 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 int childIndex(const FilterListNode *node) const { return -1; } + virtual int index() const { return (parent() != NULL)? parent()->childIndex(this) : -1; } virtual QString text() const { return ""; } virtual bool isLeaf() const { return false; } virtual const char *textCStr() const { return text().toStdString().c_str(); } + virtual void nodeChanged() const { + printf("%s -> ", textCStr()); + if (parent() != NULL) parent()->nodeChanged(); + } + virtual void preInsertChild(const FilterListNode *p, int i) const { + //printf("%s -> ", textCStr()); + if (parent() != NULL) parent()->preInsertChild(p, i); + } + virtual void postInsertChild(const FilterListNode *p, int i) const { + //printf("%s -> ", textCStr()); + if (parent() != NULL) parent()->postInsertChild(p, i); + } + virtual void preRemoveChild(const FilterListNode *p, int i) const { + printf("%s -> ", textCStr()); + if (parent() != NULL) parent()->preRemoveChild(p, i); + } + virtual void postRemoveChild(const FilterListNode *p, int i) const { + printf("%s -> ", textCStr()); + if (parent() != NULL) parent()->postRemoveChild(p, i); + } +}; + +template +class FilterListInnerNode : public FilterListNode { +protected: + QList childNodes; +public: + ~FilterListInnerNode(); + FilterListNode *nodeAt(int i) const; + void deleteAt(int i); + int childCount() const { return childNodes.size(); } + int childIndex(const FilterListNode *node) const; }; class FilterItemList; class FilterList; -class LogicMap - : public QList - , public FilterListNode { +class LogicMap : public FilterListInnerNode { + private: FilterList *const p; + public: const CardFilter::Attr attr; LogicMap(CardFilter::Attr a, FilterList *parent) : attr(a), p(parent) {} - ~LogicMap(); const FilterItemList *findTypeList(CardFilter::Type type) const; 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)); } + FilterListNode *parent() const; + QString text() const { return QString(CardFilter::attrName(attr)); } }; class FilterItem; -class FilterItemList - : public QList - , public FilterListNode { +class FilterItemList : public FilterListInnerNode { private: LogicMap *const p; public: @@ -61,14 +87,16 @@ public: 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)); } + FilterListNode *parent() const { return p; } + int termIndex(const QString &term) const; + FilterListNode *termNode(const QString &term); + QString text() const { return QString(CardFilter::typeName(type)); } + + bool testTypeAnd(const CardInfo *info, CardFilter::Attr attr) const; + bool testTypeAndNot(const CardInfo *info, CardFilter::Attr attr) const; + bool testTypeOr(const CardInfo *info, CardFilter::Attr attr) const; + bool testTypeOrNot(const CardInfo *info, CardFilter::Attr attr) const; }; class FilterItem : public FilterListNode { @@ -82,48 +110,38 @@ public: 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; } + FilterListNode *parent() const { return p; } + QString text() const { return term; } + bool isLeaf() const { return true; } + + bool acceptName(const CardInfo *info) const; + bool acceptType(const CardInfo *info) const; + bool acceptColor(const CardInfo *info) const; + bool acceptText(const CardInfo *info) const; + bool acceptSet(const CardInfo *info) const; + bool acceptManaCost(const CardInfo *info) const; + bool acceptCardAttr(const CardInfo *info, CardFilter::Attr attr) const; }; -class FilterList : public QObject, public FilterListNode { +class FilterList : public QObject, public FilterListInnerNode { Q_OBJECT signals: void preInsertRow(const FilterListNode *parent, int i) const; void postInsertRow(const FilterListNode *parent, int i) const; + void preRemoveRow(const FilterListNode *parent, int i) const; + void postRemoveRow(const FilterListNode *parent, int i) const; void changed() const; private: - QList logicAttrs; - LogicMap *attrLogicMap(CardFilter::Attr attr); FilterItemList *attrTypeList(CardFilter::Attr attr, CardFilter::Type type); - bool acceptName(const CardInfo *info, const QString &term) const; - bool acceptType(const CardInfo *info, const QString &term) const; - bool acceptColor(const CardInfo *info, const QString &term) const; - bool acceptCardAttr(const CardInfo *info, const QString &term, - CardFilter::Attr attr) const; - bool acceptText(const CardInfo *info, const QString &term) const; - bool acceptSet(const CardInfo *info, const QString &term) const; - bool acceptManaCost(const CardInfo *info, const QString &term) const; - - bool testTypeAnd(const CardInfo *info, CardFilter::Attr attr, - const FilterItemList *fil) const; - bool testTypeAndNot(const CardInfo *info, CardFilter::Attr attr, - const FilterItemList *fil) const; - bool testTypeOr(const CardInfo *info, CardFilter::Attr attr, - const FilterItemList *filOr, - const FilterItemList *filOrNot) const; - bool testAttr(const CardInfo *info, const LogicMap *lm) const; public: + FilterList(); ~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); @@ -132,16 +150,14 @@ public: 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; } + QString text() const { return QString("root"); } + int index() const { return 0; } + + void nodeChanged() const { printf("root\n"); emit changed(); } void preInsertChild(const FilterListNode *p, int i) const { emit preInsertRow(p, i); } - void postInsertChild(const FilterListNode *p, int i) const { emit postInsertRow(p, i); emit changed(); } - void emitChanged() const { emit changed(); } + void postInsertChild(const FilterListNode *p, int i) const { emit postInsertRow(p, i); } + void preRemoveChild(const FilterListNode *p, int i) const { printf("root\n"); emit preRemoveRow(p, i); } + void postRemoveChild(const FilterListNode *p, int i) const { printf("root\n"); emit postRemoveRow(p, i); } bool acceptsCard(const CardInfo *info) const; }; diff --git a/cockatrice/src/filterlistmodel.cpp b/cockatrice/src/filterlistmodel.cpp index a6f2404b..2185ff5c 100644 --- a/cockatrice/src/filterlistmodel.cpp +++ b/cockatrice/src/filterlistmodel.cpp @@ -13,6 +13,12 @@ FilterListModel::FilterListModel(QObject *parent) connect(fList, SIGNAL(postInsertRow(const FilterListNode *, int)), this, SLOT(proxyEndInsertRow(const FilterListNode *, int))); + connect(fList, + SIGNAL(preRemoveRow(const FilterListNode *, int)), + this, SLOT(proxyBeginRemoveRow(const FilterListNode *, int))); + connect(fList, + SIGNAL(postRemoveRow(const FilterListNode *, int)), + this, SLOT(proxyEndRemoveRow(const FilterListNode *, int))); } FilterListModel::~FilterListModel() @@ -38,6 +44,24 @@ void FilterListModel::proxyEndInsertRow(const FilterListNode *node, int) endInsertRows(); } +void FilterListModel::proxyBeginRemoveRow(const FilterListNode *node, int i) +{ + int idx; + + idx = node->index(); + if(idx >= 0) + beginRemoveRows(createIndex(idx, 0, (void *) node), i, i); +} + +void FilterListModel::proxyEndRemoveRow(const FilterListNode *node, int) +{ + int idx; + + idx = node->index(); + if(idx >= 0) + endRemoveRows(); +} + FilterListNode *FilterListModel::indexToNode(const QModelIndex &idx) const { void *ip; @@ -235,11 +259,13 @@ bool FilterListModel::removeRows(int row, int count, const QModelIndex & parent) if(node == NULL || last >= node->childCount()) return false; - beginRemoveRows(parent, row, last); - for(i = 0; i < count; i++) + printf("delete children in %s\n", node->textCStr()); + fflush(stdout); + for(i = 0; i < count; i++) { + printf(" delete %d\n", i); + fflush(stdout); node->deleteAt(row); - endRemoveRows(); - fList->emitChanged(); + } if(node != fList && node->childCount() < 1) return removeRow(parent.row(), parent.parent()); diff --git a/cockatrice/src/filterlistmodel.h b/cockatrice/src/filterlistmodel.h index 944bb5b7..73cdb7e9 100644 --- a/cockatrice/src/filterlistmodel.h +++ b/cockatrice/src/filterlistmodel.h @@ -17,7 +17,9 @@ public slots: private slots: void proxyBeginInsertRow(const FilterListNode *, int); - void proxyEndInsertRow(const FilterListNode *node, int i); + void proxyEndInsertRow(const FilterListNode *, int); + void proxyBeginRemoveRow(const FilterListNode *, int); + void proxyEndRemoveRow(const FilterListNode *, int); private: FilterListNode *indexToNode(const QModelIndex &idx) const;