Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
viewtestutils.cpp
Go to the documentation of this file.
1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include "viewtestutils_p.h"
5
6#include <QtCore/QRandomGenerator>
7#include <QtCore/QTimer>
8#include <QtQuick/QQuickView>
9#include <QtQuick/QQuickView>
10#include <QtGui/QScreen>
11#include <QtGui/qpa/qwindowsysteminterface.h>
12
13#include <QtTest/QTest>
14
15#include <QtQuick/private/qquickdeliveryagent_p_p.h>
16#if QT_CONFIG(quick_itemview)
17#include <QtQuick/private/qquickitemview_p_p.h>
18#endif
19#include <QtQuick/private/qquickwindow_p.h>
20
21#include <QtQuickTestUtils/private/visualtestutils_p.h>
22
24
33
35{
36 const QRect screenGeometry = window->screen()->availableGeometry();
37 const QPoint offset = QPoint(size.width() / 2, size.height() / 2);
38 window->setFramePosition(screenGeometry.center() - offset);
39}
40
45
47{
48#if QT_CONFIG(cursor) // Get the cursor out of the way.
49 QCursor::setPos(window->geometry().topRight() + QPoint(100, 100));
50#else
52#endif
53}
54
60
66
67void QQuickViewTestUtils::flick(QQuickView *window, const QPoint &from, const QPoint &to, int duration)
68{
69 const int pointCount = 5;
70 QPoint diff = to - from;
71
72 // send press, five equally spaced moves, and release.
73 moveAndPress(window, from);
74
75 for (int i = 0; i < pointCount; ++i)
76 QTest::mouseMove(window, from + (i+1)*diff/pointCount, duration / pointCount);
77
79 QTest::qWait(50);
80}
81
82QList<int> QQuickViewTestUtils::adjustIndexesForAddDisplaced(const QList<int> &indexes, int index, int count)
83{
84 QList<int> result;
85 for (int i=0; i<indexes.size(); i++) {
86 int num = indexes[i];
87 if (num >= index) {
88 num += count;
89 }
90 result << num;
91 }
92 return result;
93}
94
95QList<int> QQuickViewTestUtils::adjustIndexesForMove(const QList<int> &indexes, int from, int to, int count)
96{
97 QList<int> result;
98 for (int i=0; i<indexes.size(); i++) {
99 int num = indexes[i];
100 if (from < to) {
101 if (num >= from && num < from + count)
102 num += (to - from); // target
103 else if (num >= from && num < to + count)
104 num -= count; // displaced
105 } else if (from > to) {
106 if (num >= from && num < from + count)
107 num -= (from - to); // target
108 else if (num >= to && num < from + count)
109 num += count; // displaced
110 }
111 result << num;
112 }
113 return result;
114}
115
116QList<int> QQuickViewTestUtils::adjustIndexesForRemoveDisplaced(const QList<int> &indexes, int index, int count)
117{
118 QList<int> result;
119 for (int i=0; i<indexes.size(); i++) {
120 int num = indexes[i];
121 if (num >= index)
122 num -= count;
123 result << num;
124 }
125 return result;
126}
127
132
134{
135 Q_UNUSED(parent);
136 return list.size();
137}
138
140{
141 Q_UNUSED(parent);
142 return columns;
143}
144
145QHash<int,QByteArray> QQuickViewTestUtils::QaimModel::roleNames() const
146{
147 QHash<int,QByteArray> roles = QAbstractListModel::roleNames();
148 roles.insert(Name, "name");
149 roles.insert(Number, "number");
150 return roles;
151}
152
154{
155 QVariant rv;
156 if (role == Name)
157 rv = list.at(index.row()).first;
158 else if (role == Number)
159 rv = list.at(index.row()).second;
160
161 return rv;
162}
163
165{
166 return rowCount() * columnCount();
167}
168
170{
171 return list.at(index).first;
172}
173
175{
176 return list.at(index).second;
177}
178
180{
182 list.append(QPair<QString,QString>(name, number));
183 emit endInsertRows();
184}
185
186void QQuickViewTestUtils::QaimModel::addItems(const QList<QPair<QString, QString> > &items)
187{
189 for (int i=0; i<items.size(); i++)
190 list.append(QPair<QString,QString>(items[i].first, items[i].second));
191 emit endInsertRows();
192}
193
195{
197 list.insert(index, QPair<QString,QString>(name, number));
198 emit endInsertRows();
199}
200
201void QQuickViewTestUtils::QaimModel::insertItems(int index, const QList<QPair<QString, QString> > &items)
202{
204 for (int i=0; i<items.size(); i++)
205 list.insert(index + i, QPair<QString,QString>(items[i].first, items[i].second));
206 emit endInsertRows();
207}
208
215
217{
219 while (count--)
221 emit endRemoveRows();
222}
223
225{
226 emit beginMoveRows(QModelIndex(), from, from, QModelIndex(), to);
227 list.move(from, to);
228 emit endMoveRows();
229}
230
232{
233 emit beginMoveRows(QModelIndex(), from, from+count-1, QModelIndex(), to > from ? to+count : to);
235 emit endMoveRows();
236}
237
239{
240 list[idx] = QPair<QString,QString>(name, number);
241 emit dataChanged(index(idx,0), index(idx,0));
242}
243
245{
246 int count = list.size();
247 if (count > 0) {
249 list.clear();
250 endRemoveRows();
251 }
252}
253
255{
256 emit beginResetModel();
257 emit endResetModel();
258}
259
260void QQuickViewTestUtils::QaimModel::resetItems(const QList<QPair<QString, QString> > &items)
261{
262 beginResetModel();
263 list = items;
264 endResetModel();
265}
266
268{
269 Q_DISABLE_COPY_MOVE(ScopedPrintable)
270
271public:
273 ~ScopedPrintable() { delete[] data; }
274
275 operator const char*() const { return data; }
276
277private:
278 const char *data;
279};
280
281void QQuickViewTestUtils::QaimModel::matchAgainst(const QList<QPair<QString, QString> > &other, const QString &error1, const QString &error2) {
282 for (int i=0; i<other.size(); i++) {
284 ScopedPrintable(other[i].first + QLatin1Char(' ') + other[i].second + QLatin1Char(' ') + error1));
285 }
286 for (int i=0; i<list.size(); i++) {
287 QVERIFY2(other.contains(list[i]),
288 ScopedPrintable(list[i].first + QLatin1Char(' ') + list[i].second + QLatin1Char(' ') + error2));
289 }
290}
291
292
293
298
300 : valid(other.valid)
301{
302 indexes = other.indexes;
303}
304
306 : valid(true)
307{
308 for (int i=start; i<=end; i++)
309 indexes << i;
310}
311
315
317{
318 if (other == *this)
319 return *this;
320 ListRange a(*this);
321 a.indexes.append(other.indexes);
322 return a;
323}
324
326{
327 return QSet<int>(indexes.cbegin(), indexes.cend())
328 == QSet<int>(other.indexes.cbegin(), other.indexes.cend());
329}
330
332{
333 return !(*this == other);
334}
335
337{
338 return valid;
339}
340
342{
343 return indexes.size();
344}
345
347{
348 QList<QPair<QString,QString> > data;
349 if (!valid)
350 return data;
351 for (int i=0; i<indexes.size(); i++)
352 data.append(qMakePair(model.name(indexes[i]), model.number(indexes[i])));
353 return data;
354}
355
358 , m_rowCount(20)
359{
360 QTimer *t = new QTimer(this);
361 t->setInterval(500);
362 t->start();
363
365}
366
368{
369 return m_rowCount;
370}
371
376
378{
379 if (m_rowCount > 10) {
380 for (int i = 0; i < 10; ++i) {
381 int rnum = QRandomGenerator::global()->bounded(m_rowCount);
382 beginRemoveRows(QModelIndex(), rnum, rnum);
383 m_rowCount--;
384 endRemoveRows();
385 }
386 }
387 if (m_rowCount < 20) {
388 for (int i = 0; i < 10; ++i) {
389 int rnum = QRandomGenerator::global()->bounded(m_rowCount);
390 beginInsertRows(QModelIndex(), rnum, rnum);
391 m_rowCount++;
392 endInsertRows();
393 }
394 }
395}
396
397#if QT_CONFIG(quick_itemview) && defined(QT_BUILD_INTERNAL)
398bool QQuickViewTestUtils::testVisibleItems(const QQuickItemViewPrivate *priv, bool *nonUnique, FxViewItem **failItem, int *expectedIdx)
399{
400 QHash<QQuickItem*, int> uniqueItems;
401
402 int skip = 0;
403 for (int i = 0; i < priv->visibleItems.size(); ++i) {
404 FxViewItem *item = priv->visibleItems.at(i);
405 if (!item) {
406 *failItem = nullptr;
407 return false;
408 }
409#if 0
410 qDebug() << "\t" << item->index
411 << item->item
412 << item->position()
413 << (!item->item || QQuickItemPrivate::get(item->item)->culled ? "hidden" : "visible");
414#endif
415 if (item->index == -1) {
416 ++skip;
417 } else if (item->index != priv->visibleIndex + i - skip) {
418 *nonUnique = false;
419 *failItem = item;
420 *expectedIdx = priv->visibleIndex + i - skip;
421 return false;
422 } else if (uniqueItems.contains(item->item)) {
423 *nonUnique = true;
424 *failItem = item;
425 *expectedIdx = uniqueItems.find(item->item).value();
426 return false;
427 }
428
429 uniqueItems.insert(item->item, item->index);
430 }
431
432 return true;
433}
434#endif
435
437
438 /* QQuickWindow does event compression and only delivers events just
439 * before it is about to render the next frame. Since some tests
440 * rely on events being delivered immediately AND that no other
441 * event processing has occurred in the meanwhile, we flush the
442 * event manually and immediately.
443 */
444 void flush(QQuickWindow *window) {
445 if (!window)
446 return;
447 QQuickDeliveryAgentPrivate *da = QQuickWindowPrivate::get(window)->deliveryAgentPrivate();
448 if (!da || !da->delayedTouch)
449 return;
450 da->deliverDelayedTouchEvent();
451 }
452
453}
454
455namespace QTest {
456 int Q_TESTLIB_EXPORT defaultMouseDelay();
457}
458
459namespace QQuickTest {
460
469 bool initView(QQuickView &view, const QUrl &url, bool moveMouseOut, QByteArray *errorMessage)
470 {
472 while (view.status() == QQuickView::Loading)
473 QTest::qWait(10);
474 if (view.status() != QQuickView::Ready) {
475 if (errorMessage) {
476 for (const QQmlError &e : view.errors())
477 errorMessage->append(e.toString().toLocal8Bit() + '\n');
478 }
479 return false;
480 }
481 const QRect screenGeometry = view.screen()->availableGeometry();
482 const QSize size = view.size();
483 if (view.width() == 0)
484 view.setWidth(100);
485 if (view.height() == 0)
486 view.setHeight(100);
487 const QPoint offset = QPoint(size.width() / 2, size.height() / 2);
488 view.setFramePosition(screenGeometry.center() - offset);
489 #if QT_CONFIG(cursor) // Get the cursor out of the way.
490 if (moveMouseOut)
491 QCursor::setPos(view.geometry().topRight() + QPoint(100, 100));
492 #else
493 Q_UNUSED(moveMouseOut);
494 #endif
495 return true;
496 }
497
510 {
511 if (!initView(view, url))
512 return false;
513 view.show();
515 return false;
516 if (!view.rootObject())
517 return false;
518 return true;
519 }
520
521 // TODO maybe move the generic pointerPress/Move/Release functions to QTestLib later on
522
524 static Qt::KeyboardModifiers pressedTabletModifiers = Qt::NoModifier;
525
526 void pointerPress(const QPointingDevice *dev, QQuickWindow *window, int pointId, const QPoint &p,
527 Qt::MouseButton button, Qt::KeyboardModifiers modifiers)
528 {
529 switch (dev->type()) {
533 break;
535 QTest::touchEvent(window, const_cast<QPointingDevice *>(dev)).press(pointId, p, window);
537 break;
545 button, 0.8, 0, 0, 0, 0, 0, modifiers);
546 break;
547 default:
548 qWarning() << "can't send a press event from" << dev;
549 break;
550 }
551 }
552
553 void pointerMove(const QPointingDevice *dev, QQuickWindow *window, int pointId, const QPoint &p)
554 {
555 switch (dev->type()) {
559 break;
561 QTest::touchEvent(window, const_cast<QPointingDevice *>(dev)).move(pointId, p, window);
563 break;
570 break;
571 default:
572 qWarning() << "can't send a move event from" << dev;
573 break;
574 }
575 }
576
577 void pointerRelease(const QPointingDevice *dev, QQuickWindow *window, int pointId, const QPoint &p,
578 Qt::MouseButton button, Qt::KeyboardModifiers modifiers)
579 {
580 switch (dev->type()) {
584 break;
586 QTest::touchEvent(window, const_cast<QPointingDevice *>(dev)).release(pointId, p, window);
588 break;
594 Qt::NoButton, 0, 0, 0, 0, 0, 0, modifiers);
595 break;
596 default:
597 qWarning() << "can't send a press event from" << dev;
598 break;
599 }
600 }
601
602}
603
605
606#include "moc_viewtestutils_p.cpp"
virtual QHash< int, QByteArray > roleNames() const
\inmodule QtCore
Definition qbytearray.h:57
static void setPos(int x, int y)
Moves the cursor (hot spot) of the primary screen to the global screen position (x,...
Definition qcursor.cpp:240
DeviceType type
Definition qlist.h:75
qsizetype size() const noexcept
Definition qlist.h:397
T & first()
Definition qlist.h:645
void removeAt(qsizetype i)
Definition qlist.h:590
iterator insert(qsizetype i, parameter_type t)
Definition qlist.h:488
const_reference at(qsizetype i) const noexcept
Definition qlist.h:446
void move(qsizetype from, qsizetype to)
Definition qlist.h:610
void append(parameter_type t)
Definition qlist.h:458
void clear()
Definition qlist.h:434
\inmodule QtCore
\inmodule QtCore
Definition qobject.h:103
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2960
\inmodule QtCore\reentrant
Definition qpoint.h:25
The QPointingDevice class describes a device from which mouse, touch or tablet events originate.
The QQmlError class encapsulates a QML error.
Definition qqmlerror.h:18
static QQuickItemPrivate * get(QQuickItem *item)
bool operator==(const ListRange &other) const
QList< QPair< QString, QString > > getModelDataValues(const QaimModel &model)
bool operator!=(const ListRange &other) const
ListRange operator+(const ListRange &other) const
void insertItem(int index, const QString &name, const QString &number)
Q_INVOKABLE void addItem(const QString &name, const QString &number)
QString number(int index) const
QHash< int, QByteArray > roleNames() const override
Q_INVOKABLE void removeItem(int index)
void removeItems(int index, int count)
int rowCount(const QModelIndex &parent=QModelIndex()) const override
Returns the number of rows under the given parent.
int columnCount(const QModelIndex &parent=QModelIndex()) const override
void matchAgainst(const QList< QPair< QString, QString > > &other, const QString &error1, const QString &error2)
void insertItems(int index, const QList< QPair< QString, QString > > &items)
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
Returns the data stored under the given role for the item referred to by the index.
void resetItems(const QList< QPair< QString, QString > > &items)
QString name(int index) const
void modifyItem(int idx, const QString &name, const QString &number)
void addItems(const QList< QPair< QString, QString > > &items)
void moveItems(int from, int to, int count)
void moveItem(int from, int to)
QVariant data(const QModelIndex &, int) const override
Returns the data stored under the given role for the item referred to by the index.
int rowCount(const QModelIndex &) const override
Returns the number of rows under the given parent.
The QQuickView class provides a window for displaying a Qt Quick user interface.
Definition qquickview.h:20
QList< QQmlError > errors() const
Return the list of errors that occurred during the last compile or create operation.
Status status
The component's current \l{QQuickView::Status} {status}.
Definition qquickview.h:23
void setSource(const QUrl &)
Sets the source to the url, loads the QML component and instantiates it.
QQuickItem * rootObject() const
Returns the view's root \l {QQuickItem} {item}.
static QQuickWindowPrivate * get(QQuickWindow *c)
\qmltype Window \instantiates QQuickWindow \inqmlmodule QtQuick
static Q_DECL_CONST_FUNCTION QRandomGenerator * global()
\threadsafe
Definition qrandom.h:275
\inmodule QtCore\reentrant
Definition qrect.h:30
constexpr QPoint center() const noexcept
Returns the center point of the rectangle.
Definition qrect.h:233
\inmodule QtCore
Definition qsize.h:25
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
QTouchEventSequence & move(int touchId, const QPoint &pt, QWindow *window=nullptr)
QTouchEventSequence & press(int touchId, const QPoint &pt, QWindow *window=nullptr)
QTouchEventSequence & release(int touchId, const QPoint &pt, QWindow *window=nullptr)
\inmodule QtCore
Definition qtimer.h:20
void timeout(QPrivateSignal)
This signal is emitted when the timer times out.
\inmodule QtCore
Definition qurl.h:94
\inmodule QtCore
Definition qvariant.h:65
static bool handleTabletEvent(QWindow *window, ulong timestamp, const QPointingDevice *device, const QPointF &local, const QPointF &global, Qt::MouseButtons buttons, qreal pressure, int xTilt, int yTilt, qreal tangentialPressure, qreal rotation, int z, Qt::KeyboardModifiers modifiers=Qt::NoModifier)
void setWidth(int arg)
Definition qwindow.cpp:1687
int width
the width of the window's geometry
Definition qwindow.h:82
void show()
Shows the window.
Definition qwindow.cpp:2254
void setHeight(int arg)
Definition qwindow.cpp:1696
int height
the height of the window's geometry
Definition qwindow.h:83
ScopedPrintable(const QString &string)
EGLImageKHR int int EGLuint64KHR * modifiers
QPushButton * button
[2]
std::list< QString >::iterator Name
Definition lalr.h:28
void pointerRelease(const QPointingDevice *dev, QQuickWindow *window, int pointId, const QPoint &p, Qt::MouseButton button, Qt::KeyboardModifiers modifiers)
static Qt::KeyboardModifiers pressedTabletModifiers
static Qt::MouseButton pressedTabletButton
bool initView(QQuickView &view, const QUrl &url, bool moveMouseOut, QByteArray *errorMessage)
bool showView(QQuickView &view, const QUrl &url)
void pointerMove(const QPointingDevice *dev, QQuickWindow *window, int pointId, const QPoint &p)
void pointerPress(const QPointingDevice *dev, QQuickWindow *window, int pointId, const QPoint &p, Qt::MouseButton button, Qt::KeyboardModifiers modifiers)
void flush(QQuickWindow *window)
QQuickView * createView()
QList< int > adjustIndexesForAddDisplaced(const QList< int > &indexes, int index, int count)
QList< int > adjustIndexesForMove(const QList< int > &indexes, int from, int to, int count)
static void qquickmodelviewstestutil_move(int from, int to, int n, T *items)
QList< int > adjustIndexesForRemoveDisplaced(const QList< int > &indexes, int index, int count)
void flick(QQuickView *window, const QPoint &from, const QPoint &to, int duration)
void moveAndPress(QQuickView *window, const QPoint &position)
void centerOnScreen(QQuickView *window, const QSize &size)
void moveMouseAway(QQuickView *window)
void moveAndRelease(QQuickView *window, const QPoint &position)
Combined button and popup list for selecting options.
Q_TESTLIB_EXPORT int lastMouseTimestamp
int Q_TESTLIB_EXPORT defaultMouseDelay()
Q_GUI_EXPORT bool qWaitForWindowExposed(QWindow *window, int timeout=5000)
void mouseMove(QWindow *window, QPoint pos=QPoint(), int delay=-1)
Definition qtestmouse.h:145
void mouseRelease(QWindow *window, Qt::MouseButton button, Qt::KeyboardModifiers stateKey=Qt::KeyboardModifiers(), QPoint pos=QPoint(), int delay=-1)
Definition qtestmouse.h:133
void mousePress(QWindow *window, Qt::MouseButton button, Qt::KeyboardModifiers stateKey=Qt::KeyboardModifiers(), QPoint pos=QPoint(), int delay=-1)
Definition qtestmouse.h:129
Q_CORE_EXPORT void qWait(int ms)
This is an overloaded member function, provided for convenience. It differs from the above function o...
QTouchEventSequence touchEvent(QWindow *window, QPointingDevice *device, bool autoCommit=true)
Definition qtesttouch.h:42
MouseButton
Definition qnamespace.h:56
@ LeftButton
Definition qnamespace.h:58
@ NoButton
Definition qnamespace.h:57
@ NoModifier
#define qDebug
[1]
Definition qlogging.h:164
#define qWarning
Definition qlogging.h:166
static const QMetaObjectPrivate * priv(const uint *data)
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint index
[2]
GLuint GLuint end
GLenum GLenum GLsizei count
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLuint start
GLenum GLuint GLintptr offset
GLuint name
GLint first
GLdouble GLdouble t
Definition qopenglext.h:243
GLuint64EXT * result
[6]
GLfloat GLfloat p
[1]
GLuint num
GLsizei const GLchar *const * string
[0]
Definition qopenglext.h:694
QT_BEGIN_NAMESPACE constexpr decltype(auto) qMakePair(T1 &&value1, T2 &&value2) noexcept(noexcept(std::make_pair(std::forward< T1 >(value1), std::forward< T2 >(value2))))
Definition qpair.h:19
static qreal position(const QQuickItem *item, QQuickAnchors::Anchor anchorLine)
#define QVERIFY2(statement, description)
Definition qtestcase.h:70
#define emit
#define Q_UNUSED(x)
static QString errorMessage(QUrlPrivate::ErrorCode errorCode, const QString &errorSource, qsizetype errorPosition)
Definition qurl.cpp:3517
QSqlQueryModel * model
[16]
QList< int > list
[14]
QUrl url("example.com")
[constructor-url-reference]
beginInsertRows(parent, 2, 4)
[0]
beginMoveRows(sourceParent, 2, 4, destinationParent, 2)
[5]
beginRemoveRows(parent, 2, 3)
[1]
QSharedPointer< T > other(t)
[5]
QGraphicsItem * item
QList< QTreeWidgetItem * > items
aWidget window() -> setWindowTitle("New Window Title")
[2]
QQuickView * view
[0]
char * toString(const MyType &t)
[31]
\inmodule QtCore \reentrant
Definition qchar.h:18
bool contains(const AT &t) const noexcept
Definition qlist.h:45