forked from teamnwah/openmw-tes3coop
Merge branch 'master' of https://github.com/OpenMW/openmw into osg
Conflicts: apps/openmw/engine.cpp apps/openmw/mwgui/mainmenu.cpp apps/openmw/mwgui/windowmanagerimp.cpp apps/openmw/mwinput/inputmanagerimp.cpp apps/openmw/mwrender/animation.cpp apps/openmw/mwrender/debugging.cpp apps/openmw/mwrender/npcanimation.cpp apps/openmw/mwrender/renderingmanager.cpp apps/openmw/mwrender/sky.cpp components/nif/nifkey.hpp components/nif/nifstream.hpp components/nifbullet/bulletnifloader.cpp components/nifogre/ogrenifloader.hpp libs/openengine/bullet/physic.cpp libs/openengine/gui/manager.cppc++11
commit
e1f4a7f647
@ -0,0 +1,259 @@
|
|||||||
|
#include "idtree.hpp"
|
||||||
|
|
||||||
|
#include "nestedtablewrapper.hpp"
|
||||||
|
|
||||||
|
#include "collectionbase.hpp"
|
||||||
|
#include "nestedcollection.hpp"
|
||||||
|
#include "columnbase.hpp"
|
||||||
|
|
||||||
|
// NOTE: parent class still needs idCollection
|
||||||
|
CSMWorld::IdTree::IdTree (NestedCollection *nestedCollection, CollectionBase *idCollection, unsigned int features)
|
||||||
|
: IdTable (idCollection, features), mNestedCollection (nestedCollection)
|
||||||
|
{}
|
||||||
|
|
||||||
|
CSMWorld::IdTree::~IdTree()
|
||||||
|
{}
|
||||||
|
|
||||||
|
int CSMWorld::IdTree::rowCount (const QModelIndex & parent) const
|
||||||
|
{
|
||||||
|
if (hasChildren(parent))
|
||||||
|
return mNestedCollection->getNestedRowsCount(parent.row(), parent.column());
|
||||||
|
|
||||||
|
return IdTable::rowCount(parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
int CSMWorld::IdTree::columnCount (const QModelIndex & parent) const
|
||||||
|
{
|
||||||
|
if (hasChildren(parent))
|
||||||
|
return mNestedCollection->getNestedColumnsCount(parent.row(), parent.column());
|
||||||
|
|
||||||
|
return IdTable::columnCount(parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 (index.internalId() != 0)
|
||||||
|
{
|
||||||
|
std::pair<int, int> parentAddress(unfoldIndexAddress(index.internalId()));
|
||||||
|
|
||||||
|
if (role == Qt::EditRole &&
|
||||||
|
!mNestedCollection->getNestableColumn(parentAddress.second)->nestedColumn(index.column()).isEditable())
|
||||||
|
{
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
return mNestedCollection->getNestedData(parentAddress.first,
|
||||||
|
parentAddress.second, index.row(), index.column());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (role==Qt::EditRole && !idCollection()->getColumn (index.column()).isEditable())
|
||||||
|
return QVariant();
|
||||||
|
|
||||||
|
return idCollection()->getData (index.row(), index.column());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant CSMWorld::IdTree::nestedHeaderData(int section, int subSection, Qt::Orientation orientation, int role) const
|
||||||
|
{
|
||||||
|
if (section < 0 || section >= idCollection()->getColumns())
|
||||||
|
return QVariant();
|
||||||
|
|
||||||
|
const NestableColumn *parentColumn = mNestedCollection->getNestableColumn(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 idCollection()->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 (idCollection()->getColumn(parent(index).column()).isEditable() && role==Qt::EditRole)
|
||||||
|
{
|
||||||
|
const std::pair<int, int>& parentAddress(unfoldIndexAddress(index.internalId()));
|
||||||
|
|
||||||
|
mNestedCollection->setNestedData(parentAddress.first, parentAddress.second, value, index.row(), index.column());
|
||||||
|
|
||||||
|
emit dataChanged (CSMWorld::IdTree::index (parentAddress.first, 0),
|
||||||
|
CSMWorld::IdTree::index (parentAddress.first, idCollection()->getColumns()-1));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return IdTable::setData(index, value, role);
|
||||||
|
}
|
||||||
|
|
||||||
|
Qt::ItemFlags CSMWorld::IdTree::flags (const QModelIndex & index) const
|
||||||
|
{
|
||||||
|
if (!index.isValid())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (index.internalId() != 0)
|
||||||
|
{
|
||||||
|
std::pair<int, int> parentAddress(unfoldIndexAddress(index.internalId()));
|
||||||
|
|
||||||
|
Qt::ItemFlags flags = Qt::ItemIsSelectable | Qt::ItemIsEnabled;
|
||||||
|
|
||||||
|
if (mNestedCollection->getNestableColumn(parentAddress.second)->nestedColumn(index.column()).isEditable())
|
||||||
|
flags |= Qt::ItemIsEditable;
|
||||||
|
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return IdTable::flags(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSMWorld::IdTree::removeRows (int row, int count, const QModelIndex& parent)
|
||||||
|
{
|
||||||
|
if (parent.isValid())
|
||||||
|
{
|
||||||
|
beginRemoveRows (parent, row, row+count-1);
|
||||||
|
|
||||||
|
for (int i = 0; i < count; ++i)
|
||||||
|
{
|
||||||
|
mNestedCollection->removeNestedRows(parent.row(), parent.column(), row+i);
|
||||||
|
}
|
||||||
|
|
||||||
|
endRemoveRows();
|
||||||
|
|
||||||
|
emit dataChanged (CSMWorld::IdTree::index (parent.row(), 0),
|
||||||
|
CSMWorld::IdTree::index (parent.row(), idCollection()->getColumns()-1));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return IdTable::removeRows(row, count, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
mNestedCollection->addNestedRow(row, parent.column(), position);
|
||||||
|
endInsertRows();
|
||||||
|
|
||||||
|
emit dataChanged (CSMWorld::IdTree::index (row, 0),
|
||||||
|
CSMWorld::IdTree::index (row, idCollection()->getColumns()-1));
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex CSMWorld::IdTree::index (int row, int column, const QModelIndex& parent) const
|
||||||
|
{
|
||||||
|
unsigned int encodedId = 0;
|
||||||
|
if (parent.isValid())
|
||||||
|
{
|
||||||
|
encodedId = this->foldIndexAddress(parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (row<0 || row>=idCollection()->getSize())
|
||||||
|
return QModelIndex();
|
||||||
|
|
||||||
|
if (column<0 || column>=idCollection()->getColumns())
|
||||||
|
return QModelIndex();
|
||||||
|
|
||||||
|
return createIndex(row, column, encodedId); // store internal id
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex CSMWorld::IdTree::getNestedModelIndex (const std::string& id, int column) const
|
||||||
|
{
|
||||||
|
return CSMWorld::IdTable::index(idCollection()->getIndex (id), column);
|
||||||
|
}
|
||||||
|
|
||||||
|
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<int, int>& adress(unfoldIndexAddress(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);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int CSMWorld::IdTree::foldIndexAddress (const QModelIndex& index) const
|
||||||
|
{
|
||||||
|
unsigned int out = index.row() * this->columnCount();
|
||||||
|
out += index.column();
|
||||||
|
return ++out;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair< int, int > CSMWorld::IdTree::unfoldIndexAddress (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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: Not sure why this check is also needed?
|
||||||
|
//
|
||||||
|
// index.data().isValid() requires RefIdAdapter::getData() to return a valid QVariant for
|
||||||
|
// nested columns (refidadapterimp.hpp)
|
||||||
|
//
|
||||||
|
// Also see comments in refidadapter.hpp and refidadapterimp.hpp.
|
||||||
|
bool CSMWorld::IdTree::hasChildren(const QModelIndex& index) const
|
||||||
|
{
|
||||||
|
return (index.isValid() &&
|
||||||
|
index.internalId() == 0 &&
|
||||||
|
mNestedCollection->getNestableColumn(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;
|
||||||
|
}
|
||||||
|
|
||||||
|
mNestedCollection->setNestedTable(index.row(), index.column(), nestedTable);
|
||||||
|
|
||||||
|
emit dataChanged (CSMWorld::IdTree::index (index.row(), 0),
|
||||||
|
CSMWorld::IdTree::index (index.row(), idCollection()->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 mNestedCollection->nestedTable(index.row(), index.column());
|
||||||
|
}
|
@ -0,0 +1,84 @@
|
|||||||
|
#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;
|
||||||
|
struct NestedTableWrapperBase;
|
||||||
|
|
||||||
|
class IdTree : public IdTable
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
NestedCollection *mNestedCollection;
|
||||||
|
|
||||||
|
// not implemented
|
||||||
|
IdTree (const IdTree&);
|
||||||
|
IdTree& operator= (const IdTree&);
|
||||||
|
|
||||||
|
unsigned int foldIndexAddress(const QModelIndex& index) const;
|
||||||
|
std::pair<int, int> unfoldIndexAddress(unsigned int id) const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
IdTree (NestedCollection *nestedCollection, CollectionBase *idCollection, unsigned int features = 0);
|
||||||
|
///< The ownerships of \a nestedCollecton and \a idCollection are 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 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;
|
||||||
|
|
||||||
|
QModelIndex getNestedModelIndex (const std::string& id, int column) 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);
|
||||||
|
|
||||||
|
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
|
@ -0,0 +1,531 @@
|
|||||||
|
#include "nestedcoladapterimp.hpp"
|
||||||
|
|
||||||
|
#include <components/esm/loadregn.hpp>
|
||||||
|
#include <components/esm/loadfact.hpp>
|
||||||
|
|
||||||
|
#include "idcollection.hpp"
|
||||||
|
#include "pathgrid.hpp"
|
||||||
|
#include "info.hpp"
|
||||||
|
|
||||||
|
namespace CSMWorld
|
||||||
|
{
|
||||||
|
PathgridPointListAdapter::PathgridPointListAdapter () {}
|
||||||
|
|
||||||
|
void PathgridPointListAdapter::addRow(Record<Pathgrid>& record, int position) const
|
||||||
|
{
|
||||||
|
Pathgrid pathgrid = record.get();
|
||||||
|
|
||||||
|
ESM::Pathgrid::PointList& points = pathgrid.mPoints;
|
||||||
|
|
||||||
|
// blank row
|
||||||
|
ESM::Pathgrid::Point point;
|
||||||
|
point.mX = 0;
|
||||||
|
point.mY = 0;
|
||||||
|
point.mZ = 0;
|
||||||
|
point.mAutogenerated = 0;
|
||||||
|
point.mConnectionNum = 0;
|
||||||
|
point.mUnknown = 0;
|
||||||
|
|
||||||
|
// inserting a point should trigger re-indexing of the edges
|
||||||
|
//
|
||||||
|
// FIXME: does not auto refresh edges table view
|
||||||
|
std::vector<ESM::Pathgrid::Edge>::iterator iter = pathgrid.mEdges.begin();
|
||||||
|
for (;iter != pathgrid.mEdges.end(); ++iter)
|
||||||
|
{
|
||||||
|
if ((*iter).mV0 >= position)
|
||||||
|
(*iter).mV0++;
|
||||||
|
if ((*iter).mV1 >= position)
|
||||||
|
(*iter).mV1++;
|
||||||
|
}
|
||||||
|
|
||||||
|
points.insert(points.begin()+position, point);
|
||||||
|
pathgrid.mData.mS2 += 1; // increment the number of points
|
||||||
|
|
||||||
|
record.setModified (pathgrid);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PathgridPointListAdapter::removeRow(Record<Pathgrid>& record, int rowToRemove) const
|
||||||
|
{
|
||||||
|
Pathgrid pathgrid = record.get();
|
||||||
|
|
||||||
|
ESM::Pathgrid::PointList& points = pathgrid.mPoints;
|
||||||
|
|
||||||
|
if (rowToRemove < 0 || rowToRemove >= static_cast<int> (points.size()))
|
||||||
|
throw std::runtime_error ("index out of range");
|
||||||
|
|
||||||
|
// deleting a point should trigger re-indexing of the edges
|
||||||
|
// dangling edges are not allowed and hence removed
|
||||||
|
//
|
||||||
|
// FIXME: does not auto refresh edges table view
|
||||||
|
std::vector<ESM::Pathgrid::Edge>::iterator iter = pathgrid.mEdges.begin();
|
||||||
|
for (; iter != pathgrid.mEdges.end();)
|
||||||
|
{
|
||||||
|
if (((*iter).mV0 == rowToRemove) || ((*iter).mV1 == rowToRemove))
|
||||||
|
iter = pathgrid.mEdges.erase(iter);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((*iter).mV0 > rowToRemove)
|
||||||
|
(*iter).mV0--;
|
||||||
|
|
||||||
|
if ((*iter).mV1 > rowToRemove)
|
||||||
|
(*iter).mV1--;
|
||||||
|
|
||||||
|
++iter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
points.erase(points.begin()+rowToRemove);
|
||||||
|
pathgrid.mData.mS2 -= 1; // decrement the number of points
|
||||||
|
|
||||||
|
record.setModified (pathgrid);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PathgridPointListAdapter::setTable(Record<Pathgrid>& record,
|
||||||
|
const NestedTableWrapperBase& nestedTable) const
|
||||||
|
{
|
||||||
|
Pathgrid pathgrid = record.get();
|
||||||
|
|
||||||
|
pathgrid.mPoints =
|
||||||
|
static_cast<const PathgridPointsWrap &>(nestedTable).mRecord.mPoints;
|
||||||
|
pathgrid.mData.mS2 =
|
||||||
|
static_cast<const PathgridPointsWrap &>(nestedTable).mRecord.mData.mS2;
|
||||||
|
// also update edges in case points were added/removed
|
||||||
|
pathgrid.mEdges =
|
||||||
|
static_cast<const PathgridPointsWrap &>(nestedTable).mRecord.mEdges;
|
||||||
|
|
||||||
|
record.setModified (pathgrid);
|
||||||
|
}
|
||||||
|
|
||||||
|
NestedTableWrapperBase* PathgridPointListAdapter::table(const Record<Pathgrid>& record) const
|
||||||
|
{
|
||||||
|
// deleted by dtor of NestedTableStoring
|
||||||
|
return new PathgridPointsWrap(record.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant PathgridPointListAdapter::getData(const Record<Pathgrid>& record,
|
||||||
|
int subRowIndex, int subColIndex) const
|
||||||
|
{
|
||||||
|
ESM::Pathgrid::Point point = record.get().mPoints[subRowIndex];
|
||||||
|
switch (subColIndex)
|
||||||
|
{
|
||||||
|
case 0: return subRowIndex;
|
||||||
|
case 1: return point.mX;
|
||||||
|
case 2: return point.mY;
|
||||||
|
case 3: return point.mZ;
|
||||||
|
default: throw std::runtime_error("Pathgrid point subcolumn index out of range");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PathgridPointListAdapter::setData(Record<Pathgrid>& record,
|
||||||
|
const QVariant& value, int subRowIndex, int subColIndex) const
|
||||||
|
{
|
||||||
|
Pathgrid pathgrid = record.get();
|
||||||
|
ESM::Pathgrid::Point point = pathgrid.mPoints[subRowIndex];
|
||||||
|
switch (subColIndex)
|
||||||
|
{
|
||||||
|
case 0: return; // return without saving
|
||||||
|
case 1: point.mX = value.toInt(); break;
|
||||||
|
case 2: point.mY = value.toInt(); break;
|
||||||
|
case 3: point.mZ = value.toInt(); break;
|
||||||
|
default: throw std::runtime_error("Pathgrid point subcolumn index out of range");
|
||||||
|
}
|
||||||
|
|
||||||
|
pathgrid.mPoints[subRowIndex] = point;
|
||||||
|
|
||||||
|
record.setModified (pathgrid);
|
||||||
|
}
|
||||||
|
|
||||||
|
int PathgridPointListAdapter::getColumnsCount(const Record<Pathgrid>& record) const
|
||||||
|
{
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
int PathgridPointListAdapter::getRowsCount(const Record<Pathgrid>& record) const
|
||||||
|
{
|
||||||
|
return static_cast<int>(record.get().mPoints.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
PathgridEdgeListAdapter::PathgridEdgeListAdapter () {}
|
||||||
|
|
||||||
|
// ToDo: seems to be auto-sorted in the dialog table display after insertion
|
||||||
|
void PathgridEdgeListAdapter::addRow(Record<Pathgrid>& record, int position) const
|
||||||
|
{
|
||||||
|
Pathgrid pathgrid = record.get();
|
||||||
|
|
||||||
|
ESM::Pathgrid::EdgeList& edges = pathgrid.mEdges;
|
||||||
|
|
||||||
|
// blank row
|
||||||
|
ESM::Pathgrid::Edge edge;
|
||||||
|
edge.mV0 = 0;
|
||||||
|
edge.mV1 = 0;
|
||||||
|
|
||||||
|
// NOTE: inserting a blank edge does not really make sense, perhaps this should be a
|
||||||
|
// logic_error exception
|
||||||
|
//
|
||||||
|
// Currently the code assumes that the end user to know what he/she is doing.
|
||||||
|
// e.g. Edges come in pairs, from points a->b and b->a
|
||||||
|
edges.insert(edges.begin()+position, edge);
|
||||||
|
|
||||||
|
record.setModified (pathgrid);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PathgridEdgeListAdapter::removeRow(Record<Pathgrid>& record, int rowToRemove) const
|
||||||
|
{
|
||||||
|
Pathgrid pathgrid = record.get();
|
||||||
|
|
||||||
|
ESM::Pathgrid::EdgeList& edges = pathgrid.mEdges;
|
||||||
|
|
||||||
|
if (rowToRemove < 0 || rowToRemove >= static_cast<int> (edges.size()))
|
||||||
|
throw std::runtime_error ("index out of range");
|
||||||
|
|
||||||
|
edges.erase(edges.begin()+rowToRemove);
|
||||||
|
|
||||||
|
record.setModified (pathgrid);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PathgridEdgeListAdapter::setTable(Record<Pathgrid>& record,
|
||||||
|
const NestedTableWrapperBase& nestedTable) const
|
||||||
|
{
|
||||||
|
Pathgrid pathgrid = record.get();
|
||||||
|
|
||||||
|
pathgrid.mEdges =
|
||||||
|
static_cast<const NestedTableWrapper<ESM::Pathgrid::EdgeList> &>(nestedTable).mNestedTable;
|
||||||
|
|
||||||
|
record.setModified (pathgrid);
|
||||||
|
}
|
||||||
|
|
||||||
|
NestedTableWrapperBase* PathgridEdgeListAdapter::table(const Record<Pathgrid>& record) const
|
||||||
|
{
|
||||||
|
// deleted by dtor of NestedTableStoring
|
||||||
|
return new NestedTableWrapper<ESM::Pathgrid::EdgeList>(record.get().mEdges);
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant PathgridEdgeListAdapter::getData(const Record<Pathgrid>& record,
|
||||||
|
int subRowIndex, int subColIndex) const
|
||||||
|
{
|
||||||
|
Pathgrid pathgrid = record.get();
|
||||||
|
|
||||||
|
if (subRowIndex < 0 || subRowIndex >= static_cast<int> (pathgrid.mEdges.size()))
|
||||||
|
throw std::runtime_error ("index out of range");
|
||||||
|
|
||||||
|
ESM::Pathgrid::Edge edge = pathgrid.mEdges[subRowIndex];
|
||||||
|
switch (subColIndex)
|
||||||
|
{
|
||||||
|
case 0: return subRowIndex;
|
||||||
|
case 1: return edge.mV0;
|
||||||
|
case 2: return edge.mV1;
|
||||||
|
default: throw std::runtime_error("Pathgrid edge subcolumn index out of range");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToDo: detect duplicates in mEdges
|
||||||
|
void PathgridEdgeListAdapter::setData(Record<Pathgrid>& record,
|
||||||
|
const QVariant& value, int subRowIndex, int subColIndex) const
|
||||||
|
{
|
||||||
|
Pathgrid pathgrid = record.get();
|
||||||
|
|
||||||
|
if (subRowIndex < 0 || subRowIndex >= static_cast<int> (pathgrid.mEdges.size()))
|
||||||
|
throw std::runtime_error ("index out of range");
|
||||||
|
|
||||||
|
ESM::Pathgrid::Edge edge = pathgrid.mEdges[subRowIndex];
|
||||||
|
switch (subColIndex)
|
||||||
|
{
|
||||||
|
case 0: return; // return without saving
|
||||||
|
case 1: edge.mV0 = value.toInt(); break;
|
||||||
|
case 2: edge.mV1 = value.toInt(); break;
|
||||||
|
default: throw std::runtime_error("Pathgrid edge subcolumn index out of range");
|
||||||
|
}
|
||||||
|
|
||||||
|
pathgrid.mEdges[subRowIndex] = edge;
|
||||||
|
|
||||||
|
record.setModified (pathgrid);
|
||||||
|
}
|
||||||
|
|
||||||
|
int PathgridEdgeListAdapter::getColumnsCount(const Record<Pathgrid>& record) const
|
||||||
|
{
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
int PathgridEdgeListAdapter::getRowsCount(const Record<Pathgrid>& record) const
|
||||||
|
{
|
||||||
|
return static_cast<int>(record.get().mEdges.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
FactionReactionsAdapter::FactionReactionsAdapter () {}
|
||||||
|
|
||||||
|
void FactionReactionsAdapter::addRow(Record<ESM::Faction>& record, int position) const
|
||||||
|
{
|
||||||
|
ESM::Faction faction = record.get();
|
||||||
|
|
||||||
|
std::map<std::string, int>& reactions = faction.mReactions;
|
||||||
|
|
||||||
|
// blank row
|
||||||
|
reactions.insert(std::make_pair("", 0));
|
||||||
|
|
||||||
|
record.setModified (faction);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FactionReactionsAdapter::removeRow(Record<ESM::Faction>& record, int rowToRemove) const
|
||||||
|
{
|
||||||
|
ESM::Faction faction = record.get();
|
||||||
|
|
||||||
|
std::map<std::string, int>& reactions = faction.mReactions;
|
||||||
|
|
||||||
|
if (rowToRemove < 0 || rowToRemove >= static_cast<int> (reactions.size()))
|
||||||
|
throw std::runtime_error ("index out of range");
|
||||||
|
|
||||||
|
// FIXME: how to ensure that the map entries correspond to table indicies?
|
||||||
|
// WARNING: Assumed that the table view has the same order as std::map
|
||||||
|
std::map<std::string, int>::iterator iter = reactions.begin();
|
||||||
|
for(int i = 0; i < rowToRemove; ++i)
|
||||||
|
iter++;
|
||||||
|
reactions.erase(iter);
|
||||||
|
|
||||||
|
record.setModified (faction);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FactionReactionsAdapter::setTable(Record<ESM::Faction>& record,
|
||||||
|
const NestedTableWrapperBase& nestedTable) const
|
||||||
|
{
|
||||||
|
ESM::Faction faction = record.get();
|
||||||
|
|
||||||
|
faction.mReactions =
|
||||||
|
static_cast<const NestedTableWrapper<std::map<std::string, int> >&>(nestedTable).mNestedTable;
|
||||||
|
|
||||||
|
record.setModified (faction);
|
||||||
|
}
|
||||||
|
|
||||||
|
NestedTableWrapperBase* FactionReactionsAdapter::table(const Record<ESM::Faction>& record) const
|
||||||
|
{
|
||||||
|
// deleted by dtor of NestedTableStoring
|
||||||
|
return new NestedTableWrapper<std::map<std::string, int> >(record.get().mReactions);
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant FactionReactionsAdapter::getData(const Record<ESM::Faction>& record,
|
||||||
|
int subRowIndex, int subColIndex) const
|
||||||
|
{
|
||||||
|
ESM::Faction faction = record.get();
|
||||||
|
|
||||||
|
std::map<std::string, int>& reactions = faction.mReactions;
|
||||||
|
|
||||||
|
if (subRowIndex < 0 || subRowIndex >= static_cast<int> (reactions.size()))
|
||||||
|
throw std::runtime_error ("index out of range");
|
||||||
|
|
||||||
|
// FIXME: how to ensure that the map entries correspond to table indicies?
|
||||||
|
// WARNING: Assumed that the table view has the same order as std::map
|
||||||
|
std::map<std::string, int>::const_iterator iter = reactions.begin();
|
||||||
|
for(int i = 0; i < subRowIndex; ++i)
|
||||||
|
iter++;
|
||||||
|
switch (subColIndex)
|
||||||
|
{
|
||||||
|
case 0: return QString((*iter).first.c_str());
|
||||||
|
case 1: return (*iter).second;
|
||||||
|
default: throw std::runtime_error("Faction reactions subcolumn index out of range");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FactionReactionsAdapter::setData(Record<ESM::Faction>& record,
|
||||||
|
const QVariant& value, int subRowIndex, int subColIndex) const
|
||||||
|
{
|
||||||
|
ESM::Faction faction = record.get();
|
||||||
|
|
||||||
|
std::map<std::string, int>& reactions = faction.mReactions;
|
||||||
|
|
||||||
|
if (subRowIndex < 0 || subRowIndex >= static_cast<int> (reactions.size()))
|
||||||
|
throw std::runtime_error ("index out of range");
|
||||||
|
|
||||||
|
// FIXME: how to ensure that the map entries correspond to table indicies?
|
||||||
|
// WARNING: Assumed that the table view has the same order as std::map
|
||||||
|
std::map<std::string, int>::iterator iter = reactions.begin();
|
||||||
|
for(int i = 0; i < subRowIndex; ++i)
|
||||||
|
iter++;
|
||||||
|
|
||||||
|
std::string factionId = (*iter).first;
|
||||||
|
int reaction = (*iter).second;
|
||||||
|
|
||||||
|
switch (subColIndex)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
{
|
||||||
|
reactions.erase(iter);
|
||||||
|
reactions.insert(std::make_pair(value.toString().toUtf8().constData(), reaction));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
reactions[factionId] = value.toInt();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: throw std::runtime_error("Faction reactions subcolumn index out of range");
|
||||||
|
}
|
||||||
|
|
||||||
|
record.setModified (faction);
|
||||||
|
}
|
||||||
|
|
||||||
|
int FactionReactionsAdapter::getColumnsCount(const Record<ESM::Faction>& record) const
|
||||||
|
{
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
int FactionReactionsAdapter::getRowsCount(const Record<ESM::Faction>& record) const
|
||||||
|
{
|
||||||
|
return static_cast<int>(record.get().mReactions.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
RegionSoundListAdapter::RegionSoundListAdapter () {}
|
||||||
|
|
||||||
|
void RegionSoundListAdapter::addRow(Record<ESM::Region>& record, int position) const
|
||||||
|
{
|
||||||
|
ESM::Region region = record.get();
|
||||||
|
|
||||||
|
std::vector<ESM::Region::SoundRef>& soundList = region.mSoundList;
|
||||||
|
|
||||||
|
// blank row
|
||||||
|
ESM::Region::SoundRef soundRef;
|
||||||
|
soundRef.mSound.assign("");
|
||||||
|
soundRef.mChance = 0;
|
||||||
|
|
||||||
|
soundList.insert(soundList.begin()+position, soundRef);
|
||||||
|
|
||||||
|
record.setModified (region);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionSoundListAdapter::removeRow(Record<ESM::Region>& record, int rowToRemove) const
|
||||||
|
{
|
||||||
|
ESM::Region region = record.get();
|
||||||
|
|
||||||
|
std::vector<ESM::Region::SoundRef>& soundList = region.mSoundList;
|
||||||
|
|
||||||
|
if (rowToRemove < 0 || rowToRemove >= static_cast<int> (soundList.size()))
|
||||||
|
throw std::runtime_error ("index out of range");
|
||||||
|
|
||||||
|
soundList.erase(soundList.begin()+rowToRemove);
|
||||||
|
|
||||||
|
record.setModified (region);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionSoundListAdapter::setTable(Record<ESM::Region>& record,
|
||||||
|
const NestedTableWrapperBase& nestedTable) const
|
||||||
|
{
|
||||||
|
ESM::Region region = record.get();
|
||||||
|
|
||||||
|
region.mSoundList =
|
||||||
|
static_cast<const NestedTableWrapper<std::vector<ESM::Region::SoundRef> >&>(nestedTable).mNestedTable;
|
||||||
|
|
||||||
|
record.setModified (region);
|
||||||
|
}
|
||||||
|
|
||||||
|
NestedTableWrapperBase* RegionSoundListAdapter::table(const Record<ESM::Region>& record) const
|
||||||
|
{
|
||||||
|
// deleted by dtor of NestedTableStoring
|
||||||
|
return new NestedTableWrapper<std::vector<ESM::Region::SoundRef> >(record.get().mSoundList);
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant RegionSoundListAdapter::getData(const Record<ESM::Region>& record,
|
||||||
|
int subRowIndex, int subColIndex) const
|
||||||
|
{
|
||||||
|
ESM::Region region = record.get();
|
||||||
|
|
||||||
|
std::vector<ESM::Region::SoundRef>& soundList = region.mSoundList;
|
||||||
|
|
||||||
|
if (subRowIndex < 0 || subRowIndex >= static_cast<int> (soundList.size()))
|
||||||
|
throw std::runtime_error ("index out of range");
|
||||||
|
|
||||||
|
ESM::Region::SoundRef soundRef = soundList[subRowIndex];
|
||||||
|
switch (subColIndex)
|
||||||
|
{
|
||||||
|
case 0: return QString(soundRef.mSound.toString().c_str());
|
||||||
|
case 1: return soundRef.mChance;
|
||||||
|
default: throw std::runtime_error("Region sounds subcolumn index out of range");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionSoundListAdapter::setData(Record<ESM::Region>& record,
|
||||||
|
const QVariant& value, int subRowIndex, int subColIndex) const
|
||||||
|
{
|
||||||
|
ESM::Region region = record.get();
|
||||||
|
|
||||||
|
std::vector<ESM::Region::SoundRef>& soundList = region.mSoundList;
|
||||||
|
|
||||||
|
if (subRowIndex < 0 || subRowIndex >= static_cast<int> (soundList.size()))
|
||||||
|
throw std::runtime_error ("index out of range");
|
||||||
|
|
||||||
|
ESM::Region::SoundRef soundRef = soundList[subRowIndex];
|
||||||
|
switch (subColIndex)
|
||||||
|
{
|
||||||
|
case 0: soundRef.mSound.assign(value.toString().toUtf8().constData()); break;
|
||||||
|
case 1: soundRef.mChance = static_cast<unsigned char>(value.toInt()); break;
|
||||||
|
default: throw std::runtime_error("Region sounds subcolumn index out of range");
|
||||||
|
}
|
||||||
|
|
||||||
|
region.mSoundList[subRowIndex] = soundRef;
|
||||||
|
|
||||||
|
record.setModified (region);
|
||||||
|
}
|
||||||
|
|
||||||
|
int RegionSoundListAdapter::getColumnsCount(const Record<ESM::Region>& record) const
|
||||||
|
{
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
int RegionSoundListAdapter::getRowsCount(const Record<ESM::Region>& record) const
|
||||||
|
{
|
||||||
|
return static_cast<int>(record.get().mSoundList.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
InfoListAdapter::InfoListAdapter () {}
|
||||||
|
|
||||||
|
void InfoListAdapter::addRow(Record<Info>& record, int position) const
|
||||||
|
{
|
||||||
|
throw std::logic_error ("cannot add a row to a fixed table");
|
||||||
|
}
|
||||||
|
|
||||||
|
void InfoListAdapter::removeRow(Record<Info>& record, int rowToRemove) const
|
||||||
|
{
|
||||||
|
throw std::logic_error ("cannot add a row to a fixed table");
|
||||||
|
}
|
||||||
|
|
||||||
|
void InfoListAdapter::setTable(Record<Info>& record,
|
||||||
|
const NestedTableWrapperBase& nestedTable) const
|
||||||
|
{
|
||||||
|
throw std::logic_error ("table operation not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
NestedTableWrapperBase* InfoListAdapter::table(const Record<Info>& record) const
|
||||||
|
{
|
||||||
|
throw std::logic_error ("table operation not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant InfoListAdapter::getData(const Record<Info>& record,
|
||||||
|
int subRowIndex, int subColIndex) const
|
||||||
|
{
|
||||||
|
Info info = record.get();
|
||||||
|
|
||||||
|
if (subColIndex == 0)
|
||||||
|
return QString(info.mResultScript.c_str());
|
||||||
|
else
|
||||||
|
throw std::runtime_error("Trying to access non-existing column in the nested table!");
|
||||||
|
}
|
||||||
|
|
||||||
|
void InfoListAdapter::setData(Record<Info>& record,
|
||||||
|
const QVariant& value, int subRowIndex, int subColIndex) const
|
||||||
|
{
|
||||||
|
Info info = record.get();
|
||||||
|
|
||||||
|
if (subColIndex == 0)
|
||||||
|
info.mResultScript = value.toString().toStdString();
|
||||||
|
else
|
||||||
|
throw std::runtime_error("Trying to access non-existing column in the nested table!");
|
||||||
|
|
||||||
|
record.setModified (info);
|
||||||
|
}
|
||||||
|
|
||||||
|
int InfoListAdapter::getColumnsCount(const Record<Info>& record) const
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int InfoListAdapter::getRowsCount(const Record<Info>& record) const
|
||||||
|
{
|
||||||
|
return 1; // fixed at size 1
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,417 @@
|
|||||||
|
#ifndef CSM_WOLRD_NESTEDCOLADAPTERIMP_H
|
||||||
|
#define CSM_WOLRD_NESTEDCOLADAPTERIMP_H
|
||||||
|
|
||||||
|
#include <QVariant>
|
||||||
|
|
||||||
|
#include <components/esm/loadpgrd.hpp>
|
||||||
|
#include <components/esm/effectlist.hpp>
|
||||||
|
#include <components/esm/loadmgef.hpp> // for converting magic effect id to string & back
|
||||||
|
#include <components/esm/loadskil.hpp> // for converting skill names
|
||||||
|
#include <components/esm/attr.hpp> // for converting attributes
|
||||||
|
|
||||||
|
#include "nestedcolumnadapter.hpp"
|
||||||
|
#include "nestedtablewrapper.hpp"
|
||||||
|
|
||||||
|
namespace ESM
|
||||||
|
{
|
||||||
|
struct Faction;
|
||||||
|
struct Region;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace CSMWorld
|
||||||
|
{
|
||||||
|
struct Pathgrid;
|
||||||
|
struct Info;
|
||||||
|
|
||||||
|
struct PathgridPointsWrap : public NestedTableWrapperBase
|
||||||
|
{
|
||||||
|
ESM::Pathgrid mRecord;
|
||||||
|
|
||||||
|
PathgridPointsWrap(ESM::Pathgrid pathgrid)
|
||||||
|
: mRecord(pathgrid) {}
|
||||||
|
|
||||||
|
virtual ~PathgridPointsWrap() {}
|
||||||
|
|
||||||
|
virtual int size() const
|
||||||
|
{
|
||||||
|
return mRecord.mPoints.size(); // used in IdTree::setNestedTable()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class PathgridPointListAdapter : public NestedColumnAdapter<Pathgrid>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PathgridPointListAdapter ();
|
||||||
|
|
||||||
|
virtual void addRow(Record<Pathgrid>& record, int position) const;
|
||||||
|
|
||||||
|
virtual void removeRow(Record<Pathgrid>& record, int rowToRemove) const;
|
||||||
|
|
||||||
|
virtual void setTable(Record<Pathgrid>& record,
|
||||||
|
const NestedTableWrapperBase& nestedTable) const;
|
||||||
|
|
||||||
|
virtual NestedTableWrapperBase* table(const Record<Pathgrid>& record) const;
|
||||||
|
|
||||||
|
virtual QVariant getData(const Record<Pathgrid>& record,
|
||||||
|
int subRowIndex, int subColIndex) const;
|
||||||
|
|
||||||
|
virtual void setData(Record<Pathgrid>& record,
|
||||||
|
const QVariant& value, int subRowIndex, int subColIndex) const;
|
||||||
|
|
||||||
|
virtual int getColumnsCount(const Record<Pathgrid>& record) const;
|
||||||
|
|
||||||
|
virtual int getRowsCount(const Record<Pathgrid>& record) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PathgridEdgeListAdapter : public NestedColumnAdapter<Pathgrid>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PathgridEdgeListAdapter ();
|
||||||
|
|
||||||
|
virtual void addRow(Record<Pathgrid>& record, int position) const;
|
||||||
|
|
||||||
|
virtual void removeRow(Record<Pathgrid>& record, int rowToRemove) const;
|
||||||
|
|
||||||
|
virtual void setTable(Record<Pathgrid>& record,
|
||||||
|
const NestedTableWrapperBase& nestedTable) const;
|
||||||
|
|
||||||
|
virtual NestedTableWrapperBase* table(const Record<Pathgrid>& record) const;
|
||||||
|
|
||||||
|
virtual QVariant getData(const Record<Pathgrid>& record,
|
||||||
|
int subRowIndex, int subColIndex) const;
|
||||||
|
|
||||||
|
virtual void setData(Record<Pathgrid>& record,
|
||||||
|
const QVariant& value, int subRowIndex, int subColIndex) const;
|
||||||
|
|
||||||
|
virtual int getColumnsCount(const Record<Pathgrid>& record) const;
|
||||||
|
|
||||||
|
virtual int getRowsCount(const Record<Pathgrid>& record) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
class FactionReactionsAdapter : public NestedColumnAdapter<ESM::Faction>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FactionReactionsAdapter ();
|
||||||
|
|
||||||
|
virtual void addRow(Record<ESM::Faction>& record, int position) const;
|
||||||
|
|
||||||
|
virtual void removeRow(Record<ESM::Faction>& record, int rowToRemove) const;
|
||||||
|
|
||||||
|
virtual void setTable(Record<ESM::Faction>& record,
|
||||||
|
const NestedTableWrapperBase& nestedTable) const;
|
||||||
|
|
||||||
|
virtual NestedTableWrapperBase* table(const Record<ESM::Faction>& record) const;
|
||||||
|
|
||||||
|
virtual QVariant getData(const Record<ESM::Faction>& record,
|
||||||
|
int subRowIndex, int subColIndex) const;
|
||||||
|
|
||||||
|
virtual void setData(Record<ESM::Faction>& record,
|
||||||
|
const QVariant& value, int subRowIndex, int subColIndex) const;
|
||||||
|
|
||||||
|
virtual int getColumnsCount(const Record<ESM::Faction>& record) const;
|
||||||
|
|
||||||
|
virtual int getRowsCount(const Record<ESM::Faction>& record) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
class RegionSoundListAdapter : public NestedColumnAdapter<ESM::Region>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RegionSoundListAdapter ();
|
||||||
|
|
||||||
|
virtual void addRow(Record<ESM::Region>& record, int position) const;
|
||||||
|
|
||||||
|
virtual void removeRow(Record<ESM::Region>& record, int rowToRemove) const;
|
||||||
|
|
||||||
|
virtual void setTable(Record<ESM::Region>& record,
|
||||||
|
const NestedTableWrapperBase& nestedTable) const;
|
||||||
|
|
||||||
|
virtual NestedTableWrapperBase* table(const Record<ESM::Region>& record) const;
|
||||||
|
|
||||||
|
virtual QVariant getData(const Record<ESM::Region>& record,
|
||||||
|
int subRowIndex, int subColIndex) const;
|
||||||
|
|
||||||
|
virtual void setData(Record<ESM::Region>& record,
|
||||||
|
const QVariant& value, int subRowIndex, int subColIndex) const;
|
||||||
|
|
||||||
|
virtual int getColumnsCount(const Record<ESM::Region>& record) const;
|
||||||
|
|
||||||
|
virtual int getRowsCount(const Record<ESM::Region>& record) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename ESXRecordT>
|
||||||
|
class SpellListAdapter : public NestedColumnAdapter<ESXRecordT>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SpellListAdapter () {}
|
||||||
|
|
||||||
|
virtual void addRow(Record<ESXRecordT>& record, int position) const
|
||||||
|
{
|
||||||
|
ESXRecordT raceOrBthSgn = record.get();
|
||||||
|
|
||||||
|
std::vector<std::string>& spells = raceOrBthSgn.mPowers.mList;
|
||||||
|
|
||||||
|
// blank row
|
||||||
|
std::string spell = "";
|
||||||
|
|
||||||
|
spells.insert(spells.begin()+position, spell);
|
||||||
|
|
||||||
|
record.setModified (raceOrBthSgn);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void removeRow(Record<ESXRecordT>& record, int rowToRemove) const
|
||||||
|
{
|
||||||
|
ESXRecordT raceOrBthSgn = record.get();
|
||||||
|
|
||||||
|
std::vector<std::string>& spells = raceOrBthSgn.mPowers.mList;
|
||||||
|
|
||||||
|
if (rowToRemove < 0 || rowToRemove >= static_cast<int> (spells.size()))
|
||||||
|
throw std::runtime_error ("index out of range");
|
||||||
|
|
||||||
|
spells.erase(spells.begin()+rowToRemove);
|
||||||
|
|
||||||
|
record.setModified (raceOrBthSgn);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void setTable(Record<ESXRecordT>& record, const NestedTableWrapperBase& nestedTable) const
|
||||||
|
{
|
||||||
|
ESXRecordT raceOrBthSgn = record.get();
|
||||||
|
|
||||||
|
raceOrBthSgn.mPowers.mList =
|
||||||
|
static_cast<const NestedTableWrapper<std::vector<std::string> >&>(nestedTable).mNestedTable;
|
||||||
|
|
||||||
|
record.setModified (raceOrBthSgn);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual NestedTableWrapperBase* table(const Record<ESXRecordT>& record) const
|
||||||
|
{
|
||||||
|
// deleted by dtor of NestedTableStoring
|
||||||
|
return new NestedTableWrapper<std::vector<std::string> >(record.get().mPowers.mList);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual QVariant getData(const Record<ESXRecordT>& record, int subRowIndex, int subColIndex) const
|
||||||
|
{
|
||||||
|
ESXRecordT raceOrBthSgn = record.get();
|
||||||
|
|
||||||
|
std::vector<std::string>& spells = raceOrBthSgn.mPowers.mList;
|
||||||
|
|
||||||
|
if (subRowIndex < 0 || subRowIndex >= static_cast<int> (spells.size()))
|
||||||
|
throw std::runtime_error ("index out of range");
|
||||||
|
|
||||||
|
std::string spell = spells[subRowIndex];
|
||||||
|
switch (subColIndex)
|
||||||
|
{
|
||||||
|
case 0: return QString(spell.c_str());
|
||||||
|
default: throw std::runtime_error("Spells subcolumn index out of range");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void setData(Record<ESXRecordT>& record, const QVariant& value,
|
||||||
|
int subRowIndex, int subColIndex) const
|
||||||
|
{
|
||||||
|
ESXRecordT raceOrBthSgn = record.get();
|
||||||
|
|
||||||
|
std::vector<std::string>& spells = raceOrBthSgn.mPowers.mList;
|
||||||
|
|
||||||
|
if (subRowIndex < 0 || subRowIndex >= static_cast<int> (spells.size()))
|
||||||
|
throw std::runtime_error ("index out of range");
|
||||||
|
|
||||||
|
std::string spell = spells[subRowIndex];
|
||||||
|
switch (subColIndex)
|
||||||
|
{
|
||||||
|
case 0: spell = value.toString().toUtf8().constData(); break;
|
||||||
|
default: throw std::runtime_error("Spells subcolumn index out of range");
|
||||||
|
}
|
||||||
|
|
||||||
|
raceOrBthSgn.mPowers.mList[subRowIndex] = spell;
|
||||||
|
|
||||||
|
record.setModified (raceOrBthSgn);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int getColumnsCount(const Record<ESXRecordT>& record) const
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int getRowsCount(const Record<ESXRecordT>& record) const
|
||||||
|
{
|
||||||
|
return static_cast<int>(record.get().mPowers.mList.size());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename ESXRecordT>
|
||||||
|
class EffectsListAdapter : public NestedColumnAdapter<ESXRecordT>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
EffectsListAdapter () {}
|
||||||
|
|
||||||
|
virtual void addRow(Record<ESXRecordT>& record, int position) const
|
||||||
|
{
|
||||||
|
ESXRecordT magic = record.get();
|
||||||
|
|
||||||
|
std::vector<ESM::ENAMstruct>& effectsList = magic.mEffects.mList;
|
||||||
|
|
||||||
|
// blank row
|
||||||
|
ESM::ENAMstruct effect;
|
||||||
|
effect.mEffectID = 0;
|
||||||
|
effect.mSkill = -1;
|
||||||
|
effect.mAttribute = -1;
|
||||||
|
effect.mRange = 0;
|
||||||
|
effect.mArea = 0;
|
||||||
|
effect.mDuration = 0;
|
||||||
|
effect.mMagnMin = 0;
|
||||||
|
effect.mMagnMax = 0;
|
||||||
|
|
||||||
|
effectsList.insert(effectsList.begin()+position, effect);
|
||||||
|
|
||||||
|
record.setModified (magic);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void removeRow(Record<ESXRecordT>& record, int rowToRemove) const
|
||||||
|
{
|
||||||
|
ESXRecordT magic = record.get();
|
||||||
|
|
||||||
|
std::vector<ESM::ENAMstruct>& effectsList = magic.mEffects.mList;
|
||||||
|
|
||||||
|
if (rowToRemove < 0 || rowToRemove >= static_cast<int> (effectsList.size()))
|
||||||
|
throw std::runtime_error ("index out of range");
|
||||||
|
|
||||||
|
effectsList.erase(effectsList.begin()+rowToRemove);
|
||||||
|
|
||||||
|
record.setModified (magic);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void setTable(Record<ESXRecordT>& record, const NestedTableWrapperBase& nestedTable) const
|
||||||
|
{
|
||||||
|
ESXRecordT magic = record.get();
|
||||||
|
|
||||||
|
magic.mEffects.mList =
|
||||||
|
static_cast<const NestedTableWrapper<std::vector<ESM::ENAMstruct> >&>(nestedTable).mNestedTable;
|
||||||
|
|
||||||
|
record.setModified (magic);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual NestedTableWrapperBase* table(const Record<ESXRecordT>& record) const
|
||||||
|
{
|
||||||
|
// deleted by dtor of NestedTableStoring
|
||||||
|
return new NestedTableWrapper<std::vector<ESM::ENAMstruct> >(record.get().mEffects.mList);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual QVariant getData(const Record<ESXRecordT>& record, int subRowIndex, int subColIndex) const
|
||||||
|
{
|
||||||
|
ESXRecordT magic = record.get();
|
||||||
|
|
||||||
|
std::vector<ESM::ENAMstruct>& effectsList = magic.mEffects.mList;
|
||||||
|
|
||||||
|
if (subRowIndex < 0 || subRowIndex >= static_cast<int> (effectsList.size()))
|
||||||
|
throw std::runtime_error ("index out of range");
|
||||||
|
|
||||||
|
ESM::ENAMstruct effect = effectsList[subRowIndex];
|
||||||
|
switch (subColIndex)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
{
|
||||||
|
if (effect.mEffectID >=0 && effect.mEffectID < ESM::MagicEffect::Length)
|
||||||
|
return effect.mRange;
|
||||||
|
else
|
||||||
|
throw std::runtime_error("Magic effects ID unexpected value");
|
||||||
|
}
|
||||||
|
case 1: return effect.mSkill;
|
||||||
|
case 2: return effect.mAttribute;
|
||||||
|
case 3:
|
||||||
|
{
|
||||||
|
if (effect.mRange >=0 && effect.mRange <=2)
|
||||||
|
return effect.mRange;
|
||||||
|
else
|
||||||
|
throw std::runtime_error("Magic effects range unexpected value");
|
||||||
|
}
|
||||||
|
case 4: return effect.mArea;
|
||||||
|
case 5: return effect.mDuration;
|
||||||
|
case 6: return effect.mMagnMin;
|
||||||
|
case 7: return effect.mMagnMax;
|
||||||
|
default: throw std::runtime_error("Magic Effects subcolumn index out of range");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void setData(Record<ESXRecordT>& record, const QVariant& value,
|
||||||
|
int subRowIndex, int subColIndex) const
|
||||||
|
{
|
||||||
|
ESXRecordT magic = record.get();
|
||||||
|
|
||||||
|
std::vector<ESM::ENAMstruct>& effectsList = magic.mEffects.mList;
|
||||||
|
|
||||||
|
if (subRowIndex < 0 || subRowIndex >= static_cast<int> (effectsList.size()))
|
||||||
|
throw std::runtime_error ("index out of range");
|
||||||
|
|
||||||
|
ESM::ENAMstruct effect = effectsList[subRowIndex];
|
||||||
|
switch (subColIndex)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
{
|
||||||
|
effect.mEffectID = static_cast<short>(value.toInt());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
effect.mSkill = static_cast<signed char>(value.toInt());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
effect.mAttribute = static_cast<signed char>(value.toInt());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 3:
|
||||||
|
{
|
||||||
|
effect.mRange = value.toInt();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 4: effect.mArea = value.toInt(); break;
|
||||||
|
case 5: effect.mDuration = value.toInt(); break;
|
||||||
|
case 6: effect.mMagnMin = value.toInt(); break;
|
||||||
|
case 7: effect.mMagnMax = value.toInt(); break;
|
||||||
|
default: throw std::runtime_error("Magic Effects subcolumn index out of range");
|
||||||
|
}
|
||||||
|
|
||||||
|
magic.mEffects.mList[subRowIndex] = effect;
|
||||||
|
|
||||||
|
record.setModified (magic);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int getColumnsCount(const Record<ESXRecordT>& record) const
|
||||||
|
{
|
||||||
|
return 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int getRowsCount(const Record<ESXRecordT>& record) const
|
||||||
|
{
|
||||||
|
return static_cast<int>(record.get().mEffects.mList.size());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class InfoListAdapter : public NestedColumnAdapter<Info>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
InfoListAdapter ();
|
||||||
|
|
||||||
|
virtual void addRow(Record<Info>& record, int position) const;
|
||||||
|
|
||||||
|
virtual void removeRow(Record<Info>& record, int rowToRemove) const;
|
||||||
|
|
||||||
|
virtual void setTable(Record<Info>& record,
|
||||||
|
const NestedTableWrapperBase& nestedTable) const;
|
||||||
|
|
||||||
|
virtual NestedTableWrapperBase* table(const Record<Info>& record) const;
|
||||||
|
|
||||||
|
virtual QVariant getData(const Record<Info>& record,
|
||||||
|
int subRowIndex, int subColIndex) const;
|
||||||
|
|
||||||
|
virtual void setData(Record<Info>& record,
|
||||||
|
const QVariant& value, int subRowIndex, int subColIndex) const;
|
||||||
|
|
||||||
|
virtual int getColumnsCount(const Record<Info>& record) const;
|
||||||
|
|
||||||
|
virtual int getRowsCount(const Record<Info>& record) const;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CSM_WOLRD_NESTEDCOLADAPTERIMP_H
|
@ -0,0 +1,17 @@
|
|||||||
|
#include "nestedcollection.hpp"
|
||||||
|
|
||||||
|
CSMWorld::NestedCollection::NestedCollection()
|
||||||
|
{}
|
||||||
|
|
||||||
|
CSMWorld::NestedCollection::~NestedCollection()
|
||||||
|
{}
|
||||||
|
|
||||||
|
int CSMWorld::NestedCollection::getNestedRowsCount(int row, int column) const
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CSMWorld::NestedCollection::getNestedColumnsCount(int row, int column) const
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
#ifndef CSM_WOLRD_NESTEDCOLLECTION_H
|
||||||
|
#define CSM_WOLRD_NESTEDCOLLECTION_H
|
||||||
|
|
||||||
|
class QVariant;
|
||||||
|
|
||||||
|
namespace CSMWorld
|
||||||
|
{
|
||||||
|
class NestableColumn;
|
||||||
|
struct NestedTableWrapperBase;
|
||||||
|
|
||||||
|
class NestedCollection
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
NestedCollection();
|
||||||
|
virtual ~NestedCollection();
|
||||||
|
|
||||||
|
virtual void addNestedRow(int row, int col, int position) = 0;
|
||||||
|
|
||||||
|
virtual void removeNestedRows(int row, int column, int subRow) = 0;
|
||||||
|
|
||||||
|
virtual QVariant getNestedData(int row, int column, int subRow, int subColumn) const = 0;
|
||||||
|
|
||||||
|
virtual void setNestedData(int row, int column, const QVariant& data, int subRow, int subColumn) = 0;
|
||||||
|
|
||||||
|
virtual NestedTableWrapperBase* nestedTable(int row, int column) const = 0;
|
||||||
|
|
||||||
|
virtual void setNestedTable(int row, int column, const NestedTableWrapperBase& nestedTable) = 0;
|
||||||
|
|
||||||
|
virtual int getNestedRowsCount(int row, int column) const;
|
||||||
|
|
||||||
|
virtual int getNestedColumnsCount(int row, int column) const;
|
||||||
|
|
||||||
|
virtual NestableColumn *getNestableColumn(int column) = 0;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CSM_WOLRD_NESTEDCOLLECTION_H
|
@ -0,0 +1,40 @@
|
|||||||
|
#ifndef CSM_WOLRD_NESTEDCOLUMNADAPTER_H
|
||||||
|
#define CSM_WOLRD_NESTEDCOLUMNADAPTER_H
|
||||||
|
|
||||||
|
class QVariant;
|
||||||
|
|
||||||
|
namespace CSMWorld
|
||||||
|
{
|
||||||
|
struct NestedTableWrapperBase;
|
||||||
|
|
||||||
|
template <typename ESXRecordT>
|
||||||
|
struct Record;
|
||||||
|
|
||||||
|
template<typename ESXRecordT>
|
||||||
|
class NestedColumnAdapter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
NestedColumnAdapter() {}
|
||||||
|
|
||||||
|
virtual ~NestedColumnAdapter() {}
|
||||||
|
|
||||||
|
virtual void addRow(Record<ESXRecordT>& record, int position) const = 0;
|
||||||
|
|
||||||
|
virtual void removeRow(Record<ESXRecordT>& record, int rowToRemove) const = 0;
|
||||||
|
|
||||||
|
virtual void setTable(Record<ESXRecordT>& record, const NestedTableWrapperBase& nestedTable) const = 0;
|
||||||
|
|
||||||
|
virtual NestedTableWrapperBase* table(const Record<ESXRecordT>& record) const = 0;
|
||||||
|
|
||||||
|
virtual QVariant getData(const Record<ESXRecordT>& record, int subRowIndex, int subColIndex) const = 0;
|
||||||
|
|
||||||
|
virtual void setData(Record<ESXRecordT>& record, const QVariant& value, int subRowIndex, int subColIndex) const = 0;
|
||||||
|
|
||||||
|
virtual int getColumnsCount(const Record<ESXRecordT>& record) const = 0;
|
||||||
|
|
||||||
|
virtual int getRowsCount(const Record<ESXRecordT>& record) const = 0;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CSM_WOLRD_NESTEDCOLUMNADAPTER_H
|
@ -0,0 +1,175 @@
|
|||||||
|
#ifndef CSM_WOLRD_NESTEDIDCOLLECTION_H
|
||||||
|
#define CSM_WOLRD_NESTEDIDCOLLECTION_H
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
#include "nestedcollection.hpp"
|
||||||
|
#include "nestedcoladapterimp.hpp"
|
||||||
|
|
||||||
|
namespace ESM
|
||||||
|
{
|
||||||
|
class ESMReader;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace CSMWorld
|
||||||
|
{
|
||||||
|
struct NestedTableWrapperBase;
|
||||||
|
struct Cell;
|
||||||
|
|
||||||
|
template<typename T, typename AT>
|
||||||
|
class IdCollection;
|
||||||
|
|
||||||
|
template<typename ESXRecordT, typename IdAccessorT = IdAccessor<ESXRecordT> >
|
||||||
|
class NestedIdCollection : public IdCollection<ESXRecordT, IdAccessorT>, public NestedCollection
|
||||||
|
{
|
||||||
|
std::map<const ColumnBase*, NestedColumnAdapter<ESXRecordT>* > mAdapters;
|
||||||
|
|
||||||
|
const NestedColumnAdapter<ESXRecordT>& getAdapter(const ColumnBase &column) const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
NestedIdCollection ();
|
||||||
|
~NestedIdCollection();
|
||||||
|
|
||||||
|
virtual void addNestedRow(int row, int column, int position);
|
||||||
|
|
||||||
|
virtual void removeNestedRows(int row, int column, int subRow);
|
||||||
|
|
||||||
|
virtual QVariant getNestedData(int row, int column, int subRow, int subColumn) const;
|
||||||
|
|
||||||
|
virtual void setNestedData(int row, int column, const QVariant& data, int subRow, int subColumn);
|
||||||
|
|
||||||
|
virtual NestedTableWrapperBase* nestedTable(int row, int column) const;
|
||||||
|
|
||||||
|
virtual void setNestedTable(int row, int column, const NestedTableWrapperBase& nestedTable);
|
||||||
|
|
||||||
|
virtual int getNestedRowsCount(int row, int column) const;
|
||||||
|
|
||||||
|
virtual int getNestedColumnsCount(int row, int column) const;
|
||||||
|
|
||||||
|
// this method is inherited from NestedCollection, not from Collection<ESXRecordT>
|
||||||
|
virtual NestableColumn *getNestableColumn(int column);
|
||||||
|
|
||||||
|
void addAdapter(std::pair<const ColumnBase*, NestedColumnAdapter<ESXRecordT>* > adapter);
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename ESXRecordT, typename IdAccessorT>
|
||||||
|
NestedIdCollection<ESXRecordT, IdAccessorT>::NestedIdCollection ()
|
||||||
|
{}
|
||||||
|
|
||||||
|
template<typename ESXRecordT, typename IdAccessorT>
|
||||||
|
NestedIdCollection<ESXRecordT, IdAccessorT>::~NestedIdCollection()
|
||||||
|
{
|
||||||
|
for (typename std::map<const ColumnBase *, NestedColumnAdapter<ESXRecordT>* >::iterator
|
||||||
|
iter (mAdapters.begin()); iter!=mAdapters.end(); ++iter)
|
||||||
|
{
|
||||||
|
delete (*iter).second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ESXRecordT, typename IdAccessorT>
|
||||||
|
void NestedIdCollection<ESXRecordT, IdAccessorT>::addAdapter(std::pair<const ColumnBase*,
|
||||||
|
NestedColumnAdapter<ESXRecordT>* > adapter)
|
||||||
|
{
|
||||||
|
mAdapters.insert(adapter);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ESXRecordT, typename IdAccessorT>
|
||||||
|
const NestedColumnAdapter<ESXRecordT>& NestedIdCollection<ESXRecordT, IdAccessorT>::getAdapter(const ColumnBase &column) const
|
||||||
|
{
|
||||||
|
typename std::map<const ColumnBase *, NestedColumnAdapter<ESXRecordT>* >::const_iterator iter =
|
||||||
|
mAdapters.find (&column);
|
||||||
|
|
||||||
|
if (iter==mAdapters.end())
|
||||||
|
throw std::logic_error("No such column in the nestedidadapter");
|
||||||
|
|
||||||
|
return *iter->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ESXRecordT, typename IdAccessorT>
|
||||||
|
void NestedIdCollection<ESXRecordT, IdAccessorT>::addNestedRow(int row, int column, int position)
|
||||||
|
{
|
||||||
|
Record<ESXRecordT> record;
|
||||||
|
record.assign(Collection<ESXRecordT, IdAccessorT>::getRecord(row));
|
||||||
|
|
||||||
|
getAdapter(Collection<ESXRecordT, IdAccessorT>::getColumn(column)).addRow(record, position);
|
||||||
|
|
||||||
|
Collection<ESXRecordT, IdAccessorT>::setRecord(row, record);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ESXRecordT, typename IdAccessorT>
|
||||||
|
void NestedIdCollection<ESXRecordT, IdAccessorT>::removeNestedRows(int row, int column, int subRow)
|
||||||
|
{
|
||||||
|
Record<ESXRecordT> record;
|
||||||
|
record.assign(Collection<ESXRecordT, IdAccessorT>::getRecord(row));
|
||||||
|
|
||||||
|
getAdapter(Collection<ESXRecordT, IdAccessorT>::getColumn(column)).removeRow(record, subRow);
|
||||||
|
|
||||||
|
Collection<ESXRecordT, IdAccessorT>::setRecord(row, record);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ESXRecordT, typename IdAccessorT>
|
||||||
|
QVariant NestedIdCollection<ESXRecordT, IdAccessorT>::getNestedData (int row,
|
||||||
|
int column, int subRow, int subColumn) const
|
||||||
|
{
|
||||||
|
return getAdapter(Collection<ESXRecordT, IdAccessorT>::getColumn(column)).getData(
|
||||||
|
Collection<ESXRecordT, IdAccessorT>::getRecord(row), subRow, subColumn);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ESXRecordT, typename IdAccessorT>
|
||||||
|
void NestedIdCollection<ESXRecordT, IdAccessorT>::setNestedData(int row,
|
||||||
|
int column, const QVariant& data, int subRow, int subColumn)
|
||||||
|
{
|
||||||
|
Record<ESXRecordT> record;
|
||||||
|
record.assign(Collection<ESXRecordT, IdAccessorT>::getRecord(row));
|
||||||
|
|
||||||
|
getAdapter(Collection<ESXRecordT, IdAccessorT>::getColumn(column)).setData(
|
||||||
|
record, data, subRow, subColumn);
|
||||||
|
|
||||||
|
Collection<ESXRecordT, IdAccessorT>::setRecord(row, record);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ESXRecordT, typename IdAccessorT>
|
||||||
|
CSMWorld::NestedTableWrapperBase* NestedIdCollection<ESXRecordT, IdAccessorT>::nestedTable(int row,
|
||||||
|
int column) const
|
||||||
|
{
|
||||||
|
return getAdapter(Collection<ESXRecordT, IdAccessorT>::getColumn(column)).table(
|
||||||
|
Collection<ESXRecordT, IdAccessorT>::getRecord(row));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ESXRecordT, typename IdAccessorT>
|
||||||
|
void NestedIdCollection<ESXRecordT, IdAccessorT>::setNestedTable(int row,
|
||||||
|
int column, const CSMWorld::NestedTableWrapperBase& nestedTable)
|
||||||
|
{
|
||||||
|
Record<ESXRecordT> record;
|
||||||
|
record.assign(Collection<ESXRecordT, IdAccessorT>::getRecord(row));
|
||||||
|
|
||||||
|
getAdapter(Collection<ESXRecordT, IdAccessorT>::getColumn(column)).setTable(
|
||||||
|
record, nestedTable);
|
||||||
|
|
||||||
|
Collection<ESXRecordT, IdAccessorT>::setRecord(row, record);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ESXRecordT, typename IdAccessorT>
|
||||||
|
int NestedIdCollection<ESXRecordT, IdAccessorT>::getNestedRowsCount(int row, int column) const
|
||||||
|
{
|
||||||
|
return getAdapter(Collection<ESXRecordT, IdAccessorT>::getColumn(column)).getRowsCount(
|
||||||
|
Collection<ESXRecordT, IdAccessorT>::getRecord(row));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ESXRecordT, typename IdAccessorT>
|
||||||
|
int NestedIdCollection<ESXRecordT, IdAccessorT>::getNestedColumnsCount(int row, int column) const
|
||||||
|
{
|
||||||
|
return getAdapter(Collection<ESXRecordT, IdAccessorT>::getColumn(column)).getColumnsCount(
|
||||||
|
Collection<ESXRecordT, IdAccessorT>::getRecord(row));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ESXRecordT, typename IdAccessorT>
|
||||||
|
CSMWorld::NestableColumn *NestedIdCollection<ESXRecordT, IdAccessorT>::getNestableColumn(int column)
|
||||||
|
{
|
||||||
|
return Collection<ESXRecordT, IdAccessorT>::getNestableColumn(column);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CSM_WOLRD_NESTEDIDCOLLECTION_H
|
@ -0,0 +1,110 @@
|
|||||||
|
#include "nestedinfocollection.hpp"
|
||||||
|
|
||||||
|
#include "nestedcoladapterimp.hpp"
|
||||||
|
|
||||||
|
namespace CSMWorld
|
||||||
|
{
|
||||||
|
NestedInfoCollection::NestedInfoCollection ()
|
||||||
|
{}
|
||||||
|
|
||||||
|
NestedInfoCollection::~NestedInfoCollection()
|
||||||
|
{
|
||||||
|
for (std::map<const ColumnBase *, NestedColumnAdapter<Info>* >::iterator
|
||||||
|
iter (mAdapters.begin()); iter!=mAdapters.end(); ++iter)
|
||||||
|
{
|
||||||
|
delete (*iter).second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NestedInfoCollection::addAdapter(std::pair<const ColumnBase*,
|
||||||
|
NestedColumnAdapter<Info>* > adapter)
|
||||||
|
{
|
||||||
|
mAdapters.insert(adapter);
|
||||||
|
}
|
||||||
|
|
||||||
|
const NestedColumnAdapter<Info>& NestedInfoCollection::getAdapter(const ColumnBase &column) const
|
||||||
|
{
|
||||||
|
std::map<const ColumnBase *, NestedColumnAdapter<Info>* >::const_iterator iter =
|
||||||
|
mAdapters.find (&column);
|
||||||
|
|
||||||
|
if (iter==mAdapters.end())
|
||||||
|
throw std::logic_error("No such column in the nestedidadapter");
|
||||||
|
|
||||||
|
return *iter->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NestedInfoCollection::addNestedRow(int row, int column, int position)
|
||||||
|
{
|
||||||
|
Record<Info> record;
|
||||||
|
record.assign(Collection<Info, IdAccessor<Info> >::getRecord(row));
|
||||||
|
|
||||||
|
getAdapter(Collection<Info, IdAccessor<Info> >::getColumn(column)).addRow(record, position);
|
||||||
|
|
||||||
|
Collection<Info, IdAccessor<Info> >::setRecord(row, record);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NestedInfoCollection::removeNestedRows(int row, int column, int subRow)
|
||||||
|
{
|
||||||
|
Record<Info> record;
|
||||||
|
record.assign(Collection<Info, IdAccessor<Info> >::getRecord(row));
|
||||||
|
|
||||||
|
getAdapter(Collection<Info, IdAccessor<Info> >::getColumn(column)).removeRow(record, subRow);
|
||||||
|
|
||||||
|
Collection<Info, IdAccessor<Info> >::setRecord(row, record);
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant NestedInfoCollection::getNestedData (int row,
|
||||||
|
int column, int subRow, int subColumn) const
|
||||||
|
{
|
||||||
|
return getAdapter(Collection<Info, IdAccessor<Info> >::getColumn(column)).getData(
|
||||||
|
Collection<Info, IdAccessor<Info> >::getRecord(row), subRow, subColumn);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NestedInfoCollection::setNestedData(int row,
|
||||||
|
int column, const QVariant& data, int subRow, int subColumn)
|
||||||
|
{
|
||||||
|
Record<Info> record;
|
||||||
|
record.assign(Collection<Info, IdAccessor<Info> >::getRecord(row));
|
||||||
|
|
||||||
|
getAdapter(Collection<Info, IdAccessor<Info> >::getColumn(column)).setData(
|
||||||
|
record, data, subRow, subColumn);
|
||||||
|
|
||||||
|
Collection<Info, IdAccessor<Info> >::setRecord(row, record);
|
||||||
|
}
|
||||||
|
|
||||||
|
CSMWorld::NestedTableWrapperBase* NestedInfoCollection::nestedTable(int row,
|
||||||
|
int column) const
|
||||||
|
{
|
||||||
|
return getAdapter(Collection<Info, IdAccessor<Info> >::getColumn(column)).table(
|
||||||
|
Collection<Info, IdAccessor<Info> >::getRecord(row));
|
||||||
|
}
|
||||||
|
|
||||||
|
void NestedInfoCollection::setNestedTable(int row,
|
||||||
|
int column, const CSMWorld::NestedTableWrapperBase& nestedTable)
|
||||||
|
{
|
||||||
|
Record<Info> record;
|
||||||
|
record.assign(Collection<Info, IdAccessor<Info> >::getRecord(row));
|
||||||
|
|
||||||
|
getAdapter(Collection<Info, IdAccessor<Info> >::getColumn(column)).setTable(
|
||||||
|
record, nestedTable);
|
||||||
|
|
||||||
|
Collection<Info, IdAccessor<Info> >::setRecord(row, record);
|
||||||
|
}
|
||||||
|
|
||||||
|
int NestedInfoCollection::getNestedRowsCount(int row, int column) const
|
||||||
|
{
|
||||||
|
return getAdapter(Collection<Info, IdAccessor<Info> >::getColumn(column)).getRowsCount(
|
||||||
|
Collection<Info, IdAccessor<Info> >::getRecord(row));
|
||||||
|
}
|
||||||
|
|
||||||
|
int NestedInfoCollection::getNestedColumnsCount(int row, int column) const
|
||||||
|
{
|
||||||
|
return getAdapter(Collection<Info, IdAccessor<Info> >::getColumn(column)).getColumnsCount(
|
||||||
|
Collection<Info, IdAccessor<Info> >::getRecord(row));
|
||||||
|
}
|
||||||
|
|
||||||
|
CSMWorld::NestableColumn *NestedInfoCollection::getNestableColumn(int column)
|
||||||
|
{
|
||||||
|
return Collection<Info, IdAccessor<Info> >::getNestableColumn(column);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,50 @@
|
|||||||
|
#ifndef CSM_WOLRD_NESTEDINFOCOLLECTION_H
|
||||||
|
#define CSM_WOLRD_NESTEDINFOCOLLECTION_H
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#include "infocollection.hpp"
|
||||||
|
#include "nestedcollection.hpp"
|
||||||
|
|
||||||
|
namespace CSMWorld
|
||||||
|
{
|
||||||
|
struct NestedTableWrapperBase;
|
||||||
|
|
||||||
|
template<typename ESXRecordT>
|
||||||
|
class NestedColumnAdapter;
|
||||||
|
|
||||||
|
class NestedInfoCollection : public InfoCollection, public NestedCollection
|
||||||
|
{
|
||||||
|
std::map<const ColumnBase*, NestedColumnAdapter<Info>* > mAdapters;
|
||||||
|
|
||||||
|
const NestedColumnAdapter<Info>& getAdapter(const ColumnBase &column) const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
NestedInfoCollection ();
|
||||||
|
~NestedInfoCollection();
|
||||||
|
|
||||||
|
virtual void addNestedRow(int row, int column, int position);
|
||||||
|
|
||||||
|
virtual void removeNestedRows(int row, int column, int subRow);
|
||||||
|
|
||||||
|
virtual QVariant getNestedData(int row, int column, int subRow, int subColumn) const;
|
||||||
|
|
||||||
|
virtual void setNestedData(int row, int column, const QVariant& data, int subRow, int subColumn);
|
||||||
|
|
||||||
|
virtual NestedTableWrapperBase* nestedTable(int row, int column) const;
|
||||||
|
|
||||||
|
virtual void setNestedTable(int row, int column, const NestedTableWrapperBase& nestedTable);
|
||||||
|
|
||||||
|
virtual int getNestedRowsCount(int row, int column) const;
|
||||||
|
|
||||||
|
virtual int getNestedColumnsCount(int row, int column) const;
|
||||||
|
|
||||||
|
// this method is inherited from NestedCollection, not from Collection<Info, IdAccessor<Info> >
|
||||||
|
virtual NestableColumn *getNestableColumn(int column);
|
||||||
|
|
||||||
|
void addAdapter(std::pair<const ColumnBase*, NestedColumnAdapter<Info>* > adapter);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CSM_WOLRD_NESTEDINFOCOLLECTION_H
|
@ -0,0 +1,195 @@
|
|||||||
|
#include "nestedtableproxymodel.hpp"
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include "idtree.hpp"
|
||||||
|
|
||||||
|
CSMWorld::NestedTableProxyModel::NestedTableProxyModel(const QModelIndex& parent,
|
||||||
|
ColumnBase::Display columnId,
|
||||||
|
CSMWorld::IdTree* parentModel)
|
||||||
|
: mParentColumn(parent.column()),
|
||||||
|
mMainModel(parentModel)
|
||||||
|
{
|
||||||
|
const int parentRow = parent.row();
|
||||||
|
|
||||||
|
mId = std::string(parentModel->index(parentRow, 0).data().toString().toUtf8());
|
||||||
|
|
||||||
|
QAbstractProxyModel::setSourceModel(parentModel);
|
||||||
|
|
||||||
|
connect(mMainModel, SIGNAL(rowsAboutToBeInserted(const QModelIndex &, int, int)),
|
||||||
|
this, SLOT(forwardRowsAboutToInserted(const QModelIndex &, int, int)));
|
||||||
|
|
||||||
|
connect(mMainModel, SIGNAL(rowsInserted(const QModelIndex &, int, int)),
|
||||||
|
this, SLOT(forwardRowsInserted(const QModelIndex &, int, int)));
|
||||||
|
|
||||||
|
connect(mMainModel, SIGNAL(rowsAboutToBeRemoved(const QModelIndex &, int, int)),
|
||||||
|
this, SLOT(forwardRowsAboutToRemoved(const QModelIndex &, int, int)));
|
||||||
|
|
||||||
|
connect(mMainModel, SIGNAL(rowsRemoved(const QModelIndex &, int, int)),
|
||||||
|
this, SLOT(forwardRowsRemoved(const QModelIndex &, int, int)));
|
||||||
|
|
||||||
|
connect(mMainModel, SIGNAL(resetStart(const QString&)),
|
||||||
|
this, SLOT(forwardResetStart(const QString&)));
|
||||||
|
|
||||||
|
connect(mMainModel, SIGNAL(resetEnd(const QString&)),
|
||||||
|
this, SLOT(forwardResetEnd(const QString&)));
|
||||||
|
|
||||||
|
connect(mMainModel, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)),
|
||||||
|
this, SLOT(forwardDataChanged(const QModelIndex &, const QModelIndex &)));
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex CSMWorld::NestedTableProxyModel::mapFromSource(const QModelIndex& sourceIndex) const
|
||||||
|
{
|
||||||
|
const QModelIndex& testedParent = mMainModel->parent(sourceIndex);
|
||||||
|
const QModelIndex& parent = mMainModel->getNestedModelIndex (mId, mParentColumn);
|
||||||
|
if (testedParent == parent)
|
||||||
|
{
|
||||||
|
return createIndex(sourceIndex.row(), sourceIndex.column());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return QModelIndex();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex CSMWorld::NestedTableProxyModel::mapToSource(const QModelIndex& proxyIndex) const
|
||||||
|
{
|
||||||
|
const QModelIndex& parent = mMainModel->getNestedModelIndex (mId, mParentColumn);
|
||||||
|
return mMainModel->index(proxyIndex.row(), proxyIndex.column(), parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
int CSMWorld::NestedTableProxyModel::rowCount(const QModelIndex& index) const
|
||||||
|
{
|
||||||
|
assert (!index.isValid());
|
||||||
|
|
||||||
|
return mMainModel->rowCount(mMainModel->getModelIndex(mId, mParentColumn));
|
||||||
|
}
|
||||||
|
|
||||||
|
int CSMWorld::NestedTableProxyModel::columnCount(const QModelIndex& parent) const
|
||||||
|
{
|
||||||
|
assert (!parent.isValid());
|
||||||
|
|
||||||
|
return mMainModel->columnCount(mMainModel->getModelIndex(mId, mParentColumn));
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex CSMWorld::NestedTableProxyModel::index(int row, int column, const QModelIndex& parent) const
|
||||||
|
{
|
||||||
|
assert (!parent.isValid());
|
||||||
|
|
||||||
|
int rows = mMainModel->rowCount(parent);
|
||||||
|
int columns = mMainModel->columnCount(parent);
|
||||||
|
|
||||||
|
if (row < 0 || row >= rows || column < 0 || column >= columns)
|
||||||
|
return QModelIndex();
|
||||||
|
|
||||||
|
return createIndex(row, column);
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex CSMWorld::NestedTableProxyModel::parent(const QModelIndex& index) const
|
||||||
|
{
|
||||||
|
return QModelIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant CSMWorld::NestedTableProxyModel::headerData(int section,
|
||||||
|
Qt::Orientation orientation,
|
||||||
|
int role) const
|
||||||
|
{
|
||||||
|
return mMainModel->nestedHeaderData(mParentColumn, section, orientation, role);
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant CSMWorld::NestedTableProxyModel::data(const QModelIndex& index, int role) const
|
||||||
|
{
|
||||||
|
return mMainModel->data(mapToSource(index), role);
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: Due to mapToSouce(index) the dataChanged() signal resulting from setData() will have the
|
||||||
|
// source model's index values. The indicies need to be converted to the proxy space values.
|
||||||
|
// See forwardDataChanged()
|
||||||
|
bool CSMWorld::NestedTableProxyModel::setData (const QModelIndex & index, const QVariant & value, int role)
|
||||||
|
{
|
||||||
|
return mMainModel->setData(mapToSource(index), value, role);
|
||||||
|
}
|
||||||
|
|
||||||
|
Qt::ItemFlags CSMWorld::NestedTableProxyModel::flags(const QModelIndex& index) const
|
||||||
|
{
|
||||||
|
return mMainModel->flags(mapToSource(index));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string CSMWorld::NestedTableProxyModel::getParentId() const
|
||||||
|
{
|
||||||
|
return mId;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CSMWorld::NestedTableProxyModel::getParentColumn() const
|
||||||
|
{
|
||||||
|
return mParentColumn;
|
||||||
|
}
|
||||||
|
|
||||||
|
CSMWorld::IdTree* CSMWorld::NestedTableProxyModel::model() const
|
||||||
|
{
|
||||||
|
return mMainModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMWorld::NestedTableProxyModel::forwardRowsAboutToInserted(const QModelIndex& parent,
|
||||||
|
int first, int last)
|
||||||
|
{
|
||||||
|
if (indexIsParent(parent))
|
||||||
|
{
|
||||||
|
beginInsertRows(QModelIndex(), first, last);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMWorld::NestedTableProxyModel::forwardRowsInserted(const QModelIndex& parent, int first, int last)
|
||||||
|
{
|
||||||
|
if (indexIsParent(parent))
|
||||||
|
{
|
||||||
|
endInsertRows();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSMWorld::NestedTableProxyModel::indexIsParent(const QModelIndex& index)
|
||||||
|
{
|
||||||
|
return (index.isValid() &&
|
||||||
|
index.column() == mParentColumn &&
|
||||||
|
mMainModel->data(mMainModel->index(index.row(), 0)).toString().toUtf8().constData() == mId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMWorld::NestedTableProxyModel::forwardRowsAboutToRemoved(const QModelIndex& parent,
|
||||||
|
int first, int last)
|
||||||
|
{
|
||||||
|
if (indexIsParent(parent))
|
||||||
|
{
|
||||||
|
beginRemoveRows(QModelIndex(), first, last);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMWorld::NestedTableProxyModel::forwardRowsRemoved(const QModelIndex& parent, int first, int last)
|
||||||
|
{
|
||||||
|
if (indexIsParent(parent))
|
||||||
|
{
|
||||||
|
endRemoveRows();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMWorld::NestedTableProxyModel::forwardResetStart(const QString& id)
|
||||||
|
{
|
||||||
|
if (id.toUtf8() == mId.c_str())
|
||||||
|
beginResetModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMWorld::NestedTableProxyModel::forwardResetEnd(const QString& id)
|
||||||
|
{
|
||||||
|
if (id.toUtf8() == mId.c_str())
|
||||||
|
endResetModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMWorld::NestedTableProxyModel::forwardDataChanged (const QModelIndex& topLeft,
|
||||||
|
const QModelIndex& bottomRight)
|
||||||
|
{
|
||||||
|
const QModelIndex& parent = mMainModel->getNestedModelIndex (mId, mParentColumn);
|
||||||
|
|
||||||
|
if (topLeft.column() <= parent.column() && bottomRight.column() >= parent.column())
|
||||||
|
{
|
||||||
|
emit dataChanged(index(0,0),
|
||||||
|
index(mMainModel->rowCount(parent)-1, mMainModel->columnCount(parent)-1));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,84 @@
|
|||||||
|
#ifndef CSM_WOLRD_NESTEDTABLEPROXYMODEL_H
|
||||||
|
#define CSM_WOLRD_NESTEDTABLEPROXYMODEL_H
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <QAbstractProxyModel>
|
||||||
|
|
||||||
|
#include "universalid.hpp"
|
||||||
|
#include "columns.hpp"
|
||||||
|
#include "columnbase.hpp"
|
||||||
|
|
||||||
|
/*! \brief
|
||||||
|
* Proxy model used to connect view in the dialogue into the nested columns of the main model.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace CSMWorld
|
||||||
|
{
|
||||||
|
class CollectionBase;
|
||||||
|
struct RecordBase;
|
||||||
|
class IdTree;
|
||||||
|
|
||||||
|
class NestedTableProxyModel : public QAbstractProxyModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
const int mParentColumn;
|
||||||
|
IdTree* mMainModel;
|
||||||
|
std::string mId;
|
||||||
|
|
||||||
|
public:
|
||||||
|
NestedTableProxyModel(const QModelIndex& parent,
|
||||||
|
ColumnBase::Display displayType,
|
||||||
|
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::IdTree* model() const;
|
||||||
|
|
||||||
|
virtual QModelIndex mapFromSource(const QModelIndex& sourceIndex) const;
|
||||||
|
|
||||||
|
virtual QModelIndex mapToSource(const QModelIndex& proxyIndex) const;
|
||||||
|
|
||||||
|
virtual int rowCount(const QModelIndex& parent) const;
|
||||||
|
|
||||||
|
virtual int columnCount(const QModelIndex& parent) const;
|
||||||
|
|
||||||
|
virtual QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const;
|
||||||
|
|
||||||
|
virtual QModelIndex parent(const QModelIndex& index) const;
|
||||||
|
|
||||||
|
virtual QVariant headerData (int section, Qt::Orientation orientation, int role) const;
|
||||||
|
|
||||||
|
virtual QVariant data(const QModelIndex & index, 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;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void setupHeaderVectors(ColumnBase::Display columnId);
|
||||||
|
|
||||||
|
bool indexIsParent(const QModelIndex& index);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void forwardRowsAboutToInserted(const QModelIndex & parent, int first, int last);
|
||||||
|
|
||||||
|
void forwardRowsInserted(const QModelIndex & parent, int first, int last);
|
||||||
|
|
||||||
|
void forwardRowsAboutToRemoved(const QModelIndex & parent, int first, int last);
|
||||||
|
|
||||||
|
void forwardRowsRemoved(const QModelIndex & parent, int first, int last);
|
||||||
|
|
||||||
|
void forwardResetStart(const QString& id);
|
||||||
|
|
||||||
|
void forwardResetEnd(const QString& id);
|
||||||
|
|
||||||
|
void forwardDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -0,0 +1,12 @@
|
|||||||
|
#include "nestedtablewrapper.hpp"
|
||||||
|
|
||||||
|
CSMWorld::NestedTableWrapperBase::NestedTableWrapperBase()
|
||||||
|
{}
|
||||||
|
|
||||||
|
CSMWorld::NestedTableWrapperBase::~NestedTableWrapperBase()
|
||||||
|
{}
|
||||||
|
|
||||||
|
int CSMWorld::NestedTableWrapperBase::size() const
|
||||||
|
{
|
||||||
|
return -5;
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
#ifndef CSM_WOLRD_NESTEDTABLEWRAPPER_H
|
||||||
|
#define CSM_WOLRD_NESTEDTABLEWRAPPER_H
|
||||||
|
|
||||||
|
namespace CSMWorld
|
||||||
|
{
|
||||||
|
struct NestedTableWrapperBase
|
||||||
|
{
|
||||||
|
virtual ~NestedTableWrapperBase();
|
||||||
|
|
||||||
|
virtual int size() const;
|
||||||
|
|
||||||
|
NestedTableWrapperBase();
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename NestedTable>
|
||||||
|
struct NestedTableWrapper : public NestedTableWrapperBase
|
||||||
|
{
|
||||||
|
NestedTable mNestedTable;
|
||||||
|
|
||||||
|
NestedTableWrapper(const NestedTable& nestedTable)
|
||||||
|
: mNestedTable(nestedTable) {}
|
||||||
|
|
||||||
|
virtual ~NestedTableWrapper() {}
|
||||||
|
|
||||||
|
virtual int size() const
|
||||||
|
{
|
||||||
|
return mNestedTable.size(); //i hope that this will be enough
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif
|
@ -1,8 +1,18 @@
|
|||||||
|
|
||||||
#include "ref.hpp"
|
#include "ref.hpp"
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
CSMWorld::CellRef::CellRef()
|
CSMWorld::CellRef::CellRef()
|
||||||
{
|
{
|
||||||
mRefNum.mIndex = 0;
|
mRefNum.mIndex = 0;
|
||||||
mRefNum.mContentFile = 0;
|
mRefNum.mContentFile = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::pair<int, int> CSMWorld::CellRef::getCellIndex() const
|
||||||
|
{
|
||||||
|
const int cellSize = 8192;
|
||||||
|
|
||||||
|
return std::make_pair (
|
||||||
|
std::floor (mPos.pos[0]/cellSize), std::floor (mPos.pos[1]/cellSize));
|
||||||
|
}
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
|
|
||||||
#include "refidadapter.hpp"
|
#include "refidadapter.hpp"
|
||||||
|
|
||||||
CSMWorld::RefIdAdapter::RefIdAdapter() {}
|
CSMWorld::RefIdAdapter::RefIdAdapter() {}
|
||||||
|
|
||||||
CSMWorld::RefIdAdapter::~RefIdAdapter() {}
|
CSMWorld::RefIdAdapter::~RefIdAdapter() {}
|
||||||
|
|
||||||
|
CSMWorld::NestedRefIdAdapterBase::NestedRefIdAdapterBase() {}
|
||||||
|
|
||||||
|
CSMWorld::NestedRefIdAdapterBase::~NestedRefIdAdapterBase() {}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,95 @@
|
|||||||
|
#include "nestedtable.hpp"
|
||||||
|
#include "../../model/world/nestedtableproxymodel.hpp"
|
||||||
|
#include "../../model/world/universalid.hpp"
|
||||||
|
#include "../../model/world/commands.hpp"
|
||||||
|
#include "../../model/world/commanddispatcher.hpp"
|
||||||
|
#include "util.hpp"
|
||||||
|
|
||||||
|
#include <QHeaderView>
|
||||||
|
#include <QContextMenuEvent>
|
||||||
|
#include <QMenu>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
CSVWorld::NestedTable::NestedTable(CSMDoc::Document& document,
|
||||||
|
CSMWorld::UniversalId id,
|
||||||
|
CSMWorld::NestedTableProxyModel* model,
|
||||||
|
QWidget* parent)
|
||||||
|
: QTableView(parent),
|
||||||
|
mUndoStack(document.getUndoStack()),
|
||||||
|
mModel(model)
|
||||||
|
{
|
||||||
|
mDispatcher = new CSMWorld::CommandDispatcher (document, id, this);
|
||||||
|
|
||||||
|
setSelectionBehavior (QAbstractItemView::SelectRows);
|
||||||
|
setSelectionMode (QAbstractItemView::ExtendedSelection);
|
||||||
|
|
||||||
|
horizontalHeader()->setResizeMode (QHeaderView::Interactive);
|
||||||
|
verticalHeader()->hide();
|
||||||
|
|
||||||
|
int columns = model->columnCount(QModelIndex());
|
||||||
|
|
||||||
|
for(int i = 0 ; i < columns; ++i)
|
||||||
|
{
|
||||||
|
CSMWorld::ColumnBase::Display display = static_cast<CSMWorld::ColumnBase::Display> (
|
||||||
|
model->headerData (i, Qt::Horizontal, CSMWorld::ColumnBase::Role_Display).toInt());
|
||||||
|
|
||||||
|
CommandDelegate *delegate = CommandDelegateFactoryCollection::get().makeDelegate(display,
|
||||||
|
mDispatcher,
|
||||||
|
document,
|
||||||
|
this);
|
||||||
|
|
||||||
|
setItemDelegateForColumn(i, delegate);
|
||||||
|
}
|
||||||
|
|
||||||
|
setModel(model);
|
||||||
|
|
||||||
|
setAcceptDrops(true);
|
||||||
|
|
||||||
|
mAddNewRowAction = new QAction (tr ("Add new row"), this);
|
||||||
|
|
||||||
|
connect(mAddNewRowAction, SIGNAL(triggered()),
|
||||||
|
this, SLOT(addNewRowActionTriggered()));
|
||||||
|
|
||||||
|
mRemoveRowAction = new QAction (tr ("Remove row"), this);
|
||||||
|
|
||||||
|
connect(mRemoveRowAction, SIGNAL(triggered()),
|
||||||
|
this, SLOT(removeRowActionTriggered()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVWorld::NestedTable::dragEnterEvent(QDragEnterEvent *event)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVWorld::NestedTable::dragMoveEvent(QDragMoveEvent *event)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVWorld::NestedTable::contextMenuEvent (QContextMenuEvent *event)
|
||||||
|
{
|
||||||
|
QModelIndexList selectedRows = selectionModel()->selectedRows();
|
||||||
|
|
||||||
|
QMenu menu(this);
|
||||||
|
|
||||||
|
if (selectionModel()->selectedRows().size() == 1)
|
||||||
|
menu.addAction(mRemoveRowAction);
|
||||||
|
|
||||||
|
menu.addAction(mAddNewRowAction);
|
||||||
|
|
||||||
|
menu.exec (event->globalPos());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVWorld::NestedTable::removeRowActionTriggered()
|
||||||
|
{
|
||||||
|
mUndoStack.push(new CSMWorld::DeleteNestedCommand(*(mModel->model()),
|
||||||
|
mModel->getParentId(),
|
||||||
|
selectionModel()->selectedRows().begin()->row(),
|
||||||
|
mModel->getParentColumn()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVWorld::NestedTable::addNewRowActionTriggered()
|
||||||
|
{
|
||||||
|
mUndoStack.push(new CSMWorld::AddNestedCommand(*(mModel->model()),
|
||||||
|
mModel->getParentId(),
|
||||||
|
selectionModel()->selectedRows().size(),
|
||||||
|
mModel->getParentColumn()));
|
||||||
|
}
|
@ -0,0 +1,56 @@
|
|||||||
|
#ifndef CSV_WORLD_NESTEDTABLE_H
|
||||||
|
#define CSV_WORLD_NESTEDTABLE_H
|
||||||
|
|
||||||
|
#include <QTableView>
|
||||||
|
#include <QtGui/qevent.h>
|
||||||
|
|
||||||
|
class QUndoStack;
|
||||||
|
class QAction;
|
||||||
|
class QContextMenuEvent;
|
||||||
|
|
||||||
|
namespace CSMWorld
|
||||||
|
{
|
||||||
|
class NestedTableProxyModel;
|
||||||
|
class UniversalId;
|
||||||
|
class CommandDispatcher;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace CSMDoc
|
||||||
|
{
|
||||||
|
class Document;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace CSVWorld
|
||||||
|
{
|
||||||
|
class NestedTable : public QTableView
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
QAction *mAddNewRowAction;
|
||||||
|
QAction *mRemoveRowAction;
|
||||||
|
QUndoStack& mUndoStack;
|
||||||
|
CSMWorld::NestedTableProxyModel* mModel;
|
||||||
|
CSMWorld::CommandDispatcher *mDispatcher;
|
||||||
|
|
||||||
|
public:
|
||||||
|
NestedTable(CSMDoc::Document& document,
|
||||||
|
CSMWorld::UniversalId id,
|
||||||
|
CSMWorld::NestedTableProxyModel* model,
|
||||||
|
QWidget* parent = NULL);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void dragEnterEvent(QDragEnterEvent *event);
|
||||||
|
|
||||||
|
void dragMoveEvent(QDragMoveEvent *event);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void contextMenuEvent (QContextMenuEvent *event);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void removeRowActionTriggered();
|
||||||
|
|
||||||
|
void addNewRowActionTriggered();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue