forked from mirror/openmw-tes3mp
changes in the model (idtable) to support nested data
This commit is contained in:
parent
6720d85a04
commit
55d451febe
15 changed files with 133 additions and 39 deletions
|
@ -18,7 +18,7 @@ opencs_hdrs_noqt (model/doc
|
|||
|
||||
|
||||
opencs_units (model/world
|
||||
idtable idtableproxymodel regionmap data
|
||||
idtable idtableproxymodel regionmap data nestedtablemodel
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -82,6 +82,8 @@ namespace CSMWorld
|
|||
|
||||
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 const ColumnBase& getColumn (int column) const;
|
||||
|
@ -277,6 +279,12 @@ namespace CSMWorld
|
|||
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>
|
||||
void Collection<ESXRecordT, IdAccessorT>::setData (int index, int column, const QVariant& data)
|
||||
{
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "collectionbase.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <cassert>
|
||||
|
||||
#include "columnbase.hpp"
|
||||
|
||||
|
|
|
@ -44,6 +44,8 @@ namespace CSMWorld
|
|||
|
||||
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;
|
||||
|
||||
// Not in use. Temporarily removed so that the implementation of RefIdCollection can continue without
|
||||
|
|
|
@ -89,7 +89,9 @@ namespace CSMWorld
|
|||
Display_RefRecordType,
|
||||
Display_DialogueType,
|
||||
Display_QuestStatusType,
|
||||
Display_Gender
|
||||
Display_Gender,
|
||||
|
||||
Display_Nested
|
||||
};
|
||||
|
||||
int mColumnId;
|
||||
|
@ -125,6 +127,12 @@ namespace CSMWorld
|
|||
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
|
||||
|
|
|
@ -36,8 +36,14 @@ 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<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
|
||||
{
|
||||
|
@ -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
|
||||
{
|
||||
unsigned int encodedId = 0;
|
||||
if (parent.isValid())
|
||||
return QModelIndex();
|
||||
{
|
||||
encodedId = this->foldIndexAdress(parent);
|
||||
}
|
||||
|
||||
if (row<0 || row>=mIdCollection->getSize())
|
||||
return QModelIndex();
|
||||
|
@ -106,14 +115,26 @@ QModelIndex CSMWorld::IdTable::index (int row, int column, const QModelIndex& pa
|
|||
if (column<0 || column>=mIdCollection->getColumns())
|
||||
return QModelIndex();
|
||||
|
||||
return createIndex (row, column);
|
||||
return createIndex(row, column, encodedId);
|
||||
}
|
||||
|
||||
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<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)
|
||||
{
|
||||
int index = mIdCollection->getAppendIndex (id, type);
|
||||
|
@ -136,7 +157,7 @@ void CSMWorld::IdTable::cloneRecord(const std::string& origin,
|
|||
endInsertRows();
|
||||
}
|
||||
|
||||
|
||||
///This method can return only indexes to the top level table cells
|
||||
QModelIndex CSMWorld::IdTable::getModelIndex (const std::string& id, int column) const
|
||||
{
|
||||
return index(mIdCollection->getIndex (id), column);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
///For top level data/columns
|
||||
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<int, int>(row, column);
|
||||
}
|
|
@ -8,6 +8,15 @@
|
|||
#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;
|
||||
|
@ -44,6 +53,8 @@ namespace CSMWorld
|
|||
// not implemented
|
||||
IdTable (const IdTable&);
|
||||
IdTable& operator= (const IdTable&);
|
||||
unsigned int foldIndexAdress(const QModelIndex& index) const;
|
||||
std::pair<int, int> unfoldIndexAdress(unsigned int id) const;
|
||||
|
||||
public:
|
||||
|
||||
|
|
|
@ -8,13 +8,13 @@ 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);
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -30,10 +30,10 @@ namespace CSMWorld
|
|||
const QVariant& value) const = 0;
|
||||
///< 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;
|
||||
|
||||
virtual void setData (const RefIdColumn *column, RefIdData& data,
|
||||
virtual void setNestedData (const RefIdColumn *column, RefIdData& data,
|
||||
const QVariant& value, int index,
|
||||
int subRowIndex, int subColIndex) const;
|
||||
|
||||
|
|
|
@ -222,7 +222,7 @@ void CSMWorld::ContainerRefIdAdapter::setData (const RefIdColumn *column, RefIdD
|
|||
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,
|
||||
const QVariant& value,
|
||||
int subRowIndex,
|
||||
|
@ -242,6 +242,9 @@ void CSMWorld::ContainerRefIdAdapter::setData(const RefIdColumn *column, RefIdDa
|
|||
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
|
||||
{
|
||||
|
@ -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,
|
||||
int index,
|
||||
int subRowIndex,
|
||||
|
|
|
@ -617,15 +617,13 @@ namespace CSMWorld
|
|||
ContainerRefIdAdapter (const NameColumns& columns, const RefIdColumn *weight,
|
||||
const RefIdColumn *organic, const RefIdColumn *respawn, const RefIdColumn *content);
|
||||
|
||||
using RefIdAdapter::getData;
|
||||
virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index,
|
||||
virtual QVariant getNestedData (const RefIdColumn *column, const RefIdData& data, int index,
|
||||
int subRowIndex, int subColIndex) const;
|
||||
|
||||
virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index)
|
||||
const;
|
||||
|
||||
using RefIdAdapter::setData;
|
||||
virtual void setData (const RefIdColumn *column, RefIdData& data, int index,
|
||||
virtual void setNestedData (const RefIdColumn *column, RefIdData& data, int index,
|
||||
const QVariant& value, int subRowIndex, int subColIndex) const;
|
||||
|
||||
virtual void setData (const RefIdColumn *column, RefIdData& data, int index,
|
||||
|
|
|
@ -165,7 +165,7 @@ 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_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();
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
RefIdData::LocalIndex localIndex = mData.globalToLocalIndex (index);
|
||||
|
|
|
@ -65,6 +65,8 @@ namespace CSMWorld
|
|||
|
||||
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 removeRows (int index, int count);
|
||||
|
|
|
@ -295,7 +295,7 @@ QWidget* CSVWorld::DialogueDelegateDispatcher::makeEditor(CSMWorld::ColumnBase::
|
|||
{
|
||||
connect(editor, SIGNAL(editingFinished()), proxy, SLOT(editorDataCommited()));
|
||||
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)));
|
||||
mProxys.push_back(proxy); //deleted in the destructor
|
||||
|
@ -361,6 +361,7 @@ void CSVWorld::EditWidget::remake(int row)
|
|||
int unlocked = 0;
|
||||
int locked = 0;
|
||||
const int columns = mTable->columnCount();
|
||||
|
||||
for (int i=0; i<columns; ++i)
|
||||
{
|
||||
int flags = mTable->headerData (i, Qt::Horizontal, CSMWorld::ColumnBase::Role_Flags).toInt();
|
||||
|
@ -370,6 +371,8 @@ void CSVWorld::EditWidget::remake(int row)
|
|||
CSMWorld::ColumnBase::Display display = static_cast<CSMWorld::ColumnBase::Display>
|
||||
(mTable->headerData (i, Qt::Horizontal, CSMWorld::ColumnBase::Role_Display).toInt());
|
||||
|
||||
if (display != CSMWorld::ColumnBase::Display_Nested)
|
||||
{
|
||||
mDispatcher.makeDelegate (display);
|
||||
QWidget* editor = mDispatcher.makeEditor (display, (mTable->index (row, i)));
|
||||
|
||||
|
@ -379,6 +382,7 @@ void CSVWorld::EditWidget::remake(int row)
|
|||
QLabel* label = new QLabel (mTable->headerData (i, Qt::Horizontal).toString(), mMainWidget);
|
||||
label->setSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed);
|
||||
editor->setSizePolicy (QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
|
||||
|
||||
if (! (mTable->flags (mTable->index (row, i)) & Qt::ItemIsEditable))
|
||||
{
|
||||
lockedLayout->addWidget (label, locked, 0);
|
||||
|
@ -391,6 +395,10 @@ void CSVWorld::EditWidget::remake(int row)
|
|||
++unlocked;
|
||||
}
|
||||
}
|
||||
} else
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -172,7 +172,8 @@ QWidget *CSVWorld::CommandDelegate::createEditor (QWidget *parent, const QStyleO
|
|||
display == CSMWorld::ColumnBase::Display_Class ||
|
||||
display == CSMWorld::ColumnBase::Display_Faction ||
|
||||
display == CSMWorld::ColumnBase::Display_Miscellaneous ||
|
||||
display == CSMWorld::ColumnBase::Display_Sound)
|
||||
display == CSMWorld::ColumnBase::Display_Sound ||
|
||||
display == CSMWorld::ColumnBase::Display_Region)
|
||||
{
|
||||
return new DropLineEdit(parent);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue