1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-02-04 12:39:55 +00:00

changes in the model (idtable) to support nested data

This commit is contained in:
Marek Kochanowicz 2014-06-02 20:41:37 +02:00
parent 6720d85a04
commit 55d451febe
15 changed files with 133 additions and 39 deletions

View File

@ -18,7 +18,7 @@ opencs_hdrs_noqt (model/doc
opencs_units (model/world opencs_units (model/world
idtable idtableproxymodel regionmap data idtable idtableproxymodel regionmap data nestedtablemodel
) )

View File

@ -82,6 +82,8 @@ namespace CSMWorld
virtual QVariant getData (int index, int column) const; virtual QVariant getData (int index, int column) const;
virtual QVariant getNestedData(int row, int column, int subRow, int subColumn) const;
virtual void setData (int index, int column, const QVariant& data); virtual void setData (int index, int column, const QVariant& data);
virtual const ColumnBase& getColumn (int column) const; virtual const ColumnBase& getColumn (int column) const;
@ -277,6 +279,12 @@ namespace CSMWorld
return mColumns.at (column)->get (mRecords.at (index)); return mColumns.at (column)->get (mRecords.at (index));
} }
template<typename ESXRecordT, typename IdAccessorT>
QVariant Collection<ESXRecordT, IdAccessorT>::getNestedData(int row, int column, int subRow, int subColumn) const
{
return 10; //TODO
}
template<typename ESXRecordT, typename IdAccessorT> template<typename ESXRecordT, typename IdAccessorT>
void Collection<ESXRecordT, IdAccessorT>::setData (int index, int column, const QVariant& data) void Collection<ESXRecordT, IdAccessorT>::setData (int index, int column, const QVariant& data)
{ {

View File

@ -2,6 +2,7 @@
#include "collectionbase.hpp" #include "collectionbase.hpp"
#include <stdexcept> #include <stdexcept>
#include <cassert>
#include "columnbase.hpp" #include "columnbase.hpp"

View File

@ -44,6 +44,8 @@ namespace CSMWorld
virtual QVariant getData (int index, int column) const = 0; virtual QVariant getData (int index, int column) const = 0;
virtual QVariant getNestedData(int row, int column, int subRow, int subColumn) const = 0;
virtual void setData (int index, int column, const QVariant& data) = 0; virtual void setData (int index, int column, const QVariant& data) = 0;
// Not in use. Temporarily removed so that the implementation of RefIdCollection can continue without // Not in use. Temporarily removed so that the implementation of RefIdCollection can continue without

View File

@ -89,7 +89,9 @@ namespace CSMWorld
Display_RefRecordType, Display_RefRecordType,
Display_DialogueType, Display_DialogueType,
Display_QuestStatusType, Display_QuestStatusType,
Display_Gender Display_Gender,
Display_Nested
}; };
int mColumnId; int mColumnId;
@ -125,6 +127,12 @@ namespace CSMWorld
throw std::logic_error ("Column " + getTitle() + " is not editable"); throw std::logic_error ("Column " + getTitle() + " is not editable");
} }
}; };
template<typename ESXRecordT>
struct NestedColumn
{
virtual QVariant getNested(const Record<ESXRecordT>& record, int subColumn, int subSow) const = 0;
};
} }
#endif #endif

View File

@ -36,7 +36,13 @@ QVariant CSMWorld::IdTable::data (const QModelIndex & index, int role) const
if (role==Qt::EditRole && !mIdCollection->getColumn (index.column()).isEditable()) if (role==Qt::EditRole && !mIdCollection->getColumn (index.column()).isEditable())
return QVariant(); return QVariant();
return mIdCollection->getData (index.row(), index.column()); if (index.internalId() != 0)
{
std::pair<int, int> parentAdress(unfoldIndexAdress(index.internalId()));
return mIdCollection->getNestedData(index.row(), index.column(), parentAdress.first, parentAdress.second);
} else {
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
@ -97,8 +103,11 @@ bool CSMWorld::IdTable::removeRows (int row, int count, const QModelIndex& paren
QModelIndex CSMWorld::IdTable::index (int row, int column, const QModelIndex& parent) const QModelIndex CSMWorld::IdTable::index (int row, int column, const QModelIndex& parent) const
{ {
unsigned int encodedId = 0;
if (parent.isValid()) if (parent.isValid())
return QModelIndex(); {
encodedId = this->foldIndexAdress(parent);
}
if (row<0 || row>=mIdCollection->getSize()) if (row<0 || row>=mIdCollection->getSize())
return QModelIndex(); return QModelIndex();
@ -106,12 +115,24 @@ QModelIndex CSMWorld::IdTable::index (int row, int column, const QModelIndex& pa
if (column<0 || column>=mIdCollection->getColumns()) if (column<0 || column>=mIdCollection->getColumns())
return QModelIndex(); return QModelIndex();
return createIndex (row, column); return createIndex(row, column, encodedId);
} }
QModelIndex CSMWorld::IdTable::parent (const QModelIndex& index) const QModelIndex CSMWorld::IdTable::parent (const QModelIndex& index) const
{ {
return QModelIndex(); 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<int, int>& 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::IdTable::addRecord (const std::string& id, UniversalId::Type type) void CSMWorld::IdTable::addRecord (const std::string& id, UniversalId::Type type)
@ -136,10 +157,10 @@ void CSMWorld::IdTable::cloneRecord(const std::string& origin,
endInsertRows(); endInsertRows();
} }
///This method can return only indexes to the top level table cells
QModelIndex CSMWorld::IdTable::getModelIndex (const std::string& id, int column) const QModelIndex CSMWorld::IdTable::getModelIndex (const std::string& id, int column) const
{ {
return index (mIdCollection->getIndex (id), column); return index(mIdCollection->getIndex (id), column);
} }
void CSMWorld::IdTable::setRecord (const std::string& id, const RecordBase& record) void CSMWorld::IdTable::setRecord (const std::string& id, const RecordBase& record)
@ -238,7 +259,28 @@ std::pair<CSMWorld::UniversalId, std::string> CSMWorld::IdTable::view (int row)
return std::make_pair (UniversalId (UniversalId::Type_Scene, id), hint); return std::make_pair (UniversalId (UniversalId::Type_Scene, id), hint);
} }
///For top level data/columns
int CSMWorld::IdTable::getColumnId(int column) const int CSMWorld::IdTable::getColumnId(int column) const
{ {
return mIdCollection->getColumn(column).getId(); 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<int, int>(row, column);
} }

View File

@ -8,6 +8,15 @@
#include "universalid.hpp" #include "universalid.hpp"
#include "columns.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 namespace CSMWorld
{ {
class CollectionBase; class CollectionBase;
@ -44,6 +53,8 @@ namespace CSMWorld
// not implemented // not implemented
IdTable (const IdTable&); IdTable (const IdTable&);
IdTable& operator= (const IdTable&); IdTable& operator= (const IdTable&);
unsigned int foldIndexAdress(const QModelIndex& index) const;
std::pair<int, int> unfoldIndexAdress(unsigned int id) const;
public: public:

View File

@ -8,13 +8,13 @@ CSMWorld::RefIdAdapter::RefIdAdapter() {}
CSMWorld::RefIdAdapter::~RefIdAdapter() {} CSMWorld::RefIdAdapter::~RefIdAdapter() {}
QVariant CSMWorld::RefIdAdapter::getData (const CSMWorld::RefIdColumn* column, const CSMWorld::RefIdData& data, int idnex, int subRowIndex, int subColIndex) const QVariant CSMWorld::RefIdAdapter::getNestedData (const CSMWorld::RefIdColumn* column, const CSMWorld::RefIdData& data, int idnex, int subRowIndex, int subColIndex) const
{ {
assert(false); assert(false);
return QVariant(); return QVariant();
} }
void CSMWorld::RefIdAdapter::setData (const CSMWorld::RefIdColumn* column, CSMWorld::RefIdData& data, const QVariant& value, int index, int subRowIndex, int subColIndex) const void CSMWorld::RefIdAdapter::setNestedData (const CSMWorld::RefIdColumn* column, CSMWorld::RefIdData& data, const QVariant& value, int index, int subRowIndex, int subColIndex) const
{ {
assert(false); assert(false);
} }

View File

@ -30,10 +30,10 @@ namespace CSMWorld
const QVariant& value) const = 0; const QVariant& value) const = 0;
///< If the data type does not match an exception is thrown. ///< If the data type does not match an exception is thrown.
virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, virtual QVariant getNestedData (const RefIdColumn *column, const RefIdData& data,
int idnex, int subRowIndex, int subColIndex) const; int idnex, int subRowIndex, int subColIndex) const;
virtual void setData (const RefIdColumn *column, RefIdData& data, virtual void setNestedData (const RefIdColumn *column, RefIdData& data,
const QVariant& value, int index, const QVariant& value, int index,
int subRowIndex, int subColIndex) const; int subRowIndex, int subColIndex) const;

View File

@ -222,7 +222,7 @@ void CSMWorld::ContainerRefIdAdapter::setData (const RefIdColumn *column, RefIdD
NameRefIdAdapter<ESM::Container>::setData (column, data, index, value); NameRefIdAdapter<ESM::Container>::setData (column, data, index, value);
} }
void CSMWorld::ContainerRefIdAdapter::setData(const RefIdColumn *column, RefIdData& data, void CSMWorld::ContainerRefIdAdapter::setNestedData(const RefIdColumn *column, RefIdData& data,
int index, int index,
const QVariant& value, const QVariant& value,
int subRowIndex, int subRowIndex,
@ -242,6 +242,9 @@ void CSMWorld::ContainerRefIdAdapter::setData(const RefIdColumn *column, RefIdDa
case 1: case 1:
record.get().mInventory.mList.at(subRowIndex).mCount = value.toInt(); record.get().mInventory.mList.at(subRowIndex).mCount = value.toInt();
break; break;
default:
throw "Trying to access non-existing column in the nested table!";
} }
} else } else
{ {
@ -249,7 +252,7 @@ void CSMWorld::ContainerRefIdAdapter::setData(const RefIdColumn *column, RefIdDa
} }
} }
QVariant CSMWorld::ContainerRefIdAdapter::getData (const CSMWorld::RefIdColumn* column, QVariant CSMWorld::ContainerRefIdAdapter::getNestedData (const CSMWorld::RefIdColumn* column,
const CSMWorld::RefIdData& data, const CSMWorld::RefIdData& data,
int index, int index,
int subRowIndex, int subRowIndex,

View File

@ -617,15 +617,13 @@ namespace CSMWorld
ContainerRefIdAdapter (const NameColumns& columns, const RefIdColumn *weight, ContainerRefIdAdapter (const NameColumns& columns, const RefIdColumn *weight,
const RefIdColumn *organic, const RefIdColumn *respawn, const RefIdColumn *content); const RefIdColumn *organic, const RefIdColumn *respawn, const RefIdColumn *content);
using RefIdAdapter::getData; virtual QVariant getNestedData (const RefIdColumn *column, const RefIdData& data, int index,
virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index,
int subRowIndex, int subColIndex) const; int subRowIndex, int subColIndex) const;
virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index) virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index)
const; const;
using RefIdAdapter::setData; virtual void setNestedData (const RefIdColumn *column, RefIdData& data, int index,
virtual void setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value, int subRowIndex, int subColIndex) const; const QVariant& value, int subRowIndex, int subColIndex) const;
virtual void setData (const RefIdColumn *column, RefIdData& data, int index, virtual void setData (const RefIdColumn *column, RefIdData& data, int index,

View File

@ -165,7 +165,7 @@ CSMWorld::RefIdCollection::RefIdCollection()
mColumns.push_back (RefIdColumn (Columns::ColumnId_Respawn, ColumnBase::Display_Boolean)); mColumns.push_back (RefIdColumn (Columns::ColumnId_Respawn, ColumnBase::Display_Boolean));
const RefIdColumn *respawn = &mColumns.back(); const RefIdColumn *respawn = &mColumns.back();
mColumns.push_back(RefIdColumn (Columns::ColumnId_ContainerContent, ColumnBase::Display_None, ColumnBase::Flag_Dialogue, false, false)); mColumns.push_back(RefIdColumn (Columns::ColumnId_ContainerContent, ColumnBase::Display_Nested, ColumnBase::Flag_Dialogue, false, false));
const RefIdColumn *content = &mColumns.back(); const RefIdColumn *content = &mColumns.back();
CreatureColumns creatureColumns (actorsColumns); CreatureColumns creatureColumns (actorsColumns);
@ -419,6 +419,16 @@ QVariant CSMWorld::RefIdCollection::getData (int index, int column) const
return adaptor.getData (&mColumns.at (column), mData, localIndex.first); return adaptor.getData (&mColumns.at (column), mData, localIndex.first);
} }
QVariant CSMWorld::RefIdCollection::getNestedData (int row, int column, int subRow, int subColumn) const
{
RefIdData::LocalIndex localIndex = mData.globalToLocalIndex(row);
const RefIdAdapter& adaptor = 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);
}
void CSMWorld::RefIdCollection::setData (int index, int column, const QVariant& data) void CSMWorld::RefIdCollection::setData (int index, int column, const QVariant& data)
{ {
RefIdData::LocalIndex localIndex = mData.globalToLocalIndex (index); RefIdData::LocalIndex localIndex = mData.globalToLocalIndex (index);

View File

@ -65,6 +65,8 @@ namespace CSMWorld
virtual QVariant getData (int index, int column) const; virtual QVariant getData (int index, int column) const;
virtual QVariant getNestedData(int row, int column, int subRow, int subColumn) const;
virtual void setData (int index, int column, const QVariant& data); virtual void setData (int index, int column, const QVariant& data);
virtual void removeRows (int index, int count); virtual void removeRows (int index, int count);

View File

@ -295,7 +295,7 @@ QWidget* CSVWorld::DialogueDelegateDispatcher::makeEditor(CSMWorld::ColumnBase::
{ {
connect(editor, SIGNAL(editingFinished()), proxy, SLOT(editorDataCommited())); connect(editor, SIGNAL(editingFinished()), proxy, SLOT(editorDataCommited()));
skip = true; skip = true;
} } //lisp cond pairs would be nice in the C++
connect(proxy, SIGNAL(editorDataCommited(QWidget*, const QModelIndex&, CSMWorld::ColumnBase::Display)), this, SLOT(editorDataCommited(QWidget*, const QModelIndex&, CSMWorld::ColumnBase::Display))); connect(proxy, SIGNAL(editorDataCommited(QWidget*, const QModelIndex&, CSMWorld::ColumnBase::Display)), this, SLOT(editorDataCommited(QWidget*, const QModelIndex&, CSMWorld::ColumnBase::Display)));
mProxys.push_back(proxy); //deleted in the destructor mProxys.push_back(proxy); //deleted in the destructor
@ -361,6 +361,7 @@ void CSVWorld::EditWidget::remake(int row)
int unlocked = 0; int unlocked = 0;
int locked = 0; int locked = 0;
const int columns = mTable->columnCount(); const int columns = mTable->columnCount();
for (int i=0; i<columns; ++i) for (int i=0; i<columns; ++i)
{ {
int flags = mTable->headerData (i, Qt::Horizontal, CSMWorld::ColumnBase::Role_Flags).toInt(); int flags = mTable->headerData (i, Qt::Horizontal, CSMWorld::ColumnBase::Role_Flags).toInt();
@ -368,28 +369,35 @@ void CSVWorld::EditWidget::remake(int row)
if (flags & CSMWorld::ColumnBase::Flag_Dialogue) if (flags & CSMWorld::ColumnBase::Flag_Dialogue)
{ {
CSMWorld::ColumnBase::Display display = static_cast<CSMWorld::ColumnBase::Display> CSMWorld::ColumnBase::Display display = static_cast<CSMWorld::ColumnBase::Display>
(mTable->headerData (i, Qt::Horizontal, CSMWorld::ColumnBase::Role_Display).toInt()); (mTable->headerData (i, Qt::Horizontal, CSMWorld::ColumnBase::Role_Display).toInt());
mDispatcher.makeDelegate(display); if (display != CSMWorld::ColumnBase::Display_Nested)
QWidget *editor = mDispatcher.makeEditor(display, (mTable->index (row, i)));
if (editor)
{ {
mWidgetMapper->addMapping (editor, i); mDispatcher.makeDelegate (display);
QLabel* label = new QLabel(mTable->headerData (i, Qt::Horizontal).toString(), mMainWidget); QWidget* editor = mDispatcher.makeEditor (display, (mTable->index (row, i)));
label->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
editor->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); if (editor)
if (! (mTable->flags (mTable->index (row, i)) & Qt::ItemIsEditable))
{ {
lockedLayout->addWidget (label, locked, 0); mWidgetMapper->addMapping (editor, i);
lockedLayout->addWidget (editor, locked, 1); QLabel* label = new QLabel (mTable->headerData (i, Qt::Horizontal).toString(), mMainWidget);
++locked; label->setSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed);
} else editor->setSizePolicy (QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
{
unlockedLayout->addWidget (label, unlocked, 0); if (! (mTable->flags (mTable->index (row, i)) & Qt::ItemIsEditable))
unlockedLayout->addWidget (editor, unlocked, 1); {
++unlocked; lockedLayout->addWidget (label, locked, 0);
lockedLayout->addWidget (editor, locked, 1);
++locked;
} else
{
unlockedLayout->addWidget (label, unlocked, 0);
unlockedLayout->addWidget (editor, unlocked, 1);
++unlocked;
}
} }
} else
{
//TODO
} }
} }
} }

View File

@ -172,7 +172,8 @@ QWidget *CSVWorld::CommandDelegate::createEditor (QWidget *parent, const QStyleO
display == CSMWorld::ColumnBase::Display_Class || display == CSMWorld::ColumnBase::Display_Class ||
display == CSMWorld::ColumnBase::Display_Faction || display == CSMWorld::ColumnBase::Display_Faction ||
display == CSMWorld::ColumnBase::Display_Miscellaneous || display == CSMWorld::ColumnBase::Display_Miscellaneous ||
display == CSMWorld::ColumnBase::Display_Sound) display == CSMWorld::ColumnBase::Display_Sound ||
display == CSMWorld::ColumnBase::Display_Region)
{ {
return new DropLineEdit(parent); return new DropLineEdit(parent);
} }