1
/****************************************************************************
2
**
3
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4
** All rights reserved.
5
** Contact: Nokia Corporation (qt-info@nokia.com)
6
**
7
** This file is part of the test suite of the Qt Toolkit.
8
**
9
** $QT_BEGIN_LICENSE:LGPL$
10
** GNU Lesser General Public License Usage
11
** This file may be used under the terms of the GNU Lesser General Public
12
** License version 2.1 as published by the Free Software Foundation and
13
** appearing in the file LICENSE.LGPL included in the packaging of this
14
** file. Please review the following information to ensure the GNU Lesser
15
** General Public License version 2.1 requirements will be met:
16
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17
**
18
** In addition, as a special exception, Nokia gives you certain additional
19
** rights. These rights are described in the Nokia Qt LGPL Exception
20
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21
**
22
** GNU General Public License Usage
23
** Alternatively, this file may be used under the terms of the GNU General
24
** Public License version 3.0 as published by the Free Software Foundation
25
** and appearing in the file LICENSE.GPL included in the packaging of this
26
** file. Please review the following information to ensure the GNU General
27
** Public License version 3.0 requirements will be met:
28
** http://www.gnu.org/copyleft/gpl.html.
29
**
30
** Other Usage
31
** Alternatively, this file may be used in accordance with the terms and
32
** conditions contained in a signed written agreement between you and Nokia.
33
**
34
**
35
**
36
**
37
**
38
** $QT_END_LICENSE$
39
**
40
****************************************************************************/
41
42
43
#include <QtTest/QtTest>
44
45
#include <qcoreapplication.h>
46
#include <qdebug.h>
47
#include <qabstractscrollarea.h>
48
#include <qscrollarea.h>
49
#include <qscrollbar.h>
50
#include <qlabel.h>
51
#include <qwidget.h>
52
#include <qdialog.h>
53
54
//TESTED_CLASS=
55
//TESTED_FILES=
56
57
class tst_QAbstractScrollArea : public QObject
58
{
59
Q_OBJECT
60
61
public:
62
    tst_QAbstractScrollArea();
63
    virtual ~tst_QAbstractScrollArea();
64
private slots:
65
    void scrollBarWidgets();
66
    void setScrollBars();
67
    void setScrollBars2();
68
    void objectNaming();
69
    void patternBackground();
70
71
    void viewportCrash();
72
    void task214488_layoutDirection_data();
73
    void task214488_layoutDirection();
74
};
75
76
tst_QAbstractScrollArea::tst_QAbstractScrollArea()
77
{
78
}
79
80
tst_QAbstractScrollArea::~tst_QAbstractScrollArea()
81
{
82
}
83
84
void tst_QAbstractScrollArea::scrollBarWidgets()
85
{
86
    QWidget *w1 = new QWidget(0);
87
    QWidget *w2 = new QWidget(0);
88
    QWidget *w3 = new QWidget(0);
89
90
    Qt::Alignment all = Qt::AlignLeft | Qt::AlignRight | Qt::AlignTop | Qt::AlignBottom;
91
92
    QWidgetList w1List = QWidgetList() << w1;
93
    QWidgetList w2List = QWidgetList() << w2;
94
    QWidgetList w3List = QWidgetList() << w3;
95
96
    QWidgetList w1w2List = w1List + w2List;
97
    QWidgetList allList = w1List + w2List + w3List;
98
99
    QAbstractScrollArea area;
100
    area.show();
101
    QCOMPARE(area.scrollBarWidgets(all), QWidgetList());
102
103
    area.addScrollBarWidget(w1, Qt::AlignLeft);
104
    QCOMPARE(area.scrollBarWidgets(all), w1List);
105
    QCOMPARE(area.scrollBarWidgets(Qt::AlignLeft), w1List);
106
    QCOMPARE(area.scrollBarWidgets(Qt::AlignRight), QWidgetList());
107
    QCOMPARE(area.scrollBarWidgets(Qt::AlignTop), QWidgetList());
108
    QCOMPARE(area.scrollBarWidgets(Qt::AlignBottom), QWidgetList());
109
110
    area.addScrollBarWidget(w2, Qt::AlignBottom);
111
    QCOMPARE(area.scrollBarWidgets(all), w1w2List);
112
    QCOMPARE(area.scrollBarWidgets(Qt::AlignLeft), w1List);
113
    QCOMPARE(area.scrollBarWidgets(Qt::AlignRight), QWidgetList());
114
    QCOMPARE(area.scrollBarWidgets(Qt::AlignTop), QWidgetList());
115
    QCOMPARE(area.scrollBarWidgets(Qt::AlignBottom), w2List);
116
117
    // duplicate add
118
    area.addScrollBarWidget(w2, Qt::AlignBottom);
119
    QCOMPARE(area.scrollBarWidgets(all), w1w2List);
120
    QCOMPARE(area.scrollBarWidgets(Qt::AlignLeft), w1List);
121
    QCOMPARE(area.scrollBarWidgets(Qt::AlignRight), QWidgetList());
122
    QCOMPARE(area.scrollBarWidgets(Qt::AlignTop), QWidgetList());
123
    QCOMPARE(area.scrollBarWidgets(Qt::AlignBottom), w2List);
124
125
    //reparent
126
    w2->setParent(w1);
127
    QCOMPARE(area.scrollBarWidgets(all), w1List);
128
    QCOMPARE(area.scrollBarWidgets(Qt::AlignLeft), w1List);
129
    QCOMPARE(area.scrollBarWidgets(Qt::AlignRight), QWidgetList());
130
    QCOMPARE(area.scrollBarWidgets(Qt::AlignTop), QWidgetList());
131
    QCOMPARE(area.scrollBarWidgets(Qt::AlignBottom), QWidgetList());
132
133
    // add after reparent
134
    area.addScrollBarWidget(w2, Qt::AlignBottom);
135
    QCOMPARE(area.scrollBarWidgets(all), w1w2List);
136
    QCOMPARE(area.scrollBarWidgets(Qt::AlignLeft), w1List);
137
    QCOMPARE(area.scrollBarWidgets(Qt::AlignRight), QWidgetList());
138
    QCOMPARE(area.scrollBarWidgets(Qt::AlignTop), QWidgetList());
139
    QCOMPARE(area.scrollBarWidgets(Qt::AlignBottom), w2List);
140
141
    // two widgets at Bottom.
142
    area.addScrollBarWidget(w3, Qt::AlignBottom);
143
    QCOMPARE(area.scrollBarWidgets(all).toSet(), allList.toSet());
144
    QCOMPARE(area.scrollBarWidgets(Qt::AlignLeft), w1List);
145
    QCOMPARE(area.scrollBarWidgets(Qt::AlignRight), QWidgetList());
146
    QCOMPARE(area.scrollBarWidgets(Qt::AlignTop), QWidgetList());
147
    QCOMPARE(area.scrollBarWidgets(Qt::AlignBottom).toSet(), (w2List + w3List).toSet());
148
149
    //delete
150
    delete w1;
151
    delete w2;
152
    delete w3;
153
154
    QCOMPARE(area.scrollBarWidgets(all), QWidgetList());
155
    QCOMPARE(area.scrollBarWidgets(Qt::AlignLeft), QWidgetList());
156
    QCOMPARE(area.scrollBarWidgets(Qt::AlignRight), QWidgetList());
157
    QCOMPARE(area.scrollBarWidgets(Qt::AlignTop), QWidgetList());
158
    QCOMPARE(area.scrollBarWidgets(Qt::AlignBottom), QWidgetList());
159
}
160
161
void tst_QAbstractScrollArea::setScrollBars()
162
{
163
    QScrollArea scrollArea;
164
    scrollArea.resize(300, 300);
165
    scrollArea.show();
166
167
    QPointer<QScrollBar> vbar = scrollArea.verticalScrollBar();
168
    QPointer<QScrollBar> hbar = scrollArea.horizontalScrollBar();
169
170
    // Now set properties on the scroll bars
171
    scrollArea.verticalScrollBar()->setInvertedAppearance(true);
172
    scrollArea.verticalScrollBar()->setInvertedControls(true);
173
    scrollArea.verticalScrollBar()->setTracking(true);
174
    scrollArea.verticalScrollBar()->setRange(-100, 100);
175
    scrollArea.verticalScrollBar()->setPageStep(42);
176
    scrollArea.verticalScrollBar()->setSingleStep(3);
177
    scrollArea.verticalScrollBar()->setValue(43);
178
    scrollArea.horizontalScrollBar()->setInvertedAppearance(true);
179
    scrollArea.horizontalScrollBar()->setInvertedControls(true);
180
    scrollArea.horizontalScrollBar()->setTracking(true);
181
    scrollArea.horizontalScrollBar()->setRange(-100, 100);
182
    scrollArea.horizontalScrollBar()->setPageStep(42);
183
    scrollArea.horizontalScrollBar()->setSingleStep(3);
184
    scrollArea.horizontalScrollBar()->setValue(43);
185
186
    qApp->processEvents();
187
188
    // Then replace the scroll bars
189
    scrollArea.setVerticalScrollBar(new QScrollBar);
190
    scrollArea.setHorizontalScrollBar(new QScrollBar);
191
192
    // Check that the old ones were deleted
193
    QVERIFY(!vbar);
194
    QVERIFY(!hbar);
195
196
    qApp->processEvents();
197
198
    // Check that all properties have been populated
199
    QVERIFY(scrollArea.verticalScrollBar()->invertedAppearance());
200
    QVERIFY(scrollArea.verticalScrollBar()->invertedControls());
201
    QVERIFY(scrollArea.verticalScrollBar()->hasTracking());
202
    QVERIFY(scrollArea.verticalScrollBar()->isVisible());
203
    QCOMPARE(scrollArea.verticalScrollBar()->minimum(), -100);
204
    QCOMPARE(scrollArea.verticalScrollBar()->maximum(), 100);
205
    QCOMPARE(scrollArea.verticalScrollBar()->pageStep(), 42);
206
    QCOMPARE(scrollArea.verticalScrollBar()->singleStep(), 3);
207
    QCOMPARE(scrollArea.verticalScrollBar()->value(), 43);
208
    QVERIFY(scrollArea.horizontalScrollBar()->invertedAppearance());
209
    QVERIFY(scrollArea.horizontalScrollBar()->invertedControls());
210
    QVERIFY(scrollArea.horizontalScrollBar()->hasTracking());
211
    QVERIFY(scrollArea.horizontalScrollBar()->isVisible());
212
    QCOMPARE(scrollArea.horizontalScrollBar()->minimum(), -100);
213
    QCOMPARE(scrollArea.horizontalScrollBar()->maximum(), 100);
214
    QCOMPARE(scrollArea.horizontalScrollBar()->pageStep(), 42);
215
    QCOMPARE(scrollArea.horizontalScrollBar()->singleStep(), 3);
216
    QCOMPARE(scrollArea.horizontalScrollBar()->value(), 43);
217
}
218
219
void tst_QAbstractScrollArea::setScrollBars2()
220
{
221
    QAbstractScrollArea scrollArea;
222
    scrollArea.resize(300, 300);
223
224
    QScrollBar *hbar = new QScrollBar;
225
    scrollArea.setHorizontalScrollBar(hbar);
226
    qApp->processEvents();
227
    QCOMPARE(scrollArea.horizontalScrollBar(), hbar);
228
229
    QScrollBar *vbar = new QScrollBar;
230
    scrollArea.setVerticalScrollBar(vbar);
231
    qApp->processEvents();
232
    QCOMPARE(scrollArea.verticalScrollBar(), vbar);
233
234
    scrollArea.horizontalScrollBar()->setRange(0, 100);
235
    scrollArea.verticalScrollBar()->setRange(0, 100);
236
    scrollArea.show();
237
238
    // Make sure scroll bars are not explicitly hidden by QAbstractScrollArea itself.
239
    QVERIFY(hbar->isVisible());
240
    QVERIFY(vbar->isVisible());
241
242
    // Hide the OLD scroll bar and ensure that the NEW one is hidden.
243
    hbar->hide();
244
    scrollArea.setHorizontalScrollBar(new QScrollBar);
245
    qApp->processEvents();
246
    QVERIFY(!scrollArea.horizontalScrollBar()->isVisible());
247
248
    vbar->hide();
249
    scrollArea.setVerticalScrollBar(new QScrollBar);
250
    qApp->processEvents();
251
    QVERIFY(!scrollArea.verticalScrollBar()->isVisible());
252
253
    scrollArea.verticalScrollBar()->show();
254
    scrollArea.horizontalScrollBar()->show();
255
256
    // Hide the NEW scroll bar and ensure that it's visible
257
    // (because the OLD one is visible).
258
    hbar = new QScrollBar;
259
    hbar->hide();
260
    scrollArea.setHorizontalScrollBar(hbar);
261
    qApp->processEvents();
262
    QVERIFY(hbar->isVisible());
263
264
    vbar = new QScrollBar;
265
    vbar->hide();
266
    scrollArea.setVerticalScrollBar(vbar);
267
    qApp->processEvents();
268
    QVERIFY(vbar->isVisible());
269
270
    vbar->setRange(0, 0);
271
    qApp->processEvents();
272
    QVERIFY(!vbar->isVisible());
273
274
    hbar->setRange(0, 0);
275
    qApp->processEvents();
276
    QVERIFY(!hbar->isVisible());
277
}
278
279
// we need to make sure the viewport internal widget is named
280
// qt_scrollarea_viewport, otherwise we're going to confuse Squish
281
// and friends.
282
void tst_QAbstractScrollArea::objectNaming()
283
{
284
    QScrollArea area;
285
    QCOMPARE(area.viewport()->objectName(), QString("qt_scrollarea_viewport"));
286
}
287
288
class ViewportCrashWidget : public QDialog
289
{
290
public:
291
    ViewportCrashWidget()
292
    {
293
        // temprorary set PaintOnScreen to set the nativeChildrenForced flag.
294
        setAttribute(Qt::WA_PaintOnScreen, true);
295
        setAttribute(Qt::WA_PaintOnScreen, false);
296
297
        setAttribute(Qt::WA_DropSiteRegistered, true);
298
299
        startTimer(2000);
300
    }
301
302
    void timerEvent(QTimerEvent *event)
303
    {
304
        // should not crash.
305
        (void)new QScrollArea(this);
306
        accept();
307
    }
308
};
309
310
void tst_QAbstractScrollArea::viewportCrash()
311
{
312
    ViewportCrashWidget w;
313
    // should not crash
314
    w.exec();
315
}
316
317
Q_DECLARE_METATYPE(Qt::LayoutDirection);
318
Q_DECLARE_METATYPE(Qt::Key);
319
320
void tst_QAbstractScrollArea::task214488_layoutDirection_data()
321
{
322
    QTest::addColumn<Qt::LayoutDirection>("dir");
323
    QTest::addColumn<Qt::Key>("key");
324
    QTest::addColumn<bool>("lessThan");
325
326
    QTest::newRow("LTR left")  << Qt::LeftToRight << Qt::Key_Left << true;
327
    QTest::newRow("LTR right") << Qt::LeftToRight << Qt::Key_Right << false;
328
    QTest::newRow("RTL left")  << Qt::RightToLeft << Qt::Key_Left << false;
329
    QTest::newRow("RTL right") << Qt::RightToLeft << Qt::Key_Right << true;
330
}
331
332
void tst_QAbstractScrollArea::task214488_layoutDirection()
333
{
334
    QScrollArea scrollArea;
335
    scrollArea.resize(200, 200);
336
    QWidget widget;
337
    widget.resize(600, 600);
338
    scrollArea.setWidget(&widget);
339
    scrollArea.show();
340
    QScrollBar *hbar = scrollArea.horizontalScrollBar();
341
    hbar->setValue((hbar->minimum() + hbar->maximum()) / 2);
342
343
    QFETCH(Qt::LayoutDirection, dir);
344
    QFETCH(Qt::Key, key);
345
    QFETCH(bool, lessThan);
346
347
    scrollArea.setLayoutDirection(dir);
348
349
    int refValue = hbar->value();
350
    qApp->sendEvent(&scrollArea, new QKeyEvent(QEvent::KeyPress, key, Qt::NoModifier));
351
    QVERIFY(lessThan ? (hbar->value() < refValue) : (hbar->value() > refValue));
352
}
353
354
void tst_QAbstractScrollArea::patternBackground()
355
{
356
    QWidget topLevel;
357
    QScrollArea scrollArea(&topLevel);
358
    scrollArea.resize(200, 200);
359
    QWidget widget;
360
    widget.resize(600, 600);
361
    scrollArea.setWidget(&widget);
362
    topLevel.show();
363
364
    QLinearGradient linearGrad(QPointF(250, 250), QPointF(300, 300));
365
    linearGrad.setColorAt(0, Qt::yellow);
366
    linearGrad.setColorAt(1, Qt::red);
367
    QBrush bg(linearGrad);
368
    scrollArea.viewport()->setPalette(QPalette(Qt::black, bg, bg, bg, bg, bg, bg, bg, bg));
369
    widget.setPalette(Qt::transparent);
370
371
    QTest::qWait(50);
372
373
    QImage image(200, 200, QImage::Format_ARGB32);
374
    scrollArea.render(&image);
375
376
    QCOMPARE(image.pixel(QPoint(20,20)) , QColor(Qt::yellow).rgb());
377
378
    QScrollBar *hbar = scrollArea.horizontalScrollBar();
379
    hbar->setValue(hbar->maximum());
380
    QScrollBar *vbar = scrollArea.verticalScrollBar();
381
    vbar->setValue(vbar->maximum());
382
383
    QTest::qWait(50);
384
385
    scrollArea.render(&image);
386
    QCOMPARE(image.pixel(QPoint(20,20)) , QColor(Qt::red).rgb());
387
}
388
389
QTEST_MAIN(tst_QAbstractScrollArea)
390
#include "tst_qabstractscrollarea.moc"