6#include <QtTest/qsignalspy.h>
7#include <QtQml/qqmlcomponent.h>
8#include <QtQuickControls2/qquickstyle.h>
9#include <QtQuickTemplates2/private/qquickabstractbutton_p.h>
10#include <QtQuickTemplates2/private/qquickapplicationwindow_p.h>
11#include <QtQuickTemplates2/private/qquickcontrol_p_p.h>
12#include <QtQuickTemplates2/private/qquickpopup_p.h>
13#include <QtQuickTemplates2/private/qquickpopupitem_p_p.h>
14#include <QtQuickTemplates2/private/qquickmenu_p_p.h>
15#include <QtQuickTemplates2/private/qquickmenuitem_p.h>
16#include <QtQuickTemplates2/private/qquickmenuitem_p_p.h>
18QQuickControlsTestUtils::QQuickControlsApplicationHelper::QQuickControlsApplicationHelper(QQmlDataTest *testCase,
19 const QString &testFilePath,
const QVariantMap &initialProperties,
const QStringList &qmlImportPaths)
20 : QQuickApplicationHelper(testCase, testFilePath, initialProperties, qmlImportPaths)
23 appWindow = qobject_cast<QQuickApplicationWindow*>(cleanup.data());
27
28
29
30
31
32
33
37 if (!currentStyle.isEmpty() && style == currentStyle)
42 qmlClearTypeRegistrations();
43 engine.reset(
new QQmlEngine);
44 QQuickStyle::setStyle(style);
46 QQmlComponent component(engine.data());
47 component.setData(QString::fromUtf8(
"import QtQuick\nimport QtQuick.Controls\n Control { }").toUtf8(), QUrl());
48 if (!component.isReady())
49 qWarning() <<
"Failed to load component:" << component.errorString();
50 return component.isReady();
54 const QString &sourcePath,
const QString &targetPath,
const QStringList &skipList,
68 const QFileInfoList entries = QDir(qqc2ImportPath + QLatin1Char(
'/') + sourcePath).entryInfoList(
69 QStringList(QStringLiteral(
"*.qml")), QDir::Files);
70 for (
const QFileInfo &entry : entries) {
71 QString name = entry.baseName();
72 if (!skipList.contains(name)) {
73 const auto importPathList = engine->importPathList();
74 for (
const QString &importPath : importPathList) {
75 QString name = entry.dir().dirName() + QLatin1Char(
'/') + entry.fileName();
76 QString filePath = importPath + QLatin1Char(
'/') + targetPath + QLatin1Char(
'/') + entry.fileName();
77 if (filePath.startsWith(QLatin1Char(
':')))
78 filePath.prepend(QStringLiteral(
"qrc"));
79 if (QFile::exists(filePath)) {
80 callback(name, QUrl::fromLocalFile(filePath));
84 filePath = QQmlFile::urlToLocalFileOrQrc(filePath);
85 if (!filePath.isEmpty() && QFile::exists(filePath)) {
96 const QString &sourcePath,
const QString &targetPath,
const QStringList &skipList)
98 forEachControl(engine, qqc2ImportPath, sourcePath, targetPath, skipList, [&](
const QString &relativePath,
const QUrl &absoluteUrl) {
99 QTest::newRow(qPrintable(relativePath)) << absoluteUrl;
105 if (!button->window()) {
106 qWarning() <<
"button" << button <<
"doesn't have an associated window";
110 if (!button->isEnabled()) {
111 qWarning() <<
"button" << button <<
"is not enabled";
115 if (!button->isVisible()) {
116 qWarning() <<
"button" << button <<
"is not visible";
120 if (button->width() <= 0.0) {
121 qWarning() <<
"button" << button <<
"must have a width greater than 0";
125 if (button->height() <= 0.0) {
126 qWarning() <<
"button" << button <<
"must have a height greater than 0";
138 QSignalSpy spy(button, &QQuickAbstractButton::clicked);
139 if (!spy.isValid()) {
140 qWarning() <<
"Button" << button <<
"must have a valid clicked signal";
144 const QPoint buttonCenter = button->mapToScene(QPointF(button->width() / 2, button->height() / 2)).toPoint();
145 QTest::mouseClick(button->window(), Qt::LeftButton, Qt::NoModifier, buttonCenter);
146 if (spy.size() != 1) {
147 QDebug warning(QtWarningMsg);
148 warning.nospace() <<
"The clicked signal of button " << button <<
" was not emitted after "
149 <<
"clicking at " << buttonCenter <<
".";
150 const QQuickPopup *popup = popupParent(button);
151 if (popup && !popup->isOpened()) {
152 warning <<
" The popup it's in (" << popup <<
") is no longer opened; "
153 <<
"the click may have missed the button and gone outside of the popup, "
154 <<
"causing it to close.";
163
164
165
166
169 auto *menuItemPrivate = QQuickMenuItemPrivate::get(menuItem);
170 if (!menuItemPrivate->menu) {
171 qWarning() <<
"MenuItem" << menuItem <<
"must be in a menu in order to be clicked";
175 if (menuItemPrivate->menu->enter()) {
177
178
179
180
181
182
183
184
185
186
187
188
189
194 return clickButton(menuItem);
202 QSignalSpy spy(button, &QQuickAbstractButton::clicked);
203 if (!spy.isValid()) {
204 qWarning() <<
"button" << button <<
"must have a valid doubleClicked signal";
208 const QPoint buttonCenter = button->mapToScene(QPointF(button->width() / 2, button->height() / 2)).toPoint();
209 QTest::mouseDClick(button->window(), Qt::LeftButton, Qt::NoModifier, buttonCenter);
210 if (spy.size() != 1) {
211 qWarning() <<
"doubleClicked signal of button" << button <<
"was not emitted after double-clicking";
219
220
221
224 std::unique_ptr<QQmlComponent> component(
new QQmlComponent(qmlEngine(
this)));
225 component->setData(data, QUrl());
226 if (component->isError())
227 qmlWarning(
this) <<
"Failed to create component from the following data:\n" << data;
228 return component.release();
233 return QQuickStyle::name();
237
238
239
240
243 return QString::fromLocal8Bit(qgetenv(name.toLocal8Bit()));
248 return qputenv(name.toLocal8Bit(), value.toLocal8Bit());
254 QDebug debug(&message);
255 const auto *controlPrivate = QQuickControlPrivate::get(control);
256 const QQuickWindow *window = control->window();
257 const QString activeFocusItemStr = window
258 ? QDebug::toString(window->activeFocusItem()) : QStringLiteral(
"(unknown; control has no window)");
259 debug.nospace() <<
"control: " << control <<
" activeFocus: " << control->hasActiveFocus()
260 <<
" focusReason: " <<
static_cast<Qt::FocusReason>(controlPrivate->focusReason)
261 <<
" activeFocusItem: " << activeFocusItemStr;
267 return QCoreApplication::testAttribute(attribute);
272 QCoreApplication::setAttribute(attribute, on);
277#if defined(Q_OS_WINDOWS) || defined(Q_OS_MACOS)
278 return QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::Capability::MultipleWindows);
285
286
287
288
291 QQuickItem *parentItem = item;
293 auto *parentAsPopupItem = qobject_cast<QQuickPopupItem *>(parentItem);
294 if (parentAsPopupItem)
295 return QQuickPopupItemPrivate::get(parentAsPopupItem)->popup;
297 parentItem = parentItem->parentItem();
306 QDebug debug(&message);
307 const QQuickWindow *window = popup->window();
308 const QString activeFocusItemStr = window
309 ? QDebug::toString(window->activeFocusItem()) : QStringLiteral(
"(unknown; popup has no window)");
310 debug.nospace() <<
"popup: " << popup;
311 debug.noquote() <<
" window's activeFocusItem: " << activeFocusItemStr;
The QQmlComponent class encapsulates a QML component definition.
Q_INVOKABLE void set(Qt::ApplicationAttribute attribute, bool on=true)
Q_INVOKABLE bool setValue(const QString &name, const QString &value)
bool verifyButtonClickable(QQuickAbstractButton *button)
void addTestRowForEachControl(QQmlEngine *engine, const QString &qqc2ImportPath, const QString &sourcePath, const QString &targetPath, const QStringList &skipList=QStringList())
void forEachControl(QQmlEngine *engine, const QString &qqc2ImportPath, const QString &sourcePath, const QString &targetPath, const QStringList &skipList, ForEachCallback callback)
bool clickMenuItem(QQuickMenuItem *menuItem)
bool doubleClickButton(QQuickAbstractButton *button)
QQuickPopup * popupParent(QQuickItem *item)
QString visualFocusFailureMessage(QQuickControl *control)
bool arePopupWindowsSupported()
bool clickButton(QQuickAbstractButton *button)
std::function< void(const QString &, const QUrl &)> ForEachCallback
QByteArray qActiveFocusFailureMessage(QQuickPopup *popup)
bool updateStyle(const QString &style)