From 21a1f6f4aef555775cdd66e4b4d7483d95f9b8cb Mon Sep 17 00:00:00 2001 From: Marek Kochanowicz Date: Mon, 9 Jun 2014 10:35:39 +0200 Subject: [PATCH] working on the issue --- apps/opencs/model/world/collection.hpp | 20 ++++- apps/opencs/model/world/collectionbase.cpp | 19 +++- apps/opencs/model/world/collectionbase.hpp | 8 +- apps/opencs/model/world/idtable.cpp | 89 +++++++++++++++++-- apps/opencs/model/world/idtable.hpp | 22 +++++ apps/opencs/model/world/refidadapter.cpp | 10 ++- apps/opencs/model/world/refidadapter.hpp | 22 ++++- apps/opencs/model/world/refidadapterimp.cpp | 98 ++++++++++++++++++++- apps/opencs/model/world/refidadapterimp.hpp | 25 +++++- apps/opencs/model/world/refidcollection.cpp | 41 +++++++++ apps/opencs/model/world/refidcollection.hpp | 6 ++ 11 files changed, 342 insertions(+), 18 deletions(-) diff --git a/apps/opencs/model/world/collection.hpp b/apps/opencs/model/world/collection.hpp index 1fb3e1f1db..3f110b4dd7 100644 --- a/apps/opencs/model/world/collection.hpp +++ b/apps/opencs/model/world/collection.hpp @@ -73,6 +73,10 @@ namespace CSMWorld ///< Add a new record (modified) virtual int getSize() const; + + virtual int getNestedColumnsCount(int column) const; + + virtual int getNestedRowsCount(int row, int column) const; virtual std::string getId (int index) const; @@ -92,7 +96,7 @@ namespace CSMWorld virtual void purge(); ///< Remove records that are flagged as erased. - virtual void removeRows (int index, int count) ; + virtual void removeRows (int index, int count); virtual void appendBlankRecord (const std::string& id, UniversalId::Type type = UniversalId::Type_None); @@ -247,6 +251,20 @@ namespace CSMWorld { return mRecords.size(); } + + template + int Collection::getNestedRowsCount(int row, int column) const + { + //TODO + return 0; + } + + template + int Collection::getNestedColumnsCount(int column) const + { + //TODO + return 0; + } template std::string Collection::getId (int index) const diff --git a/apps/opencs/model/world/collectionbase.cpp b/apps/opencs/model/world/collectionbase.cpp index 241f198cb2..eed157a7ba 100644 --- a/apps/opencs/model/world/collectionbase.cpp +++ b/apps/opencs/model/world/collectionbase.cpp @@ -28,4 +28,21 @@ int CSMWorld::CollectionBase::findColumnIndex (Columns::ColumnId id) const throw std::logic_error ("invalid column index"); return index; -} \ No newline at end of file +} + +void CSMWorld::CollectionBase::setNestedData(int row, int column, const QVariant& data, int subRow, int subColumn) +{ + assert(false); //TODO remove and make pure abstract +} + +int CSMWorld::CollectionBase::getNestedColumnsCount(int row, int column) const +{ + assert(false); //TODO remove and make pure abstract + return 0; +} + +int CSMWorld::CollectionBase::getNestedRowsCount(int row, int column) const +{ + assert(false); //TODO, make pure abstract + return 0; +} diff --git a/apps/opencs/model/world/collectionbase.hpp b/apps/opencs/model/world/collectionbase.hpp index 442055d5f3..4c3afc0925 100644 --- a/apps/opencs/model/world/collectionbase.hpp +++ b/apps/opencs/model/world/collectionbase.hpp @@ -33,6 +33,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 std::string getId (int index) const = 0; @@ -46,6 +50,8 @@ namespace CSMWorld 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); + // Not in use. Temporarily removed so that the implementation of RefIdCollection can continue without // these functions for now. // virtual void merge() = 0; @@ -106,4 +112,4 @@ namespace CSMWorld }; } -#endif \ No newline at end of file +#endif diff --git a/apps/opencs/model/world/idtable.cpp b/apps/opencs/model/world/idtable.cpp index 50998c36f1..59fc3a5081 100644 --- a/apps/opencs/model/world/idtable.cpp +++ b/apps/opencs/model/world/idtable.cpp @@ -1,6 +1,8 @@ #include "idtable.hpp" +#include + #include "collectionbase.hpp" #include "columnbase.hpp" @@ -14,16 +16,21 @@ CSMWorld::IdTable::~IdTable() int CSMWorld::IdTable::rowCount (const QModelIndex & parent) const { - if (parent.isValid()) - return 0; - + if (hasChildren(parent)) + { + int nestedRows = mIdCollection->getNestedRowsCount(parent.row(), parent.column()); + return nestedRows; + } + return mIdCollection->getSize(); } int CSMWorld::IdTable::columnCount (const QModelIndex & parent) const { if (parent.isValid()) - return 0; + { + return mIdCollection->getNestedColumnsCount(parent.row(), parent.column()); + } return mIdCollection->getColumns(); } @@ -36,7 +43,17 @@ QVariant CSMWorld::IdTable::data (const QModelIndex & index, int role) const if (role==Qt::EditRole && !mIdCollection->getColumn (index.column()).isEditable()) return QVariant(); +<<<<<<< Updated upstream return mIdCollection->getData (index.row(), index.column()); +======= + 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()); + } +>>>>>>> Stashed changes } QVariant CSMWorld::IdTable::headerData (int section, Qt::Orientation orientation, int role) const @@ -60,11 +77,18 @@ bool CSMWorld::IdTable::setData ( const QModelIndex &index, const QVariant &valu { if (mIdCollection->getColumn (index.column()).isEditable() && role==Qt::EditRole) { - mIdCollection->setData (index.row(), index.column(), value); + if (index.internalId() == 0) + { + mIdCollection->setData (index.row(), index.column(), value); - emit dataChanged (CSMWorld::IdTable::index (index.row(), 0), - CSMWorld::IdTable::index (index.row(), mIdCollection->getColumns()-1)); + emit dataChanged (CSMWorld::IdTable::index (index.row(), 0), + CSMWorld::IdTable::index (index.row(), mIdCollection->getColumns()-1)); + } else + { + const std::pair& parentAdress(unfoldIndexAdress(index.internalId())); + mIdCollection->setNestedData(parentAdress.first, parentAdress.second, value, index.row(), index.column()); + } return true; } @@ -111,7 +135,23 @@ QModelIndex CSMWorld::IdTable::index (int row, int column, const QModelIndex& pa QModelIndex CSMWorld::IdTable::parent (const QModelIndex& index) const { +<<<<<<< Updated upstream return QModelIndex(); +======= + if (index.internalId() == 0) //0 is used for indexs with invalid parent (top level data) + { + return QModelIndex(); + } + + const std::pair& adress(unfoldIndexAdress(index.internalId())); + + if (adress.first >= this->rowCount() || adress.second >= this->columnCount()) + { + qDebug()<<"Parent index is not present in the model"; + throw "Parent index is not present in the model"; + } + return createIndex(adress.first, adress.second, 0); +>>>>>>> Stashed changes } void CSMWorld::IdTable::addRecord (const std::string& id, UniversalId::Type type) @@ -240,4 +280,37 @@ std::pair CSMWorld::IdTable::view (int row) int CSMWorld::IdTable::getColumnId(int column) const { return mIdCollection->getColumn(column).getId(); -} \ No newline at end of file +<<<<<<< Updated upstream +} +======= +} + +bool CSMWorld::IdTable::hasChildren(const QModelIndex& index) const +{ + return (index.isValid() && + mIdCollection->getColumn (index.column()).mDisplayType == ColumnBase::Display_Nested && + index.data().isValid()); +} + +unsigned int CSMWorld::IdTable::foldIndexAdress (const QModelIndex& index) const +{ + unsigned int out = index.row() * this->columnCount(); + out += index.column(); + ++out; + return out; +} + +std::pair< int, int > CSMWorld::IdTable::unfoldIndexAdress (unsigned int id) const +{ + if (id == 0) + { + qDebug()<<"Attempt to unfold index id of the top level data cell"; + 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); +} +>>>>>>> Stashed changes diff --git a/apps/opencs/model/world/idtable.hpp b/apps/opencs/model/world/idtable.hpp index 8b54628256..bf9f4a555a 100644 --- a/apps/opencs/model/world/idtable.hpp +++ b/apps/opencs/model/world/idtable.hpp @@ -8,6 +8,19 @@ #include "universalid.hpp" #include "columns.hpp" +<<<<<<< Updated upstream +======= +/*! \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. The parent is encoded in the internalid of the index model + * See methods fold and unfold adress to see why. This approach has some serious limitations: it allows only + * a single level of the nesting. At the point of creating this code this seemed to be a good enough solution. + * If for some reason it turned out that in fact multiple levels of nesting are needed, change in the addressing of the + * index is most likely the very first to be considered. + */ + +>>>>>>> Stashed changes namespace CSMWorld { class CollectionBase; @@ -44,6 +57,13 @@ namespace CSMWorld // not implemented IdTable (const IdTable&); IdTable& operator= (const IdTable&); +<<<<<<< Updated upstream +======= + + unsigned int foldIndexAdress(const QModelIndex& index) const; + + std::pair unfoldIndexAdress(unsigned int id) const; +>>>>>>> Stashed changes public: @@ -71,6 +91,8 @@ namespace CSMWorld 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 diff --git a/apps/opencs/model/world/refidadapter.cpp b/apps/opencs/model/world/refidadapter.cpp index 94ae38c3c2..785e98d5eb 100644 --- a/apps/opencs/model/world/refidadapter.cpp +++ b/apps/opencs/model/world/refidadapter.cpp @@ -3,4 +3,12 @@ CSMWorld::RefIdAdapter::RefIdAdapter() {} -CSMWorld::RefIdAdapter::~RefIdAdapter() {} \ No newline at end of file +<<<<<<< Updated upstream +CSMWorld::RefIdAdapter::~RefIdAdapter() {} +======= +CSMWorld::RefIdAdapter::~RefIdAdapter() {} + +CSMWorld::NestedRefIdAdapter::NestedRefIdAdapter() {} + +CSMWorld::NestedRefIdAdapter::~NestedRefIdAdapter() {} +>>>>>>> Stashed changes diff --git a/apps/opencs/model/world/refidadapter.hpp b/apps/opencs/model/world/refidadapter.hpp index 0870a2d3e6..3a9d02dcae 100644 --- a/apps/opencs/model/world/refidadapter.hpp +++ b/apps/opencs/model/world/refidadapter.hpp @@ -31,8 +31,28 @@ namespace CSMWorld ///< If the data type does not match an exception is thrown. virtual std::string getId (const RecordBase& record) const = 0; + virtual void setId(RecordBase& record, const std::string& id) = 0; }; + + class NestedRefIdAdapter + { + public: + NestedRefIdAdapter(); + + virtual ~NestedRefIdAdapter(); + + virtual void setNestedData (const RefIdColumn *column, RefIdData& data, int row, + const QVariant& value, int subRowIndex, int subColIndex) const = 0; + + virtual QVariant getNestedData (const RefIdColumn *column, const RefIdData& data, + int index, int subRowIndex, int subColIndex) const = 0; + + + virtual int getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const = 0; + + virtual int getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const = 0; + }; } -#endif \ No newline at end of file +#endif diff --git a/apps/opencs/model/world/refidadapterimp.cpp b/apps/opencs/model/world/refidadapterimp.cpp index f00e9fc77b..b67b26cdb7 100644 --- a/apps/opencs/model/world/refidadapterimp.cpp +++ b/apps/opencs/model/world/refidadapterimp.cpp @@ -1,6 +1,8 @@ #include "refidadapterimp.hpp" +#include + CSMWorld::PotionRefIdAdapter::PotionRefIdAdapter (const InventoryColumns& columns, const RefIdColumn *autoCalc) : InventoryRefIdAdapter (UniversalId::Type_Potion, columns), @@ -178,6 +180,32 @@ CSMWorld::ContainerRefIdAdapter::ContainerRefIdAdapter (const NameColumns& colum mOrganic (organic), mRespawn (respawn) {} +int CSMWorld::ContainerRefIdAdapter::getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const +{ + qDebug()<<"getting nested columns count"; + if (column==mContent) + { + return 2; + } else { + throw "Trying to obtain nested columns count, but column does not have nested columns!"; + } +} + +int CSMWorld::ContainerRefIdAdapter::getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const +{ + qDebug()<<"getting nested rows count"; + const Record& record = static_cast&> ( + data.getRecord(RefIdData::LocalIndex (index, UniversalId::Type_Container))); + + qDebug() << "exception above"; + if (column==mContent) + { + qDebug() << record.get().mInventory.mList.size(); + return record.get().mInventory.mList.size(); + } else { + throw "Trying to obtain nested rows count, but column does not have nested columns!"; + } +} QVariant CSMWorld::ContainerRefIdAdapter::getData (const RefIdColumn *column, const RefIdData& data, int index) const { @@ -192,6 +220,9 @@ QVariant CSMWorld::ContainerRefIdAdapter::getData (const RefIdColumn *column, co if (column==mRespawn) return (record.get().mFlags & ESM::Container::Respawn)!=0; + + if (column==mContent) + return true; return NameRefIdAdapter::getData (column, data, index); } @@ -222,6 +253,71 @@ void CSMWorld::ContainerRefIdAdapter::setData (const RefIdColumn *column, RefIdD NameRefIdAdapter::setData (column, data, index, value); } +<<<<<<< Updated upstream +======= +void CSMWorld::ContainerRefIdAdapter::setNestedData(const RefIdColumn *column, RefIdData& data, + int row, + const QVariant& value, + int subRowIndex, + int subColIndex) const +{ + Record& record = static_cast&> ( + data.getRecord (RefIdData::LocalIndex (row, UniversalId::Type_Container))); + + if (column==mContent) + { + switch (subColIndex) + { + case 0: + record.get().mInventory.mList.at(subRowIndex).mItem.assign(std::string(value.toString().toUtf8().constData())); + break; + + case 1: + record.get().mInventory.mList.at(subRowIndex).mCount = value.toInt(); + break; + + default: + throw "Trying to access non-existing column in the nested table!"; + } + } else + { + throw "This column does not hold multiple values."; + } +} + +QVariant CSMWorld::ContainerRefIdAdapter::getNestedData (const CSMWorld::RefIdColumn* column, + const CSMWorld::RefIdData& data, + int index, + int subRowIndex, + int subColIndex) const +{ + qDebug()<<"Accessing content column"; + const Record& record = static_cast&> ( + data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Container))); + + if (column==mContent) + { + const ESM::ContItem& content = record.get().mInventory.mList.at(subRowIndex); + + switch (subColIndex) + { + case 0: + return QString::fromUtf8(content.mItem.toString().c_str()); + + case 1: + return content.mCount; + + default: + throw "Trying to access non-existing column in the nested table!"; + } + } else + { + throw "This column does not hold multiple values."; + } +} + + +>>>>>>> Stashed changes CSMWorld::CreatureColumns::CreatureColumns (const ActorColumns& actorColumns) : ActorColumns (actorColumns) {} @@ -572,4 +668,4 @@ void CSMWorld::WeaponRefIdAdapter::setData (const RefIdColumn *column, RefIdData else EnchantableRefIdAdapter::setData (column, data, index, value); } -} \ No newline at end of file +} diff --git a/apps/opencs/model/world/refidadapterimp.hpp b/apps/opencs/model/world/refidadapterimp.hpp index bd509a86b6..ed6c50fe3f 100644 --- a/apps/opencs/model/world/refidadapterimp.hpp +++ b/apps/opencs/model/world/refidadapterimp.hpp @@ -23,6 +23,7 @@ namespace CSMWorld }; /// \brief Base adapter for all refereceable record types + /// Adapters that can handle nested tables, needs to return valid qvariant for parent columns template class BaseRefIdAdapter : public RefIdAdapter { @@ -605,7 +606,7 @@ namespace CSMWorld ///< If the data type does not match an exception is thrown. }; - class ContainerRefIdAdapter : public NameRefIdAdapter + class ContainerRefIdAdapter : public NameRefIdAdapter, public NestedRefIdAdapter { const RefIdColumn *mWeight; const RefIdColumn *mOrganic; @@ -614,14 +615,30 @@ namespace CSMWorld public: ContainerRefIdAdapter (const NameColumns& columns, const RefIdColumn *weight, +<<<<<<< Updated upstream const RefIdColumn *organic, const RefIdColumn *respawn); +======= + const RefIdColumn *organic, const RefIdColumn *respawn, const RefIdColumn *content); - virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index) - const; + virtual QVariant getNestedData (const RefIdColumn *column, const RefIdData& data, + int index, int subRowIndex, int subColIndex) const; +>>>>>>> Stashed changes + virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index) const; + +<<<<<<< Updated upstream +======= + virtual void setNestedData (const RefIdColumn *column, RefIdData& data, int index, + const QVariant& value, int subRowIndex, int subColIndex) const; + +>>>>>>> Stashed changes virtual void setData (const RefIdColumn *column, RefIdData& data, int index, - const QVariant& value) const; + const QVariant& value) const; ///< If the data type does not match an exception is thrown. + + virtual int getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const; + + virtual int getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const; }; struct CreatureColumns : public ActorColumns diff --git a/apps/opencs/model/world/refidcollection.cpp b/apps/opencs/model/world/refidcollection.cpp index f515e34d8e..c9d6700b5e 100644 --- a/apps/opencs/model/world/refidcollection.cpp +++ b/apps/opencs/model/world/refidcollection.cpp @@ -3,6 +3,7 @@ #include #include +#include #include @@ -416,6 +417,19 @@ QVariant CSMWorld::RefIdCollection::getData (int index, int column) const return adaptor.getData (&mColumns.at (column), mData, localIndex.first); } +<<<<<<< Updated upstream +======= +QVariant CSMWorld::RefIdCollection::getNestedData (int row, int column, int subRow, int subColumn) const +{ + RefIdData::LocalIndex localIndex = mData.globalToLocalIndex(row); + + const CSMWorld::NestedRefIdAdapter& adaptor = dynamic_cast(findAdaptor (localIndex.second)); + + //if this overloaded, base class method was not overriden, crash will happen (assert(false)) Don't try to use this method for non-nested columns! + return adaptor.getNestedData (&mColumns.at (column), mData, localIndex.first, subRow, subColumn); +} + +>>>>>>> Stashed changes void CSMWorld::RefIdCollection::setData (int index, int column, const QVariant& data) { RefIdData::LocalIndex localIndex = mData.globalToLocalIndex (index); @@ -425,6 +439,15 @@ void CSMWorld::RefIdCollection::setData (int index, int column, const QVariant& adaptor.setData (&mColumns.at (column), mData, localIndex.first, data); } +void CSMWorld::RefIdCollection::setNestedData(int row, int column, const QVariant& data, int subRow, int subColumn) +{ + RefIdData::LocalIndex localIndex = mData.globalToLocalIndex (row); + + const RefIdAdapter& adaptor = findAdaptor (localIndex.second); + + dynamic_cast(adaptor).setNestedData (&mColumns.at (column), mData, localIndex.first, data, subRow, subColumn); +} + void CSMWorld::RefIdCollection::removeRows (int index, int count) { mData.erase (index, count); @@ -566,3 +589,21 @@ const CSMWorld::RefIdData& CSMWorld::RefIdCollection::getDataSet() const return mData; } +int CSMWorld::RefIdCollection::getNestedRowsCount(int row, int column) const +{ + RefIdData::LocalIndex localIndex = mData.globalToLocalIndex (row); + + const CSMWorld::NestedRefIdAdapter& adaptor = dynamic_cast(findAdaptor (localIndex.second)); + + const int count = adaptor.getNestedRowsCount(&mColumns.at(column), mData, localIndex.first); + return count; +} + +int CSMWorld::RefIdCollection::getNestedColumnsCount(int row, int column) const +{ + RefIdData::LocalIndex localIndex = mData.globalToLocalIndex (row); + + const CSMWorld::NestedRefIdAdapter& adaptor = dynamic_cast(findAdaptor (localIndex.second)); + + return adaptor.getNestedColumnsCount(&mColumns.at(column), mData); +} diff --git a/apps/opencs/model/world/refidcollection.hpp b/apps/opencs/model/world/refidcollection.hpp index dd6213677e..f4ac556cf3 100644 --- a/apps/opencs/model/world/refidcollection.hpp +++ b/apps/opencs/model/world/refidcollection.hpp @@ -55,6 +55,10 @@ 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; @@ -67,6 +71,8 @@ namespace CSMWorld 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 cloneRecord(const std::string& origin,