diff options
author | J-P Nurmi <jpnurmi@qt.io> | 2016-11-17 18:35:24 +0100 |
---|---|---|
committer | J-P Nurmi <jpnurmi@qt.io> | 2016-11-17 18:35:24 +0100 |
commit | 4f2bb3e5a1ecbb1728209c7b2525c2c645ef49a2 (patch) | |
tree | f3be806d0301078e69d3043c2ac1d370aca14825 | |
parent | 170869fe1457fc68e96d46c9ff804071f86bd029 (diff) | |
parent | 4ef7af98e69bf676dd39e6aad5e6a5f980648e75 (diff) |
Merge remote-tracking branch 'origin/5.8' into dev
Conflicts:
src/quickcontrols2/qquickstyle.cpp
src/quicktemplates2/qquickslider.cpp
Change-Id: Ie12132690680706def6f516334a6ef0ba27336b3
71 files changed, 1400 insertions, 385 deletions
@@ -11,6 +11,7 @@ /examples/quickcontrols2/chattutorial/chapter3-navigation/chapter3-navigation /examples/quickcontrols2/chattutorial/chapter4-models/chapter4-models /examples/quickcontrols2/chattutorial/chapter5-styling/chapter5-styling +/examples/quickcontrols2/contactlist/contactlist /examples/quickcontrols2/gallery/gallery /examples/quickcontrols2/texteditor/texteditor diff --git a/examples/quickcontrols2/contactlist/ContactDelegate.ui.qml b/examples/quickcontrols2/contactlist/ContactDelegate.ui.qml new file mode 100644 index 00000000..8c8c4722 --- /dev/null +++ b/examples/quickcontrols2/contactlist/ContactDelegate.ui.qml @@ -0,0 +1,184 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples 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 2.7 +import QtQuick.Controls 2.1 + +AbstractButton { + clip: true + checkable: true + autoExclusive: true + + id: delegate + + height: 50 + property alias remove: remove + property alias edit: edit + width: 300 + + Column { + id: column1 + height: 400 + width: parent.width - 20 + spacing: 4 + + Row { + id: row1 + spacing: 10 + + Label { + text: fullName + font.pointSize: 16 + anchors.verticalCenter: parent.verticalCenter + font.bold: true + } + } + + Grid { + id: grid + opacity: 0 + + x: 60 + spacing: 10 + columns: 2 + Label { + text: qsTr("Address:") + font.bold: true + font.pixelSize: 16 + } + + Label { + text: address + font.pixelSize: 16 + font.bold: true + } + + Label { + text: qsTr("City:") + font.pixelSize: 16 + font.bold: true + } + + Label { + text: city + font.pixelSize: 16 + font.bold: true + } + + Label { + text: qsTr("Number:") + font.pixelSize: 16 + font.bold: true + } + + Label { + text: number + font.pixelSize: 16 + font.bold: true + } + } + + Row { + id: row + spacing: 12 + anchors.right: parent.right + + Button { + id: remove + width: 60 + height: 20 + text: "Remove" + } + + Button { + id: edit + width: 60 + height: 20 + text: "Edit" + } + } + + MenuSeparator { + id: separator + opacity: 0 + padding: 0 + anchors.right: parent.right + anchors.rightMargin: 4 + anchors.left: parent.left + anchors.leftMargin: 4 + } + } + + states: [ + State { + name: "collapsed" + when: !delegate.checked + }, + State { + name: "expanded" + when: delegate.checked + + PropertyChanges { + target: delegate + height: 160 + } + + PropertyChanges { + target: separator + opacity: 1 + } + + PropertyChanges { + target: grid + opacity: 1 + } + } + ] +} diff --git a/examples/quickcontrols2/contactlist/ContactDialog.qml b/examples/quickcontrols2/contactlist/ContactDialog.qml new file mode 100644 index 00000000..ed781282 --- /dev/null +++ b/examples/quickcontrols2/contactlist/ContactDialog.qml @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples 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 2.7 +import QtQuick.Window 2.2 +import QtQuick.Controls 2.1 + +Dialog { + standardButtons: Dialog.Ok | Dialog.Cancel + modal: true + + x: parent.width / 2 - width / 2 + y: parent.height / 2 - height / 2 + + property int lastIndex + property QtObject lastModel + + property alias form: form + + function addContact(model) { + form.fullName.clear(); + form.address.clear(); + form.city.clear(); + form.number.clear(); + lastIndex = -1; + lastModel = model; + + dialog.open(); + } + + function editContact(model, index) { + form.fullName.text = model.getFullName(index); + form.address.text = model.getAddress(index); + form.city.text = model.getCity(index); + form.number.text = model.getNumber(index); + lastIndex = index; + lastModel = model; + + dialog.open(); + } + + contentItem: ContactDialogForm { + id: form + } + + onAccepted: lastModel.updateContact(lastIndex, form.fullName.text, + form.address.text, form.city.text, + form.number.text) +} diff --git a/examples/quickcontrols2/contactlist/ContactDialogForm.ui.qml b/examples/quickcontrols2/contactlist/ContactDialogForm.ui.qml new file mode 100644 index 00000000..e1f31943 --- /dev/null +++ b/examples/quickcontrols2/contactlist/ContactDialogForm.ui.qml @@ -0,0 +1,120 @@ + +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples 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 2.7 +import QtQuick.Layouts 1.0 +import QtQuick.Controls 2.1 + +GridLayout { + id: grid + property alias fullName: fullName + property alias address: address + property alias city: city + property alias number: number + property int minimumInputSize: 120 + property string placeholderText: qsTr("<enter>") + + rows: 4 + columns: 2 + + Label { + text: qsTr("Full Name:") + Layout.alignment: Qt.AlignLeft | Qt.AlignBaseline + } + + TextField { + id: fullName + Layout.fillWidth: true + Layout.minimumWidth: grid.minimumInputSize + Layout.alignment: Qt.AlignLeft | Qt.AlignBaseline + placeholderText: grid.placeholderText + } + + Label { + text: qsTr("Address") + Layout.alignment: Qt.AlignLeft | Qt.AlignBaseline + } + + TextField { + id: address + Layout.fillWidth: true + Layout.minimumWidth: grid.minimumInputSize + Layout.alignment: Qt.AlignLeft | Qt.AlignBaseline + placeholderText: grid.placeholderText + } + + Label { + text: qsTr("City") + Layout.alignment: Qt.AlignLeft | Qt.AlignBaseline + } + + TextField { + id: city + Layout.fillWidth: true + Layout.minimumWidth: grid.minimumInputSize + Layout.alignment: Qt.AlignLeft | Qt.AlignBaseline + placeholderText: grid.placeholderText + } + + Label { + text: qsTr("Number") + Layout.alignment: Qt.AlignLeft | Qt.AlignBaseline + } + + TextField { + id: number + Layout.fillWidth: true + Layout.minimumWidth: grid.minimumInputSize + Layout.alignment: Qt.AlignLeft | Qt.AlignBaseline + placeholderText: grid.placeholderText + } +} + diff --git a/examples/quickcontrols2/contactlist/MainForm.ui.qml b/examples/quickcontrols2/contactlist/MainForm.ui.qml new file mode 100644 index 00000000..634398bd --- /dev/null +++ b/examples/quickcontrols2/contactlist/MainForm.ui.qml @@ -0,0 +1,113 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples 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 2.7 +import Backend 1.0 +import QtQuick.Controls 2.1 + +Page { + id: form + + width: 320 + height: 480 + + property alias button: button + property alias listView: listView + + property ContactDialog dialog: ContactDialog { + } + + ListView { + id: listView + + currentIndex: -1 + boundsBehavior: Flickable.StopAtBounds + clip: true + focus: true + anchors.fill: parent + section.criteria: ViewSection.FirstCharacter + section.property: "fullName" + snapMode: ListView.SnapToItem + + section.delegate: SectionDelegate { + width: listView.width + } + + delegate: ContactDelegate { + id: delegate + width: listView.width + x: 5 + + Connections { + target: delegate.edit + onClicked: dialog.editContact(listView.model, index) + } + + Connections { + target: delegate.remove + onClicked: listView.model.removeContact(index) + } + } + + model: AddressModel { + } + + ScrollBar.vertical: ScrollBar { + } + } + + footer: ToolBar { + ToolButton { + id: button + text: "Add Contact" + anchors.right: parent.right + } + } +} diff --git a/examples/quickcontrols2/gallery/pages/DrawerPage.qml b/examples/quickcontrols2/contactlist/SectionDelegate.ui.qml index 9e77223c..3b9f7dc5 100644 --- a/examples/quickcontrols2/gallery/pages/DrawerPage.qml +++ b/examples/quickcontrols2/contactlist/SectionDelegate.ui.qml @@ -1,12 +1,22 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: +** 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 @@ -38,36 +48,30 @@ ** ****************************************************************************/ -import QtQuick 2.6 +import QtQuick 2.7 import QtQuick.Controls 2.1 -Pane { - id: pane - - Column { - spacing: 40 - width: parent.width - - Label { - width: parent.width - wrapMode: Label.Wrap - horizontalAlignment: Qt.AlignHCenter - text: "Drawer provides a swipe-based side panel, similar to those often used " - + "in touch interfaces to provide a central location for navigation." +Rectangle { + height: 20 + width: 120 + gradient: Gradient { + GradientStop { + position: 0 + color: "#dddddd" } - Button { - text: "Open" - anchors.horizontalCenter: parent.horizontalCenter - width: Math.max(implicitWidth, Math.min(implicitWidth * 2, pane.availableWidth / 3)) - - onClicked: drawer.open() + GradientStop { + position: 1 + color: "blue" } } - Image { - source: "../images/arrow.png" - anchors.left: parent.left - anchors.bottom: parent.bottom + Label { + x: 12 + color: "white" + text: section + style: Text.Raised + font.pixelSize: 18 + font.bold: true } } diff --git a/examples/quickcontrols2/contactlist/addressmodel.cpp b/examples/quickcontrols2/contactlist/addressmodel.cpp new file mode 100644 index 00000000..fb83186e --- /dev/null +++ b/examples/quickcontrols2/contactlist/addressmodel.cpp @@ -0,0 +1,150 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples 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$ +** +****************************************************************************/ + +#include "addressmodel.h" + +AddressModel::AddressModel(QObject *parent ) : QAbstractListModel(parent) +{ + m_data.append({ "Angel Hogan", "Chapel St. 368 ", "Clearwater" , "0311 1823993" }); + m_data.append({ "Felicia Patton", "Annadale Lane 2", "Knoxville" , "0368 1244494" }); + m_data.append({ "Grant Crawford", "Windsor Drive 34", "Riverdale" , "0351 7826892" }); + m_data.append({ "Gretchen Little", "Sunset Drive 348", "Virginia Beach" , "0343 1234991" }); + m_data.append({ "Geoffrey Richards", "University Lane 54", "Trussville" , "0423 2144944" }); + m_data.append({ "Henrietta Chavez", "Via Volto San Luca 3", "Piobesi Torinese" , "0399 2826994" }); + m_data.append({ "Harvey Chandler", "North Squaw Creek 11", "Madisonville" , "0343 1244492" }); + m_data.append({ "Miguel Gomez", "Wild Rose Street 13", "Trussville" , "0343 9826996" }); + m_data.append({ "Norma Rodriguez", " Glen Eagles Street 53", "Buffalo" , "0241 5826596" }); + m_data.append({ "Shelia Ramirez", "East Miller Ave 68", "Pickerington" , "0346 4844556" }); + m_data.append({ "Stephanie Moss", "Piazza Trieste e Trento 77", "Roata Chiusani" , "0363 0510490" }); +} + +int AddressModel::rowCount(const QModelIndex &) const +{ + return m_data.count(); +} + +QVariant AddressModel::data(const QModelIndex &index, int role) const +{ + if (index.row() < rowCount()) + switch (role) { + case FullNameRole: return m_data.at(index.row()).fullName; + case AddressRole: return m_data.at(index.row()).address; + case CityRole: return m_data.at(index.row()).city; + case NumberRole: return m_data.at(index.row()).number; + default: return QVariant(); + + } + return QVariant(); +} + +QHash<int, QByteArray> AddressModel::roleNames() const +{ + static QHash<int, QByteArray> roleNames { + { FullNameRole, "fullName" }, + { AddressRole, "address" }, + { CityRole, "city" }, + { NumberRole, "number" } + }; + return roleNames; +} + +void AddressModel::updateContact(int row, + const QString &fullName, + const QString &address, + const QString &city, + const QString &number) +{ + if (row >= 0 && row < rowCount()) { + m_data.replace(row, { fullName, address, city, number }); + dataChanged(index(row, 0), index(row, 0), { FullNameRole, AddressRole, CityRole, NumberRole }); + } else if (row < 0) { + beginInsertRows(QModelIndex(), rowCount() - 1, rowCount() - 1); + m_data.append({fullName, address, city, number}); + endInsertRows(); + dataChanged(index(rowCount() - 1, 0), index(rowCount() - 1, 0), { FullNameRole, AddressRole, CityRole, NumberRole }); + } +} + +void AddressModel::removeContact(int row) +{ + if (row >= 0 && row < rowCount()) { + beginRemoveRows(QModelIndex(), row, row); + m_data.removeAt(row); + endRemoveRows(); + } +} + +QString AddressModel::getFullName(int row) const +{ + if (row >= 0 && row < rowCount()) + return m_data.at(row).fullName; + return QString(); +} + +QString AddressModel::getAddress(int row) const +{ + if (row >= 0 && row < rowCount()) + return m_data.at(row).address; + return QString(); +} + +QString AddressModel::getCity(int row) const +{ + if (row >= 0 && row < rowCount()) + return m_data.at(row).city; + return QString(); +} + +QString AddressModel::getNumber(int row) const +{ + if (row >= 0 && row < rowCount()) + return m_data.at(row).number; + return QString(); +} diff --git a/examples/quickcontrols2/contactlist/addressmodel.h b/examples/quickcontrols2/contactlist/addressmodel.h new file mode 100644 index 00000000..04417b95 --- /dev/null +++ b/examples/quickcontrols2/contactlist/addressmodel.h @@ -0,0 +1,95 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples 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$ +** +****************************************************************************/ + +#ifndef ADDRESSMODEL_H +#define ADDRESSMODEL_H + +#include <QAbstractListModel> + +class AddressModel : public QAbstractListModel +{ + Q_OBJECT + +public: + enum AdressModelRoles { + FullNameRole = Qt::DisplayRole, + AddressRole = Qt::UserRole, + CityRole, + NumberRole + }; + + Q_ENUM(AdressModelRoles) + + AddressModel(QObject *parent = nullptr); + + int rowCount(const QModelIndex & = QModelIndex()) const; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + QHash<int, QByteArray> roleNames() const; + + Q_INVOKABLE QString getFullName(int row) const; + Q_INVOKABLE QString getAddress(int row) const; + Q_INVOKABLE QString getCity(int row) const; + Q_INVOKABLE QString getNumber(int row) const; + + Q_INVOKABLE void updateContact(int row, const QString &fullName, const QString &address, const QString &city, const QString &number); + Q_INVOKABLE void removeContact(int row); + +private: + struct Data { + QString fullName; + QString address; + QString city; + QString number; + }; + + QList<Data> m_data; +}; + +#endif // ADDRESSMODEL_H diff --git a/examples/quickcontrols2/contactlist/contactlist.pro b/examples/quickcontrols2/contactlist/contactlist.pro new file mode 100644 index 00000000..8125d020 --- /dev/null +++ b/examples/quickcontrols2/contactlist/contactlist.pro @@ -0,0 +1,26 @@ +TEMPLATE = app +TARGET = contactlist + +QT += quick quickcontrols2 +CONFIG += c++11 + +HEADERS += \ + addressmodel.h + +SOURCES += main.cpp \ + addressmodel.cpp + +RESOURCES += \ + $$files(*.qml) \ + +# Additional import path used to resolve QML modules in Qt Creator's code model +QML_IMPORT_PATH=$$PWD/imports + +# Additional import path used to resolve QML modules just for Qt Quick Designer +QML_DESIGNER_IMPORT_PATH=$$PWD/designer + +OTHER_FILES += \ + designer/Backend/*.qml + +target.path = $$[QT_INSTALL_EXAMPLES]/quickcontrols2/contactlist +INSTALLS += target diff --git a/examples/quickcontrols2/gallery/pages/MenuPage.qml b/examples/quickcontrols2/contactlist/contactlist.qml index 49e6da07..7ace67fa 100644 --- a/examples/quickcontrols2/gallery/pages/MenuPage.qml +++ b/examples/quickcontrols2/contactlist/contactlist.qml @@ -1,12 +1,22 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: +** 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 @@ -38,30 +48,17 @@ ** ****************************************************************************/ -import QtQuick 2.6 +import QtQuick 2.7 import QtQuick.Controls 2.1 -ScrollablePage { - id: page - - Column { - spacing: 40 - width: parent.width - - Label { - width: parent.width - wrapMode: Label.Wrap - horizontalAlignment: Qt.AlignHCenter - text: "Menu can be used either as a context menu, or as a popup menu." - } - - Button { - id: button - text: "Open" - anchors.horizontalCenter: parent.horizontalCenter - width: Math.max(implicitWidth, Math.min(implicitWidth * 2, page.availableWidth / 3)) +ApplicationWindow { + visible: true + width: 320 + height: 480 + title: qsTr("Contact List") - onClicked: optionsMenu.open() - } + MainForm { + button.onClicked: dialog.addContact(listView.model) + anchors.fill: parent } } diff --git a/examples/quickcontrols2/contactlist/designer/Backend/AddressModel.qml b/examples/quickcontrols2/contactlist/designer/Backend/AddressModel.qml new file mode 100644 index 00000000..b9570934 --- /dev/null +++ b/examples/quickcontrols2/contactlist/designer/Backend/AddressModel.qml @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples 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 2.6 + +ListModel { + ListElement { + address: "Chapel St. 368" + city: "Knoxville" + number: "0311 1823993" + fullName: "Angel Hogan" + } + + ListElement { + address: "Annadale Lane 2" + city: "Clearwater" + number: "0368 1244494" + fullName: "Felicia Patton" + } + + ListElement { + address: "Windsor Drive 34" + city: "Riverdale" + number: "0368 1244494" + fullName: "Grant Crawford" + } + + ListElement { + address: "Sunset Drive 348" + city: "Virginia Beach" + number: "0351 7826892" + fullName: "Gretchen Little" + } + + ListElement { + address: "University Lane 54" + city: "Trussville" + number: "0399 2826994" + fullName: "Geoffrey Richards" + } +} diff --git a/examples/quickcontrols2/contactlist/designer/Backend/qmldir b/examples/quickcontrols2/contactlist/designer/Backend/qmldir new file mode 100644 index 00000000..45552843 --- /dev/null +++ b/examples/quickcontrols2/contactlist/designer/Backend/qmldir @@ -0,0 +1,2 @@ +module Backend +AddressModel 1.0 AddressModel.qml diff --git a/examples/quickcontrols2/contactlist/doc/images/qtquickcontrols2-contactlist.png b/examples/quickcontrols2/contactlist/doc/images/qtquickcontrols2-contactlist.png Binary files differnew file mode 100644 index 00000000..642cf2dc --- /dev/null +++ b/examples/quickcontrols2/contactlist/doc/images/qtquickcontrols2-contactlist.png diff --git a/examples/quickcontrols2/contactlist/doc/src/qtquickcontrols2-contactlist.qdoc b/examples/quickcontrols2/contactlist/doc/src/qtquickcontrols2-contactlist.qdoc new file mode 100644 index 00000000..93ef569d --- /dev/null +++ b/examples/quickcontrols2/contactlist/doc/src/qtquickcontrols2-contactlist.qdoc @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** 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 Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ +/*! + \example contactlist + \title Qt Quick Controls 2 - Contact List + \ingroup qtquickcontrols2-examples + \brief A QML app using Qt Quick Controls 2 and a C++ class that implements + a simple contact list. + + The \e {Contact List Example} shows how to integrate a C++ backend in a way that + is compatible with Qt Quick Designer. + For the declarative parts of the UI, .ui.qml files are used that can be edited + visually in the Qt Quick Designer. + + \section1 C++ Backend + + \borderedimage image qtquickcontrols2-contactlist.png + + The contact list application allows the user to add, edit, and remove contacts. + The actual implementation is done in C++ and exposed as a QAbstractListModel. + + The AdressModel C++ class is registered under a namespace and later + imported and instantiated by \e MainForm.ui.qml. For more information about registering C++ + classes as QML types, see \l {Defining QML Types from C++}. + + \code + #include <QtQml/qqml.h> + ... + qmlRegisterType<AdressModel>("Backend", 1, 0, "AdressModel"); + ... + \endcode + + \section1 Designer Support + + In the designer subdirectory, we create a plugin that replaces the AdressModel + in Qt Quick Designer. For this to work we add the following line to \e contactlist.pro. + + \code + QML_DESIGNER_IMPORT_PATH=$$PWD/designer + \endcode + + Because Qt Quick Designer cannot instantiate the AdressModel C++ class, we define + a mockup using a ListModel. This ensures that the ListView using the model shows something + in Qt Quick Designer. + + \include examples-run.qdocinc +*/ diff --git a/examples/quickcontrols2/gallery/pages/PopupPage.qml b/examples/quickcontrols2/contactlist/main.cpp index ac3b02b7..9c75d7b3 100644 --- a/examples/quickcontrols2/gallery/pages/PopupPage.qml +++ b/examples/quickcontrols2/contactlist/main.cpp @@ -1,12 +1,22 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: +** 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 @@ -38,31 +48,20 @@ ** ****************************************************************************/ -import QtQuick 2.6 -import QtQuick.Controls 2.1 +#include "addressmodel.h" -ScrollablePage { - id: page +#include <QGuiApplication> +#include <QQmlApplicationEngine> - Column { - spacing: 40 - width: parent.width +int main(int argc, char *argv[]) +{ + QGuiApplication app(argc, argv); - Label { - width: parent.width - wrapMode: Label.Wrap - horizontalAlignment: Qt.AlignHCenter - text: "Popup is used to display modal or modeless content that overlays other " - + "application content. In this example, the settings are shown in a popup." - } + qmlRegisterType<AddressModel>("Backend", 1, 0, "AddressModel"); - Button { - id: button - text: "Open" - anchors.horizontalCenter: parent.horizontalCenter - width: Math.max(implicitWidth, Math.min(implicitWidth * 2, page.availableWidth / 3)) + QQmlApplicationEngine engine; + engine.addImportPath(":/imports"); + engine.load(QUrl(QStringLiteral("qrc:/contactlist.qml"))); - onClicked: settingsDialog.open() - } - } + return app.exec(); } diff --git a/examples/quickcontrols2/gallery/gallery.qml b/examples/quickcontrols2/gallery/gallery.qml index a07872d5..06e7fc06 100644 --- a/examples/quickcontrols2/gallery/gallery.qml +++ b/examples/quickcontrols2/gallery/gallery.qml @@ -159,12 +159,9 @@ ApplicationWindow { ListElement { title: "Dial"; source: "qrc:/pages/DialPage.qml" } ListElement { title: "Dialog"; source: "qrc:/pages/DialogPage.qml" } ListElement { title: "Delegates"; source: "qrc:/pages/DelegatePage.qml" } - ListElement { title: "Drawer"; source: "qrc:/pages/DrawerPage.qml" } ListElement { title: "Frame"; source: "qrc:/pages/FramePage.qml" } ListElement { title: "GroupBox"; source: "qrc:/pages/GroupBoxPage.qml" } - ListElement { title: "Menu"; source: "qrc:/pages/MenuPage.qml" } ListElement { title: "PageIndicator"; source: "qrc:/pages/PageIndicatorPage.qml" } - ListElement { title: "Popup"; source: "qrc:/pages/PopupPage.qml" } ListElement { title: "ProgressBar"; source: "qrc:/pages/ProgressBarPage.qml" } ListElement { title: "RadioButton"; source: "qrc:/pages/RadioButtonPage.qml" } ListElement { title: "RangeSlider"; source: "qrc:/pages/RangeSliderPage.qml" } diff --git a/examples/quickcontrols2/gallery/pages/BusyIndicatorPage.qml b/examples/quickcontrols2/gallery/pages/BusyIndicatorPage.qml index d9e5f788..403da14e 100644 --- a/examples/quickcontrols2/gallery/pages/BusyIndicatorPage.qml +++ b/examples/quickcontrols2/gallery/pages/BusyIndicatorPage.qml @@ -57,9 +57,6 @@ ScrollablePage { } BusyIndicator { - readonly property int size: Math.min(page.availableWidth, page.availableHeight) / 5 - width: size - height: size anchors.horizontalCenter: parent.horizontalCenter } } diff --git a/examples/quickcontrols2/gallery/pages/ButtonPage.qml b/examples/quickcontrols2/gallery/pages/ButtonPage.qml index 7e945fa1..39776380 100644 --- a/examples/quickcontrols2/gallery/pages/ButtonPage.qml +++ b/examples/quickcontrols2/gallery/pages/ButtonPage.qml @@ -39,13 +39,12 @@ ****************************************************************************/ import QtQuick 2.6 +import QtQuick.Layouts 1.0 import QtQuick.Controls 2.1 ScrollablePage { id: page - readonly property int itemWidth: Math.max(button.implicitWidth, Math.min(button.implicitWidth * 2, page.availableWidth / 3)) - Column { spacing: 40 width: parent.width @@ -58,24 +57,24 @@ ScrollablePage { + "Buttons are normally used to perform an action, or to answer a question." } - Column { + ColumnLayout { spacing: 20 anchors.horizontalCenter: parent.horizontalCenter Button { text: "First" - width: itemWidth + Layout.fillWidth: true } Button { id: button text: "Second" - width: itemWidth highlighted: true + Layout.fillWidth: true } Button { text: "Third" enabled: false - width: itemWidth + Layout.fillWidth: true } } } diff --git a/examples/quickcontrols2/gallery/pages/ComboBoxPage.qml b/examples/quickcontrols2/gallery/pages/ComboBoxPage.qml index c800ba73..a52fcb67 100644 --- a/examples/quickcontrols2/gallery/pages/ComboBoxPage.qml +++ b/examples/quickcontrols2/gallery/pages/ComboBoxPage.qml @@ -58,7 +58,6 @@ ScrollablePage { ComboBox { model: ["First", "Second", "Third"] - width: Math.max(implicitWidth, Math.min(implicitWidth * 2, page.availableWidth / 3)) anchors.horizontalCenter: parent.horizontalCenter } } diff --git a/examples/quickcontrols2/gallery/pages/ProgressBarPage.qml b/examples/quickcontrols2/gallery/pages/ProgressBarPage.qml index 1548192f..a2646fd0 100644 --- a/examples/quickcontrols2/gallery/pages/ProgressBarPage.qml +++ b/examples/quickcontrols2/gallery/pages/ProgressBarPage.qml @@ -44,8 +44,6 @@ import QtQuick.Controls 2.1 ScrollablePage { id: page - readonly property int itemWidth: Math.max(bar.implicitWidth, page.availableWidth / 3) - Column { spacing: 40 width: parent.width @@ -61,13 +59,11 @@ ScrollablePage { ProgressBar { id: bar value: 0.5 - width: itemWidth anchors.horizontalCenter: parent.horizontalCenter } ProgressBar { indeterminate: true - width: itemWidth anchors.horizontalCenter: parent.horizontalCenter } } diff --git a/examples/quickcontrols2/gallery/pages/RangeSliderPage.qml b/examples/quickcontrols2/gallery/pages/RangeSliderPage.qml index 6a74e348..629a788b 100644 --- a/examples/quickcontrols2/gallery/pages/RangeSliderPage.qml +++ b/examples/quickcontrols2/gallery/pages/RangeSliderPage.qml @@ -44,8 +44,6 @@ import QtQuick.Controls 2.1 ScrollablePage { id: page - readonly property int itemWidth: Math.max(slider.implicitWidth, Math.min(slider.implicitWidth * 2, page.availableWidth / 3)) - Column { spacing: 40 width: parent.width @@ -61,7 +59,6 @@ ScrollablePage { id: slider first.value: 0.25 second.value: 0.75 - width: itemWidth anchors.horizontalCenter: parent.horizontalCenter } @@ -69,7 +66,6 @@ ScrollablePage { orientation: Qt.Vertical first.value: 0.25 second.value: 0.75 - height: itemWidth anchors.horizontalCenter: parent.horizontalCenter } } diff --git a/examples/quickcontrols2/gallery/pages/SliderPage.qml b/examples/quickcontrols2/gallery/pages/SliderPage.qml index 03cb7696..83ae32ef 100644 --- a/examples/quickcontrols2/gallery/pages/SliderPage.qml +++ b/examples/quickcontrols2/gallery/pages/SliderPage.qml @@ -44,8 +44,6 @@ import QtQuick.Controls 2.1 ScrollablePage { id: page - readonly property int itemWidth: Math.max(slider.implicitWidth, Math.min(slider.implicitWidth * 2, page.availableWidth / 3)) - Column { spacing: 40 width: parent.width @@ -60,14 +58,12 @@ ScrollablePage { Slider { id: slider value: 0.5 - width: itemWidth anchors.horizontalCenter: parent.horizontalCenter } Slider { orientation: Qt.Vertical value: 0.5 - height: itemWidth anchors.horizontalCenter: parent.horizontalCenter } } diff --git a/examples/quickcontrols2/gallery/pages/SpinBoxPage.qml b/examples/quickcontrols2/gallery/pages/SpinBoxPage.qml index c75982c2..93adc01a 100644 --- a/examples/quickcontrols2/gallery/pages/SpinBoxPage.qml +++ b/examples/quickcontrols2/gallery/pages/SpinBoxPage.qml @@ -44,8 +44,6 @@ import QtQuick.Controls 2.1 ScrollablePage { id: page - readonly property int itemWidth: Math.max(box.implicitWidth, Math.min(box.implicitWidth * 2, pane.availableWidth / 3)) - Column { spacing: 40 width: parent.width @@ -61,7 +59,6 @@ ScrollablePage { SpinBox { id: box value: 50 - width: itemWidth anchors.horizontalCenter: parent.horizontalCenter editable: true } diff --git a/examples/quickcontrols2/gallery/pages/TextFieldPage.qml b/examples/quickcontrols2/gallery/pages/TextFieldPage.qml index 9917da33..1b22fd08 100644 --- a/examples/quickcontrols2/gallery/pages/TextFieldPage.qml +++ b/examples/quickcontrols2/gallery/pages/TextFieldPage.qml @@ -58,7 +58,6 @@ ScrollablePage { TextField { id: field placeholderText: "TextField" - width: Math.max(implicitWidth, Math.min(implicitWidth * 2, pane.availableWidth / 3)) anchors.horizontalCenter: parent.horizontalCenter } } diff --git a/examples/quickcontrols2/gallery/pages/ToolTipPage.qml b/examples/quickcontrols2/gallery/pages/ToolTipPage.qml index 98ecd92e..d9bc969d 100644 --- a/examples/quickcontrols2/gallery/pages/ToolTipPage.qml +++ b/examples/quickcontrols2/gallery/pages/ToolTipPage.qml @@ -58,7 +58,6 @@ ScrollablePage { Button { text: "Tip" anchors.horizontalCenter: parent.horizontalCenter - width: Math.max(implicitWidth, Math.min(implicitWidth * 2, pane.availableWidth / 3)) ToolTip.timeout: 5000 ToolTip.visible: pressed diff --git a/examples/quickcontrols2/quickcontrols2.pro b/examples/quickcontrols2/quickcontrols2.pro index 6d732b17..458d10db 100644 --- a/examples/quickcontrols2/quickcontrols2.pro +++ b/examples/quickcontrols2/quickcontrols2.pro @@ -2,4 +2,5 @@ TEMPLATE = subdirs SUBDIRS += \ gallery \ chattutorial \ - texteditor + texteditor \ + contactlist diff --git a/src/imports/controls/doc/src/includes/qquickswitch.qdocinc b/src/imports/controls/doc/src/includes/qquickswitch.qdocinc index 32ccbb89..985f85d9 100644 --- a/src/imports/controls/doc/src/includes/qquickswitch.qdocinc +++ b/src/imports/controls/doc/src/includes/qquickswitch.qdocinc @@ -2,7 +2,7 @@ This property holds the logical position of the thumb indicator. -The position is defined as a percentage of the indicator's size, scaled to +The position is expressed as a fraction of the indicator's size, in the range \c 0.0 - \c 1.0. The position can be used for example to determine whether the thumb has been dragged past the halfway point. For visualizing a thumb indicator, the right-to-left aware \l visualPosition should be used instead. @@ -16,7 +16,7 @@ indicator, the right-to-left aware \l visualPosition should be used instead. This property holds the visual position of the thumb indicator. -The position is defined as a percentage of the indicator's size, scaled to +The position is expressed as a fraction of the indicator's size, in the range \c 0.0 - \c 1.0. When the control is \l {Control::mirrored}{mirrored}, the value is equal to \c {1.0 - position}. This makes the value suitable for visualizing the thumb indicator taking right-to-left support into account. diff --git a/src/imports/controls/material/Button.qml b/src/imports/controls/material/Button.qml index 8842f0ac..9b3ced25 100644 --- a/src/imports/controls/material/Button.qml +++ b/src/imports/controls/material/Button.qml @@ -62,7 +62,7 @@ T.Button { font: control.font color: !control.enabled ? control.Material.hintTextColor : control.flat && control.highlighted ? control.Material.accentColor : - control.highlighted ? control.Material.primaryHighlightedTextColor : control.Material.primaryTextColor + control.highlighted ? control.Material.primaryHighlightedTextColor : control.Material.foreground horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter elide: Text.ElideRight diff --git a/src/imports/controls/material/CheckBox.qml b/src/imports/controls/material/CheckBox.qml index bb760bbd..979654f7 100644 --- a/src/imports/controls/material/CheckBox.qml +++ b/src/imports/controls/material/CheckBox.qml @@ -78,7 +78,7 @@ T.CheckBox { text: control.text font: control.font - color: control.enabled ? control.Material.primaryTextColor : control.Material.hintTextColor + color: control.enabled ? control.Material.foreground : control.Material.hintTextColor elide: Text.ElideRight visible: control.text horizontalAlignment: Text.AlignLeft diff --git a/src/imports/controls/material/CheckDelegate.qml b/src/imports/controls/material/CheckDelegate.qml index e77e0a9c..aec48bf1 100644 --- a/src/imports/controls/material/CheckDelegate.qml +++ b/src/imports/controls/material/CheckDelegate.qml @@ -66,7 +66,7 @@ T.CheckDelegate { text: control.text font: control.font - color: control.enabled ? control.Material.primaryTextColor : control.Material.hintTextColor + color: control.enabled ? control.Material.foreground : control.Material.hintTextColor elide: Text.ElideRight visible: control.text horizontalAlignment: Text.AlignLeft diff --git a/src/imports/controls/material/ComboBox.qml b/src/imports/controls/material/ComboBox.qml index 814f8ae7..ab6fd17c 100644 --- a/src/imports/controls/material/ComboBox.qml +++ b/src/imports/controls/material/ComboBox.qml @@ -57,7 +57,7 @@ T.ComboBox { Material.elevation: flat ? control.pressed || control.hovered ? 2 : 0 : control.pressed ? 8 : 2 Material.background: flat ? "transparent" : undefined - Material.foreground: flat ? undefined : Material.foreground + Material.foreground: flat ? undefined : Material.primaryTextColor delegate: MenuItem { width: parent.width @@ -70,7 +70,7 @@ T.ComboBox { indicator: Image { x: control.mirrored ? control.padding : control.width - width - control.padding y: control.topPadding + (control.availableHeight - height) / 2 - source: "image://material/drop-indicator/" + (control.enabled ? control.Material.primaryTextColor : control.Material.hintTextColor) + source: "image://material/drop-indicator/" + (control.enabled ? control.Material.foreground : control.Material.hintTextColor) } contentItem: Text { @@ -80,7 +80,7 @@ T.ComboBox { text: control.displayText font: control.font - color: control.enabled ? control.Material.primaryTextColor : control.Material.hintTextColor + color: control.enabled ? control.Material.foreground : control.Material.hintTextColor horizontalAlignment: Text.AlignLeft verticalAlignment: Text.AlignVCenter elide: Text.ElideRight diff --git a/src/imports/controls/material/GroupBox.qml b/src/imports/controls/material/GroupBox.qml index afd1c8d1..64b589af 100644 --- a/src/imports/controls/material/GroupBox.qml +++ b/src/imports/controls/material/GroupBox.qml @@ -60,7 +60,7 @@ T.GroupBox { text: control.title font: control.font - color: control.enabled ? control.Material.primaryTextColor : control.Material.hintTextColor + color: control.enabled ? control.Material.foreground : control.Material.hintTextColor elide: Text.ElideRight horizontalAlignment: Text.AlignLeft verticalAlignment: Text.AlignVCenter diff --git a/src/imports/controls/material/ItemDelegate.qml b/src/imports/controls/material/ItemDelegate.qml index ad9604fd..ec74fbee 100644 --- a/src/imports/controls/material/ItemDelegate.qml +++ b/src/imports/controls/material/ItemDelegate.qml @@ -58,7 +58,7 @@ T.ItemDelegate { text: control.text font: control.font - color: control.enabled ? control.Material.primaryTextColor : control.Material.hintTextColor + color: control.enabled ? control.Material.foreground : control.Material.hintTextColor elide: Text.ElideRight visible: control.text horizontalAlignment: Text.AlignLeft diff --git a/src/imports/controls/material/Label.qml b/src/imports/controls/material/Label.qml index f4e12813..3a728dc8 100644 --- a/src/imports/controls/material/Label.qml +++ b/src/imports/controls/material/Label.qml @@ -41,6 +41,6 @@ import QtQuick.Controls.Material 2.1 T.Label { id: control - color: enabled ? Material.primaryTextColor : Material.hintTextColor + color: enabled ? Material.foreground : Material.hintTextColor linkColor: Material.accentColor } diff --git a/src/imports/controls/material/MenuItem.qml b/src/imports/controls/material/MenuItem.qml index 15c2d392..a6dbba2c 100644 --- a/src/imports/controls/material/MenuItem.qml +++ b/src/imports/controls/material/MenuItem.qml @@ -67,7 +67,7 @@ T.MenuItem { text: control.text font: control.font - color: control.enabled ? control.Material.primaryTextColor : control.Material.hintTextColor + color: control.enabled ? control.Material.foreground : control.Material.hintTextColor elide: Text.ElideRight visible: control.text horizontalAlignment: Text.AlignLeft diff --git a/src/imports/controls/material/PageIndicator.qml b/src/imports/controls/material/PageIndicator.qml index 7378dbbf..5a68df6b 100644 --- a/src/imports/controls/material/PageIndicator.qml +++ b/src/imports/controls/material/PageIndicator.qml @@ -54,7 +54,7 @@ T.PageIndicator { implicitHeight: 8 radius: width / 2 - color: control.enabled ? control.Material.primaryTextColor : control.Material.hintTextColor + color: control.enabled ? control.Material.foreground : control.Material.hintTextColor opacity: index === currentIndex ? 0.95 : pressed ? 0.7 : 0.45 Behavior on opacity { OpacityAnimator { duration: 100 } } diff --git a/src/imports/controls/material/RadioButton.qml b/src/imports/controls/material/RadioButton.qml index 6faf1caa..32bf1cbd 100644 --- a/src/imports/controls/material/RadioButton.qml +++ b/src/imports/controls/material/RadioButton.qml @@ -78,7 +78,7 @@ T.RadioButton { text: control.text font: control.font - color: control.enabled ? control.Material.primaryTextColor : control.Material.hintTextColor + color: control.enabled ? control.Material.foreground : control.Material.hintTextColor elide: Text.ElideRight visible: control.text horizontalAlignment: Text.AlignLeft diff --git a/src/imports/controls/material/RadioDelegate.qml b/src/imports/controls/material/RadioDelegate.qml index 4b7af82a..349352b4 100644 --- a/src/imports/controls/material/RadioDelegate.qml +++ b/src/imports/controls/material/RadioDelegate.qml @@ -66,7 +66,7 @@ T.RadioDelegate { text: control.text font: control.font - color: control.enabled ? control.Material.primaryTextColor : control.Material.hintTextColor + color: control.enabled ? control.Material.foreground : control.Material.hintTextColor elide: Text.ElideRight visible: control.text horizontalAlignment: Text.AlignLeft diff --git a/src/imports/controls/material/RangeSlider.qml b/src/imports/controls/material/RangeSlider.qml index 2442a38b..c46ddd2b 100644 --- a/src/imports/controls/material/RangeSlider.qml +++ b/src/imports/controls/material/RangeSlider.qml @@ -76,7 +76,7 @@ T.RangeSlider { implicitHeight: horizontal ? 48 : 200 width: horizontal ? control.availableWidth : 1 height: horizontal ? 1 : control.availableHeight - color: control.Material.primaryTextColor + color: control.Material.foreground scale: horizontal && control.mirrored ? -1 : 1 readonly property bool horizontal: control.orientation === Qt.Horizontal diff --git a/src/imports/controls/material/RoundButton.qml b/src/imports/controls/material/RoundButton.qml index e385ac1b..f6899dea 100644 --- a/src/imports/controls/material/RoundButton.qml +++ b/src/imports/controls/material/RoundButton.qml @@ -60,7 +60,7 @@ T.RoundButton { font: control.font color: !control.enabled ? control.Material.hintTextColor : control.flat && control.highlighted ? control.Material.accentColor : - control.highlighted ? control.Material.primaryHighlightedTextColor : control.Material.primaryTextColor + control.highlighted ? control.Material.primaryHighlightedTextColor : control.Material.foreground horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter elide: Text.ElideRight diff --git a/src/imports/controls/material/Slider.qml b/src/imports/controls/material/Slider.qml index fb871a02..5677193a 100644 --- a/src/imports/controls/material/Slider.qml +++ b/src/imports/controls/material/Slider.qml @@ -65,7 +65,7 @@ T.Slider { implicitHeight: horizontal ? 48 : 200 width: horizontal ? control.availableWidth : 1 height: horizontal ? 1 : control.availableHeight - color: control.Material.primaryTextColor + color: control.Material.foreground scale: horizontal && control.mirrored ? -1 : 1 readonly property bool horizontal: control.orientation === Qt.Horizontal diff --git a/src/imports/controls/material/SpinBox.qml b/src/imports/controls/material/SpinBox.qml index c48cb56f..18c5affd 100644 --- a/src/imports/controls/material/SpinBox.qml +++ b/src/imports/controls/material/SpinBox.qml @@ -68,9 +68,9 @@ T.SpinBox { text: control.textFromValue(control.value, control.locale) font: control.font - color: enabled ? control.Material.primaryTextColor : control.Material.hintTextColor + color: enabled ? control.Material.foreground : control.Material.hintTextColor selectionColor: control.Material.textSelectionColor - selectedTextColor: control.Material.primaryTextColor + selectedTextColor: control.Material.foreground horizontalAlignment: Qt.AlignHCenter verticalAlignment: Qt.AlignVCenter @@ -104,14 +104,14 @@ T.SpinBox { y: (parent.height - height) / 2 width: Math.min(parent.width / 3, parent.width / 3) height: 2 - color: enabled ? control.Material.primaryTextColor : control.Material.spinBoxDisabledIconColor + color: enabled ? control.Material.foreground : control.Material.spinBoxDisabledIconColor } Rectangle { x: (parent.width - width) / 2 y: (parent.height - height) / 2 width: 2 height: Math.min(parent.width / 3, parent.width / 3) - color: enabled ? control.Material.primaryTextColor : control.Material.spinBoxDisabledIconColor + color: enabled ? control.Material.foreground : control.Material.spinBoxDisabledIconColor } } @@ -138,7 +138,7 @@ T.SpinBox { y: (parent.height - height) / 2 width: parent.width / 3 height: 2 - color: enabled ? control.Material.primaryTextColor : control.Material.spinBoxDisabledIconColor + color: enabled ? control.Material.foreground : control.Material.spinBoxDisabledIconColor } } diff --git a/src/imports/controls/material/SwipeDelegate.qml b/src/imports/controls/material/SwipeDelegate.qml index 23db44fd..da54b0c3 100644 --- a/src/imports/controls/material/SwipeDelegate.qml +++ b/src/imports/controls/material/SwipeDelegate.qml @@ -60,7 +60,7 @@ T.SwipeDelegate { text: control.text font: control.font - color: control.enabled ? control.Material.primaryTextColor : control.Material.hintTextColor + color: control.enabled ? control.Material.foreground : control.Material.hintTextColor elide: Text.ElideRight visible: control.text horizontalAlignment: Text.AlignLeft diff --git a/src/imports/controls/material/Switch.qml b/src/imports/controls/material/Switch.qml index 3c9fbe51..645dc55a 100644 --- a/src/imports/controls/material/Switch.qml +++ b/src/imports/controls/material/Switch.qml @@ -73,7 +73,7 @@ T.Switch { text: control.text font: control.font - color: control.enabled ? control.Material.primaryTextColor : control.Material.hintTextColor + color: control.enabled ? control.Material.foreground : control.Material.hintTextColor elide: Text.ElideRight visible: control.text horizontalAlignment: Text.AlignLeft diff --git a/src/imports/controls/material/SwitchDelegate.qml b/src/imports/controls/material/SwitchDelegate.qml index 1a590774..9fb18271 100644 --- a/src/imports/controls/material/SwitchDelegate.qml +++ b/src/imports/controls/material/SwitchDelegate.qml @@ -66,7 +66,7 @@ T.SwitchDelegate { text: control.text font: control.font - color: control.enabled ? control.Material.primaryTextColor : control.Material.hintTextColor + color: control.enabled ? control.Material.foreground : control.Material.hintTextColor elide: Text.ElideRight visible: control.text horizontalAlignment: Text.AlignLeft diff --git a/src/imports/controls/material/TabButton.qml b/src/imports/controls/material/TabButton.qml index a900747a..a76df820 100644 --- a/src/imports/controls/material/TabButton.qml +++ b/src/imports/controls/material/TabButton.qml @@ -54,7 +54,7 @@ T.TabButton { text: control.text font: control.font elide: Text.ElideRight - color: !control.enabled ? control.Material.hintTextColor : control.down || control.checked ? control.Material.accentColor : control.Material.primaryTextColor + color: !control.enabled ? control.Material.hintTextColor : control.down || control.checked ? control.Material.accentColor : control.Material.foreground horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter } diff --git a/src/imports/controls/material/TextArea.qml b/src/imports/controls/material/TextArea.qml index 9018df2e..db67d059 100644 --- a/src/imports/controls/material/TextArea.qml +++ b/src/imports/controls/material/TextArea.qml @@ -52,7 +52,7 @@ T.TextArea { topPadding: 8 bottomPadding: 16 - color: enabled ? Material.primaryTextColor : Material.hintTextColor + color: enabled ? Material.foreground : Material.hintTextColor selectionColor: Material.accentColor selectedTextColor: Material.primaryHighlightedTextColor diff --git a/src/imports/controls/material/TextField.qml b/src/imports/controls/material/TextField.qml index ef7ae200..e6876f1c 100644 --- a/src/imports/controls/material/TextField.qml +++ b/src/imports/controls/material/TextField.qml @@ -52,7 +52,7 @@ T.TextField { topPadding: 8 bottomPadding: 16 - color: enabled ? Material.primaryTextColor : Material.hintTextColor + color: enabled ? Material.foreground : Material.hintTextColor selectionColor: Material.accentColor selectedTextColor: Material.primaryHighlightedTextColor verticalAlignment: TextInput.AlignVCenter diff --git a/src/imports/controls/material/ToolButton.qml b/src/imports/controls/material/ToolButton.qml index d11e41ae..78b15ac2 100644 --- a/src/imports/controls/material/ToolButton.qml +++ b/src/imports/controls/material/ToolButton.qml @@ -54,7 +54,7 @@ T.ToolButton { text: control.text font: control.font color: !control.enabled ? control.Material.hintTextColor : - control.checked || control.highlighted ? control.Material.accent : control.Material.primaryTextColor + control.checked || control.highlighted ? control.Material.accent : control.Material.foreground elide: Text.ElideRight horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter diff --git a/src/imports/controls/material/ToolTip.qml b/src/imports/controls/material/ToolTip.qml index 455f79c6..559b85da 100644 --- a/src/imports/controls/material/ToolTip.qml +++ b/src/imports/controls/material/ToolTip.qml @@ -72,7 +72,7 @@ T.ToolTip { text: control.text font: control.font // TODO: wrapMode: Label.Wrap - color: control.Material.primaryTextColor + color: control.Material.foreground } background: Rectangle { diff --git a/src/imports/controls/material/Tumbler.qml b/src/imports/controls/material/Tumbler.qml index 06a012f6..b8d0e975 100644 --- a/src/imports/controls/material/Tumbler.qml +++ b/src/imports/controls/material/Tumbler.qml @@ -48,7 +48,7 @@ T.Tumbler { delegate: Text { id: label text: modelData - color: control.Material.primaryTextColor + color: control.Material.foreground font: control.font opacity: (1.0 - Math.abs(Tumbler.displacement) / (visibleItemCount / 2)) * (control.enabled ? 1 : 0.6) horizontalAlignment: Text.AlignHCenter diff --git a/src/imports/controls/material/qquickmaterialstyle.cpp b/src/imports/controls/material/qquickmaterialstyle.cpp index a4041d0d..08203482 100644 --- a/src/imports/controls/material/qquickmaterialstyle.cpp +++ b/src/imports/controls/material/qquickmaterialstyle.cpp @@ -638,7 +638,13 @@ void QQuickMaterialStyle::resetAccent() QVariant QQuickMaterialStyle::foreground() const { - return primaryTextColor(); + if (!m_hasForeground) + return QColor::fromRgba(m_theme == Light ? primaryTextColorLight : primaryTextColorDark); + if (m_customForeground) + return QColor::fromRgba(m_foreground); + if (m_foreground > BlueGrey) + return QColor(); + return QColor::fromRgba(colors[m_foreground][Shade500]); } void QQuickMaterialStyle::setForeground(const QVariant &var) @@ -814,13 +820,7 @@ QColor QQuickMaterialStyle::backgroundColor() const QColor QQuickMaterialStyle::primaryTextColor() const { - if (!m_hasForeground) - return QColor::fromRgba(m_theme == Light ? primaryTextColorLight : primaryTextColorDark); - if (m_customForeground) - return QColor::fromRgba(m_foreground); - if (m_foreground > BlueGrey) - return QColor(); - return colors[m_foreground][Shade500]; + return QColor::fromRgba(m_theme == Light ? primaryTextColorLight : primaryTextColorDark); } QColor QQuickMaterialStyle::primaryHighlightedTextColor() const diff --git a/src/imports/controls/material/qquickmaterialstyle_p.h b/src/imports/controls/material/qquickmaterialstyle_p.h index aec665f6..dbf366cd 100644 --- a/src/imports/controls/material/qquickmaterialstyle_p.h +++ b/src/imports/controls/material/qquickmaterialstyle_p.h @@ -66,7 +66,7 @@ class QQuickMaterialStyle : public QQuickStyleAttached Q_PROPERTY(QColor primaryColor READ primaryColor NOTIFY primaryChanged FINAL) // TODO: remove? Q_PROPERTY(QColor accentColor READ accentColor NOTIFY accentChanged FINAL) // TODO: remove? Q_PROPERTY(QColor backgroundColor READ backgroundColor NOTIFY backgroundChanged FINAL) - Q_PROPERTY(QColor primaryTextColor READ primaryTextColor NOTIFY foregroundChanged FINAL) // TODO: rename to foregroundColor()? + Q_PROPERTY(QColor primaryTextColor READ primaryTextColor NOTIFY paletteChanged FINAL) Q_PROPERTY(QColor primaryHighlightedTextColor READ primaryHighlightedTextColor NOTIFY paletteChanged FINAL) Q_PROPERTY(QColor secondaryTextColor READ secondaryTextColor NOTIFY paletteChanged FINAL) Q_PROPERTY(QColor hintTextColor READ hintTextColor NOTIFY paletteChanged FINAL) diff --git a/src/imports/controls/plugins.qmltypes b/src/imports/controls/plugins.qmltypes index 0a89a8b0..de4e26f8 100644 --- a/src/imports/controls/plugins.qmltypes +++ b/src/imports/controls/plugins.qmltypes @@ -508,6 +508,7 @@ Module { Property { name: "down"; type: "bool" } Property { name: "pressed"; type: "bool"; isReadonly: true } Property { name: "checked"; type: "bool" } + Property { name: "checkable"; type: "bool" } Property { name: "autoExclusive"; type: "bool" } Property { name: "indicator"; type: "QQuickItem"; isPointer: true } Signal { name: "pressed" } @@ -559,7 +560,6 @@ Module { prototype: "QQuickAbstractButton" exports: ["QtQuick.Templates/Button 2.0"] exportMetaObjectRevisions: [0] - Property { name: "checkable"; type: "bool" } Property { name: "autoRepeat"; type: "bool" } Property { name: "highlighted"; type: "bool" } Property { name: "flat"; type: "bool" } @@ -894,7 +894,6 @@ Module { prototype: "QQuickAbstractButton" exports: ["QtQuick.Templates/MenuItem 2.0"] exportMetaObjectRevisions: [0] - Property { name: "checkable"; type: "bool" } Property { name: "highlighted"; type: "bool" } Signal { name: "triggered" } } diff --git a/src/imports/templates/plugins.qmltypes b/src/imports/templates/plugins.qmltypes index 31267ce2..6b644437 100644 --- a/src/imports/templates/plugins.qmltypes +++ b/src/imports/templates/plugins.qmltypes @@ -18,6 +18,7 @@ Module { Property { name: "down"; type: "bool" } Property { name: "pressed"; type: "bool"; isReadonly: true } Property { name: "checked"; type: "bool" } + Property { name: "checkable"; type: "bool" } Property { name: "autoExclusive"; type: "bool" } Property { name: "indicator"; type: "QQuickItem"; isPointer: true } Signal { name: "pressed" } @@ -69,7 +70,6 @@ Module { prototype: "QQuickAbstractButton" exports: ["QtQuick.Templates/Button 2.0"] exportMetaObjectRevisions: [0] - Property { name: "checkable"; type: "bool" } Property { name: "autoRepeat"; type: "bool" } Property { name: "highlighted"; type: "bool" } Property { name: "flat"; type: "bool" } @@ -404,7 +404,6 @@ Module { prototype: "QQuickAbstractButton" exports: ["QtQuick.Templates/MenuItem 2.0"] exportMetaObjectRevisions: [0] - Property { name: "checkable"; type: "bool" } Property { name: "highlighted"; type: "bool" } Signal { name: "triggered" } } diff --git a/src/quickcontrols2/qquickstyle.cpp b/src/quickcontrols2/qquickstyle.cpp index 4247b204..aa168301 100644 --- a/src/quickcontrols2/qquickstyle.cpp +++ b/src/quickcontrols2/qquickstyle.cpp @@ -41,6 +41,7 @@ #include <QtCore/qdir.h> #include <QtCore/qdebug.h> #include <QtCore/qsettings.h> +#include <QtCore/qlibraryinfo.h> #include <QtGui/private/qguiapplication_p.h> #include <QtQml/private/qqmlmetatype_p.h> #include <QtQml/qqmlengine.h> @@ -96,6 +97,23 @@ QT_BEGIN_NAMESPACE \sa {Styling Qt Quick Controls 2} */ +// TODO: QQmlImportDatabase::defaultImportPathList() +static QStringList defaultImportPathList() +{ + QStringList importPaths; + importPaths.reserve(3); + importPaths += QLibraryInfo::location(QLibraryInfo::Qml2ImportsPath); + + if (Q_UNLIKELY(!qEnvironmentVariableIsEmpty("QML2_IMPORT_PATH"))) { + const QByteArray envImportPath = qgetenv("QML2_IMPORT_PATH"); + importPaths += QString::fromLatin1(envImportPath).split(QDir::listSeparator(), QString::SkipEmptyParts); + } + + importPaths += QStringLiteral("qrc:/qt-project.org/imports"); + importPaths += QCoreApplication::applicationDirPath(); + return importPaths; +} + struct QQuickStyleSpec { QQuickStyleSpec() : custom(false), resolved(false) { } @@ -222,7 +240,7 @@ QStringList QQuickStylePrivate::stylePaths() // built-in import paths const QString targetPath = QStringLiteral("QtQuick/Controls.2"); - const QStringList importPaths = QQmlEngine().importPathList(); + const QStringList importPaths = defaultImportPathList(); for (const QString &importPath : importPaths) { QDir dir(importPath); if (dir.cd(targetPath)) diff --git a/src/quicktemplates2/qquickabstractbutton.cpp b/src/quicktemplates2/qquickabstractbutton.cpp index 85f58fd5..350af84a 100644 --- a/src/quicktemplates2/qquickabstractbutton.cpp +++ b/src/quicktemplates2/qquickabstractbutton.cpp @@ -332,6 +332,8 @@ void QQuickAbstractButton::setPressed(bool isPressed) \qmlproperty bool QtQuick.Controls::AbstractButton::checked This property holds whether the button is checked. + + \sa checkable */ bool QQuickAbstractButton::isChecked() const { @@ -354,11 +356,21 @@ void QQuickAbstractButton::setChecked(bool checked) emit checkedChanged(); } -// We define these in QQuickAbstractButton without exposing checkable as a -// property, and instead expose it as a property in QQuickButton. -// QQuickRadioButton, QQuickSwitch and QQuickCheckBox are checkable by default, -// but if we removed the checkable code from here, they'd each have to -// duplicate it. +/*! + \qmlproperty bool QtQuick.Controls::AbstractButton::checkable + + This property holds whether the button is checkable. + + A checkable button toggles between checked (on) and unchecked (off) when + the user clicks on it or presses the space bar while the button has active + focus. + + Setting \l checked to \c true forces this property to \c true. + + The default value is \c false. + + \sa checked +*/ bool QQuickAbstractButton::isCheckable() const { Q_D(const QQuickAbstractButton); @@ -374,6 +386,7 @@ void QQuickAbstractButton::setCheckable(bool checkable) d->checkable = checkable; setAccessibleProperty("checkable", checkable); checkableChange(); + emit checkableChanged(); } /*! @@ -529,7 +542,7 @@ void QQuickAbstractButton::mouseMoveEvent(QMouseEvent *event) QQuickControl::mouseMoveEvent(event); setPressed(d->keepPressed || contains(event->pos())); - if (d->autoRepeat) + if (!d->pressed && d->autoRepeat) d->stopPressRepeat(); else if (d->holdTimer > 0 && (!d->pressed || QLineF(d->pressPoint, event->localPos()).length() > QGuiApplication::styleHints()->startDragDistance())) d->stopPressAndHold(); diff --git a/src/quicktemplates2/qquickabstractbutton_p.h b/src/quicktemplates2/qquickabstractbutton_p.h index 3b4fff6b..524dd130 100644 --- a/src/quicktemplates2/qquickabstractbutton_p.h +++ b/src/quicktemplates2/qquickabstractbutton_p.h @@ -61,6 +61,7 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickAbstractButton : public QQuickContr Q_PROPERTY(bool down READ isDown WRITE setDown NOTIFY downChanged RESET resetDown FINAL) Q_PROPERTY(bool pressed READ isPressed NOTIFY pressedChanged FINAL) Q_PROPERTY(bool checked READ isChecked WRITE setChecked NOTIFY checkedChanged FINAL) + Q_PROPERTY(bool checkable READ isCheckable WRITE setCheckable NOTIFY checkableChanged FINAL) Q_PROPERTY(bool autoExclusive READ autoExclusive WRITE setAutoExclusive NOTIFY autoExclusiveChanged FINAL) Q_PROPERTY(QQuickItem *indicator READ indicator WRITE setIndicator NOTIFY indicatorChanged FINAL) @@ -107,6 +108,7 @@ Q_SIGNALS: void downChanged(); void pressedChanged(); void checkedChanged(); + void checkableChanged(); void autoExclusiveChanged(); void indicatorChanged(); diff --git a/src/quicktemplates2/qquickbutton.cpp b/src/quicktemplates2/qquickbutton.cpp index 3d00e40c..b11d2179 100644 --- a/src/quicktemplates2/qquickbutton.cpp +++ b/src/quicktemplates2/qquickbutton.cpp @@ -96,28 +96,6 @@ QQuickButton::QQuickButton(QQuickButtonPrivate &dd, QQuickItem *parent) : } /*! - \qmlproperty bool QtQuick.Controls::Button::checkable - - This property holds whether the button is checkable. - - A checkable button toggles between checked (on) and unchecked (off) when - the user clicks on it or presses the space bar while the button has active - focus. - - Setting \l {AbstractButton::}{checked} to \c true forces this property to - \c true. - - The default value is \c false. - - \sa CheckBox, Switch -*/ - -void QQuickButton::checkableChange() -{ - emit checkableChanged(); -} - -/*! \qmlproperty bool QtQuick.Controls::Button::autoRepeat This property holds whether the button repeats diff --git a/src/quicktemplates2/qquickbutton_p.h b/src/quicktemplates2/qquickbutton_p.h index 95f94f10..5edbbe4e 100644 --- a/src/quicktemplates2/qquickbutton_p.h +++ b/src/quicktemplates2/qquickbutton_p.h @@ -57,7 +57,6 @@ class QQuickButtonPrivate; class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickButton : public QQuickAbstractButton { Q_OBJECT - Q_PROPERTY(bool checkable READ isCheckable WRITE setCheckable NOTIFY checkableChanged FINAL) Q_PROPERTY(bool autoRepeat READ autoRepeat WRITE setAutoRepeat NOTIFY autoRepeatChanged FINAL) Q_PROPERTY(bool highlighted READ isHighlighted WRITE setHighlighted NOTIFY highlightedChanged FINAL) Q_PROPERTY(bool flat READ isFlat WRITE setFlat NOTIFY flatChanged FINAL) @@ -72,7 +71,6 @@ public: void setFlat(bool flat); Q_SIGNALS: - void checkableChanged(); void autoRepeatChanged(); void highlightedChanged(); void flatChanged(); @@ -80,7 +78,6 @@ Q_SIGNALS: protected: QQuickButton(QQuickButtonPrivate &dd, QQuickItem *parent); - void checkableChange() override; void autoRepeatChange() override; QFont defaultFont() const override; diff --git a/src/quicktemplates2/qquickdial.cpp b/src/quicktemplates2/qquickdial.cpp index 4c8576a7..9475cff7 100644 --- a/src/quicktemplates2/qquickdial.cpp +++ b/src/quicktemplates2/qquickdial.cpp @@ -283,8 +283,8 @@ void QQuickDial::setValue(qreal value) This property holds the logical position of the handle. - The position is defined as a percentage of the control's angle range (the - range within which the handle can be moved) scaled to \c {0.0 - 1.0}. + The position is expressed as a fraction of the control's angle range (the + range within which the handle can be moved) in the range \c {0.0 - 1.0}. Unlike the \l value property, the \c position is continuously updated while the handle is dragged. diff --git a/src/quicktemplates2/qquickmenuitem.cpp b/src/quicktemplates2/qquickmenuitem.cpp index 564d3f38..cb23df07 100644 --- a/src/quicktemplates2/qquickmenuitem.cpp +++ b/src/quicktemplates2/qquickmenuitem.cpp @@ -110,22 +110,6 @@ QQuickMenuItem::QQuickMenuItem(QQuickItem *parent) : connect(this, &QQuickAbstractButton::clicked, this, &QQuickMenuItem::triggered); } -/*! - \qmlproperty bool QtQuick.Controls::MenuItem::checkable - - This property holds whether the menu item is checkable. - - A checkable menu item toggles between checked (on) and unchecked (off) when - the user clicks on it or interacts with it via the keyboard. - - \sa {AbstractButton::}{checked} -*/ - -void QQuickMenuItem::checkableChange() -{ - emit checkableChanged(); -} - QFont QQuickMenuItem::defaultFont() const { return QQuickControlPrivate::themeFont(QPlatformTheme::MenuItemFont); diff --git a/src/quicktemplates2/qquickmenuitem_p.h b/src/quicktemplates2/qquickmenuitem_p.h index 6c717e13..258a096f 100644 --- a/src/quicktemplates2/qquickmenuitem_p.h +++ b/src/quicktemplates2/qquickmenuitem_p.h @@ -57,7 +57,6 @@ class QQuickMenuItemPrivate; class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickMenuItem : public QQuickAbstractButton { Q_OBJECT - Q_PROPERTY(bool checkable READ isCheckable WRITE setCheckable NOTIFY checkableChanged FINAL) Q_PROPERTY(bool highlighted READ isHighlighted WRITE setHighlighted NOTIFY highlightedChanged FINAL) public: @@ -67,12 +66,10 @@ public: void setHighlighted(bool highlighted); Q_SIGNALS: - void checkableChanged(); void triggered(); void highlightedChanged(); protected: - void checkableChange() override; QFont defaultFont() const override; #ifndef QT_NO_ACCESSIBILITY diff --git a/src/quicktemplates2/qquickprogressbar.cpp b/src/quicktemplates2/qquickprogressbar.cpp index 5d5503e6..d8ada6f4 100644 --- a/src/quicktemplates2/qquickprogressbar.cpp +++ b/src/quicktemplates2/qquickprogressbar.cpp @@ -192,7 +192,7 @@ void QQuickProgressBar::setValue(qreal value) This property holds the logical position of the progress. - The position is defined as a percentage of the value, scaled to + The position is expressed as a fraction of the value, in the range \c {0.0 - 1.0}. For visualizing the progress, the right-to-left aware \l visualPosition should be used instead. @@ -212,7 +212,7 @@ qreal QQuickProgressBar::position() const This property holds the visual position of the progress. - The position is defined as a percentage of the value, scaled to \c {0.0 - 1.0}. + The position is expressed as a fraction of the value, in the range \c {0.0 - 1.0}. When the control is \l {Control::mirrored}{mirrored}, \c visuaPosition is equal to \c {1.0 - position}. This makes \c visualPosition suitable for visualizing the progress, taking right-to-left support into account. diff --git a/src/quicktemplates2/qquickrangeslider.cpp b/src/quicktemplates2/qquickrangeslider.cpp index ffe2e976..cd6395bd 100644 --- a/src/quicktemplates2/qquickrangeslider.cpp +++ b/src/quicktemplates2/qquickrangeslider.cpp @@ -68,8 +68,8 @@ QT_BEGIN_NAMESPACE } \endcode - The \l {first.position} and \l {second.position} properties are defined as a - percentage of the control's size, scaled within the range \c {0.0 - 1.0}. + The \l {first.position} and \l {second.position} properties are expressed as + fractions of the control's size, in the range \c {0.0 - 1.0}. The \l {first.visualPosition} and \l {second.visualPosition} properties are the same, except that they are reversed in a \l {Right-to-left User Interfaces}{right-to-left} application. @@ -489,7 +489,7 @@ void QQuickRangeSlider::setTo(qreal to) \li visualPosition \li This property holds the visual position of the first handle. - The position is defined as a percentage of the control's size, scaled to + The position is expressed as a fraction of the control's size, in the range \c {0.0 - 1.0}. When the control is \l {Control::mirrored}{mirrored}, the value is equal to \c {1.0 - position}. This makes the value suitable for visualizing the slider, taking right-to-left support into account. @@ -497,8 +497,8 @@ void QQuickRangeSlider::setTo(qreal to) \li position \li This property holds the logical position of the first handle. - The position is defined as a percentage of the control's size, scaled - to \c {0.0 - 1.0}. Unlike \l {first.value}{value}, position is + The position is expressed as a fraction of the control's size, in the range + \c {0.0 - 1.0}. Unlike \l {first.value}{value}, position is continuously updated while the handle is dragged. For visualizing a slider, the right-to-left aware \l {first.visualPosition}{visualPosition} should be used instead. @@ -553,7 +553,7 @@ QQuickRangeSliderNode *QQuickRangeSlider::first() const \li visualPosition \li This property holds the visual position of the second handle. - The position is defined as a percentage of the control's size, scaled to + The position is expressed as a fraction of the control's size, in the range \c {0.0 - 1.0}. When the control is \l {Control::mirrored}{mirrored}, the value is equal to \c {1.0 - position}. This makes the value suitable for visualizing the slider, taking right-to-left support into account. @@ -561,8 +561,8 @@ QQuickRangeSliderNode *QQuickRangeSlider::first() const \li position \li This property holds the logical position of the second handle. - The position is defined as a percentage of the control's size, scaled - to \c {0.0 - 1.0}. Unlike \l {second.value}{value}, position is + The position is expressed as a fraction of the control's size, in the range + \c {0.0 - 1.0}. Unlike \l {second.value}{value}, position is continuously updated while the handle is dragged. For visualizing a slider, the right-to-left aware \l {second.visualPosition}{visualPosition} should be used instead. diff --git a/src/quicktemplates2/qquickslider.cpp b/src/quicktemplates2/qquickslider.cpp index 0b91d61d..d2d5da89 100644 --- a/src/quicktemplates2/qquickslider.cpp +++ b/src/quicktemplates2/qquickslider.cpp @@ -64,8 +64,8 @@ QT_BEGIN_NAMESPACE } \endcode - The \l position property is defined as a percentage of the control's size, - scaled within the range \c {0.0 - 1.0}. The \l visualPosition property is + The \l position property is expressed as a fraction of the control's size, + in the range \c {0.0 - 1.0}. The \l visualPosition property is the same, except that it is reversed in a \l {Right-to-left User Interfaces}{right-to-left} application. The visualPosition is useful for positioning the handle when styling Slider. @@ -259,8 +259,8 @@ void QQuickSlider::setValue(qreal value) This property holds the logical position of the handle. - The position is defined as a percentage of the control's size, scaled - to \c {0.0 - 1.0}. The \c position is continuously updated while the + The position is expressed as a fraction of the control's size, in the range + \c {0.0 - 1.0}. The \c position is continuously updated while the handle is dragged. For visualizing a slider, the right-to-left aware \l visualPosition should be used instead. @@ -278,7 +278,7 @@ qreal QQuickSlider::position() const This property holds the visual position of the handle. - The position is defined as a percentage of the control's size, scaled to + The position is expressed as a fraction of the control's size, in the range \c {0.0 - 1.0}. When the control is \l {Control::mirrored}{mirrored}, the value is equal to \c {1.0 - position}. This makes the value suitable for visualizing the slider, taking right-to-left support into account. diff --git a/src/quicktemplates2/qquickspinbox.cpp b/src/quicktemplates2/qquickspinbox.cpp index 957200a4..506405fe 100644 --- a/src/quicktemplates2/qquickspinbox.cpp +++ b/src/quicktemplates2/qquickspinbox.cpp @@ -252,7 +252,8 @@ bool QQuickSpinBoxPrivate::handleMouseMoveEvent(QQuickItem *child, QMouseEvent * bool pressed = up->isPressed() || down->isPressed(); q->setAccessibleProperty("pressed", pressed); - stopPressRepeat(); + if (!pressed) + stopPressRepeat(); return pressed; } diff --git a/tests/auto/controls/data/tst_button.qml b/tests/auto/controls/data/tst_button.qml index 16d1bb94..dcce20d7 100644 --- a/tests/auto/controls/data/tst_button.qml +++ b/tests/auto/controls/data/tst_button.qml @@ -52,13 +52,13 @@ TestCase { Component { id: button - Button { - id: control + Button { } + } - property SignalSequenceSpy spy: SignalSequenceSpy { - target: control - signals: ["pressed", "released", "canceled", "clicked", "doubleClicked", "pressedChanged", "downChanged", "checkedChanged"] - } + Component { + id: signalSequenceSpy + SignalSequenceSpy { + signals: ["pressed", "released", "canceled", "clicked", "doubleClicked", "pressedChanged", "downChanged", "checkedChanged"] } } @@ -84,52 +84,54 @@ TestCase { var control = button.createObject(testCase) verify(control) + var sequenceSpy = signalSequenceSpy.createObject(control, {target: control}) + // click - control.spy.expectedSequence = [["pressedChanged", { "pressed": true }], + sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": true }], ["downChanged", { "down": true }], "pressed"] mousePress(control, control.width / 2, control.height / 2, Qt.LeftButton) compare(control.pressed, true) - verify(control.spy.success) + verify(sequenceSpy.success) - control.spy.expectedSequence = [["pressedChanged", { "pressed": false }], + sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": false }], ["downChanged", { "down": false }], "released", "clicked"] mouseRelease(control, control.width / 2, control.height / 2, Qt.LeftButton) compare(control.pressed, false) - verify(control.spy.success) + verify(sequenceSpy.success) // release outside - control.spy.expectedSequence = [["pressedChanged", { "pressed": true }], + sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": true }], ["downChanged", { "down": true }], "pressed"] mousePress(control, control.width / 2, control.height / 2, Qt.LeftButton) compare(control.pressed, true) - verify(control.spy.success) + verify(sequenceSpy.success) - control.spy.expectedSequence = [["pressedChanged", { "pressed": false }], + sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": false }], ["downChanged", { "down": false }]] mouseMove(control, control.width * 2, control.height * 2, 0, Qt.LeftButton) compare(control.pressed, false) - verify(control.spy.success) + verify(sequenceSpy.success) - control.spy.expectedSequence = [["canceled", { "pressed": false }]] + sequenceSpy.expectedSequence = [["canceled", { "pressed": false }]] mouseRelease(control, control.width * 2, control.height * 2, Qt.LeftButton) compare(control.pressed, false) - verify(control.spy.success) + verify(sequenceSpy.success) // right button - control.spy.expectedSequence = [] + sequenceSpy.expectedSequence = [] mousePress(control, control.width / 2, control.height / 2, Qt.RightButton) compare(control.pressed, false) mouseRelease(control, control.width / 2, control.height / 2, Qt.RightButton) compare(control.pressed, false) - verify(control.spy.success) + verify(sequenceSpy.success) // double click - control.spy.expectedSequence = [["pressedChanged", { "pressed": true }], + sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": true }], ["downChanged", { "down": true }], "pressed", ["pressedChanged", { "pressed": false }], @@ -145,7 +147,7 @@ TestCase { "released", "clicked"] mouseDoubleClickSequence(control, control.width / 2, control.height / 2, Qt.LeftButton) - verify(control.spy.success) + verify(sequenceSpy.success) control.destroy() } @@ -157,8 +159,10 @@ TestCase { control.forceActiveFocus() verify(control.activeFocus) + var sequenceSpy = signalSequenceSpy.createObject(control, {target: control}) + // click - control.spy.expectedSequence = [["pressedChanged", { "pressed": true }], + sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": true }], ["downChanged", { "down": true }], "pressed", ["pressedChanged", { "pressed": false }], @@ -166,15 +170,15 @@ TestCase { "released", "clicked"] keyClick(Qt.Key_Space) - verify(control.spy.success) + verify(sequenceSpy.success) // no change - control.spy.expectedSequence = [] + sequenceSpy.expectedSequence = [] var keys = [Qt.Key_Enter, Qt.Key_Return, Qt.Key_Escape, Qt.Key_Tab] for (var i = 0; i < keys.length; ++i) { - control.spy.reset() + sequenceSpy.reset() keyClick(keys[i]) - verify(control.spy.success) + verify(sequenceSpy.success) } control.destroy() @@ -197,54 +201,75 @@ TestCase { var clickSpy = signalSpy.createObject(control, {target: control, signalName: "clicked"}) verify(clickSpy.valid) + var pressSpy = signalSpy.createObject(control, {target: control, signalName: "pressed"}) + verify(pressSpy.valid) + var releaseSpy = signalSpy.createObject(control, {target: control, signalName: "released"}) + verify(releaseSpy.valid) - var repeatCount = 2 - var repeatSequence = [["pressedChanged", { "pressed": true }], - ["downChanged", { "down": true }], - "pressed", - "released", - "clicked", - "pressed", - "released", - "clicked", - "pressed"] - - // auto-repeat a couple of mouse clicks - control.spy.expectedSequence = repeatSequence + // auto-repeat mouse click mousePress(control) compare(control.pressed, true) - tryVerify(function() { return clickSpy.count >= repeatCount }) - if (clickSpy.count > repeatCount) - warn("Expected auto-repeat count " + repeatCount + " exceeded (" + clickSpy.count + ") - busy CI?") - else - verify(control.spy.success) - - control.spy.expectedSequence = [["pressedChanged", { "pressed": false }], - ["downChanged", { "down": false }], - "released", - "clicked"] + clickSpy.wait() + clickSpy.wait() + compare(pressSpy.count, clickSpy.count + 1) + compare(releaseSpy.count, clickSpy.count) mouseRelease(control) compare(control.pressed, false) - verify(control.spy.success) + compare(clickSpy.count, pressSpy.count) + compare(releaseSpy.count, pressSpy.count) - // auto-repeat a couple of key clicks clickSpy.clear() - control.spy.expectedSequence = repeatSequence + pressSpy.clear() + releaseSpy.clear() + + // auto-repeat key click keyPress(Qt.Key_Space) compare(control.pressed, true) - tryVerify(function() { return clickSpy.count >= repeatCount }) - if (clickSpy.count > repeatCount) - warn("Expected auto-repeat count " + repeatCount + " exceeded (" + clickSpy.count + ") - busy CI?") - else - verify(control.spy.success) - - control.spy.expectedSequence = [["pressedChanged", { "pressed": false }], - ["downChanged", { "down": false }], - "released", - "clicked"] + clickSpy.wait() + clickSpy.wait() + compare(pressSpy.count, clickSpy.count + 1) + compare(releaseSpy.count, clickSpy.count) keyRelease(Qt.Key_Space) compare(control.pressed, false) - verify(control.spy.success) + compare(clickSpy.count, pressSpy.count) + compare(releaseSpy.count, pressSpy.count) + + clickSpy.clear() + pressSpy.clear() + releaseSpy.clear() + + mousePress(control) + compare(control.pressed, true) + clickSpy.wait() + compare(pressSpy.count, clickSpy.count + 1) + compare(releaseSpy.count, clickSpy.count) + + // move inside during repeat -> continue repeat + mouseMove(control, control.width / 4, control.height / 4) + clickSpy.wait() + compare(pressSpy.count, clickSpy.count + 1) + compare(releaseSpy.count, clickSpy.count) + + clickSpy.clear() + pressSpy.clear() + releaseSpy.clear() + + // move outside during repeat -> stop repeat + mouseMove(control, -1, -1) + // NOTE: The following wait() is NOT a reliable way to test that the + // auto-repeat timer is not running, but there's no way dig into the + // private APIs from QML. If this test ever fails in the future, it + // indicates that the auto-repeat timer logic is broken. + wait(125) + compare(clickSpy.count, 0) + compare(pressSpy.count, 0) + compare(releaseSpy.count, 0) + + mouseRelease(control, -1, -1) + compare(control.pressed, false) + compare(clickSpy.count, 0) + compare(pressSpy.count, 0) + compare(releaseSpy.count, 0) control.destroy() } @@ -262,7 +287,9 @@ TestCase { verify(control.hasOwnProperty("checkable")) verify(!control.checkable) - control.spy.expectedSequence = [["pressedChanged", { "pressed": true }], + var sequenceSpy = signalSequenceSpy.createObject(control, {target: control}) + + sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": true }], ["downChanged", { "down": true }], "pressed", ["pressedChanged", { "pressed": false }], @@ -271,9 +298,9 @@ TestCase { "clicked"] mouseClick(control) verify(!control.checked) - verify(control.spy.success) + verify(sequenceSpy.success) - control.spy.expectedSequence = [["pressedChanged", { "pressed": true }], + sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": true }], ["downChanged", { "down": true }], "pressed", ["pressedChanged", { "pressed": false }], @@ -284,9 +311,9 @@ TestCase { control.checkable = true mouseClick(control) verify(control.checked) - verify(control.spy.success) + verify(sequenceSpy.success) - control.spy.expectedSequence = [["pressedChanged", { "pressed": true }], + sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": true }], ["downChanged", { "down": true }], "pressed", ["pressedChanged", { "pressed": false }], @@ -296,7 +323,7 @@ TestCase { "clicked"] mouseClick(control) verify(!control.checked) - verify(control.spy.success) + verify(sequenceSpy.success) control.destroy() } diff --git a/tests/auto/controls/data/tst_checkbox.qml b/tests/auto/controls/data/tst_checkbox.qml index d1b590e4..b88e6deb 100644 --- a/tests/auto/controls/data/tst_checkbox.qml +++ b/tests/auto/controls/data/tst_checkbox.qml @@ -52,13 +52,13 @@ TestCase { Component { id: checkBox - CheckBox { - id: control + CheckBox { } + } - property SignalSequenceSpy spy: SignalSequenceSpy { - target: control - signals: ["pressed", "released", "canceled", "clicked", "pressedChanged", "checkedChanged", "checkStateChanged"] - } + Component { + id: signalSequenceSpy + SignalSequenceSpy { + signals: ["pressed", "released", "canceled", "clicked", "pressedChanged", "checkedChanged", "checkStateChanged"] } } @@ -79,24 +79,26 @@ TestCase { var control = checkBox.createObject(testCase) verify(control) - control.spy.expectedSequence = [] + var sequenceSpy = signalSequenceSpy.createObject(control, {target: control}) + + sequenceSpy.expectedSequence = [] compare(control.checked, false) compare(control.checkState, Qt.Unchecked) - verify(control.spy.success) + verify(sequenceSpy.success) - control.spy.expectedSequence = [["checkStateChanged", { "checked": true, "checkState": Qt.Checked }], + sequenceSpy.expectedSequence = [["checkStateChanged", { "checked": true, "checkState": Qt.Checked }], ["checkedChanged", { "checked": true, "checkState": Qt.Checked }]] control.checked = true compare(control.checked, true) compare(control.checkState, Qt.Checked) - verify(control.spy.success) + verify(sequenceSpy.success) - control.spy.expectedSequence = [["checkStateChanged", { "checked": false, "checkState": Qt.Unchecked }], + sequenceSpy.expectedSequence = [["checkStateChanged", { "checked": false, "checkState": Qt.Unchecked }], ["checkedChanged", { "checked": false, "checkState": Qt.Unchecked }]] control.checked = false compare(control.checked, false) compare(control.checkState, Qt.Unchecked) - verify(control.spy.success) + verify(sequenceSpy.success) control.destroy() } @@ -105,24 +107,26 @@ TestCase { var control = checkBox.createObject(testCase) verify(control) - control.spy.expectedSequence = [] + var sequenceSpy = signalSequenceSpy.createObject(control, {target: control}) + + sequenceSpy.expectedSequence = [] compare(control.checked, false) compare(control.checkState, Qt.Unchecked) - verify(control.spy.success) + verify(sequenceSpy.success) - control.spy.expectedSequence = [["checkStateChanged", { "checked": true, "checkState": Qt.Checked }], + sequenceSpy.expectedSequence = [["checkStateChanged", { "checked": true, "checkState": Qt.Checked }], ["checkedChanged", { "checked": true, "checkState": Qt.Checked }]] control.checkState = Qt.Checked compare(control.checked, true) compare(control.checkState, Qt.Checked) - verify(control.spy.success) + verify(sequenceSpy.success) - control.spy.expectedSequence = [["checkStateChanged", { "checked": false, "checkState": Qt.Unchecked }], + sequenceSpy.expectedSequence = [["checkStateChanged", { "checked": false, "checkState": Qt.Unchecked }], ["checkedChanged", { "checked": false, "checkState": Qt.Unchecked }]] control.checkState = Qt.Unchecked compare(control.checked, false) compare(control.checkState, Qt.Unchecked) - verify(control.spy.success) + verify(sequenceSpy.success) control.destroy() } @@ -131,14 +135,16 @@ TestCase { var control = checkBox.createObject(testCase) verify(control) + var sequenceSpy = signalSequenceSpy.createObject(control, {target: control}) + // check - control.spy.expectedSequence = [["pressedChanged", { "pressed": true, "checked": false, "checkState": Qt.Unchecked }], + sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": true, "checked": false, "checkState": Qt.Unchecked }], "pressed"] mousePress(control, control.width / 2, control.height / 2, Qt.LeftButton) compare(control.pressed, true) - verify(control.spy.success) + verify(sequenceSpy.success) - control.spy.expectedSequence = [["pressedChanged", { "pressed": false, "checked": false, "checkState": Qt.Unchecked }], + sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": false, "checked": false, "checkState": Qt.Unchecked }], ["checkStateChanged", { "pressed": false, "checked": true, "checkState": Qt.Checked }], ["checkedChanged", { "pressed": false, "checked": true, "checkState": Qt.Checked }], "released", @@ -147,15 +153,15 @@ TestCase { compare(control.checked, true) compare(control.checkState, Qt.Checked) compare(control.pressed, false) - verify(control.spy.success) + verify(sequenceSpy.success) // uncheck - control.spy.expectedSequence = [["pressedChanged", { "pressed": true, "checked": true, "checkState": Qt.Checked }], + sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": true, "checked": true, "checkState": Qt.Checked }], "pressed"] mousePress(control, control.width / 2, control.height / 2, Qt.LeftButton) compare(control.pressed, true) - verify(control.spy.success) - control.spy.expectedSequence = [["pressedChanged", { "pressed": false, "checked": true, "checkState": Qt.Checked }], + verify(sequenceSpy.success) + sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": false, "checked": true, "checkState": Qt.Checked }], ["checkStateChanged", { "pressed": false, "checked": false, "checkState": Qt.Unchecked }], ["checkedChanged", { "pressed": false, "checked": false, "checkState": Qt.Unchecked }], "released", @@ -164,34 +170,34 @@ TestCase { compare(control.checked, false) compare(control.checkState, Qt.Unchecked) compare(control.pressed, false) - verify(control.spy.success) + verify(sequenceSpy.success) // release outside - control.spy.expectedSequence = [["pressedChanged", { "pressed": true, "checked": false, "checkState": Qt.Unchecked }], + sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": true, "checked": false, "checkState": Qt.Unchecked }], "pressed"] mousePress(control, control.width / 2, control.height / 2, Qt.LeftButton) compare(control.pressed, true) - verify(control.spy.success) - control.spy.expectedSequence = [["pressedChanged", { "pressed": false, "checked": false, "checkState": Qt.Unchecked }]] + verify(sequenceSpy.success) + sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": false, "checked": false, "checkState": Qt.Unchecked }]] mouseMove(control, control.width * 2, control.height * 2, 0, Qt.LeftButton) compare(control.pressed, false) - verify(control.spy.success) - control.spy.expectedSequence = [["canceled", { "pressed": false, "checked": false, "checkState": Qt.Unchecked }]] + verify(sequenceSpy.success) + sequenceSpy.expectedSequence = [["canceled", { "pressed": false, "checked": false, "checkState": Qt.Unchecked }]] mouseRelease(control, control.width * 2, control.height * 2, Qt.LeftButton) compare(control.checked, false) compare(control.checkState, Qt.Unchecked) compare(control.pressed, false) - verify(control.spy.success) + verify(sequenceSpy.success) // right button - control.spy.expectedSequence = [] + sequenceSpy.expectedSequence = [] mousePress(control, control.width / 2, control.height / 2, Qt.RightButton) compare(control.pressed, false) mouseRelease(control, control.width / 2, control.height / 2, Qt.RightButton) compare(control.checked, false) compare(control.checkState, Qt.Unchecked) compare(control.pressed, false) - verify(control.spy.success) + verify(sequenceSpy.success) control.destroy() } @@ -200,13 +206,15 @@ TestCase { var control = checkBox.createObject(testCase) verify(control) - control.spy.expectedSequence = [] + var sequenceSpy = signalSequenceSpy.createObject(control, {target: control}) + + sequenceSpy.expectedSequence = [] control.forceActiveFocus() verify(control.activeFocus) - verify(control.spy.success) + verify(sequenceSpy.success) // check - control.spy.expectedSequence = [["pressedChanged", { "pressed": true, "checked": false, "checkState": Qt.Unchecked }], + sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": true, "checked": false, "checkState": Qt.Unchecked }], "pressed", ["pressedChanged", { "pressed": false, "checked": false, "checkState": Qt.Unchecked }], ["checkStateChanged", { "pressed": false, "checked": true, "checkState": Qt.Checked }], @@ -216,10 +224,10 @@ TestCase { keyClick(Qt.Key_Space) compare(control.checked, true) compare(control.checkState, Qt.Checked) - verify(control.spy.success) + verify(sequenceSpy.success) // uncheck - control.spy.expectedSequence = [["pressedChanged", { "pressed": true, "checked": true, "checkState": Qt.Checked }], + sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": true, "checked": true, "checkState": Qt.Checked }], "pressed", ["pressedChanged", { "pressed": false, "checked": true, "checkState": Qt.Checked }], ["checkStateChanged", { "pressed": false, "checked": false, "checkState": Qt.Unchecked }], @@ -229,16 +237,16 @@ TestCase { keyClick(Qt.Key_Space) compare(control.checked, false) compare(control.checkState, Qt.Unchecked) - verify(control.spy.success) + verify(sequenceSpy.success) // no change - control.spy.expectedSequence = [] + sequenceSpy.expectedSequence = [] var keys = [Qt.Key_Enter, Qt.Key_Return, Qt.Key_Escape, Qt.Key_Tab] for (var i = 0; i < keys.length; ++i) { - control.spy.reset() + sequenceSpy.reset() keyClick(keys[i]) compare(control.checked, false) - verify(control.spy.success) + verify(sequenceSpy.success) } control.destroy() @@ -323,7 +331,9 @@ TestCase { function test_tristate() { var control = checkBox.createObject(testCase) - control.spy.expectedSequence = [] + var sequenceSpy = signalSequenceSpy.createObject(control, {target: control}) + + sequenceSpy.expectedSequence = [] control.forceActiveFocus() verify(control.activeFocus) @@ -331,16 +341,16 @@ TestCase { compare(control.checked, false) compare(control.checkState, Qt.Unchecked) - control.spy.expectedSequence = [["checkStateChanged", { "pressed": false, "checked": true, "checkState": Qt.PartiallyChecked }], + sequenceSpy.expectedSequence = [["checkStateChanged", { "pressed": false, "checked": true, "checkState": Qt.PartiallyChecked }], ["checkedChanged", { "pressed": false, "checked": true, "checkState": Qt.PartiallyChecked }]] control.checkState = Qt.PartiallyChecked compare(control.tristate, true) compare(control.checked, true) compare(control.checkState, Qt.PartiallyChecked) - verify(control.spy.success) + verify(sequenceSpy.success) // key: partial -> checked - control.spy.expectedSequence = [["pressedChanged", { "pressed": true, "checked": true, "checkState": Qt.PartiallyChecked }], + sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": true, "checked": true, "checkState": Qt.PartiallyChecked }], "pressed", ["pressedChanged", { "pressed": false, "checked": true, "checkState": Qt.PartiallyChecked }], ["checkStateChanged", { "pressed": false, "checked": true, "checkState": Qt.Checked }], @@ -349,10 +359,10 @@ TestCase { keyClick(Qt.Key_Space) compare(control.checked, true) compare(control.checkState, Qt.Checked) - verify(control.spy.success) + verify(sequenceSpy.success) // key: checked -> unchecked - control.spy.expectedSequence = [["pressedChanged", { "pressed": true, "checked": true, "checkState": Qt.Checked }], + sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": true, "checked": true, "checkState": Qt.Checked }], "pressed", ["pressedChanged", { "pressed": false, "checked": true, "checkState": Qt.Checked }], ["checkStateChanged", { "pressed": false, "checked": false, "checkState": Qt.Unchecked }], @@ -362,10 +372,10 @@ TestCase { keyClick(Qt.Key_Space) compare(control.checked, false) compare(control.checkState, Qt.Unchecked) - verify(control.spy.success) + verify(sequenceSpy.success) // key: unchecked -> partial - control.spy.expectedSequence = [["pressedChanged", { "pressed": true, "checked": false, "checkState": Qt.Unchecked }], + sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": true, "checked": false, "checkState": Qt.Unchecked }], "pressed", ["pressedChanged", { "pressed": false, "checked": false, "checkState": Qt.Unchecked }], ["checkStateChanged", { "pressed": false, "checked": true, "checkState": Qt.PartiallyChecked }], @@ -375,10 +385,10 @@ TestCase { keyClick(Qt.Key_Space) compare(control.checked, true) compare(control.checkState, Qt.PartiallyChecked) - verify(control.spy.success) + verify(sequenceSpy.success) // mouse: partial -> checked - control.spy.expectedSequence = [["pressedChanged", { "pressed": true, "checked": true, "checkState": Qt.PartiallyChecked }], + sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": true, "checked": true, "checkState": Qt.PartiallyChecked }], "pressed", ["pressedChanged", { "pressed": false, "checked": true, "checkState": Qt.PartiallyChecked }], ["checkStateChanged", { "pressed": false, "checked": true, "checkState": Qt.Checked }], @@ -387,10 +397,10 @@ TestCase { mouseClick(control) compare(control.checked, true) compare(control.checkState, Qt.Checked) - verify(control.spy.success) + verify(sequenceSpy.success) // mouse: checked -> unchecked - control.spy.expectedSequence = [["pressedChanged", { "pressed": true, "checked": true, "checkState": Qt.Checked }], + sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": true, "checked": true, "checkState": Qt.Checked }], "pressed", ["pressedChanged", { "pressed": false, "checked": true, "checkState": Qt.Checked }], ["checkStateChanged", { "pressed": false, "checked": false, "checkState": Qt.Unchecked }], @@ -400,10 +410,10 @@ TestCase { mouseClick(control) compare(control.checked, false) compare(control.checkState, Qt.Unchecked) - verify(control.spy.success) + verify(sequenceSpy.success) // mouse: unchecked -> partial - control.spy.expectedSequence = [["pressedChanged", { "pressed": true, "checked": false, "checkState": Qt.Unchecked }], + sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": true, "checked": false, "checkState": Qt.Unchecked }], "pressed", ["pressedChanged", { "pressed": false, "checked": false, "checkState": Qt.Unchecked }], ["checkStateChanged", { "pressed": false, "checked": true, "checkState": Qt.PartiallyChecked }], @@ -413,7 +423,7 @@ TestCase { mouseClick(control) compare(control.checked, true) compare(control.checkState, Qt.PartiallyChecked) - verify(control.spy.success) + verify(sequenceSpy.success) control.destroy() } diff --git a/tests/auto/controls/data/tst_radiobutton.qml b/tests/auto/controls/data/tst_radiobutton.qml index 94e3a2cb..9b6a2ae5 100644 --- a/tests/auto/controls/data/tst_radiobutton.qml +++ b/tests/auto/controls/data/tst_radiobutton.qml @@ -52,13 +52,13 @@ TestCase { Component { id: radioButton - RadioButton { - id: control + RadioButton { } + } - property SignalSequenceSpy spy: SignalSequenceSpy { - target: control - signals: ["pressed", "released", "canceled", "clicked", "pressedChanged", "checkedChanged"] - } + Component { + id: signalSequenceSpy + SignalSequenceSpy { + signals: ["pressed", "released", "canceled", "clicked", "pressedChanged", "checkedChanged"] } } @@ -79,19 +79,21 @@ TestCase { var control = radioButton.createObject(testCase) verify(control) - control.spy.expectedSequence = [] // No change expected + var sequenceSpy = signalSequenceSpy.createObject(control, {target: control}) + + sequenceSpy.expectedSequence = [] // No change expected compare(control.checked, false) - verify(control.spy.success) + verify(sequenceSpy.success) - control.spy.expectedSequence = ["checkedChanged"] + sequenceSpy.expectedSequence = ["checkedChanged"] control.checked = true compare(control.checked, true) - verify(control.spy.success) + verify(sequenceSpy.success) - control.spy.reset() + sequenceSpy.reset() control.checked = false compare(control.checked, false) - verify(control.spy.success) + verify(sequenceSpy.success) control.destroy() } @@ -100,59 +102,61 @@ TestCase { var control = radioButton.createObject(testCase) verify(control) + var sequenceSpy = signalSequenceSpy.createObject(control, {target: control}) + // check - control.spy.expectedSequence = [["pressedChanged", { "pressed": true, "checked": false }], + sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": true, "checked": false }], "pressed"] mousePress(control, control.width / 2, control.height / 2, Qt.LeftButton) compare(control.pressed, true) - verify(control.spy.success) - control.spy.expectedSequence = [["pressedChanged", { "pressed": false, "checked": false }], + verify(sequenceSpy.success) + sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": false, "checked": false }], ["checkedChanged", { "pressed": false, "checked": true }], "released", "clicked"] mouseRelease(control, control.width / 2, control.height / 2, Qt.LeftButton) compare(control.checked, true) compare(control.pressed, false) - verify(control.spy.success) + verify(sequenceSpy.success) // attempt uncheck - control.spy.expectedSequence = [["pressedChanged", { "pressed": true, "checked": true }], + sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": true, "checked": true }], "pressed"] mousePress(control, control.width / 2, control.height / 2, Qt.LeftButton) compare(control.pressed, true) - verify(control.spy.success) - control.spy.expectedSequence = [["pressedChanged", { "pressed": false, "checked": true }], + verify(sequenceSpy.success) + sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": false, "checked": true }], "released", "clicked"] mouseRelease(control, control.width / 2, control.height / 2, Qt.LeftButton) compare(control.checked, true) compare(control.pressed, false) - verify(control.spy.success) + verify(sequenceSpy.success) // release outside - control.spy.expectedSequence = [["pressedChanged", { "pressed": true, "checked": true }], + sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": true, "checked": true }], "pressed"] mousePress(control, control.width / 2, control.height / 2, Qt.LeftButton) compare(control.pressed, true) - verify(control.spy.success) - control.spy.expectedSequence = [["pressedChanged", { "pressed": false, "checked": true }]] + verify(sequenceSpy.success) + sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": false, "checked": true }]] mouseMove(control, control.width * 2, control.height * 2, 0, Qt.LeftButton) compare(control.pressed, false) - control.spy.expectedSequence = [["canceled", { "pressed": false, "checked": true }]] + sequenceSpy.expectedSequence = [["canceled", { "pressed": false, "checked": true }]] mouseRelease(control, control.width * 2, control.height * 2, Qt.LeftButton) compare(control.checked, true) compare(control.pressed, false) - verify(control.spy.success) + verify(sequenceSpy.success) // right button - control.spy.expectedSequence = [] + sequenceSpy.expectedSequence = [] mousePress(control, control.width / 2, control.height / 2, Qt.RightButton) compare(control.pressed, false) - verify(control.spy.success) + verify(sequenceSpy.success) mouseRelease(control, control.width / 2, control.height / 2, Qt.RightButton) compare(control.checked, true) compare(control.pressed, false) - verify(control.spy.success) + verify(sequenceSpy.success) control.destroy() } @@ -161,13 +165,15 @@ TestCase { var control = radioButton.createObject(testCase) verify(control) - control.spy.expectedSequence = [] + var sequenceSpy = signalSequenceSpy.createObject(control, {target: control}) + + sequenceSpy.expectedSequence = [] control.forceActiveFocus() verify(control.activeFocus) - verify(control.spy.success) + verify(sequenceSpy.success) // check - control.spy.expectedSequence = [["pressedChanged", { "pressed": true, "checked": false }], + sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": true, "checked": false }], "pressed", ["pressedChanged", { "pressed": false, "checked": false }], ["checkedChanged", { "pressed": false, "checked": true }], @@ -175,26 +181,26 @@ TestCase { "clicked"] keyClick(Qt.Key_Space) compare(control.checked, true) - verify(control.spy.success) + verify(sequenceSpy.success) // attempt uncheck - control.spy.expectedSequence = [["pressedChanged", { "pressed": true, "checked": true }], + sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": true, "checked": true }], "pressed", ["pressedChanged", { "pressed": false, "checked": true }], "released", "clicked"] keyClick(Qt.Key_Space) compare(control.checked, true) - verify(control.spy.success) + verify(sequenceSpy.success) // no change - control.spy.expectedSequence = [] + sequenceSpy.expectedSequence = [] var keys = [Qt.Key_Enter, Qt.Key_Return, Qt.Key_Escape, Qt.Key_Tab] for (var i = 0; i < keys.length; ++i) { - control.spy.reset() + sequenceSpy.reset() keyClick(keys[i]) compare(control.checked, true) - verify(control.spy.success) + verify(sequenceSpy.success) } control.destroy() diff --git a/tests/auto/controls/data/tst_spinbox.qml b/tests/auto/controls/data/tst_spinbox.qml index 30db246f..de44415d 100644 --- a/tests/auto/controls/data/tst_spinbox.qml +++ b/tests/auto/controls/data/tst_spinbox.qml @@ -520,4 +520,66 @@ TestCase { control.destroy() } + + function test_autoRepeat() { + var control = spinBox.createObject(testCase) + verify(control) + + compare(control.value, 0) + + var valueSpy = signalSpy.createObject(control, {target: control, signalName: "valueChanged"}) + verify(valueSpy.valid) + + var countBefore = 0 + + // repeat up + mousePress(control.up.indicator) + verify(control.up.pressed) + compare(valueSpy.count, 0) + valueSpy.wait() + valueSpy.wait() + countBefore = valueSpy.count + mouseRelease(control.up.indicator) + verify(!control.up.pressed) + compare(valueSpy.count, countBefore) + + valueSpy.clear() + + // repeat down + mousePress(control.down.indicator) + verify(control.down.pressed) + compare(valueSpy.count, 0) + valueSpy.wait() + valueSpy.wait() + countBefore = valueSpy.count + mouseRelease(control.down.indicator) + verify(!control.down.pressed) + compare(valueSpy.count, countBefore) + + mousePress(control.up.indicator) + verify(control.up.pressed) + valueSpy.wait() + + // move inside during repeat -> continue repeat (QTBUG-57085) + mouseMove(control.up.indicator, control.up.indicator.width / 4, control.up.indicator.height / 4) + verify(control.up.pressed) + valueSpy.wait() + + valueSpy.clear() + + // move outside during repeat -> stop repeat + mouseMove(control.up.indicator, -1, -1) + verify(!control.up.pressed) + // NOTE: The following wait() is NOT a reliable way to test that the + // auto-repeat timer is not running, but there's no way dig into the + // private APIs from QML. If this test ever fails in the future, it + // indicates that the auto-repeat timer logic is broken. + wait(125) + compare(valueSpy.count, 0) + + mouseRelease(control.up.indicator, -1, -1) + verify(!control.up.pressed) + + control.destroy() + } } |