From 1ff8abb240e4f235e8d66af9c169cc92735e0c21 Mon Sep 17 00:00:00 2001 From: Marek Kochanowicz Date: Fri, 18 Jul 2014 18:26:22 +0200 Subject: [PATCH] store whole container representing the nested table inside of the command Static nature of C++ forced me to use templates. Bit frustraiting. --- apps/opencs/CMakeLists.txt | 2 +- apps/opencs/model/world/collection.hpp | 18 ++++++++++ apps/opencs/model/world/collectionbase.hpp | 11 ++++-- apps/opencs/model/world/commands.cpp | 36 ++++--------------- apps/opencs/model/world/commands.hpp | 6 +++- apps/opencs/model/world/idtable.cpp | 21 +++++++++++ apps/opencs/model/world/idtable.hpp | 5 +++ .../opencs/model/world/nestedtablewrapper.cpp | 7 ++++ .../opencs/model/world/nestedtablewrapper.hpp | 33 +++++++++++++++++ apps/opencs/model/world/refidadapter.hpp | 9 +++-- apps/opencs/model/world/refidadapterimp.cpp | 23 ++++++++++++ apps/opencs/model/world/refidadapterimp.hpp | 6 ++++ apps/opencs/model/world/refidcollection.cpp | 21 ++++++++++- apps/opencs/model/world/refidcollection.hpp | 7 +++- 14 files changed, 167 insertions(+), 38 deletions(-) create mode 100644 apps/opencs/model/world/nestedtablewrapper.cpp create mode 100644 apps/opencs/model/world/nestedtablewrapper.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 3871a4d5a..bcc64b60a 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -19,7 +19,7 @@ opencs_hdrs_noqt (model/doc opencs_units (model/world idtable idtableproxymodel regionmap data commanddispatcher - idtablebase resourcetable nestedtablemodel + idtablebase resourcetable nestedtablemodel nestedtablewrapper ) diff --git a/apps/opencs/model/world/collection.hpp b/apps/opencs/model/world/collection.hpp index 904587eaf..ac4351986 100644 --- a/apps/opencs/model/world/collection.hpp +++ b/apps/opencs/model/world/collection.hpp @@ -16,6 +16,8 @@ #include "collectionbase.hpp" +#include "nestedtablewrapper.hpp" + namespace CSMWorld { /// \brief Access to ID field in records @@ -90,6 +92,10 @@ namespace CSMWorld virtual void setData (int index, int column, const QVariant& data); + virtual NestedTableWrapperBase nestedTable(int row, int column) const; + + virtual void setNestedTable(int row, int column, const NestedTableWrapperBase& nestedTable); + virtual const ColumnBase& getColumn (int column) const; virtual void merge(); @@ -300,6 +306,18 @@ namespace CSMWorld { return QVariant(); } + + template + NestedTableWrapperBase Collection::nestedTable(int row, int column) const + { + return NestedTableWrapperBase(); + } + + template + void Collection::setNestedTable(int row, int column, const NestedTableWrapperBase& nestedTable) + { + throw std::logic_error("setNestedTable was not overriden"); + } template void Collection::setData (int index, int column, const QVariant& data) diff --git a/apps/opencs/model/world/collectionbase.hpp b/apps/opencs/model/world/collectionbase.hpp index aad40d36b..62f4079fc 100644 --- a/apps/opencs/model/world/collectionbase.hpp +++ b/apps/opencs/model/world/collectionbase.hpp @@ -13,6 +13,7 @@ namespace CSMWorld { struct ColumnBase; struct RecordBase; + class NestedTableWrapperBase; /// \brief Base class for record collections /// @@ -33,10 +34,10 @@ namespace CSMWorld virtual ~CollectionBase(); virtual int getSize() const = 0; - - virtual int getNestedRowsCount(int row, int column) const; - virtual int getNestedColumnsCount(int row, int column) const; + virtual int getNestedRowsCount(int row, int column) const; + + virtual int getNestedColumnsCount(int row, int column) const; virtual std::string getId (int index) const = 0; @@ -50,6 +51,10 @@ namespace CSMWorld virtual QVariant getNestedData(int row, int column, int subRow, int subColumn) const = 0; + virtual NestedTableWrapperBase nestedTable(int row, int column) const = 0; + + virtual void setNestedTable(int row, int column, const NestedTableWrapperBase& nestedTable) = 0; + virtual void setData (int index, int column, const QVariant& data) = 0; virtual void setNestedData(int row, int column, const QVariant& data, int subRow, int subColumn); diff --git a/apps/opencs/model/world/commands.cpp b/apps/opencs/model/world/commands.cpp index 012736697..5e886bdb4 100644 --- a/apps/opencs/model/world/commands.cpp +++ b/apps/opencs/model/world/commands.cpp @@ -177,26 +177,10 @@ CSMWorld::DeleteNestedCommand::DeleteNestedCommand (IdTable& model, const std::s mModel(model), mParentColumn(parentColumn), QUndoCommand(parent), - mNestedRow(nestedRow) + mNestedRow(nestedRow), + mOld(model.nestedTable(model.getModelIndex(id, parentColumn))) { setText (("Delete nested row in " + mId).c_str()); - - const QModelIndex& parentIndex = mModel.getModelIndex(mId, mParentColumn); - - const int columnsCount = mModel.columnCount(parentIndex); - - for (int i = 0; i < columnsCount; ++i) - { - const QModelIndex& childIndex = mModel.index(nestedRow, i, parentIndex); - - QVariant data = childIndex.data(); - if (!data.isValid()) - { - data = childIndex.data(Qt::DisplayRole); - } - - mOld.push_back(data); - } } void CSMWorld::DeleteNestedCommand::redo() @@ -211,14 +195,7 @@ void CSMWorld::DeleteNestedCommand::undo() { const QModelIndex& parentIndex = mModel.getModelIndex(mId, mParentColumn); - mModel.addNestedRow(parentIndex, mNestedRow); - - for (int i = 0; i < mModel.columnCount(parentIndex); ++i) - { - const QModelIndex& current = mModel.index(mNestedRow, i, parentIndex); - - mModel.setData(current, mOld[i]); - } + mModel.setNestedTable(parentIndex, mOld); } CSMWorld::AddNestedCommand::AddNestedCommand(IdTable& model, const std::string& id, int nestedRow, int parentColumn, QUndoCommand* parent) @@ -226,7 +203,8 @@ CSMWorld::AddNestedCommand::AddNestedCommand(IdTable& model, const std::string& mId(id), mNewRow(nestedRow), mParentColumn(parentColumn), - QUndoCommand(parent) + QUndoCommand(parent), + mOld(model.nestedTable(model.getModelIndex(id, parentColumn))) { setText (("Added nested row in " + mId).c_str()); } @@ -241,6 +219,6 @@ void CSMWorld::AddNestedCommand::redo() void CSMWorld::AddNestedCommand::undo() { const QModelIndex& parentIndex = mModel.getModelIndex(mId, mParentColumn); - - mModel.removeRows(mNewRow, 1, parentIndex); + + mModel.setNestedTable(parentIndex, mOld); } diff --git a/apps/opencs/model/world/commands.hpp b/apps/opencs/model/world/commands.hpp index e6f2d9724..214a5157e 100644 --- a/apps/opencs/model/world/commands.hpp +++ b/apps/opencs/model/world/commands.hpp @@ -13,6 +13,7 @@ #include #include "universalid.hpp" +#include "nestedtablewrapper.hpp" class QModelIndex; class QAbstractItemModel; @@ -22,6 +23,7 @@ namespace CSMWorld class IdTable; class IdTable; class RecordBase; + class NestedTableWrapperBase; class ModifyCommand : public QUndoCommand { @@ -143,7 +145,7 @@ namespace CSMWorld std::string mId; - std::vector mOld; + NestedTableWrapperBase mOld; int mParentColumn; @@ -164,6 +166,8 @@ namespace CSMWorld std::string mId; + NestedTableWrapperBase mOld; + int mNewRow; int mParentColumn; diff --git a/apps/opencs/model/world/idtable.cpp b/apps/opencs/model/world/idtable.cpp index a3435180c..df0f4546d 100644 --- a/apps/opencs/model/world/idtable.cpp +++ b/apps/opencs/model/world/idtable.cpp @@ -2,6 +2,7 @@ #include #include +#include "nestedtablewrapper.hpp" #include "collectionbase.hpp" #include "columnbase.hpp" @@ -357,3 +358,23 @@ bool CSMWorld::IdTable::hasChildren(const QModelIndex& index) const mIdCollection->getColumn(index.column()).mCanNest && index.data().isValid()); } + +void CSMWorld::IdTable::setNestedTable(const QModelIndex& index, const CSMWorld::NestedTableWrapperBase& nestedTable) +{ + if (!hasChildren(index)) + { + throw std::logic_error("Tried to set nested table, but index has no children"); + } + + mIdCollection->setNestedTable(index.row(), index.column(), nestedTable); +} + +CSMWorld::NestedTableWrapperBase CSMWorld::IdTable::nestedTable(const QModelIndex& index) const +{ + if (!hasChildren(index)) + { + throw std::logic_error("Tried to retrive nested table, but index has no children"); + } + + return mIdCollection->nestedTable(index.row(), index.column()); +} diff --git a/apps/opencs/model/world/idtable.hpp b/apps/opencs/model/world/idtable.hpp index fcb87c8b2..fd3f699ba 100644 --- a/apps/opencs/model/world/idtable.hpp +++ b/apps/opencs/model/world/idtable.hpp @@ -20,6 +20,7 @@ namespace CSMWorld { class CollectionBase; class RecordBase; + class NestedTableWrapperBase; class IdTable : public IdTableBase { @@ -51,6 +52,10 @@ namespace CSMWorld virtual QVariant headerData (int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; QVariant nestedHeaderData(int section, int subSection, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + + NestedTableWrapperBase nestedTable(const QModelIndex &index) const; + + void setNestedTable(const QModelIndex &index, const NestedTableWrapperBase& nestedTable); virtual bool setData ( const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); diff --git a/apps/opencs/model/world/nestedtablewrapper.cpp b/apps/opencs/model/world/nestedtablewrapper.cpp new file mode 100644 index 000000000..387bc6e7b --- /dev/null +++ b/apps/opencs/model/world/nestedtablewrapper.cpp @@ -0,0 +1,7 @@ +#include "nestedtablewrapper.hpp" + +CSMWorld::NestedTableWrapperBase::NestedTableWrapperBase() +{} + +CSMWorld::NestedTableWrapperBase::~NestedTableWrapperBase() +{} diff --git a/apps/opencs/model/world/nestedtablewrapper.hpp b/apps/opencs/model/world/nestedtablewrapper.hpp new file mode 100644 index 000000000..9fc21f8e0 --- /dev/null +++ b/apps/opencs/model/world/nestedtablewrapper.hpp @@ -0,0 +1,33 @@ +#ifndef CSM_WOLRD_NESTEDTABLEWRAPPER_H +#define CSM_WOLRD_NESTEDTABLEWRAPPER_H + +#include + +#include +namespace CSMWorld +{ + struct NestedTableWrapperBase + { + virtual ~NestedTableWrapperBase(); + + NestedTableWrapperBase(); + }; + + template + class NestedTableWrapper : public NestedTableWrapperBase + { + NestedTable mNestedTable; + + public: + + NestedTableWrapper(const NestedTable& nestedTable) {} + + NestedTable getNestedTable() const + { + return mNestedTable; + } + + virtual ~NestedTableWrapper() {} + }; +} +#endif diff --git a/apps/opencs/model/world/refidadapter.hpp b/apps/opencs/model/world/refidadapter.hpp index 068347fda..f4aa769fd 100644 --- a/apps/opencs/model/world/refidadapter.hpp +++ b/apps/opencs/model/world/refidadapter.hpp @@ -10,6 +10,7 @@ namespace CSMWorld class RefIdColumn; class RefIdData; class RecordBase; + class NestedTableWrapperBase; class RefIdAdapter { @@ -41,7 +42,7 @@ namespace CSMWorld NestedRefIdAdapter(); virtual ~NestedRefIdAdapter(); - + virtual void setNestedData (const RefIdColumn *column, RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const = 0; @@ -53,8 +54,12 @@ namespace CSMWorld virtual int getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const = 0; virtual void removeNestedRow (const RefIdColumn *column, RefIdData& data, int index, int rowToRemove) const = 0; - + virtual void addNestedRow (const RefIdColumn *column, RefIdData& data, int index, int position) const = 0; + + virtual void setNestedTable (const RefIdColumn* column, RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) = 0; + + virtual NestedTableWrapperBase nestedTable (const RefIdColumn * column, const RefIdData& data, int index) const = 0; }; } diff --git a/apps/opencs/model/world/refidadapterimp.cpp b/apps/opencs/model/world/refidadapterimp.cpp index 8d6ab838d..cb078ab74 100644 --- a/apps/opencs/model/world/refidadapterimp.cpp +++ b/apps/opencs/model/world/refidadapterimp.cpp @@ -1,7 +1,9 @@ #include "refidadapterimp.hpp" +#include "nestedtablewrapper.hpp" #include #include +#include CSMWorld::PotionRefIdAdapter::PotionRefIdAdapter (const InventoryColumns& columns, const RefIdColumn *autoCalc) @@ -305,6 +307,27 @@ void CSMWorld::ContainerRefIdAdapter::setNestedData(const RefIdColumn *column, } } +void CSMWorld::ContainerRefIdAdapter::setNestedTable(const RefIdColumn* column, + RefIdData& data, + int index, + const NestedTableWrapperBase& nestedTable) +{ + Record& record = dynamic_cast&> ( + data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Container))); + + record.get().mInventory.mList = dynamic_cast >&>(nestedTable).getNestedTable(); +} + +CSMWorld::NestedTableWrapperBase CSMWorld::ContainerRefIdAdapter::nestedTable (const RefIdColumn* column, + const RefIdData& data, + int index) const +{ + const Record& record = dynamic_cast&> ( + data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Container))); + + return NestedTableWrapper >(record.get().mInventory.mList); +} + QVariant CSMWorld::ContainerRefIdAdapter::getNestedData (const CSMWorld::RefIdColumn* column, const CSMWorld::RefIdData& data, int index, diff --git a/apps/opencs/model/world/refidadapterimp.hpp b/apps/opencs/model/world/refidadapterimp.hpp index 500b18ef8..4198fb367 100644 --- a/apps/opencs/model/world/refidadapterimp.hpp +++ b/apps/opencs/model/world/refidadapterimp.hpp @@ -15,6 +15,8 @@ namespace CSMWorld { + class NestedTableWrapperBase; + struct BaseColumns { const RefIdColumn *mId; @@ -637,6 +639,10 @@ namespace CSMWorld 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 NestedTableWrapperBase nestedTable (const RefIdColumn * column, const RefIdData& data, int index) const; + + virtual void setNestedTable (const RefIdColumn* column, RefIdData& data, int index, const NestedTableWrapperBase& nestedTable); }; struct CreatureColumns : public ActorColumns diff --git a/apps/opencs/model/world/refidcollection.cpp b/apps/opencs/model/world/refidcollection.cpp index 1a164d12f..6ff0df802 100644 --- a/apps/opencs/model/world/refidcollection.cpp +++ b/apps/opencs/model/world/refidcollection.cpp @@ -10,6 +10,7 @@ #include "refidadapter.hpp" #include "refidadapterimp.hpp" #include "columns.hpp" +#include "nestedtablewrapper.hpp" CSMWorld::RefIdColumn::RefIdColumn (int columnId, Display displayType, int flag, bool editable, bool userEditable, bool canNest) @@ -27,7 +28,7 @@ bool CSMWorld::RefIdColumn::isUserEditable() const } -const CSMWorld::RefIdAdapter& CSMWorld::RefIdCollection::findAdaptor (UniversalId::Type type) const +CSMWorld::RefIdAdapter& CSMWorld::RefIdCollection::findAdaptor (UniversalId::Type type) const { std::map::const_iterator iter = mAdapters.find (type); @@ -641,3 +642,21 @@ void CSMWorld::RefIdCollection::addNestedRow(int row, int col, int position) adaptor.addNestedRow(&mColumns.at(col), mData, localIndex.first, position); } + +void CSMWorld::RefIdCollection::setNestedTable(int row, int column, const CSMWorld::NestedTableWrapperBase& nestedTable) +{ + RefIdData::LocalIndex localIndex = mData.globalToLocalIndex (row); + + CSMWorld::NestedRefIdAdapter& adaptor = dynamic_cast(findAdaptor (localIndex.second)); + + adaptor.setNestedTable(&mColumns.at(column), mData, localIndex.first, nestedTable); +} + +CSMWorld::NestedTableWrapperBase CSMWorld::RefIdCollection::nestedTable(int row, int column) const +{ + RefIdData::LocalIndex localIndex = mData.globalToLocalIndex (row); + + const CSMWorld::NestedRefIdAdapter& adaptor = dynamic_cast(findAdaptor (localIndex.second)); + + return adaptor.nestedTable(&mColumns.at(column), mData, localIndex.first); +} diff --git a/apps/opencs/model/world/refidcollection.hpp b/apps/opencs/model/world/refidcollection.hpp index 02b77400b..927331c93 100644 --- a/apps/opencs/model/world/refidcollection.hpp +++ b/apps/opencs/model/world/refidcollection.hpp @@ -17,6 +17,7 @@ namespace ESM namespace CSMWorld { class RefIdAdapter; + class NestedTableWrapperBase; class RefIdColumn : public NestColumn { @@ -44,7 +45,7 @@ namespace CSMWorld private: - const RefIdAdapter& findAdaptor (UniversalId::Type) const; + RefIdAdapter& findAdaptor (UniversalId::Type) const; ///< Throws an exception if no adaptor for \a Type can be found. public: @@ -70,6 +71,10 @@ namespace CSMWorld virtual QVariant getData (int index, int column) const; virtual QVariant getNestedData(int row, int column, int subRow, int subColumn) const; + + virtual NestedTableWrapperBase nestedTable(int row, int column) const; + + virtual void setNestedTable(int row, int column, const NestedTableWrapperBase& nestedTable); virtual void setData (int index, int column, const QVariant& data);