Something went wrong. Try again.
OpenMW is an open implementation of the Morrowind engine
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282#include "idtree.hpp"
#include "nestedtablewrapper.hpp"
#include "collectionbase.hpp"#include "columnbase.hpp"#include "nestedcollection.hpp"
#include <apps/opencs/model/world/columns.hpp>#include <apps/opencs/model/world/idtable.hpp>
#include <stdexcept>
// NOTE: parent class still needs idCollectionCSMWorld::IdTree::IdTree(NestedCollection* nestedCollection, CollectionBase* idCollection, unsigned int features) : IdTable(idCollection, features) , mNestedCollection(nestedCollection){}
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 (index.internalId() != 0) { std::pair<int, int> parentAddress(unfoldIndexAddress(index.internalId())); const NestableColumn* parentColumn = mNestedCollection->getNestableColumn(parentAddress.second);
if (role == ColumnBase::Role_Display) return parentColumn->nestedColumn(index.column()).mDisplayType;
if (role == ColumnBase::Role_ColumnId) return parentColumn->nestedColumn(index.column()).mColumnId;
if (role == Qt::EditRole && !parentColumn->nestedColumn(index.column()).isEditable()) return QVariant();
if (role != Qt::DisplayRole && role != Qt::EditRole) return QVariant();
return mNestedCollection->getNestedData(parentAddress.first, parentAddress.second, index.row(), index.column()); } else { return IdTable::data(index, role); }}
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 parentColumn->nestedColumn(subSection).mFlags;
if (role == ColumnBase::Role_Display) return parentColumn->nestedColumn(subSection).mDisplayType;
if (role == ColumnBase::Role_ColumnId) return parentColumn->nestedColumn(subSection).mColumnId;
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(index, index);
// Modifying a value can also change the Modified status of a record. int stateColumn = searchColumnIndex(Columns::ColumnId_Modification); if (stateColumn != -1) { QModelIndex stateIndex = this->index(index.parent().row(), stateColumn); emit dataChanged(stateIndex, stateIndex); }
return true; } else return false; } return IdTable::setData(index, value, role);}
Qt::ItemFlags CSMWorld::IdTree::flags(const QModelIndex& index) const{ if (!index.isValid()) return Qt::ItemFlags();
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 >= rowCount(parent)) return QModelIndex();
if (column < 0 || column >= columnCount(parent)) 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(ESM::RefId::stringRefId(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>& address(unfoldIndexAddress(id));
if (address.first >= this->rowCount() || address.second >= this->columnCount()) throw std::logic_error("Parent index is not present in the model");
return createIndex(address.first, address.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 std::runtime_error("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 retrieve nested table, but index has no children");
return mNestedCollection->nestedTable(index.row(), index.column());}
int CSMWorld::IdTree::searchNestedColumnIndex(int parentColumn, Columns::ColumnId id){ return mNestedCollection->searchNestedColumnIndex(parentColumn, id);}
int CSMWorld::IdTree::findNestedColumnIndex(int parentColumn, Columns::ColumnId id){ return mNestedCollection->findNestedColumnIndex(parentColumn, id);}