diff --git a/apps/opencs/model/world/columns.cpp b/apps/opencs/model/world/columns.cpp index 547efac56..83d6ceb57 100644 --- a/apps/opencs/model/world/columns.cpp +++ b/apps/opencs/model/world/columns.cpp @@ -263,6 +263,10 @@ namespace CSMWorld { ColumnId_PartRefMale, "Male"}, { ColumnId_PartRefFemale, "Female"}, + { ColumnId_LevelledList,"Levelled List"}, + { ColumnId_LevelledItemId,"Item ID"}, + { ColumnId_LevelledItemLevel,"Level"}, + { ColumnId_UseValue1, "Use value 1" }, { ColumnId_UseValue2, "Use value 2" }, { ColumnId_UseValue3, "Use value 3" }, diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index 6068ea6e7..81cae5e36 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -253,6 +253,10 @@ namespace CSMWorld ColumnId_PartRefMale = 231, ColumnId_PartRefFemale = 232, + ColumnId_LevelledList = 233, + ColumnId_LevelledItemId = 234, + ColumnId_LevelledItemLevel = 235, + // Allocated to a separate value range, so we don't get a collision should we ever need // to extend the number of use values. ColumnId_UseValue1 = 0x10000, diff --git a/apps/opencs/model/world/refidadapterimp.hpp b/apps/opencs/model/world/refidadapterimp.hpp index bc00d31f9..d09aaaa45 100644 --- a/apps/opencs/model/world/refidadapterimp.hpp +++ b/apps/opencs/model/world/refidadapterimp.hpp @@ -1828,6 +1828,188 @@ namespace CSMWorld return static_cast(record.get().mParts.mParts.size()); } }; + + struct LevListColumns : public BaseColumns + { + const RefIdColumn *mLevList; + + LevListColumns (const BaseColumns& base) : BaseColumns (base) {} + }; + + template + class LevelledListRefIdAdapter : public BaseRefIdAdapter + { + LevListColumns mLevList; + + public: + + LevelledListRefIdAdapter (UniversalId::Type type, const LevListColumns &columns); + + virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index) + const; + + virtual void setData (const RefIdColumn *column, RefIdData& data, int index, + const QVariant& value) const; + ///< If the data type does not match an exception is thrown. + }; + + template + LevelledListRefIdAdapter::LevelledListRefIdAdapter (UniversalId::Type type, + const LevListColumns &columns) + : BaseRefIdAdapter (type, columns), mLevList (columns) + {} + + template + QVariant LevelledListRefIdAdapter::getData (const RefIdColumn *column, const RefIdData& data, + int index) const + { + if (column==mLevList.mLevList) + return true; // to show nested tables in dialogue subview, see IdTree::hasChildren() + + return BaseRefIdAdapter::getData (column, data, index); + } + + template + void LevelledListRefIdAdapter::setData (const RefIdColumn *column, RefIdData& data, int index, + const QVariant& value) const + { + BaseRefIdAdapter::setData (column, data, index, value); + return; + } + + template + class NestedLevListRefIdAdapter : public NestedRefIdAdapterBase + { + UniversalId::Type mType; + + // not implemented + NestedLevListRefIdAdapter (const NestedLevListRefIdAdapter&); + NestedLevListRefIdAdapter& operator= (const NestedLevListRefIdAdapter&); + + public: + + NestedLevListRefIdAdapter(UniversalId::Type type) :mType(type) {} + + virtual ~NestedLevListRefIdAdapter() {} + + virtual void addNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int position) const + { + Record& record = + static_cast&> (data.getRecord (RefIdData::LocalIndex (index, mType))); + ESXRecordT leveled = record.get(); + + std::vector& list = leveled.mList; + + ESM::LevelledListBase::LevelItem newItem; + newItem.mId = ""; + newItem.mLevel = 0; + + if (position >= (int)list.size()) + list.push_back(newItem); + else + list.insert(list.begin()+position, newItem); + + record.setModified (leveled); + } + + virtual void removeNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int rowToRemove) const + { + Record& record = + static_cast&> (data.getRecord (RefIdData::LocalIndex (index, mType))); + ESXRecordT leveled = record.get(); + + std::vector& list = leveled.mList; + + if (rowToRemove < 0 || rowToRemove >= static_cast (list.size())) + throw std::runtime_error ("index out of range"); + + list.erase (list.begin () + rowToRemove); + + record.setModified (leveled); + } + + 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 leveled = record.get(); + + leveled.mList = + static_cast >&>(nestedTable).mNestedTable; + + record.setModified (leveled); + } + + 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().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().mList; + + if (subRowIndex < 0 || subRowIndex >= static_cast (list.size())) + throw std::runtime_error ("index out of range"); + + const ESM::LevelledListBase::LevelItem& content = list.at(subRowIndex); + + switch (subColIndex) + { + case 0: return QString(content.mId.c_str()); + case 1: return content.mLevel; + 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 leveled = record.get(); + std::vector& list = leveled.mList; + + if (subRowIndex < 0 || subRowIndex >= static_cast (list.size())) + throw std::runtime_error ("index out of range"); + + switch(subColIndex) + { + case 0: list.at(subRowIndex).mId = value.toString().toStdString(); break; + case 1: list.at(subRowIndex).mLevel = static_cast(value.toInt()); break; + default: + throw std::runtime_error("Trying to access non-existing column in the nested table!"); + } + + record.setModified (leveled); + } + + virtual int getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const + { + return 2; + } + + 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().mList.size()); + } + }; } #endif diff --git a/apps/opencs/model/world/refidcollection.cpp b/apps/opencs/model/world/refidcollection.cpp index 48f95451c..be5d67766 100644 --- a/apps/opencs/model/world/refidcollection.cpp +++ b/apps/opencs/model/world/refidcollection.cpp @@ -73,14 +73,13 @@ CSMWorld::RefIdCollection::RefIdCollection() // nested table PotionColumns potionColumns (inventoryColumns); - mColumns.push_back (RefIdColumn (Columns::ColumnId_EffectList, ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue)); + mColumns.push_back (RefIdColumn (Columns::ColumnId_EffectList, + ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue)); potionColumns.mEffects = &mColumns.back(); // see refidadapterimp.hpp - std::map effectsMap; - effectsMap.insert( - std::make_pair(UniversalId::Type_Potion, new EffectsRefIdAdapter (UniversalId::Type_Potion))); + 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( @@ -126,15 +125,14 @@ CSMWorld::RefIdCollection::RefIdCollection() actorsColumns.mAlarm = &mColumns.back(); // Nested table - mColumns.push_back(RefIdColumn (Columns::ColumnId_ActorInventory, ColumnBase::Display_NestedItemList, ColumnBase::Flag_Dialogue)); + mColumns.push_back(RefIdColumn (Columns::ColumnId_ActorInventory, + ColumnBase::Display_NestedItemList, ColumnBase::Flag_Dialogue)); actorsColumns.mInventory = &mColumns.back(); - 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))); - + 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)); @@ -142,28 +140,27 @@ CSMWorld::RefIdCollection::RefIdCollection() new RefIdColumn (Columns::ColumnId_ItemCount, CSMWorld::ColumnBase::Display_Integer)); // Nested table - mColumns.push_back(RefIdColumn (Columns::ColumnId_SpellList, ColumnBase::Display_NestedSpellList, ColumnBase::Flag_Dialogue)); + 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))); - + 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)); + 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))); + 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)); @@ -181,15 +178,14 @@ CSMWorld::RefIdCollection::RefIdCollection() new RefIdColumn (Columns::ColumnId_RotZ, CSMWorld::ColumnBase::Display_Float)); // Nested table - mColumns.push_back(RefIdColumn (Columns::ColumnId_AiPackageList, ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue)); + mColumns.push_back(RefIdColumn (Columns::ColumnId_AiPackageList, + ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue)); actorsColumns.mAiPackages = &mColumns.back(); - std::map aiMap; - aiMap.insert( - std::make_pair(UniversalId::Type_Npc, new ActorAiRefIdAdapter (UniversalId::Type_Npc))); - aiMap.insert( - std::make_pair(UniversalId::Type_Creature, new ActorAiRefIdAdapter (UniversalId::Type_Creature))); - + aiMap.insert(std::make_pair(UniversalId::Type_Npc, + new ActorAiRefIdAdapter (UniversalId::Type_Npc))); + aiMap.insert(std::make_pair(UniversalId::Type_Creature, + new ActorAiRefIdAdapter (UniversalId::Type_Creature))); mNestedAdapters.push_back (std::make_pair(&mColumns.back(), aiMap)); mColumns.back().addColumn( new RefIdColumn (Columns::ColumnId_AiPackage, CSMWorld::ColumnBase::Display_String)); @@ -284,14 +280,13 @@ CSMWorld::RefIdCollection::RefIdCollection() const RefIdColumn *respawn = &mColumns.back(); // Nested table - mColumns.push_back(RefIdColumn (Columns::ColumnId_ContainerContent, ColumnBase::Display_NestedItemList, ColumnBase::Flag_Dialogue)); + mColumns.push_back(RefIdColumn (Columns::ColumnId_ContainerContent, + ColumnBase::Display_NestedItemList, ColumnBase::Flag_Dialogue)); const RefIdColumn *content = &mColumns.back(); - std::map contMap; - contMap.insert( - std::make_pair(UniversalId::Type_Container, new NestedInventoryRefIdAdapter (UniversalId::Type_Container))); + 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( @@ -478,20 +473,36 @@ CSMWorld::RefIdCollection::RefIdCollection() // Nested table mColumns.push_back(RefIdColumn (Columns::ColumnId_PartRefList, ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue)); const RefIdColumn *partRef = &mColumns.back(); - std::map partMap; - partMap.insert( - std::make_pair(UniversalId::Type_Armor, new BodyPartRefIdAdapter (UniversalId::Type_Armor))); - partMap.insert( - std::make_pair(UniversalId::Type_Clothing, new BodyPartRefIdAdapter (UniversalId::Type_Clothing))); - + partMap.insert(std::make_pair(UniversalId::Type_Armor, + new BodyPartRefIdAdapter (UniversalId::Type_Armor))); + partMap.insert(std::make_pair(UniversalId::Type_Clothing, + new BodyPartRefIdAdapter (UniversalId::Type_Clothing))); mNestedAdapters.push_back (std::make_pair(&mColumns.back(), partMap)); mColumns.back().addColumn( - new RefIdColumn (Columns::ColumnId_PartRefType, CSMWorld::ColumnBase::Display_String)); + new RefIdColumn (Columns::ColumnId_PartRefType, CSMWorld::ColumnBase::Display_String)); mColumns.back().addColumn( - new RefIdColumn (Columns::ColumnId_PartRefMale, CSMWorld::ColumnBase::Display_String)); + new RefIdColumn (Columns::ColumnId_PartRefMale, CSMWorld::ColumnBase::Display_String)); mColumns.back().addColumn( - new RefIdColumn (Columns::ColumnId_PartRefFemale, CSMWorld::ColumnBase::Display_String)); + new RefIdColumn (Columns::ColumnId_PartRefFemale, CSMWorld::ColumnBase::Display_String)); + + LevListColumns levListColumns (baseColumns); + + // Nested table + mColumns.push_back(RefIdColumn (Columns::ColumnId_LevelledList, + ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue)); + levListColumns.mLevList = &mColumns.back(); + std::map levListMap; + levListMap.insert(std::make_pair(UniversalId::Type_CreatureLevelledList, + new NestedLevListRefIdAdapter (UniversalId::Type_CreatureLevelledList))); + levListMap.insert(std::make_pair(UniversalId::Type_ItemLevelledList, + new NestedLevListRefIdAdapter (UniversalId::Type_ItemLevelledList))); + mNestedAdapters.push_back (std::make_pair(&mColumns.back(), levListMap)); + mColumns.back().addColumn( + new RefIdColumn (Columns::ColumnId_LevelledItemId, CSMWorld::ColumnBase::Display_String)); + mColumns.back().addColumn( + new RefIdColumn (Columns::ColumnId_LevelledItemLevel, CSMWorld::ColumnBase::Display_Integer)); + mAdapters.insert (std::make_pair (UniversalId::Type_Activator, new NameRefIdAdapter (UniversalId::Type_Activator, nameColumns))); @@ -514,10 +525,10 @@ CSMWorld::RefIdCollection::RefIdCollection() mAdapters.insert (std::make_pair (UniversalId::Type_Ingredient, new InventoryRefIdAdapter (UniversalId::Type_Ingredient, inventoryColumns))); mAdapters.insert (std::make_pair (UniversalId::Type_CreatureLevelledList, - new BaseRefIdAdapter ( - UniversalId::Type_CreatureLevelledList, baseColumns))); + new LevelledListRefIdAdapter ( + UniversalId::Type_CreatureLevelledList, levListColumns))); mAdapters.insert (std::make_pair (UniversalId::Type_ItemLevelledList, - new BaseRefIdAdapter (UniversalId::Type_ItemLevelledList, baseColumns))); + new LevelledListRefIdAdapter (UniversalId::Type_ItemLevelledList, levListColumns))); mAdapters.insert (std::make_pair (UniversalId::Type_Light, new LightRefIdAdapter (lightColumns))); mAdapters.insert (std::make_pair (UniversalId::Type_Lockpick,