From 806e9a28880a9379c5bcc4c3a906dbc1538b6a4b Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 22 Aug 2013 13:14:35 +0200 Subject: [PATCH] added and and or filter nodes --- apps/opencs/CMakeLists.txt | 2 +- apps/opencs/model/filter/andnode.cpp | 20 +++++ apps/opencs/model/filter/andnode.hpp | 23 ++++++ apps/opencs/model/filter/narynode.cpp | 31 +++++++- apps/opencs/model/filter/narynode.hpp | 9 ++- apps/opencs/model/filter/ornode.cpp | 20 +++++ apps/opencs/model/filter/ornode.hpp | 23 ++++++ apps/opencs/model/filter/parser.cpp | 82 +++++++++++++++++++++ apps/opencs/model/filter/parser.hpp | 2 + apps/opencs/view/filter/editwidget.cpp | 2 +- apps/opencs/view/filter/editwidget.hpp | 3 +- apps/opencs/view/filter/filterbox.cpp | 4 +- apps/opencs/view/filter/filterbox.hpp | 3 +- apps/opencs/view/filter/recordfilterbox.cpp | 4 +- apps/opencs/view/filter/recordfilterbox.hpp | 3 +- apps/opencs/view/world/tablesubview.cpp | 4 +- 16 files changed, 218 insertions(+), 17 deletions(-) create mode 100644 apps/opencs/model/filter/andnode.cpp create mode 100644 apps/opencs/model/filter/andnode.hpp create mode 100644 apps/opencs/model/filter/ornode.cpp create mode 100644 apps/opencs/model/filter/ornode.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 031c650dfa..9fb6c1be3e 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -108,7 +108,7 @@ opencs_units_noqt (model/settings ) opencs_units_noqt (model/filter - node unarynode narynode leafnode booleannode parser + node unarynode narynode leafnode booleannode parser andnode ornode ) opencs_hdrs_noqt (model/filter diff --git a/apps/opencs/model/filter/andnode.cpp b/apps/opencs/model/filter/andnode.cpp new file mode 100644 index 0000000000..dfaa56e782 --- /dev/null +++ b/apps/opencs/model/filter/andnode.cpp @@ -0,0 +1,20 @@ + +#include "andnode.hpp" + +#include + +CSMFilter::AndNode::AndNode (const std::vector >& nodes) +: NAryNode (nodes, "and") +{} + +bool CSMFilter::AndNode::test (const CSMWorld::IdTable& table, int row, + const std::map& columns) const +{ + int size = getSize(); + + for (int i=0; i >& nodes); + + virtual bool test (const CSMWorld::IdTable& table, int row, + const std::map& columns) const; + ///< \return Can the specified table row pass through to filter? + /// \param columns column ID to column index mapping + }; +} + +#endif diff --git a/apps/opencs/model/filter/narynode.cpp b/apps/opencs/model/filter/narynode.cpp index cc131d8aca..b96e7d4b2e 100644 --- a/apps/opencs/model/filter/narynode.cpp +++ b/apps/opencs/model/filter/narynode.cpp @@ -1,8 +1,11 @@ #include "narynode.hpp" -CSMFilter::NAryNode::NAryNode (const std::vector >& nodes) -: mNodes (nodes) +#include + +CSMFilter::NAryNode::NAryNode (const std::vector >& nodes, + const std::string& name) +: mNodes (nodes), mName (name) {} int CSMFilter::NAryNode::getSize() const @@ -30,6 +33,30 @@ std::vector CSMFilter::NAryNode::getReferencedColumns() const return columns; } +std::string CSMFilter::NAryNode::toString (bool numericColumns) const +{ + std::ostringstream stream; + + stream << mName << " ("; + + bool first = true; + int size = getSize(); + + for (int i=0; i +#include #include @@ -12,10 +13,11 @@ namespace CSMFilter class NAryNode : public Node { std::vector > mNodes; + std::string mName; public: - NAryNode (const std::vector >& nodes); + NAryNode (const std::vector >& nodes, const std::string& name); int getSize() const; @@ -25,6 +27,11 @@ namespace CSMFilter ///< Return a list of the IDs of the columns referenced by this node. The column mapping /// passed into test as columns must contain all columns listed here. + virtual std::string toString (bool numericColumns) const; + ///< Return a string that represents this node. + /// + /// \param numericColumns Use numeric IDs instead of string to represent columns. + virtual bool isSimple() const; ///< \return Can this filter be displayed in simple mode. diff --git a/apps/opencs/model/filter/ornode.cpp b/apps/opencs/model/filter/ornode.cpp new file mode 100644 index 0000000000..4fc34e1d5a --- /dev/null +++ b/apps/opencs/model/filter/ornode.cpp @@ -0,0 +1,20 @@ + +#include "ornode.hpp" + +#include + +CSMFilter::OrNode::OrNode (const std::vector >& nodes) +: NAryNode (nodes, "or") +{} + +bool CSMFilter::OrNode::test (const CSMWorld::IdTable& table, int row, + const std::map& columns) const +{ + int size = getSize(); + + for (int i=0; i >& nodes); + + virtual bool test (const CSMWorld::IdTable& table, int row, + const std::map& columns) const; + ///< \return Can the specified table row pass through to filter? + /// \param columns column ID to column index mapping + }; +} + +#endif diff --git a/apps/opencs/model/filter/parser.cpp b/apps/opencs/model/filter/parser.cpp index 305bf7a7d0..a35c4bdfdf 100644 --- a/apps/opencs/model/filter/parser.cpp +++ b/apps/opencs/model/filter/parser.cpp @@ -8,6 +8,8 @@ #include #include "booleannode.hpp" +#include "ornode.hpp" +#include "andnode.hpp" namespace CSMFilter { @@ -209,12 +211,89 @@ CSMFilter::Token CSMFilter::Parser::getNextToken() boost::shared_ptr CSMFilter::Parser::parseImp() { + if (Token token = getNextToken()) + { + switch (token.mType) + { + case Token::Type_Keyword_True: + return boost::shared_ptr (new BooleanNode (true)); + case Token::Type_Keyword_False: + + return boost::shared_ptr (new BooleanNode (false)); + + case Token::Type_Keyword_And: + case Token::Type_Keyword_Or: + + return parseNAry (token); + + case Token::Type_EOS: + + return boost::shared_ptr(); + + default: + + error(); + } + } return boost::shared_ptr(); } +boost::shared_ptr CSMFilter::Parser::parseNAry (const Token& keyword) +{ + std::vector > nodes; + + Token token = getNextToken(); + + if (!token || token.mType!=Token::Type_Open) + { + error(); + return boost::shared_ptr(); + } + + for (;;) + { + boost::shared_ptr node = parseImp(); + + if (mError) + return boost::shared_ptr(); + + if (!node.get()) + { + error(); + return boost::shared_ptr(); + } + + nodes.push_back (node); + + Token token = getNextToken(); + + if (!token || (token.mType!=Token::Type_Close && token.mType!=Token::Type_Comma)) + { + error(); + return boost::shared_ptr(); + } + + if (token.mType==Token::Type_Close) + break; + } + + if (nodes.empty()) + { + error(); + return boost::shared_ptr(); + } + + switch (keyword.mType) + { + case Token::Type_Keyword_And: return boost::shared_ptr (new AndNode (nodes)); + case Token::Type_Keyword_Or: return boost::shared_ptr (new OrNode (nodes)); + default: error(); return boost::shared_ptr(); + } +} + void CSMFilter::Parser::error() { mError = true; @@ -235,6 +314,9 @@ bool CSMFilter::Parser::parse (const std::string& filter) if (mError) return false; + if (getNextToken()!=Token (Token::Type_EOS)) + return false; + if (node) mFilter = node; else diff --git a/apps/opencs/model/filter/parser.hpp b/apps/opencs/model/filter/parser.hpp index 4341fae9fd..d9f14b5d9a 100644 --- a/apps/opencs/model/filter/parser.hpp +++ b/apps/opencs/model/filter/parser.hpp @@ -28,6 +28,8 @@ namespace CSMFilter boost::shared_ptr parseImp(); ///< Will return a null-pointer, if there is nothing more to parse. + boost::shared_ptr parseNAry (const Token& keyword); + void error(); public: diff --git a/apps/opencs/view/filter/editwidget.cpp b/apps/opencs/view/filter/editwidget.cpp index 793e0504ed..b691a5e169 100644 --- a/apps/opencs/view/filter/editwidget.cpp +++ b/apps/opencs/view/filter/editwidget.cpp @@ -13,7 +13,7 @@ void CSVFilter::EditWidget::textChanged (const QString& text) if (mParser.parse (text.toUtf8().constData())) { setPalette (mPalette); - emit filterChanged (mParser.getFilter(), ""); + emit filterChanged (mParser.getFilter()); } else { diff --git a/apps/opencs/view/filter/editwidget.hpp b/apps/opencs/view/filter/editwidget.hpp index 4e692fc4d8..76b484de96 100644 --- a/apps/opencs/view/filter/editwidget.hpp +++ b/apps/opencs/view/filter/editwidget.hpp @@ -24,8 +24,7 @@ namespace CSVFilter signals: - void filterChanged (boost::shared_ptr filter, - const std::string& userValue); + void filterChanged (boost::shared_ptr filter); private slots: diff --git a/apps/opencs/view/filter/filterbox.cpp b/apps/opencs/view/filter/filterbox.cpp index 9da08d3bad..495abf8713 100644 --- a/apps/opencs/view/filter/filterbox.cpp +++ b/apps/opencs/view/filter/filterbox.cpp @@ -19,6 +19,6 @@ CSVFilter::FilterBox::FilterBox (QWidget *parent) setLayout (layout); connect (recordFilterBox, - SIGNAL (filterChanged (boost::shared_ptr, const std::string&)), - this, SIGNAL (recordFilterChanged (boost::shared_ptr, const std::string&))); + SIGNAL (filterChanged (boost::shared_ptr)), + this, SIGNAL (recordFilterChanged (boost::shared_ptr))); } \ No newline at end of file diff --git a/apps/opencs/view/filter/filterbox.hpp b/apps/opencs/view/filter/filterbox.hpp index 5f260003af..d3806876df 100644 --- a/apps/opencs/view/filter/filterbox.hpp +++ b/apps/opencs/view/filter/filterbox.hpp @@ -17,8 +17,7 @@ namespace CSVFilter signals: - void recordFilterChanged (boost::shared_ptr filter, - const std::string& userValue); + void recordFilterChanged (boost::shared_ptr filter); }; } diff --git a/apps/opencs/view/filter/recordfilterbox.cpp b/apps/opencs/view/filter/recordfilterbox.cpp index c4b516f03b..3b5f73f474 100644 --- a/apps/opencs/view/filter/recordfilterbox.cpp +++ b/apps/opencs/view/filter/recordfilterbox.cpp @@ -22,6 +22,6 @@ CSVFilter::RecordFilterBox::RecordFilterBox (QWidget *parent) setLayout (layout); connect ( - editWidget, SIGNAL (filterChanged (boost::shared_ptr, const std::string&)), - this, SIGNAL (filterChanged (boost::shared_ptr, const std::string&))); + editWidget, SIGNAL (filterChanged (boost::shared_ptr)), + this, SIGNAL (filterChanged (boost::shared_ptr))); } diff --git a/apps/opencs/view/filter/recordfilterbox.hpp b/apps/opencs/view/filter/recordfilterbox.hpp index 8fc1e263bc..64c1848a85 100644 --- a/apps/opencs/view/filter/recordfilterbox.hpp +++ b/apps/opencs/view/filter/recordfilterbox.hpp @@ -21,8 +21,7 @@ namespace CSVFilter signals: - void filterChanged (boost::shared_ptr filter, - const std::string& userValue); + void filterChanged (boost::shared_ptr filter); }; } diff --git a/apps/opencs/view/world/tablesubview.cpp b/apps/opencs/view/world/tablesubview.cpp index cb6f430c1c..a43ae2dacb 100644 --- a/apps/opencs/view/world/tablesubview.cpp +++ b/apps/opencs/view/world/tablesubview.cpp @@ -52,8 +52,8 @@ CSVWorld::TableSubView::TableSubView (const CSMWorld::UniversalId& id, CSMDoc::D mTable, SLOT (requestFocus (const std::string&))); connect (filterBox, - SIGNAL (recordFilterChanged (boost::shared_ptr, const std::string&)), - mTable, SLOT (recordFilterChanged (boost::shared_ptr, const std::string&))); + SIGNAL (recordFilterChanged (boost::shared_ptr)), + mTable, SLOT (recordFilterChanged (boost::shared_ptr))); } void CSVWorld::TableSubView::setEditLock (bool locked)