From 3a6cf7202f07f97c1184c0dd0c39fc33d442f7c3 Mon Sep 17 00:00:00 2001 From: Tillmann Karras Date: Sun, 23 Jun 2024 00:48:16 +0100 Subject: [PATCH] DolphinQt: avoid scrolling while game list is being modified --- Source/Core/DolphinQt/CMakeLists.txt | 2 ++ Source/Core/DolphinQt/DolphinQt.vcxproj | 2 ++ Source/Core/DolphinQt/GameList/GameList.cpp | 3 ++ Source/Core/DolphinQt/GameList/GameList.h | 3 ++ .../Core/DolphinQt/QtUtils/ViewScrollLock.cpp | 35 +++++++++++++++++++ .../Core/DolphinQt/QtUtils/ViewScrollLock.h | 25 +++++++++++++ 6 files changed, 70 insertions(+) create mode 100644 Source/Core/DolphinQt/QtUtils/ViewScrollLock.cpp create mode 100644 Source/Core/DolphinQt/QtUtils/ViewScrollLock.h diff --git a/Source/Core/DolphinQt/CMakeLists.txt b/Source/Core/DolphinQt/CMakeLists.txt index bd766e0453..9af86e1ccf 100644 --- a/Source/Core/DolphinQt/CMakeLists.txt +++ b/Source/Core/DolphinQt/CMakeLists.txt @@ -325,6 +325,8 @@ add_executable(dolphin-emu QtUtils/SignalBlocking.h QtUtils/UTF8CodePointCountValidator.cpp QtUtils/UTF8CodePointCountValidator.h + QtUtils/ViewScrollLock.cpp + QtUtils/ViewScrollLock.h QtUtils/WindowActivationEventFilter.cpp QtUtils/WindowActivationEventFilter.h QtUtils/WrapInScrollArea.cpp diff --git a/Source/Core/DolphinQt/DolphinQt.vcxproj b/Source/Core/DolphinQt/DolphinQt.vcxproj index f4bc2e0030..f6736303f0 100644 --- a/Source/Core/DolphinQt/DolphinQt.vcxproj +++ b/Source/Core/DolphinQt/DolphinQt.vcxproj @@ -199,6 +199,7 @@ + @@ -259,6 +260,7 @@ + diff --git a/Source/Core/DolphinQt/GameList/GameList.cpp b/Source/Core/DolphinQt/GameList/GameList.cpp index 64e9ae6774..0571052285 100644 --- a/Source/Core/DolphinQt/GameList/GameList.cpp +++ b/Source/Core/DolphinQt/GameList/GameList.cpp @@ -67,6 +67,7 @@ #include "DolphinQt/QtUtils/ModalMessageBox.h" #include "DolphinQt/QtUtils/ParallelProgressDialog.h" #include "DolphinQt/QtUtils/SetWindowDecorations.h" +#include "DolphinQt/QtUtils/ViewScrollLock.h" #include "DolphinQt/Resources.h" #include "DolphinQt/Settings.h" #include "DolphinQt/WiiUpdate.h" @@ -116,6 +117,8 @@ GameList::GameList(QWidget* parent) : QStackedWidget(parent), m_model(this) connect(&m_model, &QAbstractItemModel::rowsInserted, this, &GameList::ConsiderViewChange); connect(&m_model, &QAbstractItemModel::rowsRemoved, this, &GameList::ConsiderViewChange); + m_viewScrollLock = new ViewScrollLock(this, m_list_proxy, m_list); + addWidget(m_list); addWidget(m_grid); addWidget(m_empty); diff --git a/Source/Core/DolphinQt/GameList/GameList.h b/Source/Core/DolphinQt/GameList/GameList.h index 54ca50ab15..6cf641dac3 100644 --- a/Source/Core/DolphinQt/GameList/GameList.h +++ b/Source/Core/DolphinQt/GameList/GameList.h @@ -20,6 +20,8 @@ namespace UICommon class GameFile; } +class ViewScrollLock; + class GameList final : public QStackedWidget { Q_OBJECT @@ -100,6 +102,7 @@ private: void UpdateFont(); GameListModel m_model; + ViewScrollLock* m_viewScrollLock; QSortFilterProxyModel* m_list_proxy; QSortFilterProxyModel* m_grid_proxy; diff --git a/Source/Core/DolphinQt/QtUtils/ViewScrollLock.cpp b/Source/Core/DolphinQt/QtUtils/ViewScrollLock.cpp new file mode 100644 index 0000000000..75d0316513 --- /dev/null +++ b/Source/Core/DolphinQt/QtUtils/ViewScrollLock.cpp @@ -0,0 +1,35 @@ +// Copyright 2024 Dolphin Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include +#include + +#include "DolphinQt/QtUtils/ViewScrollLock.h" + +ViewScrollLock::ViewScrollLock(QObject* parent, QAbstractItemModel* model, QAbstractItemView* view) + : QObject(parent), m_view(view) +{ + connect(model, &QAbstractItemModel::rowsAboutToBeInserted, this, + &ViewScrollLock::AboutToBeModified); + connect(model, &QAbstractItemModel::rowsAboutToBeRemoved, this, + &ViewScrollLock::AboutToBeModified); + connect(model, &QAbstractItemModel::rowsInserted, this, &ViewScrollLock::Modified); + connect(model, &QAbstractItemModel::rowsRemoved, this, &ViewScrollLock::Modified); +} + +void ViewScrollLock::AboutToBeModified() +{ + QSize size = m_view->size(); + m_first = m_view->indexAt(QPoint(0, 0)); + m_last = m_view->indexAt(QPoint(size.height(), size.width())); +} + +void ViewScrollLock::Modified() +{ + // Try to keep the first row at the top. + // If that fails, try to keep the last row at the bottom. + if (m_first.isValid()) + m_view->scrollTo(m_first, QAbstractItemView::PositionAtTop); + else if (m_last.isValid()) + m_view->scrollTo(m_last, QAbstractItemView::PositionAtBottom); +} diff --git a/Source/Core/DolphinQt/QtUtils/ViewScrollLock.h b/Source/Core/DolphinQt/QtUtils/ViewScrollLock.h new file mode 100644 index 0000000000..86b7d238bb --- /dev/null +++ b/Source/Core/DolphinQt/QtUtils/ViewScrollLock.h @@ -0,0 +1,25 @@ +// Copyright 2024 Dolphin Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include + +class QAbstractItemModel; +class QAbstractItemView; + +// Try to keep visible items in view while items are added/removed. +class ViewScrollLock : public QObject +{ + Q_OBJECT + +public: + ViewScrollLock(QObject* parent, QAbstractItemModel* model, QAbstractItemView* view); + void AboutToBeModified(); + void Modified(); + +private: + QAbstractItemView* m_view; + QPersistentModelIndex m_first, m_last; +};