aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorOliver Eftevaag <oliver.eftevaag@qt.io>2021-03-15 16:05:11 +0100
committerOliver Eftevaag <oliver.eftevaag@qt.io>2021-06-04 18:02:30 +0200
commitc830979fbb176e6e48b3ff45c84fa0742aaa186e (patch)
treeb594ec6b742a2155113f766d6eaac76c2f2f6ec6 /tests
parent4ab599b2058949e18ac3fcdf71f9204f307d93ef (diff)
Add FontDialog to QtQuick.Dialogs
Adding non-native FontDialog to QtQuick. This is a native FontDialog on platforms that support it, and a non-native Qt Quick FontDialog on platforms that don't. Fixes: QTBUG-87799 Change-Id: I43a59e3668a8a40f1d0c04a3c2506283d552a22b Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
Diffstat (limited to 'tests')
-rw-r--r--tests/auto/dialogs/CMakeLists.txt1
-rw-r--r--tests/auto/dialogs/qquickfontdialogimpl/BLACKLIST4
-rw-r--r--tests/auto/dialogs/qquickfontdialogimpl/CMakeLists.txt39
-rw-r--r--tests/auto/dialogs/qquickfontdialogimpl/data/fontDialog.qml65
-rw-r--r--tests/auto/dialogs/qquickfontdialogimpl/tst_qquickfontdialogimpl.cpp520
-rw-r--r--tests/manual/dialogs/CMakeLists.txt1
-rw-r--r--tests/manual/dialogs/FontDialogPage.qml222
-rw-r--r--tests/manual/dialogs/dialogs.pro1
-rw-r--r--tests/manual/dialogs/dialogs.qml3
9 files changed, 855 insertions, 1 deletions
diff --git a/tests/auto/dialogs/CMakeLists.txt b/tests/auto/dialogs/CMakeLists.txt
index 26eb933f..94485f87 100644
--- a/tests/auto/dialogs/CMakeLists.txt
+++ b/tests/auto/dialogs/CMakeLists.txt
@@ -1 +1,2 @@
add_subdirectory(qquickfiledialogimpl)
+add_subdirectory(qquickfontdialogimpl)
diff --git a/tests/auto/dialogs/qquickfontdialogimpl/BLACKLIST b/tests/auto/dialogs/qquickfontdialogimpl/BLACKLIST
new file mode 100644
index 00000000..acabf6c5
--- /dev/null
+++ b/tests/auto/dialogs/qquickfontdialogimpl/BLACKLIST
@@ -0,0 +1,4 @@
+# See qtbase/src/testlib/qtestblacklist.cpp for format
+# QTBUG-94225
+[listViews]
+b2qt
diff --git a/tests/auto/dialogs/qquickfontdialogimpl/CMakeLists.txt b/tests/auto/dialogs/qquickfontdialogimpl/CMakeLists.txt
new file mode 100644
index 00000000..0250c64e
--- /dev/null
+++ b/tests/auto/dialogs/qquickfontdialogimpl/CMakeLists.txt
@@ -0,0 +1,39 @@
+# Collect test data
+file(GLOB_RECURSE test_data_glob
+ RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
+ data/*)
+list(APPEND test_data ${test_data_glob})
+
+qt_internal_add_test(tst_qquickfontdialogimpl
+ SOURCES
+ ../../shared/qtest_quickcontrols.h
+ ../../shared/util.cpp ../../shared/util.h
+ ../../shared/visualtestutil.cpp ../../shared/visualtestutil.h
+ tst_qquickfontdialogimpl.cpp
+ DEFINES
+ QQC2_IMPORT_PATH=\\\"${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/imports\\\"
+ PUBLIC_LIBRARIES
+ Qt::CorePrivate
+ Qt::Gui
+ Qt::GuiPrivate
+ Qt::QmlPrivate
+ Qt::QuickControls2
+ Qt::QuickControls2Private
+ Qt::QuickDialogs2Private
+ Qt::QuickDialogs2QuickImplPrivate
+ Qt::QuickPrivate
+ Qt::QuickTemplates2Private
+ Qt::QuickTest
+ Qt::TestPrivate
+ TESTDATA ${test_data}
+)
+
+qt_internal_extend_target(tst_qquickfontdialogimpl CONDITION ANDROID OR IOS
+ DEFINES
+ QT_QMLTEST_DATADIR=\\\":/data\\\"
+)
+
+qt_internal_extend_target(tst_qquickfontdialogimpl CONDITION NOT ANDROID AND NOT IOS
+ DEFINES
+ QT_QMLTEST_DATADIR=\\\"${CMAKE_CURRENT_SOURCE_DIR}/data\\\"
+)
diff --git a/tests/auto/dialogs/qquickfontdialogimpl/data/fontDialog.qml b/tests/auto/dialogs/qquickfontdialogimpl/data/fontDialog.qml
new file mode 100644
index 00000000..4979d473
--- /dev/null
+++ b/tests/auto/dialogs/qquickfontdialogimpl/data/fontDialog.qml
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Dialogs
+
+ApplicationWindow {
+ width: 640
+ height: 480
+
+ property alias dialog: dialog
+
+ FontDialog {
+ id: dialog
+ objectName: "FontDialog"
+ }
+}
diff --git a/tests/auto/dialogs/qquickfontdialogimpl/tst_qquickfontdialogimpl.cpp b/tests/auto/dialogs/qquickfontdialogimpl/tst_qquickfontdialogimpl.cpp
new file mode 100644
index 00000000..42f60f1b
--- /dev/null
+++ b/tests/auto/dialogs/qquickfontdialogimpl/tst_qquickfontdialogimpl.cpp
@@ -0,0 +1,520 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "../../shared/dialogtestutil.h"
+#include "../../shared/util.h"
+#include "../../shared/visualtestutil.h"
+
+#include <QtTest/qtest.h>
+#include <QtTest/qsignalspy.h>
+#include <QtQml/qqmlfile.h>
+#include <QtQuick/private/qquicklistview_p.h>
+#include <QtQuickTemplates2/private/qquickitemdelegate_p.h>
+#include <QtQuickDialogs2/private/qquickfontdialog_p.h>
+#include <QtQuickDialogs2QuickImpl/private/qquickfontdialogimpl_p.h>
+#include <QtQuickTest/quicktest.h>
+#include <QtQuickTemplates2/private/qquickapplicationwindow_p.h>
+#include <QtQuickTemplates2/private/qquickcombobox_p.h>
+#include <QtQuickTemplates2/private/qquicktextfield_p.h>
+#include <QtQuickTemplates2/private/qquickdialogbuttonbox_p.h>
+#include <QtQuickTemplates2/private/qquickdialogbuttonbox_p_p.h>
+#include <QtQuickTemplates2/private/qquicklabel_p.h>
+#include <QtQuickTemplates2/private/qquickoverlay_p.h>
+
+using namespace QQuickDialogTestUtil;
+using namespace QQuickVisualTestUtil;
+
+class tst_QQuickFontDialogImpl : public QQmlDataTest
+{
+ Q_OBJECT
+
+private slots:
+ void writingSystem();
+ void listViews();
+ void effects();
+ void changeFontSize();
+ void changeDialogTitle();
+ void searchFamily();
+
+private:
+ QQuickAbstractButton *findDialogButton(QQuickDialogButtonBox *box, const QString &buttonText)
+ {
+ for (int i = 0; i < box->count(); ++i) {
+ auto button = qobject_cast<QQuickAbstractButton *>(box->itemAt(i));
+ if (button && button->text().toUpper() == buttonText.toUpper())
+ return button;
+ }
+ return nullptr;
+ }
+
+ bool closePopup(DialogTestHelper<QQuickFontDialog, QQuickFontDialogImpl> *dialogHelper,
+ QString dialogButton, QString &failureMessage)
+ {
+ auto dialogButtonBox =
+ dialogHelper->quickDialog->footer()->findChild<QQuickDialogButtonBox *>();
+
+ if (!dialogButtonBox) {
+ failureMessage = QLatin1String("dialogButtonBox is null");
+ return false;
+ }
+
+ QQuickAbstractButton *openButton = findDialogButton(dialogButtonBox, dialogButton);
+
+ if (!openButton) {
+ failureMessage =
+ QLatin1String("Couldn't find a button with text '%1'").arg(dialogButton);
+ return false;
+ }
+
+ bool clicked = clickButton(openButton);
+
+ if (!clicked) {
+ failureMessage = QLatin1String("'%1' button was never clicked").arg(dialogButton);
+ return false;
+ }
+
+ bool visible = dialogHelper->dialog->isVisible();
+ if (visible) {
+ failureMessage = QLatin1String("Dialog is still visible after clicking the '%1' button")
+ .arg(dialogButton);
+ return false;
+ }
+ return true;
+ }
+};
+
+#define CREATE_DIALOG_TEST_HELPER \
+ DialogTestHelper<QQuickFontDialog, QQuickFontDialogImpl> dialogHelper(this, "fontDialog.qml"); \
+ QVERIFY2(dialogHelper.isWindowInitialized(), dialogHelper.failureMessage()); \
+ QVERIFY(dialogHelper.waitForWindowActive());
+
+#define CLOSE_DIALOG(BUTTON) \
+ QString errorMessage; \
+ QVERIFY2(closePopup(&dialogHelper, BUTTON, errorMessage), qPrintable(errorMessage)); \
+ QTRY_VERIFY(!dialogHelper.quickDialog->isVisible());
+
+void tst_QQuickFontDialogImpl::writingSystem()
+{
+ CREATE_DIALOG_TEST_HELPER
+
+ // Open the dialog.
+ QVERIFY(dialogHelper.openDialog());
+ QTRY_VERIFY(dialogHelper.isQuickDialogOpen());
+
+ const QQuickTextEdit *sampleEdit =
+ dialogHelper.quickDialog->findChild<QQuickTextEdit *>("sampleEdit");
+ QVERIFY(sampleEdit);
+
+ QCOMPARE(sampleEdit->text(), QFontDatabase::writingSystemSample(QFontDatabase::Any));
+
+ // Check that the font family list view exist and add signal spy.
+ const QQuickListView *fontFamilyListView =
+ dialogHelper.quickDialog->findChild<QQuickListView *>("familyListView");
+ QVERIFY(fontFamilyListView);
+ QSignalSpy fontFamilyModelSpy(fontFamilyListView, SIGNAL(modelChanged()));
+
+ // Open the ComboBox's popup.
+ const QQuickComboBox *writingSystemComboBox = dialogHelper.quickDialog->findChild<QQuickComboBox*>();
+ QVERIFY(writingSystemComboBox);
+ const QPoint comboBoxCenterPos = writingSystemComboBox->mapToScene({ writingSystemComboBox->width() / 2, writingSystemComboBox->height() / 2 }).toPoint();
+ QTest::mouseClick(dialogHelper.window(), Qt::LeftButton, Qt::NoModifier, comboBoxCenterPos);
+ QTRY_VERIFY(writingSystemComboBox->popup()->isOpened());
+
+ // "Any" should be selected by default.
+ QQuickListView *comboBoxPopupListView = qobject_cast<QQuickListView*>(writingSystemComboBox->popup()->contentItem());
+ QVERIFY(comboBoxPopupListView);
+ const int anyIndex = QFontDatabase::Any;
+ QQuickAbstractButton *anyDelegate = qobject_cast<QQuickAbstractButton*>(findViewDelegateItem(comboBoxPopupListView, anyIndex));
+ QVERIFY(anyDelegate);
+ QCOMPARE(anyDelegate->text(), QFontDatabase::writingSystemName(QFontDatabase::Any));
+
+ QCOMPARE(fontFamilyModelSpy.count(), 0);
+
+ // Select "Japanese" from the ComboBox.
+ const int japaneseIndex = QFontDatabase::Japanese;
+ QQuickAbstractButton *japaneseDelegate = qobject_cast<QQuickAbstractButton*>(findViewDelegateItem(comboBoxPopupListView, japaneseIndex));
+ QVERIFY(japaneseDelegate);
+ QCOMPARE(japaneseDelegate->text(), QFontDatabase::writingSystemName(QFontDatabase::Japanese));
+ QVERIFY(clickButton(japaneseDelegate));
+ QTRY_VERIFY(!writingSystemComboBox->popup()->isVisible());
+
+ // Check that the contents of the font family listview changed
+ QCOMPARE(fontFamilyModelSpy.count(), 1);
+
+ // And that the sample text is correctly set
+ QCOMPARE(sampleEdit->text(), QFontDatabase::writingSystemSample(QFontDatabase::Japanese));
+
+ // Then accept it to close it.
+ auto dialogButtonBox = dialogHelper.quickDialog->footer()->findChild<QQuickDialogButtonBox*>();
+ QVERIFY(dialogButtonBox);
+ QQuickAbstractButton* openButton = findDialogButton(dialogButtonBox, "Ok");
+ QVERIFY(openButton);
+ QVERIFY(clickButton(openButton));
+ QVERIFY(!dialogHelper.dialog->isVisible());
+ QTRY_VERIFY(!dialogHelper.quickDialog->isVisible());
+}
+
+void tst_QQuickFontDialogImpl::listViews()
+{
+ CREATE_DIALOG_TEST_HELPER
+
+ // Open the dialog.
+ QVERIFY(dialogHelper.openDialog());
+ QTRY_VERIFY(dialogHelper.isQuickDialogOpen());
+
+ QQuickListView *fontFamilyListView =
+ dialogHelper.quickDialog->findChild<QQuickListView *>("familyListView");
+ QVERIFY(fontFamilyListView);
+
+ const QQuickListView *fontStyleListView =
+ dialogHelper.quickDialog->findChild<QQuickListView *>("styleListView");
+ QVERIFY(fontStyleListView);
+
+ const QQuickListView *fontSizeListView =
+ dialogHelper.quickDialog->findChild<QQuickListView *>("sizeListView");
+ QVERIFY(fontSizeListView);
+
+ QSignalSpy currentFontSpy(dialogHelper.dialog, SIGNAL(currentFontChanged()));
+ QSignalSpy styleModelSpy(fontStyleListView, SIGNAL(modelChanged()));
+ QSignalSpy sizeModelSpy(fontSizeListView, SIGNAL(modelChanged()));
+
+ QCOMPARE(fontFamilyListView->currentIndex(), 0);
+ QCOMPARE(fontStyleListView->currentIndex(), 0);
+ QCOMPARE(fontSizeListView->currentIndex(), 0);
+
+ auto fontListModel = QFontDatabase::families(QFontDatabase::WritingSystem::Any);
+ fontListModel.removeIf(QFontDatabase::isPrivateFamily);
+
+ // In case the font database contains a significant number of font families
+ const int maxNumberOfFamiliesToTest = 10;
+
+ for (auto i = 1; i < qMin(fontListModel.size(), maxNumberOfFamiliesToTest); ++i) {
+ currentFontSpy.clear();
+ styleModelSpy.clear();
+ sizeModelSpy.clear();
+
+ const QString err = QString("LOOP INDEX %1, EXPECTED %2, ACTUAL %3").arg(i);
+
+ const QFont currentFont = dialogHelper.dialog->currentFont();
+
+ const auto oldStyleModel = fontStyleListView->model();
+ const auto oldSizeModel = fontSizeListView->model();
+
+ const QString expected1 = fontListModel[i - 1], actual1 = currentFont.family();
+ QVERIFY2(expected1 == actual1, qPrintable(err.arg(expected1, actual1)));
+
+ QQuickAbstractButton *fontDelegate =
+ qobject_cast<QQuickAbstractButton *>(findViewDelegateItem(fontFamilyListView, i));
+ QVERIFY2(fontDelegate, qPrintable(QString("LOOP INDEX %1").arg(i)));
+
+ QVERIFY2(clickButton(fontDelegate), qPrintable(QString("LOOP INDEX %1").arg(i)));
+
+ const QString expected2 = fontListModel[i],
+ actual2 = dialogHelper.dialog->currentFont().family();
+ QVERIFY2(expected2 == actual2, qPrintable(err.arg(expected2, actual2).append(" font: ").append(fontDelegate->text())));
+ QVERIFY2(currentFontSpy.count() == 1, qPrintable(err.arg(1, currentFontSpy.count())));
+ QVERIFY2((oldStyleModel == fontStyleListView->model()) != (styleModelSpy.count() == 1),
+ qPrintable(QString("LOOP INDEX %1").arg(i)));
+ QVERIFY2((oldSizeModel == fontSizeListView->model()) != (sizeModelSpy.count() == 1),
+ qPrintable(QString("LOOP INDEX %1").arg(i)));
+ }
+
+ // Then accept it to close it.
+ QVERIFY(dialogHelper.dialog->currentFont() != dialogHelper.dialog->selectedFont());
+
+ CLOSE_DIALOG("Ok");
+
+ QVERIFY(dialogHelper.dialog->currentFont() == dialogHelper.dialog->selectedFont());
+}
+
+void tst_QQuickFontDialogImpl::effects()
+{
+ CREATE_DIALOG_TEST_HELPER
+
+ // Open the dialog.
+ QVERIFY(dialogHelper.openDialog());
+ QTRY_VERIFY(dialogHelper.isQuickDialogOpen());
+
+ QSignalSpy currentFontSpy(dialogHelper.dialog, SIGNAL(currentFontChanged()));
+
+ QQuickCheckBox *underlineCheckBox =
+ dialogHelper.quickDialog->findChild<QQuickCheckBox *>("underlineEffect");
+ QVERIFY(underlineCheckBox);
+
+ QQuickCheckBox *strikeoutCheckBox =
+ dialogHelper.quickDialog->findChild<QQuickCheckBox *>("strikeoutEffect");
+ QVERIFY(strikeoutCheckBox);
+
+ QVERIFY(!dialogHelper.dialog->currentFont().underline());
+ QVERIFY(!dialogHelper.dialog->currentFont().strikeOut());
+
+ QVERIFY(clickButton(underlineCheckBox));
+
+ QCOMPARE(currentFontSpy.count(), 1);
+ QVERIFY(dialogHelper.dialog->currentFont().underline());
+ QVERIFY(!dialogHelper.dialog->currentFont().strikeOut());
+
+ QVERIFY(clickButton(underlineCheckBox));
+
+ QCOMPARE(currentFontSpy.count(), 2);
+ QVERIFY(!dialogHelper.dialog->currentFont().underline());
+ QVERIFY(!dialogHelper.dialog->currentFont().strikeOut());
+
+ QVERIFY(clickButton(strikeoutCheckBox));
+
+ QCOMPARE(currentFontSpy.count(), 3);
+ QVERIFY(!dialogHelper.dialog->currentFont().underline());
+ QVERIFY(dialogHelper.dialog->currentFont().strikeOut());
+
+ QVERIFY(clickButton(strikeoutCheckBox));
+
+ QCOMPARE(currentFontSpy.count(), 4);
+ QVERIFY(!dialogHelper.dialog->currentFont().underline());
+ QVERIFY(!dialogHelper.dialog->currentFont().strikeOut());
+
+ // Then accept it to close it.
+ CLOSE_DIALOG("Ok");
+}
+
+void tst_QQuickFontDialogImpl::changeFontSize()
+{
+ CREATE_DIALOG_TEST_HELPER
+
+ // Open the dialog.
+ QVERIFY(dialogHelper.openDialog());
+ QTRY_VERIFY(dialogHelper.isQuickDialogOpen());
+
+ QQuickTextField *sizeEdit = dialogHelper.quickDialog->findChild<QQuickTextField *>("sizeEdit");
+ QVERIFY(sizeEdit);
+
+ QQuickListView *fontSizeListView =
+ dialogHelper.quickDialog->findChild<QQuickListView *>("sizeListView");
+ QVERIFY(fontSizeListView);
+
+ const QQuickItemDelegate *firstSizeDelegate =
+ qobject_cast<QQuickItemDelegate *>(findViewDelegateItem(fontSizeListView, 0));
+
+ QCOMPARE(dialogHelper.dialog->currentFont().pointSize(), firstSizeDelegate->text().toInt());
+
+ sizeEdit->setText("15");
+ QCOMPARE(dialogHelper.dialog->currentFont().pointSize(), 15);
+
+ sizeEdit->setText("22");
+ QCOMPARE(dialogHelper.dialog->currentFont().pointSize(), 22);
+
+ QVERIFY(dialogHelper.dialog->currentFont() != dialogHelper.dialog->selectedFont());
+
+ // Then accept it to close it.
+ CLOSE_DIALOG("Ok");
+
+ QVERIFY(dialogHelper.dialog->currentFont() == dialogHelper.dialog->selectedFont());
+}
+
+void tst_QQuickFontDialogImpl::changeDialogTitle()
+{
+ CREATE_DIALOG_TEST_HELPER
+
+ // Open the dialog.
+ QVERIFY(dialogHelper.openDialog());
+ QTRY_VERIFY(dialogHelper.isQuickDialogOpen());
+
+ const auto dialogButtonBox =
+ dialogHelper.quickDialog->footer()->findChild<QQuickDialogButtonBox *>();
+ QVERIFY(dialogButtonBox);
+ QQuickAbstractButton *cancelButton = findDialogButton(dialogButtonBox, "Cancel");
+ QVERIFY(cancelButton);
+
+ const QQuickLabel *titleLabel = dialogHelper.quickDialog->header()->findChild<QQuickLabel *>();
+ QVERIFY(titleLabel);
+
+ QCOMPARE(titleLabel->text(), QString());
+
+ const QString newTitle1 = QLatin1String("Some random title #1");
+
+ // Dialog must be closed for the title to update
+ QVERIFY(clickButton(cancelButton));
+ QVERIFY(!dialogHelper.dialog->isVisible());
+ QTRY_VERIFY(!dialogHelper.quickDialog->isVisible());
+
+ dialogHelper.dialog->setTitle(newTitle1);
+
+ // Reopen the dialog
+ QVERIFY(dialogHelper.openDialog());
+ QTRY_VERIFY(dialogHelper.isQuickDialogOpen());
+ QVERIFY(dialogHelper.dialog->isVisible());
+ QTRY_VERIFY(dialogHelper.quickDialog->isVisible());
+
+ QCOMPARE(titleLabel->text(), newTitle1);
+
+ const QString newTitle2 = QLatin1String("Some random other title #2");
+
+ dialogHelper.dialog->setTitle(newTitle2);
+
+ // Shouldn't update unless you reopen the dialog
+ QCOMPARE(titleLabel->text(), newTitle1);
+
+ QVERIFY(clickButton(cancelButton));
+ QVERIFY(dialogHelper.openDialog());
+ QTRY_VERIFY(dialogHelper.isQuickDialogOpen());
+
+ // Should now be updated
+ QCOMPARE(titleLabel->text(), newTitle2);
+
+ CLOSE_DIALOG("Ok");
+}
+
+/*
+ Represents the expected search logic we use when the user types text into
+ one of the read-only text edits.
+
+ As we test against real fonts installed on the system and hence cannot use
+ a hard-coded list, we need this helper to ensure that the (non-trivial)
+ searching behavior matches what we expect.
+*/
+class ListSearchHelper
+{
+public:
+ ListSearchHelper(const QStringList &model)
+ : m_model(model)
+ {
+ }
+
+ int expectedCurrentIndexForSearch(const QString &searchText)
+ {
+ bool redo = false;
+
+ do {
+ m_searchText.append(searchText);
+
+ for (int i = 0; i < m_model.count(); ++i) {
+ if (m_model.at(i).startsWith(m_searchText, Qt::CaseInsensitive))
+ return i;
+ }
+
+ m_searchText.clear();
+
+ redo = !redo;
+ } while (redo);
+
+ return -1;
+ }
+
+private:
+ QStringList m_model;
+ QString m_searchText;
+};
+
+void tst_QQuickFontDialogImpl::searchFamily()
+{
+ CREATE_DIALOG_TEST_HELPER
+
+ // Open the dialog.
+ QVERIFY(dialogHelper.openDialog());
+ QTRY_VERIFY(dialogHelper.isQuickDialogOpen());
+
+ const QQuickTextField *familyEdit =
+ dialogHelper.quickDialog->findChild<QQuickTextField *>("familyEdit");
+ QVERIFY(familyEdit);
+
+ QQuickListView *fontFamilyListView =
+ dialogHelper.quickDialog->findChild<QQuickListView *>("familyListView");
+ QVERIFY(fontFamilyListView);
+
+ const QPoint familyEditCenterPos =
+ familyEdit->mapToScene({ familyEdit->width() / 2, familyEdit->height() / 2 }).toPoint();
+ QTest::mouseClick(dialogHelper.window(), Qt::LeftButton, Qt::NoModifier, familyEditCenterPos);
+ QVERIFY(familyEdit->hasActiveFocus());
+
+ QSignalSpy familyListViewCurrentIndexSpy(fontFamilyListView, SIGNAL(currentIndexChanged()));
+ QVERIFY(familyListViewCurrentIndexSpy.isValid());
+
+ const QString alphabet("abcdefghijklmnopqrstuvwxyz");
+ QStringList model = QFontDatabase::families(QFontDatabase::WritingSystem::Any);
+ model.removeIf(QFontDatabase::isPrivateFamily);
+
+ ListSearchHelper listSearchHelper(model);
+
+ // For each letter in the alphabet, press the corresponding key
+ // and check that the relevant delegate item in familyListView is selected.
+ for (auto alphabet_it = alphabet.cbegin(); alphabet_it != alphabet.cend(); alphabet_it++) {
+ const int previousIndex = fontFamilyListView->currentIndex();
+
+ const char keyEntered = alphabet_it->toLatin1();
+ QTest::keyClick(dialogHelper.window(), keyEntered);
+
+ int expectedListViewIndex = listSearchHelper.expectedCurrentIndexForSearch(QString(keyEntered));
+ if (expectedListViewIndex == -1) {
+ // There was no match, so the currentIndex should remain unchanged.
+ expectedListViewIndex = previousIndex;
+ }
+ if (fontFamilyListView->currentIndex() == expectedListViewIndex) {
+ // Working as expected; keep testing.
+ continue;
+ }
+
+ // Get the actual text of the current delegate item and the expected text.
+ auto currentDelegateItem = findViewDelegateItem(fontFamilyListView, fontFamilyListView->currentIndex());
+ QVERIFY(currentDelegateItem);
+ const auto actualDelegateText = currentDelegateItem->property("text").toString();
+ const auto expectedDelegateText = expectedListViewIndex != -1 ? model.at(expectedListViewIndex) : "(none)";
+
+ QFAIL(qPrintable(QString::fromLatin1("Expected fontFamilyListView to"
+ " change its currentIndex to %1 (%2) after typing '%3', but it is %4 (%5)")
+ .arg(expectedListViewIndex)
+ .arg(expectedDelegateText)
+ .arg(keyEntered)
+ .arg(fontFamilyListView->currentIndex())
+ .arg(actualDelegateText)));
+ }
+
+ CLOSE_DIALOG("Ok");
+}
+
+int main(int argc, char *argv[])
+{
+ // We need to set this attribute, and this (defining main() ourselves and
+ // calling QTEST_MAIN_IMPL) seems to be the nicest way to do it without
+ // duplicating too much code.
+ // We also don't want to run this for every style, as each one will have
+ // different ways of implementing the dialogs.
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeDialogs);
+ // For now we only test one style.
+ // TODO: use Basic
+ QQuickStyle::setStyle("Fusion");
+ QTEST_MAIN_IMPL(tst_QQuickFontDialogImpl)
+}
+
+#include "tst_qquickfontdialogimpl.moc"
diff --git a/tests/manual/dialogs/CMakeLists.txt b/tests/manual/dialogs/CMakeLists.txt
index d99d64b9..cc132f36 100644
--- a/tests/manual/dialogs/CMakeLists.txt
+++ b/tests/manual/dialogs/CMakeLists.txt
@@ -18,6 +18,7 @@ qt_internal_add_manual_test(dialogs
set(qmake_immediate_resource_files
"dialogs.qml"
"FileDialogPage.qml"
+ "FontDialogPage.qml"
"StringListView.qml"
"qmldir"
"Theme.qml"
diff --git a/tests/manual/dialogs/FontDialogPage.qml b/tests/manual/dialogs/FontDialogPage.qml
new file mode 100644
index 00000000..5b5d1034
--- /dev/null
+++ b/tests/manual/dialogs/FontDialogPage.qml
@@ -0,0 +1,222 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick
+import QtQuick.Controls
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Dialogs
+import QtQuick.Layouts
+
+import "."
+
+ColumnLayout {
+ property alias dialog: fontDialog
+
+ // Put it all in another ColumnLayout so we can easily add margins.
+ ColumnLayout {
+ Layout.leftMargin: 12
+ Layout.rightMargin: 12
+ Layout.topMargin: 12
+ Layout.bottomMargin: 12
+
+ GroupBox {
+ title: qsTr("Dialog properties")
+
+ Layout.fillWidth: true
+
+ GridLayout {
+ columns: 2
+ anchors.fill: parent
+
+ Label {
+ text: qsTr("modality")
+
+ Layout.alignment: Qt.AlignTop
+ Layout.minimumWidth: ApplicationWindow.window.width * 0.2
+ Layout.maximumWidth: ApplicationWindow.window.width * 0.2
+ }
+ ButtonGroup {
+ id: modalityButtonGroup
+ buttons: modalityColumnLayout.children
+ }
+ ColumnLayout {
+ id: modalityColumnLayout
+
+ RadioButton {
+ text: qsTr("Qt.NonModal")
+
+ readonly property int modality: Qt.NonModal
+ }
+ RadioButton {
+ text: qsTr("Qt.WindowModal")
+ checked: true
+
+ readonly property int modality: Qt.WindowModal
+ }
+ RadioButton {
+ text: qsTr("Qt.ApplicationModal")
+
+ readonly property int modality: Qt.ApplicationModal
+ }
+ }
+
+ Label {
+ text: qsTr("result")
+ }
+ TextField {
+ id: resultTextField
+ text: fontDialog.result === 1 ? qsTr("Accepted") : qsTr("Rejected")
+ readOnly: true
+ enabled: false
+ }
+
+ Label {
+ text: qsTr("title")
+ }
+ TextField {
+ id: titleTextField
+ text: qsTr("Pick a font")
+ }
+ }
+ }
+
+ GroupBox {
+ title: qsTr("FontDialog properties")
+
+ Layout.fillWidth: true
+
+ GridLayout {
+ columns: 2
+ anchors.fill: parent
+
+ Label {
+ Layout.minimumWidth: ApplicationWindow.window.width * 0.2
+ Layout.maximumWidth: ApplicationWindow.window.width * 0.2
+ text: qsTr("currentFont")
+ }
+ TextField {
+ id: currentFontTextField
+ text: qsTr("AaBbYyZz")
+ font: fontDialog.currentFont
+ readOnly: true
+ selectByMouse: true
+
+ Layout.fillWidth: true
+ }
+
+ Label {
+ text: qsTr("selectedFont")
+ }
+ TextField {
+ id: selectedFontTextField
+ text: qsTr("AaBbYyZz")
+ font: fontDialog.selectedFont
+ readOnly: true
+ selectByMouse: true
+
+ Layout.fillWidth: true
+ }
+
+ Label {
+ text: qsTr("fontOptions")
+
+ Layout.alignment: Qt.AlignTop
+ }
+ ColumnLayout {
+ id: fontOptionsColumnLayout
+
+ CheckBox {
+ id: noButtons
+ text: qsTr("NoButtons")
+
+ readonly property int fontOption: checked ? FontDialog.NoButtons : 0
+ }
+ CheckBox {
+ id: scalableFonts
+ text: qsTr("ScalableFonts")
+
+ readonly property int fontOption: checked ? FontDialog.ScalableFonts : 0
+ }
+ CheckBox {
+ id: nonScalableFonts
+ text: qsTr("NonScalableFonts")
+
+ readonly property int fontOption: checked ? FontDialog.NonScalableFonts : 0
+ }
+ CheckBox {
+ id: monospacedFonts
+ text: qsTr("MonospacedFonts")
+
+ readonly property int fontOption: checked ? FontDialog.MonospacedFonts : 0
+ }
+ CheckBox {
+ id: proportionalFonts
+ text: qsTr("ProportionalFonts")
+
+ readonly property int fontOption: checked ? FontDialog.ProportionalFonts : 0
+ }
+ }
+ }
+ }
+
+ FontDialog {
+ id: fontDialog
+
+ modality: modalityButtonGroup.checkedButton.modality
+ title: titleTextField.text
+ options: noButtons.fontOption
+ | scalableFonts.fontOption
+ | nonScalableFonts.fontOption
+ | monospacedFonts.fontOption
+ | proportionalFonts.fontOption
+ }
+ }
+}
diff --git a/tests/manual/dialogs/dialogs.pro b/tests/manual/dialogs/dialogs.pro
index abb31492..7dc1b8fd 100644
--- a/tests/manual/dialogs/dialogs.pro
+++ b/tests/manual/dialogs/dialogs.pro
@@ -6,6 +6,7 @@ SOURCES += dialogs.cpp
RESOURCES += \
dialogs.qml \
FileDialogPage.qml \
+ FontDialogPage.qml \
StringListView.qml \
qmldir \
Theme.qml
diff --git a/tests/manual/dialogs/dialogs.qml b/tests/manual/dialogs/dialogs.qml
index d1f54c08..6e64659e 100644
--- a/tests/manual/dialogs/dialogs.qml
+++ b/tests/manual/dialogs/dialogs.qml
@@ -84,7 +84,7 @@ ApplicationWindow {
text: qsTr("FileDialog")
}
TabButton {
- text: qsTr("Coming Soon...")
+ text: qsTr("FontDialog")
}
}
@@ -99,6 +99,7 @@ ApplicationWindow {
width: scrollView.width
FileDialogPage {}
+ FontDialogPage {}
}
}
}