From 4b57f6c82153ece3ce0e2f8ca90ef94dc49c5236 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sat, 16 May 2015 08:05:12 +1000 Subject: [PATCH 1/6] Modifying an object instance (e.g. 3D edit) triggers the instances table to scroll to the corresponding record. Should resolve Feature #2554. --- apps/opencs/model/settings/usersettings.cpp | 5 +++++ apps/opencs/view/world/table.cpp | 25 ++++++++++++++++----- apps/opencs/view/world/table.hpp | 4 +++- 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/apps/opencs/model/settings/usersettings.cpp b/apps/opencs/model/settings/usersettings.cpp index 41ce593b75..fe9aa9d02d 100644 --- a/apps/opencs/model/settings/usersettings.cpp +++ b/apps/opencs/model/settings/usersettings.cpp @@ -214,6 +214,11 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() "Jump to the added or cloned record."); jumpToAdded->setDefaultValue (defaultValue); jumpToAdded->setDeclaredValues (jumpValues); + + Setting *jumpToModified = createSetting (Type_CheckBox, "jump-to-modified", "Jump to modified Record"); + jumpToModified->setDefaultValue ("true"); + jumpToModified->setToolTip ("Whether to jump to the modified record. This setting effects the instances table only." + "\nCan be useful in finding the moved or modified object instance while 3D editing."); } declareSection ("search", "Search & Replace"); diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp index 86daf8af7b..c54f2e24bf 100644 --- a/apps/opencs/view/world/table.cpp +++ b/apps/opencs/view/world/table.cpp @@ -370,10 +370,14 @@ CSVWorld::Table::Table (const CSMWorld::UniversalId& id, connect (mProxyModel, SIGNAL (rowsInserted (const QModelIndex&, int, int)), this, SLOT (rowsInsertedEvent(const QModelIndex&, int, int))); - /// \note This signal could instead be connected to a slot that filters out changes not affecting - /// the records status column (for permanence reasons) - connect (mProxyModel, SIGNAL (dataChanged (const QModelIndex&, const QModelIndex&)), - this, SLOT (tableSizeUpdate())); + if (id == CSMWorld::UniversalId::Type_References) + connect (mProxyModel, SIGNAL (dataChanged (const QModelIndex&, const QModelIndex&)), + this, SLOT (dataChangedEvent(const QModelIndex&, const QModelIndex&))); + else + /// \note This signal could instead be connected to a slot that filters out changes not affecting + /// the records status column (for permanence reasons) + connect (mProxyModel, SIGNAL (dataChanged (const QModelIndex&, const QModelIndex&)), + this, SLOT (tableSizeUpdate())); connect (selectionModel(), SIGNAL (selectionChanged (const QItemSelection&, const QItemSelection&)), this, SLOT (selectionSizeUpdate ())); @@ -640,7 +644,7 @@ void CSVWorld::Table::tableSizeUpdate() case CSMWorld::RecordBase::State_BaseOnly: ++size; break; case CSMWorld::RecordBase::State_Modified: ++size; ++modified; break; case CSMWorld::RecordBase::State_ModifiedOnly: ++size; ++modified; break; - case CSMWorld::RecordBase:: State_Deleted: ++deleted; ++modified; break; + case CSMWorld::RecordBase::State_Deleted: ++deleted; ++modified; break; } } } @@ -743,6 +747,7 @@ std::vector< CSMWorld::UniversalId > CSVWorld::Table::getDraggedRecords() const void CSVWorld::Table::rowsInsertedEvent(const QModelIndex& parent, int start, int end) { tableSizeUpdate(); + if(mJumpToAddedRecord) { selectRow(end); @@ -751,3 +756,13 @@ void CSVWorld::Table::rowsInsertedEvent(const QModelIndex& parent, int start, in clearSelection(); } } + +void CSVWorld::Table::dataChangedEvent(const QModelIndex &topLeft, const QModelIndex &bottomRight) +{ + tableSizeUpdate(); + + // this event is assumed to be infreqent, don't bother keeping a member variable + CSMSettings::UserSettings &settings = CSMSettings::UserSettings::instance(); + if (settings.setting("table-input/jump-to-modified", "true") == "true") + selectRow(bottomRight.row()); +} diff --git a/apps/opencs/view/world/table.hpp b/apps/opencs/view/world/table.hpp index becb21f65d..f1d87d79a7 100644 --- a/apps/opencs/view/world/table.hpp +++ b/apps/opencs/view/world/table.hpp @@ -142,7 +142,9 @@ namespace CSVWorld void updateUserSetting (const QString &name, const QStringList &list); - void rowsInsertedEvent(const QModelIndex& parent, int start, int end); + void rowsInsertedEvent(const QModelIndex &parent, int start, int end); + + void dataChangedEvent(const QModelIndex &topLeft, const QModelIndex &bottomRight); }; } From 85a20be3213ae1eda8799ca704dddbb041d7d011 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sat, 30 May 2015 13:34:42 +1000 Subject: [PATCH 2/6] Add a per table subview options section and a checkbox option to scroll the table to the modified record (from another subview). - Always start disabled, needs to be manually set per table - There is no user preference setting, the options are active during the editing session only --- apps/opencs/model/settings/usersettings.cpp | 5 -- apps/opencs/view/world/table.cpp | 26 +++++----- apps/opencs/view/world/table.hpp | 3 ++ apps/opencs/view/world/tablesubview.cpp | 54 +++++++++++++++++++-- apps/opencs/view/world/tablesubview.hpp | 4 ++ 5 files changed, 70 insertions(+), 22 deletions(-) diff --git a/apps/opencs/model/settings/usersettings.cpp b/apps/opencs/model/settings/usersettings.cpp index 3516064bcb..ea002c5edd 100644 --- a/apps/opencs/model/settings/usersettings.cpp +++ b/apps/opencs/model/settings/usersettings.cpp @@ -232,11 +232,6 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() "Jump to the added or cloned record."); jumpToAdded->setDefaultValue (defaultValue); jumpToAdded->setDeclaredValues (jumpValues); - - Setting *jumpToModified = createSetting (Type_CheckBox, "jump-to-modified", "Jump to modified Record"); - jumpToModified->setDefaultValue ("true"); - jumpToModified->setToolTip ("Whether to jump to the modified record. This setting effects the instances table only." - "\nCan be useful in finding the moved or modified object instance while 3D editing."); } declareSection ("search", "Search & Replace"); diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp index 7fc8706a67..25162a67f7 100644 --- a/apps/opencs/view/world/table.cpp +++ b/apps/opencs/view/world/table.cpp @@ -254,7 +254,7 @@ void CSVWorld::Table::mouseDoubleClickEvent (QMouseEvent *event) CSVWorld::Table::Table (const CSMWorld::UniversalId& id, bool createAndDelete, bool sorting, CSMDoc::Document& document) : DragRecordTable(document), mCreateAction (0), - mCloneAction(0),mRecordStatusDisplay (0) + mCloneAction(0),mRecordStatusDisplay (0), mAutoJump (false) { CSMSettings::UserSettings &settings = CSMSettings::UserSettings::instance(); QString jumpSetting = settings.settingValue ("table-input/jump-to-added"); @@ -370,14 +370,10 @@ CSVWorld::Table::Table (const CSMWorld::UniversalId& id, connect (mProxyModel, SIGNAL (rowsInserted (const QModelIndex&, int, int)), this, SLOT (rowsInsertedEvent(const QModelIndex&, int, int))); - if (id == CSMWorld::UniversalId::Type_References) - connect (mProxyModel, SIGNAL (dataChanged (const QModelIndex&, const QModelIndex&)), - this, SLOT (dataChangedEvent(const QModelIndex&, const QModelIndex&))); - else - /// \note This signal could instead be connected to a slot that filters out changes not affecting - /// the records status column (for permanence reasons) - connect (mProxyModel, SIGNAL (dataChanged (const QModelIndex&, const QModelIndex&)), - this, SLOT (tableSizeUpdate())); + /// \note This signal could instead be connected to a slot that filters out changes not affecting + /// the records status column (for permanence reasons) + connect (mProxyModel, SIGNAL (dataChanged (const QModelIndex&, const QModelIndex&)), + this, SLOT (dataChangedEvent(const QModelIndex&, const QModelIndex&))); connect (selectionModel(), SIGNAL (selectionChanged (const QItemSelection&, const QItemSelection&)), this, SLOT (selectionSizeUpdate ())); @@ -765,8 +761,14 @@ void CSVWorld::Table::dataChangedEvent(const QModelIndex &topLeft, const QModelI { tableSizeUpdate(); - // this event is assumed to be infreqent, don't bother keeping a member variable - CSMSettings::UserSettings &settings = CSMSettings::UserSettings::instance(); - if (settings.setting("table-input/jump-to-modified", "true") == "true") + if (mAutoJump) selectRow(bottomRight.row()); } + +void CSVWorld::Table::jumpAfterModChanged(int state) +{ + if(state == Qt::Checked) + mAutoJump = true; + else + mAutoJump = false; +} diff --git a/apps/opencs/view/world/table.hpp b/apps/opencs/view/world/table.hpp index f1d87d79a7..ea6a026f98 100644 --- a/apps/opencs/view/world/table.hpp +++ b/apps/opencs/view/world/table.hpp @@ -69,6 +69,7 @@ namespace CSVWorld std::map mDoubleClickActions; bool mJumpToAddedRecord; bool mUnselectAfterJump; + bool mAutoJump; private: @@ -145,6 +146,8 @@ namespace CSVWorld void rowsInsertedEvent(const QModelIndex &parent, int start, int end); void dataChangedEvent(const QModelIndex &topLeft, const QModelIndex &bottomRight); + + void jumpAfterModChanged(int state); }; } diff --git a/apps/opencs/view/world/tablesubview.cpp b/apps/opencs/view/world/tablesubview.cpp index af0b644475..46393faf87 100644 --- a/apps/opencs/view/world/tablesubview.cpp +++ b/apps/opencs/view/world/tablesubview.cpp @@ -1,6 +1,8 @@ - #include "tablesubview.hpp" +#include +#include +#include #include #include #include @@ -18,7 +20,7 @@ CSVWorld::TableSubView::TableSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document, const CreatorFactoryBase& creatorFactory, bool sorting) -: SubView (id) +: SubView (id), mShowOptions(false), mOptions(0) { QVBoxLayout *layout = new QVBoxLayout; @@ -32,7 +34,37 @@ CSVWorld::TableSubView::TableSubView (const CSMWorld::UniversalId& id, CSMDoc::D mFilterBox = new CSVFilter::FilterBox (document.getData(), this); - layout->insertWidget (0, mFilterBox); + QHBoxLayout *hLayout = new QHBoxLayout; + hLayout->insertWidget(0,mFilterBox); + + mOptions = new QWidget; + + QHBoxLayout *optHLayout = new QHBoxLayout; + QCheckBox *autoJump = new QCheckBox("Auto Jump"); + autoJump->setToolTip ("Whether to jump to the modified record." + "\nCan be useful in finding the moved or modified" + "\nobject instance while 3D editing."); + autoJump->setCheckState(Qt::Unchecked); + connect(autoJump, SIGNAL (stateChanged(int)), mTable, SLOT (jumpAfterModChanged(int))); + optHLayout->insertWidget(0, autoJump); + optHLayout->setContentsMargins (QMargins (0, 3, 0, 0)); + mOptions->setLayout(optHLayout); + mOptions->resize(mOptions->width(), mFilterBox->height()); + mOptions->hide(); + + QPushButton *opt = new QPushButton (); + opt->setIcon (QIcon (":startup/configure")); + opt->setSizePolicy (QSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed)); + opt->setToolTip ("Open additional options for this subview."); + connect (opt, SIGNAL (clicked()), this, SLOT (toggleOptions())); + + QVBoxLayout *buttonLayout = new QVBoxLayout; // work around margin issues + buttonLayout->setContentsMargins (QMargins (0/*left*/, 3/*top*/, 3/*right*/, 0/*bottom*/)); + buttonLayout->insertWidget(0, opt, 0, Qt::AlignVCenter|Qt::AlignRight); + hLayout->insertWidget(1, mOptions); + hLayout->insertLayout(2, buttonLayout); + + layout->insertLayout (0, hLayout); CSVDoc::SizeHintWidget *widget = new CSVDoc::SizeHintWidget; @@ -95,8 +127,7 @@ void CSVWorld::TableSubView::editRequest (const CSMWorld::UniversalId& id, const focusId (id, hint); } -void CSVWorld::TableSubView::updateUserSetting - (const QString &name, const QStringList &list) +void CSVWorld::TableSubView::updateUserSetting (const QString &name, const QStringList &list) { mTable->updateUserSetting(name, list); } @@ -166,3 +197,16 @@ bool CSVWorld::TableSubView::eventFilter (QObject* object, QEvent* event) return false; } +void CSVWorld::TableSubView::toggleOptions() +{ + if (mShowOptions) + { + mShowOptions = false; + mOptions->hide(); + } + else + { + mShowOptions = true; + mOptions->show(); + } +} diff --git a/apps/opencs/view/world/tablesubview.hpp b/apps/opencs/view/world/tablesubview.hpp index 9d86c32e40..22ba608896 100644 --- a/apps/opencs/view/world/tablesubview.hpp +++ b/apps/opencs/view/world/tablesubview.hpp @@ -6,6 +6,7 @@ #include class QModelIndex; +class QWidget; namespace CSMWorld { @@ -35,6 +36,8 @@ namespace CSVWorld Table *mTable; TableBottomBox *mBottom; CSVFilter::FilterBox *mFilterBox; + bool mShowOptions; + QWidget *mOptions; public: @@ -63,6 +66,7 @@ namespace CSVWorld void cloneRequest (const CSMWorld::UniversalId& toClone); void createFilterRequest(std::vector< CSMWorld::UniversalId >& types, Qt::DropAction action); + void toggleOptions (); }; } From 445f8280143b6a0286d602b5df43820940700044 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sat, 30 May 2015 18:22:58 +1000 Subject: [PATCH 3/6] Refresh filter only if one exists. Fixes Qt warning message "QSortFilterProxyModel: inconsistent changes reported by source model" when a record is deleted. --- apps/opencs/model/world/idtableproxymodel.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/apps/opencs/model/world/idtableproxymodel.cpp b/apps/opencs/model/world/idtableproxymodel.cpp index 987d274620..5c621cec13 100644 --- a/apps/opencs/model/world/idtableproxymodel.cpp +++ b/apps/opencs/model/world/idtableproxymodel.cpp @@ -56,6 +56,9 @@ bool CSMWorld::IdTableProxyModel::lessThan(const QModelIndex &left, const QModel void CSMWorld::IdTableProxyModel::refreshFilter() { - updateColumnMap(); - invalidateFilter(); + if (mFilter) + { + updateColumnMap(); + invalidateFilter(); + } } From 4152086890f952bfacb144aceefecc343cc20c2d Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sat, 30 May 2015 18:24:26 +1000 Subject: [PATCH 4/6] Get the correct index for the type of the record being cloned. --- apps/opencs/model/world/idtable.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/opencs/model/world/idtable.cpp b/apps/opencs/model/world/idtable.cpp index 04aa271ccc..1f1e35b603 100644 --- a/apps/opencs/model/world/idtable.cpp +++ b/apps/opencs/model/world/idtable.cpp @@ -140,7 +140,7 @@ void CSMWorld::IdTable::cloneRecord(const std::string& origin, const std::string& destination, CSMWorld::UniversalId::Type type) { - int index = mIdCollection->getAppendIndex (destination); + int index = mIdCollection->getAppendIndex (destination, type); beginInsertRows (QModelIndex(), index, index); mIdCollection->cloneRecord(origin, destination, type); From 16bf9716a36b5ada56f8ae105c39d50c0f716906 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sat, 30 May 2015 18:25:43 +1000 Subject: [PATCH 5/6] Scroll the selected row to the middle of the viewport. --- apps/opencs/view/world/table.cpp | 17 +++++++++++++++++ apps/opencs/view/world/table.hpp | 2 ++ 2 files changed, 19 insertions(+) diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp index 25162a67f7..692f54b8e9 100644 --- a/apps/opencs/view/world/table.cpp +++ b/apps/opencs/view/world/table.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include "../../model/doc/document.hpp" @@ -744,6 +745,10 @@ std::vector< CSMWorld::UniversalId > CSVWorld::Table::getDraggedRecords() const return idToDrag; } +// parent, start and end depend on the model sending the signal, in this case mProxyModel +// +// If, for example, mModel was used instead, then scrolTo() should use the index +// mProxyModel->mapFromSource(mModel->index(end, 0)) void CSVWorld::Table::rowsInsertedEvent(const QModelIndex& parent, int start, int end) { tableSizeUpdate(); @@ -752,17 +757,29 @@ void CSVWorld::Table::rowsInsertedEvent(const QModelIndex& parent, int start, in { selectRow(end); + // without this delay the scroll works but goes to top for add/clone + QMetaObject::invokeMethod(this, "queuedScrollTo", Qt::QueuedConnection, Q_ARG(int, end)); + if(mUnselectAfterJump) clearSelection(); } } +void CSVWorld::Table::queuedScrollTo(int row) +{ + scrollTo(mProxyModel->index(row, 0), QAbstractItemView::PositionAtCenter); +} + void CSVWorld::Table::dataChangedEvent(const QModelIndex &topLeft, const QModelIndex &bottomRight) { tableSizeUpdate(); if (mAutoJump) + { selectRow(bottomRight.row()); + scrollTo(mProxyModel->index(bottomRight.row(), 0), QAbstractItemView::PositionAtCenter); + //scrollTo(bottomRight, QAbstractItemView::PositionAtCenter); // alternative + } } void CSVWorld::Table::jumpAfterModChanged(int state) diff --git a/apps/opencs/view/world/table.hpp b/apps/opencs/view/world/table.hpp index ea6a026f98..a3d726a7f7 100644 --- a/apps/opencs/view/world/table.hpp +++ b/apps/opencs/view/world/table.hpp @@ -148,6 +148,8 @@ namespace CSVWorld void dataChangedEvent(const QModelIndex &topLeft, const QModelIndex &bottomRight); void jumpAfterModChanged(int state); + + void queuedScrollTo(int state); }; } From 007c733578f249a4d9c683c81c1fb8fc37216820 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sun, 31 May 2015 07:14:37 +1000 Subject: [PATCH 6/6] Resolve merge issues and add back user preference setting for auto selecting a modified record. (cherry picked from commit 321b1b5106a47500bffd4c78a66d3d6f44a06f5b) Conflicts: apps/opencs/model/settings/usersettings.cpp --- apps/opencs/model/settings/usersettings.cpp | 5 +++++ apps/opencs/view/world/tablesubview.cpp | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/apps/opencs/model/settings/usersettings.cpp b/apps/opencs/model/settings/usersettings.cpp index a40a790b74..5cf3bd7a74 100644 --- a/apps/opencs/model/settings/usersettings.cpp +++ b/apps/opencs/model/settings/usersettings.cpp @@ -243,6 +243,11 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() jumpToAdded->setDefaultValue (defaultValue); jumpToAdded->setDeclaredValues (jumpValues); + Setting *jumpToModified = createSetting (Type_CheckBox, "jump-to-modified", "Jump to modified Record"); + jumpToModified->setDefaultValue ("true"); + jumpToModified->setToolTip ("Whether to jump to the modified record. This setting effects the instances table only." + "\nCan be useful in finding the moved or modified object instance while 3D editing."); + Setting *extendedConfig = createSetting (Type_CheckBox, "extended-config", "Manually specify affected record types for an extended delete/revert"); extendedConfig->setDefaultValue("false"); diff --git a/apps/opencs/view/world/tablesubview.cpp b/apps/opencs/view/world/tablesubview.cpp index 7a26804344..81f78cdadd 100644 --- a/apps/opencs/view/world/tablesubview.cpp +++ b/apps/opencs/view/world/tablesubview.cpp @@ -54,7 +54,8 @@ CSVWorld::TableSubView::TableSubView (const CSMWorld::UniversalId& id, CSMDoc::D autoJump->setToolTip ("Whether to jump to the modified record." "\nCan be useful in finding the moved or modified" "\nobject instance while 3D editing."); - autoJump->setCheckState(Qt::Unchecked); + autoJump->setCheckState( + userSettings.settingValue ("table-input/jump-to-modified") == "true" ? Qt::Checked : Qt::Unchecked); connect(autoJump, SIGNAL (stateChanged(int)), mTable, SLOT (jumpAfterModChanged(int))); optHLayout->insertWidget(0, autoJump); optHLayout->insertWidget(1, added);