From d1516792ce28001bf1a316382e10dc9603e2aab2 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 24 Aug 2013 17:17:22 +0200 Subject: [PATCH 1/9] made document data available to filter parser --- apps/opencs/model/filter/parser.cpp | 3 ++- apps/opencs/model/filter/parser.hpp | 8 +++++++- apps/opencs/view/filter/editwidget.cpp | 4 ++-- apps/opencs/view/filter/editwidget.hpp | 7 ++++++- apps/opencs/view/filter/filterbox.cpp | 4 ++-- apps/opencs/view/filter/filterbox.hpp | 7 ++++++- apps/opencs/view/filter/recordfilterbox.cpp | 4 ++-- apps/opencs/view/filter/recordfilterbox.hpp | 7 ++++++- apps/opencs/view/world/tablesubview.cpp | 2 +- 9 files changed, 34 insertions(+), 12 deletions(-) diff --git a/apps/opencs/model/filter/parser.cpp b/apps/opencs/model/filter/parser.cpp index 5e580b6e1..2cf882f2d 100644 --- a/apps/opencs/model/filter/parser.cpp +++ b/apps/opencs/model/filter/parser.cpp @@ -506,7 +506,8 @@ void CSMFilter::Parser::error() mError = true; } -CSMFilter::Parser::Parser() : mIndex (0), mError (false) {} +CSMFilter::Parser::Parser (const CSMWorld::Data& data) +: mIndex (0), mError (false), mData (data) {} bool CSMFilter::Parser::parse (const std::string& filter) { diff --git a/apps/opencs/model/filter/parser.hpp b/apps/opencs/model/filter/parser.hpp index 1600992b7..c26168611 100644 --- a/apps/opencs/model/filter/parser.hpp +++ b/apps/opencs/model/filter/parser.hpp @@ -5,6 +5,11 @@ #include "node.hpp" +namespace CSMWorld +{ + class Data; +} + namespace CSMFilter { struct Token; @@ -15,6 +20,7 @@ namespace CSMFilter std::string mInput; int mIndex; bool mError; + const CSMWorld::Data& mData; Token getStringToken(); @@ -38,7 +44,7 @@ namespace CSMFilter public: - Parser(); + Parser (const CSMWorld::Data& data); bool parse (const std::string& filter); ///< Discards any previous calls to parse diff --git a/apps/opencs/view/filter/editwidget.cpp b/apps/opencs/view/filter/editwidget.cpp index b691a5e16..98d23efdb 100644 --- a/apps/opencs/view/filter/editwidget.cpp +++ b/apps/opencs/view/filter/editwidget.cpp @@ -1,8 +1,8 @@ #include "editwidget.hpp" -CSVFilter::EditWidget::EditWidget (QWidget *parent) -: QLineEdit (parent) +CSVFilter::EditWidget::EditWidget (const CSMWorld::Data& data, QWidget *parent) +: QLineEdit (parent), mParser (data) { mPalette = palette(); connect (this, SIGNAL (textChanged (const QString&)), this, SLOT (textChanged (const QString&))); diff --git a/apps/opencs/view/filter/editwidget.hpp b/apps/opencs/view/filter/editwidget.hpp index 76b484de9..72b2659d5 100644 --- a/apps/opencs/view/filter/editwidget.hpp +++ b/apps/opencs/view/filter/editwidget.hpp @@ -9,6 +9,11 @@ #include "../../model/filter/parser.hpp" #include "../../model/filter/node.hpp" +namespace CSMWorld +{ + class Data; +} + namespace CSVFilter { class EditWidget : public QLineEdit @@ -20,7 +25,7 @@ namespace CSVFilter public: - EditWidget (QWidget *parent = 0); + EditWidget (const CSMWorld::Data& data, QWidget *parent = 0); signals: diff --git a/apps/opencs/view/filter/filterbox.cpp b/apps/opencs/view/filter/filterbox.cpp index 495abf871..af449437b 100644 --- a/apps/opencs/view/filter/filterbox.cpp +++ b/apps/opencs/view/filter/filterbox.cpp @@ -5,14 +5,14 @@ #include "recordfilterbox.hpp" -CSVFilter::FilterBox::FilterBox (QWidget *parent) +CSVFilter::FilterBox::FilterBox (const CSMWorld::Data& data, QWidget *parent) : QWidget (parent) { QHBoxLayout *layout = new QHBoxLayout (this); layout->setContentsMargins (0, 0, 0, 0); - RecordFilterBox *recordFilterBox = new RecordFilterBox (this); + RecordFilterBox *recordFilterBox = new RecordFilterBox (data, this); layout->addWidget (recordFilterBox); diff --git a/apps/opencs/view/filter/filterbox.hpp b/apps/opencs/view/filter/filterbox.hpp index d3806876d..60d2f038f 100644 --- a/apps/opencs/view/filter/filterbox.hpp +++ b/apps/opencs/view/filter/filterbox.hpp @@ -5,6 +5,11 @@ #include "../../model/filter/node.hpp" +namespace CSMWorld +{ + class Data; +} + namespace CSVFilter { class FilterBox : public QWidget @@ -13,7 +18,7 @@ namespace CSVFilter public: - FilterBox (QWidget *parent = 0); + FilterBox (const CSMWorld::Data& data, QWidget *parent = 0); signals: diff --git a/apps/opencs/view/filter/recordfilterbox.cpp b/apps/opencs/view/filter/recordfilterbox.cpp index 3b5f73f47..6b1831e30 100644 --- a/apps/opencs/view/filter/recordfilterbox.cpp +++ b/apps/opencs/view/filter/recordfilterbox.cpp @@ -6,7 +6,7 @@ #include "editwidget.hpp" -CSVFilter::RecordFilterBox::RecordFilterBox (QWidget *parent) +CSVFilter::RecordFilterBox::RecordFilterBox (const CSMWorld::Data& data, QWidget *parent) : QWidget (parent) { QHBoxLayout *layout = new QHBoxLayout (this); @@ -15,7 +15,7 @@ CSVFilter::RecordFilterBox::RecordFilterBox (QWidget *parent) layout->addWidget (new QLabel ("Record Filter", this)); - EditWidget *editWidget = new EditWidget (this); + EditWidget *editWidget = new EditWidget (data, this); layout->addWidget (editWidget); diff --git a/apps/opencs/view/filter/recordfilterbox.hpp b/apps/opencs/view/filter/recordfilterbox.hpp index 64c1848a8..6b1b0e9bb 100644 --- a/apps/opencs/view/filter/recordfilterbox.hpp +++ b/apps/opencs/view/filter/recordfilterbox.hpp @@ -9,6 +9,11 @@ #include "../../model/filter/node.hpp" +namespace CSMWorld +{ + class Data; +} + namespace CSVFilter { class RecordFilterBox : public QWidget @@ -17,7 +22,7 @@ namespace CSVFilter public: - RecordFilterBox (QWidget *parent = 0); + RecordFilterBox (const CSMWorld::Data& data, QWidget *parent = 0); signals: diff --git a/apps/opencs/view/world/tablesubview.cpp b/apps/opencs/view/world/tablesubview.cpp index a43ae2dac..1e05fbf51 100644 --- a/apps/opencs/view/world/tablesubview.cpp +++ b/apps/opencs/view/world/tablesubview.cpp @@ -25,7 +25,7 @@ CSVWorld::TableSubView::TableSubView (const CSMWorld::UniversalId& id, CSMDoc::D layout->insertWidget (0, mTable = new Table (id, document.getData(), document.getUndoStack(), mBottom->canCreateAndDelete()), 2); - CSVFilter::FilterBox *filterBox = new CSVFilter::FilterBox (this); + CSVFilter::FilterBox *filterBox = new CSVFilter::FilterBox (document.getData(), this); layout->insertWidget (0, filterBox); From 25e6380884f4b9e9495516506c90975a68910e9a Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 24 Aug 2013 17:40:00 +0200 Subject: [PATCH 2/9] implemented use of predefined filters --- apps/opencs/model/filter/parser.cpp | 67 +++++++++++++++++++++++------ apps/opencs/model/filter/parser.hpp | 2 +- apps/opencs/model/world/data.cpp | 10 +++++ apps/opencs/model/world/data.hpp | 4 ++ 4 files changed, 70 insertions(+), 13 deletions(-) diff --git a/apps/opencs/model/filter/parser.cpp b/apps/opencs/model/filter/parser.cpp index 2cf882f2d..b800faa1e 100644 --- a/apps/opencs/model/filter/parser.cpp +++ b/apps/opencs/model/filter/parser.cpp @@ -8,6 +8,8 @@ #include #include "../world/columns.hpp" +#include "../world/data.hpp" +#include "../world/idcollection.hpp" #include "booleannode.hpp" #include "ornode.hpp" @@ -31,6 +33,7 @@ namespace CSMFilter Type_OpenSquare, Type_CloseSquare, Type_Comma, + Type_OneShot, Type_Keyword_True, ///< \attention Keyword enums must be arranged continuously. Type_Keyword_False, Type_Keyword_And, @@ -208,6 +211,7 @@ CSMFilter::Token CSMFilter::Parser::getNextToken() case '[': ++mIndex; return Token (Token::Type_OpenSquare); case ']': ++mIndex; return Token (Token::Type_CloseSquare); case ',': ++mIndex; return Token (Token::Type_Comma); + case '?': ++mIndex; return Token (Token::Type_OneShot); } if (c=='"' || c=='_' || std::isalpha (c)) @@ -509,7 +513,7 @@ void CSMFilter::Parser::error() CSMFilter::Parser::Parser (const CSMWorld::Data& data) : mIndex (0), mError (false), mData (data) {} -bool CSMFilter::Parser::parse (const std::string& filter) +bool CSMFilter::Parser::parse (const std::string& filter, bool allowPredefined) { // reset mFilter.reset(); @@ -517,23 +521,62 @@ bool CSMFilter::Parser::parse (const std::string& filter) mInput = filter; mIndex = 0; - boost::shared_ptr node = parseImp (true); + Token token = getNextToken(); - if (mError) - return false; + if (token==Token (Token::Type_OneShot)) + { + boost::shared_ptr node = parseImp (true); - if (getNextToken()!=Token (Token::Type_EOS)) - return false; + if (mError) + return false; + + if (getNextToken()!=Token (Token::Type_EOS)) + { + error(); + return false; + } + + if (node) + mFilter = node; + else + { + // Empty filter string equals to filter "true". + mFilter.reset (new BooleanNode (true)); + } - if (node) - mFilter = node; + return true; + } + else if (token.mType==Token::Type_String && allowPredefined) + { + if (getNextToken()!=Token (Token::Type_EOS)) + { + error(); + return false; + } + + int index = mData.getFilters().searchId (token.mString); + + if (index==-1) + { + error(); + return false; + } + + const CSMWorld::Record& record = mData.getFilters().getRecord (index); + + if (record.isDeleted()) + { + error(); + return false; + } + + return parse (record.get().mFilter, false); + } else { - // Empty filter string equals to filter "true". - mFilter.reset (new BooleanNode (true)); + error(); + return false; } - - return true; } boost::shared_ptr CSMFilter::Parser::getFilter() const diff --git a/apps/opencs/model/filter/parser.hpp b/apps/opencs/model/filter/parser.hpp index c26168611..fbaf6972e 100644 --- a/apps/opencs/model/filter/parser.hpp +++ b/apps/opencs/model/filter/parser.hpp @@ -46,7 +46,7 @@ namespace CSMFilter Parser (const CSMWorld::Data& data); - bool parse (const std::string& filter); + bool parse (const std::string& filter, bool allowPredefined = true); ///< Discards any previous calls to parse /// /// \return Success? diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 4a5dcb38f..b9f6d1718 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -316,6 +316,16 @@ CSMWorld::RefCollection& CSMWorld::Data::getReferences() return mRefs; } +const CSMWorld::IdCollection& CSMWorld::Data::getFilters() const +{ + return mFilters; +} + +CSMWorld::IdCollection& CSMWorld::Data::getFilters() +{ + return mFilters; +} + QAbstractItemModel *CSMWorld::Data::getTableModel (const UniversalId& id) { std::map::iterator iter = mModelIndex.find (id.getType()); diff --git a/apps/opencs/model/world/data.hpp b/apps/opencs/model/world/data.hpp index aebdd6ecd..2f8a2117e 100644 --- a/apps/opencs/model/world/data.hpp +++ b/apps/opencs/model/world/data.hpp @@ -119,6 +119,10 @@ namespace CSMWorld RefCollection& getReferences(); + const IdCollection& getFilters() const; + + IdCollection& getFilters(); + QAbstractItemModel *getTableModel (const UniversalId& id); ///< If no table model is available for \a id, an exception is thrown. /// From 7e02c9acf229daad0a17f03c113dfda1c1b479ab Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 24 Aug 2013 18:53:11 +0200 Subject: [PATCH 3/9] added filter text column to filter table --- apps/opencs/model/world/columnimp.hpp | 25 +++++++++++++++++++++++++ apps/opencs/model/world/columns.cpp | 1 + apps/opencs/model/world/columns.hpp | 1 + apps/opencs/model/world/data.cpp | 1 + 4 files changed, 28 insertions(+) diff --git a/apps/opencs/model/world/columnimp.hpp b/apps/opencs/model/world/columnimp.hpp index 6c31fddf3..1a2bf9df1 100644 --- a/apps/opencs/model/world/columnimp.hpp +++ b/apps/opencs/model/world/columnimp.hpp @@ -1191,6 +1191,31 @@ namespace CSMWorld return true; } }; + + template + struct FilterColumn : public Column + { + FilterColumn() : Column (Columns::ColumnId_Filter, ColumnBase::Display_String) {} + + virtual QVariant get (const Record& record) const + { + return QString::fromUtf8 (record.get().mFilter.c_str()); + } + + virtual void set (Record& record, const QVariant& data) + { + ESXRecordT record2 = record.get(); + + record2.mFilter = data.toString().toUtf8().constData(); + + record.setModified (record2); + } + + virtual bool isEditable() const + { + return true; + } + }; } #endif diff --git a/apps/opencs/model/world/columns.cpp b/apps/opencs/model/world/columns.cpp index f6eb8fe34..b20632258 100644 --- a/apps/opencs/model/world/columns.cpp +++ b/apps/opencs/model/world/columns.cpp @@ -144,6 +144,7 @@ namespace CSMWorld { ColumnId_MaxThrust, "Max Thrust" }, { ColumnId_Magical, "Magical" }, { ColumnId_Silver, "Silver" }, + { ColumnId_Filter, "Filter" }, { ColumnId_UseValue1, "Use value 1" }, { ColumnId_UseValue2, "Use value 2" }, diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index 28da60e93..9a39e1678 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -138,6 +138,7 @@ namespace CSMWorld ColumnId_MaxThrust = 106, ColumnId_Magical = 107, ColumnId_Silver = 108, + ColumnId_Filter = 109, // Allocated to a separate value range, so we don't get a collision should we ever need // to extend the number of use values. diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index b9f6d1718..fbdbb4413 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -150,6 +150,7 @@ CSMWorld::Data::Data() : mRefs (mCells) mFilters.addColumn (new StringIdColumn); mFilters.addColumn (new RecordStateColumn); + mFilters.addColumn (new FilterColumn); mFilters.addColumn (new DescriptionColumn); addModel (new IdTable (&mGlobals), UniversalId::Type_Globals, UniversalId::Type_Global); From d007d4dc9a921bcc592790182b54edb58278a909 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 24 Aug 2013 19:12:47 +0200 Subject: [PATCH 4/9] allow colons in names (filter) --- apps/opencs/model/filter/parser.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/opencs/model/filter/parser.cpp b/apps/opencs/model/filter/parser.cpp index b800faa1e..2320aa0be 100644 --- a/apps/opencs/model/filter/parser.cpp +++ b/apps/opencs/model/filter/parser.cpp @@ -92,7 +92,7 @@ CSMFilter::Token CSMFilter::Parser::getStringToken() { char c = mInput[mIndex]; - if (std::isalpha (c) || c=='_' || (!string.empty() && std::isdigit (c)) || c=='"' || + if (std::isalpha (c) || c==':' || c=='_' || (!string.empty() && std::isdigit (c)) || c=='"' || (!string.empty() && string[0]=='"')) string += c; else @@ -214,7 +214,7 @@ CSMFilter::Token CSMFilter::Parser::getNextToken() case '?': ++mIndex; return Token (Token::Type_OneShot); } - if (c=='"' || c=='_' || std::isalpha (c)) + if (c=='"' || c=='_' || std::isalpha (c) || c==':') return getStringToken(); if (c=='-' || c=='.' || std::isdigit (c)) From 937f5b11a2795d91a033da953405f6f7b5c7a665 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 26 Aug 2013 12:25:19 +0200 Subject: [PATCH 5/9] fixed broken record deletion --- apps/opencs/model/world/collection.hpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/opencs/model/world/collection.hpp b/apps/opencs/model/world/collection.hpp index 526c07815..6cf31d0a4 100644 --- a/apps/opencs/model/world/collection.hpp +++ b/apps/opencs/model/world/collection.hpp @@ -236,14 +236,15 @@ namespace CSMWorld if (iter->second>=index+count) { iter->second -= count; + ++iter; } else { mIndex.erase (iter++); } } - - ++iter; + else + ++iter; } } From 20bd0707dcff43888b0d55006a850ebb8c216763 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 26 Aug 2013 12:25:52 +0200 Subject: [PATCH 6/9] avoid use of column number literals --- apps/opencs/model/world/commands.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/apps/opencs/model/world/commands.cpp b/apps/opencs/model/world/commands.cpp index 43ecaca63..f6f421c6a 100644 --- a/apps/opencs/model/world/commands.cpp +++ b/apps/opencs/model/world/commands.cpp @@ -69,7 +69,9 @@ CSMWorld::RevertCommand::~RevertCommand() void CSMWorld::RevertCommand::redo() { - QModelIndex index = mModel.getModelIndex (mId, 1); + int column = mModel.findColumnIndex (Columns::ColumnId_Modification); + + QModelIndex index = mModel.getModelIndex (mId, column); RecordBase::State state = static_cast (mModel.data (index).toInt()); if (state==RecordBase::State_ModifiedOnly) @@ -102,7 +104,9 @@ CSMWorld::DeleteCommand::~DeleteCommand() void CSMWorld::DeleteCommand::redo() { - QModelIndex index = mModel.getModelIndex (mId, 1); + int column = mModel.findColumnIndex (Columns::ColumnId_Modification); + + QModelIndex index = mModel.getModelIndex (mId, column); RecordBase::State state = static_cast (mModel.data (index).toInt()); if (state==RecordBase::State_ModifiedOnly) From aa935ff03d86709a629295e232be743ce8c15e3a Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 26 Aug 2013 12:49:13 +0200 Subject: [PATCH 7/9] update tables on filter record changes --- apps/opencs/view/filter/editwidget.cpp | 36 +++++++++++++++++++-- apps/opencs/view/filter/editwidget.hpp | 10 +++++- apps/opencs/view/filter/filterbox.cpp | 2 +- apps/opencs/view/filter/filterbox.hpp | 2 +- apps/opencs/view/filter/recordfilterbox.cpp | 2 +- apps/opencs/view/filter/recordfilterbox.hpp | 2 +- 6 files changed, 47 insertions(+), 7 deletions(-) diff --git a/apps/opencs/view/filter/editwidget.cpp b/apps/opencs/view/filter/editwidget.cpp index 98d23efdb..708d45032 100644 --- a/apps/opencs/view/filter/editwidget.cpp +++ b/apps/opencs/view/filter/editwidget.cpp @@ -1,11 +1,27 @@ #include "editwidget.hpp" -CSVFilter::EditWidget::EditWidget (const CSMWorld::Data& data, QWidget *parent) +#include + +#include "../../model/world/data.hpp" + +CSVFilter::EditWidget::EditWidget (CSMWorld::Data& data, QWidget *parent) : QLineEdit (parent), mParser (data) { mPalette = palette(); connect (this, SIGNAL (textChanged (const QString&)), this, SLOT (textChanged (const QString&))); + + QAbstractItemModel *model = data.getTableModel (CSMWorld::UniversalId::Type_Filters); + + connect (model, SIGNAL (dataChanged (const QModelIndex &, const QModelIndex&)), + this, SLOT (filterDataChanged (const QModelIndex &, const QModelIndex&)), + Qt::QueuedConnection); + connect (model, SIGNAL (rowsRemoved (const QModelIndex&, int, int)), + this, SLOT (filterRowsRemoved (const QModelIndex&, int, int)), + Qt::QueuedConnection); + connect (model, SIGNAL (rowsInserted (const QModelIndex&, int, int)), + this, SLOT (filterRowsInserted (const QModelIndex&, int, int)), + Qt::QueuedConnection); } void CSVFilter::EditWidget::textChanged (const QString& text) @@ -23,4 +39,20 @@ void CSVFilter::EditWidget::textChanged (const QString& text) /// \todo improve error reporting; mark only the faulty part } -} \ No newline at end of file +} + +void CSVFilter::EditWidget::filterDataChanged (const QModelIndex& topLeft, + const QModelIndex& bottomRight) +{ + textChanged (text()); +} + +void CSVFilter::EditWidget::filterRowsRemoved (const QModelIndex& parent, int start, int end) +{ + textChanged (text()); +} + +void CSVFilter::EditWidget::filterRowsInserted (const QModelIndex& parent, int start, int end) +{ + textChanged (text()); +} diff --git a/apps/opencs/view/filter/editwidget.hpp b/apps/opencs/view/filter/editwidget.hpp index 72b2659d5..31904e624 100644 --- a/apps/opencs/view/filter/editwidget.hpp +++ b/apps/opencs/view/filter/editwidget.hpp @@ -9,6 +9,8 @@ #include "../../model/filter/parser.hpp" #include "../../model/filter/node.hpp" +class QModelIndex; + namespace CSMWorld { class Data; @@ -25,7 +27,7 @@ namespace CSVFilter public: - EditWidget (const CSMWorld::Data& data, QWidget *parent = 0); + EditWidget (CSMWorld::Data& data, QWidget *parent = 0); signals: @@ -34,6 +36,12 @@ namespace CSVFilter private slots: void textChanged (const QString& text); + + void filterDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight); + + void filterRowsRemoved (const QModelIndex& parent, int start, int end); + + void filterRowsInserted (const QModelIndex& parent, int start, int end); }; } diff --git a/apps/opencs/view/filter/filterbox.cpp b/apps/opencs/view/filter/filterbox.cpp index af449437b..273170884 100644 --- a/apps/opencs/view/filter/filterbox.cpp +++ b/apps/opencs/view/filter/filterbox.cpp @@ -5,7 +5,7 @@ #include "recordfilterbox.hpp" -CSVFilter::FilterBox::FilterBox (const CSMWorld::Data& data, QWidget *parent) +CSVFilter::FilterBox::FilterBox (CSMWorld::Data& data, QWidget *parent) : QWidget (parent) { QHBoxLayout *layout = new QHBoxLayout (this); diff --git a/apps/opencs/view/filter/filterbox.hpp b/apps/opencs/view/filter/filterbox.hpp index 60d2f038f..2524fa0a3 100644 --- a/apps/opencs/view/filter/filterbox.hpp +++ b/apps/opencs/view/filter/filterbox.hpp @@ -18,7 +18,7 @@ namespace CSVFilter public: - FilterBox (const CSMWorld::Data& data, QWidget *parent = 0); + FilterBox (CSMWorld::Data& data, QWidget *parent = 0); signals: diff --git a/apps/opencs/view/filter/recordfilterbox.cpp b/apps/opencs/view/filter/recordfilterbox.cpp index 6b1831e30..c405177b0 100644 --- a/apps/opencs/view/filter/recordfilterbox.cpp +++ b/apps/opencs/view/filter/recordfilterbox.cpp @@ -6,7 +6,7 @@ #include "editwidget.hpp" -CSVFilter::RecordFilterBox::RecordFilterBox (const CSMWorld::Data& data, QWidget *parent) +CSVFilter::RecordFilterBox::RecordFilterBox (CSMWorld::Data& data, QWidget *parent) : QWidget (parent) { QHBoxLayout *layout = new QHBoxLayout (this); diff --git a/apps/opencs/view/filter/recordfilterbox.hpp b/apps/opencs/view/filter/recordfilterbox.hpp index 6b1b0e9bb..057d69518 100644 --- a/apps/opencs/view/filter/recordfilterbox.hpp +++ b/apps/opencs/view/filter/recordfilterbox.hpp @@ -22,7 +22,7 @@ namespace CSVFilter public: - RecordFilterBox (const CSMWorld::Data& data, QWidget *parent = 0); + RecordFilterBox (CSMWorld::Data& data, QWidget *parent = 0); signals: From 2e9948e86a43498dc0f09babb8ed143870cf17c5 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 26 Aug 2013 14:40:34 +0200 Subject: [PATCH 8/9] improved one-shot filter handling; allow empty pre-defined filters --- apps/opencs/model/filter/parser.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/apps/opencs/model/filter/parser.cpp b/apps/opencs/model/filter/parser.cpp index 2320aa0be..abdc3bab3 100644 --- a/apps/opencs/model/filter/parser.cpp +++ b/apps/opencs/model/filter/parser.cpp @@ -47,7 +47,7 @@ namespace CSMFilter std::string mString; double mNumber; - Token (Type type); + Token (Type type = Type_None); Token (const std::string& string); @@ -521,9 +521,12 @@ bool CSMFilter::Parser::parse (const std::string& filter, bool allowPredefined) mInput = filter; mIndex = 0; - Token token = getNextToken(); + Token token; + + if (allowPredefined) + token = getNextToken(); - if (token==Token (Token::Type_OneShot)) + if (!allowPredefined || token==Token (Token::Type_OneShot)) { boost::shared_ptr node = parseImp (true); From 26b3d93293afc4363fa9e715c217bc8e3dbf5ca5 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 27 Aug 2013 18:58:23 +0200 Subject: [PATCH 9/9] streamlined filter syntax --- apps/opencs/model/filter/parser.cpp | 68 +++++++++++++++-------------- apps/opencs/model/filter/parser.hpp | 2 +- 2 files changed, 37 insertions(+), 33 deletions(-) diff --git a/apps/opencs/model/filter/parser.cpp b/apps/opencs/model/filter/parser.cpp index abdc3bab3..d334a7f63 100644 --- a/apps/opencs/model/filter/parser.cpp +++ b/apps/opencs/model/filter/parser.cpp @@ -174,14 +174,14 @@ CSMFilter::Token CSMFilter::Parser::checkKeywords (const Token& token) { "true", "false", "and", "or", "not", - "text", "value", + "string", "value", 0 }; std::string string = Misc::StringUtils::lowerCase (token.mString); for (int i=0; sKeywords[i]; ++i) - if (sKeywords[i]==string) + if (sKeywords[i]==string || (string.size()==1 && sKeywords[i][0]==string[0])) return Token (static_cast (i+Token::Type_Keyword_True)); return token; @@ -211,7 +211,7 @@ CSMFilter::Token CSMFilter::Parser::getNextToken() case '[': ++mIndex; return Token (Token::Type_OpenSquare); case ']': ++mIndex; return Token (Token::Type_CloseSquare); case ',': ++mIndex; return Token (Token::Type_Comma); - case '?': ++mIndex; return Token (Token::Type_OneShot); + case '!': ++mIndex; return Token (Token::Type_OneShot); } if (c=='"' || c=='_' || std::isalpha (c) || c==':') @@ -224,54 +224,58 @@ CSMFilter::Token CSMFilter::Parser::getNextToken() return Token (Token::Type_None); } -boost::shared_ptr CSMFilter::Parser::parseImp (bool allowEmpty) +boost::shared_ptr CSMFilter::Parser::parseImp (bool allowEmpty, bool ignoreOneShot) { if (Token token = getNextToken()) { - switch (token.mType) - { - case Token::Type_Keyword_True: + if (token==Token (Token::Type_OneShot)) + token = getNextToken(); - return boost::shared_ptr (new BooleanNode (true)); + if (token) + switch (token.mType) + { + case Token::Type_Keyword_True: - case Token::Type_Keyword_False: + return boost::shared_ptr (new BooleanNode (true)); - return boost::shared_ptr (new BooleanNode (false)); + case Token::Type_Keyword_False: - case Token::Type_Keyword_And: - case Token::Type_Keyword_Or: + return boost::shared_ptr (new BooleanNode (false)); - return parseNAry (token); + case Token::Type_Keyword_And: + case Token::Type_Keyword_Or: - case Token::Type_Keyword_Not: - { - boost::shared_ptr node = parseImp(); + return parseNAry (token); - if (mError) - return boost::shared_ptr(); + case Token::Type_Keyword_Not: + { + boost::shared_ptr node = parseImp(); - return boost::shared_ptr (new NotNode (node)); - } + if (mError) + return boost::shared_ptr(); - case Token::Type_Keyword_Text: + return boost::shared_ptr (new NotNode (node)); + } - return parseText(); + case Token::Type_Keyword_Text: - case Token::Type_Keyword_Value: + return parseText(); - return parseValue(); + case Token::Type_Keyword_Value: - case Token::Type_EOS: + return parseValue(); - if (!allowEmpty) - error(); + case Token::Type_EOS: - return boost::shared_ptr(); + if (!allowEmpty) + error(); - default: + return boost::shared_ptr(); - error(); - } + default: + + error(); + } } return boost::shared_ptr(); @@ -528,7 +532,7 @@ bool CSMFilter::Parser::parse (const std::string& filter, bool allowPredefined) if (!allowPredefined || token==Token (Token::Type_OneShot)) { - boost::shared_ptr node = parseImp (true); + boost::shared_ptr node = parseImp (true, token!=Token (Token::Type_OneShot)); if (mError) return false; diff --git a/apps/opencs/model/filter/parser.hpp b/apps/opencs/model/filter/parser.hpp index fbaf6972e..5700102cf 100644 --- a/apps/opencs/model/filter/parser.hpp +++ b/apps/opencs/model/filter/parser.hpp @@ -31,7 +31,7 @@ namespace CSMFilter Token checkKeywords (const Token& token); ///< Turn string token into keyword token, if possible. - boost::shared_ptr parseImp (bool allowEmpty = false); + boost::shared_ptr parseImp (bool allowEmpty = false, bool ignoreOneShot = false); ///< Will return a null-pointer, if there is nothing more to parse. boost::shared_ptr parseNAry (const Token& keyword);