#ifndef CSM_WOLRD_IDADAPTERIMP_H #define CSM_WOLRD_IDADAPTERIMP_H #include #include #include "idadapter.hpp" namespace CSMWorld { struct NestedTableWrapperBase; 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); } virtual void setNestedTable(Record& record, const NestedTableWrapperBase& nestedTable) { record.get().mPoints = static_cast &>(nestedTable).mNestedTable; } virtual NestedTableWrapperBase* nestedTable(const Record& record) const { // deleted by dtor of NestedTableStoring return new NestedTableWrapper(record.get().mPoints); } 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::logic_error("Pathgrid point subcolumn index out of range"); } } 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::logic_error("Pathgrid point subcolumn index out of range"); } pathgrid.mPoints[subRowIndex] = point; record.setModified (pathgrid); } virtual int getNestedColumnsCount(const Record& record) const { return 4; } virtual int getNestedRowsCount(const Record& record) const { return static_cast(record.get().mPoints.size()); } }; template class PathgridEdgeListAdapter : 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); } virtual void setNestedTable(Record& record, const NestedTableWrapperBase& nestedTable) { 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 { ESM::Pathgrid::Edge edge = record.get().mEdges[subRowIndex]; switch (subColIndex) { case 0: return subRowIndex; case 1: return edge.mV0; case 2: return edge.mV1; default: throw std::logic_error("Pathgrid edge subcolumn index out of range"); } } // FIXME: detect duplicates in mEdges virtual void setNestedData(Record& record, const QVariant& value, int subRowIndex, int subColIndex) const { ESXRecordT pathgrid = record.get(); 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::logic_error("Pathgrid edge subcolumn index out of range"); } pathgrid.mEdges[subRowIndex] = edge; record.setModified (pathgrid); } virtual int getNestedColumnsCount(const Record& record) const { return 3; } virtual int getNestedRowsCount(const Record& record) const { return static_cast(record.get().mEdges.size()); } }; } #endif // CSM_WOLRD_IDADAPTERIMP_H