Allow horizontal scrolling with a mouse wheel for QListView

Convert vertical wheel events to horizontal for two cases of
the items layout when vertical scrolling is impossible:
1) TopToBottom flow with wrapping
2) LeftToRight flow without wrapping

Do it only for pure vertical events to avoid a mess for such
devices as touchpads or Apple Mouse.

[ChangeLog][QtWidgets][Important Behavior Changes] Allow
horizontal scrolling with a vertical mouse wheel for QListView.

Task-number: QTBUG-37007
Change-Id: Ie2525153fa7b443d27ca08cc5f5d4d7ecdb8c183
Reviewed-by: Thorbjørn Lund Martsum <tmartsum@gmail.com>
Reviewed-by: Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
bb10
Alexander Volkov 2014-12-05 16:08:28 +03:00 committed by Giuseppe D'Angelo
parent 8458b4054a
commit 59cc316620
3 changed files with 83 additions and 0 deletions

View File

@ -53,6 +53,8 @@
QT_BEGIN_NAMESPACE
extern bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event);
/*!
\class QListView
@ -796,6 +798,35 @@ void QListView::mouseReleaseEvent(QMouseEvent *e)
}
}
#ifndef QT_NO_WHEELEVENT
/*!
\reimp
*/
void QListView::wheelEvent(QWheelEvent *e)
{
Q_D(QListView);
if (e->orientation() == Qt::Vertical) {
if (e->angleDelta().x() == 0
&& ((d->flow == TopToBottom && d->wrap) || (d->flow == LeftToRight && !d->wrap))
&& d->vbar->minimum() == 0 && d->vbar->maximum() == 0) {
QPoint pixelDelta(e->pixelDelta().y(), e->pixelDelta().x());
QPoint angleDelta(e->angleDelta().y(), e->angleDelta().x());
QWheelEvent hwe(e->pos(), e->globalPos(), pixelDelta, angleDelta, e->delta(),
Qt::Horizontal, e->buttons(), e->modifiers(), e->phase());
if (e->spontaneous())
qt_sendSpontaneousEvent(d->hbar, &hwe);
else
QApplication::sendEvent(d->hbar, &hwe);
e->setAccepted(hwe.isAccepted());
} else {
QApplication::sendEvent(d->vbar, e);
}
} else {
QApplication::sendEvent(d->hbar, e);
}
}
#endif // QT_NO_WHEELEVENT
/*!
\reimp
*/

View File

@ -146,6 +146,9 @@ protected:
void mouseMoveEvent(QMouseEvent *e) Q_DECL_OVERRIDE;
void mouseReleaseEvent(QMouseEvent *e) Q_DECL_OVERRIDE;
#ifndef QT_NO_WHEELEVENT
void wheelEvent(QWheelEvent *e) Q_DECL_OVERRIDE;
#endif
void timerEvent(QTimerEvent *e) Q_DECL_OVERRIDE;
void resizeEvent(QResizeEvent *e) Q_DECL_OVERRIDE;

View File

@ -38,6 +38,7 @@
#include <qapplication.h>
#include <qlistview.h>
#include <private/qlistview_p.h>
#include <private/qcoreapplication_p.h>
#include <qlistwidget.h>
#include <qitemdelegate.h>
#include <qstandarditemmodel.h>
@ -148,6 +149,7 @@ private slots:
void testScrollToWithHidden();
void testViewOptions();
void taskQTBUG_39902_mutualScrollBars();
void horizontalScrollingByVerticalWheelEvents();
};
// Testing get/set functions
@ -2372,5 +2374,52 @@ void tst_QListView::taskQTBUG_39902_mutualScrollBars()
QTest::qWait(100);
}
void tst_QListView::horizontalScrollingByVerticalWheelEvents()
{
QListView lv;
lv.setWrapping(true);
TestDelegate *delegate = new TestDelegate(&lv);
delegate->m_sizeHint = QSize(100, 100);
lv.setItemDelegate(delegate);
QtTestModel model;
model.colCount = 1;
model.rCount = 100;
lv.setModel(&model);
lv.resize(300, 300);
lv.show();
QTest::qWaitForWindowExposed(&lv);
QPoint globalPos = lv.geometry().center();
QPoint pos = lv.viewport()->geometry().center();
QWheelEvent wheelDownEvent(pos, globalPos, QPoint(0, 0), QPoint(0, -120), -120, Qt::Vertical, 0, 0);
QWheelEvent wheelUpEvent(pos, globalPos, QPoint(0, 0), QPoint(0, 120), 120, Qt::Vertical, 0, 0);
QWheelEvent wheelLeftDownEvent(pos, globalPos, QPoint(0, 0), QPoint(120, -120), -120, Qt::Vertical, 0, 0);
int hValue = lv.horizontalScrollBar()->value();
QApplication::sendEvent(lv.viewport(), &wheelDownEvent);
QVERIFY(lv.horizontalScrollBar()->value() > hValue);
QApplication::sendEvent(lv.viewport(), &wheelUpEvent);
QVERIFY(lv.horizontalScrollBar()->value() == hValue);
QApplication::sendEvent(lv.viewport(), &wheelLeftDownEvent);
QVERIFY(lv.horizontalScrollBar()->value() == hValue);
// ensure that vertical wheel events are not converted when vertical
// scroll bar is not visible but vertical scrolling is possible
lv.setWrapping(false);
lv.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
QApplication::processEvents();
int vValue = lv.verticalScrollBar()->value();
QApplication::sendEvent(lv.viewport(), &wheelDownEvent);
QVERIFY(lv.verticalScrollBar()->value() > vValue);
}
QTEST_MAIN(tst_QListView)
#include "tst_qlistview.moc"