From bfff84ba8f76aed1f511870e76a0cc3dda631f46 Mon Sep 17 00:00:00 2001 From: dteviot Date: Sun, 14 Jun 2015 10:30:55 +1200 Subject: [PATCH 01/11] replaced #include with forward class declaration, as suggested by slaugherfish. --- apps/openmw/mwmechanics/aipackage.hpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/openmw/mwmechanics/aipackage.hpp b/apps/openmw/mwmechanics/aipackage.hpp index 0370072a4..78a2bfd9f 100644 --- a/apps/openmw/mwmechanics/aipackage.hpp +++ b/apps/openmw/mwmechanics/aipackage.hpp @@ -4,8 +4,6 @@ #include "pathfinding.hpp" #include -#include "../mwworld/cellstore.hpp" - #include "obstacle.hpp" #include "aistate.hpp" @@ -16,6 +14,7 @@ namespace MWWorld namespace ESM { + struct Cell; namespace AiSequence { struct AiSequence; From 520fbd63c4a50a56b79a49bd90b8da6f10c2e26a Mon Sep 17 00:00:00 2001 From: dteviot Date: Sun, 14 Jun 2015 15:14:02 +1200 Subject: [PATCH 02/11] simplified pathfinding code. remove mIsPathConstructed. Instead call !mPath.empty(). --- apps/openmw/mwmechanics/pathfinding.cpp | 17 ++--------------- apps/openmw/mwmechanics/pathfinding.hpp | 4 +--- 2 files changed, 3 insertions(+), 18 deletions(-) diff --git a/apps/openmw/mwmechanics/pathfinding.cpp b/apps/openmw/mwmechanics/pathfinding.cpp index 980de1bad..fea993e23 100644 --- a/apps/openmw/mwmechanics/pathfinding.cpp +++ b/apps/openmw/mwmechanics/pathfinding.cpp @@ -114,8 +114,7 @@ namespace MWMechanics } PathFinder::PathFinder() - : mIsPathConstructed(false), - mPathgrid(NULL), + : mPathgrid(NULL), mCell(NULL) { } @@ -124,7 +123,6 @@ namespace MWMechanics { if(!mPath.empty()) mPath.clear(); - mIsPathConstructed = false; } /* @@ -180,7 +178,6 @@ namespace MWMechanics static_cast(endPoint.mX), static_cast(endPoint.mY), static_cast(endPoint.mZ))) { mPath.push_back(endPoint); - mIsPathConstructed = true; return; } } @@ -197,7 +194,6 @@ namespace MWMechanics if(!mPathgrid || mPathgrid->mPoints.empty()) { mPath.push_back(endPoint); - mIsPathConstructed = true; return; } @@ -235,7 +231,6 @@ namespace MWMechanics if(startNode == endNode.first) { mPath.push_back(endPoint); - mIsPathConstructed = true; return; } @@ -243,7 +238,6 @@ namespace MWMechanics if(!mPath.empty()) { - mIsPathConstructed = true; // Add the destination (which may be different to the closest // pathgrid point). However only add if endNode was the closest // point to endPoint. @@ -256,14 +250,8 @@ namespace MWMechanics if(endNode.second) mPath.push_back(endPoint); } - else - mIsPathConstructed = false; } - else - mIsPathConstructed = false; } - else - mIsPathConstructed = false; return; } @@ -271,7 +259,7 @@ namespace MWMechanics float PathFinder::getZAngleToNext(float x, float y) const { // This should never happen (programmers should have an if statement checking - // mIsPathConstructed that prevents this call if otherwise). + // isPathConstructed that prevents this call if otherwise). if(mPath.empty()) return 0.; @@ -293,7 +281,6 @@ namespace MWMechanics mPath.pop_front(); if(mPath.empty()) { - mIsPathConstructed = false; return true; } } diff --git a/apps/openmw/mwmechanics/pathfinding.hpp b/apps/openmw/mwmechanics/pathfinding.hpp index 0f52a6e19..644d79236 100644 --- a/apps/openmw/mwmechanics/pathfinding.hpp +++ b/apps/openmw/mwmechanics/pathfinding.hpp @@ -48,7 +48,7 @@ namespace MWMechanics bool isPathConstructed() const { - return mIsPathConstructed; + return !mPath.empty(); } int getPathSize() const @@ -96,8 +96,6 @@ namespace MWMechanics private: - bool mIsPathConstructed; - std::list mPath; const ESM::Pathgrid *mPathgrid; From d906a9d7d10b0b9d7d16d65b7cf3c727ffe32c29 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Tue, 16 Jun 2015 00:19:51 +0300 Subject: [PATCH 03/11] DataDisplayDelegate doesn't draw a text outside a table cell --- .../opencs/view/world/datadisplaydelegate.cpp | 32 ++++++++++--------- .../opencs/view/world/datadisplaydelegate.hpp | 1 - 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/apps/opencs/view/world/datadisplaydelegate.cpp b/apps/opencs/view/world/datadisplaydelegate.cpp index b9df52bf7..71686d77d 100644 --- a/apps/opencs/view/world/datadisplaydelegate.cpp +++ b/apps/opencs/view/world/datadisplaydelegate.cpp @@ -15,8 +15,6 @@ CSVWorld::DataDisplayDelegate::DataDisplayDelegate(const ValueList &values, mIcons (icons), mIconSize (QSize(16, 16)), mIconLeftOffset(3), mTextLeftOffset(8), mSettingKey (pageName + '/' + settingName) { - mTextAlignment.setAlignment (Qt::AlignLeft | Qt::AlignVCenter ); - buildPixmaps(); QString value = @@ -81,24 +79,28 @@ void CSVWorld::DataDisplayDelegate::paint (QPainter *painter, const QStyleOption void CSVWorld::DataDisplayDelegate::paintIcon (QPainter *painter, const QStyleOptionViewItem &option, int index) const { - //function-level statics QRect iconRect = option.rect; QRect textRect = iconRect; - const QString &text = mValues.at(index).second; - - iconRect.setSize (mIconSize); - iconRect.translate(mIconLeftOffset, (option.rect.height() - iconRect.height())/2); - - if (mDisplayMode == Mode_IconAndText ) + iconRect.setLeft(iconRect.left() + mIconLeftOffset); + iconRect.setRight(option.rect.right()); + if (mDisplayMode == Mode_IconAndText) { - textRect.translate (iconRect.width() + mTextLeftOffset, 0 ); - painter->drawText (textRect, text, mTextAlignment); - } - else - iconRect.translate( (option.rect.width() - iconRect.width()) / 2, 0); + iconRect.setWidth(mIconSize.width()); + textRect.setLeft(iconRect.right() + mTextLeftOffset); + textRect.setRight(option.rect.right()); - painter->drawPixmap (iconRect, mPixmaps.at(index).second); + QString text = option.fontMetrics.elidedText(mValues.at(index).second, + option.textElideMode, + textRect.width()); + QApplication::style()->drawItemText(painter, + textRect, + Qt::AlignLeft | Qt::AlignVCenter, + option.palette, + true, + text); + } + QApplication::style()->drawItemPixmap(painter, iconRect, Qt::AlignCenter, mPixmaps.at(index).second); } void CSVWorld::DataDisplayDelegate::updateUserSetting (const QString &name, diff --git a/apps/opencs/view/world/datadisplaydelegate.hpp b/apps/opencs/view/world/datadisplaydelegate.hpp index f6e4c2688..07fa1fd8d 100755 --- a/apps/opencs/view/world/datadisplaydelegate.hpp +++ b/apps/opencs/view/world/datadisplaydelegate.hpp @@ -30,7 +30,6 @@ namespace CSVWorld private: std::vector > mPixmaps; - QTextOption mTextAlignment; QSize mIconSize; int mIconLeftOffset; int mTextLeftOffset; From 0ffb2bc6bc4527975ccb827a2d953d80761d7566 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Tue, 16 Jun 2015 14:18:47 +0300 Subject: [PATCH 04/11] Proper size hint for EnumDelegate --- apps/opencs/view/world/enumdelegate.cpp | 31 +++++++++++++++++++++++++ apps/opencs/view/world/enumdelegate.hpp | 2 ++ 2 files changed, 33 insertions(+) diff --git a/apps/opencs/view/world/enumdelegate.cpp b/apps/opencs/view/world/enumdelegate.cpp index 4b76bf9d6..b9eca670a 100644 --- a/apps/opencs/view/world/enumdelegate.cpp +++ b/apps/opencs/view/world/enumdelegate.cpp @@ -115,6 +115,37 @@ void CSVWorld::EnumDelegate::paint (QPainter *painter, const QStyleOptionViewIte } } +QSize CSVWorld::EnumDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + if (index.data().isValid()) + { + int value = index.data().toInt(); + + // Calculate the size hint as for a combobox. + // So, the whole text is visible (isn't elided) when the editor is created + QStyleOptionComboBox itemOption; + itemOption.fontMetrics = option.fontMetrics; + itemOption.palette = option.palette; + itemOption.rect = option.rect; + itemOption.state = option.state; + + std::vector >::const_iterator current = mValues.begin(); + std::vector >::const_iterator end = mValues.end(); + for (; current != end; ++current) + { + if (current->first == value) + { + QSize valueSize = QSize(itemOption.fontMetrics.width(current->second), + itemOption.fontMetrics.height()); + itemOption.currentText = current->second; + return QApplication::style()->sizeFromContents(QStyle::CT_ComboBox, + &itemOption, + valueSize); + } + } + } + return option.rect.size(); +} CSVWorld::EnumDelegateFactory::EnumDelegateFactory() {} diff --git a/apps/opencs/view/world/enumdelegate.hpp b/apps/opencs/view/world/enumdelegate.hpp index 82890c791..757dbf0b4 100644 --- a/apps/opencs/view/world/enumdelegate.hpp +++ b/apps/opencs/view/world/enumdelegate.hpp @@ -46,6 +46,8 @@ namespace CSVWorld virtual void paint (QPainter *painter, const QStyleOptionViewItem& option, const QModelIndex& index) const; + virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const; + }; class EnumDelegateFactory : public CommandDelegateFactory From 2c1ca33a207c50e93c3c1527c2326bfb5090dd33 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Tue, 16 Jun 2015 15:39:54 +0300 Subject: [PATCH 05/11] Refactor Enum- and DataDisplayDelegate code --- .../opencs/view/world/datadisplaydelegate.cpp | 11 +-- apps/opencs/view/world/enumdelegate.cpp | 88 +++++++++---------- apps/opencs/view/world/enumdelegate.hpp | 2 + 3 files changed, 45 insertions(+), 56 deletions(-) diff --git a/apps/opencs/view/world/datadisplaydelegate.cpp b/apps/opencs/view/world/datadisplaydelegate.cpp index 71686d77d..5f23d95d9 100644 --- a/apps/opencs/view/world/datadisplaydelegate.cpp +++ b/apps/opencs/view/world/datadisplaydelegate.cpp @@ -62,16 +62,11 @@ void CSVWorld::DataDisplayDelegate::paint (QPainter *painter, const QStyleOption EnumDelegate::paint(painter, option, index); else { - unsigned int i = 0; - - for (; i < mValues.size(); ++i) + int valueIndex = getValueIndex(index); + if (valueIndex != -1) { - if (mValues.at(i).first == index.data().toInt()) - break; + paintIcon(painter, option, valueIndex); } - - if (i < mValues.size() ) - paintIcon (painter, option, i); } painter->restore(); diff --git a/apps/opencs/view/world/enumdelegate.cpp b/apps/opencs/view/world/enumdelegate.cpp index b9eca670a..2190a62c6 100644 --- a/apps/opencs/view/world/enumdelegate.cpp +++ b/apps/opencs/view/world/enumdelegate.cpp @@ -10,6 +10,24 @@ #include "../../model/world/commands.hpp" +int CSVWorld::EnumDelegate::getValueIndex(const QModelIndex &index, int role) const +{ + if (index.isValid() && index.data(role).isValid()) + { + int value = index.data(role).toInt(); + + int size = static_cast(mValues.size()); + for (int i = 0; i < size; ++i) + { + if (value == mValues.at(i).first) + { + return i; + } + } + } + return -1; +} + void CSVWorld::EnumDelegate::setModelDataImp (QWidget *editor, QAbstractItemModel *model, const QModelIndex& index) const { @@ -67,60 +85,43 @@ QWidget *CSVWorld::EnumDelegate::createEditor(QWidget *parent, const QStyleOptio void CSVWorld::EnumDelegate::setEditorData (QWidget *editor, const QModelIndex& index, bool tryDisplay) const { - if (QComboBox *comboBox = dynamic_cast (editor)) + if (QComboBox *comboBox = dynamic_cast(editor)) { - QVariant data = index.data (Qt::EditRole); - - if (tryDisplay && !data.isValid()) + int role = Qt::EditRole; + if (tryDisplay && !index.data(role).isValid()) { - data = index.data (Qt::DisplayRole); - if (!data.isValid()) + role = Qt::DisplayRole; + if (!index.data(role).isValid()) { return; } } - int value = data.toInt(); - - std::size_t size = mValues.size(); - - for (std::size_t i=0; isetCurrentIndex (i); - break; - } + int valueIndex = getValueIndex(index, role); + if (valueIndex != -1) + { + comboBox->setCurrentIndex(valueIndex); + } } } void CSVWorld::EnumDelegate::paint (QPainter *painter, const QStyleOptionViewItem& option, const QModelIndex& index) const { - if (index.data().isValid()) + int valueIndex = getValueIndex(index); + if (valueIndex != -1) { - QStyleOptionViewItemV4 option2 (option); - - int value = index.data().toInt(); - - for (std::vector >::const_iterator iter (mValues.begin()); - iter!=mValues.end(); ++iter) - if (iter->first==value) - { - option2.text = iter->second; - - QApplication::style()->drawControl (QStyle::CE_ItemViewItem, &option2, painter); - - break; - } + QStyleOptionViewItemV4 itemOption(option); + itemOption.text = mValues.at(valueIndex).second; + QApplication::style()->drawControl(QStyle::CE_ItemViewItem, &itemOption, painter); } } QSize CSVWorld::EnumDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const { - if (index.data().isValid()) + int valueIndex = getValueIndex(index); + if (valueIndex != -1) { - int value = index.data().toInt(); - // Calculate the size hint as for a combobox. // So, the whole text is visible (isn't elided) when the editor is created QStyleOptionComboBox itemOption; @@ -129,20 +130,11 @@ QSize CSVWorld::EnumDelegate::sizeHint(const QStyleOptionViewItem &option, const itemOption.rect = option.rect; itemOption.state = option.state; - std::vector >::const_iterator current = mValues.begin(); - std::vector >::const_iterator end = mValues.end(); - for (; current != end; ++current) - { - if (current->first == value) - { - QSize valueSize = QSize(itemOption.fontMetrics.width(current->second), - itemOption.fontMetrics.height()); - itemOption.currentText = current->second; - return QApplication::style()->sizeFromContents(QStyle::CT_ComboBox, - &itemOption, - valueSize); - } - } + const QString &valueText = mValues.at(valueIndex).second; + QSize valueSize = QSize(itemOption.fontMetrics.width(valueText), itemOption.fontMetrics.height()); + + itemOption.currentText = valueText; + return QApplication::style()->sizeFromContents(QStyle::CT_ComboBox, &itemOption, valueSize); } return option.rect.size(); } diff --git a/apps/opencs/view/world/enumdelegate.hpp b/apps/opencs/view/world/enumdelegate.hpp index 757dbf0b4..a31945427 100644 --- a/apps/opencs/view/world/enumdelegate.hpp +++ b/apps/opencs/view/world/enumdelegate.hpp @@ -19,6 +19,8 @@ namespace CSVWorld std::vector > mValues; + int getValueIndex(const QModelIndex &index, int role = Qt::DisplayRole) const; + private: virtual void setModelDataImp (QWidget *editor, QAbstractItemModel *model, From 6cfee630aaa24edff56efa9fc1b124272c2e1f92 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Tue, 16 Jun 2015 21:25:06 +0300 Subject: [PATCH 06/11] Proper size hint for DataDisplayDelegate --- .../opencs/view/world/datadisplaydelegate.cpp | 39 ++++++++++++++----- .../opencs/view/world/datadisplaydelegate.hpp | 7 ++-- 2 files changed, 33 insertions(+), 13 deletions(-) diff --git a/apps/opencs/view/world/datadisplaydelegate.cpp b/apps/opencs/view/world/datadisplaydelegate.cpp index 5f23d95d9..77ed33daa 100644 --- a/apps/opencs/view/world/datadisplaydelegate.cpp +++ b/apps/opencs/view/world/datadisplaydelegate.cpp @@ -12,7 +12,8 @@ CSVWorld::DataDisplayDelegate::DataDisplayDelegate(const ValueList &values, const QString &settingName, QObject *parent) : EnumDelegate (values, dispatcher, document, parent), mDisplayMode (Mode_TextOnly), - mIcons (icons), mIconSize (QSize(16, 16)), mIconLeftOffset(3), + mIcons (icons), mIconSize (QSize(16, 16)), + mHorizontalMargin(QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1), mTextLeftOffset(8), mSettingKey (pageName + '/' + settingName) { buildPixmaps(); @@ -43,16 +44,36 @@ void CSVWorld::DataDisplayDelegate::setIconSize(const QSize& size) buildPixmaps(); } -void CSVWorld::DataDisplayDelegate::setIconLeftOffset(int offset) -{ - mIconLeftOffset = offset; -} - void CSVWorld::DataDisplayDelegate::setTextLeftOffset(int offset) { mTextLeftOffset = offset; } +QSize CSVWorld::DataDisplayDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + QSize size = EnumDelegate::sizeHint(option, index); + + int valueIndex = getValueIndex(index); + if (valueIndex != -1) + { + if (mDisplayMode == Mode_IconOnly) + { + size.setWidth(mIconSize.width() + 2 * mHorizontalMargin); + } + else if (mDisplayMode == Mode_IconAndText) + { + int valueWidth = option.fontMetrics.width(mValues.at(valueIndex).second); + size.setWidth(size.width() + mIconSize.width() + mTextLeftOffset); + } + + if (mDisplayMode != Mode_TextOnly) + { + size.setHeight(qMax(size.height(), mIconSize.height())); + } + } + return size; +} + void CSVWorld::DataDisplayDelegate::paint (QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { painter->save(); @@ -77,13 +98,13 @@ void CSVWorld::DataDisplayDelegate::paintIcon (QPainter *painter, const QStyleOp QRect iconRect = option.rect; QRect textRect = iconRect; - iconRect.setLeft(iconRect.left() + mIconLeftOffset); - iconRect.setRight(option.rect.right()); + iconRect.setLeft(iconRect.left() + mHorizontalMargin); + iconRect.setRight(option.rect.right() - mHorizontalMargin); if (mDisplayMode == Mode_IconAndText) { iconRect.setWidth(mIconSize.width()); textRect.setLeft(iconRect.right() + mTextLeftOffset); - textRect.setRight(option.rect.right()); + textRect.setRight(option.rect.right() - mHorizontalMargin); QString text = option.fontMetrics.elidedText(mValues.at(index).second, option.textElideMode, diff --git a/apps/opencs/view/world/datadisplaydelegate.hpp b/apps/opencs/view/world/datadisplaydelegate.hpp index 07fa1fd8d..e565a3469 100755 --- a/apps/opencs/view/world/datadisplaydelegate.hpp +++ b/apps/opencs/view/world/datadisplaydelegate.hpp @@ -31,7 +31,7 @@ namespace CSVWorld std::vector > mPixmaps; QSize mIconSize; - int mIconLeftOffset; + int mHorizontalMargin; int mTextLeftOffset; QString mSettingKey; @@ -45,12 +45,11 @@ namespace CSVWorld virtual void paint (QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; + virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const; + /// pass a QSize defining height / width of icon. Default is QSize (16,16). void setIconSize (const QSize& icon); - /// offset the horizontal position of the icon from the left edge of the cell. Default is 3 pixels. - void setIconLeftOffset (int offset); - /// offset the horizontal position of the text from the right edge of the icon. Default is 8 pixels. void setTextLeftOffset (int offset); From 1e368de28938723a2102b99c8ba7c3e1d81235e1 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Tue, 16 Jun 2015 21:47:27 +0300 Subject: [PATCH 07/11] Adjust columns of nested tables when a dialog subview is opened --- apps/opencs/view/world/dialoguesubview.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/opencs/view/world/dialoguesubview.cpp b/apps/opencs/view/world/dialoguesubview.cpp index 66e8fcb7a..fa3a3e27a 100644 --- a/apps/opencs/view/world/dialoguesubview.cpp +++ b/apps/opencs/view/world/dialoguesubview.cpp @@ -469,8 +469,7 @@ void CSVWorld::EditWidget::remake(int row) mTable->data (mTable->index (row, idColumn)).toString().toUtf8().constData()); NestedTable* table = new NestedTable(mDocument, id, mNestedModels.back(), this); - // FIXME: does not work well when enum delegates are used - //table->resizeColumnsToContents(); + table->resizeColumnsToContents(); if(mTable->index(row, i).data().type() == QVariant::UserType) { From 2e40b68862256d63803f32eeba579b624adfdaa2 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Wed, 17 Jun 2015 22:47:39 +0300 Subject: [PATCH 08/11] Add a custom proxy model for Info tables --- apps/opencs/CMakeLists.txt | 2 +- .../model/world/infotableproxymodel.cpp | 40 +++++++++++++++++++ .../model/world/infotableproxymodel.hpp | 29 ++++++++++++++ 3 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 apps/opencs/model/world/infotableproxymodel.cpp create mode 100644 apps/opencs/model/world/infotableproxymodel.hpp 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..1377ac20e --- /dev/null +++ b/apps/opencs/model/world/infotableproxymodel.cpp @@ -0,0 +1,40 @@ +#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); +} + +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); + QVariant info = mSourceModel->data(mSourceModel->index(currentRow, column)); + while (--currentRow >= 0 && + mSourceModel->data(mSourceModel->index(currentRow, column)) == info); + return currentRow + 1; +} diff --git a/apps/opencs/model/world/infotableproxymodel.hpp b/apps/opencs/model/world/infotableproxymodel.hpp new file mode 100644 index 000000000..a90607d34 --- /dev/null +++ b/apps/opencs/model/world/infotableproxymodel.hpp @@ -0,0 +1,29 @@ +#ifndef CSM_WORLD_INFOTABLEPROXYMODEL_HPP +#define CSM_WORLD_INFOTABLEPROXYMODEL_HPP + +#include "idtableproxymodel.hpp" +#include "universalid.hpp" + +namespace CSMWorld +{ + class IdTableBase; + + class InfoTableProxyModel : public IdTableProxyModel + { + UniversalId::Type mType; + IdTableBase *mSourceModel; + + 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; + }; +} + +#endif From a6624ca576f6fd8b63097d0df99bdace6e244a7b Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Wed, 17 Jun 2015 23:46:51 +0300 Subject: [PATCH 09/11] Cache topic/journal first rows in InfoTableProxyModel --- .../model/world/infotableproxymodel.cpp | 22 +++++++++++++++++-- .../model/world/infotableproxymodel.hpp | 9 ++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/apps/opencs/model/world/infotableproxymodel.cpp b/apps/opencs/model/world/infotableproxymodel.cpp index 1377ac20e..7522e492b 100644 --- a/apps/opencs/model/world/infotableproxymodel.cpp +++ b/apps/opencs/model/world/infotableproxymodel.cpp @@ -15,6 +15,11 @@ void CSMWorld::InfoTableProxyModel::setSourceModel(QAbstractItemModel *sourceMod { 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 @@ -33,8 +38,21 @@ int CSMWorld::InfoTableProxyModel::getFirstInfoRow(int currentRow) const } int column = mSourceModel->findColumnIndex(columnId); - QVariant info = mSourceModel->data(mSourceModel->index(currentRow, column)); - while (--currentRow >= 0 && + 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 index a90607d34..322831626 100644 --- a/apps/opencs/model/world/infotableproxymodel.hpp +++ b/apps/opencs/model/world/infotableproxymodel.hpp @@ -1,6 +1,8 @@ #ifndef CSM_WORLD_INFOTABLEPROXYMODEL_HPP #define CSM_WORLD_INFOTABLEPROXYMODEL_HPP +#include + #include "idtableproxymodel.hpp" #include "universalid.hpp" @@ -10,9 +12,13 @@ namespace CSMWorld 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 @@ -23,6 +29,9 @@ namespace CSMWorld protected: virtual bool lessThan(const QModelIndex &left, const QModelIndex &right) const; + + private slots: + void modelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight); }; } From c60fed89ace024cdfc086fe74a471cab1c436ac3 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Wed, 17 Jun 2015 23:50:18 +0300 Subject: [PATCH 10/11] Enable sorting for Info tables --- apps/opencs/view/world/subviews.cpp | 4 ++-- apps/opencs/view/world/table.cpp | 12 +++++++++++- 2 files changed, 13 insertions(+), 3 deletions(-) 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); From 63d46f7e6627385f1aa18527865e5befd4534622 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 18 Jun 2015 10:26:35 +0200 Subject: [PATCH 11/11] removed an unused variable --- apps/opencs/view/world/datadisplaydelegate.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/opencs/view/world/datadisplaydelegate.cpp b/apps/opencs/view/world/datadisplaydelegate.cpp index 77ed33daa..72f45a18c 100644 --- a/apps/opencs/view/world/datadisplaydelegate.cpp +++ b/apps/opencs/view/world/datadisplaydelegate.cpp @@ -62,7 +62,6 @@ QSize CSVWorld::DataDisplayDelegate::sizeHint(const QStyleOptionViewItem &option } else if (mDisplayMode == Mode_IconAndText) { - int valueWidth = option.fontMetrics.width(mValues.at(valueIndex).second); size.setWidth(size.width() + mIconSize.width() + mTextLeftOffset); }