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
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 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)
{

View file

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

View file

@ -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

View file

@ -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

View file

@ -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);
}

View file

@ -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:

View file

@ -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);
}

View file

@ -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;

View file

@ -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,

View file

@ -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,

View file

@ -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);

View file

@ -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);

View file

@ -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
}
}
}

View file

@ -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);
}