1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the test suite of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28
29
30#include <QtTest/QtTest>
31#include <QScrollBar>
32#include <QStyleOptionSlider>
33#include <QScrollArea>
34#include <QScreen>
35
36#include <QtTest/private/qtesthelpers_p.h>
37
38using namespace QTestPrivate;
39
40class tst_QScrollBar : public QObject
41{
42 Q_OBJECT
43private slots:
44 void scrollSingleStep();
45 void task_209492();
46#if QT_CONFIG(wheelevent)
47 void QTBUG_27308();
48#endif
49 void QTBUG_42871();
50};
51
52class SingleStepTestScrollBar : public QScrollBar {
53 Q_OBJECT
54public:
55 explicit SingleStepTestScrollBar(Qt::Orientation o, QWidget *parent = 0) : QScrollBar(o, parent) {}
56
57public slots:
58 void hideAndShow()
59 {
60 hide();
61 show();
62 }
63};
64
65// Check that the scrollbar doesn't scroll after calling hide and show
66// from a slot connected to the scrollbar's actionTriggered signal.
67void tst_QScrollBar::scrollSingleStep()
68{
69 SingleStepTestScrollBar testWidget(Qt::Horizontal);
70 connect(sender: &testWidget, signal: &QAbstractSlider::actionTriggered, receiver: &testWidget, slot: &SingleStepTestScrollBar::hideAndShow);
71 testWidget.resize(w: 100, h: testWidget.height());
72 centerOnScreen(w: &testWidget);
73 testWidget.show();
74 QVERIFY(QTest::qWaitForWindowExposed(&testWidget));
75
76 testWidget.setValue(testWidget.minimum());
77 QCOMPARE(testWidget.value(), testWidget.minimum());
78
79 // Get rect for the area to click on
80 const QStyleOptionSlider opt = qt_qscrollbarStyleOption(scrollBar: &testWidget);
81 QRect sr = testWidget.style()->subControlRect(cc: QStyle::CC_ScrollBar, opt: &opt,
82 sc: QStyle::SC_ScrollBarAddLine, widget: &testWidget);
83
84 if (!sr.isValid())
85 QSKIP("SC_ScrollBarAddLine not valid");
86
87 QTest::mouseClick(widget: &testWidget, button: Qt::LeftButton, stateKey: Qt::NoModifier, pos: QPoint(sr.x(), sr.y()));
88 QTest::qWait(ms: 510); // initial delay is 500 for setRepeatAction
89 disconnect(sender: &testWidget, signal: &QAbstractSlider::actionTriggered, receiver: &testWidget, slot: &SingleStepTestScrollBar::hideAndShow);
90#ifdef Q_OS_MAC
91 QEXPECT_FAIL("", "This test fails on OS X, see QTBUG-25272", Abort);
92#endif
93 QCOMPARE(testWidget.value(), testWidget.singleStep());
94}
95
96void tst_QScrollBar::task_209492()
97{
98 class MyScrollArea : public QScrollArea
99 {
100 public:
101 int scrollCount;
102 MyScrollArea(QWidget *parent = 0) : QScrollArea(parent), scrollCount(0) {}
103 protected:
104 void paintEvent(QPaintEvent *) { QTest::qSleep(ms: 600); }
105 void scrollContentsBy(int, int) { ++scrollCount; viewport()->update(); }
106 };
107
108 MyScrollArea scrollArea;
109 QScrollBar *verticalScrollBar = scrollArea.verticalScrollBar();
110 verticalScrollBar->setRange(min: 0, max: 1000);
111 centerOnScreen(w: &scrollArea);
112 scrollArea.show();
113 QVERIFY(QTest::qWaitForWindowExposed(&scrollArea));
114
115 QSignalSpy spy(verticalScrollBar, SIGNAL(actionTriggered(int)));
116 QCOMPARE(scrollArea.scrollCount, 0);
117 QCOMPARE(spy.count(), 0);
118
119 // Simulate a mouse click on the "scroll down button".
120 const QPoint pressPoint(verticalScrollBar->width() / 2, verticalScrollBar->height() - 10);
121 const QPoint globalPressPoint = verticalScrollBar->mapToGlobal(globalPressPoint);
122 QMouseEvent mousePressEvent(QEvent::MouseButtonPress, pressPoint, globalPressPoint,
123 Qt::LeftButton, Qt::LeftButton, {});
124 QApplication::sendEvent(receiver: verticalScrollBar, event: &mousePressEvent);
125 QTest::qWait(ms: 1);
126 QMouseEvent mouseReleaseEvent(QEvent::MouseButtonRelease, pressPoint, globalPressPoint,
127 Qt::LeftButton, Qt::LeftButton, {});
128 QApplication::sendEvent(receiver: verticalScrollBar, event: &mouseReleaseEvent);
129
130 // Check that the action was triggered once.
131
132#ifdef Q_OS_MAC
133 QSKIP("The result depends on system setting and is not relevant on Mac");
134#endif
135 QCOMPARE(scrollArea.scrollCount, 1);
136 QCOMPARE(spy.count(), 1);
137}
138
139#if QT_CONFIG(wheelevent)
140#define WHEEL_DELTA 120 // copied from tst_QAbstractSlider / tst_QComboBox
141void tst_QScrollBar::QTBUG_27308()
142{
143 // QTBUG-27308
144 // Check that a disabled scrollbar doesn't react on wheel events anymore
145
146 QScrollBar testWidget(Qt::Horizontal);
147 testWidget.resize(w: 100, h: testWidget.height());
148 centerOnScreen(w: &testWidget);
149 testWidget.show();
150 QVERIFY(QTest::qWaitForWindowExposed(&testWidget));
151
152 testWidget.setValue(testWidget.minimum());
153 testWidget.setEnabled(false);
154 const QPoint wheelPoint = testWidget.rect().center();
155 const QPoint angleDelta(testWidget.orientation() == Qt::Horizontal ? -WHEEL_DELTA : 0,
156 testWidget.orientation() == Qt::Vertical ? -WHEEL_DELTA : 0);
157 QWheelEvent event(wheelPoint, testWidget.mapToGlobal(wheelPoint), QPoint(), angleDelta,
158 Qt::NoButton, Qt::NoModifier, Qt::NoScrollPhase, false);
159 qApp->sendEvent(receiver: &testWidget, event: &event);
160 QCOMPARE(testWidget.value(), testWidget.minimum());
161}
162#endif
163
164class QTBUG_42871_Handler : public QObject {
165 Q_OBJECT
166public:
167 int updatesCount;
168 QTBUG_42871_Handler() : QObject(), updatesCount(0) {}
169public slots:
170 void valueUpdated(int) { ++updatesCount; QTest::qSleep(ms: 600); }
171};
172
173void tst_QScrollBar::QTBUG_42871()
174{
175 QTBUG_42871_Handler myHandler;
176 QScrollBar scrollBarWidget(Qt::Vertical);
177 bool connection = connect(sender: &scrollBarWidget, SIGNAL(valueChanged(int)), receiver: &myHandler, SLOT(valueUpdated(int)));
178 QVERIFY(connection);
179 scrollBarWidget.resize(w: 100, h: scrollBarWidget.height());
180 centerOnScreen(w: &scrollBarWidget);
181 scrollBarWidget.show();
182 QVERIFY(QTest::qWaitForWindowExposed(&scrollBarWidget));
183 QSignalSpy spy(&scrollBarWidget, SIGNAL(actionTriggered(int)));
184 QVERIFY(spy.isValid());
185 QCOMPARE(myHandler.updatesCount, 0);
186 QCOMPARE(spy.count(), 0);
187
188 // Simulate a mouse click on the "scroll down button".
189 const QPoint pressPoint(scrollBarWidget.width() / 2, scrollBarWidget.height() - 10);
190 const QPoint globalPressPoint = scrollBarWidget.mapToGlobal(pressPoint);
191 QMouseEvent mousePressEvent(QEvent::MouseButtonPress, pressPoint, globalPressPoint,
192 Qt::LeftButton, Qt::LeftButton, {});
193 QApplication::sendEvent(receiver: &scrollBarWidget, event: &mousePressEvent);
194 QTest::qWait(ms: 1);
195 QMouseEvent mouseReleaseEvent(QEvent::MouseButtonRelease, pressPoint, globalPressPoint,
196 Qt::LeftButton, Qt::LeftButton, {});
197 QApplication::sendEvent(receiver: &scrollBarWidget, event: &mouseReleaseEvent);
198 // Check that the action was triggered once.
199 QCOMPARE(myHandler.updatesCount, 1);
200 QCOMPARE(spy.count(), 1);
201}
202
203QTEST_MAIN(tst_QScrollBar)
204#include "tst_qscrollbar.moc"
205

source code of qtbase/tests/auto/widgets/widgets/qscrollbar/tst_qscrollbar.cpp