Skip to content

Commit 87ae4f0

Browse files
committed
Fix autoExpand timer reset behavior (workaround for bug in Qt framework)
Starting with at least Qt 5.0.0 (released in 2011) and still present in current versions of Qt (Qt 6.8.0 at the time of this commit), there is a bug in the implementation of QTreeView::dragMoveEvent and autoExpandDelay: QT BUG DESCRIPTION Instead of resetting the delay timer whenever the mouse moves to a new item, it is reset on every little mouse movement, which makes autoExpand useless e.g. on laptop touchpads. OUR WORKAROUND Only reset the delay timer whenever the mouse has moved to a new item, by bypassing QTreeView::dragMoveEvent() and directly calling QAbstractItemView::dragMoveEvent() instead unless the mouse has moved to a new item.
1 parent 07ac220 commit 87ae4f0

2 files changed

Lines changed: 45 additions & 7 deletions

File tree

src/widget/wlibrarysidebar.cpp

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ void WLibrarySidebar::dragEnterEvent(QDragEnterEvent* pEvent) {
8383
/// or when the drag is aborted through Escape or other means.
8484
void WLibrarySidebar::dragLeaveEvent(QDragLeaveEvent* pEvent) {
8585
// qDebug() << "WLibrarySidebar::dragLeaveEvent";
86+
m_autoExpandIndex = QModelIndex();
8687
toggleDragHoverPropertyAndUpdateStyle(false);
8788

8889
QTreeView::dragLeaveEvent(pEvent);
@@ -101,22 +102,58 @@ void WLibrarySidebar::dragMoveEvent(QDragMoveEvent* pEvent) {
101102
// actual data being dragged is supported, e.g. whether it is
102103
// a list of valid track URLs.
103104
//
104-
// Note: We go through QTreeView here instead of directly calling
105-
// SidebarModel to retain other useful features from the base class,
106-
// like e.g. auto-scroll behavior when the mouse cursor reaches
107-
// the boundaries of the tree view.
105+
// Note: We go through QTreeView/QAbstractItemView here, instead of
106+
// directly calling SidebarModel, to retain other useful features
107+
// from the base class, like e.g. auto-scroll behavior when the mouse
108+
// cursor reaches the boundaries of the tree view.
108109
//
109110
// Note: pEvent->source() will be NULL if something is dropped
110111
// from a different application. This knowledge is used
111112
// inside the LibraryFeature implementations.
112-
setSourceOfCurrentDragDropEvent(pEvent->source());
113-
QTreeView::dragMoveEvent(pEvent);
114-
setSourceOfCurrentDragDropEvent(nullptr);
113+
114+
// ========================================================================
115+
// Fix autoExpand timer reset behavior (workaround for bug in Qt framework)
116+
//
117+
// Starting with at least Qt 5.0.0 (released in 2011) and still present
118+
// in current versions of Qt (Qt 6.8.0 at the time of this commit), there
119+
// is a bug in the implementation of QTreeView::dragMoveEvent and autoExpandDelay:
120+
//
121+
// QT BUG DESCRIPTION
122+
//
123+
// Instead of resetting the delay timer whenever the mouse moves to a
124+
// new item, it is reset on every little mouse movement, which makes
125+
// autoExpand useless e.g. on laptop touchpads.
126+
//
127+
// OUR WORKAROUND
128+
//
129+
// Only reset the delay timer whenever the mouse has moved to a new item,
130+
// by bypassing QTreeView::dragMoveEvent() and directly calling
131+
// QAbstractItemView::dragMoveEvent() instead unless the mouse
132+
// has moved to a new item.
133+
// ========================================================================
134+
const QPoint pos = pEvent->position().toPoint();
135+
const QModelIndex index = indexAt(pos);
136+
137+
if (m_autoExpandIndex != index) {
138+
m_autoExpandIndex = index;
139+
// QTreeView::dragMoveEvent just restarts the autoExpand timer
140+
// and then calls QAbstractItemView::dragMoveEvent
141+
setSourceOfCurrentDragDropEvent(pEvent->source());
142+
QTreeView::dragMoveEvent(pEvent);
143+
setSourceOfCurrentDragDropEvent(nullptr);
144+
} else {
145+
// Skip resetting the autoExpand timer (see above)
146+
// because we are still hovering over the same item
147+
setSourceOfCurrentDragDropEvent(pEvent->source());
148+
QAbstractItemView::dragMoveEvent(pEvent);
149+
setSourceOfCurrentDragDropEvent(nullptr);
150+
}
115151
}
116152

117153
// Drag-and-drop "drop" event. Occurs when something is dropped onto the track sources view
118154
void WLibrarySidebar::dropEvent(QDropEvent* pEvent) {
119155
// qDebug() << "WLibrarySidebar::dropEvent";
156+
m_autoExpandIndex = QModelIndex();
120157
toggleDragHoverPropertyAndUpdateStyle(false);
121158

122159
// QTreeView::dropEvent will, through some indirection, call

src/widget/wlibrarysidebar.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,4 +53,5 @@ class WLibrarySidebar : public QTreeView, public WBaseWidget {
5353
void setSourceOfCurrentDragDropEvent(QObject* pSource);
5454

5555
int m_hoverExpandDelay;
56+
QModelIndex m_autoExpandIndex;
5657
};

0 commit comments

Comments
 (0)