From 83bcc8d4512c4571421d9602fb0e367c440dc9f1 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Thu, 2 Apr 2015 20:19:15 +1100 Subject: [PATCH] Reorganised class inheritance structure of collections, columns and idtable model. --- apps/opencs/CMakeLists.txt | 5 +- apps/opencs/model/world/columnbase.cpp | 45 +-- apps/opencs/model/world/columnbase.hpp | 39 +-- apps/opencs/model/world/commands.cpp | 13 +- apps/opencs/model/world/commands.hpp | 21 +- apps/opencs/model/world/data.cpp | 3 +- apps/opencs/model/world/idtable.cpp | 208 +----------- apps/opencs/model/world/idtable.hpp | 27 -- apps/opencs/model/world/idtree.cpp | 296 ++++++++++++++++++ apps/opencs/model/world/idtree.hpp | 88 ++++++ apps/opencs/model/world/nestablecolumn.cpp | 44 +++ apps/opencs/model/world/nestablecolumn.hpp | 33 ++ apps/opencs/model/world/nestedcollection.hpp | 10 + .../model/world/nestedtableproxymodel.cpp | 6 +- .../model/world/nestedtableproxymodel.hpp | 8 +- apps/opencs/model/world/refidcollection.cpp | 62 ++-- apps/opencs/model/world/refidcollection.hpp | 45 +-- apps/opencs/model/world/refiddata.hpp | 6 +- apps/opencs/view/world/dialoguesubview.cpp | 3 +- 19 files changed, 590 insertions(+), 372 deletions(-) create mode 100644 apps/opencs/model/world/idtree.cpp create mode 100644 apps/opencs/model/world/idtree.hpp create mode 100644 apps/opencs/model/world/nestablecolumn.cpp create mode 100644 apps/opencs/model/world/nestablecolumn.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 5f95592578..39b4c486bc 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -18,15 +18,14 @@ opencs_hdrs_noqt (model/doc opencs_units (model/world - idtable idtableproxymodel regionmap data commanddispatcher - idtablebase resourcetable nestedtableproxymodel + idtable idtableproxymodel regionmap data commanddispatcher idtablebase resourcetable nestedtableproxymodel idtree ) 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 + pathgrid landtexture land nestedtablewrapper nestedadapters nestedcollection nestablecolumn ) opencs_hdrs_noqt (model/world diff --git a/apps/opencs/model/world/columnbase.cpp b/apps/opencs/model/world/columnbase.cpp index 60e201ba45..665ab93545 100644 --- a/apps/opencs/model/world/columnbase.cpp +++ b/apps/opencs/model/world/columnbase.cpp @@ -1,9 +1,10 @@ + #include "columnbase.hpp" #include "columns.hpp" -CSMWorld::ColumnBase::ColumnBase (int columnId, Display displayType, int flags, bool canNest) - : mColumnId (columnId), mDisplayType (displayType), mFlags (flags), mCanNest(canNest) +CSMWorld::ColumnBase::ColumnBase (int columnId, Display displayType, int flags) +: mColumnId (columnId), mDisplayType (displayType), mFlags (flags) {} CSMWorld::ColumnBase::~ColumnBase() {} @@ -22,43 +23,3 @@ int CSMWorld::ColumnBase::getId() const { return mColumnId; } - -bool CSMWorld::NestColumn::canHaveNestedColumns() const -{ - return mCanNest; -} - -void CSMWorld::NestColumn::addNestedColumn(int columnId, Display displayType) -{ - if (!mCanNest) - throw std::logic_error("Tried to nest inside of the non-nest column"); - - mNestedColumns.push_back(CSMWorld::NestedColumn(columnId, displayType, mFlags, this)); -} - -const CSMWorld::ColumnBase& CSMWorld::NestColumn::nestedColumn(int subColumn) const -{ - if (!mCanNest) - throw std::logic_error("Tried to access nested column of the non-nest column"); - - return mNestedColumns.at(subColumn); -} - -int CSMWorld::NestColumn::nestedColumnCount() const -{ - if (!mCanNest) - throw std::logic_error("Tried to access number of the subcolumns in the non-nest column"); - - return mNestedColumns.size(); -} - -CSMWorld::NestColumn::NestColumn(int columnId, Display displayType, int flags, bool canNest) - : CSMWorld::ColumnBase(columnId, displayType, flags, canNest) {} - -CSMWorld::NestedColumn::NestedColumn(int columnId, Display displayType, int flag, const CSMWorld::NestColumn* parent) - : mParent(parent), CSMWorld::ColumnBase(columnId, displayType, flag) {} - -bool CSMWorld::NestedColumn::isEditable() const -{ - return mParent->isEditable(); -} diff --git a/apps/opencs/model/world/columnbase.hpp b/apps/opencs/model/world/columnbase.hpp index 607f585b76..b717f3a52b 100644 --- a/apps/opencs/model/world/columnbase.hpp +++ b/apps/opencs/model/world/columnbase.hpp @@ -3,7 +3,7 @@ #include #include -#include +#include #include #include @@ -117,9 +117,8 @@ namespace CSMWorld int mColumnId; int mFlags; Display mDisplayType; - bool mCanNest; - ColumnBase (int columnId, Display displayType, int flag, bool canNest = false); + ColumnBase (int columnId, Display displayType, int flag); virtual ~ColumnBase(); @@ -133,39 +132,11 @@ namespace CSMWorld virtual int getId() const; }; - class NestedColumn; - - class NestColumn : public ColumnBase - { - std::vector mNestedColumns; - - public: - NestColumn(int columnId, Display displayType, int flags, bool canNest); - - void addNestedColumn(int columnId, Display displayType); - - bool canHaveNestedColumns() const; - - const ColumnBase& nestedColumn(int subColumn) const; - - int nestedColumnCount() const; - }; - - class NestedColumn : public ColumnBase - { - const ColumnBase* mParent; - - public: - NestedColumn(int columnId, Display displayType, int flag, const NestColumn* parent); - - virtual bool isEditable() const; - }; - template - struct Column : public NestColumn + struct Column : public ColumnBase { - Column (int columnId, Display displayType, int flags = Flag_Table | Flag_Dialogue, bool canNest = false) - : NestColumn (columnId, displayType, flags, canNest) {} + Column (int columnId, Display displayType, int flags = Flag_Table | Flag_Dialogue) + : ColumnBase (columnId, displayType, flags) {} virtual QVariant get (const Record& record) const = 0; diff --git a/apps/opencs/model/world/commands.cpp b/apps/opencs/model/world/commands.cpp index 959f6b345c..7acc6058ef 100644 --- a/apps/opencs/model/world/commands.cpp +++ b/apps/opencs/model/world/commands.cpp @@ -3,6 +3,7 @@ #include #include "idtable.hpp" +#include "idtree.hpp" #include #include "nestedtablewrapper.hpp" @@ -172,10 +173,10 @@ void CSMWorld::CloneCommand::undo() mModel.removeRow (mModel.getModelIndex (mId, 0).row()); } -CSMWorld::DeleteNestedCommand::DeleteNestedCommand (IdTable& model, +CSMWorld::DeleteNestedCommand::DeleteNestedCommand (IdTree& model, const std::string& id, - int nestedRow, - int parentColumn, + int nestedRow, + int parentColumn, QUndoCommand* parent) : mId(id), mModel(model), @@ -192,7 +193,7 @@ void CSMWorld::DeleteNestedCommand::redo() const QModelIndex& parentIndex = mModel.getModelIndex(mId, mParentColumn); mModel.removeRows (mNestedRow, 1, parentIndex); -} +} void CSMWorld::DeleteNestedCommand::undo() @@ -202,7 +203,7 @@ void CSMWorld::DeleteNestedCommand::undo() mModel.setNestedTable(parentIndex, getOld()); } -CSMWorld::AddNestedCommand::AddNestedCommand(IdTable& model, const std::string& id, int nestedRow, int parentColumn, QUndoCommand* parent) +CSMWorld::AddNestedCommand::AddNestedCommand(IdTree& model, const std::string& id, int nestedRow, int parentColumn, QUndoCommand* parent) : mModel(model), mId(id), mNewRow(nestedRow), @@ -227,7 +228,7 @@ void CSMWorld::AddNestedCommand::undo() mModel.setNestedTable(parentIndex, getOld()); } -CSMWorld::NestedTableStoring::NestedTableStoring(const IdTable& model, const std::string& id, int parentColumn) +CSMWorld::NestedTableStoring::NestedTableStoring(const IdTree& model, const std::string& id, int parentColumn) : mOld(model.nestedTable(model.getModelIndex(id, parentColumn))) {} CSMWorld::NestedTableStoring::~NestedTableStoring() diff --git a/apps/opencs/model/world/commands.hpp b/apps/opencs/model/world/commands.hpp index c194e2779b..42405a2f9d 100644 --- a/apps/opencs/model/world/commands.hpp +++ b/apps/opencs/model/world/commands.hpp @@ -10,7 +10,6 @@ #include #include #include -#include #include "universalid.hpp" #include "nestedtablewrapper.hpp" @@ -21,7 +20,7 @@ class QAbstractItemModel; namespace CSMWorld { class IdTable; - class IdTable; + class IdTree; struct RecordBase; class NestedTableWrapperBase; @@ -148,18 +147,18 @@ namespace CSMWorld NestedTableWrapperBase* mOld; public: - NestedTableStoring(const IdTable& model, const std::string& id, int parentColumn); - + NestedTableStoring(const IdTree& model, const std::string& id, int parentColumn); + ~NestedTableStoring(); - + protected: const NestedTableWrapperBase& getOld() const; }; - + class DeleteNestedCommand : public QUndoCommand, private NestedTableStoring { - IdTable& mModel; + IdTree& mModel; std::string mId; @@ -169,16 +168,16 @@ namespace CSMWorld public: - DeleteNestedCommand (IdTable& model, const std::string& id, int nestedRow, int parentColumn, QUndoCommand* parent = 0); + DeleteNestedCommand (IdTree& model, const std::string& id, int nestedRow, int parentColumn, QUndoCommand* parent = 0); virtual void redo(); virtual void undo(); }; - + class AddNestedCommand : public QUndoCommand, private NestedTableStoring { - IdTable& mModel; + IdTree& mModel; std::string mId; @@ -188,7 +187,7 @@ namespace CSMWorld public: - AddNestedCommand(IdTable& model, const std::string& id, int nestedRow, int parentColumn, QUndoCommand* parent = 0); + AddNestedCommand(IdTree& model, const std::string& id, int nestedRow, int parentColumn, QUndoCommand* parent = 0); virtual void redo(); diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 39cff3db65..a5ef439a7e 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -12,6 +12,7 @@ #include #include "idtable.hpp" +#include "idtree.hpp" #include "columnimp.hpp" #include "regionmap.hpp" #include "columns.hpp" @@ -332,7 +333,7 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc addModel (new IdTable (&mMagicEffects), UniversalId::Type_MagicEffect); addModel (new IdTable (&mPathgrids), UniversalId::Type_Pathgrid); addModel (new IdTable (&mStartScripts), UniversalId::Type_StartScript); - addModel (new IdTable (&mReferenceables, IdTable::Feature_Preview), + addModel (new IdTree (&mReferenceables, IdTable::Feature_Preview), UniversalId::Type_Referenceable); addModel (new IdTable (&mRefs, IdTable::Feature_ViewCell | IdTable::Feature_Preview), UniversalId::Type_Reference); addModel (new IdTable (&mFilters), UniversalId::Type_Filter); diff --git a/apps/opencs/model/world/idtable.cpp b/apps/opencs/model/world/idtable.cpp index 1c21e64c3d..7618a073a9 100644 --- a/apps/opencs/model/world/idtable.cpp +++ b/apps/opencs/model/world/idtable.cpp @@ -1,12 +1,6 @@ #include "idtable.hpp" -#include - -#include -#include -#include "nestedtablewrapper.hpp" #include "collectionbase.hpp" -#include "nestedcollection.hpp" #include "columnbase.hpp" CSMWorld::IdTable::IdTable (CollectionBase *idCollection, unsigned int features) @@ -14,26 +8,20 @@ CSMWorld::IdTable::IdTable (CollectionBase *idCollection, unsigned int features) {} CSMWorld::IdTable::~IdTable() -{ - mIdCollection = 0; // FIXME: workaround only, should stop QHideEvent calling after destruction -} +{} int CSMWorld::IdTable::rowCount (const QModelIndex & parent) const { - if (hasChildren(parent)) - { - return dynamic_cast(mIdCollection)->getNestedRowsCount(parent.row(), parent.column()); - } + if (parent.isValid()) + return 0; return mIdCollection->getSize(); } int CSMWorld::IdTable::columnCount (const QModelIndex & parent) const { - if (hasChildren(parent)) - { - return dynamic_cast(mIdCollection)->getNestedColumnsCount(parent.row(), parent.column()); - } + if (parent.isValid()) + return 0; return mIdCollection->getColumns(); } @@ -46,23 +34,10 @@ QVariant CSMWorld::IdTable::data (const QModelIndex & index, int role) const if (role==Qt::EditRole && !mIdCollection->getColumn (index.column()).isEditable()) return QVariant(); - if (index.internalId() != 0) - { - std::pair parentAdress(unfoldIndexAdress(index.internalId())); - return dynamic_cast(mIdCollection)->getNestedData(parentAdress.first, - parentAdress.second, - index.row(), - index.column()); - } - else - { - return mIdCollection->getData (index.row(), index.column()); - } + return mIdCollection->getData (index.row(), index.column()); } -QVariant CSMWorld::IdTable::headerData (int section, - Qt::Orientation orientation, - int role) const +QVariant CSMWorld::IdTable::headerData (int section, Qt::Orientation orientation, int role) const { if (orientation==Qt::Vertical) return QVariant(); @@ -74,63 +49,19 @@ QVariant CSMWorld::IdTable::headerData (int section, return mIdCollection->getColumn (section).mFlags; if (role==ColumnBase::Role_Display) - { return mIdCollection->getColumn (section).mDisplayType; - } - - return QVariant(); -} - -QVariant CSMWorld::IdTable::nestedHeaderData(int section, int subSection, Qt::Orientation orientation, int role) const -{ - // FIXME: workaround only, should stop QHideEvent calling after destruction - if (section < 0 || !mIdCollection || section >= mIdCollection->getColumns()) - return QVariant(); - - const NestColumn& parentColumn = dynamic_cast(mIdCollection->getColumn(section)); - - if (orientation==Qt::Vertical) - return QVariant(); - - if (role==Qt::DisplayRole) - return tr(parentColumn.nestedColumn(subSection).getTitle().c_str()); - - if (role==ColumnBase::Role_Flags) - return mIdCollection->getColumn (section).mFlags; - - if (role==ColumnBase::Role_Display) - return parentColumn.nestedColumn(subSection).mDisplayType; return QVariant(); } bool CSMWorld::IdTable::setData (const QModelIndex &index, const QVariant &value, int role) { - if (index.internalId() != 0) - { - if (mIdCollection->getColumn(parent(index).column()).isEditable() && role==Qt::EditRole) - { - const std::pair& parentAdress(unfoldIndexAdress(index.internalId())); - - dynamic_cast(mIdCollection)->setNestedData(parentAdress.first, parentAdress.second, value, index.row(), index.column()); - - emit dataChanged (CSMWorld::IdTable::index (parentAdress.first, 0), - CSMWorld::IdTable::index (parentAdress.second, mIdCollection->getColumns()-1)); - - return true; - } - else - { - return false; - } - } - if (mIdCollection->getColumn (index.column()).isEditable() && role==Qt::EditRole) { mIdCollection->setData (index.row(), index.column(), value); emit dataChanged (CSMWorld::IdTable::index (index.row(), 0), - CSMWorld::IdTable::index (index.row(), mIdCollection->getColumns()-1)); + CSMWorld::IdTable::index (index.row(), mIdCollection->getColumns()-1)); return true; } @@ -150,56 +81,22 @@ Qt::ItemFlags CSMWorld::IdTable::flags (const QModelIndex & index) const bool CSMWorld::IdTable::removeRows (int row, int count, const QModelIndex& parent) { + if (parent.isValid()) + return false; + beginRemoveRows (parent, row, row+count-1); - if (parent.isValid()) - { - for (int i = 0; i < count; ++i) - { - dynamic_cast(mIdCollection)->removeNestedRows(parent.row(), parent.column(), row+i); - } - } - else - { - - beginRemoveRows (parent, row, row+count-1); - - mIdCollection->removeRows (row, count); - } + mIdCollection->removeRows (row, count); endRemoveRows(); - emit dataChanged (CSMWorld::IdTable::index (parent.row(), 0), - CSMWorld::IdTable::index (parent.row(), mIdCollection->getColumns()-1)); - return true; } -void CSMWorld::IdTable::addNestedRow(const QModelIndex& parent, int position) -{ - if (!hasChildren(parent)) - { - throw std::logic_error("Tried to set nested table, but index has no children"); - } - - int row = parent.row(); - - beginInsertRows(parent, position, position); - dynamic_cast(mIdCollection)->addNestedRow(row, parent.column(), position); - - endInsertRows(); - - emit dataChanged (CSMWorld::IdTable::index (row, 0), - CSMWorld::IdTable::index (row, mIdCollection->getColumns()-1)); -} - QModelIndex CSMWorld::IdTable::index (int row, int column, const QModelIndex& parent) const { - unsigned int encodedId = 0; if (parent.isValid()) - { - encodedId = this->foldIndexAdress(parent); - } + return QModelIndex(); if (row<0 || row>=mIdCollection->getSize()) return QModelIndex(); @@ -207,24 +104,12 @@ QModelIndex CSMWorld::IdTable::index (int row, int column, const QModelIndex& pa if (column<0 || column>=mIdCollection->getColumns()) return QModelIndex(); - return createIndex(row, column, encodedId); + return createIndex (row, column); } QModelIndex CSMWorld::IdTable::parent (const QModelIndex& index) const { - if (index.internalId() == 0) //0 is used for indexs with invalid parent (top level data) - { - return QModelIndex(); - } - - unsigned int id = index.internalId(); - const std::pair& adress(unfoldIndexAdress(id)); - - if (adress.first >= this->rowCount() || adress.second >= this->columnCount()) - { - throw "Parent index is not present in the model"; - } - return createIndex(adress.first, adress.second); + return QModelIndex(); } void CSMWorld::IdTable::addRecord (const std::string& id, UniversalId::Type type) @@ -346,66 +231,3 @@ int CSMWorld::IdTable::getColumnId(int column) const { return mIdCollection->getColumn(column).getId(); } - -unsigned int CSMWorld::IdTable::foldIndexAdress (const QModelIndex& index) const -{ - unsigned int out = index.row() * this->columnCount(); - out += index.column(); - return ++out; -} - -std::pair< int, int > CSMWorld::IdTable::unfoldIndexAdress (unsigned int id) const -{ - if (id == 0) - { - throw "Attempt to unfold index id of the top level data cell"; - } - - --id; - int row = id / this->columnCount(); - int column = id - row * this->columnCount(); - return std::make_pair (row, column); -} - -bool CSMWorld::IdTable::hasChildren(const QModelIndex& index) const -{ - return (index.isValid() && - index.internalId() == 0 && - 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"); - } - - bool removeRowsMode = false; - if (nestedTable.size() != this->nestedTable(index)->size()) - { - emit resetStart(this->index(index.row(), 0).data().toString()); - removeRowsMode = true; - } - - dynamic_cast(mIdCollection)->setNestedTable(index.row(), index.column(), nestedTable); - - emit dataChanged (CSMWorld::IdTable::index (index.row(), 0), - CSMWorld::IdTable::index (index.row(), mIdCollection->getColumns()-1)); - - if (removeRowsMode) - { - emit resetEnd(this->index(index.row(), 0).data().toString()); - } -} - -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 dynamic_cast(mIdCollection)->nestedTable(index.row(), index.column()); -} diff --git a/apps/opencs/model/world/idtable.hpp b/apps/opencs/model/world/idtable.hpp index 05c523ccb8..ea8ab80f91 100644 --- a/apps/opencs/model/world/idtable.hpp +++ b/apps/opencs/model/world/idtable.hpp @@ -7,20 +7,10 @@ #include "universalid.hpp" #include "columns.hpp" -/*! \brief - * Clas for holding the model. Uses typical qt table abstraction/interface for granting access to the individiual fields of the records, - * Some records are holding nested data (for instance inventory list of the npc). In casses like this, table model offers interface - * to access nested data in the qt way – that is specify parent. Since some of those nested data require multiple columns to - * represent informations, single int (default way to index model in the qmodelindex) is not sufficiant. Therefore tablemodelindex class - * can hold two ints for the sake of indexing two dimensions of the table. This model does not support multiple levels of the nested - * data. Vast majority of methods makes sense only for the top level data. - */ - namespace CSMWorld { class CollectionBase; struct RecordBase; - class NestedTableWrapperBase; class IdTable : public IdTableBase { @@ -33,8 +23,6 @@ namespace CSMWorld // not implemented IdTable (const IdTable&); IdTable& operator= (const IdTable&); - unsigned int foldIndexAdress(const QModelIndex& index) const; - std::pair unfoldIndexAdress(unsigned int id) const; public: @@ -51,27 +39,17 @@ 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); virtual Qt::ItemFlags flags (const QModelIndex & index) const; virtual bool removeRows (int row, int count, const QModelIndex& parent = QModelIndex()); - void addNestedRow (const QModelIndex& parent, int position); - virtual QModelIndex index (int row, int column, const QModelIndex& parent = QModelIndex()) const; virtual QModelIndex parent (const QModelIndex& index) const; - virtual bool hasChildren (const QModelIndex& index) const; - void addRecord (const std::string& id, UniversalId::Type type = UniversalId::Type_None); ///< \param type Will be ignored, unless the collection supports multiple record types @@ -105,11 +83,6 @@ namespace CSMWorld virtual bool isDeleted (const std::string& id) const; int getColumnId(int column) const; - - signals: - void resetStart(const QString& id); - - void resetEnd(const QString& id); }; } diff --git a/apps/opencs/model/world/idtree.cpp b/apps/opencs/model/world/idtree.cpp new file mode 100644 index 0000000000..595b0ac51e --- /dev/null +++ b/apps/opencs/model/world/idtree.cpp @@ -0,0 +1,296 @@ +#include "idtree.hpp" + +#include "nestedtablewrapper.hpp" // FIXME: is this necessary? + +#include "nestedcollection.hpp" +#include "nestablecolumn.hpp" + +CSMWorld::IdTree::IdTree (NestedCollection *idCollection, unsigned int features) +: IdTable (idCollection, features), mIdCollection (idCollection) +{} + +CSMWorld::IdTree::~IdTree() +{ + // FIXME: workaround only, a proper fix should stop QHideEvent calls after destruction + mIdCollection = 0; +} + +int CSMWorld::IdTree::rowCount (const QModelIndex & parent) const +{ + if (hasChildren(parent)) + return mIdCollection->getNestedRowsCount(parent.row(), parent.column()); + + return mIdCollection->getSize(); +} + +int CSMWorld::IdTree::columnCount (const QModelIndex & parent) const +{ + if (hasChildren(parent)) + return mIdCollection->getNestedColumnsCount(parent.row(), parent.column()); + + return mIdCollection->getColumns(); +} + +QVariant CSMWorld::IdTree::data (const QModelIndex & index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + if ((role!=Qt::DisplayRole && role!=Qt::EditRole) || index.row() < 0 || index.column() < 0) + return QVariant(); + + if (role==Qt::EditRole && !mIdCollection->getColumn (index.column()).isEditable()) + return QVariant(); + + if (index.internalId() != 0) + { + std::pair parentAdress(unfoldIndexAdress(index.internalId())); + + return mIdCollection->getNestedData(parentAdress.first, + parentAdress.second, index.row(), index.column()); + } + else + return mIdCollection->getData (index.row(), index.column()); +} + +QVariant CSMWorld::IdTree::headerData (int section, Qt::Orientation orientation, int role) const +{ + if (orientation==Qt::Vertical) + return QVariant(); + + if (orientation != Qt::Horizontal) + throw std::logic_error("Unknown header orientation specified"); + + if (role == Qt::DisplayRole) + return tr (mIdCollection->getColumn (section).getTitle().c_str()); + + if (role == ColumnBase::Role_Flags) + return mIdCollection->getColumn (section).mFlags; + + if (role == ColumnBase::Role_Display) + return mIdCollection->getColumn (section).mDisplayType; + + return QVariant(); +} + +QVariant CSMWorld::IdTree::nestedHeaderData(int section, int subSection, Qt::Orientation orientation, int role) const +{ + // FIXME: workaround only, a proper fix should stop QHideEvent calls after destruction + if (section < 0 || !mIdCollection || section >= mIdCollection->getColumns()) + return QVariant(); + + // FIXME: dynamic cast + const NestableColumn& parentColumn = dynamic_cast(mIdCollection->getColumn(section)); + + if (orientation==Qt::Vertical) + return QVariant(); + + if (role==Qt::DisplayRole) + return tr(parentColumn.nestedColumn(subSection).getTitle().c_str()); + + if (role==ColumnBase::Role_Flags) + return mIdCollection->getColumn (section).mFlags; + + if (role==ColumnBase::Role_Display) + return parentColumn.nestedColumn(subSection).mDisplayType; + + return QVariant(); +} + +bool CSMWorld::IdTree::setData (const QModelIndex &index, const QVariant &value, int role) +{ + if (index.internalId() != 0) + { + if (mIdCollection->getColumn(parent(index).column()).isEditable() && role==Qt::EditRole) + { + const std::pair& parentAdress(unfoldIndexAdress(index.internalId())); + + mIdCollection->setNestedData(parentAdress.first, parentAdress.second, value, index.row(), index.column()); + + emit dataChanged (CSMWorld::IdTree::index (parentAdress.first, 0), + CSMWorld::IdTree::index (parentAdress.second, mIdCollection->getColumns()-1)); + + return true; + } + else + return false; + } + + if (mIdCollection->getColumn (index.column()).isEditable() && role==Qt::EditRole) + { + mIdCollection->setData (index.row(), index.column(), value); + + emit dataChanged (CSMWorld::IdTree::index (index.row(), 0), + CSMWorld::IdTree::index (index.row(), mIdCollection->getColumns()-1)); + + return true; + } + + return false; +} + +Qt::ItemFlags CSMWorld::IdTree::flags (const QModelIndex & index) const +{ + if (!index.isValid()) + return 0; + + Qt::ItemFlags flags = Qt::ItemIsSelectable | Qt::ItemIsEnabled; + + if (mIdCollection->getColumn (index.column()).isUserEditable()) + flags |= Qt::ItemIsEditable; + + return flags; +} + +bool CSMWorld::IdTree::removeRows (int row, int count, const QModelIndex& parent) +{ + beginRemoveRows (parent, row, row+count-1); + + if (parent.isValid()) + { + for (int i = 0; i < count; ++i) + { + mIdCollection->removeNestedRows(parent.row(), parent.column(), row+i); + } + } + else + { + + beginRemoveRows (parent, row, row+count-1); + + mIdCollection->removeRows (row, count); + } + + endRemoveRows(); + + emit dataChanged (CSMWorld::IdTree::index (parent.row(), 0), + CSMWorld::IdTree::index (parent.row(), mIdCollection->getColumns()-1)); + + return true; +} + +void CSMWorld::IdTree::addNestedRow(const QModelIndex& parent, int position) +{ + if (!hasChildren(parent)) + throw std::logic_error("Tried to set nested table, but index has no children"); + + int row = parent.row(); + + beginInsertRows(parent, position, position); + mIdCollection->addNestedRow(row, parent.column(), position); + endInsertRows(); + + emit dataChanged (CSMWorld::IdTree::index (row, 0), + CSMWorld::IdTree::index (row, mIdCollection->getColumns()-1)); +} + +QModelIndex CSMWorld::IdTree::index (int row, int column, const QModelIndex& parent) const +{ + unsigned int encodedId = 0; + if (parent.isValid()) + { + encodedId = this->foldIndexAdress(parent); + } + + if (row<0 || row>=mIdCollection->getSize()) + return QModelIndex(); + + if (column<0 || column>=mIdCollection->getColumns()) + return QModelIndex(); + + return createIndex(row, column, encodedId); // store internal id +} + +QModelIndex CSMWorld::IdTree::parent (const QModelIndex& index) const +{ + if (index.internalId() == 0) // 0 is used for indexs with invalid parent (top level data) + return QModelIndex(); + + unsigned int id = index.internalId(); + const std::pair& adress(unfoldIndexAdress(id)); + + if (adress.first >= this->rowCount() || adress.second >= this->columnCount()) + throw "Parent index is not present in the model"; + + return createIndex(adress.first, adress.second); +} + +void CSMWorld::IdTree::setRecord (const std::string& id, const RecordBase& record) +{ + int index = mIdCollection->searchId (id); + + if (index==-1) + { + int index = mIdCollection->getAppendIndex (id); + + beginInsertRows (QModelIndex(), index, index); + + mIdCollection->appendRecord (record); + + endInsertRows(); + } + else + { + mIdCollection->replace (index, record); + emit dataChanged (CSMWorld::IdTree::index (index, 0), + CSMWorld::IdTree::index (index, mIdCollection->getColumns()-1)); + } +} + +unsigned int CSMWorld::IdTree::foldIndexAdress (const QModelIndex& index) const +{ + unsigned int out = index.row() * this->columnCount(); + out += index.column(); + return ++out; +} + +std::pair< int, int > CSMWorld::IdTree::unfoldIndexAdress (unsigned int id) const +{ + if (id == 0) + throw "Attempt to unfold index id of the top level data cell"; + + --id; + int row = id / this->columnCount(); + int column = id - row * this->columnCount(); + return std::make_pair (row, column); +} + +bool CSMWorld::IdTree::hasChildren(const QModelIndex& index) const +{ + // FIXME: dynamic cast + return (index.isValid() && + index.internalId() == 0 && + dynamic_cast(mIdCollection->getColumn(index.column())).hasChildren() && + index.data().isValid()); +} + +void CSMWorld::IdTree::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"); + + bool removeRowsMode = false; + if (nestedTable.size() != this->nestedTable(index)->size()) + { + emit resetStart(this->index(index.row(), 0).data().toString()); + removeRowsMode = true; + } + + mIdCollection->setNestedTable(index.row(), index.column(), nestedTable); + + emit dataChanged (CSMWorld::IdTree::index (index.row(), 0), + CSMWorld::IdTree::index (index.row(), mIdCollection->getColumns()-1)); + + if (removeRowsMode) + { + emit resetEnd(this->index(index.row(), 0).data().toString()); + } +} + +CSMWorld::NestedTableWrapperBase* CSMWorld::IdTree::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/idtree.hpp b/apps/opencs/model/world/idtree.hpp new file mode 100644 index 0000000000..6a3d7423ca --- /dev/null +++ b/apps/opencs/model/world/idtree.hpp @@ -0,0 +1,88 @@ +#ifndef CSM_WOLRD_IDTREE_H +#define CSM_WOLRD_IDTREE_H + +#include "idtable.hpp" +#include "universalid.hpp" +#include "columns.hpp" + +/*! \brief + * Class for holding the model. Uses typical qt table abstraction/interface for granting access + * to the individiual fields of the records, Some records are holding nested data (for instance + * inventory list of the npc). In casses like this, table model offers interface to access + * nested data in the qt way - that is specify parent. Since some of those nested data require + * multiple columns to represent informations, single int (default way to index model in the + * qmodelindex) is not sufficiant. Therefore tablemodelindex class can hold two ints for the + * sake of indexing two dimensions of the table. This model does not support multiple levels of + * the nested data. Vast majority of methods makes sense only for the top level data. + */ + +namespace CSMWorld +{ + class NestedCollection; + struct RecordBase; + class NestedTableWrapperBase; // FIXME: is this necessary? + + class IdTree : public IdTable // IdTable is derived from QAbstractItemModel + { + Q_OBJECT + + private: + + NestedCollection *mIdCollection; + + // not implemented + IdTree (const IdTree&); + IdTree& operator= (const IdTree&); + + unsigned int foldIndexAdress(const QModelIndex& index) const; + std::pair unfoldIndexAdress(unsigned int id) const; + + public: + + IdTree (NestedCollection *idCollection, unsigned int features = 0); + ///< The ownership of \a idCollection is not transferred. + + virtual ~IdTree(); + + virtual int rowCount (const QModelIndex & parent = QModelIndex()) const; + + virtual int columnCount (const QModelIndex & parent = QModelIndex()) const; + + virtual QVariant data (const QModelIndex & index, int role = Qt::DisplayRole) const; + + virtual QVariant headerData (int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + + virtual bool setData ( const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); + + virtual Qt::ItemFlags flags (const QModelIndex & index) const; + + virtual bool removeRows (int row, int count, const QModelIndex& parent = QModelIndex()); + + virtual QModelIndex index (int row, int column, const QModelIndex& parent = QModelIndex()) + const; + + virtual QModelIndex parent (const QModelIndex& index) const; + + void setRecord (const std::string& id, const RecordBase& record); + ///< Add record or overwrite existing recrod. + + // TODO: check if below methods are really needed + 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); + + void addNestedRow (const QModelIndex& parent, int position); + + virtual bool hasChildren (const QModelIndex& index) const; + + signals: + + void resetStart(const QString& id); + + void resetEnd(const QString& id); + }; +} + +#endif diff --git a/apps/opencs/model/world/nestablecolumn.cpp b/apps/opencs/model/world/nestablecolumn.cpp new file mode 100644 index 0000000000..4ade75b336 --- /dev/null +++ b/apps/opencs/model/world/nestablecolumn.cpp @@ -0,0 +1,44 @@ +#include "nestablecolumn.hpp" + +#include + +void CSMWorld::NestableColumn::addColumn(CSMWorld::NestableColumn *column) +{ + mNestedColumns.push_back(column); + mHasChildren = true; +} + +const CSMWorld::ColumnBase& CSMWorld::NestableColumn::nestedColumn(int subColumn) const +{ + if (!mHasChildren) + throw std::logic_error("Tried to access nested column of the non-nest column"); + + return *mNestedColumns.at(subColumn); +} + +int CSMWorld::NestableColumn::nestedColumnCount() const +{ + if (!mHasChildren) + throw std::logic_error("Tried to access number of the subcolumns in the non-nest column"); + + return mNestedColumns.size(); +} + +CSMWorld::NestableColumn::NestableColumn(int columnId, CSMWorld::ColumnBase::Display displayType, + int flag, const CSMWorld::NestableColumn* parent) + : mParent(parent), mHasChildren(false), CSMWorld::ColumnBase(columnId, displayType, flag) +{ +} + +CSMWorld::NestableColumn::~NestableColumn() +{ + for (unsigned int i = 0; i < mNestedColumns.size(); ++i) + { + delete mNestedColumns[i]; + } +} + +bool CSMWorld::NestableColumn::hasChildren() const +{ + return mHasChildren; +} diff --git a/apps/opencs/model/world/nestablecolumn.hpp b/apps/opencs/model/world/nestablecolumn.hpp new file mode 100644 index 0000000000..28ced85e99 --- /dev/null +++ b/apps/opencs/model/world/nestablecolumn.hpp @@ -0,0 +1,33 @@ +#ifndef CSM_WOLRD_NESTABLECOLUMN_H +#define CSM_WOLRD_NESTABLECOLUMN_H + +#include + +#include "columnbase.hpp" + +namespace CSMWorld +{ + class NestableColumn : public ColumnBase + { + std::vector mNestedColumns; + const NestableColumn* mParent; + bool mHasChildren; // cached + + public: + + NestableColumn(int columnId, + Display displayType, int flag, const NestableColumn* parent = 0); + + ~NestableColumn(); + + void addColumn(CSMWorld::NestableColumn *column); + + const ColumnBase& nestedColumn(int subColumn) const; + + int nestedColumnCount() const; + + bool hasChildren() const; + }; +} + +#endif diff --git a/apps/opencs/model/world/nestedcollection.hpp b/apps/opencs/model/world/nestedcollection.hpp index dffa295733..5ec50b4238 100644 --- a/apps/opencs/model/world/nestedcollection.hpp +++ b/apps/opencs/model/world/nestedcollection.hpp @@ -1,6 +1,8 @@ #ifndef CSM_WOLRD_NESTEDCOLLECTION_H #define CSM_WOLRD_NESTEDCOLLECTION_H +#include + #include "collectionbase.hpp" class QVariant; @@ -11,7 +13,12 @@ namespace CSMWorld class NestedCollection : public CollectionBase { + public: + + NestedCollection(); + virtual ~NestedCollection(); + virtual void addNestedRow(int row, int col, int position) = 0; virtual QVariant getNestedData(int row, int column, int subRow, int subColumn) const = 0; @@ -28,7 +35,10 @@ namespace CSMWorld virtual void removeNestedRows(int row, int column, int subRow) = 0; + private: + std::vector mChildren; + NestedCollection *mParent; // currently unused }; } diff --git a/apps/opencs/model/world/nestedtableproxymodel.cpp b/apps/opencs/model/world/nestedtableproxymodel.cpp index c098e03166..fede8383bc 100644 --- a/apps/opencs/model/world/nestedtableproxymodel.cpp +++ b/apps/opencs/model/world/nestedtableproxymodel.cpp @@ -1,11 +1,11 @@ #include "nestedtableproxymodel.hpp" #include -#include "idtable.hpp" +#include "idtree.hpp" CSMWorld::NestedTableProxyModel::NestedTableProxyModel(const QModelIndex& parent, ColumnBase::Display columnId, - CSMWorld::IdTable* parentModel) + CSMWorld::IdTree* parentModel) : mParentColumn(parent.column()), mMainModel(parentModel) { @@ -119,7 +119,7 @@ int CSMWorld::NestedTableProxyModel::getParentColumn() const return mParentColumn; } -CSMWorld::IdTable* CSMWorld::NestedTableProxyModel::model() const +CSMWorld::IdTree* CSMWorld::NestedTableProxyModel::model() const { return mMainModel; } diff --git a/apps/opencs/model/world/nestedtableproxymodel.hpp b/apps/opencs/model/world/nestedtableproxymodel.hpp index 7ad8fc0c23..7dc66989c7 100644 --- a/apps/opencs/model/world/nestedtableproxymodel.hpp +++ b/apps/opencs/model/world/nestedtableproxymodel.hpp @@ -17,27 +17,27 @@ namespace CSMWorld { class CollectionBase; class RecordBase; - class IdTable; + class IdTree; class NestedTableProxyModel : public QAbstractProxyModel { Q_OBJECT const int mParentColumn; - IdTable* mMainModel; + IdTree* mMainModel; std::string mId; public: NestedTableProxyModel(const QModelIndex& parent, ColumnBase::Display displayType, - IdTable* parentModel); + IdTree* parentModel); //parent is the parent of columns to work with. Columnid provides information about the column std::string getParentId() const; int getParentColumn() const; - CSMWorld::IdTable* model() const; + CSMWorld::IdTree* model() const; virtual QModelIndex mapFromSource(const QModelIndex& sourceIndex) const; diff --git a/apps/opencs/model/world/refidcollection.cpp b/apps/opencs/model/world/refidcollection.cpp index c488964358..ca5efcdd92 100644 --- a/apps/opencs/model/world/refidcollection.cpp +++ b/apps/opencs/model/world/refidcollection.cpp @@ -2,18 +2,17 @@ #include #include -#include #include #include "refidadapter.hpp" #include "refidadapterimp.hpp" #include "columns.hpp" -#include "nestedtablewrapper.hpp" +#include "nestedtablewrapper.hpp" // FIXME: is this really necessary? CSMWorld::RefIdColumn::RefIdColumn (int columnId, Display displayType, int flag, - bool editable, bool userEditable, bool canNest) - : NestColumn (columnId, displayType, flag, canNest), mEditable (editable), mUserEditable (userEditable) + bool editable, bool userEditable) + : NestableColumn (columnId, displayType, flag), mEditable (editable), mUserEditable (userEditable) {} bool CSMWorld::RefIdColumn::isEditable() const @@ -27,7 +26,8 @@ bool CSMWorld::RefIdColumn::isUserEditable() const } -CSMWorld::RefIdAdapter& CSMWorld::RefIdCollection::findAdapter (UniversalId::Type type) const +// FIXME: const problem +/*const*/ CSMWorld::RefIdAdapter& CSMWorld::RefIdCollection::findAdapter (UniversalId::Type type) const { std::map::const_iterator iter = mAdapters.find (type); @@ -99,14 +99,19 @@ CSMWorld::RefIdCollection::RefIdCollection() mColumns.push_back (RefIdColumn (Columns::ColumnId_AiAlarm, ColumnBase::Display_Integer)); actorsColumns.mAlarm = &mColumns.back(); - mColumns.push_back(RefIdColumn (Columns::ColumnId_ActorInventory, ColumnBase::Display_NestedItemList, ColumnBase::Flag_Dialogue, true, true, true)); + // Nested table + mColumns.push_back(RefIdColumn (Columns::ColumnId_ActorInventory, ColumnBase::Display_NestedItemList, ColumnBase::Flag_Dialogue)); actorsColumns.mInventory = &mColumns.back(); - mColumns.back().addNestedColumn(Columns::ColumnId_InventoryItemId, CSMWorld::ColumnBase::Display_String); - mColumns.back().addNestedColumn(Columns::ColumnId_ItemCount, CSMWorld::ColumnBase::Display_Integer); + mColumns.back().addColumn( + new RefIdColumn (Columns::ColumnId_InventoryItemId, CSMWorld::ColumnBase::Display_String)); + mColumns.back().addColumn( + new RefIdColumn (Columns::ColumnId_ItemCount, CSMWorld::ColumnBase::Display_Integer)); - mColumns.push_back(RefIdColumn (Columns::ColumnId_ActorSpells, ColumnBase::Display_NestedSpellList, ColumnBase::Flag_Dialogue, true, true, true)); + // Nested table + mColumns.push_back(RefIdColumn (Columns::ColumnId_ActorSpells, ColumnBase::Display_NestedSpellList, ColumnBase::Flag_Dialogue)); actorsColumns.mSpells = &mColumns.back(); - mColumns.back().addNestedColumn(Columns::ColumnId_SpellId, CSMWorld::ColumnBase::Display_String); + mColumns.back().addColumn( + new RefIdColumn (Columns::ColumnId_SpellId, CSMWorld::ColumnBase::Display_String)); static const struct { @@ -175,10 +180,13 @@ CSMWorld::RefIdCollection::RefIdCollection() mColumns.push_back (RefIdColumn (Columns::ColumnId_Respawn, ColumnBase::Display_Boolean)); const RefIdColumn *respawn = &mColumns.back(); - mColumns.push_back(RefIdColumn (Columns::ColumnId_ContainerContent, ColumnBase::Display_NestedItemList, ColumnBase::Flag_Dialogue, true, true, true)); + // Nested table + mColumns.push_back(RefIdColumn (Columns::ColumnId_ContainerContent, ColumnBase::Display_NestedItemList, ColumnBase::Flag_Dialogue)); const RefIdColumn *content = &mColumns.back(); - mColumns.back().addNestedColumn(Columns::ColumnId_InventoryItemId, CSMWorld::ColumnBase::Display_String); - mColumns.back().addNestedColumn(Columns::ColumnId_ItemCount, CSMWorld::ColumnBase::Display_Integer); + mColumns.back().addColumn( + new RefIdColumn (Columns::ColumnId_InventoryItemId, CSMWorld::ColumnBase::Display_String)); + mColumns.back().addColumn( + new RefIdColumn (Columns::ColumnId_ItemCount, CSMWorld::ColumnBase::Display_Integer)); CreatureColumns creatureColumns (actorsColumns); @@ -315,16 +323,24 @@ CSMWorld::RefIdCollection::RefIdCollection() npcColumns.mFlags.insert (std::make_pair (metalBlood, ESM::NPC::Metal)); - mColumns.push_back(RefIdColumn (Columns::ColumnId_NpcDestinations, ColumnBase::Display_NestedDestinationsList, ColumnBase::Flag_Dialogue, true, true, true)); + // Nested table + mColumns.push_back(RefIdColumn (Columns::ColumnId_NpcDestinations, ColumnBase::Display_NestedDestinationsList, ColumnBase::Flag_Dialogue)); npcColumns.mDestinations = &mColumns.back(); - mColumns.back().addNestedColumn(Columns::ColumnId_DestinationCell, CSMWorld::ColumnBase::Display_String); - mColumns.back().addNestedColumn(Columns::ColumnId_PosX, CSMWorld::ColumnBase::Display_Float); - mColumns.back().addNestedColumn(Columns::ColumnId_PosY, CSMWorld::ColumnBase::Display_Float); - mColumns.back().addNestedColumn(Columns::ColumnId_PosZ, CSMWorld::ColumnBase::Display_Float); - mColumns.back().addNestedColumn(Columns::ColumnId_RotX, CSMWorld::ColumnBase::Display_Float); - mColumns.back().addNestedColumn(Columns::ColumnId_RotY, CSMWorld::ColumnBase::Display_Float); - mColumns.back().addNestedColumn(Columns::ColumnId_RotZ, CSMWorld::ColumnBase::Display_Float); - + 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)); @@ -664,8 +680,10 @@ void CSMWorld::RefIdCollection::setNestedTable(int row, int column, const CSMWor { RefIdData::LocalIndex localIndex = mData.globalToLocalIndex (row); + // FIXME: const problem CSMWorld::NestedRefIdAdapter& adaptor = dynamic_cast(findAdapter (localIndex.second)); + // FIXME: const problem adaptor.setNestedTable(&mColumns.at(column), mData, localIndex.first, nestedTable); } diff --git a/apps/opencs/model/world/refidcollection.hpp b/apps/opencs/model/world/refidcollection.hpp index ab25c93fa3..dd432c5a96 100644 --- a/apps/opencs/model/world/refidcollection.hpp +++ b/apps/opencs/model/world/refidcollection.hpp @@ -5,8 +5,7 @@ #include #include -#include "columnbase.hpp" -#include "collectionbase.hpp" +#include "nestablecolumn.hpp" #include "nestedcollection.hpp" #include "refiddata.hpp" @@ -18,9 +17,9 @@ namespace ESM namespace CSMWorld { class RefIdAdapter; - class NestedTableWrapperBase; + class NestedTableWrapperBase; // FIXME: is this really needed? - class RefIdColumn : public NestColumn + class RefIdColumn : public NestableColumn { bool mEditable; bool mUserEditable; @@ -29,7 +28,7 @@ namespace CSMWorld RefIdColumn (int columnId, Display displayType, int flag = Flag_Table | Flag_Dialogue, bool editable = true, - bool userEditable = true, bool canNest = false); + bool userEditable = true); virtual bool isEditable() const; @@ -46,7 +45,7 @@ namespace CSMWorld private: - RefIdAdapter& findAdapter (UniversalId::Type) const; + /*const*/ RefIdAdapter& findAdapter (UniversalId::Type) const; ///< Throws an exception if no adaptor for \a Type can be found. public: @@ -57,10 +56,6 @@ namespace CSMWorld virtual int getSize() const; - virtual int getNestedRowsCount(int row, int column) const; - - virtual int getNestedColumnsCount(int row, int column) const; - virtual std::string getId (int index) const; virtual int getIndex (const std::string& id) const; @@ -71,22 +66,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); - virtual void setNestedData(int row, int column, const QVariant& data, int subRow, int subColumn); - virtual void removeRows (int index, int count); - virtual void removeNestedRows(int row, int column, int subRow); - - virtual void addNestedRow(int row, int col, int position); - virtual void cloneRecord(const std::string& origin, const std::string& destination, const UniversalId::Type type); @@ -128,6 +111,24 @@ namespace CSMWorld /// /// \return Success? + 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); + + // FIXME + virtual int getNestedRowsCount(int row, int column) const; + + // FIXME + virtual int getNestedColumnsCount(int row, int column) const; + + virtual void setNestedData(int row, int column, const QVariant& data, int subRow, int subColumn); + + virtual void removeNestedRows(int row, int column, int subRow); + + virtual void addNestedRow(int row, int col, int position); + void save (int index, ESM::ESMWriter& writer) const; const RefIdData& getDataSet() const; //I can't figure out a better name for this one :( diff --git a/apps/opencs/model/world/refiddata.hpp b/apps/opencs/model/world/refiddata.hpp index bfdd4f9eec..eaa7b115d3 100644 --- a/apps/opencs/model/world/refiddata.hpp +++ b/apps/opencs/model/world/refiddata.hpp @@ -52,7 +52,7 @@ namespace CSMWorld virtual void load (int index, ESM::ESMReader& reader, bool base) = 0; virtual void erase (int index, int count) = 0; - + virtual std::string getId (int index) const = 0; virtual void save (int index, ESM::ESMWriter& writer) const = 0; @@ -134,7 +134,7 @@ namespace CSMWorld throw std::runtime_error ("invalid RefIdDataContainer index"); mContainer.erase (mContainer.begin()+index, mContainer.begin()+index+count); - } + } template std::string RefIdDataContainer::getId (int index) const @@ -231,7 +231,7 @@ namespace CSMWorld void save (int index, ESM::ESMWriter& writer) const; - //RECORD CONTAINERS ACCESS METHODS + //RECORD CONTAINERS ACCESS METHODS const RefIdDataContainer& getBooks() const; const RefIdDataContainer& getActivators() const; const RefIdDataContainer& getPotions() const; diff --git a/apps/opencs/view/world/dialoguesubview.cpp b/apps/opencs/view/world/dialoguesubview.cpp index e26dcdc9ba..0aa83eb921 100644 --- a/apps/opencs/view/world/dialoguesubview.cpp +++ b/apps/opencs/view/world/dialoguesubview.cpp @@ -26,6 +26,7 @@ #include "../../model/world/nestedtableproxymodel.hpp" #include "../../model/world/columnbase.hpp" #include "../../model/world/idtable.hpp" +#include "../../model/world/idtree.hpp" #include "../../model/world/columns.hpp" #include "../../model/world/record.hpp" #include "../../model/world/tablemimedata.hpp" @@ -422,7 +423,7 @@ void CSVWorld::EditWidget::remake(int row) if (mTable->hasChildren(mTable->index(row, i))) { - mNestedModels.push_back(new CSMWorld::NestedTableProxyModel (mTable->index(row, i), display, mTable)); + mNestedModels.push_back(new CSMWorld::NestedTableProxyModel (mTable->index(row, i), display, dynamic_cast(mTable))); NestedTable* table = new NestedTable(mDocument, mNestedModels.back(), this);