summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/widgets/itemviews/qabstractitemview.cpp16
-rw-r--r--src/widgets/itemviews/qabstractitemview.h1
-rw-r--r--src/widgets/itemviews/qlistview.cpp5
-rw-r--r--src/widgets/itemviews/qtableview.cpp5
-rw-r--r--src/widgets/itemviews/qtreeview.cpp5
-rw-r--r--src/widgets/widgets/qabstractslider.cpp19
-rw-r--r--src/widgets/widgets/qabstractslider_p.h3
-rw-r--r--src/widgets/widgets/qscrollbar.h7
-rw-r--r--tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp39
-rw-r--r--tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp38
-rw-r--r--tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp43
11 files changed, 174 insertions, 7 deletions
diff --git a/src/widgets/itemviews/qabstractitemview.cpp b/src/widgets/itemviews/qabstractitemview.cpp
index 639f18c4bc..fe98fae17a 100644
--- a/src/widgets/itemviews/qabstractitemview.cpp
+++ b/src/widgets/itemviews/qabstractitemview.cpp
@@ -54,6 +54,7 @@
#include <private/qabstractitemview_p.h>
#include <private/qabstractitemmodel_p.h>
#include <private/qguiapplication_p.h>
+#include <private/qscrollbar_p.h>
#ifndef QT_NO_ACCESSIBILITY
#include <qaccessible.h>
#endif
@@ -427,6 +428,11 @@ void QAbstractItemViewPrivate::_q_scrollerStateChanged()
\since 4.2
\enum QAbstractItemView::ScrollMode
+ Describes how the scrollbar should behave. When setting the scroll mode
+ to ScrollPerPixel the single step size will adjust automatically unless
+ it was set explicitly using \l{QAbstractSlider::}{setSingleStep()}.
+ The automatic adjustment can be restored by setting the single step size to -1.
+
\value ScrollPerItem The view will scroll the contents one item at a time.
\value ScrollPerPixel The view will scroll the contents one pixel at a time.
*/
@@ -1235,6 +1241,10 @@ void QAbstractItemView::setVerticalScrollMode(ScrollMode mode)
return;
QModelIndex topLeft = indexAt(QPoint(0, 0));
d->verticalScrollMode = mode;
+ if (mode == ScrollPerItem)
+ verticalScrollBar()->d_func()->itemviewChangeSingleStep(1); // setSingleStep(-1) => step with 1
+ else
+ verticalScrollBar()->setSingleStep(-1); // Ensure that the view can update single step
updateGeometries(); // update the scroll bars
scrollTo(topLeft, QAbstractItemView::PositionAtTop);
}
@@ -1257,7 +1267,13 @@ QAbstractItemView::ScrollMode QAbstractItemView::verticalScrollMode() const
void QAbstractItemView::setHorizontalScrollMode(ScrollMode mode)
{
Q_D(QAbstractItemView);
+ if (mode == d->horizontalScrollMode)
+ return;
d->horizontalScrollMode = mode;
+ if (mode == ScrollPerItem)
+ horizontalScrollBar()->d_func()->itemviewChangeSingleStep(1); // setSingleStep(-1) => step with 1
+ else
+ horizontalScrollBar()->setSingleStep(-1); // Ensure that the view can update single step
updateGeometries(); // update the scroll bars
}
diff --git a/src/widgets/itemviews/qabstractitemview.h b/src/widgets/itemviews/qabstractitemview.h
index ff1848b149..e32c5dad2f 100644
--- a/src/widgets/itemviews/qabstractitemview.h
+++ b/src/widgets/itemviews/qabstractitemview.h
@@ -362,6 +362,7 @@ private:
friend class QTreeViewPrivate; // needed to compile with MSVC
friend class QListModeViewBase;
friend class QListViewPrivate;
+ friend class QAbstractSlider;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QAbstractItemView::EditTriggers)
diff --git a/src/widgets/itemviews/qlistview.cpp b/src/widgets/itemviews/qlistview.cpp
index 7745004774..2dbbd211c0 100644
--- a/src/widgets/itemviews/qlistview.cpp
+++ b/src/widgets/itemviews/qlistview.cpp
@@ -46,6 +46,7 @@
#include <qscrollbar.h>
#include <qrubberband.h>
#include <private/qlistview_p.h>
+#include <private/qscrollbar_p.h>
#include <qdebug.h>
#ifndef QT_NO_ACCESSIBILITY
#include <qaccessible.h>
@@ -1868,7 +1869,7 @@ void QCommonListViewBase::paintDragDrop(QPainter *painter)
void QCommonListViewBase::updateHorizontalScrollBar(const QSize &step)
{
- horizontalScrollBar()->setSingleStep(step.width() + spacing());
+ horizontalScrollBar()->d_func()->itemviewChangeSingleStep(step.width() + spacing());
horizontalScrollBar()->setPageStep(viewport()->width());
// If both scroll bars are set to auto, we might end up in a situation with enough space
@@ -1898,7 +1899,7 @@ void QCommonListViewBase::updateHorizontalScrollBar(const QSize &step)
void QCommonListViewBase::updateVerticalScrollBar(const QSize &step)
{
- verticalScrollBar()->setSingleStep(step.height() + spacing());
+ verticalScrollBar()->d_func()->itemviewChangeSingleStep(step.height() + spacing());
verticalScrollBar()->setPageStep(viewport()->height());
// If both scroll bars are set to auto, we might end up in a situation with enough space
diff --git a/src/widgets/itemviews/qtableview.cpp b/src/widgets/itemviews/qtableview.cpp
index 0e38485f5a..2e88310b2f 100644
--- a/src/widgets/itemviews/qtableview.cpp
+++ b/src/widgets/itemviews/qtableview.cpp
@@ -46,6 +46,7 @@
#include <qabstractbutton.h>
#include <private/qtableview_p.h>
#include <private/qheaderview_p.h>
+#include <private/qscrollbar_p.h>
#ifndef QT_NO_ACCESSIBILITY
#include <qaccessible.h>
#endif
@@ -2166,7 +2167,7 @@ void QTableView::updateGeometries()
} else { // ScrollPerPixel
horizontalScrollBar()->setPageStep(vsize.width());
horizontalScrollBar()->setRange(0, horizontalLength - vsize.width());
- horizontalScrollBar()->setSingleStep(qMax(vsize.width() / (columnsInViewport + 1), 2));
+ horizontalScrollBar()->d_func()->itemviewChangeSingleStep(qMax(vsize.width() / (columnsInViewport + 1), 2));
}
// vertical scroll bar
@@ -2194,7 +2195,7 @@ void QTableView::updateGeometries()
} else { // ScrollPerPixel
verticalScrollBar()->setPageStep(vsize.height());
verticalScrollBar()->setRange(0, verticalLength - vsize.height());
- verticalScrollBar()->setSingleStep(qMax(vsize.height() / (rowsInViewport + 1), 2));
+ verticalScrollBar()->d_func()->itemviewChangeSingleStep(qMax(vsize.height() / (rowsInViewport + 1), 2));
}
d->geometryRecursionBlock = false;
diff --git a/src/widgets/itemviews/qtreeview.cpp b/src/widgets/itemviews/qtreeview.cpp
index 57092a7cdc..41f1ca7502 100644
--- a/src/widgets/itemviews/qtreeview.cpp
+++ b/src/widgets/itemviews/qtreeview.cpp
@@ -45,6 +45,7 @@
#include <qpen.h>
#include <qdebug.h>
#include <QMetaMethod>
+#include <private/qscrollbar_p.h>
#ifndef QT_NO_ACCESSIBILITY
#include <qaccessible.h>
#endif
@@ -3698,7 +3699,7 @@ void QTreeViewPrivate::updateScrollBars()
}
vbar->setRange(0, contentsHeight - viewportSize.height());
vbar->setPageStep(viewportSize.height());
- vbar->setSingleStep(qMax(viewportSize.height() / (itemsInViewport + 1), 2));
+ vbar->d_func()->itemviewChangeSingleStep(qMax(viewportSize.height() / (itemsInViewport + 1), 2));
}
const int columnCount = header->count();
@@ -3724,7 +3725,7 @@ void QTreeViewPrivate::updateScrollBars()
viewportSize = maxSize;
hbar->setPageStep(viewportSize.width());
hbar->setRange(0, qMax(horizontalLength - viewportSize.width(), 0));
- hbar->setSingleStep(qMax(viewportSize.width() / (columnsInViewport + 1), 2));
+ hbar->d_func()->itemviewChangeSingleStep(qMax(viewportSize.width() / (columnsInViewport + 1), 2));
}
}
diff --git a/src/widgets/widgets/qabstractslider.cpp b/src/widgets/widgets/qabstractslider.cpp
index 8d8c3aa4bc..c2d4d3278f 100644
--- a/src/widgets/widgets/qabstractslider.cpp
+++ b/src/widgets/widgets/qabstractslider.cpp
@@ -205,7 +205,7 @@ QT_BEGIN_NAMESPACE
QAbstractSliderPrivate::QAbstractSliderPrivate()
: minimum(0), maximum(99), pageStep(10), value(0), position(0), pressValue(-1),
- singleStep(1), offset_accumulated(0), tracking(true),
+ singleStep(1), singleStepFromItemView(-1), viewMayChangeSingleStep(true), offset_accumulated(0), tracking(true),
blocktracking(false), pressed(false),
invertedAppearance(false), invertedControls(false),
orientation(Qt::Horizontal), repeatAction(QAbstractSlider::SliderNoAction)
@@ -378,6 +378,11 @@ int QAbstractSlider::maximum() const
void QAbstractSlider::setSingleStep(int step)
{
Q_D(QAbstractSlider);
+
+ d->viewMayChangeSingleStep = (step < 0);
+ if (step < 0 && d->singleStepFromItemView > 0)
+ step = d->singleStepFromItemView;
+
if (step != d->singleStep)
d->setSteps(step, d->pageStep);
}
@@ -936,4 +941,16 @@ bool QAbstractSlider::event(QEvent *e)
return QWidget::event(e);
}
+// This function is called from itemviews when doing scroll per pixel (on updateGeometries())
+// It will not have any effect if there has been a call to setSingleStep with
+// a 'reasonable' value (since viewMayChangeSingleStep will be set to false).
+// (If setSingleStep is called with -1 it will however allow the views to change singleStep.)
+
+void QAbstractSliderPrivate::itemviewChangeSingleStep(int step)
+{
+ singleStepFromItemView = step;
+ if (viewMayChangeSingleStep && singleStep != step)
+ setSteps(step, pageStep);
+}
+
QT_END_NAMESPACE
diff --git a/src/widgets/widgets/qabstractslider_p.h b/src/widgets/widgets/qabstractslider_p.h
index 3df73cf172..32ae55795b 100644
--- a/src/widgets/widgets/qabstractslider_p.h
+++ b/src/widgets/widgets/qabstractslider_p.h
@@ -67,6 +67,8 @@ public:
* Call effectiveSingleStep() when changing the slider value.
*/
int singleStep;
+ int singleStepFromItemView; // If we have itemViews we track the views preferred singleStep value.
+ bool viewMayChangeSingleStep;
float offset_accumulated;
uint tracking : 1;
@@ -108,6 +110,7 @@ public:
#endif
;
}
+ void itemviewChangeSingleStep(int step);
virtual int bound(int val) const { return qMax(minimum, qMin(maximum, val)); }
inline int overflowSafeAdd(int add) const
diff --git a/src/widgets/widgets/qscrollbar.h b/src/widgets/widgets/qscrollbar.h
index 4af5fb4a55..d044ec0519 100644
--- a/src/widgets/widgets/qscrollbar.h
+++ b/src/widgets/widgets/qscrollbar.h
@@ -78,6 +78,13 @@ private:
Q_DISABLE_COPY(QScrollBar)
Q_DECLARE_PRIVATE(QScrollBar)
+#ifndef QT_NO_ITEMVIEWS
+ friend class QTableView;
+ friend class QTreeViewPrivate;
+ friend class QCommonListViewBase;
+ friend class QListModeViewBase;
+ friend class QAbstractItemView;
+#endif
};
#endif // QT_NO_SCROLLBAR
diff --git a/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp b/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp
index 13b953c48b..6540c544cc 100644
--- a/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp
+++ b/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp
@@ -161,6 +161,7 @@ private slots:
void taskQTBUG_39902_mutualScrollBars_data();
void taskQTBUG_39902_mutualScrollBars();
void horizontalScrollingByVerticalWheelEvents();
+ void taskQTBUG_7232_AllowUserToControlSingleStep();
};
// Testing get/set functions
@@ -2469,5 +2470,43 @@ void tst_QListView::horizontalScrollingByVerticalWheelEvents()
QVERIFY(lv.verticalScrollBar()->value() > vValue);
}
+void tst_QListView::taskQTBUG_7232_AllowUserToControlSingleStep()
+{
+ // When we set the scrollMode to ScrollPerPixel it will adjust the scrollbars singleStep automatically
+ // Setting a singlestep on a scrollbar should however imply that the user takes control.
+ // Setting a singlestep to -1 return to an automatic control of the singleStep.
+ QListView lv;
+ lv.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
+ lv.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
+
+ QStandardItemModel model(1000, 100);
+ QString str = QString::fromLatin1("This is a long string made to ensure that we get some horizontal scroll (and we want scroll)");
+ model.setData(model.index(0, 0), str);
+ lv.setModel(&model);
+ lv.setGeometry(150, 150, 150, 150);
+ lv.show();
+ lv.setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
+ lv.setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
+ QVERIFY(QTest::qWaitForWindowExposed(&lv));
+
+ int vStep1 = lv.verticalScrollBar()->singleStep();
+ int hStep1 = lv.horizontalScrollBar()->singleStep();
+ QVERIFY(lv.verticalScrollBar()->singleStep() > 1);
+ QVERIFY(lv.horizontalScrollBar()->singleStep() > 1);
+
+ lv.verticalScrollBar()->setSingleStep(1);
+ lv.setGeometry(200, 200, 200, 200);
+ QCOMPARE(lv.verticalScrollBar()->singleStep(), 1);
+
+ lv.horizontalScrollBar()->setSingleStep(1);
+ lv.setGeometry(150, 150, 150, 150);
+ QCOMPARE(lv.horizontalScrollBar()->singleStep(), 1);
+
+ lv.verticalScrollBar()->setSingleStep(-1);
+ lv.horizontalScrollBar()->setSingleStep(-1);
+ QCOMPARE(vStep1, lv.verticalScrollBar()->singleStep());
+ QCOMPARE(hStep1, lv.horizontalScrollBar()->singleStep());
+}
+
QTEST_MAIN(tst_QListView)
#include "tst_qlistview.moc"
diff --git a/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp b/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp
index 45dab3f2c1..432c03a2df 100644
--- a/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp
+++ b/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp
@@ -214,6 +214,8 @@ private slots:
void changeHeaderData();
void viewOptions();
+
+ void taskQTBUG_7232_AllowUserToControlSingleStep();
};
// Testing get/set functions
@@ -4483,5 +4485,41 @@ void tst_QTableView::taskQTBUG_30653_doItemsLayout()
QCOMPARE(scrollToBottomOffset, doItemsLayoutOffset);
}
+void tst_QTableView::taskQTBUG_7232_AllowUserToControlSingleStep()
+{
+ // When we set the scrollMode to ScrollPerPixel it will adjust the scrollbars singleStep automatically
+ // Setting a singlestep on a scrollbar should however imply that the user takes control (and it is not changed by geometry updates).
+ // Setting a singlestep to -1 return to an automatic control of the singleStep.
+ QTableView t;
+ t.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
+ t.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
+ QStandardItemModel model(200, 200);
+ t.setModel(&model);
+ t.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&t));
+ t.setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
+ t.setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
+
+ t.setGeometry(200, 200, 200, 200);
+ int vStep1 = t.verticalScrollBar()->singleStep();
+ int hStep1 = t.horizontalScrollBar()->singleStep();
+ QVERIFY(vStep1 > 1);
+ QVERIFY(hStep1 > 1);
+
+ t.verticalScrollBar()->setSingleStep(1);
+ t.setGeometry(300, 300, 300, 300);
+ QCOMPARE(t.verticalScrollBar()->singleStep(), 1);
+
+ t.horizontalScrollBar()->setSingleStep(1);
+ t.setGeometry(400, 400, 400, 400);
+ QCOMPARE(t.horizontalScrollBar()->singleStep(), 1);
+
+ t.setGeometry(200, 200, 200, 200);
+ t.verticalScrollBar()->setSingleStep(-1);
+ t.horizontalScrollBar()->setSingleStep(-1);
+ QCOMPARE(vStep1, t.verticalScrollBar()->singleStep());
+ QCOMPARE(hStep1, t.horizontalScrollBar()->singleStep());
+}
+
QTEST_MAIN(tst_QTableView)
#include "tst_qtableview.moc"
diff --git a/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp b/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp
index dec6a66a7f..07413f5040 100644
--- a/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp
+++ b/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp
@@ -255,6 +255,7 @@ private slots:
void taskQTBUG_8176_emitOnExpandAll();
void taskQTBUG_37813_crash();
void taskQTBUG_45697_crash();
+ void taskQTBUG_7232_AllowUserToControlSingleStep();
void testInitialFocus();
};
@@ -4447,5 +4448,47 @@ void tst_QTreeView::taskQTBUG_45697_crash()
QTRY_VERIFY(testWidget.timerTick() >= 2);
}
+void tst_QTreeView::taskQTBUG_7232_AllowUserToControlSingleStep()
+{
+ // When we set the scrollMode to ScrollPerPixel it will adjust the scrollbars singleStep automatically
+ // Setting a singlestep on a scrollbar should however imply that the user takes control.
+ // Setting a singlestep to -1 return to an automatic control of the singleStep.
+ QTreeWidget t;
+ t.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
+ t.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
+ t.setColumnCount(2);
+ QTreeWidgetItem *mainItem = new QTreeWidgetItem(&t, QStringList() << "Root");
+ for (int i = 0; i < 200; ++i) {
+ QTreeWidgetItem *item = new QTreeWidgetItem(mainItem, QStringList(QString("Item")));
+ new QTreeWidgetItem(item, QStringList() << "Child" << "1");
+ new QTreeWidgetItem(item, QStringList() << "Child" << "2");
+ new QTreeWidgetItem(item, QStringList() << "Child" << "3");
+ }
+ t.expandAll();
+
+ t.setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
+ t.setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
+
+ t.setGeometry(200, 200, 200, 200);
+ int vStep1 = t.verticalScrollBar()->singleStep();
+ int hStep1 = t.horizontalScrollBar()->singleStep();
+ QVERIFY(vStep1 > 1);
+ QVERIFY(hStep1 > 1);
+
+ t.verticalScrollBar()->setSingleStep(1);
+ t.setGeometry(300, 300, 300, 300);
+ QCOMPARE(t.verticalScrollBar()->singleStep(), 1);
+
+ t.horizontalScrollBar()->setSingleStep(1);
+ t.setGeometry(400, 400, 400, 400);
+ QCOMPARE(t.horizontalScrollBar()->singleStep(), 1);
+
+ t.setGeometry(200, 200, 200, 200);
+ t.verticalScrollBar()->setSingleStep(-1);
+ t.horizontalScrollBar()->setSingleStep(-1);
+ QCOMPARE(vStep1, t.verticalScrollBar()->singleStep());
+ QCOMPARE(hStep1, t.horizontalScrollBar()->singleStep());
+}
+
QTEST_MAIN(tst_QTreeView)
#include "tst_qtreeview.moc"