diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index bf39b36c1..d49541590 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -18,7 +18,7 @@ opencs_hdrs_noqt (model/doc opencs_units (model/world - idtable idtableproxymodel regionmap data commanddispatcher idtablebase resourcetable nestedtableproxymodel idtree + idtable idtableproxymodel regionmap data commanddispatcher idtablebase resourcetable nestedtableproxymodel idtree infotableproxymodel ) diff --git a/apps/opencs/model/world/infotableproxymodel.cpp b/apps/opencs/model/world/infotableproxymodel.cpp new file mode 100644 index 000000000..7522e492b --- /dev/null +++ b/apps/opencs/model/world/infotableproxymodel.cpp @@ -0,0 +1,58 @@ +#include "infotableproxymodel.hpp" + +#include "idtablebase.hpp" +#include "columns.hpp" + +CSMWorld::InfoTableProxyModel::InfoTableProxyModel(CSMWorld::UniversalId::Type type, QObject *parent) + : IdTableProxyModel(parent), + mType(type), + mSourceModel(NULL) +{ + Q_ASSERT(type == UniversalId::Type_TopicInfos || type == UniversalId::Type_JournalInfos); +} + +void CSMWorld::InfoTableProxyModel::setSourceModel(QAbstractItemModel *sourceModel) +{ + IdTableProxyModel::setSourceModel(sourceModel); + mSourceModel = dynamic_cast(sourceModel); + connect(mSourceModel, + SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), + this, + SLOT(modelDataChanged(const QModelIndex &, const QModelIndex &))); + mFirstRowCache.clear(); +} + +bool CSMWorld::InfoTableProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const +{ + QModelIndex first = mSourceModel->index(getFirstInfoRow(left.row()), left.column()); + QModelIndex second = mSourceModel->index(getFirstInfoRow(right.row()), right.column()); + return IdTableProxyModel::lessThan(first, second); +} + +int CSMWorld::InfoTableProxyModel::getFirstInfoRow(int currentRow) const +{ + Columns::ColumnId columnId = Columns::ColumnId_Topic; + if (mType == UniversalId::Type_JournalInfos) + { + columnId = Columns::ColumnId_Journal; + } + + int column = mSourceModel->findColumnIndex(columnId); + QString info = mSourceModel->data(mSourceModel->index(currentRow, column)).toString(); + + if (mFirstRowCache.contains(info)) + { + return mFirstRowCache[info]; + } + + while (--currentRow >= 0 && + mSourceModel->data(mSourceModel->index(currentRow, column)) == info); + + mFirstRowCache[info] = currentRow + 1; + return currentRow + 1; +} + +void CSMWorld::InfoTableProxyModel::modelDataChanged(const QModelIndex &/*topLeft*/, const QModelIndex &/*bottomRight*/) +{ + mFirstRowCache.clear(); +} diff --git a/apps/opencs/model/world/infotableproxymodel.hpp b/apps/opencs/model/world/infotableproxymodel.hpp new file mode 100644 index 000000000..322831626 --- /dev/null +++ b/apps/opencs/model/world/infotableproxymodel.hpp @@ -0,0 +1,38 @@ +#ifndef CSM_WORLD_INFOTABLEPROXYMODEL_HPP +#define CSM_WORLD_INFOTABLEPROXYMODEL_HPP + +#include + +#include "idtableproxymodel.hpp" +#include "universalid.hpp" + +namespace CSMWorld +{ + class IdTableBase; + + class InfoTableProxyModel : public IdTableProxyModel + { + Q_OBJECT + + UniversalId::Type mType; + IdTableBase *mSourceModel; + + mutable QHash mFirstRowCache; + + int getFirstInfoRow(int currentRow) const; + ///< Finds the first row with the same topic (journal entry) as in \a currentRow + + public: + InfoTableProxyModel(UniversalId::Type type, QObject *parent = 0); + + void setSourceModel(QAbstractItemModel *sourceModel); + + protected: + virtual bool lessThan(const QModelIndex &left, const QModelIndex &right) const; + + private slots: + void modelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight); + }; +} + +#endif diff --git a/apps/opencs/view/world/subviews.cpp b/apps/opencs/view/world/subviews.cpp index cd9b37a64..e81da23e1 100644 --- a/apps/opencs/view/world/subviews.cpp +++ b/apps/opencs/view/world/subviews.cpp @@ -68,10 +68,10 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) new CSVDoc::SubViewFactoryWithCreator); manager.add (CSMWorld::UniversalId::Type_TopicInfos, - new CSVDoc::SubViewFactoryWithCreator > (false)); + new CSVDoc::SubViewFactoryWithCreator >); manager.add (CSMWorld::UniversalId::Type_JournalInfos, - new CSVDoc::SubViewFactoryWithCreator > (false)); + new CSVDoc::SubViewFactoryWithCreator >); // Subviews for resources tables manager.add (CSMWorld::UniversalId::Type_Meshes, diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp index b4efbd3c8..072b645c4 100644 --- a/apps/opencs/view/world/table.cpp +++ b/apps/opencs/view/world/table.cpp @@ -13,6 +13,7 @@ #include "../../model/world/data.hpp" #include "../../model/world/commands.hpp" +#include "../../model/world/infotableproxymodel.hpp" #include "../../model/world/idtableproxymodel.hpp" #include "../../model/world/idtablebase.hpp" #include "../../model/world/idtable.hpp" @@ -276,7 +277,16 @@ CSVWorld::Table::Table (const CSMWorld::UniversalId& id, mModel = &dynamic_cast (*mDocument.getData().getTableModel (id)); - mProxyModel = new CSMWorld::IdTableProxyModel (this); + bool isInfoTable = id.getType() == CSMWorld::UniversalId::Type_TopicInfos || + id.getType() == CSMWorld::UniversalId::Type_JournalInfos; + if (isInfoTable) + { + mProxyModel = new CSMWorld::InfoTableProxyModel(id.getType(), this); + } + else + { + mProxyModel = new CSMWorld::IdTableProxyModel (this); + } mProxyModel->setSourceModel (mModel); mDispatcher = new CSMWorld::CommandDispatcher (document, id, this);