1 | // Copyright (C) 2021 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 |
3 | |
4 | #ifndef QQUICKVIEWTESTUTILS_P_H |
5 | #define QQUICKVIEWTESTUTILS_P_H |
6 | |
7 | // |
8 | // W A R N I N G |
9 | // ------------- |
10 | // |
11 | // This file is not part of the Qt API. It exists purely as an |
12 | // implementation detail. This header file may change from version to |
13 | // version without notice, or even be removed. |
14 | // |
15 | // We mean it. |
16 | // |
17 | |
18 | #include <QtCore/QAbstractListModel> |
19 | #include <QtQml/QQmlExpression> |
20 | #include <QtQuick/QQuickItem> |
21 | #include <QtCore/private/qglobal_p.h> |
22 | #include <QtQuick/private/qtquickglobal_p.h> |
23 | |
24 | QT_FORWARD_DECLARE_CLASS(QQuickView) |
25 | QT_FORWARD_DECLARE_CLASS(QQuickItemViewPrivate) |
26 | QT_FORWARD_DECLARE_CLASS(FxViewItem) |
27 | |
28 | QT_BEGIN_NAMESPACE |
29 | |
30 | namespace QQuickViewTestUtils |
31 | { |
32 | QQuickView *createView(); |
33 | |
34 | void flick(QQuickView *window, const QPoint &from, const QPoint &to, int duration); |
35 | void centerOnScreen(QQuickView *window, const QSize &size); |
36 | void centerOnScreen(QQuickView *window); |
37 | void moveMouseAway(QQuickView *window); |
38 | void moveAndPress(QQuickView *window, const QPoint &position); |
39 | void moveAndRelease(QQuickView *window, const QPoint &position); |
40 | |
41 | QList<int> adjustIndexesForAddDisplaced(const QList<int> &indexes, int index, int count); |
42 | QList<int> adjustIndexesForMove(const QList<int> &indexes, int from, int to, int count); |
43 | QList<int> adjustIndexesForRemoveDisplaced(const QList<int> &indexes, int index, int count); |
44 | |
45 | struct ListChange { |
46 | enum { Inserted, Removed, Moved, SetCurrent, SetContentY, Polish } type; |
47 | int index; |
48 | int count; |
49 | int to; // Move |
50 | qreal pos; // setContentY |
51 | |
52 | static ListChange insert(int index, int count = 1) { ListChange c = { .type: Inserted, .index: index, .count: count, .to: -1, .pos: 0.0 }; return c; } |
53 | static ListChange remove(int index, int count = 1) { ListChange c = { .type: Removed, .index: index, .count: count, .to: -1, .pos: 0.0 }; return c; } |
54 | static ListChange move(int index, int to, int count) { ListChange c = { .type: Moved, .index: index, .count: count, .to: to, .pos: 0.0 }; return c; } |
55 | static ListChange setCurrent(int index) { ListChange c = { .type: SetCurrent, .index: index, .count: -1, .to: -1, .pos: 0.0 }; return c; } |
56 | static ListChange setContentY(qreal pos) { ListChange c = { .type: SetContentY, .index: -1, .count: -1, .to: -1, .pos: pos }; return c; } |
57 | static ListChange polish() { ListChange c = { .type: Polish, .index: -1, .count: -1, .to: -1, .pos: 0.0 }; return c; } |
58 | }; |
59 | |
60 | class QaimModel : public QAbstractListModel |
61 | { |
62 | Q_OBJECT |
63 | public: |
64 | enum Roles { Name = Qt::UserRole+1, Number = Qt::UserRole+2 }; |
65 | |
66 | QaimModel(QObject *parent=0); |
67 | |
68 | int rowCount(const QModelIndex &parent=QModelIndex()) const override; |
69 | int columnCount(const QModelIndex &parent=QModelIndex()) const override; |
70 | QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override; |
71 | QHash<int,QByteArray> roleNames() const override; |
72 | |
73 | int count() const; |
74 | QString name(int index) const; |
75 | QString number(int index) const; |
76 | |
77 | Q_INVOKABLE void addItem(const QString &name, const QString &number); |
78 | void addItems(const QList<QPair<QString, QString> > &items); |
79 | void insertItem(int index, const QString &name, const QString &number); |
80 | void insertItems(int index, const QList<QPair<QString, QString> > &items); |
81 | |
82 | Q_INVOKABLE void removeItem(int index); |
83 | void removeItems(int index, int count); |
84 | |
85 | void moveItem(int from, int to); |
86 | void moveItems(int from, int to, int count); |
87 | |
88 | void modifyItem(int idx, const QString &name, const QString &number); |
89 | |
90 | void clear(); |
91 | void reset(); |
92 | void resetItems(const QList<QPair<QString, QString> > &items); |
93 | |
94 | void matchAgainst(const QList<QPair<QString, QString> > &other, const QString &error1, const QString &error2); |
95 | |
96 | using QAbstractListModel::dataChanged; |
97 | |
98 | int columns = 1; |
99 | |
100 | private: |
101 | QList<QPair<QString,QString> > list; |
102 | }; |
103 | |
104 | class ListRange |
105 | { |
106 | public: |
107 | ListRange(); |
108 | ListRange(const ListRange &other); |
109 | ListRange(int start, int end); |
110 | |
111 | ~ListRange(); |
112 | |
113 | ListRange operator+(const ListRange &other) const; |
114 | bool operator==(const ListRange &other) const; |
115 | bool operator!=(const ListRange &other) const; |
116 | |
117 | bool isValid() const; |
118 | int count() const; |
119 | |
120 | QList<QPair<QString,QString> > getModelDataValues(const QaimModel &model); |
121 | |
122 | QList<int> indexes; |
123 | bool valid; |
124 | }; |
125 | |
126 | template<typename T> |
127 | static void qquickmodelviewstestutil_move(int from, int to, int n, T *items) |
128 | { |
129 | if (from > to) { |
130 | // Only move forwards - flip if backwards moving |
131 | int tfrom = from; |
132 | int tto = to; |
133 | from = tto; |
134 | to = tto+n; |
135 | n = tfrom-tto; |
136 | } |
137 | |
138 | T replaced; |
139 | int i=0; |
140 | typename T::ConstIterator it=items->begin(); it += from+n; |
141 | for (; i<to-from; ++i,++it) |
142 | replaced.append(*it); |
143 | i=0; |
144 | it=items->begin(); it += from; |
145 | for (; i<n; ++i,++it) |
146 | replaced.append(*it); |
147 | typename T::ConstIterator f=replaced.begin(); |
148 | typename T::Iterator t=items->begin(); t += from; |
149 | for (; f != replaced.end(); ++f, ++t) |
150 | *t = *f; |
151 | } |
152 | |
153 | class StressTestModel : public QAbstractListModel |
154 | { |
155 | Q_OBJECT |
156 | |
157 | public: |
158 | |
159 | StressTestModel(); |
160 | |
161 | int rowCount(const QModelIndex &) const override; |
162 | QVariant data(const QModelIndex &, int) const override; |
163 | |
164 | public Q_SLOTS: |
165 | void updateModel(); |
166 | |
167 | private: |
168 | int m_rowCount; |
169 | }; |
170 | |
171 | #if QT_CONFIG(quick_itemview) |
172 | [[nodiscard]] bool testVisibleItems(const QQuickItemViewPrivate *priv, |
173 | bool *nonUnique, FxViewItem **failItem, int *expectedIdx); |
174 | #endif |
175 | } |
176 | |
177 | namespace QQuickTouchUtils { |
178 | void flush(QQuickWindow *window); |
179 | } |
180 | |
181 | namespace QQuickTest { |
182 | [[nodiscard]] bool initView(QQuickView &v, const QUrl &url, |
183 | bool moveMouseOut = true, QByteArray *errorMessage = nullptr); |
184 | [[nodiscard]] bool showView(QQuickView &v, const QUrl &url); |
185 | |
186 | void pointerPress(const QPointingDevice *dev, QQuickWindow *window, |
187 | int pointId, const QPoint &p, Qt::MouseButton button = Qt::LeftButton, |
188 | Qt::KeyboardModifiers modifiers = Qt::NoModifier); |
189 | |
190 | void pointerMove(const QPointingDevice *dev, QQuickWindow *window, int pointId, |
191 | const QPoint &p); |
192 | |
193 | void pointerRelease(const QPointingDevice *dev, QQuickWindow *window, int pointId, |
194 | const QPoint &p, Qt::MouseButton button = Qt::LeftButton, |
195 | Qt::KeyboardModifiers modifiers = Qt::NoModifier); |
196 | } |
197 | |
198 | QT_END_NAMESPACE |
199 | |
200 | Q_DECLARE_METATYPE(QQuickViewTestUtils::QaimModel*) |
201 | Q_DECLARE_METATYPE(QQuickViewTestUtils::ListChange) |
202 | Q_DECLARE_METATYPE(QList<QQuickViewTestUtils::ListChange>) |
203 | Q_DECLARE_METATYPE(QQuickViewTestUtils::ListRange) |
204 | |
205 | |
206 | #endif // QQUICKVIEWTESTUTILS_P_H |
207 | |