diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 8cf37da1d..bc0b964ae 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 + pathgrid landtexture land nestedtablewrapper nestedadapters nestedcollection idadapterimp ) opencs_hdrs_noqt (model/world diff --git a/apps/opencs/model/world/columnbase.hpp b/apps/opencs/model/world/columnbase.hpp index dc3aae11a..c7c8d3cd8 100644 --- a/apps/opencs/model/world/columnbase.hpp +++ b/apps/opencs/model/world/columnbase.hpp @@ -169,7 +169,8 @@ namespace CSMWorld template struct NestedParentColumn : public Column { - NestedParentColumn (int id) : Column (id, Display_NestedHeader, Flag_Dialogue) + NestedParentColumn (int id) : Column (id, + ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue) {} virtual QVariant get (const Record& record) const diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 69e2b5aa8..db644affa 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -112,7 +112,7 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc NestedParentColumn *reactions = new NestedParentColumn (Columns::ColumnId_FactionReactions); mFactions.addColumn (reactions); - mFactions.addAdapter (std::make_pair(reactions, new FactionReactionsAdapter ())); + mFactions.addAdapter (std::make_pair(reactions, new FactionReactionsAdapter ())); mFactions.getNestableColumn(mFactions.getColumns()-1)->addColumn( new NestedChildColumn (Columns::ColumnId_Faction, ColumnBase::Display_String)); mFactions.getNestableColumn(mFactions.getColumns()-1)->addColumn( @@ -160,7 +160,7 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc NestedParentColumn *soundList = new NestedParentColumn (Columns::ColumnId_RegionSounds); mRegions.addColumn (soundList); - mRegions.addAdapter (std::make_pair(soundList, new RegionSoundListAdapter ())); + mRegions.addAdapter (std::make_pair(soundList, new RegionSoundListAdapter ())); mRegions.getNestableColumn(mRegions.getColumns()-1)->addColumn( new NestedChildColumn (Columns::ColumnId_SoundName, ColumnBase::Display_String)); mRegions.getNestableColumn(mRegions.getColumns()-1)->addColumn( @@ -335,7 +335,7 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc new NestedParentColumn (Columns::ColumnId_PathgridPoints); mPathgrids.addColumn (pointList); // new object deleted in dtor of SubCellCollection - mPathgrids.addAdapter (std::make_pair(pointList, new PathgridPointListAdapter ())); + mPathgrids.addAdapter (std::make_pair(pointList, new PathgridPointListAdapter ())); // new objects deleted in dtor of NestableColumn // WARNING: The order of the columns below are assumed in PathgridPointListAdapter mPathgrids.getNestableColumn(mPathgrids.getColumns()-1)->addColumn( @@ -350,7 +350,7 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc NestedParentColumn *edgeList = new NestedParentColumn (Columns::ColumnId_PathgridEdges); mPathgrids.addColumn (edgeList); - mPathgrids.addAdapter (std::make_pair(edgeList, new PathgridEdgeListAdapter ())); + mPathgrids.addAdapter (std::make_pair(edgeList, new PathgridEdgeListAdapter ())); mPathgrids.getNestableColumn(mPathgrids.getColumns()-1)->addColumn( new NestedChildColumn (Columns::ColumnId_PathgridEdgeIndex, ColumnBase::Display_Integer, false)); mPathgrids.getNestableColumn(mPathgrids.getColumns()-1)->addColumn( diff --git a/apps/opencs/model/world/idadapterimp.cpp b/apps/opencs/model/world/idadapterimp.cpp new file mode 100644 index 000000000..95e68e09e --- /dev/null +++ b/apps/opencs/model/world/idadapterimp.cpp @@ -0,0 +1,457 @@ +#include "idadapterimp.hpp" + +#include +#include + +#include "idcollection.hpp" +#include "pathgrid.hpp" + +namespace CSMWorld +{ + PathgridPointListAdapter::PathgridPointListAdapter () {} + + void PathgridPointListAdapter::addNestedRow(Record& record, int position) const + { + Pathgrid pathgrid = record.get(); + + ESM::Pathgrid::PointList& points = pathgrid.mPoints; + + // blank row + ESM::Pathgrid::Point point; + point.mX = 0; + point.mY = 0; + point.mZ = 0; + point.mAutogenerated = 0; + point.mConnectionNum = 0; + point.mUnknown = 0; + + // inserting a point should trigger re-indexing of the edges + // + // FIXME: does not auto refresh edges table view + std::vector::iterator iter = pathgrid.mEdges.begin(); + for (;iter != pathgrid.mEdges.end(); ++iter) + { + if ((*iter).mV0 >= position) + (*iter).mV0++; + if ((*iter).mV1 >= position) + (*iter).mV1++; + } + + points.insert(points.begin()+position, point); + pathgrid.mData.mS2 += 1; // increment the number of points + + record.setModified (pathgrid); + } + + void PathgridPointListAdapter::removeNestedRow(Record& record, int rowToRemove) const + { + Pathgrid pathgrid = record.get(); + + ESM::Pathgrid::PointList& points = pathgrid.mPoints; + + if (rowToRemove < 0 || rowToRemove >= static_cast (points.size())) + throw std::runtime_error ("index out of range"); + + // deleting a point should trigger re-indexing of the edges + // dangling edges are not allowed and hence removed + // + // FIXME: does not auto refresh edges table view + std::vector::iterator iter = pathgrid.mEdges.begin(); + for (; iter != pathgrid.mEdges.end();) + { + if (((*iter).mV0 == rowToRemove) || ((*iter).mV1 == rowToRemove)) + iter = pathgrid.mEdges.erase(iter); + else + { + if ((*iter).mV0 > rowToRemove) + (*iter).mV0--; + + if ((*iter).mV1 > rowToRemove) + (*iter).mV1--; + + ++iter; + } + } + points.erase(points.begin()+rowToRemove); + pathgrid.mData.mS2 -= 1; // decrement the number of points + + record.setModified (pathgrid); + } + + void PathgridPointListAdapter::setNestedTable(Record& record, + const NestedTableWrapperBase& nestedTable) const + { + record.get().mPoints = + static_cast(nestedTable).mRecord.mPoints; + record.get().mData.mS2 = + static_cast(nestedTable).mRecord.mData.mS2; + // also update edges in case points were added/removed + record.get().mEdges = + static_cast(nestedTable).mRecord.mEdges; + } + + NestedTableWrapperBase* PathgridPointListAdapter::nestedTable(const Record& record) const + { + // deleted by dtor of NestedTableStoring + return new PathgridPointsWrap(record.get()); + } + + QVariant PathgridPointListAdapter::getNestedData(const Record& record, + int subRowIndex, int subColIndex) const + { + ESM::Pathgrid::Point point = record.get().mPoints[subRowIndex]; + switch (subColIndex) + { + case 0: return subRowIndex; + case 1: return point.mX; + case 2: return point.mY; + case 3: return point.mZ; + default: throw std::runtime_error("Pathgrid point subcolumn index out of range"); + } + } + + void PathgridPointListAdapter::setNestedData(Record& record, + const QVariant& value, int subRowIndex, int subColIndex) const + { + Pathgrid pathgrid = record.get(); + ESM::Pathgrid::Point point = pathgrid.mPoints[subRowIndex]; + switch (subColIndex) + { + case 0: break; + case 1: point.mX = value.toInt(); break; + case 2: point.mY = value.toInt(); break; + case 3: point.mZ = value.toInt(); break; + default: throw std::runtime_error("Pathgrid point subcolumn index out of range"); + } + + pathgrid.mPoints[subRowIndex] = point; + + record.setModified (pathgrid); + } + + int PathgridPointListAdapter::getNestedColumnsCount(const Record& record) const + { + return 4; + } + + int PathgridPointListAdapter::getNestedRowsCount(const Record& record) const + { + return static_cast(record.get().mPoints.size()); + } + + PathgridEdgeListAdapter::PathgridEdgeListAdapter () {} + + // ToDo: seems to be auto-sorted in the dialog table display after insertion + void PathgridEdgeListAdapter::addNestedRow(Record& record, int position) const + { + Pathgrid pathgrid = record.get(); + + ESM::Pathgrid::EdgeList& edges = pathgrid.mEdges; + + // blank row + ESM::Pathgrid::Edge edge; + edge.mV0 = 0; + edge.mV1 = 0; + + // NOTE: inserting a blank edge does not really make sense, perhaps this should be a + // logic_error exception + // + // Currently the code assumes that the end user to know what he/she is doing. + // e.g. Edges come in pairs, from points a->b and b->a + edges.insert(edges.begin()+position, edge); + + record.setModified (pathgrid); + } + + void PathgridEdgeListAdapter::removeNestedRow(Record& record, int rowToRemove) const + { + Pathgrid pathgrid = record.get(); + + ESM::Pathgrid::EdgeList& edges = pathgrid.mEdges; + + if (rowToRemove < 0 || rowToRemove >= static_cast (edges.size())) + throw std::runtime_error ("index out of range"); + + edges.erase(edges.begin()+rowToRemove); + + record.setModified (pathgrid); + } + + void PathgridEdgeListAdapter::setNestedTable(Record& record, + const NestedTableWrapperBase& nestedTable) const + { + record.get().mEdges = + static_cast &>(nestedTable).mNestedTable; + } + + NestedTableWrapperBase* PathgridEdgeListAdapter::nestedTable(const Record& record) const + { + // deleted by dtor of NestedTableStoring + return new NestedTableWrapper(record.get().mEdges); + } + + QVariant PathgridEdgeListAdapter::getNestedData(const Record& record, + int subRowIndex, int subColIndex) const + { + Pathgrid pathgrid = record.get(); + + if (subRowIndex < 0 || subRowIndex >= static_cast (pathgrid.mEdges.size())) + throw std::runtime_error ("index out of range"); + + ESM::Pathgrid::Edge edge = pathgrid.mEdges[subRowIndex]; + switch (subColIndex) + { + case 0: return subRowIndex; + case 1: return edge.mV0; + case 2: return edge.mV1; + default: throw std::runtime_error("Pathgrid edge subcolumn index out of range"); + } + } + + // ToDo: detect duplicates in mEdges + void PathgridEdgeListAdapter::setNestedData(Record& record, + const QVariant& value, int subRowIndex, int subColIndex) const + { + Pathgrid pathgrid = record.get(); + + if (subRowIndex < 0 || subRowIndex >= static_cast (pathgrid.mEdges.size())) + throw std::runtime_error ("index out of range"); + + ESM::Pathgrid::Edge edge = pathgrid.mEdges[subRowIndex]; + switch (subColIndex) + { + case 0: break; + case 1: edge.mV0 = value.toInt(); break; + case 2: edge.mV1 = value.toInt(); break; + default: throw std::runtime_error("Pathgrid edge subcolumn index out of range"); + } + + pathgrid.mEdges[subRowIndex] = edge; + + record.setModified (pathgrid); + } + + int PathgridEdgeListAdapter::getNestedColumnsCount(const Record& record) const + { + return 3; + } + + int PathgridEdgeListAdapter::getNestedRowsCount(const Record& record) const + { + return static_cast(record.get().mEdges.size()); + } + + FactionReactionsAdapter::FactionReactionsAdapter () {} + + void FactionReactionsAdapter::addNestedRow(Record& record, int position) const + { + ESM::Faction faction = record.get(); + + std::map& reactions = faction.mReactions; + + // blank row + reactions.insert(std::make_pair("", 0)); + + record.setModified (faction); + } + + void FactionReactionsAdapter::removeNestedRow(Record& record, int rowToRemove) const + { + ESM::Faction faction = record.get(); + + std::map& reactions = faction.mReactions; + + if (rowToRemove < 0 || rowToRemove >= static_cast (reactions.size())) + throw std::runtime_error ("index out of range"); + + // FIXME: how to ensure that the map entries correspond to table indicies? + // WARNING: Assumed that the table view has the same order as std::map + std::map::iterator iter = reactions.begin(); + for(int i = 0; i < rowToRemove; ++i) + iter++; + reactions.erase(iter); + + record.setModified (faction); + } + + void FactionReactionsAdapter::setNestedTable(Record& record, + const NestedTableWrapperBase& nestedTable) const + { + record.get().mReactions = + static_cast >&>(nestedTable).mNestedTable; + } + + NestedTableWrapperBase* FactionReactionsAdapter::nestedTable(const Record& record) const + { + // deleted by dtor of NestedTableStoring + return new NestedTableWrapper >(record.get().mReactions); + } + + QVariant FactionReactionsAdapter::getNestedData(const Record& record, + int subRowIndex, int subColIndex) const + { + ESM::Faction faction = record.get(); + + std::map& reactions = faction.mReactions; + + if (subRowIndex < 0 || subRowIndex >= static_cast (reactions.size())) + throw std::runtime_error ("index out of range"); + + // FIXME: how to ensure that the map entries correspond to table indicies? + // WARNING: Assumed that the table view has the same order as std::map + std::map::const_iterator iter = reactions.begin(); + for(int i = 0; i < subRowIndex; ++i) + iter++; + switch (subColIndex) + { + case 0: return QString((*iter).first.c_str()); + case 1: return (*iter).second; + default: throw std::runtime_error("Faction reactions subcolumn index out of range"); + } + } + + void FactionReactionsAdapter::setNestedData(Record& record, + const QVariant& value, int subRowIndex, int subColIndex) const + { + ESM::Faction faction = record.get(); + + std::map& reactions = faction.mReactions; + + if (subRowIndex < 0 || subRowIndex >= static_cast (reactions.size())) + throw std::runtime_error ("index out of range"); + + // FIXME: how to ensure that the map entries correspond to table indicies? + // WARNING: Assumed that the table view has the same order as std::map + std::map::iterator iter = reactions.begin(); + for(int i = 0; i < subRowIndex; ++i) + iter++; + + std::string factionId = (*iter).first; + int reaction = (*iter).second; + + switch (subColIndex) + { + case 0: + { + reactions.erase(iter); + reactions.insert(std::make_pair(value.toString().toUtf8().constData(), reaction)); + break; + } + case 1: + { + reactions[factionId] = value.toInt(); + break; + } + default: throw std::runtime_error("Faction reactions subcolumn index out of range"); + } + + record.setModified (faction); + } + + int FactionReactionsAdapter::getNestedColumnsCount(const Record& record) const + { + return 2; + } + + int FactionReactionsAdapter::getNestedRowsCount(const Record& record) const + { + return static_cast(record.get().mReactions.size()); + } + + RegionSoundListAdapter::RegionSoundListAdapter () {} + + void RegionSoundListAdapter::addNestedRow(Record& record, int position) const + { + ESM::Region region = record.get(); + + std::vector& soundList = region.mSoundList; + + // blank row + ESM::Region::SoundRef soundRef; + soundRef.mSound.assign(""); + soundRef.mChance = 0; + + soundList.insert(soundList.begin()+position, soundRef); + + record.setModified (region); + } + + void RegionSoundListAdapter::removeNestedRow(Record& record, int rowToRemove) const + { + ESM::Region region = record.get(); + + std::vector& soundList = region.mSoundList; + + if (rowToRemove < 0 || rowToRemove >= static_cast (soundList.size())) + throw std::runtime_error ("index out of range"); + + soundList.erase(soundList.begin()+rowToRemove); + + record.setModified (region); + } + + void RegionSoundListAdapter::setNestedTable(Record& record, + const NestedTableWrapperBase& nestedTable) const + { + record.get().mSoundList = + static_cast >&>(nestedTable).mNestedTable; + } + + NestedTableWrapperBase* RegionSoundListAdapter::nestedTable(const Record& record) const + { + // deleted by dtor of NestedTableStoring + return new NestedTableWrapper >(record.get().mSoundList); + } + + QVariant RegionSoundListAdapter::getNestedData(const Record& record, + int subRowIndex, int subColIndex) const + { + ESM::Region region = record.get(); + + std::vector& soundList = region.mSoundList; + + if (subRowIndex < 0 || subRowIndex >= static_cast (soundList.size())) + throw std::runtime_error ("index out of range"); + + ESM::Region::SoundRef soundRef = soundList[subRowIndex]; + switch (subColIndex) + { + case 0: return QString(soundRef.mSound.toString().c_str()); + case 1: return soundRef.mChance; + default: throw std::runtime_error("Region sounds subcolumn index out of range"); + } + } + + void RegionSoundListAdapter::setNestedData(Record& record, + const QVariant& value, int subRowIndex, int subColIndex) const + { + ESM::Region region = record.get(); + + std::vector& soundList = region.mSoundList; + + if (subRowIndex < 0 || subRowIndex >= static_cast (soundList.size())) + throw std::runtime_error ("index out of range"); + + ESM::Region::SoundRef soundRef = soundList[subRowIndex]; + switch (subColIndex) + { + case 0: soundRef.mSound.assign(value.toString().toUtf8().constData()); break; + case 1: soundRef.mChance = static_cast(value.toInt()); break; + default: throw std::runtime_error("Region sounds subcolumn index out of range"); + } + + region.mSoundList[subRowIndex] = soundRef; + + record.setModified (region); + } + + int RegionSoundListAdapter::getNestedColumnsCount(const Record& record) const + { + return 2; + } + + int RegionSoundListAdapter::getNestedRowsCount(const Record& record) const + { + return static_cast(record.get().mSoundList.size()); + } +} diff --git a/apps/opencs/model/world/idadapterimp.hpp b/apps/opencs/model/world/idadapterimp.hpp index d5bf83a2d..effa0011c 100644 --- a/apps/opencs/model/world/idadapterimp.hpp +++ b/apps/opencs/model/world/idadapterimp.hpp @@ -4,8 +4,6 @@ #include #include -#include -#include #include #include // for converting magic effect id to string & back #include // for converting skill names @@ -14,482 +12,129 @@ #include "idadapter.hpp" #include "nestedtablewrapper.hpp" -namespace CSMWorld +namespace ESM { - template - class PathgridPointListAdapter : public NestedIdAdapter - { - public: - PathgridPointListAdapter () {} - - virtual void addNestedRow(Record& record, int position) const - { - ESXRecordT pathgrid = record.get(); - - ESM::Pathgrid::PointList& points = pathgrid.mPoints; - - // blank row - ESM::Pathgrid::Point point; - point.mX = 0; - point.mY = 0; - point.mZ = 0; - point.mAutogenerated = 0; - point.mConnectionNum = 0; - point.mUnknown = 0; - - // inserting a point should trigger re-indexing of the edges - // - // FIXME: undo does not restore edges table view - // FIXME: does not auto refresh edges table view - std::vector::iterator iter = pathgrid.mEdges.begin(); - for (;iter != pathgrid.mEdges.end(); ++iter) - { - if ((*iter).mV0 >= position) - (*iter).mV0++; - if ((*iter).mV1 >= position) - (*iter).mV1++; - } - - points.insert(points.begin()+position, point); - pathgrid.mData.mS2 += 1; // increment the number of points - - record.setModified (pathgrid); - } - - virtual void removeNestedRow(Record& record, int rowToRemove) const - { - ESXRecordT pathgrid = record.get(); - - ESM::Pathgrid::PointList& points = pathgrid.mPoints; - - if (rowToRemove < 0 || rowToRemove >= static_cast (points.size())) - throw std::runtime_error ("index out of range"); - - // deleting a point should trigger re-indexing of the edges - // dangling edges are not allowed and hence removed - // - // FIXME: undo does not restore edges table view - // FIXME: does not auto refresh edges table view - std::vector::iterator iter = pathgrid.mEdges.begin(); - for (; iter != pathgrid.mEdges.end();) - { - if (((*iter).mV0 == rowToRemove) || ((*iter).mV1 == rowToRemove)) - iter = pathgrid.mEdges.erase(iter); - else - { - if ((*iter).mV0 > rowToRemove) - (*iter).mV0--; - - if ((*iter).mV1 > rowToRemove) - (*iter).mV1--; - - ++iter; - } - } - points.erase(points.begin()+rowToRemove); - pathgrid.mData.mS2 -= 1; // decrement the number of points - - record.setModified (pathgrid); - } - - struct PathgridPointsWrap : public NestedTableWrapperBase - { - ESM::Pathgrid mRecord; - - PathgridPointsWrap(ESM::Pathgrid pathgrid) - : mRecord(pathgrid) {} - - virtual ~PathgridPointsWrap() {} - - virtual int size() const - { - return mRecord.mPoints.size(); // used in IdTree::setNestedTable() - } - }; - - virtual void setNestedTable(Record& record, const NestedTableWrapperBase& nestedTable) const - { - record.get().mPoints = - static_cast(nestedTable).mRecord.mPoints; - record.get().mData.mS2 = - static_cast(nestedTable).mRecord.mData.mS2; - // also update edges in case points were added/removed - record.get().mEdges = - static_cast(nestedTable).mRecord.mEdges; - } - - virtual NestedTableWrapperBase* nestedTable(const Record& record) const - { - // deleted by dtor of NestedTableStoring - return new PathgridPointsWrap(record.get()); - } - - virtual QVariant getNestedData(const Record& record, int subRowIndex, int subColIndex) const - { - ESM::Pathgrid::Point point = record.get().mPoints[subRowIndex]; - switch (subColIndex) - { - case 0: return subRowIndex; - case 1: return point.mX; - case 2: return point.mY; - case 3: return point.mZ; - default: throw std::runtime_error("Pathgrid point subcolumn index out of range"); - } - } + struct Faction; + struct Region; +} - virtual void setNestedData(Record& record, const QVariant& value, - int subRowIndex, int subColIndex) const - { - ESXRecordT pathgrid = record.get(); - ESM::Pathgrid::Point point = pathgrid.mPoints[subRowIndex]; - switch (subColIndex) - { - case 0: break; - case 1: point.mX = value.toInt(); break; - case 2: point.mY = value.toInt(); break; - case 3: point.mZ = value.toInt(); break; - default: throw std::runtime_error("Pathgrid point subcolumn index out of range"); - } +namespace CSMWorld +{ + struct Pathgrid; - pathgrid.mPoints[subRowIndex] = point; + struct PathgridPointsWrap : public NestedTableWrapperBase + { + ESM::Pathgrid mRecord; - record.setModified (pathgrid); - } + PathgridPointsWrap(ESM::Pathgrid pathgrid) + : mRecord(pathgrid) {} - virtual int getNestedColumnsCount(const Record& record) const - { - return 4; - } + virtual ~PathgridPointsWrap() {} - virtual int getNestedRowsCount(const Record& record) const + virtual int size() const { - return static_cast(record.get().mPoints.size()); + return mRecord.mPoints.size(); // used in IdTree::setNestedTable() } }; - template - class PathgridEdgeListAdapter : public NestedIdAdapter + class PathgridPointListAdapter : public NestedIdAdapter { public: - PathgridEdgeListAdapter () {} - - // FIXME: seems to be auto-sorted in the dialog table display after insertion - virtual void addNestedRow(Record& record, int position) const - { - ESXRecordT pathgrid = record.get(); - - ESM::Pathgrid::EdgeList& edges = pathgrid.mEdges; - - // blank row - ESM::Pathgrid::Edge edge; - edge.mV0 = 0; - edge.mV1 = 0; - - // NOTE: inserting a blank edge does not really make sense, perhaps this should be a - // logic_error exception - // - // Currently the code assumes that the end user to know what he/she is doing. - // e.g. Edges come in pairs, from points a->b and b->a - edges.insert(edges.begin()+position, edge); - - record.setModified (pathgrid); - } - - virtual void removeNestedRow(Record& record, int rowToRemove) const - { - ESXRecordT pathgrid = record.get(); - - ESM::Pathgrid::EdgeList& edges = pathgrid.mEdges; - - if (rowToRemove < 0 || rowToRemove >= static_cast (edges.size())) - throw std::runtime_error ("index out of range"); - - edges.erase(edges.begin()+rowToRemove); - - record.setModified (pathgrid); - } + PathgridPointListAdapter (); - virtual void setNestedTable(Record& record, const NestedTableWrapperBase& nestedTable) const - { - record.get().mEdges = - static_cast &>(nestedTable).mNestedTable; - } - - virtual NestedTableWrapperBase* nestedTable(const Record& record) const - { - // deleted by dtor of NestedTableStoring - return new NestedTableWrapper(record.get().mEdges); - } - - virtual QVariant getNestedData(const Record& record, int subRowIndex, int subColIndex) const - { - ESXRecordT pathgrid = record.get(); + virtual void addNestedRow(Record& record, int position) const; - if (subRowIndex < 0 || subRowIndex >= static_cast (pathgrid.mEdges.size())) - throw std::runtime_error ("index out of range"); - - ESM::Pathgrid::Edge edge = pathgrid.mEdges[subRowIndex]; - switch (subColIndex) - { - case 0: return subRowIndex; - case 1: return edge.mV0; - case 2: return edge.mV1; - default: throw std::runtime_error("Pathgrid edge subcolumn index out of range"); - } - } + virtual void removeNestedRow(Record& record, int rowToRemove) const; - // FIXME: detect duplicates in mEdges - virtual void setNestedData(Record& record, const QVariant& value, - int subRowIndex, int subColIndex) const - { - ESXRecordT pathgrid = record.get(); + virtual void setNestedTable(Record& record, + const NestedTableWrapperBase& nestedTable) const; - if (subRowIndex < 0 || subRowIndex >= static_cast (pathgrid.mEdges.size())) - throw std::runtime_error ("index out of range"); + virtual NestedTableWrapperBase* nestedTable(const Record& record) const; - ESM::Pathgrid::Edge edge = pathgrid.mEdges[subRowIndex]; - switch (subColIndex) - { - case 0: break; - case 1: edge.mV0 = value.toInt(); break; - case 2: edge.mV1 = value.toInt(); break; - default: throw std::runtime_error("Pathgrid edge subcolumn index out of range"); - } + virtual QVariant getNestedData(const Record& record, + int subRowIndex, int subColIndex) const; - pathgrid.mEdges[subRowIndex] = edge; + virtual void setNestedData(Record& record, + const QVariant& value, int subRowIndex, int subColIndex) const; - record.setModified (pathgrid); - } + virtual int getNestedColumnsCount(const Record& record) const; - virtual int getNestedColumnsCount(const Record& record) const - { - return 3; - } - - virtual int getNestedRowsCount(const Record& record) const - { - return static_cast(record.get().mEdges.size()); - } + virtual int getNestedRowsCount(const Record& record) const; }; - template - class FactionReactionsAdapter : public NestedIdAdapter + class PathgridEdgeListAdapter : public NestedIdAdapter { public: - FactionReactionsAdapter () {} - - virtual void addNestedRow(Record& record, int position) const - { - ESXRecordT faction = record.get(); - - std::map& reactions = faction.mReactions; - - // blank row - reactions.insert(std::make_pair("", 0)); - - record.setModified (faction); - } - - virtual void removeNestedRow(Record& record, int rowToRemove) const - { - ESXRecordT faction = record.get(); - - std::map& reactions = faction.mReactions; - - if (rowToRemove < 0 || rowToRemove >= static_cast (reactions.size())) - throw std::runtime_error ("index out of range"); - - // FIXME: how to ensure that the map entries correspond to table indicies? - // WARNING: Assumed that the table view has the same order as std::map - std::map::iterator iter = reactions.begin(); - for(int i = 0; i < rowToRemove; ++i) - iter++; - reactions.erase(iter); - - record.setModified (faction); - } - - virtual void setNestedTable(Record& record, const NestedTableWrapperBase& nestedTable) const - { - record.get().mReactions = - static_cast >&>(nestedTable).mNestedTable; - } - - virtual NestedTableWrapperBase* nestedTable(const Record& record) const - { - // deleted by dtor of NestedTableStoring - return new NestedTableWrapper >(record.get().mReactions); - } - - virtual QVariant getNestedData(const Record& record, int subRowIndex, int subColIndex) const - { - ESXRecordT faction = record.get(); - - std::map& reactions = faction.mReactions; - - if (subRowIndex < 0 || subRowIndex >= static_cast (reactions.size())) - throw std::runtime_error ("index out of range"); - - // FIXME: how to ensure that the map entries correspond to table indicies? - // WARNING: Assumed that the table view has the same order as std::map - std::map::const_iterator iter = reactions.begin(); - for(int i = 0; i < subRowIndex; ++i) - iter++; - switch (subColIndex) - { - case 0: return QString((*iter).first.c_str()); - case 1: return (*iter).second; - default: throw std::runtime_error("Faction reactions subcolumn index out of range"); - } - } + PathgridEdgeListAdapter (); - virtual void setNestedData(Record& record, const QVariant& value, - int subRowIndex, int subColIndex) const - { - ESXRecordT faction = record.get(); + virtual void addNestedRow(Record& record, int position) const; - std::map& reactions = faction.mReactions; + virtual void removeNestedRow(Record& record, int rowToRemove) const; - if (subRowIndex < 0 || subRowIndex >= static_cast (reactions.size())) - throw std::runtime_error ("index out of range"); + virtual void setNestedTable(Record& record, + const NestedTableWrapperBase& nestedTable) const; - // FIXME: how to ensure that the map entries correspond to table indicies? - // WARNING: Assumed that the table view has the same order as std::map - std::map::iterator iter = reactions.begin(); - for(int i = 0; i < subRowIndex; ++i) - iter++; + virtual NestedTableWrapperBase* nestedTable(const Record& record) const; - std::string factionId = (*iter).first; - int reaction = (*iter).second; - - switch (subColIndex) - { - case 0: - { - reactions.erase(iter); - reactions.insert(std::make_pair(value.toString().toUtf8().constData(), reaction)); - break; - } - case 1: - { - reactions[factionId] = value.toInt(); - break; - } - default: throw std::runtime_error("Faction reactions subcolumn index out of range"); - } + virtual QVariant getNestedData(const Record& record, + int subRowIndex, int subColIndex) const; - record.setModified (faction); - } + virtual void setNestedData(Record& record, + const QVariant& value, int subRowIndex, int subColIndex) const; - virtual int getNestedColumnsCount(const Record& record) const - { - return 2; - } + virtual int getNestedColumnsCount(const Record& record) const; - virtual int getNestedRowsCount(const Record& record) const - { - return static_cast(record.get().mReactions.size()); - } + virtual int getNestedRowsCount(const Record& record) const; }; - template - class RegionSoundListAdapter : public NestedIdAdapter + class FactionReactionsAdapter : public NestedIdAdapter { public: - RegionSoundListAdapter () {} - - virtual void addNestedRow(Record& record, int position) const - { - ESXRecordT region = record.get(); - - std::vector& soundList = region.mSoundList; + FactionReactionsAdapter (); - // blank row - typename ESXRecordT::SoundRef soundRef; - soundRef.mSound.assign(""); - soundRef.mChance = 0; - - soundList.insert(soundList.begin()+position, soundRef); - - record.setModified (region); - } - - virtual void removeNestedRow(Record& record, int rowToRemove) const - { - ESXRecordT region = record.get(); + virtual void addNestedRow(Record& record, int position) const; - std::vector& soundList = region.mSoundList; + virtual void removeNestedRow(Record& record, int rowToRemove) const; - if (rowToRemove < 0 || rowToRemove >= static_cast (soundList.size())) - throw std::runtime_error ("index out of range"); - - soundList.erase(soundList.begin()+rowToRemove); - - record.setModified (region); - } + virtual void setNestedTable(Record& record, + const NestedTableWrapperBase& nestedTable) const; - virtual void setNestedTable(Record& record, const NestedTableWrapperBase& nestedTable) const - { - record.get().mSoundList = - static_cast >&>(nestedTable).mNestedTable; - } + virtual NestedTableWrapperBase* nestedTable(const Record& record) const; - virtual NestedTableWrapperBase* nestedTable(const Record& record) const - { - // deleted by dtor of NestedTableStoring - return new NestedTableWrapper >(record.get().mSoundList); - } + virtual QVariant getNestedData(const Record& record, + int subRowIndex, int subColIndex) const; - virtual QVariant getNestedData(const Record& record, int subRowIndex, int subColIndex) const - { - ESXRecordT region = record.get(); + virtual void setNestedData(Record& record, + const QVariant& value, int subRowIndex, int subColIndex) const; - std::vector& soundList = region.mSoundList; + virtual int getNestedColumnsCount(const Record& record) const; - if (subRowIndex < 0 || subRowIndex >= static_cast (soundList.size())) - throw std::runtime_error ("index out of range"); + virtual int getNestedRowsCount(const Record& record) const; + }; - typename ESXRecordT::SoundRef soundRef = soundList[subRowIndex]; - switch (subColIndex) - { - case 0: return QString(soundRef.mSound.toString().c_str()); - case 1: return soundRef.mChance; - default: throw std::runtime_error("Region sounds subcolumn index out of range"); - } - } + class RegionSoundListAdapter : public NestedIdAdapter + { + public: + RegionSoundListAdapter (); - virtual void setNestedData(Record& record, const QVariant& value, - int subRowIndex, int subColIndex) const - { - ESXRecordT region = record.get(); + virtual void addNestedRow(Record& record, int position) const; - std::vector& soundList = region.mSoundList; + virtual void removeNestedRow(Record& record, int rowToRemove) const; - if (subRowIndex < 0 || subRowIndex >= static_cast (soundList.size())) - throw std::runtime_error ("index out of range"); + virtual void setNestedTable(Record& record, + const NestedTableWrapperBase& nestedTable) const; - typename ESXRecordT::SoundRef soundRef = soundList[subRowIndex]; - switch (subColIndex) - { - case 0: soundRef.mSound.assign(value.toString().toUtf8().constData()); break; - case 1: soundRef.mChance = static_cast(value.toInt()); break; - default: throw std::runtime_error("Region sounds subcolumn index out of range"); - } + virtual NestedTableWrapperBase* nestedTable(const Record& record) const; - region.mSoundList[subRowIndex] = soundRef; + virtual QVariant getNestedData(const Record& record, + int subRowIndex, int subColIndex) const; - record.setModified (region); - } + virtual void setNestedData(Record& record, + const QVariant& value, int subRowIndex, int subColIndex) const; - virtual int getNestedColumnsCount(const Record& record) const - { - return 2; - } + virtual int getNestedColumnsCount(const Record& record) const; - virtual int getNestedRowsCount(const Record& record) const - { - return static_cast(record.get().mSoundList.size()); - } + virtual int getNestedRowsCount(const Record& record) const; }; template