aboutsummaryrefslogtreecommitdiffstats
path: root/src/quicktestutils/quick/visualtestutils_p.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/quicktestutils/quick/visualtestutils_p.h')
-rw-r--r--src/quicktestutils/quick/visualtestutils_p.h231
1 files changed, 231 insertions, 0 deletions
diff --git a/src/quicktestutils/quick/visualtestutils_p.h b/src/quicktestutils/quick/visualtestutils_p.h
new file mode 100644
index 0000000000..48f8b2d8f9
--- /dev/null
+++ b/src/quicktestutils/quick/visualtestutils_p.h
@@ -0,0 +1,231 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef QQUICKVISUALTESTUTILS_P_H
+#define QQUICKVISUALTESTUTILS_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtQml/qqmlexpression.h>
+#include <QtQuick/private/qquickitem_p.h>
+
+#include <private/qmlutils_p.h>
+
+#include <QtCore/qpointer.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickItemView;
+class QQuickWindow;
+
+namespace QQuickVisualTestUtils
+{
+ QQuickItem *findVisibleChild(QQuickItem *parent, const QString &objectName);
+
+ void dumpTree(QQuickItem *parent, int depth = 0);
+
+ void moveMouseAway(QQuickWindow *window);
+ void centerOnScreen(QQuickWindow *window);
+
+ template<typename F>
+ void forEachStep(int steps, F &&func)
+ {
+ for (int i = 0; i < steps; ++i) {
+ const qreal progress = qreal(i) / steps;
+ func(progress);
+ }
+ }
+
+ [[nodiscard]] QPoint lerpPoints(const QPoint &point1, const QPoint &point2, qreal t);
+
+ class [[nodiscard]] PointLerper
+ {
+ public:
+ PointLerper(QQuickWindow *window,
+ const QPointingDevice *pointingDevice = QPointingDevice::primaryPointingDevice());
+
+ void move(const QPoint &pos, int steps = 10, int delayInMilliseconds = 1);
+ void move(int x, int y, int steps = 10, int delayInMilliseconds = 1);
+
+ private:
+ QQuickWindow *mWindow = nullptr;
+ const QPointingDevice *mPointingDevice = nullptr;
+ QPoint mFrom;
+ };
+
+ [[nodiscard]] bool isDelegateVisible(QQuickItem *item);
+
+ /*
+ Find an item with the specified objectName. If index is supplied then the
+ item must also evaluate the {index} expression equal to index
+ */
+ template<typename T>
+ T *findItem(QQuickItem *parent, const QString &objectName, int index = -1)
+ {
+ using namespace Qt::StringLiterals;
+
+ const QMetaObject &mo = T::staticMetaObject;
+ for (int i = 0; i < parent->childItems().size(); ++i) {
+ QQuickItem *item = qobject_cast<QQuickItem*>(parent->childItems().at(i));
+ if (!item)
+ continue;
+ if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName)) {
+ if (index != -1) {
+ QQmlContext *context = qmlContext(item);
+ if (!context->isValid())
+ continue;
+ QQmlExpression e(context, item, u"index"_s);
+ if (e.evaluate().toInt() == index)
+ return static_cast<T*>(item);
+ } else {
+ return static_cast<T*>(item);
+ }
+ }
+ item = findItem<T>(item, objectName, index);
+ if (item)
+ return static_cast<T*>(item);
+ }
+
+ return 0;
+ }
+
+ template<typename T>
+ QList<T*> findItems(QQuickItem *parent, const QString &objectName, bool visibleOnly = true)
+ {
+ QList<T*> items;
+ const QMetaObject &mo = T::staticMetaObject;
+ for (int i = 0; i < parent->childItems().size(); ++i) {
+ QQuickItem *item = qobject_cast<QQuickItem*>(parent->childItems().at(i));
+ if (!item || (visibleOnly && (!item->isVisible() || QQuickItemPrivate::get(item)->culled)))
+ continue;
+ if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName))
+ items.append(static_cast<T*>(item));
+ items += findItems<T>(item, objectName);
+ }
+
+ return items;
+ }
+
+ template<typename T>
+ QList<T*> findItems(QQuickItem *parent, const QString &objectName, const QList<int> &indexes)
+ {
+ QList<T*> items;
+ for (int i=0; i<indexes.size(); i++)
+ items << qobject_cast<QQuickItem*>(findItem<T>(parent, objectName, indexes[i]));
+ return items;
+ }
+
+ bool compareImages(const QImage &ia, const QImage &ib, QString *errorMessage);
+
+ struct SignalMultiSpy : public QObject
+ {
+ Q_OBJECT
+ public:
+ QList<QObject *> senders;
+ QList<QByteArray> signalNames;
+
+ template <typename Func1>
+ QMetaObject::Connection connectToSignal(const typename QtPrivate::FunctionPointer<Func1>::Object *obj, Func1 signal,
+ Qt::ConnectionType type = Qt::AutoConnection)
+ {
+ return connect(obj, signal, this, &SignalMultiSpy::receive, type);
+ }
+
+ void clear() {
+ senders.clear();
+ signalNames.clear();
+ }
+
+ public Q_SLOTS:
+ void receive() {
+ QMetaMethod m = sender()->metaObject()->method(senderSignalIndex());
+ senders << sender();
+ signalNames << m.name();
+ }
+ };
+
+ enum class FindViewDelegateItemFlag {
+ None = 0x0,
+ PositionViewAtIndex = 0x01
+ };
+ Q_DECLARE_FLAGS(FindViewDelegateItemFlags, FindViewDelegateItemFlag)
+
+#if QT_CONFIG(quick_itemview)
+ QQuickItem* findViewDelegateItem(QQuickItemView *itemView, int index,
+ FindViewDelegateItemFlags flags = FindViewDelegateItemFlag::PositionViewAtIndex);
+#endif
+
+ /*!
+ \internal
+
+ Same as above except allows use in QTRY_* functions without having to call it again
+ afterwards to assign the delegate.
+ */
+ template<typename T>
+ [[nodiscard]] bool findViewDelegateItem(QQuickItemView *itemView, int index, T &delegateItem,
+ FindViewDelegateItemFlags flags = FindViewDelegateItemFlag::PositionViewAtIndex)
+ {
+ delegateItem = qobject_cast<T>(findViewDelegateItem(itemView, index, flags));
+ return delegateItem != nullptr;
+ }
+
+ class QQuickApplicationHelper
+ {
+ public:
+ QQuickApplicationHelper(QQmlDataTest *testCase, const QString &testFilePath,
+ const QVariantMap &initialProperties = {},
+ const QStringList &qmlImportPaths = {});
+
+ // Return a C-style string instead of QString because that's what QTest uses for error messages,
+ // so it saves code at the calling site.
+ inline const char *failureMessage() const
+ {
+ return errorMessage.constData();
+ }
+
+ QQmlEngine engine;
+ QScopedPointer<QObject> cleanup;
+ QQuickWindow *window = nullptr;
+
+ bool ready = false;
+ // Store as a byte array so that we can return its raw data safely;
+ // using qPrintable() in failureMessage() will construct a throwaway QByteArray
+ // that is destroyed before the function returns.
+ QByteArray errorMessage;
+ };
+
+ class MnemonicKeySimulator
+ {
+ Q_DISABLE_COPY(MnemonicKeySimulator)
+ public:
+ explicit MnemonicKeySimulator(QWindow *window);
+
+ void press(Qt::Key key);
+ void release(Qt::Key key);
+ void click(Qt::Key key);
+
+ private:
+ QPointer<QWindow> m_window;
+ Qt::KeyboardModifiers m_modifiers;
+ };
+
+ QPoint mapCenterToWindow(const QQuickItem *item);
+ QPoint mapToWindow(const QQuickItem *item, qreal relativeX, qreal relativeY);
+ QPoint mapToWindow(const QQuickItem *item, const QPointF &relativePos);
+}
+
+#define QQUICK_VERIFY_POLISH(item) \
+ QTRY_COMPARE(QQuickItemPrivate::get(item)->polishScheduled, false)
+
+QT_END_NAMESPACE
+
+#endif // QQUICKVISUALTESTUTILS_P_H