diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index babd3363fe..cfe084e2cf 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -25,7 +25,7 @@ opencs_units (model/world opencs_units_noqt (model/world universalid record commands columnbase scriptcontext cell refidcollection refidadapter refiddata refidadapterimp ref collectionbase refcollection columns infocollection tablemimedata cellcoordinates cellselection resources resourcesmanager scope - pathgrid landtexture land nestedtablewrapper nestedadapters nestedcollection nestedcoladapterimp + pathgrid landtexture land nestedtablewrapper nestedcollection nestedcoladapterimp ) opencs_hdrs_noqt (model/world diff --git a/apps/opencs/model/world/nestedadapters.cpp b/apps/opencs/model/world/nestedadapters.cpp deleted file mode 100644 index 1c8b1eff18..0000000000 --- a/apps/opencs/model/world/nestedadapters.cpp +++ /dev/null @@ -1,8 +0,0 @@ -#include "nestedadapters.hpp" - -CSMWorld::HelperBase::HelperBase(CSMWorld::UniversalId::Type type) - : mType(type) -{} - -CSMWorld::HelperBase::~HelperBase() -{} diff --git a/apps/opencs/model/world/nestedadapters.hpp b/apps/opencs/model/world/nestedadapters.hpp deleted file mode 100644 index 97046276f0..0000000000 --- a/apps/opencs/model/world/nestedadapters.hpp +++ /dev/null @@ -1,420 +0,0 @@ -#ifndef CSM_WORLD_NESTEDADAPTERS_H -#define CSM_WORLD_NESTEDADAPTERS_H - -#include -#include -#include - -#include "universalid.hpp" -#include "nestedtablewrapper.hpp" -#include "record.hpp" -#include "refiddata.hpp" -#include "refidadapter.hpp" -#include -#include -#include -#include -#include -#include - -#include - -/*! \brief - * Nested adapter redirects responsibility to the helper class. Helper classes are polymorhpic (vide HelperBase and CastableHelper) and most likely templates. - */ - -namespace CSMWorld -{ - class RefIdColumn; - - class HelperBase - { - protected: - const CSMWorld::UniversalId::Type mType; - - public: - HelperBase(CSMWorld::UniversalId::Type type); - - virtual ~HelperBase(); - - virtual void setNestedTable(RefIdData& data, - int index, - const NestedTableWrapperBase& nestedTable) = 0; - - virtual NestedTableWrapperBase* nestedTable(const RefIdData& data, - int index) const = 0; - - virtual QVariant getNestedData(const CSMWorld::RefIdData& data, - int index, - int subRowIndex, - int subColIndex) const = 0; - - virtual void removeNestedRow (RefIdData& data, - int index, - int rowToRemove) const = 0; - - virtual void setNestedData (RefIdData& data, - int index, - const QVariant& value, - int subRowIndex, - int subColIndex) const = 0; - - virtual void addNestedRow (RefIdData& data, - int index, - int position) const = 0; - - virtual int getNestedColumnsCount(const RefIdData& data) const = 0; - - virtual int getNestedRowsCount(const RefIdData& data, - int index) const = 0; - }; - - template - class CastableHelper : public HelperBase - { - - public: - CastableHelper(CSMWorld::UniversalId::Type type) - : HelperBase(type) {} - - protected: - const Record& getRecord(const RefIdData& data, int index) const - { - return dynamic_cast&> ( - data.getRecord (RefIdData::LocalIndex (index, mType))); - } - - Record& getRecord(RefIdData& data, int index) const - { - return dynamic_cast&> ( - data.getRecord (RefIdData::LocalIndex (index, mType))); - } - }; - - template - class SpellsHelper : public CastableHelper - { - public: - - SpellsHelper(CSMWorld::UniversalId::Type type) - : CastableHelper(type) {} - - virtual void setNestedTable(RefIdData& data, - int index, - const NestedTableWrapperBase& nestedTable) - { - CastableHelper::getRecord(data, index).get().mSpells.mList = - (static_cast >&>(nestedTable)).mNestedTable; - } - - virtual NestedTableWrapperBase* nestedTable(const RefIdData& data, - int index) const - { - return new NestedTableWrapper >(CastableHelper::getRecord(data, index).get().mSpells.mList); - } - - virtual QVariant getNestedData(const CSMWorld::RefIdData& data, - int index, - int subRowIndex, - int subColIndex) const - { - const std::string& content = CastableHelper::getRecord(data, index).get().mSpells.mList.at(subRowIndex); - - if (subColIndex == 0) - { - return QString::fromUtf8(content.c_str()); - } - - throw std::logic_error("Trying to access non-existing column in the nested table!"); - } - - virtual void removeNestedRow (RefIdData& data, int index, int rowToRemove) const - { - std::vector& list = CastableHelper::getRecord(data, index).get().mSpells.mList; - - list.erase (list.begin () + rowToRemove); - } - - void setNestedData (RefIdData& data, - int index, - const QVariant& value, - int subRowIndex, - int subColIndex) const - { - if (subColIndex == 0) - { - CastableHelper::getRecord(data, index).get().mSpells.mList.at(subRowIndex) = std::string(value.toString().toUtf8()); - } - else - throw std::logic_error("Trying to access non-existing column in the nested table!"); - } - - virtual void addNestedRow (RefIdData& data, int index, int position) const - { - std::vector& list = CastableHelper::getRecord(data, index).get().mSpells.mList; - - std::string newString; - if (position >= (int)list.size()) - { - list.push_back(newString); - return; - } - - list.insert(list.begin()+position, newString); - } - - virtual int getNestedColumnsCount(const RefIdData& data) const - { - return 1; - } - - - virtual int getNestedRowsCount(const RefIdData& data, - int index) const - { - return CastableHelper::getRecord(data, index).get().mSpells.mList.size(); - } - - }; - - template - class DestinationsHelper : public CastableHelper - { - public: - - DestinationsHelper(CSMWorld::UniversalId::Type type) - : CastableHelper(type) {} - - virtual void setNestedTable(RefIdData& data, - int index, - const NestedTableWrapperBase& nestedTable) - { - CastableHelper::getRecord(data, index).get().mTransport.mList = - (static_cast >&>(nestedTable)).mNestedTable; - } - - virtual NestedTableWrapperBase* nestedTable(const RefIdData& data, - int index) const - { - return new NestedTableWrapper >(CastableHelper::getRecord(data, index).get().mTransport.mList); - } - - virtual QVariant getNestedData(const CSMWorld::RefIdData& data, - int index, - int subRowIndex, - int subColIndex) const - { - const ESM::Transport::Dest& content = CastableHelper::getRecord(data, index).get().mTransport.mList.at(subRowIndex); - - switch (subColIndex) - { - case 0: - return QString::fromUtf8(content.mCellName.c_str()); - - case 1: - return content.mPos.pos[0]; - - case 2: - return content.mPos.pos[1]; - - case 3: - return content.mPos.pos[2]; - - case 4: - return content.mPos.rot[0]; - - case 5: - return content.mPos.rot[1]; - - case 6: - return content.mPos.rot[2]; - - default: - throw std::logic_error("Trying to access non-existing column in the nested table!"); - } - } - - virtual void removeNestedRow (RefIdData& data, int index, int rowToRemove) const - { - std::vector& list = CastableHelper::getRecord(data, index).get().mTransport.mList; - - list.erase (list.begin () + rowToRemove); - } - - void setNestedData (RefIdData& data, - int index, - const QVariant& value, - int subRowIndex, - int subColIndex) const - { - switch(subColIndex) - { - case 0: - CastableHelper::getRecord(data, index).get().mTransport.mList.at(subRowIndex).mCellName = std::string(value.toString().toUtf8().constData()); - break; - - case 1: - CastableHelper::getRecord(data, index).get().mTransport.mList.at(subRowIndex).mPos.pos[0] = value.toFloat(); - break; - - case 2: - CastableHelper::getRecord(data, index).get().mTransport.mList.at(subRowIndex).mPos.pos[1] = value.toFloat(); - break; - - case 3: - CastableHelper::getRecord(data, index).get().mTransport.mList.at(subRowIndex).mPos.pos[2] = value.toFloat(); - break; - - case 4: - CastableHelper::getRecord(data, index).get().mTransport.mList.at(subRowIndex).mPos.rot[0] = value.toFloat(); - break; - - case 5: - CastableHelper::getRecord(data, index).get().mTransport.mList.at(subRowIndex).mPos.rot[1] = value.toFloat(); - break; - - case 6: - CastableHelper::getRecord(data, index).get().mTransport.mList.at(subRowIndex).mPos.rot[2] = value.toFloat(); - break; - - default: - throw std::logic_error("Trying to access non-existing column in the nested table!"); - } - } - - virtual void addNestedRow (RefIdData& data, int index, int position) const - { - std::vector& list = CastableHelper::getRecord(data, index).get().mTransport.mList; - - ESM::Position newPos; - for (unsigned i = 0; i < 3; ++i) - { - newPos.pos[i] = 0; - newPos.rot[i] = 0; - } - - ESM::Transport::Dest newRow; - newRow.mPos = newPos; - newRow.mCellName = ""; - - if (position >= (int)list.size()) - { - list.push_back(newRow); - return; - } - - list.insert(list.begin()+position, newRow); - } - - virtual int getNestedColumnsCount(const RefIdData& data) const - { - return 7; - } - - virtual int getNestedRowsCount(const RefIdData& data, - int index) const - { - return CastableHelper::getRecord(data, index).get().mTransport.mList.size(); - } - - }; - - template - class InventoryHelper : public CastableHelper - { - public: - - InventoryHelper(CSMWorld::UniversalId::Type type) - : CastableHelper(type) {} - - virtual void setNestedTable(RefIdData& data, - int index, - const NestedTableWrapperBase& nestedTable) - { - CastableHelper::getRecord(data, index).get().mInventory.mList = - (static_cast >&>(nestedTable)).mNestedTable; - } - - virtual NestedTableWrapperBase* nestedTable(const RefIdData& data, - int index) const - { - return new NestedTableWrapper >(CastableHelper::getRecord(data, index).get().mInventory.mList); - } - - virtual QVariant getNestedData(const CSMWorld::RefIdData& data, - int index, - int subRowIndex, - int subColIndex) const - { - const ESM::ContItem& content = CastableHelper::getRecord(data, index).get().mInventory.mList.at(subRowIndex); - - switch (subColIndex) - { - case 0: - return QString::fromUtf8(content.mItem.toString().c_str()); - - case 1: - return content.mCount; - - default: - throw std::logic_error("Trying to access non-existing column in the nested table!"); - } - } - - virtual void removeNestedRow (RefIdData& data, int index, int rowToRemove) const - { - std::vector& list = CastableHelper::getRecord(data, index).get().mInventory.mList; - - list.erase (list.begin () + rowToRemove); - } - - void setNestedData (RefIdData& data, - int index, - const QVariant& value, - int subRowIndex, - int subColIndex) const - { - switch(subColIndex) - { - case 0: - CastableHelper::getRecord(data, index).get().mInventory.mList.at(subRowIndex).mItem.assign(std::string(value.toString().toUtf8().constData())); - break; - - case 1: - CastableHelper::getRecord(data, index).get().mInventory.mList.at(subRowIndex).mCount = value.toInt(); - break; - - default: - throw std::logic_error("Trying to access non-existing column in the nested table!"); - } - } - - virtual void addNestedRow (RefIdData& data, int index, int position) const - { - std::vector& list = CastableHelper::getRecord(data, index).get().mInventory.mList; - - ESM::ContItem newRow = {0, {""}}; - if (position >= (int)list.size()) - { - list.push_back(newRow); - return; - } - - list.insert(list.begin()+position, newRow); - } - - virtual int getNestedColumnsCount(const RefIdData& data) const - { - return 2; - } - - virtual int getNestedRowsCount(const RefIdData& data, - int index) const - { - return CastableHelper::getRecord(data, index).get().mInventory.mList.size(); - } - - }; -} - -#endif diff --git a/apps/opencs/model/world/refidadapter.cpp b/apps/opencs/model/world/refidadapter.cpp index a12a95196c..37cb67bca3 100644 --- a/apps/opencs/model/world/refidadapter.cpp +++ b/apps/opencs/model/world/refidadapter.cpp @@ -1,9 +1,5 @@ #include "refidadapter.hpp" -#include "nestedtablewrapper.hpp" - -#include - CSMWorld::RefIdAdapter::RefIdAdapter() {} CSMWorld::RefIdAdapter::~RefIdAdapter() {} @@ -11,84 +7,3 @@ CSMWorld::RefIdAdapter::~RefIdAdapter() {} CSMWorld::NestedRefIdAdapterBase::NestedRefIdAdapterBase() {} CSMWorld::NestedRefIdAdapterBase::~NestedRefIdAdapterBase() {} - -CSMWorld::NestedRefIdAdapter::NestedRefIdAdapter() -{} - -CSMWorld::NestedRefIdAdapter::~NestedRefIdAdapter() -{ - for (unsigned i = 0; i < mAssociatedColumns.size(); ++i) - { - delete mAssociatedColumns[i].second; - } -} - -void CSMWorld::NestedRefIdAdapter::setNestedData (const RefIdColumn *column, RefIdData& data, int row, - const QVariant& value, int subRowIndex, int subColIndex) const -{ - getHelper(column)->setNestedData(data, row, value, subRowIndex, subColIndex); -} - -QVariant CSMWorld::NestedRefIdAdapter::getNestedData(const RefIdColumn *column, const RefIdData& data, - int index, int subRowIndex, int subColIndex) const -{ - return getHelper(column)->getNestedData(data, index, subRowIndex, subColIndex); -} - -int CSMWorld::NestedRefIdAdapter::getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const -{ - return getHelper(column)->getNestedColumnsCount(data); -} - - -int CSMWorld::NestedRefIdAdapter::getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const -{ - return getHelper(column)->getNestedRowsCount(data, index); -} - - -void CSMWorld::NestedRefIdAdapter::removeNestedRow (const RefIdColumn *column, RefIdData& data, int index, int rowToRemove) const -{ - getHelper(column)->removeNestedRow(data, index, rowToRemove); -} - -void CSMWorld::NestedRefIdAdapter::addNestedRow (const RefIdColumn *column, RefIdData& data, int index, int position) const -{ - getHelper(column)->addNestedRow(data, index, position); //This code grows more boring and boring. I would love some macros. -} - -void CSMWorld::NestedRefIdAdapter::setNestedTable (const RefIdColumn* column, RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const -{ - getHelper(column)->setNestedTable(data, index, nestedTable); -} - - -CSMWorld::NestedTableWrapperBase* CSMWorld::NestedRefIdAdapter::nestedTable (const RefIdColumn* column, const RefIdData& data, int index) const -{ - return getHelper(column)->nestedTable(data, index); -} - -CSMWorld::HelperBase* CSMWorld::NestedRefIdAdapter::getHelper(const RefIdColumn *column) const -{ - for (unsigned i = 0; i < mAssociatedColumns.size(); ++i) - { - if (mAssociatedColumns[i].first == column) - { - return mAssociatedColumns[i].second; - } - } - - throw std::logic_error("No such column in the nestedrefidadapter"); - - return NULL; -} - -void CSMWorld::NestedRefIdAdapter::setAssocColumns(const std::vector >& assocColumns) -{ - mAssociatedColumns = assocColumns; -} - -void CSMWorld::NestedRefIdAdapter::addAssocColumn(const std::pair & assocColumn) -{ - mAssociatedColumns.push_back(assocColumn); -} diff --git a/apps/opencs/model/world/refidadapter.hpp b/apps/opencs/model/world/refidadapter.hpp index f80ce7ab38..ba9da577de 100644 --- a/apps/opencs/model/world/refidadapter.hpp +++ b/apps/opencs/model/world/refidadapter.hpp @@ -4,8 +4,6 @@ #include #include -#include "nestedadapters.hpp" - /*! \brief * Adapters acts as indirection layer, abstracting details of the record types (in the wrappers) from the higher levels of model. * Please notice that nested adaptor uses helper classes for actually performing any actions. Different record types require different helpers (needs to be created in the subclass and then fetched via member function). @@ -77,47 +75,6 @@ namespace CSMWorld virtual NestedTableWrapperBase* nestedTable (const RefIdColumn* column, const RefIdData& data, int index) const = 0; }; - - class NestedRefIdAdapter : public NestedRefIdAdapterBase - { - std::vector > mAssociatedColumns; //basically, i wanted a map, but with pointer key - - public: - NestedRefIdAdapter(); - - virtual ~NestedRefIdAdapter(); - - virtual void setNestedData (const RefIdColumn *column, RefIdData& data, int row, - const QVariant& value, int subRowIndex, int subColIndex) const; - - virtual QVariant getNestedData (const RefIdColumn *column, const RefIdData& data, - int index, int subRowIndex, int subColIndex) const; - - virtual int getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const; - - virtual int getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const; - - virtual void removeNestedRow (const RefIdColumn *column, RefIdData& data, int index, int rowToRemove) const; - - virtual void addNestedRow (const RefIdColumn *column, RefIdData& data, int index, int position) const; - - virtual void setNestedTable (const RefIdColumn* column, RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const; - - virtual NestedTableWrapperBase* nestedTable (const RefIdColumn* column, const RefIdData& data, int index) const; - - protected: - void setAssocColumns(const std::vector >& assocColumns); - ///The ownership of the Helper pointers is transfered. - ///The ownership of the column pointers it not transfered (it is not surprising, since columns are created by collection). - ///You MUST call this method to setup the nested adaptor! - - void addAssocColumn(const std::pair & assocColumn); - ///Like setAssocColumn, when it is impossible to set all columns at once - - private: - - HelperBase* getHelper(const RefIdColumn *column) const; - }; } #endif diff --git a/apps/opencs/model/world/refidadapterimp.cpp b/apps/opencs/model/world/refidadapterimp.cpp index 42d1aa52e9..cd3a203271 100644 --- a/apps/opencs/model/world/refidadapterimp.cpp +++ b/apps/opencs/model/world/refidadapterimp.cpp @@ -188,13 +188,7 @@ CSMWorld::ContainerRefIdAdapter::ContainerRefIdAdapter (const NameColumns& colum const RefIdColumn *weight, const RefIdColumn *organic, const RefIdColumn *respawn, const RefIdColumn *content) : NameRefIdAdapter (UniversalId::Type_Container, columns), mWeight (weight), mOrganic (organic), mRespawn (respawn), mContent(content) -{ - std::vector > assoCol; - - assoCol.push_back(std::make_pair(content, new InventoryHelper(UniversalId::Type_Container))); - - setAssocColumns(assoCol); -} +{} QVariant CSMWorld::ContainerRefIdAdapter::getData (const RefIdColumn *column, const RefIdData& data, @@ -471,9 +465,7 @@ CSMWorld::NpcColumns::NpcColumns (const ActorColumns& actorColumns) CSMWorld::NpcRefIdAdapter::NpcRefIdAdapter (const NpcColumns& columns) : ActorRefIdAdapter (UniversalId::Type_Npc, columns), mColumns (columns) -{ - NestedRefIdAdapter::addAssocColumn(std::make_pair(columns.mDestinations, new DestinationsHelper(UniversalId::Type_Npc))); -} +{} QVariant CSMWorld::NpcRefIdAdapter::getData (const RefIdColumn *column, const RefIdData& data, int index) const @@ -496,9 +488,6 @@ QVariant CSMWorld::NpcRefIdAdapter::getData (const RefIdColumn *column, const Re if (column==mColumns.mHead) return QString::fromUtf8 (record.get().mHead.c_str()); - if (column==mColumns.mDestinations) - return true; // to show nested tables in dialogue subview, see IdTree::hasChildren() - std::map::const_iterator iter = mColumns.mFlags.find (column); diff --git a/apps/opencs/model/world/refidadapterimp.hpp b/apps/opencs/model/world/refidadapterimp.hpp index 08e2e74938..32e9148c73 100644 --- a/apps/opencs/model/world/refidadapterimp.hpp +++ b/apps/opencs/model/world/refidadapterimp.hpp @@ -11,12 +11,12 @@ #include #include #include +#include #include "record.hpp" #include "refiddata.hpp" #include "universalid.hpp" #include "refidadapter.hpp" -#include "nestedadapters.hpp" namespace CSMWorld { @@ -489,6 +489,7 @@ namespace CSMWorld const RefIdColumn *mAlarm; const RefIdColumn *mInventory; const RefIdColumn *mSpells; + const RefIdColumn *mDestinations; std::map mServices; ActorColumns (const NameColumns& base) : NameColumns (base) {} @@ -496,7 +497,7 @@ namespace CSMWorld /// \brief Adapter for actor IDs (handles common AI functionality) template - class ActorRefIdAdapter : public NameRefIdAdapter, public NestedRefIdAdapter + class ActorRefIdAdapter : public NameRefIdAdapter { ActorColumns mActors; @@ -516,14 +517,7 @@ namespace CSMWorld ActorRefIdAdapter::ActorRefIdAdapter (UniversalId::Type type, const ActorColumns& columns) : NameRefIdAdapter (type, columns), mActors (columns) - { - std::vector > assoCol; - - assoCol.push_back(std::make_pair(mActors.mInventory, new InventoryHelper(type))); - assoCol.push_back(std::make_pair(mActors.mSpells, new SpellsHelper(type))); - - setAssocColumns(assoCol); - } + {} template QVariant ActorRefIdAdapter::getData (const RefIdColumn *column, const RefIdData& data, @@ -553,6 +547,9 @@ namespace CSMWorld if (column==mActors.mSpells) return true; // to show nested tables in dialogue subview, see IdTree::hasChildren() + if (column==mActors.mDestinations) + return true; // to show nested tables in dialogue subview, see IdTree::hasChildren() + std::map::const_iterator iter = mActors.mServices.find (column); @@ -672,7 +669,7 @@ namespace CSMWorld ///< If the data type does not match an exception is thrown. }; - class ContainerRefIdAdapter : public NameRefIdAdapter, public NestedRefIdAdapter + class ContainerRefIdAdapter : public NameRefIdAdapter { const RefIdColumn *mWeight; const RefIdColumn *mOrganic; @@ -790,7 +787,6 @@ namespace CSMWorld const RefIdColumn *mFaction; const RefIdColumn *mHair; const RefIdColumn *mHead; - const RefIdColumn *mDestinations; NpcColumns (const ActorColumns& actorColumns); }; @@ -1060,6 +1056,318 @@ namespace CSMWorld return static_cast(record.get().mInventory.mList.size()); } }; + + template + class NestedSpellRefIdAdapter : public NestedRefIdAdapterBase + { + UniversalId::Type mType; + + // not implemented + NestedSpellRefIdAdapter (const NestedSpellRefIdAdapter&); + NestedSpellRefIdAdapter& operator= (const NestedSpellRefIdAdapter&); + + public: + + NestedSpellRefIdAdapter(UniversalId::Type type) :mType(type) {} + + virtual ~NestedSpellRefIdAdapter() {} + + virtual void addNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int position) const + { + Record& record = + static_cast&> (data.getRecord (RefIdData::LocalIndex (index, mType))); + ESXRecordT caster = record.get(); + + std::vector& list = caster.mSpells.mList; + + std::string newString; + + if (position >= (int)list.size()) + list.push_back(newString); + else + list.insert(list.begin()+position, newString); + + record.setModified (caster); + } + + virtual void removeNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int rowToRemove) const + { + Record& record = + static_cast&> (data.getRecord (RefIdData::LocalIndex (index, mType))); + ESXRecordT caster = record.get(); + + std::vector& list = caster.mSpells.mList; + + if (rowToRemove < 0 || rowToRemove >= static_cast (list.size())) + throw std::runtime_error ("index out of range"); + + list.erase (list.begin () + rowToRemove); + + record.setModified (caster); + } + + virtual void setNestedTable (const RefIdColumn* column, + RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const + { + Record& record = + static_cast&> (data.getRecord (RefIdData::LocalIndex (index, mType))); + ESXRecordT caster = record.get(); + + caster.mSpells.mList = + static_cast >&>(nestedTable).mNestedTable; + + record.setModified (caster); + } + + virtual NestedTableWrapperBase* nestedTable (const RefIdColumn* column, + const RefIdData& data, int index) const + { + const Record& record = + static_cast&> (data.getRecord (RefIdData::LocalIndex (index, mType))); + + // deleted by dtor of NestedTableStoring + return new NestedTableWrapper >(record.get().mSpells.mList); + } + + virtual QVariant getNestedData (const RefIdColumn *column, + const RefIdData& data, int index, int subRowIndex, int subColIndex) const + { + const Record& record = + static_cast&> (data.getRecord (RefIdData::LocalIndex (index, mType))); + + const std::vector& list = record.get().mSpells.mList; + + if (subRowIndex < 0 || subRowIndex >= static_cast (list.size())) + throw std::runtime_error ("index out of range"); + + const std::string& content = list.at(subRowIndex); + + if (subColIndex == 0) + return QString::fromUtf8(content.c_str()); + else + throw std::runtime_error("Trying to access non-existing column in the nested table!"); + } + + virtual void setNestedData (const RefIdColumn *column, + RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const + { + Record& record = + static_cast&> (data.getRecord (RefIdData::LocalIndex (row, mType))); + ESXRecordT caster = record.get(); + std::vector& list = caster.mSpells.mList; + + if (subRowIndex < 0 || subRowIndex >= static_cast (list.size())) + throw std::runtime_error ("index out of range"); + + if (subColIndex == 0) + list.at(subRowIndex) = std::string(value.toString().toUtf8()); + else + throw std::runtime_error("Trying to access non-existing column in the nested table!"); + + record.setModified (caster); + } + + virtual int getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const + { + return 1; + } + + virtual int getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const + { + const Record& record = + static_cast&> (data.getRecord (RefIdData::LocalIndex (index, mType))); + + return static_cast(record.get().mSpells.mList.size()); + } + }; + + template + class NestedTravelRefIdAdapter : public NestedRefIdAdapterBase + { + UniversalId::Type mType; + + // not implemented + NestedTravelRefIdAdapter (const NestedTravelRefIdAdapter&); + NestedTravelRefIdAdapter& operator= (const NestedTravelRefIdAdapter&); + + public: + + NestedTravelRefIdAdapter(UniversalId::Type type) :mType(type) {} + + virtual ~NestedTravelRefIdAdapter() {} + + virtual void addNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int position) const + { + Record& record = + static_cast&> (data.getRecord (RefIdData::LocalIndex (index, mType))); + ESXRecordT traveller = record.get(); + + std::vector& list = traveller.mTransport.mList; + + ESM::Position newPos; + for (unsigned i = 0; i < 3; ++i) + { + newPos.pos[i] = 0; + newPos.rot[i] = 0; + } + + ESM::Transport::Dest newRow; + newRow.mPos = newPos; + newRow.mCellName = ""; + + if (position >= (int)list.size()) + list.push_back(newRow); + else + list.insert(list.begin()+position, newRow); + + record.setModified (traveller); + } + + virtual void removeNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int rowToRemove) const + { + Record& record = + static_cast&> (data.getRecord (RefIdData::LocalIndex (index, mType))); + ESXRecordT traveller = record.get(); + + std::vector& list = traveller.mTransport.mList; + + if (rowToRemove < 0 || rowToRemove >= static_cast (list.size())) + throw std::runtime_error ("index out of range"); + + list.erase (list.begin () + rowToRemove); + + record.setModified (traveller); + } + + virtual void setNestedTable (const RefIdColumn* column, + RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const + { + Record& record = + static_cast&> (data.getRecord (RefIdData::LocalIndex (index, mType))); + ESXRecordT traveller = record.get(); + + traveller.mTransport.mList = + static_cast >&>(nestedTable).mNestedTable; + + record.setModified (traveller); + } + + virtual NestedTableWrapperBase* nestedTable (const RefIdColumn* column, + const RefIdData& data, int index) const + { + const Record& record = + static_cast&> (data.getRecord (RefIdData::LocalIndex (index, mType))); + + // deleted by dtor of NestedTableStoring + return new NestedTableWrapper >(record.get().mTransport.mList); + } + + virtual QVariant getNestedData (const RefIdColumn *column, + const RefIdData& data, int index, int subRowIndex, int subColIndex) const + { + const Record& record = + static_cast&> (data.getRecord (RefIdData::LocalIndex (index, mType))); + + const std::vector& list = record.get().mTransport.mList; + + if (subRowIndex < 0 || subRowIndex >= static_cast (list.size())) + throw std::runtime_error ("index out of range"); + + const ESM::Transport::Dest& content = list.at(subRowIndex); + + switch (subColIndex) + { + case 0: + return QString::fromUtf8(content.mCellName.c_str()); + + case 1: + return content.mPos.pos[0]; + + case 2: + return content.mPos.pos[1]; + + case 3: + return content.mPos.pos[2]; + + case 4: + return content.mPos.rot[0]; + + case 5: + return content.mPos.rot[1]; + + case 6: + return content.mPos.rot[2]; + + default: + throw std::runtime_error("Trying to access non-existing column in the nested table!"); + } + } + + virtual void setNestedData (const RefIdColumn *column, + RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const + { + Record& record = + static_cast&> (data.getRecord (RefIdData::LocalIndex (row, mType))); + ESXRecordT traveller = record.get(); + std::vector& list = traveller.mTransport.mList; + + if (subRowIndex < 0 || subRowIndex >= static_cast (list.size())) + throw std::runtime_error ("index out of range"); + + switch(subColIndex) + { + case 0: + list.at(subRowIndex).mCellName = std::string(value.toString().toUtf8().constData()); + break; + + case 1: + list.at(subRowIndex).mPos.pos[0] = value.toFloat(); + break; + + case 2: + list.at(subRowIndex).mPos.pos[1] = value.toFloat(); + break; + + case 3: + list.at(subRowIndex).mPos.pos[2] = value.toFloat(); + break; + + case 4: + list.at(subRowIndex).mPos.rot[0] = value.toFloat(); + break; + + case 5: + list.at(subRowIndex).mPos.rot[1] = value.toFloat(); + break; + + case 6: + list.at(subRowIndex).mPos.rot[2] = value.toFloat(); + break; + + default: + throw std::runtime_error("Trying to access non-existing column in the nested table!"); + } + + record.setModified (traveller); + } + + virtual int getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const + { + return 7; + } + + virtual int getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const + { + const Record& record = + static_cast&> (data.getRecord (RefIdData::LocalIndex (index, mType))); + + return static_cast(record.get().mTransport.mList.size()); + } + }; } #endif diff --git a/apps/opencs/model/world/refidcollection.cpp b/apps/opencs/model/world/refidcollection.cpp index 755a1f56f4..92cd37d0d3 100644 --- a/apps/opencs/model/world/refidcollection.cpp +++ b/apps/opencs/model/world/refidcollection.cpp @@ -75,8 +75,12 @@ CSMWorld::RefIdCollection::RefIdCollection() PotionColumns potionColumns (inventoryColumns); mColumns.push_back (RefIdColumn (Columns::ColumnId_EffectList, ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue)); potionColumns.mEffects = &mColumns.back(); // see refidadapterimp.hpp - mNestedAdapters.insert (std::make_pair(&mColumns.back(), - new EffectsRefIdAdapter (UniversalId::Type_Potion))); + + std::map effectsMap; + effectsMap.insert( + std::make_pair(UniversalId::Type_Potion, new EffectsRefIdAdapter (UniversalId::Type_Potion))); + mNestedAdapters.push_back (std::make_pair(&mColumns.back(), effectsMap)); + mColumns.back().addColumn( new NestedChildColumn (Columns::ColumnId_EffectId, ColumnBase::Display_String/*, false*/)); mColumns.back().addColumn( @@ -124,10 +128,14 @@ CSMWorld::RefIdCollection::RefIdCollection() // Nested table mColumns.push_back(RefIdColumn (Columns::ColumnId_ActorInventory, ColumnBase::Display_NestedItemList, ColumnBase::Flag_Dialogue)); actorsColumns.mInventory = &mColumns.back(); - mNestedAdapters.insert (std::make_pair(&mColumns.back(), - new NestedInventoryRefIdAdapter (UniversalId::Type_Npc))); - mNestedAdapters.insert (std::make_pair(&mColumns.back(), - new NestedInventoryRefIdAdapter (UniversalId::Type_Creature))); + + std::map inventoryMap; + inventoryMap.insert( + std::make_pair(UniversalId::Type_Npc, new NestedInventoryRefIdAdapter (UniversalId::Type_Npc))); + inventoryMap.insert( + std::make_pair(UniversalId::Type_Creature, new NestedInventoryRefIdAdapter (UniversalId::Type_Creature))); + + mNestedAdapters.push_back (std::make_pair(&mColumns.back(), inventoryMap)); mColumns.back().addColumn( new RefIdColumn (Columns::ColumnId_InventoryItemId, CSMWorld::ColumnBase::Display_String)); mColumns.back().addColumn( @@ -136,9 +144,42 @@ CSMWorld::RefIdCollection::RefIdCollection() // Nested table mColumns.push_back(RefIdColumn (Columns::ColumnId_SpellList, ColumnBase::Display_NestedSpellList, ColumnBase::Flag_Dialogue)); actorsColumns.mSpells = &mColumns.back(); + + std::map spellsMap; + spellsMap.insert( + std::make_pair(UniversalId::Type_Npc, new NestedSpellRefIdAdapter (UniversalId::Type_Npc))); + spellsMap.insert( + std::make_pair(UniversalId::Type_Creature, new NestedSpellRefIdAdapter (UniversalId::Type_Creature))); + + mNestedAdapters.push_back (std::make_pair(&mColumns.back(), spellsMap)); mColumns.back().addColumn( new RefIdColumn (Columns::ColumnId_SpellId, CSMWorld::ColumnBase::Display_String)); + // Nested table + mColumns.push_back(RefIdColumn (Columns::ColumnId_NpcDestinations, ColumnBase::Display_NestedDestinationsList, ColumnBase::Flag_Dialogue)); + actorsColumns.mDestinations = &mColumns.back(); + + std::map destMap; + destMap.insert( + std::make_pair(UniversalId::Type_Npc, new NestedTravelRefIdAdapter (UniversalId::Type_Npc))); + destMap.insert( + std::make_pair(UniversalId::Type_Creature, new NestedTravelRefIdAdapter (UniversalId::Type_Creature))); + mNestedAdapters.push_back (std::make_pair(&mColumns.back(), destMap)); + mColumns.back().addColumn( + new RefIdColumn (Columns::ColumnId_DestinationCell, CSMWorld::ColumnBase::Display_String)); + mColumns.back().addColumn( + new RefIdColumn (Columns::ColumnId_PosX, CSMWorld::ColumnBase::Display_Float)); + mColumns.back().addColumn( + new RefIdColumn (Columns::ColumnId_PosY, CSMWorld::ColumnBase::Display_Float)); + mColumns.back().addColumn( + new RefIdColumn (Columns::ColumnId_PosZ, CSMWorld::ColumnBase::Display_Float)); + mColumns.back().addColumn( + new RefIdColumn (Columns::ColumnId_RotX, CSMWorld::ColumnBase::Display_Float)); + mColumns.back().addColumn( + new RefIdColumn (Columns::ColumnId_RotY, CSMWorld::ColumnBase::Display_Float)); + mColumns.back().addColumn( + new RefIdColumn (Columns::ColumnId_RotZ, CSMWorld::ColumnBase::Display_Float)); + static const struct { int mName; @@ -209,8 +250,12 @@ CSMWorld::RefIdCollection::RefIdCollection() // Nested table mColumns.push_back(RefIdColumn (Columns::ColumnId_ContainerContent, ColumnBase::Display_NestedItemList, ColumnBase::Flag_Dialogue)); const RefIdColumn *content = &mColumns.back(); - mNestedAdapters.insert (std::make_pair(&mColumns.back(), - new NestedInventoryRefIdAdapter (UniversalId::Type_Container))); + + std::map contMap; + contMap.insert( + std::make_pair(UniversalId::Type_Container, new NestedInventoryRefIdAdapter (UniversalId::Type_Container))); + mNestedAdapters.push_back (std::make_pair(&mColumns.back(), contMap)); + mColumns.back().addColumn( new RefIdColumn (Columns::ColumnId_InventoryItemId, CSMWorld::ColumnBase::Display_String)); mColumns.back().addColumn( @@ -351,24 +396,6 @@ CSMWorld::RefIdCollection::RefIdCollection() npcColumns.mFlags.insert (std::make_pair (metalBlood, ESM::NPC::Metal)); - // Nested table - mColumns.push_back(RefIdColumn (Columns::ColumnId_NpcDestinations, ColumnBase::Display_NestedDestinationsList, ColumnBase::Flag_Dialogue)); - npcColumns.mDestinations = &mColumns.back(); - mColumns.back().addColumn( - new RefIdColumn (Columns::ColumnId_DestinationCell, CSMWorld::ColumnBase::Display_String)); - mColumns.back().addColumn( - new RefIdColumn (Columns::ColumnId_PosX, CSMWorld::ColumnBase::Display_Float)); - mColumns.back().addColumn( - new RefIdColumn (Columns::ColumnId_PosY, CSMWorld::ColumnBase::Display_Float)); - mColumns.back().addColumn( - new RefIdColumn (Columns::ColumnId_PosZ, CSMWorld::ColumnBase::Display_Float)); - mColumns.back().addColumn( - new RefIdColumn (Columns::ColumnId_RotX, CSMWorld::ColumnBase::Display_Float)); - mColumns.back().addColumn( - new RefIdColumn (Columns::ColumnId_RotY, CSMWorld::ColumnBase::Display_Float)); - mColumns.back().addColumn( - new RefIdColumn (Columns::ColumnId_RotZ, CSMWorld::ColumnBase::Display_Float)); - WeaponColumns weaponColumns (enchantableColumns); mColumns.push_back (RefIdColumn (Columns::ColumnId_WeaponType, ColumnBase::Display_WeaponType)); @@ -461,9 +488,13 @@ CSMWorld::RefIdCollection::~RefIdCollection() iter!=mAdapters.end(); ++iter) delete iter->second; - for (std::map::iterator iter (mNestedAdapters.begin()); + for (std::vector > >::iterator iter (mNestedAdapters.begin()); iter!=mNestedAdapters.end(); ++iter) - delete iter->second; + { + for (std::map::iterator it ((iter->second).begin()); + it!=(iter->second).end(); ++it) + delete it->second; + } } int CSMWorld::RefIdCollection::getSize() const @@ -509,15 +540,11 @@ QVariant CSMWorld::RefIdCollection::getNestedData (int row, int column, int subR { RefIdData::LocalIndex localIndex = mData.globalToLocalIndex(row); - const CSMWorld::NestedRefIdAdapterBase* nestedAdapter = getNestedAdapter(mColumns.at(column)); + const CSMWorld::NestedRefIdAdapterBase* nestedAdapter = getNestedAdapter(mColumns.at(column), localIndex.second); if (nestedAdapter) - { return nestedAdapter->getNestedData(&mColumns.at (column), mData, localIndex.first, subRow, subColumn); - } - - const CSMWorld::NestedRefIdAdapter& adaptor = dynamic_cast(findAdapter (localIndex.second)); - - return adaptor.getNestedData (&mColumns.at (column), mData, localIndex.first, subRow, subColumn); + else + throw std::runtime_error("Could not find a nestedadapter"); } void CSMWorld::RefIdCollection::setData (int index, int column, const QVariant& data) @@ -533,16 +560,14 @@ void CSMWorld::RefIdCollection::setNestedData(int row, int column, const QVarian { RefIdData::LocalIndex localIndex = mData.globalToLocalIndex (row); - const CSMWorld::NestedRefIdAdapterBase* nestedAdapter = getNestedAdapter(mColumns.at(column)); + const CSMWorld::NestedRefIdAdapterBase* nestedAdapter = getNestedAdapter(mColumns.at(column), localIndex.second); if (nestedAdapter) { nestedAdapter->setNestedData(&mColumns.at (column), mData, localIndex.first, data, subRow, subColumn); return; } - - const RefIdAdapter& adaptor = findAdapter (localIndex.second); - - dynamic_cast(adaptor).setNestedData (&mColumns.at (column), mData, localIndex.first, data, subRow, subColumn); + else + throw std::runtime_error("Could not find a nestedadapter"); } void CSMWorld::RefIdCollection::removeRows (int index, int count) @@ -554,16 +579,14 @@ void CSMWorld::RefIdCollection::removeNestedRows(int row, int column, int subRow { RefIdData::LocalIndex localIndex = mData.globalToLocalIndex (row); - const CSMWorld::NestedRefIdAdapterBase* nestedAdapter = getNestedAdapter(mColumns.at(column)); + const CSMWorld::NestedRefIdAdapterBase* nestedAdapter = getNestedAdapter(mColumns.at(column), localIndex.second); if (nestedAdapter) { nestedAdapter->removeNestedRow(&mColumns.at (column), mData, localIndex.first, subRow); return; } - - const RefIdAdapter& adaptor = findAdapter (localIndex.second); - - dynamic_cast(adaptor).removeNestedRow(&mColumns.at (column), mData, localIndex.first, subRow); + else + throw std::runtime_error("Could not find a nestedadapter"); } void CSMWorld::RefIdCollection::appendBlankRecord (const std::string& id, UniversalId::Type type) @@ -705,30 +728,22 @@ int CSMWorld::RefIdCollection::getNestedRowsCount(int row, int column) const { RefIdData::LocalIndex localIndex = mData.globalToLocalIndex (row); - const CSMWorld::NestedRefIdAdapterBase* nestedAdapter = getNestedAdapter(mColumns.at(column)); + const CSMWorld::NestedRefIdAdapterBase* nestedAdapter = getNestedAdapter(mColumns.at(column), localIndex.second); if (nestedAdapter) - { return nestedAdapter->getNestedRowsCount(&mColumns.at(column), mData, localIndex.first); - } - - const CSMWorld::NestedRefIdAdapter& adaptor = dynamic_cast(findAdapter (localIndex.second)); - - return adaptor.getNestedRowsCount(&mColumns.at(column), mData, localIndex.first); + else + throw std::runtime_error("Could not find a nestedadapter"); } int CSMWorld::RefIdCollection::getNestedColumnsCount(int row, int column) const { RefIdData::LocalIndex localIndex = mData.globalToLocalIndex (row); - const CSMWorld::NestedRefIdAdapterBase* nestedAdapter = getNestedAdapter(mColumns.at(column)); + const CSMWorld::NestedRefIdAdapterBase* nestedAdapter = getNestedAdapter(mColumns.at(column), localIndex.second); if (nestedAdapter) - { return nestedAdapter->getNestedColumnsCount(&mColumns.at(column), mData); - } - - const CSMWorld::NestedRefIdAdapter& adaptor = dynamic_cast(findAdapter (localIndex.second)); - - return adaptor.getNestedColumnsCount(&mColumns.at(column), mData); + else + throw std::runtime_error("Could not find a nestedadapter"); } CSMWorld::NestableColumn *CSMWorld::RefIdCollection::getNestableColumn(int column) @@ -740,58 +755,56 @@ void CSMWorld::RefIdCollection::addNestedRow(int row, int col, int position) { RefIdData::LocalIndex localIndex = mData.globalToLocalIndex (row); - const CSMWorld::NestedRefIdAdapterBase* nestedAdapter = getNestedAdapter(mColumns.at(col)); + const CSMWorld::NestedRefIdAdapterBase* nestedAdapter = getNestedAdapter(mColumns.at(col), localIndex.second); if (nestedAdapter) { nestedAdapter->addNestedRow(&mColumns.at(col), mData, localIndex.first, position); return; } - - const CSMWorld::NestedRefIdAdapter& adaptor = dynamic_cast(findAdapter (localIndex.second)); - - adaptor.addNestedRow(&mColumns.at(col), mData, localIndex.first, position); + else + throw std::runtime_error("Could not find a nestedadapter"); } void CSMWorld::RefIdCollection::setNestedTable(int row, int column, const CSMWorld::NestedTableWrapperBase& nestedTable) { RefIdData::LocalIndex localIndex = mData.globalToLocalIndex (row); - const CSMWorld::NestedRefIdAdapterBase* nestedAdapter = getNestedAdapter(mColumns.at(column)); + const CSMWorld::NestedRefIdAdapterBase* nestedAdapter = getNestedAdapter(mColumns.at(column), localIndex.second); if (nestedAdapter) { nestedAdapter->setNestedTable(&mColumns.at(column), mData, localIndex.first, nestedTable); return; } - - const CSMWorld::NestedRefIdAdapter& adaptor = dynamic_cast(findAdapter (localIndex.second)); - - adaptor.setNestedTable(&mColumns.at(column), mData, localIndex.first, nestedTable); + else + throw std::runtime_error("Could not find a nestedadapter"); } CSMWorld::NestedTableWrapperBase* CSMWorld::RefIdCollection::nestedTable(int row, int column) const { RefIdData::LocalIndex localIndex = mData.globalToLocalIndex (row); - const CSMWorld::NestedRefIdAdapterBase* nestedAdapter = getNestedAdapter(mColumns.at(column)); + const CSMWorld::NestedRefIdAdapterBase* nestedAdapter = getNestedAdapter(mColumns.at(column), localIndex.second); if (nestedAdapter) - { return nestedAdapter->nestedTable(&mColumns.at(column), mData, localIndex.first); - } - - const CSMWorld::NestedRefIdAdapter& adaptor = dynamic_cast(findAdapter (localIndex.second)); - - return adaptor.nestedTable(&mColumns.at(column), mData, localIndex.first); + else + throw std::runtime_error("Could not find a nestedadapter"); } -const CSMWorld::NestedRefIdAdapterBase* CSMWorld::RefIdCollection::getNestedAdapter(const CSMWorld::ColumnBase &column) const +const CSMWorld::NestedRefIdAdapterBase* CSMWorld::RefIdCollection::getNestedAdapter(const CSMWorld::ColumnBase &column, UniversalId::Type type) const { - std::map::const_iterator iter = - mNestedAdapters.find (&column); + for (std::vector > >::const_iterator iter (mNestedAdapters.begin()); + iter!=mNestedAdapters.end(); ++iter) + { + if ((iter->first) == &column) + { + std::map::const_iterator it = + (iter->second).find(type); - if (iter==mNestedAdapters.end()) - return 0; // FIXME: testing only - //throw std::runtime_error("No such column in the nestedadapters"); + if (it == (iter->second).end()) + throw std::runtime_error("No such type in the nestedadapters"); - //return *iter->second; - return iter->second; + return it->second; + } + } + throw std::runtime_error("No such column in the nestedadapters"); } diff --git a/apps/opencs/model/world/refidcollection.hpp b/apps/opencs/model/world/refidcollection.hpp index 70651b78d5..f183dc7a0e 100644 --- a/apps/opencs/model/world/refidcollection.hpp +++ b/apps/opencs/model/world/refidcollection.hpp @@ -45,15 +45,14 @@ namespace CSMWorld std::deque mColumns; std::map mAdapters; - std::map mNestedAdapters; + std::vector > > mNestedAdapters; private: const RefIdAdapter& findAdapter (UniversalId::Type) const; ///< Throws an exception if no adaptor for \a Type can be found. - //const NestedRefIdAdapterBase& getNestedAdapter(const ColumnBase &column) const; - const NestedRefIdAdapterBase* getNestedAdapter(const ColumnBase &column) const; + const NestedRefIdAdapterBase* getNestedAdapter(const ColumnBase &column, UniversalId::Type type) const; public: