From 360f9881848ebba244338101fdf3e47e45e9ece8 Mon Sep 17 00:00:00 2001 From: Uwe Klotz Date: Tue, 17 Apr 2018 00:31:42 +0200 Subject: [PATCH] Fix unresponsive scrolling through crates & playlists with encoder --- src/library/baseplaylistfeature.cpp | 8 ++++- src/library/crate/cratefeature.cpp | 4 ++- src/library/libraryfeature.cpp | 29 +++++++++++++++--- src/library/libraryfeature.h | 21 ++++++++++--- src/library/sidebarmodel.cpp | 47 +++++++++++++++++++++-------- src/library/sidebarmodel.h | 17 +++++++++-- 6 files changed, 100 insertions(+), 26 deletions(-) diff --git a/src/library/baseplaylistfeature.cpp b/src/library/baseplaylistfeature.cpp index 2cfd68e974f..c0506e458db 100644 --- a/src/library/baseplaylistfeature.cpp +++ b/src/library/baseplaylistfeature.cpp @@ -19,11 +19,17 @@ #include "widget/wlibrarytextbrowser.h" #include "util/assert.h" +namespace { + +const int kClickedChildActivationTimeoutMillis = 100; + +} // anonymous namespace + BasePlaylistFeature::BasePlaylistFeature(QObject* parent, UserSettingsPointer pConfig, TrackCollection* pTrackCollection, QString rootViewName) - : LibraryFeature(pConfig, parent), + : LibraryFeature(pConfig, kClickedChildActivationTimeoutMillis, parent), m_pTrackCollection(pTrackCollection), m_playlistDao(pTrackCollection->getPlaylistDAO()), m_trackDao(pTrackCollection->getTrackDAO()), diff --git a/src/library/crate/cratefeature.cpp b/src/library/crate/cratefeature.cpp index 38c09b0eb86..da75522e398 100644 --- a/src/library/crate/cratefeature.cpp +++ b/src/library/crate/cratefeature.cpp @@ -29,6 +29,8 @@ namespace { +const int kClickedChildActivationTimeoutMillis = 100; + QString formatLabel( const CrateSummary& crateSummary) { return QString("%1 (%2) %3").arg( @@ -42,7 +44,7 @@ QString formatLabel( CrateFeature::CrateFeature(Library* pLibrary, TrackCollection* pTrackCollection, UserSettingsPointer pConfig) - : LibraryFeature(pConfig), + : LibraryFeature(pConfig, kClickedChildActivationTimeoutMillis), m_cratesIcon(":/images/library/ic_library_crates.png"), m_lockedCrateIcon(":/images/library/ic_library_locked.png"), m_pTrackCollection(pTrackCollection), diff --git a/src/library/libraryfeature.cpp b/src/library/libraryfeature.cpp index efe20d2e9dc..e5825573709 100644 --- a/src/library/libraryfeature.cpp +++ b/src/library/libraryfeature.cpp @@ -6,18 +6,37 @@ // KEEP THIS cpp file to tell scons that moc should be called on the class!!! // The reason for this is that LibraryFeature uses slots/signals and for this // to work the code has to be precompiles by moc -LibraryFeature::LibraryFeature(QObject *parent) - : QObject(parent) { +LibraryFeature::LibraryFeature( + QObject *parent) + : QObject(parent), + m_clickedChildActivationTimeoutMillis(0) { } -LibraryFeature::LibraryFeature(UserSettingsPointer pConfig, QObject* parent) +LibraryFeature::LibraryFeature( + int clickedChildActivationTimeoutMillis, + QObject *parent) : QObject(parent), - m_pConfig(pConfig) { + m_clickedChildActivationTimeoutMillis(clickedChildActivationTimeoutMillis) { + DEBUG_ASSERT(m_clickedChildActivationTimeoutMillis >= 0); } -LibraryFeature::~LibraryFeature() { +LibraryFeature::LibraryFeature( + UserSettingsPointer pConfig, + QObject* parent) + : QObject(parent), + m_pConfig(pConfig), + m_clickedChildActivationTimeoutMillis(0) { +} +LibraryFeature::LibraryFeature( + UserSettingsPointer pConfig, + int clickedChildActivationTimeoutMillis, + QObject* parent) + : QObject(parent), + m_pConfig(pConfig), + m_clickedChildActivationTimeoutMillis(clickedChildActivationTimeoutMillis) { + DEBUG_ASSERT(m_clickedChildActivationTimeoutMillis >= 0); } QStringList LibraryFeature::getPlaylistFiles(QFileDialog::FileMode mode) const { diff --git a/src/library/libraryfeature.h b/src/library/libraryfeature.h index 138d96c1aaa..7639e03557f 100644 --- a/src/library/libraryfeature.h +++ b/src/library/libraryfeature.h @@ -29,11 +29,23 @@ class KeyboardEventFilter; class LibraryFeature : public QObject { Q_OBJECT public: - LibraryFeature(QObject* parent = NULL); + explicit LibraryFeature( + QObject* parent); + explicit LibraryFeature( + int clickedChildActivationTimeoutMillis, + QObject* parent = nullptr); + explicit LibraryFeature( + UserSettingsPointer pConfig, + QObject* parent = nullptr); + explicit LibraryFeature( + UserSettingsPointer pConfig, + int clickedChildActivationTimeoutMillis, + QObject* parent = nullptr); + ~LibraryFeature() override = default; - LibraryFeature(UserSettingsPointer pConfig, - QObject* parent = NULL); - virtual ~LibraryFeature(); + int clickedChildActivationTimeoutMillis() const { + return m_clickedChildActivationTimeoutMillis; + } virtual QVariant title() = 0; virtual QIcon getIcon() = 0; @@ -124,6 +136,7 @@ class LibraryFeature : public QObject { private: QStringList getPlaylistFiles(QFileDialog::FileMode mode) const; + const int m_clickedChildActivationTimeoutMillis; }; #endif /* LIBRARYFEATURE_H */ diff --git a/src/library/sidebarmodel.cpp b/src/library/sidebarmodel.cpp index e0943bb40fb..c2bb5d198b4 100644 --- a/src/library/sidebarmodel.cpp +++ b/src/library/sidebarmodel.cpp @@ -8,13 +8,14 @@ #include "library/browse/browsefeature.h" #include "util/assert.h" -SidebarModel::SidebarModel(QObject* parent) +SidebarModel::SidebarModel( + QObject* parent) : QAbstractItemModel(parent), - m_iDefaultSelectedIndex(0) { -} - -SidebarModel::~SidebarModel() { - + m_iDefaultSelectedIndex(0), + m_clickedChildActivationTimer(new QTimer(this)), + m_clickedFeature(nullptr) { + m_clickedChildActivationTimer->setSingleShot(true); + connect(m_clickedChildActivationTimer, SIGNAL(timeout()), this, SLOT(slotActivateChildAtClickedFeatureIndex())); } void SidebarModel::addLibraryFeature(LibraryFeature* feature) { @@ -221,6 +222,20 @@ QVariant SidebarModel::data(const QModelIndex& index, int role) const { return QVariant(); } +void SidebarModel::onFeatureIndexClicked( + LibraryFeature* feature, + QModelIndex index) { + m_clickedChildActivationTimer->stop(); + m_clickedFeature = feature; + m_clickedIndex = index; +} + +void SidebarModel::slotActivateChildAtClickedFeatureIndex() { + if (m_clickedFeature) { + m_clickedFeature->activateChild(m_clickedIndex); + } +} + void SidebarModel::clicked(const QModelIndex& index) { //qDebug() << "SidebarModel::clicked() index=" << index; @@ -236,8 +251,12 @@ void SidebarModel::clicked(const QModelIndex& index) { } else { TreeItem* tree_item = (TreeItem*)index.internalPointer(); if (tree_item) { - LibraryFeature* feature = tree_item->feature(); - feature->activateChild(index); + onFeatureIndexClicked(tree_item->feature(), index); + DEBUG_ASSERT(m_clickedFeature); + // Deferred activation is required for smooth scrolling when using + // encoder knobs + m_clickedChildActivationTimer->start( + m_clickedFeature->clickedChildActivationTimeoutMillis()); } } } @@ -249,8 +268,9 @@ void SidebarModel::doubleClicked(const QModelIndex& index) { } else { TreeItem* tree_item = (TreeItem*)index.internalPointer(); if (tree_item) { - LibraryFeature* feature = tree_item->feature(); - feature->onLazyChildExpandation(index); + onFeatureIndexClicked(tree_item->feature(), index); + DEBUG_ASSERT(m_clickedFeature); + m_clickedFeature->onLazyChildExpandation(m_clickedIndex); } } } @@ -267,9 +287,10 @@ void SidebarModel::rightClicked(const QPoint& globalPos, const QModelIndex& inde { TreeItem* tree_item = (TreeItem*)index.internalPointer(); if (tree_item) { - LibraryFeature* feature = tree_item->feature(); - feature->activateChild(index); - feature->onRightClickChild(globalPos, index); + onFeatureIndexClicked(tree_item->feature(), index); + DEBUG_ASSERT(m_clickedFeature); + m_clickedFeature->activateChild(m_clickedIndex); + m_clickedFeature->onRightClickChild(globalPos, m_clickedIndex); } } } diff --git a/src/library/sidebarmodel.h b/src/library/sidebarmodel.h index 0040d2119db..17c3bb8caeb 100644 --- a/src/library/sidebarmodel.h +++ b/src/library/sidebarmodel.h @@ -7,6 +7,7 @@ #include #include #include +#include #include class LibraryFeature; @@ -14,8 +15,9 @@ class LibraryFeature; class SidebarModel : public QAbstractItemModel { Q_OBJECT public: - explicit SidebarModel(QObject* parent = 0); - virtual ~SidebarModel(); + explicit SidebarModel( + QObject* parent = nullptr); + ~SidebarModel() override = default; void addLibraryFeature(LibraryFeature* feature); QModelIndex getDefaultSelection(); @@ -64,11 +66,22 @@ class SidebarModel : public QAbstractItemModel { signals: void selectIndex(const QModelIndex& index); + private slots: + void slotActivateChildAtClickedFeatureIndex(); + private: QModelIndex translateSourceIndex(const QModelIndex& parent); void featureRenamed(LibraryFeature*); QList m_sFeatures; unsigned int m_iDefaultSelectedIndex; /** Index of the item in the sidebar model to select at startup. */ + + QTimer* const m_clickedChildActivationTimer; + LibraryFeature* m_clickedFeature; + QModelIndex m_clickedIndex; + + void onFeatureIndexClicked( + LibraryFeature* feature, + QModelIndex index); }; #endif /* SIDEBARMODEL_H */