From 649ef6f12010b2bbd24521edab214867e14bddcc Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 2 Sep 2013 11:58:05 +0200 Subject: [PATCH 01/12] moved list of enum literals from ViewManager to Columns (which makes them available to the rest of model now) --- apps/opencs/model/world/columns.cpp | 81 ++++++++++++++++++++ apps/opencs/model/world/columns.hpp | 6 ++ apps/opencs/view/doc/viewmanager.cpp | 99 +++++++------------------ apps/opencs/view/world/enumdelegate.cpp | 12 +++ apps/opencs/view/world/enumdelegate.hpp | 3 + 5 files changed, 129 insertions(+), 72 deletions(-) diff --git a/apps/opencs/model/world/columns.cpp b/apps/opencs/model/world/columns.cpp index b20632258..73a58ac82 100644 --- a/apps/opencs/model/world/columns.cpp +++ b/apps/opencs/model/world/columns.cpp @@ -196,4 +196,85 @@ int CSMWorld::Columns::getId (const std::string& name) return sNames[i].mId; return -1; +} + +namespace +{ + static const char *sSpecialisations[] = + { + "Combat", "Magic", "Stealth", 0 + }; + + static const char *sAttributes[] = + { + "Strength", "Intelligence", "Willpower", "Agility", "Speed", "Endurance", "Personality", + "Luck", 0 + }; + + static const char *sSpellTypes[] = + { + "Spell", "Ability", "Blight", "Disease", "Curse", "Power", 0 + }; + + static const char *sApparatusTypes[] = + { + "Mortar & Pestle", "Albemic", "Calcinator", "Retort", 0 + }; + + static const char *sArmorTypes[] = + { + "Helmet", "Cuirass", "Left Pauldron", "Right Pauldron", "Greaves", "Boots", "Left Gauntlet", + "Right Gauntlet", "Shield", "Left Bracer", "Right Bracer", 0 + }; + + static const char *sClothingTypes[] = + { + "Pants", "Shoes", "Shirt", "Belt", "Robe", "Right Glove", "Left Glove", "Skirt", "Ring", + "Amulet", 0 + }; + + static const char *sCreatureTypes[] = + { + "Creature", "Deadra", "Undead", "Humanoid", 0 + }; + + static const char *sWeaponTypes[] = + { + "Short Blade 1H", "Long Blade 1H", "Long Blade 2H", "Blunt 1H", "Blunt 2H Close", + "Blunt 2H Wide", "Spear 2H", "Axe 1H", "Axe 2H", "Bow", "Crossbow", "Thrown", "Arrow", + "Bolt", 0 + }; + + const char **getEnumNames (CSMWorld::Columns::ColumnId column) + { + switch (column) + { + case CSMWorld::Columns::ColumnId_Specialisation: return sSpecialisations; + case CSMWorld::Columns::ColumnId_Attribute: return sAttributes; + case CSMWorld::Columns::ColumnId_SpellType: return sSpellTypes; + case CSMWorld::Columns::ColumnId_ApparatusType: return sApparatusTypes; + case CSMWorld::Columns::ColumnId_ArmorType: return sArmorTypes; + case CSMWorld::Columns::ColumnId_ClothingType: return sClothingTypes; + case CSMWorld::Columns::ColumnId_CreatureType: return sCreatureTypes; + case CSMWorld::Columns::ColumnId_WeaponType: return sWeaponTypes; + + default: return 0; + } + } +} + +bool CSMWorld::Columns::hasEnums (ColumnId column) +{ + return getEnumNames (column)!=0; +} + +std::vector CSMWorld::Columns::getEnums (ColumnId column) +{ + std::vector enums; + + if (const char **table = getEnumNames (column)) + for (int i=0; table[i]; ++i) + enums.push_back (table[i]); + + return enums; } \ No newline at end of file diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index 9a39e1678..69b20583a 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -2,6 +2,7 @@ #define CSM_WOLRD_COLUMNS_H #include +#include namespace CSMWorld { @@ -180,6 +181,11 @@ namespace CSMWorld int getId (const std::string& name); ///< Will return -1 for an invalid name. + + bool hasEnums (ColumnId column); + + std::vector getEnums (ColumnId column); + ///< Returns an empty vector, if \æ column isn't an enum type column. } } diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index 6d06e4248..7c7c0f28b 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -8,6 +8,7 @@ #include "../../model/doc/documentmanager.hpp" #include "../../model/doc/document.hpp" +#include "../../model/world/columns.hpp" #include "../world/util.hpp" #include "../world/enumdelegate.hpp" @@ -43,51 +44,6 @@ void CSVDoc::ViewManager::updateIndices() CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager) : mDocumentManager (documentManager), mExitOnSaveStateChange(false), mUserWarned(false) { - static const char *sSpecialisations[] = - { - "Combat", "Magic", "Stealth", 0 - }; - - static const char *sAttributes[] = - { - "Strength", "Intelligence", "Willpower", "Agility", "Speed", "Endurance", "Personality", - "Luck", 0 - }; - - static const char *sSpellTypes[] = - { - "Spell", "Ability", "Blight", "Disease", "Curse", "Power", 0 - }; - - static const char *sApparatusTypes[] = - { - "Mortar & Pestle", "Albemic", "Calcinator", "Retort", 0 - }; - - static const char *sArmorTypes[] = - { - "Helmet", "Cuirass", "Left Pauldron", "Right Pauldron", "Greaves", "Boots", "Left Gauntlet", - "Right Gauntlet", "Shield", "Left Bracer", "Right Bracer", 0 - }; - - static const char *sClothingTypes[] = - { - "Pants", "Shoes", "Shirt", "Belt", "Robe", "Right Glove", "Left Glove", "Skirt", "Ring", - "Amulet", 0 - }; - - static const char *sCreatureTypes[] = - { - "Creature", "Deadra", "Undead", "Humanoid", 0 - }; - - static const char *sWeaponTypes[] = - { - "Short Blade 1H", "Long Blade 1H", "Long Blade 2H", "Blunt 1H", "Blunt 2H Close", - "Blunt 2H Wide", "Spear 2H", "Axe 1H", "Axe 2H", "Bow", "Crossbow", "Thrown", "Arrow", - "Bolt", 0 - }; - mDelegateFactories = new CSVWorld::CommandDelegateFactoryCollection; mDelegateFactories->add (CSMWorld::ColumnBase::Display_GmstVarType, @@ -96,38 +52,37 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager) mDelegateFactories->add (CSMWorld::ColumnBase::Display_GlobalVarType, new CSVWorld::VarTypeDelegateFactory (ESM::VT_Short, ESM::VT_Long, ESM::VT_Float)); - mDelegateFactories->add (CSMWorld::ColumnBase::Display_Specialisation, - new CSVWorld::EnumDelegateFactory (sSpecialisations)); - - mDelegateFactories->add (CSMWorld::ColumnBase::Display_Attribute, - new CSVWorld::EnumDelegateFactory (sAttributes, true)); - - mDelegateFactories->add (CSMWorld::ColumnBase::Display_SpellType, - new CSVWorld::EnumDelegateFactory (sSpellTypes)); - - mDelegateFactories->add (CSMWorld::ColumnBase::Display_ApparatusType, - new CSVWorld::EnumDelegateFactory (sApparatusTypes)); - - mDelegateFactories->add (CSMWorld::ColumnBase::Display_ArmorType, - new CSVWorld::EnumDelegateFactory (sArmorTypes)); - - mDelegateFactories->add (CSMWorld::ColumnBase::Display_ClothingType, - new CSVWorld::EnumDelegateFactory (sClothingTypes)); - - mDelegateFactories->add (CSMWorld::ColumnBase::Display_CreatureType, - new CSVWorld::EnumDelegateFactory (sCreatureTypes)); - - mDelegateFactories->add (CSMWorld::ColumnBase::Display_WeaponType, - new CSVWorld::EnumDelegateFactory (sWeaponTypes)); - mDelegateFactories->add (CSMWorld::ColumnBase::Display_RecordState, - new CSVWorld::RecordStatusDelegateFactory() ); + new CSVWorld::RecordStatusDelegateFactory()); mDelegateFactories->add (CSMWorld::ColumnBase::Display_RefRecordType, - new CSVWorld::RefIdTypeDelegateFactory() ); + new CSVWorld::RefIdTypeDelegateFactory()); + + struct Mapping + { + CSMWorld::ColumnBase::Display mDisplay; + CSMWorld::Columns::ColumnId mColumnId; + bool mAllowNone; + }; + + static const Mapping sMapping[] = + { + { CSMWorld::ColumnBase::Display_Specialisation, CSMWorld::Columns::ColumnId_Specialisation, false }, + { CSMWorld::ColumnBase::Display_Attribute, CSMWorld::Columns::ColumnId_Attribute, true }, + { CSMWorld::ColumnBase::Display_SpellType, CSMWorld::Columns::ColumnId_SpellType, false }, + { CSMWorld::ColumnBase::Display_ApparatusType, CSMWorld::Columns::ColumnId_ApparatusType, false }, + { CSMWorld::ColumnBase::Display_ArmorType, CSMWorld::Columns::ColumnId_ArmorType, false }, + { CSMWorld::ColumnBase::Display_ClothingType, CSMWorld::Columns::ColumnId_ClothingType, false }, + { CSMWorld::ColumnBase::Display_CreatureType, CSMWorld::Columns::ColumnId_CreatureType, false }, + { CSMWorld::ColumnBase::Display_WeaponType, CSMWorld::Columns::ColumnId_WeaponType, false } + }; + + for (std::size_t i=0; iadd (sMapping[i].mDisplay, new CSVWorld::EnumDelegateFactory ( + CSMWorld::Columns::getEnums (sMapping[i].mColumnId), sMapping[i].mAllowNone)); connect (&CSMSettings::UserSettings::instance(), SIGNAL (signalUpdateEditorSetting (const QString &, const QString &)), - this, SLOT (slotUpdateEditorSetting (const QString &, const QString &))); + this, SLOT (slotUpdateEditorSetting (const QString &, const QString &))); } CSVDoc::ViewManager::~ViewManager() diff --git a/apps/opencs/view/world/enumdelegate.cpp b/apps/opencs/view/world/enumdelegate.cpp index dd194abe9..fc9b7ee3b 100644 --- a/apps/opencs/view/world/enumdelegate.cpp +++ b/apps/opencs/view/world/enumdelegate.cpp @@ -109,6 +109,18 @@ CSVWorld::EnumDelegateFactory::EnumDelegateFactory (const char **names, bool all add (i, names[i]); } +CSVWorld::EnumDelegateFactory::EnumDelegateFactory (const std::vector& names, + bool allowNone) +{ + if (allowNone) + add (-1, ""); + + int size = static_cast (names.size()); + + for (int i=0; i& names, bool allowNone = false); + /// \param allowNone Use value of -1 for "none selected" (empty string) + virtual CommandDelegate *makeDelegate (QUndoStack& undoStack, QObject *parent) const; ///< The ownership of the returned CommandDelegate is transferred to the caller. From 9cb121bd049d2ce381f80a3c0c2165d5093933c2 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 2 Sep 2013 12:23:19 +0200 Subject: [PATCH 02/12] allow specifying enums as text in filters --- apps/opencs/model/filter/textnode.cpp | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/apps/opencs/model/filter/textnode.cpp b/apps/opencs/model/filter/textnode.cpp index 9987c66d2..a826a2d54 100644 --- a/apps/opencs/model/filter/textnode.cpp +++ b/apps/opencs/model/filter/textnode.cpp @@ -28,13 +28,30 @@ bool CSMFilter::TextNode::test (const CSMWorld::IdTable& table, int row, QVariant data = table.data (index); - if (data.type()!=QVariant::String) + QString string; + + if (data.type()==QVariant::String) + { + string = data.toString(); + } + else if (data.type()==QVariant::Int || data.type()==QVariant::UInt || + CSMWorld::Columns::hasEnums (static_cast (mColumnId))) + { + int value = data.toInt(); + + std::vector enums = + CSMWorld::Columns::getEnums (static_cast (mColumnId)); + + if (value>=0 && value (enums.size())) + string = QString::fromUtf8 (enums[value].c_str()); + } + else return false; /// \todo make pattern syntax configurable QRegExp regExp (QString::fromUtf8 (mText.c_str()), Qt::CaseInsensitive); - return regExp.exactMatch (data.toString()); + return regExp.exactMatch (string); } std::vector CSMFilter::TextNode::getReferencedColumns() const From 1744a64f77ac1740df6338d4657b66c15dd5fd11 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 3 Sep 2013 12:32:06 +0200 Subject: [PATCH 03/12] in filters allow specifiying boolean columns as strings --- apps/opencs/model/filter/parser.cpp | 2 +- apps/opencs/model/filter/textnode.cpp | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/apps/opencs/model/filter/parser.cpp b/apps/opencs/model/filter/parser.cpp index d334a7f63..15cdbfce2 100644 --- a/apps/opencs/model/filter/parser.cpp +++ b/apps/opencs/model/filter/parser.cpp @@ -120,7 +120,7 @@ CSMFilter::Token CSMFilter::Parser::getStringToken() } if (string[0]=='"') - string = string.substr (1, string.size()-2); + return string.substr (1, string.size()-2); } return checkKeywords (string); diff --git a/apps/opencs/model/filter/textnode.cpp b/apps/opencs/model/filter/textnode.cpp index a826a2d54..f3d98ce53 100644 --- a/apps/opencs/model/filter/textnode.cpp +++ b/apps/opencs/model/filter/textnode.cpp @@ -45,6 +45,10 @@ bool CSMFilter::TextNode::test (const CSMWorld::IdTable& table, int row, if (value>=0 && value (enums.size())) string = QString::fromUtf8 (enums[value].c_str()); } + else if (data.type()==QVariant::Bool) + { + string = data.toBool() ? "true" : " false"; + } else return false; From f80373a8494cf0720a192ff634aee98842f2e2d1 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 3 Sep 2013 12:53:45 +0200 Subject: [PATCH 04/12] removed two unused files --- .../view/world/refrecordtypedelegate.cpp | 25 -------- .../view/world/refrecordtypedelegate.hpp | 58 ------------------- 2 files changed, 83 deletions(-) delete mode 100644 apps/opencs/view/world/refrecordtypedelegate.cpp delete mode 100644 apps/opencs/view/world/refrecordtypedelegate.hpp diff --git a/apps/opencs/view/world/refrecordtypedelegate.cpp b/apps/opencs/view/world/refrecordtypedelegate.cpp deleted file mode 100644 index 2bcb7ca50..000000000 --- a/apps/opencs/view/world/refrecordtypedelegate.cpp +++ /dev/null @@ -1,25 +0,0 @@ -#include "refrecordtypedelegate.hpp" -#include "../../model/world/universalid.hpp" - -CSVWorld::RefRecordTypeDelegate::RefRecordTypeDelegate - (const std::vector > &values, QUndoStack& undoStack, QObject *parent) - : EnumDelegate (values, undoStack, parent) -{} - -CSVWorld::RefRecordTypeDelegateFactory::RefRecordTypeDelegateFactory() -{ - unsigned int argSize = CSMWorld::UniversalId::getIdArgSize(); - - for (unsigned int i = 0; i < argSize; i++) - { - std::pair idPair = CSMWorld::UniversalId::getIdArgPair(i); - - mValues.push_back (std::pair(idPair.first, QString::fromUtf8(idPair.second))); - } -} - -CSVWorld::CommandDelegate *CSVWorld::RefRecordTypeDelegateFactory::makeDelegate (QUndoStack& undoStack, - QObject *parent) const -{ - return new RefRecordTypeDelegate (mValues, undoStack, parent); -} diff --git a/apps/opencs/view/world/refrecordtypedelegate.hpp b/apps/opencs/view/world/refrecordtypedelegate.hpp deleted file mode 100644 index baec2cc2e..000000000 --- a/apps/opencs/view/world/refrecordtypedelegate.hpp +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef REFRECORDTYPEDELEGATE_HPP -#define REFRECORDTYPEDELEGATE_HPP - -#include "enumdelegate.hpp" -#include "util.hpp" - -namespace CSVWorld -{ - class RefRecordTypeDelegate : public EnumDelegate - { - public: - RefRecordTypeDelegate (const std::vector > &mValues, QUndoStack& undoStack, QObject *parent); - }; - - class RefRecordTypeDelegateFactory : public CommandDelegateFactory - { - - std::vector > mValues; - - public: - RefRecordTypeDelegateFactory(); - - virtual CommandDelegate *makeDelegate (QUndoStack& undoStack, QObject *parent) const; - ///< The ownership of the returned CommandDelegate is transferred to the caller. - }; -} -/* - class VarTypeDelegate : public EnumDelegate - { - private: - - virtual void addCommands (QAbstractItemModel *model, - const QModelIndex& index, int type) const; - - public: - - VarTypeDelegate (const std::vector >& values, - QUndoStack& undoStack, QObject *parent); - }; - - class VarTypeDelegateFactory : public CommandDelegateFactory - { - std::vector > mValues; - - public: - - VarTypeDelegateFactory (ESM::VarType type0 = ESM::VT_Unknown, - ESM::VarType type1 = ESM::VT_Unknown, ESM::VarType type2 = ESM::VT_Unknown, - ESM::VarType type3 = ESM::VT_Unknown); - - virtual CommandDelegate *makeDelegate (QUndoStack& undoStack, QObject *parent) const; - ///< The ownership of the returned CommandDelegate is transferred to the caller. - - void add (ESM::VarType type); - }; -*/ - -#endif // REFRECORDTYPEDELEGATE_HPP From 80f8024da790b8f2490c037df317f8308fbc0f93 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 3 Sep 2013 13:03:02 +0200 Subject: [PATCH 05/12] allow specifying record modification status column enum via strings --- apps/opencs/model/world/columns.cpp | 6 ++++++ .../opencs/view/world/recordstatusdelegate.cpp | 18 +++++++++++++----- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/apps/opencs/model/world/columns.cpp b/apps/opencs/model/world/columns.cpp index 73a58ac82..2a47a73fb 100644 --- a/apps/opencs/model/world/columns.cpp +++ b/apps/opencs/model/world/columns.cpp @@ -245,6 +245,11 @@ namespace "Bolt", 0 }; + static const char *sModificationEnums[] = + { + "Base", "Modified", "Added", "Deleted", "Deleted", 0 + }; + const char **getEnumNames (CSMWorld::Columns::ColumnId column) { switch (column) @@ -257,6 +262,7 @@ namespace case CSMWorld::Columns::ColumnId_ClothingType: return sClothingTypes; case CSMWorld::Columns::ColumnId_CreatureType: return sCreatureTypes; case CSMWorld::Columns::ColumnId_WeaponType: return sWeaponTypes; + case CSMWorld::Columns::ColumnId_Modification: return sModificationEnums; default: return 0; } diff --git a/apps/opencs/view/world/recordstatusdelegate.cpp b/apps/opencs/view/world/recordstatusdelegate.cpp index a0ffd3063..8085ec7be 100644 --- a/apps/opencs/view/world/recordstatusdelegate.cpp +++ b/apps/opencs/view/world/recordstatusdelegate.cpp @@ -1,8 +1,11 @@ #include "recordstatusdelegate.hpp" + #include #include #include + #include "../../model/settings/usersettings.hpp" +#include "../../model/world/columns.hpp" CSVWorld::RecordStatusDelegate::RecordStatusDelegate(const ValueList& values, const IconList & icons, @@ -37,9 +40,14 @@ bool CSVWorld::RecordStatusDelegate::updateEditorSetting (const QString &setting CSVWorld::RecordStatusDelegateFactory::RecordStatusDelegateFactory() { - DataDisplayDelegateFactory::add ( CSMWorld::RecordBase::State_BaseOnly, "Base", ":./base.png"); - DataDisplayDelegateFactory::add ( CSMWorld::RecordBase::State_Deleted, "Deleted", ":./removed.png"); - DataDisplayDelegateFactory::add ( CSMWorld::RecordBase::State_Erased, "Deleted", ":./removed.png"); - DataDisplayDelegateFactory::add ( CSMWorld::RecordBase::State_Modified, "Modified", ":./modified.png"); - DataDisplayDelegateFactory::add ( CSMWorld::RecordBase::State_ModifiedOnly, "Added", ":./added.png"); + std::vector enums = + CSMWorld::Columns::getEnums (CSMWorld::Columns::ColumnId_Modification); + + static const char *sIcons[] = + { + ":./base.png", ":./modified.png", ":./added.png", ":./removed.png", ":./removed.png", 0 + }; + + for (int i=0; sIcons[i]; ++i) + add (i, enums.at (i).c_str(), sIcons[i]); } From 842a616909fee9e1c79d78789125e629d095354f Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 3 Sep 2013 14:18:34 +0200 Subject: [PATCH 06/12] more cleanup --- apps/opencs/model/world/universalid.cpp | 21 ---------- apps/opencs/model/world/universalid.hpp | 3 -- apps/opencs/view/world/refidtypedelegate.cpp | 40 ++++++++++---------- 3 files changed, 21 insertions(+), 43 deletions(-) diff --git a/apps/opencs/model/world/universalid.cpp b/apps/opencs/model/world/universalid.cpp index 42ebd1f80..1cc4ca3c4 100644 --- a/apps/opencs/model/world/universalid.cpp +++ b/apps/opencs/model/world/universalid.cpp @@ -90,8 +90,6 @@ namespace { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker }; - - static const unsigned int IDARG_SIZE = sizeof (sIdArg) / sizeof (TypeData); } CSMWorld::UniversalId::UniversalId (const std::string& universalId) @@ -293,25 +291,6 @@ std::vector CSMWorld::UniversalId::listReferenceabl return list; } -std::pair CSMWorld::UniversalId::getIdArgPair (unsigned int index) -{ - std::pair retPair; - - if ( index < IDARG_SIZE ) - { - retPair.first = sIdArg[index].mType; - retPair.second = sIdArg[index].mName; - } - - return retPair; -} - -unsigned int CSMWorld::UniversalId::getIdArgSize() -{ - return IDARG_SIZE; -} - - bool CSMWorld::operator== (const CSMWorld::UniversalId& left, const CSMWorld::UniversalId& right) { return left.isEqual (right); diff --git a/apps/opencs/model/world/universalid.hpp b/apps/opencs/model/world/universalid.hpp index 8042c3dfd..341b941e6 100644 --- a/apps/opencs/model/world/universalid.hpp +++ b/apps/opencs/model/world/universalid.hpp @@ -134,9 +134,6 @@ namespace CSMWorld ///< Will return an empty string, if no icon is available. static std::vector listReferenceableTypes(); - - static std::pair getIdArgPair (unsigned int index); - static unsigned int getIdArgSize (); }; bool operator== (const UniversalId& left, const UniversalId& right); diff --git a/apps/opencs/view/world/refidtypedelegate.cpp b/apps/opencs/view/world/refidtypedelegate.cpp index bf3acbb20..7cffbf3dd 100755 --- a/apps/opencs/view/world/refidtypedelegate.cpp +++ b/apps/opencs/view/world/refidtypedelegate.cpp @@ -1,4 +1,5 @@ #include "refidtypedelegate.hpp" + #include "../../model/world/universalid.hpp" CSVWorld::RefIdTypeDelegate::RefIdTypeDelegate @@ -6,6 +7,26 @@ CSVWorld::RefIdTypeDelegate::RefIdTypeDelegate : DataDisplayDelegate (values, icons, undoStack, parent) {} +bool CSVWorld::RefIdTypeDelegate::updateEditorSetting (const QString &settingName, const QString &settingValue) +{ + if (settingName == "Referenceable ID Type Display") + { + if (settingValue == "Icon and Text") + mDisplayMode = Mode_IconAndText; + + else if (settingValue == "Icon Only") + mDisplayMode = Mode_IconOnly; + + else if (settingValue == "Text Only") + mDisplayMode = Mode_TextOnly; + + return true; + } + + return false; +} + + CSVWorld::RefIdTypeDelegateFactory::RefIdTypeDelegateFactory() { UidTypeList uIdList = buildUidTypeList(); @@ -39,22 +60,3 @@ CSVWorld::RefIdTypeDelegateFactory::UidTypeList CSVWorld::RefIdTypeDelegateFacto return list; } - -bool CSVWorld::RefIdTypeDelegate::updateEditorSetting (const QString &settingName, const QString &settingValue) -{ - if (settingName == "Referenceable ID Type Display") - { - if (settingValue == "Icon and Text") - mDisplayMode = Mode_IconAndText; - - else if (settingValue == "Icon Only") - mDisplayMode = Mode_IconOnly; - - else if (settingValue == "Text Only") - mDisplayMode = Mode_TextOnly; - - return true; - } - - return false; -} From 8bebe7179cb08cd750eef2020e01a0d3a2dadfc8 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 5 Sep 2013 13:58:36 +0200 Subject: [PATCH 07/12] some UniversalId fixes --- apps/opencs/model/world/universalid.cpp | 18 +++++++++++++++++- apps/opencs/model/world/universalid.hpp | 5 +++-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/apps/opencs/model/world/universalid.cpp b/apps/opencs/model/world/universalid.cpp index 1cc4ca3c4..d360fde8f 100644 --- a/apps/opencs/model/world/universalid.cpp +++ b/apps/opencs/model/world/universalid.cpp @@ -80,7 +80,7 @@ namespace { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Static, "Static", ":./static.png" }, { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Weapon, "Weapon", ":./weapon.png" }, { CSMWorld::UniversalId::Class_SubRecord, CSMWorld::UniversalId::Type_Reference, "Reference", 0 }, - + { CSMWorld::UniversalId::Class_SubRecord, CSMWorld::UniversalId::Type_Filter, "Filter", 0 }, { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker }; @@ -149,6 +149,22 @@ CSMWorld::UniversalId::UniversalId (Type type) : mArgumentType (ArgumentType_Non return; } + for (int i=0; sIdArg[i].mName; ++i) + if (type==sIdArg[i].mType) + { + mArgumentType = ArgumentType_Id; + mClass = sIdArg[i].mClass; + return; + } + + for (int i=0; sIndexArg[i].mName; ++i) + if (type==sIndexArg[i].mType) + { + mArgumentType = ArgumentType_Index; + mClass = sIndexArg[i].mClass; + return; + } + throw std::logic_error ("invalid argument-less UniversalId type"); } diff --git a/apps/opencs/model/world/universalid.hpp b/apps/opencs/model/world/universalid.hpp index 341b941e6..aa0cdacc0 100644 --- a/apps/opencs/model/world/universalid.hpp +++ b/apps/opencs/model/world/universalid.hpp @@ -34,7 +34,7 @@ namespace CSMWorld enum Type { - Type_None, + Type_None = 0, Type_Globals, Type_Global, Type_VerificationResults, @@ -89,6 +89,8 @@ namespace CSMWorld Type_Filters }; + enum { NumberOfTypes = Type_Filters+1 }; + private: Class mClass; @@ -102,7 +104,6 @@ namespace CSMWorld UniversalId (const std::string& universalId); UniversalId (Type type = Type_None); - ///< Using a type for a non-argument-less UniversalId will throw an exception. UniversalId (Type type, const std::string& id); ///< Using a type for a non-ID-argument UniversalId will throw an exception. From f2e86e860e4100e1c15b6f6eef8850f6e99bcaea Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 5 Sep 2013 13:59:09 +0200 Subject: [PATCH 08/12] allow the use of record types in string filters --- apps/opencs/model/world/columns.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/apps/opencs/model/world/columns.cpp b/apps/opencs/model/world/columns.cpp index 2a47a73fb..80525b59e 100644 --- a/apps/opencs/model/world/columns.cpp +++ b/apps/opencs/model/world/columns.cpp @@ -3,6 +3,8 @@ #include +#include "universalid.hpp" + namespace CSMWorld { namespace Columns @@ -271,7 +273,7 @@ namespace bool CSMWorld::Columns::hasEnums (ColumnId column) { - return getEnumNames (column)!=0; + return getEnumNames (column)!=0 || column==ColumnId_RecordType; } std::vector CSMWorld::Columns::getEnums (ColumnId column) @@ -281,6 +283,13 @@ std::vector CSMWorld::Columns::getEnums (ColumnId column) if (const char **table = getEnumNames (column)) for (int i=0; table[i]; ++i) enums.push_back (table[i]); + else if (column==ColumnId_RecordType) + { + enums.push_back (""); // none + + for (int i=UniversalId::Type_None+1; i (i)).getTypeName()); + } return enums; } \ No newline at end of file From 9332684335befac65612392b99a30b6adf5f73df Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 5 Sep 2013 15:05:49 +0200 Subject: [PATCH 09/12] allow the use of value types in string filters --- apps/opencs/model/world/columns.cpp | 6 +++++ apps/opencs/view/world/vartypedelegate.cpp | 29 +++++----------------- components/esm/variant.hpp | 2 +- 3 files changed, 13 insertions(+), 24 deletions(-) diff --git a/apps/opencs/model/world/columns.cpp b/apps/opencs/model/world/columns.cpp index 80525b59e..5616a4a48 100644 --- a/apps/opencs/model/world/columns.cpp +++ b/apps/opencs/model/world/columns.cpp @@ -252,6 +252,11 @@ namespace "Base", "Modified", "Added", "Deleted", "Deleted", 0 }; + static const char *sVarTypeEnums[] = + { + "unknown", "none", "short", "integer", "long", "float", "string", 0 + }; + const char **getEnumNames (CSMWorld::Columns::ColumnId column) { switch (column) @@ -265,6 +270,7 @@ namespace case CSMWorld::Columns::ColumnId_CreatureType: return sCreatureTypes; case CSMWorld::Columns::ColumnId_WeaponType: return sWeaponTypes; case CSMWorld::Columns::ColumnId_Modification: return sModificationEnums; + case CSMWorld::Columns::ColumnId_ValueType: return sVarTypeEnums; default: return 0; } diff --git a/apps/opencs/view/world/vartypedelegate.cpp b/apps/opencs/view/world/vartypedelegate.cpp index 72cbaae42..15ce2dbaf 100644 --- a/apps/opencs/view/world/vartypedelegate.cpp +++ b/apps/opencs/view/world/vartypedelegate.cpp @@ -4,6 +4,7 @@ #include #include "../../model/world/commands.hpp" +#include "../../model/world/columns.hpp" void CSVWorld::VarTypeDelegate::addCommands (QAbstractItemModel *model, const QModelIndex& index, int type) const @@ -75,29 +76,11 @@ CSVWorld::CommandDelegate *CSVWorld::VarTypeDelegateFactory::makeDelegate (QUndo void CSVWorld::VarTypeDelegateFactory::add (ESM::VarType type) { - struct Name - { - ESM::VarType mType; - const char *mName; - }; + std::vector enums = + CSMWorld::Columns::getEnums (CSMWorld::Columns::ColumnId_ValueType); - static const Name sNames[] = - { - { ESM::VT_None, "empty" }, - { ESM::VT_Short, "short" }, - { ESM::VT_Int, "integer" }, - { ESM::VT_Long, "long" }, - { ESM::VT_Float, "float" }, - { ESM::VT_String, "string" }, - { ESM::VT_Unknown, 0 } // end marker - }; + if (type<0 && type>=enums.size()) + throw std::logic_error ("Unsupported variable type"); - for (int i=0; sNames[i].mName; ++i) - if (sNames[i].mType==type) - { - mValues.push_back (std::make_pair (type, sNames[i].mName)); - return; - } - - throw std::logic_error ("Unsupported variable type"); + mValues.push_back (std::make_pair (type, QString::fromUtf8 (enums[type].c_str()))); } diff --git a/components/esm/variant.hpp b/components/esm/variant.hpp index 8c5f3b3d4..2bba60a15 100644 --- a/components/esm/variant.hpp +++ b/components/esm/variant.hpp @@ -11,7 +11,7 @@ namespace ESM enum VarType { - VT_Unknown, + VT_Unknown = 0, VT_None, VT_Short, // stored as a float, kinda VT_Int, From f3ce9c22a1a6439f3b6bb489cf20658c7934bc0a Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 5 Sep 2013 15:22:14 +0200 Subject: [PATCH 10/12] rewrote value node to support half-sided intervals (meaning infinity or -infinity for the missing half) --- apps/opencs/model/filter/parser.cpp | 12 +++---- apps/opencs/model/filter/valuenode.cpp | 44 ++++++++++++++++++++------ apps/opencs/model/filter/valuenode.hpp | 15 +++++++-- 3 files changed, 53 insertions(+), 18 deletions(-) diff --git a/apps/opencs/model/filter/parser.cpp b/apps/opencs/model/filter/parser.cpp index 15cdbfce2..5b1679cdd 100644 --- a/apps/opencs/model/filter/parser.cpp +++ b/apps/opencs/model/filter/parser.cpp @@ -437,22 +437,22 @@ boost::shared_ptr CSMFilter::Parser::parseValue() // parse value double lower = 0; double upper = 0; - bool min = false; - bool max = false; + ValueNode::Type lowerType = ValueNode::Type_Open; + ValueNode::Type upperType = ValueNode::Type_Open; token = getNextToken(); if (token.mType==Token::Type_Number) { // single value - min = max = true; lower = upper = token.mNumber; + lowerType = upperType = ValueNode::Type_Closed; } else { // interval if (token.mType==Token::Type_OpenSquare) - min = true; + lowerType = ValueNode::Type_Closed; else if (token.mType!=Token::Type_CloseSquare && token.mType!=Token::Type_Open) { error(); @@ -490,7 +490,7 @@ boost::shared_ptr CSMFilter::Parser::parseValue() token = getNextToken(); if (token.mType==Token::Type_CloseSquare) - max = true; + upperType = ValueNode::Type_Closed; else if (token.mType!=Token::Type_OpenSquare && token.mType!=Token::Type_Close) { error(); @@ -506,7 +506,7 @@ boost::shared_ptr CSMFilter::Parser::parseValue() return boost::shared_ptr(); } - return boost::shared_ptr (new ValueNode (columnId, lower, upper, min, max)); + return boost::shared_ptr (new ValueNode (columnId, lowerType, upperType, lower, upper)); } void CSMFilter::Parser::error() diff --git a/apps/opencs/model/filter/valuenode.cpp b/apps/opencs/model/filter/valuenode.cpp index f6cb20e4c..7eeb6beab 100644 --- a/apps/opencs/model/filter/valuenode.cpp +++ b/apps/opencs/model/filter/valuenode.cpp @@ -7,10 +7,9 @@ #include "../world/columns.hpp" #include "../world/idtable.hpp" -CSMFilter::ValueNode::ValueNode (int columnId, - double lower, double upper, bool min, bool max) -: mColumnId (columnId), mLower (lower), mUpper (upper), mMin (min), mMax (max) -{} +CSMFilter::ValueNode::ValueNode (int columnId, Type lowerType, Type upperType, + double lower, double upper) +: mColumnId (columnId), mLowerType (lowerType), mUpperType (upperType), mLower (lower), mUpper (upper){} bool CSMFilter::ValueNode::test (const CSMWorld::IdTable& table, int row, const std::map& columns) const @@ -33,10 +32,21 @@ bool CSMFilter::ValueNode::test (const CSMWorld::IdTable& table, int row, double value = data.toDouble(); - if (mLower==mUpper && mMin && mMax) - return value==mLower; + switch (mLowerType) + { + case Type_Closed: if (value=mLower : value>mLower) && (mMax ? value<=mUpper : valuemUpper) return false; break; + case Type_Open: if (value>=mUpper) return false; break; + case Type_Infinite: break; + } + + return true; } std::vector CSMFilter::ValueNode::getReferencedColumns() const @@ -60,10 +70,26 @@ std::string CSMFilter::ValueNode::toString (bool numericColumns) const stream << ", \""; - if (mLower==mUpper && mMin && mMax) + if (mLower==mUpper && mLowerType!=Type_Infinite && mUpperType!=Type_Infinite) stream << mLower; else - stream << (mMin ? "[" : "(") << mLower << ", " << mUpper << (mMax ? "]" : ")"); + { + switch (mLowerType) + { + case Type_Closed: stream << "[" << mLower; break; + case Type_Open: stream << "(" << mLower; break; + case Type_Infinite: stream << "("; break; + } + + stream << ", "; + + switch (mUpperType) + { + case Type_Closed: stream << mUpper << "]"; break; + case Type_Open: stream << mUpper << ")"; break; + case Type_Infinite: stream << ")"; break; + } + } stream << ")"; diff --git a/apps/opencs/model/filter/valuenode.hpp b/apps/opencs/model/filter/valuenode.hpp index faaa1e2ff..b1050709d 100644 --- a/apps/opencs/model/filter/valuenode.hpp +++ b/apps/opencs/model/filter/valuenode.hpp @@ -7,16 +7,25 @@ namespace CSMFilter { class ValueNode : public LeafNode { + public: + + enum Type + { + Type_Closed, Type_Open, Type_Infinite + }; + + private: + int mColumnId; std::string mText; double mLower; double mUpper; - bool mMin; - bool mMax; + Type mLowerType; + Type mUpperType; public: - ValueNode (int columnId, double lower, double upper, bool min, bool max); + ValueNode (int columnId, Type lowerType, Type upperType, double lower, double upper); virtual bool test (const CSMWorld::IdTable& table, int row, const std::map& columns) const; From 645b50ef36150f47d799919e5353cddd67670798 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 5 Sep 2013 15:38:28 +0200 Subject: [PATCH 11/12] added support for half-sided intervals to filter parser --- apps/opencs/model/filter/parser.cpp | 42 +++++++++++++++++------------ 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/apps/opencs/model/filter/parser.cpp b/apps/opencs/model/filter/parser.cpp index 5b1679cdd..8567e0a95 100644 --- a/apps/opencs/model/filter/parser.cpp +++ b/apps/opencs/model/filter/parser.cpp @@ -461,17 +461,23 @@ boost::shared_ptr CSMFilter::Parser::parseValue() token = getNextToken(); - if (token.mType!=Token::Type_Number) + if (token.mType==Token::Type_Number) { - error(); - return boost::shared_ptr(); + lower = token.mNumber; + + token = getNextToken(); + + if (token.mType!=Token::Type_Comma) + { + error(); + return boost::shared_ptr(); + } } - - lower = token.mNumber; - - token = getNextToken(); - - if (token.mType!=Token::Type_Comma) + else if (token.mType==Token::Type_Comma) + { + lowerType = ValueNode::Type_Infinite; + } + else { error(); return boost::shared_ptr(); @@ -479,18 +485,20 @@ boost::shared_ptr CSMFilter::Parser::parseValue() token = getNextToken(); - if (token.mType!=Token::Type_Number) + if (token.mType==Token::Type_Number) { - error(); - return boost::shared_ptr(); + upper = token.mNumber; + + token = getNextToken(); } - - upper = token.mNumber; - - token = getNextToken(); + else + upperType = ValueNode::Type_Infinite; if (token.mType==Token::Type_CloseSquare) - upperType = ValueNode::Type_Closed; + { + if (upperType!=ValueNode::Type_Infinite) + upperType = ValueNode::Type_Closed; + } else if (token.mType!=Token::Type_OpenSquare && token.mType!=Token::Type_Close) { error(); From 8f0ab29a9f5d9c5d44dcbd5b50e82949e52fbe27 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 5 Sep 2013 15:47:38 +0200 Subject: [PATCH 12/12] allow the use of keywords for strings without quotation marks --- apps/opencs/model/filter/parser.cpp | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/apps/opencs/model/filter/parser.cpp b/apps/opencs/model/filter/parser.cpp index 8567e0a95..8f4fcb70c 100644 --- a/apps/opencs/model/filter/parser.cpp +++ b/apps/opencs/model/filter/parser.cpp @@ -49,19 +49,31 @@ namespace CSMFilter Token (Type type = Type_None); + Token (Type type, const std::string& string); + ///< Non-string type that can also be interpreted as a string. + Token (const std::string& string); Token (double number); operator bool() const; + + bool isString() const; }; Token::Token (Type type) : mType (type) {} + Token::Token (Type type, const std::string& string) : mType (type), mString (string) {} + Token::Token (const std::string& string) : mType (Type_String), mString (string) {} Token::Token (double number) : mType (Type_Number), mNumber (number) {} + bool Token::isString() const + { + return mType==Type_String || mType>=Type_Keyword_True; + } + Token::operator bool() const { return mType!=Type_None; @@ -182,7 +194,7 @@ CSMFilter::Token CSMFilter::Parser::checkKeywords (const Token& token) for (int i=0; sKeywords[i]; ++i) if (sKeywords[i]==string || (string.size()==1 && sKeywords[i][0]==string[0])) - return Token (static_cast (i+Token::Type_Keyword_True)); + return Token (static_cast (i+Token::Type_Keyword_True), token.mString); return token; } @@ -351,7 +363,7 @@ boost::shared_ptr CSMFilter::Parser::parseText() if (static_cast (token.mNumber)==token.mNumber) columnId = static_cast (token.mNumber); } - else if (token.mType==Token::Type_String) + else if (token.isString()) { columnId = CSMWorld::Columns::getId (token.mString); } @@ -373,7 +385,7 @@ boost::shared_ptr CSMFilter::Parser::parseText() // parse text pattern token = getNextToken(); - if (token.mType!=Token::Type_String) + if (!token.isString()) { error(); return boost::shared_ptr(); @@ -415,7 +427,7 @@ boost::shared_ptr CSMFilter::Parser::parseValue() if (static_cast (token.mNumber)==token.mNumber) columnId = static_cast (token.mNumber); } - else if (token.mType==Token::Type_String) + else if (token.isString()) { columnId = CSMWorld::Columns::getId (token.mString); } @@ -561,6 +573,8 @@ bool CSMFilter::Parser::parse (const std::string& filter, bool allowPredefined) return true; } + // We do not use isString() here, because there could be a pre-defined filter with an ID that is + // equal a filter keyword. else if (token.mType==Token::Type_String && allowPredefined) { if (getNextToken()!=Token (Token::Type_EOS))