diff options
90 files changed, 2274 insertions, 718 deletions
@@ -14,6 +14,7 @@ /tests/auto/controls/tst_controls /tests/auto/material/tst_material /tests/auto/menu/tst_menu +/tests/auto/popup/tst_popup /tests/auto/pressandhold/tst_pressandhold /tests/auto/sanity/tst_sanity /tests/auto/snippets/tst_snippets @@ -1,2 +1,41 @@ -qtquickcontrols2 +Qt Labs Controls ================ + +The Qt Labs Controls module is a technology preview of the next generation +user interface controls based on Qt Quick. In comparison to the desktop- +oriented Qt Quick Controls 1, the experimental Qt Labs Controls are an order +of magnitude simpler, lighter and faster, and are primarily targeting embedded +and mobile platforms. + +More information can be found in the following blog posts: + +- http://blog.qt.io/blog/2015/03/31/qt-quick-controls-for-embedded/ +- http://blog.qt.io/blog/2015/11/23/qt-quick-controls-re-engineered-status-update/ + +## Help + +If you have problems or questions, don't hesitate to: + +- ask on the Qt Interest mailing list interest@qt-project.org +- ask on the Qt Forum http://forum.qt.io/category/12/qt-quick +- report issues to the Qt Bug Tracker https://bugreports.qt.io (component Qt Quick: Controls 2) + +## Installation + +The MINIMUM REQUIREMENT for building this project is to use the same branch +of Qt 5. The dependencies are qtbase, qtxmlpatterns and qtdeclarative. Other +optional dependencies are qtgraphicaleffects for the Material style and +qtquickcontrols for the Qt Quick Layouts. + +To install the controls into your Qt directory (QTDIR/qml): + + qmake + make + make install + +If you are compiling against a system Qt on linux, you might have to use +```sudo make install``` to install the project. + +## Usage + +Please refer to the "Getting Started with Qt Labs Controls" documentation. diff --git a/examples/controls/gallery/gallery.qml b/examples/controls/gallery/gallery.qml index d40e7f9b..f9a2665e 100644 --- a/examples/controls/gallery/gallery.qml +++ b/examples/controls/gallery/gallery.qml @@ -90,6 +90,7 @@ ApplicationWindow { Menu { id: optionsMenu x: parent.width - width + transformOrigin: Menu.TopRight MenuItem { text: "Settings" @@ -213,12 +214,11 @@ ApplicationWindow { height: settingsColumn.implicitHeight + topPadding + bottomPadding modal: true focus: true - onPressedOutside: close() + closePolicy: Popup.OnEscape | Popup.OnPressOutside contentItem: ColumnLayout { id: settingsColumn spacing: 20 - Keys.onEscapePressed: settingsPopup.close() // TODO: Popup::closePolicy Label { text: "Settings" @@ -247,6 +247,7 @@ ApplicationWindow { Label { text: "Restart required" + color: "#e41e25" opacity: styleBox.currentIndex !== styleBox.styleIndex ? 1.0 : 0.0 horizontalAlignment: Label.AlignHCenter verticalAlignment: Label.AlignVCenter @@ -290,12 +291,11 @@ ApplicationWindow { y: window.height / 6 width: Math.min(window.width, window.height) / 3 * 2 contentHeight: aboutColumn.height - onPressedOutside: close() + closePolicy: Popup.OnEscape | Popup.OnPressOutside Column { id: aboutColumn spacing: 20 - Keys.onEscapePressed: aboutDialog.close() // TODO: Popup::closePolicy Label { text: "About" diff --git a/src/controls/qquickstyle.cpp b/src/controls/qquickstyle.cpp index 576506fb..320148c3 100644 --- a/src/controls/qquickstyle.cpp +++ b/src/controls/qquickstyle.cpp @@ -40,7 +40,7 @@ #include <QtCore/qsettings.h> #include <QtCore/qfileselector.h> #include <QtQuick/private/qquickitem_p.h> -#include <QtLabsTemplates/private/qquickpopup_p_p.h> +#include <QtLabsTemplates/private/qquickpopup_p.h> QT_BEGIN_NAMESPACE @@ -119,7 +119,7 @@ static QList<QQuickStyle *> findChildStyles(const QMetaObject *type, QObject *ob } } } else if (QQuickPopup *popup = qobject_cast<QQuickPopup *>(object)) { - item = QQuickPopupPrivate::get(popup)->popupItem; + item = popup->popupItem(); QQuickStyle *style = attachedStyle(type, popup); if (style) diff --git a/src/imports/controls/ComboBox.qml b/src/imports/controls/ComboBox.qml index 33568699..fc32c6f5 100644 --- a/src/imports/controls/ComboBox.qml +++ b/src/imports/controls/ComboBox.qml @@ -56,7 +56,7 @@ T.ComboBox { //! [delegate] delegate: ItemDelegate { width: control.width - text: control.textRole ? model[control.textRole] : modelData + text: control.textRole ? (Array.isArray(control.model) ? modelData[control.textRole] : model[control.textRole]) : modelData checkable: true autoExclusive: true checked: control.currentIndex === index @@ -106,7 +106,7 @@ T.ComboBox { contentItem: ListView { id: listview clip: true - model: control.delegateModel + model: control.popup.visible ? control.delegateModel : null currentIndex: control.highlightedIndex Rectangle { diff --git a/src/imports/controls/Frame.qml b/src/imports/controls/Frame.qml index 18592b1c..3c9326e1 100644 --- a/src/imports/controls/Frame.qml +++ b/src/imports/controls/Frame.qml @@ -43,8 +43,8 @@ T.Frame { implicitWidth: Math.max(background ? background.implicitWidth : 0, contentWidth + leftPadding + rightPadding) implicitHeight: Math.max(background ? background.implicitHeight : 0, contentHeight + topPadding + bottomPadding) - contentWidth: contentChildren.length === 1 ? contentChildren[0].implicitWidth : 0 - contentHeight: contentChildren.length === 1 ? contentChildren[0].implicitHeight : 0 + contentWidth: contentItem.implicitWidth || (contentChildren.length === 1 ? contentChildren[0].implicitWidth : 0) + contentHeight: contentItem.implicitHeight || (contentChildren.length === 1 ? contentChildren[0].implicitHeight : 0) padding: 6 diff --git a/src/imports/controls/GroupBox.qml b/src/imports/controls/GroupBox.qml index 08866606..bc1801c2 100644 --- a/src/imports/controls/GroupBox.qml +++ b/src/imports/controls/GroupBox.qml @@ -45,8 +45,8 @@ T.GroupBox { contentWidth + leftPadding + rightPadding) implicitHeight: Math.max(background ? background.implicitHeight : 0, contentHeight + topPadding + bottomPadding) - contentWidth: contentChildren.length === 1 ? contentChildren[0].implicitWidth : 0 - contentHeight: contentChildren.length === 1 ? contentChildren[0].implicitHeight : 0 + contentWidth: contentItem.implicitWidth || (contentChildren.length === 1 ? contentChildren[0].implicitWidth : 0) + contentHeight: contentItem.implicitHeight || (contentChildren.length === 1 ? contentChildren[0].implicitHeight : 0) spacing: 6 padding: 6 diff --git a/src/imports/controls/Pane.qml b/src/imports/controls/Pane.qml index 7bd72493..fbbe0c38 100644 --- a/src/imports/controls/Pane.qml +++ b/src/imports/controls/Pane.qml @@ -43,8 +43,8 @@ T.Frame { implicitWidth: Math.max(background ? background.implicitWidth : 0, contentWidth + leftPadding + rightPadding) implicitHeight: Math.max(background ? background.implicitHeight : 0, contentHeight + topPadding + bottomPadding) - contentWidth: contentChildren.length === 1 ? contentChildren[0].implicitWidth : 0 - contentHeight: contentChildren.length === 1 ? contentChildren[0].implicitHeight : 0 + contentWidth: contentItem.implicitWidth || (contentChildren.length === 1 ? contentChildren[0].implicitWidth : 0) + contentHeight: contentItem.implicitHeight || (contentChildren.length === 1 ? contentChildren[0].implicitHeight : 0) padding: 6 diff --git a/src/imports/controls/Popup.qml b/src/imports/controls/Popup.qml index bc7c610c..60ea326a 100644 --- a/src/imports/controls/Popup.qml +++ b/src/imports/controls/Popup.qml @@ -43,8 +43,8 @@ T.Popup { implicitWidth: Math.max(background ? background.implicitWidth : 0, contentWidth + leftPadding + rightPadding) implicitHeight: Math.max(background ? background.implicitHeight : 0, contentHeight + topPadding + bottomPadding) - contentWidth: contentChildren.length === 1 ? contentChildren[0].implicitWidth : 0 - contentHeight: contentChildren.length === 1 ? contentChildren[0].implicitHeight : 0 + contentWidth: contentItem.implicitWidth || (contentChildren.length === 1 ? contentChildren[0].implicitWidth : 0) + contentHeight: contentItem.implicitHeight || (contentChildren.length === 1 ? contentChildren[0].implicitHeight : 0) padding: 6 diff --git a/src/imports/controls/SpinBox.qml b/src/imports/controls/SpinBox.qml index c84a2e3e..947ec74a 100644 --- a/src/imports/controls/SpinBox.qml +++ b/src/imports/controls/SpinBox.qml @@ -82,6 +82,7 @@ T.SpinBox { //! [up.indicator] up.indicator: Rectangle { x: control.mirrored ? 0 : parent.width - width + height: parent.height implicitWidth: 40 implicitHeight: 40 color: up.pressed ? "#e4e4e4" : "#f6f6f6" @@ -98,7 +99,7 @@ T.SpinBox { x: (parent.width - width) / 2 y: (parent.height - height) / 2 width: 2 - height: parent.height / 3 + height: parent.width / 3 color: control.enabled ? "#353637" : "#bdbebf" } } @@ -107,6 +108,7 @@ T.SpinBox { //! [down.indicator] down.indicator: Rectangle { x: control.mirrored ? parent.width - width : 0 + height: parent.height implicitWidth: 40 implicitHeight: 40 color: down.pressed ? "#e4e4e4" : "#f6f6f6" diff --git a/src/imports/controls/StackView.qml b/src/imports/controls/StackView.qml index 3aadd37a..f0869307 100644 --- a/src/imports/controls/StackView.qml +++ b/src/imports/controls/StackView.qml @@ -43,37 +43,37 @@ T.StackView { //! [popEnter] popEnter: Transition { - XAnimator { from: -root.width; to: 0; duration: 400; easing.type: Easing.OutCubic } + XAnimator { from: (root.mirrored ? -1 : 1) * -root.width; to: 0; duration: 400; easing.type: Easing.OutCubic } } //! [popEnter] //! [popExit] popExit: Transition { - XAnimator { from: 0; to: root.width; duration: 400; easing.type: Easing.OutCubic } + XAnimator { from: 0; to: (root.mirrored ? -1 : 1) * root.width; duration: 400; easing.type: Easing.OutCubic } } //! [popExit] //! [pushEnter] pushEnter: Transition { - XAnimator { from: root.width; to: 0; duration: 400; easing.type: Easing.OutCubic } + XAnimator { from: (root.mirrored ? -1 : 1) * root.width; to: 0; duration: 400; easing.type: Easing.OutCubic } } //! [pushEnter] //! [pushExit] pushExit: Transition { - XAnimator { from: 0; to: -root.width; duration: 400; easing.type: Easing.OutCubic } + XAnimator { from: 0; to: (root.mirrored ? -1 : 1) * -root.width; duration: 400; easing.type: Easing.OutCubic } } //! [pushExit] //! [replaceEnter] replaceEnter: Transition { - XAnimator { from: root.width; to: 0; duration: 400; easing.type: Easing.OutCubic } + XAnimator { from: (root.mirrored ? -1 : 1) * root.width; to: 0; duration: 400; easing.type: Easing.OutCubic } } //! [replaceEnter] //! [replaceExit] replaceExit: Transition { - XAnimator { from: 0; to: -root.width; duration: 400; easing.type: Easing.OutCubic } + XAnimator { from: 0; to: (root.mirrored ? -1 : 1) * -root.width; duration: 400; easing.type: Easing.OutCubic } } //! [replaceExit] } diff --git a/src/imports/controls/TabBar.qml b/src/imports/controls/TabBar.qml index 773382a3..b1a9009c 100644 --- a/src/imports/controls/TabBar.qml +++ b/src/imports/controls/TabBar.qml @@ -59,37 +59,13 @@ T.TabBar { orientation: ListView.Horizontal boundsBehavior: Flickable.StopAtBounds snapMode: ListView.SnapToItem - - highlightMoveDuration: 250 - highlightResizeDuration: 0 - highlightFollowsCurrentItem: true - highlight: Item { - z: 2 - Rectangle { - height: 4 - width: parent.width - y: parent.height - height - color: "#353637" - } - } } //! [contentItem] //! [background] background: Rectangle { - implicitWidth: 26 - implicitHeight: 26 - - border.color: "#ffffff" - border.width: 8 - color: control.count > 1 ? "#bdbebf" : "#ffffff" - - Rectangle { - y: parent.height - height - width: parent.width - height: 1 - color: "#bdbebf" - } + implicitWidth: 40 + implicitHeight: 40 } //! [background] } diff --git a/src/imports/controls/TabButton.qml b/src/imports/controls/TabButton.qml index 1fbb6050..ef11e405 100644 --- a/src/imports/controls/TabButton.qml +++ b/src/imports/controls/TabButton.qml @@ -60,7 +60,8 @@ T.TabButton { text: control.text font: control.font elide: Text.ElideRight - color: !control.enabled ? "#bdbebf" : control.pressed ? "#000000" : "#353637" + opacity: enabled ? 1 : 0.3 + color: !control.checked ? "#ffffff" : control.pressed ? "#26282a" : "#353637" horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter } @@ -68,9 +69,8 @@ T.TabButton { //! [background] background: Rectangle { - height: parent.height - 1 - implicitHeight: 26 - color: "#ffffff" + implicitHeight: 40 + color: control.pressed ? (control.checked ? "#e4e4e4" : "#585a5c") : (control.checked ? "transparent" : "#353637") } //! [background] } diff --git a/src/imports/controls/TextArea.qml b/src/imports/controls/TextArea.qml index 8df44d5b..46b6bc6c 100644 --- a/src/imports/controls/TextArea.qml +++ b/src/imports/controls/TextArea.qml @@ -50,9 +50,10 @@ T.TextArea { padding: 6 leftPadding: 10 - color: enabled ? "#26282a" : "#c2c2c2" -// selectionColor: TODO -// selectedTextColor: TODO + opacity: enabled ? 1 : 0.2 + color: "#353637" + selectionColor: "#fddd5c" + selectedTextColor: color Text { id: placeholder diff --git a/src/imports/controls/ToolBar.qml b/src/imports/controls/ToolBar.qml index fe5dbf3f..7e0f80a3 100644 --- a/src/imports/controls/ToolBar.qml +++ b/src/imports/controls/ToolBar.qml @@ -43,8 +43,8 @@ T.ToolBar { implicitWidth: Math.max(background ? background.implicitWidth : 0, contentWidth + leftPadding + rightPadding) implicitHeight: Math.max(background ? background.implicitHeight : 0, contentHeight + topPadding + bottomPadding) - contentWidth: contentChildren.length === 1 ? contentChildren[0].implicitWidth : 0 - contentHeight: contentChildren.length === 1 ? contentChildren[0].implicitHeight : 0 + contentWidth: contentItem.implicitWidth || (contentChildren.length === 1 ? contentChildren[0].implicitWidth : 0) + contentHeight: contentItem.implicitHeight || (contentChildren.length === 1 ? contentChildren[0].implicitHeight : 0) //! [contentItem] contentItem: Item { } diff --git a/src/imports/controls/designer/ButtonSection.qml b/src/imports/controls/designer/ButtonSection.qml new file mode 100644 index 00000000..2353bad2 --- /dev/null +++ b/src/imports/controls/designer/ButtonSection.qml @@ -0,0 +1,117 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Labs Controls module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.1 +import HelperWidgets 2.0 +import QtQuick.Layouts 1.0 + +Section { + id: section + + SectionLayout { + Label { + text: qsTr("Text") + tooltip: qsTr("The text displayed on the %1.").arg(section.caption.toLowerCase()) + } + SecondColumnLayout { + LineEdit { + backendValue: backendValues.text + Layout.fillWidth: true + } + } + + Label { + text: qsTr("Highlighted") + tooltip: qsTr("Whether the %1 is highlighted.").arg(section.caption.toLowerCase()) + } + SecondColumnLayout { + CheckBox { + text: backendValues.highlighted.valueToString + backendValue: backendValues.highlighted + Layout.fillWidth: true + } + } + + Label { + visible: checkable + text: qsTr("Checkable") + tooltip: qsTr("Whether the %1 is checkable.").arg(section.caption.toLowerCase()) + } + SecondColumnLayout { + CheckBox { + text: backendValues.checkable.valueToString + backendValue: backendValues.checkable + Layout.fillWidth: true + } + } + + Label { + text: qsTr("Checked") + tooltip: qsTr("Whether the %1 is checked.").arg(section.caption.toLowerCase()) + } + SecondColumnLayout { + CheckBox { + text: backendValues.checked.valueToString + backendValue: backendValues.checked + Layout.fillWidth: true + } + } + + Label { + text: qsTr("Exclusive") + tooltip: qsTr("Whether the %1 is exclusive.").arg(section.caption.toLowerCase()) + } + SecondColumnLayout { + CheckBox { + text: backendValues.autoExclusive.valueToString + backendValue: backendValues.autoExclusive + Layout.fillWidth: true + } + } + + Label { + text: qsTr("Repeat") + tooltip: qsTr("Whether the %1 repeats while pressed and held down.").arg(section.caption.toLowerCase()) + } + SecondColumnLayout { + CheckBox { + text: backendValues.autoRepeat.valueToString + backendValue: backendValues.autoRepeat + Layout.fillWidth: true + } + } + } +} diff --git a/src/imports/controls/designer/ButtonSpecifics.qml b/src/imports/controls/designer/ButtonSpecifics.qml index 2014abf0..92ccefa3 100644 --- a/src/imports/controls/designer/ButtonSpecifics.qml +++ b/src/imports/controls/designer/ButtonSpecifics.qml @@ -41,22 +41,9 @@ import QtQuick.Layouts 1.0 Column { width: parent.width - Section { - width: parent.width + ButtonSection { caption: qsTr("Button") - - SectionLayout { - Label { - text: qsTr("Text") - tooltip: qsTr("The text displayed on the button.") - } - SecondColumnLayout { - LineEdit { - backendValue: backendValues.text - Layout.fillWidth: true - } - } - } + width: parent.width } ControlSection { diff --git a/src/imports/controls/designer/CheckBoxSpecifics.qml b/src/imports/controls/designer/CheckBoxSpecifics.qml index 3082d1f1..e89ba1de 100644 --- a/src/imports/controls/designer/CheckBoxSpecifics.qml +++ b/src/imports/controls/designer/CheckBoxSpecifics.qml @@ -41,34 +41,9 @@ import QtQuick.Layouts 1.0 Column { width: parent.width - Section { - width: parent.width + ButtonSection { caption: qsTr("Check Box") - - SectionLayout { - Label { - text: qsTr("Text") - tooltip: qsTr("The text displayed on the check box.") - } - SecondColumnLayout { - LineEdit { - backendValue: backendValues.text - Layout.fillWidth: true - } - } - - Label { - text: qsTr("Checked") - tooltip: qsTr("The checked state of the check box.") - } - SecondColumnLayout { - CheckBox { - text: backendValues.checked.valueToString - backendValue: backendValues.checked - Layout.fillWidth: true - } - } - } + width: parent.width } ControlSection { diff --git a/src/imports/controls/designer/ComboBoxSpecifics.qml b/src/imports/controls/designer/ComboBoxSpecifics.qml new file mode 100644 index 00000000..60d76e77 --- /dev/null +++ b/src/imports/controls/designer/ComboBoxSpecifics.qml @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Labs Controls module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.1 +import HelperWidgets 2.0 +import QtQuick.Layouts 1.0 + +Column { + width: parent.width + + Section { + width: parent.width + caption: qsTr("Combo Box") + + SectionLayout { + Label { + text: qsTr("Text Role") + tooltip: qsTr("The model role used for displaying text.") + } + SecondColumnLayout { + LineEdit { + backendValue: backendValues.textRole + Layout.fillWidth: true + } + } + + Label { + text: qsTr("Current") + tooltip: qsTr("The index of the current item.") + } + SecondColumnLayout { + SpinBox { + maximumValue: 9999999 + minimumValue: -9999999 + decimals: 0 + backendValue: backendValues.currentIndex + Layout.fillWidth: true + } + } + } + } + + ControlSection { + width: parent.width + } + + PaddingSection { + width: parent.width + } +} diff --git a/src/imports/controls/designer/DialSpecifics.qml b/src/imports/controls/designer/DialSpecifics.qml new file mode 100644 index 00000000..98ceb6d3 --- /dev/null +++ b/src/imports/controls/designer/DialSpecifics.qml @@ -0,0 +1,114 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Labs Controls module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.1 +import HelperWidgets 2.0 +import QtQuick.Layouts 1.1 + +Column { + width: parent.width + + Section { + width: parent.width + caption: qsTr("Dial") + + SectionLayout { + Label { + text: qsTr("Value") + tooltip: qsTr("The current value of the dial.") + } + SecondColumnLayout { + SpinBox { + minimumValue: Math.min(backendValues.from.value, backendValues.to.value) + maximumValue: Math.max(backendValues.from.value, backendValues.to.value) + decimals: 2 + backendValue: backendValues.value + Layout.fillWidth: true + } + } + + Label { + text: qsTr("From") + tooltip: qsTr("The starting value of the dial range.") + } + SecondColumnLayout { + SpinBox { + maximumValue: 9999999 + minimumValue: -9999999 + decimals: 2 + backendValue: backendValues.from + Layout.fillWidth: true + } + } + + Label { + text: qsTr("To") + tooltip: qsTr("The ending value of the dial range.") + } + SecondColumnLayout { + SpinBox { + maximumValue: 9999999 + minimumValue: -9999999 + decimals: 2 + backendValue: backendValues.to + Layout.fillWidth: true + } + } + + Label { + text: qsTr("Step Size") + tooltip: qsTr("The step size of the dial.") + } + SecondColumnLayout { + SpinBox { + maximumValue: 9999999 + minimumValue: -9999999 + decimals: 2 + backendValue: backendValues.stepSize + Layout.fillWidth: true + } + } + } + } + + ControlSection { + width: parent.width + } + + PaddingSection { + width: parent.width + } +} diff --git a/src/imports/controls/designer/ItemDelegateSpecifics.qml b/src/imports/controls/designer/ItemDelegateSpecifics.qml new file mode 100644 index 00000000..29ee0a72 --- /dev/null +++ b/src/imports/controls/designer/ItemDelegateSpecifics.qml @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Labs Controls module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.1 +import HelperWidgets 2.0 +import QtQuick.Layouts 1.0 + +Column { + width: parent.width + + ButtonSection { + caption: qsTr("Item Delegate") + width: parent.width + } + + ControlSection { + width: parent.width + } + + PaddingSection { + width: parent.width + } +} diff --git a/src/imports/controls/designer/PageIndicatorSpecifics.qml b/src/imports/controls/designer/PageIndicatorSpecifics.qml index 0c2e4638..9ea06cd2 100644 --- a/src/imports/controls/designer/PageIndicatorSpecifics.qml +++ b/src/imports/controls/designer/PageIndicatorSpecifics.qml @@ -62,7 +62,7 @@ Column { Label { text: qsTr("Current") - tooltip: qsTr("The index of the current page") + tooltip: qsTr("The index of the current page.") } SecondColumnLayout { SpinBox { diff --git a/src/imports/controls/designer/PaneSpecifics.qml b/src/imports/controls/designer/PaneSpecifics.qml new file mode 100644 index 00000000..80e01cf2 --- /dev/null +++ b/src/imports/controls/designer/PaneSpecifics.qml @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Labs Controls module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.1 +import HelperWidgets 2.0 +import QtQuick.Layouts 1.0 + +Column { + width: parent.width + + ControlSection { + width: parent.width + } + + PaddingSection { + width: parent.width + } +} diff --git a/src/imports/controls/designer/RadioButtonSpecifics.qml b/src/imports/controls/designer/RadioButtonSpecifics.qml index 285b660a..f10c1170 100644 --- a/src/imports/controls/designer/RadioButtonSpecifics.qml +++ b/src/imports/controls/designer/RadioButtonSpecifics.qml @@ -41,34 +41,9 @@ import QtQuick.Layouts 1.0 Column { width: parent.width - Section { - width: parent.width + ButtonSection { caption: qsTr("Radio Button") - - SectionLayout { - Label { - text: qsTr("Text") - tooltip: qsTr("The text displayed on the radio button.") - } - SecondColumnLayout { - LineEdit { - backendValue: backendValues.text - Layout.fillWidth: true - } - } - - Label { - text: qsTr("Checked") - tooltip: qsTr("The checked state of the radio button.") - } - SecondColumnLayout { - CheckBox { - text: backendValues.checked.valueToString - backendValue: backendValues.checked - Layout.fillWidth: true - } - } - } + width: parent.width } ControlSection { diff --git a/src/imports/controls/designer/SliderSpecifics.qml b/src/imports/controls/designer/SliderSpecifics.qml index 535ae830..f323539e 100644 --- a/src/imports/controls/designer/SliderSpecifics.qml +++ b/src/imports/controls/designer/SliderSpecifics.qml @@ -89,7 +89,7 @@ Column { } Label { - text: qsTr("Step size") + text: qsTr("Step Size") tooltip: qsTr("The step size of the slider.") } SecondColumnLayout { diff --git a/src/imports/controls/designer/SpinBoxSpecifics.qml b/src/imports/controls/designer/SpinBoxSpecifics.qml new file mode 100644 index 00000000..d16f2464 --- /dev/null +++ b/src/imports/controls/designer/SpinBoxSpecifics.qml @@ -0,0 +1,114 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Labs Controls module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.1 +import HelperWidgets 2.0 +import QtQuick.Layouts 1.1 + +Column { + width: parent.width + + Section { + width: parent.width + caption: qsTr("Spin Box") + + SectionLayout { + Label { + text: qsTr("Value") + tooltip: qsTr("The current value of the spinbox.") + } + SecondColumnLayout { + SpinBox { + minimumValue: Math.min(backendValues.from.value, backendValues.to.value) + maximumValue: Math.max(backendValues.from.value, backendValues.to.value) + decimals: 2 + backendValue: backendValues.value + Layout.fillWidth: true + } + } + + Label { + text: qsTr("From") + tooltip: qsTr("The starting value of the spinbox range.") + } + SecondColumnLayout { + SpinBox { + maximumValue: 9999999 + minimumValue: -9999999 + decimals: 2 + backendValue: backendValues.from + Layout.fillWidth: true + } + } + + Label { + text: qsTr("To") + tooltip: qsTr("The ending value of the spinbox range.") + } + SecondColumnLayout { + SpinBox { + maximumValue: 9999999 + minimumValue: -9999999 + decimals: 2 + backendValue: backendValues.to + Layout.fillWidth: true + } + } + + Label { + text: qsTr("Step Size") + tooltip: qsTr("The step size of the spinbox.") + } + SecondColumnLayout { + SpinBox { + maximumValue: 9999999 + minimumValue: -9999999 + decimals: 2 + backendValue: backendValues.stepSize + Layout.fillWidth: true + } + } + } + } + + ControlSection { + width: parent.width + } + + PaddingSection { + width: parent.width + } +} diff --git a/src/imports/controls/designer/SwitchSpecifics.qml b/src/imports/controls/designer/SwitchSpecifics.qml index 63fdb4bf..e1626eb0 100644 --- a/src/imports/controls/designer/SwitchSpecifics.qml +++ b/src/imports/controls/designer/SwitchSpecifics.qml @@ -41,34 +41,9 @@ import QtQuick.Layouts 1.0 Column { width: parent.width - Section { - width: parent.width + ButtonSection { caption: qsTr("Switch") - - SectionLayout { - Label { - text: qsTr("Text") - tooltip: qsTr("The text displayed on the switch.") - } - SecondColumnLayout { - LineEdit { - backendValue: backendValues.text - Layout.fillWidth: true - } - } - - Label { - text: qsTr("Checked") - tooltip: qsTr("The checked state of the switch.") - } - SecondColumnLayout { - CheckBox { - text: backendValues.checked.valueToString - backendValue: backendValues.checked - Layout.fillWidth: true - } - } - } + width: parent.width } ControlSection { diff --git a/src/imports/controls/designer/ToolButtonSpecifics.qml b/src/imports/controls/designer/ToolButtonSpecifics.qml index fab18b5b..df0d831d 100644 --- a/src/imports/controls/designer/ToolButtonSpecifics.qml +++ b/src/imports/controls/designer/ToolButtonSpecifics.qml @@ -41,22 +41,9 @@ import QtQuick.Layouts 1.0 Column { width: parent.width - Section { - width: parent.width + ButtonSection { caption: qsTr("Tool Button") - - SectionLayout { - Label { - text: qsTr("Text") - tooltip: qsTr("The text displayed on the tool button.") - } - SecondColumnLayout { - LineEdit { - backendValue: backendValues.text - Layout.fillWidth: true - } - } - } + width: parent.width } ControlSection { diff --git a/src/imports/controls/designer/TumblerSpecifics.qml b/src/imports/controls/designer/TumblerSpecifics.qml new file mode 100644 index 00000000..6dcaf27e --- /dev/null +++ b/src/imports/controls/designer/TumblerSpecifics.qml @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Labs Controls module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.1 +import HelperWidgets 2.0 +import QtQuick.Layouts 1.0 + +Column { + width: parent.width + + Section { + width: parent.width + caption: qsTr("Tumbler") + + SectionLayout { + Label { + text: qsTr("Visible Count") + tooltip: qsTr("The count of visible items.") + } + SecondColumnLayout { + SpinBox { + maximumValue: 9999999 + minimumValue: -9999999 + decimals: 0 + backendValue: backendValues.visibleItemCount + Layout.fillWidth: true + } + } + + Label { + text: qsTr("Current") + tooltip: qsTr("The index of the current item.") + } + SecondColumnLayout { + SpinBox { + maximumValue: 9999999 + minimumValue: -9999999 + decimals: 0 + backendValue: backendValues.currentIndex + Layout.fillWidth: true + } + } + } + } + + ControlSection { + width: parent.width + } + + PaddingSection { + width: parent.width + } +} diff --git a/src/imports/controls/designer/designer.pri b/src/imports/controls/designer/designer.pri index 9b7847b1..601fc4b4 100644 --- a/src/imports/controls/designer/designer.pri +++ b/src/imports/controls/designer/designer.pri @@ -3,23 +3,30 @@ QML_FILES += \ QML_FILES += \ $$PWD/BusyIndicatorSpecifics.qml \ + $$PWD/ButtonSection.qml \ $$PWD/ButtonSpecifics.qml \ $$PWD/CheckBoxSpecifics.qml \ + $$PWD/ComboBoxSpecifics.qml \ $$PWD/ControlSection.qml \ $$PWD/ControlSpecifics.qml \ + $$PWD/DialSpecifics.qml \ $$PWD/FrameSpecifics.qml \ $$PWD/GroupBoxSpecifics.qml \ + $$PWD/ItemDelegateSpecifics.qml \ $$PWD/LabelSpecifics.qml \ $$PWD/PaddingSection.qml \ $$PWD/PageIndicatorSpecifics.qml \ + $$PWD/PaneSpecifics.qml \ $$PWD/ProgressBarSpecifics.qml \ $$PWD/RadioButtonSpecifics.qml \ $$PWD/SliderSpecifics.qml \ + $$PWD/SpinBoxSpecifics.qml \ $$PWD/SwitchSpecifics.qml \ $$PWD/TextAreaSpecifics.qml \ $$PWD/TextFieldSpecifics.qml \ $$PWD/ToolBarSpecifics.qml \ - $$PWD/ToolButtonSpecifics.qml + $$PWD/ToolButtonSpecifics.qml \ + $$PWD/TumblerSpecifics.qml QML_FILES += \ $$PWD/images/todo.png \ diff --git a/src/imports/controls/designer/qtlabscontrols.metainfo b/src/imports/controls/designer/qtlabscontrols.metainfo index 06564bf3..1c005c6f 100644 --- a/src/imports/controls/designer/qtlabscontrols.metainfo +++ b/src/imports/controls/designer/qtlabscontrols.metainfo @@ -43,6 +43,32 @@ MetaInfo { } Type { + name: "Qt.labs.controls.ComboBox" + icon: "images/todo16.png" + + ItemLibraryEntry { + name: "Combo Box" + category: "Qt Labs - Controls" + libraryIcon: "images/todo.png" + version: "1.0" + requiredImport: "Qt.labs.controls" + } + } + + Type { + name: "Qt.labs.controls.Dial" + icon: "images/todo16.png" + + ItemLibraryEntry { + name: "Dial" + category: "Qt Labs - Controls" + libraryIcon: "images/todo.png" + version: "1.0" + requiredImport: "Qt.labs.controls" + } + } + + Type { name: "Qt.labs.controls.Frame" icon: "images/todo16.png" @@ -76,6 +102,21 @@ MetaInfo { } Type { + name: "Qt.labs.controls.ItemDelegate" + icon: "images/todo16.png" + + ItemLibraryEntry { + name: "Item Delegate" + category: "Qt Labs - Controls" + libraryIcon: "images/todo.png" + version: "1.0" + requiredImport: "Qt.labs.controls" + + Property { name: "text"; type: "binding"; value: "qsTr('Item Delegate')" } + } + } + + Type { name: "Qt.labs.controls.Label" icon: "images/todo16.png" @@ -106,6 +147,22 @@ MetaInfo { } Type { + name: "Qt.labs.controls.Pane" + icon: "images/todo16.png" + + ItemLibraryEntry { + name: "Pane" + category: "Qt Labs - Controls" + libraryIcon: "images/todo.png" + version: "1.0" + requiredImport: "Qt.labs.controls" + + Property { name: "width"; type: "int"; value: 200 } + Property { name: "height"; type: "int"; value: 200 } + } + } + + Type { name: "Qt.labs.controls.ProgressBar" icon: "images/todo16.png" @@ -151,6 +208,19 @@ MetaInfo { } Type { + name: "Qt.labs.controls.SpinBox" + icon: "images/todo16.png" + + ItemLibraryEntry { + name: "Spin Box" + category: "Qt Labs - Controls" + libraryIcon: "images/todo.png" + version: "1.0" + requiredImport: "Qt.labs.controls" + } + } + + Type { name: "Qt.labs.controls.Switch" icon: "images/todo16.png" @@ -224,4 +294,17 @@ MetaInfo { Property { name: "width"; type: "int"; value: 360 } } } + + Type { + name: "Qt.labs.controls.Tumbler" + icon: "images/todo16.png" + + ItemLibraryEntry { + name: "Tumbler" + category: "Qt Labs - Controls" + libraryIcon: "images/todo.png" + version: "1.0" + requiredImport: "Qt.labs.controls" + } + } } diff --git a/src/imports/controls/doc/images/qtlabscontrols-popup-transformorigin.png b/src/imports/controls/doc/images/qtlabscontrols-popup-transformorigin.png Binary files differnew file mode 100644 index 00000000..4af320fb --- /dev/null +++ b/src/imports/controls/doc/images/qtlabscontrols-popup-transformorigin.png diff --git a/src/imports/controls/material/Button.qml b/src/imports/controls/material/Button.qml index 1256e3e1..77128861 100644 --- a/src/imports/controls/material/Button.qml +++ b/src/imports/controls/material/Button.qml @@ -71,36 +71,28 @@ T.Button { //! [label] //! [background] - background: Item { + background: Rectangle { implicitWidth: 64 implicitHeight: 48 - Rectangle { - id: rect - // external vertical padding is 6 (to increase touch area) - y: 6 - width: parent.width - height: parent.height - 12 - radius: 2 - color: !control.enabled ? (control.highlighted ? control.Material.raisedHighlightedButtonDisabledColor : control.Material.raisedButtonDisabledColor) : - (control.pressed ? (control.highlighted ? control.Material.raisedHighlightedButtonPressColor : control.Material.raisedButtonPressColor) : - (control.activeFocus ? (control.highlighted ? control.Material.raisedHighlightedButtonHoverColor : control.Material.raisedButtonHoverColor) : - (control.highlighted ? control.Material.raisedHighlightedButtonColor : control.Material.raisedButtonColor))) + // external vertical padding is 6 (to increase touch area) + y: 6 + width: parent.width + height: parent.height - 12 + radius: 2 + color: !control.enabled ? (control.highlighted ? control.Material.raisedHighlightedButtonDisabledColor : control.Material.raisedButtonDisabledColor) : + (control.pressed ? (control.highlighted ? control.Material.raisedHighlightedButtonPressColor : control.Material.raisedButtonPressColor) : + (control.activeFocus ? (control.highlighted ? control.Material.raisedHighlightedButtonHoverColor : control.Material.raisedButtonHoverColor) : + (control.highlighted ? control.Material.raisedHighlightedButtonColor : control.Material.raisedButtonColor))) - Behavior on color { - ColorAnimation { - duration: 400 - } + Behavior on color { + ColorAnimation { + duration: 400 } } - DropShadow { - source: rect - visible: control.enabled - x: rect.x - y: rect.y - width: rect.width - height: rect.height + layer.enabled: control.enabled + layer.effect: DropShadow { verticalOffset: 1 color: control.Material.dropShadowColor samples: control.pressed ? 15 : 9 diff --git a/src/imports/controls/material/ComboBox.qml b/src/imports/controls/material/ComboBox.qml index fc284be1..5979f97a 100644 --- a/src/imports/controls/material/ComboBox.qml +++ b/src/imports/controls/material/ComboBox.qml @@ -56,7 +56,7 @@ T.ComboBox { //! [delegate] delegate: ItemDelegate { width: control.width - text: control.textRole ? model[control.textRole] : modelData + text: control.textRole ? (Array.isArray(control.model) ? modelData[control.textRole] : model[control.textRole]) : modelData highlighted: control.highlightedIndex === index pressed: highlighted && control.pressed } @@ -75,29 +75,21 @@ T.ComboBox { //! [contentItem] //! [background] - background: Item { + background: Rectangle { implicitWidth: 120 implicitHeight: 32 - Rectangle { - id: rect - width: parent.width - height: parent.height - radius: 2 - color: control.Material.dialogColor + radius: 2 + color: control.Material.dialogColor - Behavior on color { - ColorAnimation { - duration: 400 - } + Behavior on color { + ColorAnimation { + duration: 400 } } - DropShadow { - source: rect - visible: control.enabled - width: parent.width - height: parent.height + layer.enabled: control.enabled + layer.effect: DropShadow { verticalOffset: 1 color: control.Material.dropShadowColor samples: control.pressed ? 15 : 9 @@ -118,6 +110,7 @@ T.ComboBox { y: control.height implicitWidth: control.width implicitHeight: Math.min(200, listview.contentHeight) + transformOrigin: Item.Top enter: Transition { // grow_fade_in @@ -134,26 +127,17 @@ T.ComboBox { contentItem: ListView { id: listview clip: true - model: control.delegateModel + model: control.popup.visible ? control.delegateModel : null currentIndex: control.highlightedIndex - transformOrigin: popup.showAbove ? Item.Bottom : Item.Top // ScrollIndicator.vertical: ScrollIndicator { } } - background: Item { - Rectangle { - id: panel - width: parent.width - height: parent.height - color: control.Material.dialogColor - } + background: Rectangle { + color: control.Material.dialogColor - DropShadow { - source: panel - visible: control.enabled - width: parent.width - height: parent.height + layer.enabled: control.enabled + layer.effect: DropShadow { verticalOffset: 1 color: control.Material.dropShadowColor samples: 15 diff --git a/src/imports/controls/material/Frame.qml b/src/imports/controls/material/Frame.qml index 3b4c8bd5..9336850d 100644 --- a/src/imports/controls/material/Frame.qml +++ b/src/imports/controls/material/Frame.qml @@ -44,8 +44,8 @@ T.Frame { implicitWidth: Math.max(background ? background.implicitWidth : 0, contentWidth + leftPadding + rightPadding) implicitHeight: Math.max(background ? background.implicitHeight : 0, contentHeight + topPadding + bottomPadding) - contentWidth: contentChildren.length === 1 ? contentChildren[0].implicitWidth : 0 - contentHeight: contentChildren.length === 1 ? contentChildren[0].implicitHeight : 0 + contentWidth: contentItem.implicitWidth || (contentChildren.length === 1 ? contentChildren[0].implicitWidth : 0) + contentHeight: contentItem.implicitHeight || (contentChildren.length === 1 ? contentChildren[0].implicitHeight : 0) padding: 6 diff --git a/src/imports/controls/material/GroupBox.qml b/src/imports/controls/material/GroupBox.qml index cbdc585e..3461cb6e 100644 --- a/src/imports/controls/material/GroupBox.qml +++ b/src/imports/controls/material/GroupBox.qml @@ -46,8 +46,8 @@ T.GroupBox { contentWidth + leftPadding + rightPadding) implicitHeight: Math.max(background ? background.implicitHeight : 0, contentHeight + topPadding + bottomPadding) - contentWidth: contentChildren.length === 1 ? contentChildren[0].implicitWidth : 0 - contentHeight: contentChildren.length === 1 ? contentChildren[0].implicitHeight : 0 + contentWidth: contentItem.implicitWidth || (contentChildren.length === 1 ? contentChildren[0].implicitWidth : 0) + contentHeight: contentItem.implicitHeight || (contentChildren.length === 1 ? contentChildren[0].implicitHeight : 0) spacing: 6 padding: 6 diff --git a/src/imports/controls/material/Menu.qml b/src/imports/controls/material/Menu.qml index 6a5c6f61..755f5a56 100644 --- a/src/imports/controls/material/Menu.qml +++ b/src/imports/controls/material/Menu.qml @@ -48,6 +48,8 @@ T.Menu { implicitHeight: Math.min(background ? background.implicitHeight : 0, contentItem ? contentItem.implicitHeight + topPadding + bottomPadding : 0) + transformOrigin: Item.Top + enter: Transition { // grow_fade_in NumberAnimation { property: "scale"; from: 0.9; to: 1.0; easing.type: Easing.OutQuint; duration: 220 } @@ -63,7 +65,6 @@ T.Menu { //! [contentItem] contentItem: ListView { implicitHeight: contentHeight - transformOrigin: Item.Top model: control.contentModel // TODO: improve this? @@ -77,21 +78,15 @@ T.Menu { //! [contentItem] //! [background] - background: Item { + background: Rectangle { implicitWidth: 200 implicitHeight: 200 - Rectangle { - id: panel - width: parent.width - height: parent.height - color: control.Material.dialogColor - } + radius: 3 + color: control.Material.dialogColor - DropShadow { - source: panel - width: parent.width - height: parent.height + layer.enabled: true + layer.effect: DropShadow { verticalOffset: 1 color: control.Material.dropShadowColor samples: 15 diff --git a/src/imports/controls/material/Pane.qml b/src/imports/controls/material/Pane.qml index abb94808..5f48aaf8 100644 --- a/src/imports/controls/material/Pane.qml +++ b/src/imports/controls/material/Pane.qml @@ -44,8 +44,8 @@ T.Frame { implicitWidth: Math.max(background ? background.implicitWidth : 0, contentWidth + leftPadding + rightPadding) implicitHeight: Math.max(background ? background.implicitHeight : 0, contentHeight + topPadding + bottomPadding) - contentWidth: contentChildren.length === 1 ? contentChildren[0].implicitWidth : 0 - contentHeight: contentChildren.length === 1 ? contentChildren[0].implicitHeight : 0 + contentWidth: contentItem.implicitWidth || (contentChildren.length === 1 ? contentChildren[0].implicitWidth : 0) + contentHeight: contentItem.implicitHeight || (contentChildren.length === 1 ? contentChildren[0].implicitHeight : 0) padding: 6 diff --git a/src/imports/controls/material/Popup.qml b/src/imports/controls/material/Popup.qml index b1c73b0c..649c5837 100644 --- a/src/imports/controls/material/Popup.qml +++ b/src/imports/controls/material/Popup.qml @@ -45,8 +45,8 @@ T.Popup { implicitWidth: Math.max(background ? background.implicitWidth : 0, contentWidth + leftPadding + rightPadding) implicitHeight: Math.max(background ? background.implicitHeight : 0, contentHeight + topPadding + bottomPadding) - contentWidth: contentChildren.length === 1 ? contentChildren[0].implicitWidth : 0 - contentHeight: contentChildren.length === 1 ? contentChildren[0].implicitHeight : 0 + contentWidth: contentItem.implicitWidth || (contentChildren.length === 1 ? contentChildren[0].implicitWidth : 0) + contentHeight: contentItem.implicitHeight || (contentChildren.length === 1 ? contentChildren[0].implicitHeight : 0) padding: 6 diff --git a/src/imports/controls/material/ProgressBar.qml b/src/imports/controls/material/ProgressBar.qml index 709ac28d..52df1660 100644 --- a/src/imports/controls/material/ProgressBar.qml +++ b/src/imports/controls/material/ProgressBar.qml @@ -37,6 +37,7 @@ import QtQuick 2.6 import Qt.labs.templates 1.0 as T import Qt.labs.controls.material 1.0 +import Qt.labs.controls.material.impl 1.0 T.ProgressBar { id: control @@ -46,43 +47,22 @@ T.ProgressBar { implicitHeight: Math.max(background ? background.implicitHeight : 0, indicator ? indicator.implicitHeight : 0) + topPadding + bottomPadding - padding: 6 - //! [indicator] - indicator: Item { + indicator: ProgressStrip { + id: strip x: control.leftPadding - y: control.topPadding + y: control.topPadding + (control.availableHeight - height) / 2 width: control.availableWidth - height: control.availableHeight + height: 4 scale: control.mirrored ? -1 : 1 + indeterminate: control.indeterminate + color: control.Material.accentColor + progress: control.position - Repeater { - model: indeterminate ? 2 : 1 - - Rectangle { - property real offset: indeterminate ? 0 : control.position - - x: (indeterminate ? offset * parent.width : 0) - y: (parent.height - height) / 2 - width: offset * (parent.width - x) - height: 4 - - color: control.Material.accentColor - - SequentialAnimation on offset { - loops: Animation.Infinite - running: indeterminate && visible - PauseAnimation { duration: index ? 520 : 0 } - NumberAnimation { - easing.type: Easing.OutCubic - duration: 1240 - from: 0 - to: 1 - } - PauseAnimation { duration: index ? 0 : 520 } - } - } + StripAnimator { + target: strip + running: control.visible && control.indeterminate } } //! [indicator] diff --git a/src/imports/controls/material/StackView.qml b/src/imports/controls/material/StackView.qml index 776188e6..c31c13d2 100644 --- a/src/imports/controls/material/StackView.qml +++ b/src/imports/controls/material/StackView.qml @@ -43,7 +43,7 @@ T.StackView { //! [popEnter] popEnter: Transition { // slide_in_left - NumberAnimation { property: "x"; from: 0.5 * -root.width; to: 0; duration: 200; easing.type: Easing.OutCubic } + NumberAnimation { property: "x"; from: (root.mirrored ? -0.5 : 0.5) * -root.width; to: 0; duration: 200; easing.type: Easing.OutCubic } NumberAnimation { property: "opacity"; from: 0.0; to: 1.0; duration: 200; easing.type: Easing.OutCubic } } //! [popEnter] @@ -51,7 +51,7 @@ T.StackView { //! [popExit] popExit: Transition { // slide_out_right - NumberAnimation { property: "x"; from: 0; to: 0.5 * root.width; duration: 200; easing.type: Easing.OutCubic } + NumberAnimation { property: "x"; from: 0; to: (root.mirrored ? -0.5 : 0.5) * root.width; duration: 200; easing.type: Easing.OutCubic } NumberAnimation { property: "opacity"; from: 1.0; to: 0.0; duration: 200; easing.type: Easing.OutCubic } } //! [popExit] @@ -59,7 +59,7 @@ T.StackView { //! [pushEnter] pushEnter: Transition { // slide_in_right - NumberAnimation { property: "x"; from: 0.5 * root.width; to: 0; duration: 200; easing.type: Easing.OutCubic } + NumberAnimation { property: "x"; from: (root.mirrored ? -0.5 : 0.5) * root.width; to: 0; duration: 200; easing.type: Easing.OutCubic } NumberAnimation { property: "opacity"; from: 0.0; to: 1.0; duration: 200; easing.type: Easing.OutCubic } } //! [pushEnter] @@ -67,7 +67,7 @@ T.StackView { //! [pushExit] pushExit: Transition { // slide_out_left - NumberAnimation { property: "x"; from: 0; to: 0.5 * -root.width; duration: 200; easing.type: Easing.OutCubic } + NumberAnimation { property: "x"; from: 0; to: (root.mirrored ? -0.5 : 0.5) * -root.width; duration: 200; easing.type: Easing.OutCubic } NumberAnimation { property: "opacity"; from: 1.0; to: 0.0; duration: 200; easing.type: Easing.OutCubic } } //! [pushExit] @@ -75,7 +75,7 @@ T.StackView { //! [replaceEnter] replaceEnter: Transition { // slide_in_right - NumberAnimation { property: "x"; from: 0.5 * root.width; to: 0; duration: 200; easing.type: Easing.OutCubic } + NumberAnimation { property: "x"; from: (root.mirrored ? -0.5 : 0.5) * root.width; to: 0; duration: 200; easing.type: Easing.OutCubic } NumberAnimation { property: "opacity"; from: 0.0; to: 1.0; duration: 200; easing.type: Easing.OutCubic } } //! [replaceEnter] @@ -83,7 +83,7 @@ T.StackView { //! [replaceExit] replaceExit: Transition { // slide_out_left - NumberAnimation { property: "x"; from: 0; to: 0.5 * -root.width; duration: 200; easing.type: Easing.OutCubic } + NumberAnimation { property: "x"; from: 0; to: (root.mirrored ? -0.5 : 0.5) * -root.width; duration: 200; easing.type: Easing.OutCubic } NumberAnimation { property: "opacity"; from: 1.0; to: 0.0; duration: 200; easing.type: Easing.OutCubic } } //! [replaceExit] diff --git a/src/imports/controls/material/Switch.qml b/src/imports/controls/material/Switch.qml index 36e2d4a8..b1a69286 100644 --- a/src/imports/controls/material/Switch.qml +++ b/src/imports/controls/material/Switch.qml @@ -97,19 +97,14 @@ T.Switch { duration: 300 } } - } - DropShadow { - x: handle.x - y: handle.y - width: handle.width - height: handle.height - source: handle - verticalOffset: 1 - color: control.Material.dropShadowColor - spread: 0.3 + layer.enabled: true + layer.effect: DropShadow { + verticalOffset: 1 + color: control.Material.dropShadowColor + spread: 0.3 + } } - } //! [indicator] diff --git a/src/imports/controls/material/ToolBar.qml b/src/imports/controls/material/ToolBar.qml index ad34e1a0..57a70564 100644 --- a/src/imports/controls/material/ToolBar.qml +++ b/src/imports/controls/material/ToolBar.qml @@ -44,8 +44,8 @@ T.ToolBar { implicitWidth: Math.max(background ? background.implicitWidth : 0, contentWidth + leftPadding + rightPadding) implicitHeight: Math.max(background ? background.implicitHeight : 0, contentHeight + topPadding + bottomPadding) - contentWidth: contentChildren.length === 1 ? contentChildren[0].implicitWidth : 0 - contentHeight: contentChildren.length === 1 ? contentChildren[0].implicitHeight : 0 + contentWidth: contentItem.implicitWidth || (contentChildren.length === 1 ? contentChildren[0].implicitWidth : 0) + contentHeight: contentItem.implicitHeight || (contentChildren.length === 1 ? contentChildren[0].implicitHeight : 0) //! [contentItem] contentItem: Item { } diff --git a/src/imports/controls/material/material.pri b/src/imports/controls/material/material.pri index bcdc0de9..e41c7d2d 100644 --- a/src/imports/controls/material/material.pri +++ b/src/imports/controls/material/material.pri @@ -1,12 +1,14 @@ HEADERS += \ $$PWD/qquickmaterialstyle_p.h \ $$PWD/qquickmaterialtheme_p.h \ - $$PWD/qquickmaterialprogressring_p.h + $$PWD/qquickmaterialprogressring_p.h \ + $$PWD/qquickmaterialprogressstrip_p.h SOURCES += \ $$PWD/qquickmaterialstyle.cpp \ $$PWD/qquickmaterialtheme.cpp \ - $$PWD/qquickmaterialprogressring.cpp + $$PWD/qquickmaterialprogressring.cpp \ + $$PWD/qquickmaterialprogressstrip.cpp QML_FILES += \ $$PWD/ApplicationWindow.qml \ diff --git a/src/imports/controls/material/qquickmaterialprogressstrip.cpp b/src/imports/controls/material/qquickmaterialprogressstrip.cpp new file mode 100644 index 00000000..a3ff6c9b --- /dev/null +++ b/src/imports/controls/material/qquickmaterialprogressstrip.cpp @@ -0,0 +1,248 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Labs Controls module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qquickmaterialprogressstrip_p.h" + +#include <QtCore/qmath.h> +#include <QtCore/qeasingcurve.h> +#include <QtQuick/qsgsimplerectnode.h> +#include <QtQuick/private/qquickitem_p.h> +#include <QtQuick/private/qquickanimatorjob_p.h> +#include <QtQuick/private/qsgadaptationlayer_p.h> + +QT_BEGIN_NAMESPACE + +static const int PauseDuration = 520; +static const int SlideDuration = 1240; +static const int TotalDuration = SlideDuration + PauseDuration; + +class QQuickMaterialProgressStripAnimatorJob : public QQuickAnimatorJob +{ +public: + QQuickMaterialProgressStripAnimatorJob(); + + void initialize(QQuickAnimatorController *controller) override; + void updateCurrentTime(int time) override; + void writeBack() override; + void nodeWasDestroyed() override; + void afterNodeSync() override; + + void moveNode(QSGTransformNode *node, const QRectF &geometry, qreal progress); + +private: + QSGNode *m_node; +}; + +QQuickMaterialProgressStripAnimatorJob::QQuickMaterialProgressStripAnimatorJob() : m_node(nullptr) +{ +} + +void QQuickMaterialProgressStripAnimatorJob::initialize(QQuickAnimatorController *controller) +{ + QQuickAnimatorJob::initialize(controller); + m_node = QQuickItemPrivate::get(m_target)->childContainerNode(); +} + +void QQuickMaterialProgressStripAnimatorJob::updateCurrentTime(int time) +{ + if (!m_node) + return; + + QSGSimpleRectNode *geometryNode = static_cast<QSGSimpleRectNode *>(m_node->firstChild()); + Q_ASSERT(!geometryNode || geometryNode->type() == QSGNode::GeometryNodeType); + if (!geometryNode) + return; + + const QRectF geometry = geometryNode->rect(); + + QSGTransformNode *firstNode = static_cast<QSGTransformNode *>(geometryNode->firstChild()); + if (firstNode) { + Q_ASSERT(firstNode->type() == QSGNode::TransformNodeType); + + const qreal progress = qMin<qreal>(1.0, static_cast<qreal>(time) / SlideDuration); + moveNode(static_cast<QSGTransformNode *>(firstNode), geometry, progress); + } + + QSGTransformNode *secondNode = static_cast<QSGTransformNode *>(geometryNode->lastChild()); + if (secondNode) { + Q_ASSERT(secondNode->type() == QSGNode::TransformNodeType); + + const qreal progress = qMax<qreal>(0.0, static_cast<qreal>(time - PauseDuration) / SlideDuration); + moveNode(static_cast<QSGTransformNode *>(secondNode), geometry, progress); + } +} + +void QQuickMaterialProgressStripAnimatorJob::writeBack() +{ +} + +void QQuickMaterialProgressStripAnimatorJob::nodeWasDestroyed() +{ + m_node = nullptr; +} + +void QQuickMaterialProgressStripAnimatorJob::afterNodeSync() +{ + m_node = QQuickItemPrivate::get(m_target)->childContainerNode(); +} + +void QQuickMaterialProgressStripAnimatorJob::moveNode(QSGTransformNode *transformNode, const QRectF &geometry, qreal progress) +{ + const qreal value = m_easing.valueForProgress(progress); + const qreal x = value * geometry.width(); + + QMatrix4x4 matrix; + matrix.translate(x, 0); + transformNode->setMatrix(matrix); + + QSGRectangleNode *rectNode = static_cast<QSGRectangleNode *>(transformNode->firstChild()); + Q_ASSERT(rectNode->type() == QSGNode::GeometryNodeType); + + QRectF r = geometry; + r.setWidth(value * (geometry.width() - x)); + rectNode->setRect(r); + rectNode->update(); +} + +QQuickMaterialStripAnimator::QQuickMaterialStripAnimator(QObject *parent) + : QQuickAnimator(parent) +{ + setLoops(Infinite); + setDuration(TotalDuration); + setEasing(QEasingCurve::OutCubic); +} + +QString QQuickMaterialStripAnimator::propertyName() const +{ + return QString(); +} + +QQuickAnimatorJob *QQuickMaterialStripAnimator::createJob() const +{ + return new QQuickMaterialProgressStripAnimatorJob; +} + +QQuickMaterialProgressStrip::QQuickMaterialProgressStrip(QQuickItem *parent) + : QQuickItem(parent), m_color(Qt::black), m_progress(0.0), m_indeterminate(false) +{ + setFlag(ItemHasContents); +} + +QColor QQuickMaterialProgressStrip::color() const +{ + return m_color; +} + +void QQuickMaterialProgressStrip::setColor(const QColor &color) +{ + if (color == m_color) + return; + + m_color = color; + update(); +} + +qreal QQuickMaterialProgressStrip::progress() const +{ + return m_progress; +} + +void QQuickMaterialProgressStrip::setProgress(qreal progress) +{ + if (progress == m_progress) + return; + + m_progress = progress; + update(); +} + +bool QQuickMaterialProgressStrip::isIndeterminate() const +{ + return m_indeterminate; +} + +void QQuickMaterialProgressStrip::setIndeterminate(bool indeterminate) +{ + if (indeterminate == m_indeterminate) + return; + + m_indeterminate = indeterminate; + update(); +} + +QSGNode *QQuickMaterialProgressStrip::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) +{ + QQuickItemPrivate *d = QQuickItemPrivate::get(this); + + if (!oldNode) + oldNode = new QSGSimpleRectNode(boundingRect(), Qt::transparent); + static_cast<QSGSimpleRectNode *>(oldNode)->setRect(boundingRect()); + + const int count = m_indeterminate ? 2 : 1; + const qreal w = m_indeterminate ? 0 : m_progress * width(); + + QSGNode *transformNode = oldNode->firstChild(); + for (int i = 0; i < count; ++i) { + if (!transformNode) { + transformNode = new QSGTransformNode; + oldNode->appendChildNode(transformNode); + + QSGRectangleNode *rectNode = d->sceneGraphContext()->createRectangleNode(); + rectNode->setAntialiasing(true); + transformNode->appendChildNode(rectNode); + } + Q_ASSERT(transformNode->type() == QSGNode::TransformNodeType); + + QSGRectangleNode *rectNode = static_cast<QSGRectangleNode *>(transformNode->firstChild()); + Q_ASSERT(rectNode->type() == QSGNode::GeometryNodeType); + + rectNode->setRect(QRectF(0, 0, w, height())); + rectNode->setColor(m_color); + rectNode->update(); + + transformNode = transformNode->nextSibling(); + } + + while (transformNode) { + QSGNode *nextSibling = transformNode->nextSibling(); + delete transformNode; + transformNode = nextSibling; + } + + return oldNode; +} + +QT_END_NAMESPACE diff --git a/src/imports/controls/material/qquickmaterialprogressstrip_p.h b/src/imports/controls/material/qquickmaterialprogressstrip_p.h new file mode 100644 index 00000000..38333ee5 --- /dev/null +++ b/src/imports/controls/material/qquickmaterialprogressstrip_p.h @@ -0,0 +1,101 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Labs Controls module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKMATERIALPROGRESSSTRIP_P_H +#define QQUICKMATERIALPROGRESSSTRIP_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtQuick/qquickitem.h> +#include <QtQuick/private/qquickanimator_p.h> + +QT_BEGIN_NAMESPACE + +class QQuickMaterialProgressStrip : public QQuickItem +{ + Q_OBJECT + Q_PROPERTY(QColor color READ color WRITE setColor FINAL) + Q_PROPERTY(qreal progress READ progress WRITE setProgress FINAL) + Q_PROPERTY(bool indeterminate READ isIndeterminate WRITE setIndeterminate FINAL) + +public: + QQuickMaterialProgressStrip(QQuickItem *parent = nullptr); + + QColor color() const; + void setColor(const QColor &color); + + qreal progress() const; + void setProgress(qreal progress); + + bool isIndeterminate() const; + void setIndeterminate(bool indeterminate); + +protected: + QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) override; + +private: + QColor m_color; + qreal m_progress; + bool m_indeterminate; +}; + +class QQuickMaterialStripAnimator : public QQuickAnimator +{ + Q_OBJECT + +public: + QQuickMaterialStripAnimator(QObject *parent = nullptr); + +protected: + QString propertyName() const override; + QQuickAnimatorJob *createJob() const override; +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QQuickMaterialProgressStrip) +QML_DECLARE_TYPE(QQuickMaterialStripAnimator) + +#endif // QQUICKMATERIALPROGRESSSTRIP_P_H diff --git a/src/imports/controls/material/qtlabsmaterialstyleplugin.cpp b/src/imports/controls/material/qtlabsmaterialstyleplugin.cpp index 7d24a249..0c6f2ad0 100644 --- a/src/imports/controls/material/qtlabsmaterialstyleplugin.cpp +++ b/src/imports/controls/material/qtlabsmaterialstyleplugin.cpp @@ -39,6 +39,7 @@ #include "qquickmaterialstyle_p.h" #include "qquickmaterialtheme_p.h" #include "qquickmaterialprogressring_p.h" +#include "qquickmaterialprogressstrip_p.h" #include <QtGui/private/qguiapplication_p.h> #include <QtLabsControls/private/qquickstyleselector_p.h> @@ -104,7 +105,9 @@ void QtLabsMaterialStylePlugin::initializeEngine(QQmlEngine *engine, const char QByteArray import = QByteArray(uri) + ".impl"; qmlRegisterType<QQuickMaterialProgressRing>(import, 1, 0, "ProgressRing"); + qmlRegisterType<QQuickMaterialProgressStrip>(import, 1, 0, "ProgressStrip"); qmlRegisterType<QQuickMaterialRingAnimator>(import, 1, 0, "RingAnimator"); + qmlRegisterType<QQuickMaterialStripAnimator>(import, 1, 0, "StripAnimator"); qmlRegisterType(QUrl(baseUrl().toString() + QStringLiteral("/Ripple.qml")), import, 1, 0, "Ripple"); qmlRegisterType(QUrl(baseUrl().toString() + QStringLiteral("/SliderHandle.qml")), import, 1, 0, "SliderHandle"); } diff --git a/src/imports/controls/plugins.qmltypes b/src/imports/controls/plugins.qmltypes index 7ffa52be..d52c6153 100644 --- a/src/imports/controls/plugins.qmltypes +++ b/src/imports/controls/plugins.qmltypes @@ -29,23 +29,11 @@ Module { Property { name: "autoRepeat"; type: "bool" } Property { name: "indicator"; type: "QQuickItem"; isPointer: true } Property { name: "label"; type: "QQuickItem"; isPointer: true } - Signal { - name: "pressed" - Parameter { name: "mouse"; type: "QQuickMouseEvent"; isPointer: true } - } - Signal { - name: "released" - Parameter { name: "mouse"; type: "QQuickMouseEvent"; isPointer: true } - } + Signal { name: "pressed" } + Signal { name: "released" } Signal { name: "canceled" } - Signal { - name: "clicked" - Parameter { name: "mouse"; type: "QQuickMouseEvent"; isPointer: true } - } - Signal { - name: "doubleClicked" - Parameter { name: "mouse"; type: "QQuickMouseEvent"; isPointer: true } - } + Signal { name: "clicked" } + Signal { name: "doubleClicked" } Method { name: "toggle" } } Component { @@ -62,6 +50,7 @@ Module { Property { name: "footer"; type: "QQuickItem"; isPointer: true } Property { name: "overlay"; type: "QQuickOverlay"; isReadonly: true; isPointer: true } Property { name: "font"; type: "QFont" } + Property { name: "locale"; type: "QLocale" } } Component { name: "QQuickApplicationWindowAttached" @@ -71,7 +60,7 @@ Module { Property { name: "activeFocusControl"; type: "QQuickItem"; isReadonly: true; isPointer: true } Property { name: "header"; type: "QQuickItem"; isReadonly: true; isPointer: true } Property { name: "footer"; type: "QQuickItem"; isReadonly: true; isPointer: true } - Property { name: "overlay"; type: "QQuickItem"; isReadonly: true; isPointer: true } + Property { name: "overlay"; type: "QQuickOverlay"; isReadonly: true; isPointer: true } } Component { name: "QQuickBusyIndicator" @@ -290,6 +279,7 @@ Module { exportMetaObjectRevisions: [0] Property { name: "contentModel"; type: "QVariant"; isReadonly: true } Property { name: "contentData"; type: "QObject"; isList: true; isReadonly: true } + Property { name: "title"; type: "string" } Method { name: "itemAt" type: "QQuickItem*" @@ -331,6 +321,17 @@ Module { Signal { name: "released" } } Component { + name: "QQuickPage" + defaultProperty: "contentData" + prototype: "QQuickControl" + exports: ["Qt.labs.templates/Page 1.0"] + exportMetaObjectRevisions: [0] + Property { name: "header"; type: "QQuickItem"; isPointer: true } + Property { name: "footer"; type: "QQuickItem"; isPointer: true } + Property { name: "contentData"; type: "QObject"; isList: true; isReadonly: true } + Property { name: "contentChildren"; type: "QQuickItem"; isList: true; isReadonly: true } + } + Component { name: "QQuickPageIndicator" defaultProperty: "data" prototype: "QQuickControl" @@ -354,18 +355,60 @@ Module { } Component { name: "QQuickPopup" + defaultProperty: "contentData" prototype: "QObject" exports: ["Qt.labs.templates/Popup 1.0"] exportMetaObjectRevisions: [0] + Enum { + name: "ClosePolicy" + values: { + "NoAutoClose": 0, + "CloseOnPressOutside": 1, + "CloseOnReleaseOutside": 2, + "CloseOnEscape": 4 + } + } + Enum { + name: "TransformOrigin" + values: { + "TopLeft": 0, + "Top": 1, + "TopRight": 2, + "Left": 3, + "Center": 4, + "Right": 5, + "BottomLeft": 6, + "Bottom": 7, + "BottomRight": 8 + } + } + Property { name: "x"; type: "double" } + Property { name: "y"; type: "double" } + Property { name: "width"; type: "double" } + Property { name: "height"; type: "double" } + Property { name: "implicitWidth"; type: "double" } + Property { name: "implicitHeight"; type: "double" } + Property { name: "contentWidth"; type: "double" } + Property { name: "contentHeight"; type: "double" } + Property { name: "availableWidth"; type: "double"; isReadonly: true } + Property { name: "availableHeight"; type: "double"; isReadonly: true } + Property { name: "padding"; type: "double" } + Property { name: "topPadding"; type: "double" } + Property { name: "leftPadding"; type: "double" } + Property { name: "rightPadding"; type: "double" } + Property { name: "bottomPadding"; type: "double" } + Property { name: "parent"; type: "QQuickItem"; isPointer: true } + Property { name: "background"; type: "QQuickItem"; isPointer: true } Property { name: "contentItem"; type: "QQuickItem"; isPointer: true } + Property { name: "contentData"; type: "QObject"; isList: true; isReadonly: true } + Property { name: "contentChildren"; type: "QQuickItem"; isList: true; isReadonly: true } Property { name: "focus"; type: "bool" } Property { name: "modal"; type: "bool" } - Property { name: "visible"; type: "bool"; isReadonly: true } + Property { name: "visible"; type: "bool" } + Property { name: "closePolicy"; type: "ClosePolicy" } + Property { name: "transformOrigin"; type: "TransformOrigin" } Property { name: "enter"; type: "QQuickTransition"; isPointer: true } Property { name: "exit"; type: "QQuickTransition"; isPointer: true } - Signal { name: "pressedOutside" } - Signal { name: "releasedOutside" } - Signal { name: "clickedOutside" } Signal { name: "aboutToShow" } Signal { name: "aboutToHide" } Method { name: "open" } @@ -975,15 +1018,15 @@ Module { } Signal { name: "horizontalAlignmentChanged" - Parameter { name: "alignment"; type: "HAlignment" } + Parameter { name: "alignment"; type: "QQuickTextEdit::HAlignment" } } Signal { name: "verticalAlignmentChanged" - Parameter { name: "alignment"; type: "VAlignment" } + Parameter { name: "alignment"; type: "QQuickTextEdit::VAlignment" } } Signal { name: "textFormatChanged" - Parameter { name: "textFormat"; type: "TextFormat" } + Parameter { name: "textFormat"; type: "QQuickTextEdit::TextFormat" } } Signal { name: "readOnlyChanged" @@ -1016,7 +1059,7 @@ Module { } Signal { name: "mouseSelectionModeChanged" - Parameter { name: "mode"; type: "SelectionMode" } + Parameter { name: "mode"; type: "QQuickTextEdit::SelectionMode" } } Signal { name: "linkActivated" @@ -1426,6 +1469,15 @@ Module { Property { name: "group"; type: "QQuickButtonGroup"; isPointer: true } } Component { + name: "QQuickProgressStrip" + defaultProperty: "data" + prototype: "QQuickItem" + exports: ["Qt.labs.controls.impl/ProgressStrip 1.0"] + exportMetaObjectRevisions: [0] + Property { name: "indeterminate"; type: "bool" } + Property { name: "progress"; type: "double" } + } + Component { prototype: "QQuickApplicationWindow" name: "Qt.labs.controls/ApplicationWindow 1.0" exports: ["Qt.labs.controls/ApplicationWindow 1.0"] @@ -1530,6 +1582,14 @@ Module { defaultProperty: "data" } Component { + prototype: "QQuickPage" + name: "Qt.labs.controls/Page 1.0" + exports: ["Qt.labs.controls/Page 1.0"] + exportMetaObjectRevisions: [0] + isComposite: true + defaultProperty: "contentData" + } + Component { prototype: "QQuickPageIndicator" name: "Qt.labs.controls/PageIndicator 1.0" exports: ["Qt.labs.controls/PageIndicator 1.0"] @@ -1546,6 +1606,14 @@ Module { defaultProperty: "contentData" } Component { + prototype: "QQuickPopup" + name: "Qt.labs.controls/Popup 1.0" + exports: ["Qt.labs.controls/Popup 1.0"] + exportMetaObjectRevisions: [0] + isComposite: true + defaultProperty: "contentData" + } + Component { prototype: "QQuickProgressBar" name: "Qt.labs.controls/ProgressBar 1.0" exports: ["Qt.labs.controls/ProgressBar 1.0"] diff --git a/src/imports/controls/universal/Button.qml b/src/imports/controls/universal/Button.qml index c18f0a25..c43d8d67 100644 --- a/src/imports/controls/universal/Button.qml +++ b/src/imports/controls/universal/Button.qml @@ -64,7 +64,7 @@ T.Button { text: control.text font: control.font elide: Text.ElideRight - horizontalAlignment: Text.AlignLeft + horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter renderType: Text.NativeRendering diff --git a/src/imports/controls/universal/ComboBox.qml b/src/imports/controls/universal/ComboBox.qml index f61ab634..0a5701b9 100644 --- a/src/imports/controls/universal/ComboBox.qml +++ b/src/imports/controls/universal/ComboBox.qml @@ -58,7 +58,7 @@ T.ComboBox { //! [delegate] delegate: ItemDelegate { width: control.width - text: control.textRole ? model[control.textRole] : modelData + text: control.textRole ? (Array.isArray(control.model) ? modelData[control.textRole] : model[control.textRole]) : modelData highlighted: control.highlightedIndex === index pressed: highlighted && control.pressed } @@ -116,7 +116,7 @@ T.ComboBox { contentItem: ListView { id: listview clip: true - model: control.delegateModel + model: control.popup.visible ? control.delegateModel : null currentIndex: control.highlightedIndex // ScrollIndicator.vertical: ScrollIndicator { } diff --git a/src/imports/controls/universal/Frame.qml b/src/imports/controls/universal/Frame.qml index 47e9e389..9427dc2f 100644 --- a/src/imports/controls/universal/Frame.qml +++ b/src/imports/controls/universal/Frame.qml @@ -44,8 +44,8 @@ T.Frame { implicitWidth: Math.max(background ? background.implicitWidth : 0, contentWidth + leftPadding + rightPadding) implicitHeight: Math.max(background ? background.implicitHeight : 0, contentHeight + topPadding + bottomPadding) - contentWidth: contentChildren.length === 1 ? contentChildren[0].implicitWidth : 0 - contentHeight: contentChildren.length === 1 ? contentChildren[0].implicitHeight : 0 + contentWidth: contentItem.implicitWidth || (contentChildren.length === 1 ? contentChildren[0].implicitWidth : 0) + contentHeight: contentItem.implicitHeight || (contentChildren.length === 1 ? contentChildren[0].implicitHeight : 0) padding: 12 diff --git a/src/imports/controls/universal/GroupBox.qml b/src/imports/controls/universal/GroupBox.qml index 524203db..9b21a17f 100644 --- a/src/imports/controls/universal/GroupBox.qml +++ b/src/imports/controls/universal/GroupBox.qml @@ -46,8 +46,8 @@ T.GroupBox { contentWidth + leftPadding + rightPadding) implicitHeight: Math.max(background ? background.implicitHeight : 0, contentHeight + topPadding + bottomPadding) - contentWidth: contentChildren.length === 1 ? contentChildren[0].implicitWidth : 0 - contentHeight: contentChildren.length === 1 ? contentChildren[0].implicitHeight : 0 + contentWidth: contentItem.implicitWidth || (contentChildren.length === 1 ? contentChildren[0].implicitWidth : 0) + contentHeight: contentItem.implicitHeight || (contentChildren.length === 1 ? contentChildren[0].implicitHeight : 0) spacing: 12 padding: 12 diff --git a/src/imports/controls/universal/Pane.qml b/src/imports/controls/universal/Pane.qml index 58c5214a..c0f87075 100644 --- a/src/imports/controls/universal/Pane.qml +++ b/src/imports/controls/universal/Pane.qml @@ -44,8 +44,8 @@ T.Frame { implicitWidth: Math.max(background ? background.implicitWidth : 0, contentWidth + leftPadding + rightPadding) implicitHeight: Math.max(background ? background.implicitHeight : 0, contentHeight + topPadding + bottomPadding) - contentWidth: contentChildren.length === 1 ? contentChildren[0].implicitWidth : 0 - contentHeight: contentChildren.length === 1 ? contentChildren[0].implicitHeight : 0 + contentWidth: contentItem.implicitWidth || (contentChildren.length === 1 ? contentChildren[0].implicitWidth : 0) + contentHeight: contentItem.implicitHeight || (contentChildren.length === 1 ? contentChildren[0].implicitHeight : 0) padding: 12 diff --git a/src/imports/controls/universal/Popup.qml b/src/imports/controls/universal/Popup.qml index 16ed5451..d26dd02d 100644 --- a/src/imports/controls/universal/Popup.qml +++ b/src/imports/controls/universal/Popup.qml @@ -44,8 +44,8 @@ T.Popup { implicitWidth: Math.max(background ? background.implicitWidth : 0, contentWidth + leftPadding + rightPadding) implicitHeight: Math.max(background ? background.implicitHeight : 0, contentHeight + topPadding + bottomPadding) - contentWidth: contentChildren.length === 1 ? contentChildren[0].implicitWidth : 0 - contentHeight: contentChildren.length === 1 ? contentChildren[0].implicitHeight : 0 + contentWidth: contentItem.implicitWidth || (contentChildren.length === 1 ? contentChildren[0].implicitWidth : 0) + contentHeight: contentItem.implicitHeight || (contentChildren.length === 1 ? contentChildren[0].implicitHeight : 0) padding: 12 diff --git a/src/imports/controls/universal/StackView.qml b/src/imports/controls/universal/StackView.qml index b09359b6..b49c2dbb 100644 --- a/src/imports/controls/universal/StackView.qml +++ b/src/imports/controls/universal/StackView.qml @@ -45,7 +45,7 @@ T.StackView { popEnter: Transition { ParallelAnimation { NumberAnimation { property: "opacity"; from: 0; to: 1; duration: 200; easing.type: Easing.InQuint } - NumberAnimation { property: "x"; from: -root.width / 3; to: 0; duration: 400; easing.type: Easing.OutCubic } + NumberAnimation { property: "x"; from: (root.mirrored ? -0.3 : 0.3) * -root.width; to: 0; duration: 400; easing.type: Easing.OutCubic } } } //! [popEnter] @@ -60,7 +60,7 @@ T.StackView { pushEnter: Transition { ParallelAnimation { NumberAnimation { property: "opacity"; from: 0; to: 1; duration: 200; easing.type: Easing.InQuint } - NumberAnimation { property: "x"; from: root.width / 3; to: 0; duration: 400; easing.type: Easing.OutCubic } + NumberAnimation { property: "x"; from: (root.mirrored ? -0.3 : 0.3) * root.width; to: 0; duration: 400; easing.type: Easing.OutCubic } } } //! [pushEnter] @@ -75,7 +75,7 @@ T.StackView { replaceEnter: Transition { ParallelAnimation { NumberAnimation { property: "opacity"; from: 0; to: 1; duration: 200; easing.type: Easing.InQuint } - NumberAnimation { property: "x"; from: root.width / 3; to: 0; duration: 400; easing.type: Easing.OutCubic } + NumberAnimation { property: "x"; from: (root.mirrored ? -0.3 : 0.3) * root.width; to: 0; duration: 400; easing.type: Easing.OutCubic } } } //! [replaceEnter] diff --git a/src/imports/controls/universal/ToolBar.qml b/src/imports/controls/universal/ToolBar.qml index e83fcc1d..cefb9dc9 100644 --- a/src/imports/controls/universal/ToolBar.qml +++ b/src/imports/controls/universal/ToolBar.qml @@ -44,8 +44,8 @@ T.ToolBar { implicitWidth: Math.max(background ? background.implicitWidth : 0, contentWidth + leftPadding + rightPadding) implicitHeight: Math.max(background ? background.implicitHeight : 0, contentHeight + topPadding + bottomPadding) - contentWidth: contentChildren.length === 1 ? contentChildren[0].implicitWidth : 0 - contentHeight: contentChildren.length === 1 ? contentChildren[0].implicitHeight : 0 + contentWidth: contentItem.implicitWidth || (contentChildren.length === 1 ? contentChildren[0].implicitWidth : 0) + contentHeight: contentItem.implicitHeight || (contentChildren.length === 1 ? contentChildren[0].implicitHeight : 0) //! [contentItem] contentItem: Item { } diff --git a/src/imports/controls/universal/ToolButton.qml b/src/imports/controls/universal/ToolButton.qml index 451e07c4..a7df8a84 100644 --- a/src/imports/controls/universal/ToolButton.qml +++ b/src/imports/controls/universal/ToolButton.qml @@ -60,7 +60,7 @@ T.ToolButton { font: control.font color: control.enabled ? control.Universal.baseHighColor : control.Universal.baseLowColor elide: Text.ElideRight - horizontalAlignment: Text.AlignLeft + horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter renderType: Text.NativeRendering } diff --git a/src/imports/templates/plugins.qmltypes b/src/imports/templates/plugins.qmltypes index e96c09d9..67058870 100644 --- a/src/imports/templates/plugins.qmltypes +++ b/src/imports/templates/plugins.qmltypes @@ -23,23 +23,11 @@ Module { Property { name: "autoRepeat"; type: "bool" } Property { name: "indicator"; type: "QQuickItem"; isPointer: true } Property { name: "label"; type: "QQuickItem"; isPointer: true } - Signal { - name: "pressed" - Parameter { name: "mouse"; type: "QQuickMouseEvent"; isPointer: true } - } - Signal { - name: "released" - Parameter { name: "mouse"; type: "QQuickMouseEvent"; isPointer: true } - } + Signal { name: "pressed" } + Signal { name: "released" } Signal { name: "canceled" } - Signal { - name: "clicked" - Parameter { name: "mouse"; type: "QQuickMouseEvent"; isPointer: true } - } - Signal { - name: "doubleClicked" - Parameter { name: "mouse"; type: "QQuickMouseEvent"; isPointer: true } - } + Signal { name: "clicked" } + Signal { name: "doubleClicked" } Method { name: "toggle" } } Component { @@ -56,6 +44,7 @@ Module { Property { name: "footer"; type: "QQuickItem"; isPointer: true } Property { name: "overlay"; type: "QQuickOverlay"; isReadonly: true; isPointer: true } Property { name: "font"; type: "QFont" } + Property { name: "locale"; type: "QLocale" } } Component { name: "QQuickApplicationWindowAttached" @@ -65,7 +54,7 @@ Module { Property { name: "activeFocusControl"; type: "QQuickItem"; isReadonly: true; isPointer: true } Property { name: "header"; type: "QQuickItem"; isReadonly: true; isPointer: true } Property { name: "footer"; type: "QQuickItem"; isReadonly: true; isPointer: true } - Property { name: "overlay"; type: "QQuickItem"; isReadonly: true; isPointer: true } + Property { name: "overlay"; type: "QQuickOverlay"; isReadonly: true; isPointer: true } } Component { name: "QQuickBusyIndicator" @@ -261,160 +250,6 @@ Module { Signal { name: "implicitHeightChanged2"; revision: 1 } } Component { - name: "QQuickItem" - defaultProperty: "data" - prototype: "QObject" - Enum { - name: "TransformOrigin" - values: { - "TopLeft": 0, - "Top": 1, - "TopRight": 2, - "Left": 3, - "Center": 4, - "Right": 5, - "BottomLeft": 6, - "Bottom": 7, - "BottomRight": 8 - } - } - Property { name: "parent"; type: "QQuickItem"; isPointer: true } - Property { name: "data"; type: "QObject"; isList: true; isReadonly: true } - Property { name: "resources"; type: "QObject"; isList: true; isReadonly: true } - Property { name: "children"; type: "QQuickItem"; isList: true; isReadonly: true } - Property { name: "x"; type: "double" } - Property { name: "y"; type: "double" } - Property { name: "z"; type: "double" } - Property { name: "width"; type: "double" } - Property { name: "height"; type: "double" } - Property { name: "opacity"; type: "double" } - Property { name: "enabled"; type: "bool" } - Property { name: "visible"; type: "bool" } - Property { name: "visibleChildren"; type: "QQuickItem"; isList: true; isReadonly: true } - Property { name: "states"; type: "QQuickState"; isList: true; isReadonly: true } - Property { name: "transitions"; type: "QQuickTransition"; isList: true; isReadonly: true } - Property { name: "state"; type: "string" } - Property { name: "childrenRect"; type: "QRectF"; isReadonly: true } - Property { name: "anchors"; type: "QQuickAnchors"; isReadonly: true; isPointer: true } - Property { name: "left"; type: "QQuickAnchorLine"; isReadonly: true } - Property { name: "right"; type: "QQuickAnchorLine"; isReadonly: true } - Property { name: "horizontalCenter"; type: "QQuickAnchorLine"; isReadonly: true } - Property { name: "top"; type: "QQuickAnchorLine"; isReadonly: true } - Property { name: "bottom"; type: "QQuickAnchorLine"; isReadonly: true } - Property { name: "verticalCenter"; type: "QQuickAnchorLine"; isReadonly: true } - Property { name: "baseline"; type: "QQuickAnchorLine"; isReadonly: true } - Property { name: "baselineOffset"; type: "double" } - Property { name: "clip"; type: "bool" } - Property { name: "focus"; type: "bool" } - Property { name: "activeFocus"; type: "bool"; isReadonly: true } - Property { name: "activeFocusOnTab"; revision: 1; type: "bool" } - Property { name: "rotation"; type: "double" } - Property { name: "scale"; type: "double" } - Property { name: "transformOrigin"; type: "TransformOrigin" } - Property { name: "transformOriginPoint"; type: "QPointF"; isReadonly: true } - Property { name: "transform"; type: "QQuickTransform"; isList: true; isReadonly: true } - Property { name: "smooth"; type: "bool" } - Property { name: "antialiasing"; type: "bool" } - Property { name: "implicitWidth"; type: "double" } - Property { name: "implicitHeight"; type: "double" } - Property { name: "layer"; type: "QQuickItemLayer"; isReadonly: true; isPointer: true } - Signal { - name: "childrenRectChanged" - Parameter { type: "QRectF" } - } - Signal { - name: "baselineOffsetChanged" - Parameter { type: "double" } - } - Signal { - name: "stateChanged" - Parameter { type: "string" } - } - Signal { - name: "focusChanged" - Parameter { type: "bool" } - } - Signal { - name: "activeFocusChanged" - Parameter { type: "bool" } - } - Signal { - name: "activeFocusOnTabChanged" - revision: 1 - Parameter { type: "bool" } - } - Signal { - name: "parentChanged" - Parameter { type: "QQuickItem"; isPointer: true } - } - Signal { - name: "transformOriginChanged" - Parameter { type: "TransformOrigin" } - } - Signal { - name: "smoothChanged" - Parameter { type: "bool" } - } - Signal { - name: "antialiasingChanged" - Parameter { type: "bool" } - } - Signal { - name: "clipChanged" - Parameter { type: "bool" } - } - Signal { - name: "windowChanged" - revision: 1 - Parameter { name: "window"; type: "QQuickWindow"; isPointer: true } - } - Method { name: "update" } - Method { - name: "grabToImage" - revision: 2 - type: "bool" - Parameter { name: "callback"; type: "QJSValue" } - Parameter { name: "targetSize"; type: "QSize" } - } - Method { - name: "grabToImage" - revision: 2 - type: "bool" - Parameter { name: "callback"; type: "QJSValue" } - } - Method { - name: "contains" - type: "bool" - Parameter { name: "point"; type: "QPointF" } - } - Method { - name: "mapFromItem" - Parameter { type: "QQmlV4Function"; isPointer: true } - } - Method { - name: "mapToItem" - Parameter { type: "QQmlV4Function"; isPointer: true } - } - Method { name: "forceActiveFocus" } - Method { - name: "forceActiveFocus" - Parameter { name: "reason"; type: "Qt::FocusReason" } - } - Method { - name: "nextItemInFocusChain" - revision: 1 - type: "QQuickItem*" - Parameter { name: "forward"; type: "bool" } - } - Method { name: "nextItemInFocusChain"; revision: 1; type: "QQuickItem*" } - Method { - name: "childAt" - type: "QQuickItem*" - Parameter { name: "x"; type: "double" } - Parameter { name: "y"; type: "double" } - } - } - Component { name: "QQuickItemDelegate" defaultProperty: "data" prototype: "QQuickAbstractButton" @@ -438,6 +273,7 @@ Module { exportMetaObjectRevisions: [0] Property { name: "contentModel"; type: "QVariant"; isReadonly: true } Property { name: "contentData"; type: "QObject"; isList: true; isReadonly: true } + Property { name: "title"; type: "string" } Method { name: "itemAt" type: "QQuickItem*" @@ -479,6 +315,17 @@ Module { Signal { name: "released" } } Component { + name: "QQuickPage" + defaultProperty: "contentData" + prototype: "QQuickControl" + exports: ["Qt.labs.templates/Page 1.0"] + exportMetaObjectRevisions: [0] + Property { name: "header"; type: "QQuickItem"; isPointer: true } + Property { name: "footer"; type: "QQuickItem"; isPointer: true } + Property { name: "contentData"; type: "QObject"; isList: true; isReadonly: true } + Property { name: "contentChildren"; type: "QQuickItem"; isList: true; isReadonly: true } + } + Component { name: "QQuickPageIndicator" defaultProperty: "data" prototype: "QQuickControl" @@ -502,18 +349,60 @@ Module { } Component { name: "QQuickPopup" + defaultProperty: "contentData" prototype: "QObject" exports: ["Qt.labs.templates/Popup 1.0"] exportMetaObjectRevisions: [0] + Enum { + name: "ClosePolicy" + values: { + "NoAutoClose": 0, + "CloseOnPressOutside": 1, + "CloseOnReleaseOutside": 2, + "CloseOnEscape": 4 + } + } + Enum { + name: "TransformOrigin" + values: { + "TopLeft": 0, + "Top": 1, + "TopRight": 2, + "Left": 3, + "Center": 4, + "Right": 5, + "BottomLeft": 6, + "Bottom": 7, + "BottomRight": 8 + } + } + Property { name: "x"; type: "double" } + Property { name: "y"; type: "double" } + Property { name: "width"; type: "double" } + Property { name: "height"; type: "double" } + Property { name: "implicitWidth"; type: "double" } + Property { name: "implicitHeight"; type: "double" } + Property { name: "contentWidth"; type: "double" } + Property { name: "contentHeight"; type: "double" } + Property { name: "availableWidth"; type: "double"; isReadonly: true } + Property { name: "availableHeight"; type: "double"; isReadonly: true } + Property { name: "padding"; type: "double" } + Property { name: "topPadding"; type: "double" } + Property { name: "leftPadding"; type: "double" } + Property { name: "rightPadding"; type: "double" } + Property { name: "bottomPadding"; type: "double" } + Property { name: "parent"; type: "QQuickItem"; isPointer: true } + Property { name: "background"; type: "QQuickItem"; isPointer: true } Property { name: "contentItem"; type: "QQuickItem"; isPointer: true } + Property { name: "contentData"; type: "QObject"; isList: true; isReadonly: true } + Property { name: "contentChildren"; type: "QQuickItem"; isList: true; isReadonly: true } Property { name: "focus"; type: "bool" } Property { name: "modal"; type: "bool" } - Property { name: "visible"; type: "bool"; isReadonly: true } + Property { name: "visible"; type: "bool" } + Property { name: "closePolicy"; type: "ClosePolicy" } + Property { name: "transformOrigin"; type: "TransformOrigin" } Property { name: "enter"; type: "QQuickTransition"; isPointer: true } Property { name: "exit"; type: "QQuickTransition"; isPointer: true } - Signal { name: "pressedOutside" } - Signal { name: "releasedOutside" } - Signal { name: "clickedOutside" } Signal { name: "aboutToShow" } Signal { name: "aboutToHide" } Method { name: "open" } @@ -1123,15 +1012,15 @@ Module { } Signal { name: "horizontalAlignmentChanged" - Parameter { name: "alignment"; type: "HAlignment" } + Parameter { name: "alignment"; type: "QQuickTextEdit::HAlignment" } } Signal { name: "verticalAlignmentChanged" - Parameter { name: "alignment"; type: "VAlignment" } + Parameter { name: "alignment"; type: "QQuickTextEdit::VAlignment" } } Signal { name: "textFormatChanged" - Parameter { name: "textFormat"; type: "TextFormat" } + Parameter { name: "textFormat"; type: "QQuickTextEdit::TextFormat" } } Signal { name: "readOnlyChanged" @@ -1164,7 +1053,7 @@ Module { } Signal { name: "mouseSelectionModeChanged" - Parameter { name: "mode"; type: "SelectionMode" } + Parameter { name: "mode"; type: "QQuickTextEdit::SelectionMode" } } Signal { name: "linkActivated" diff --git a/src/templates/qquickabstractbutton.cpp b/src/templates/qquickabstractbutton.cpp index 6c42d7d8..ca727404 100644 --- a/src/templates/qquickabstractbutton.cpp +++ b/src/templates/qquickabstractbutton.cpp @@ -67,21 +67,15 @@ static const int AUTO_REPEAT_INTERVAL = 100; */ /*! - \qmlsignal Qt.labs.controls::AbstractButton::pressed(MouseEvent mouse) + \qmlsignal Qt.labs.controls::AbstractButton::pressed() This signal is emitted when the button is interactively pressed by the user. - - The mouse parameter provides information about the press, including the x - and y position and which button was pressed. */ /*! - \qmlsignal Qt.labs.controls::AbstractButton::released(MouseEvent mouse) + \qmlsignal Qt.labs.controls::AbstractButton::released() This signal is emitted when the button is interactively released by the user. - - The mouse parameter provides information about the click, including the x - and y position of the release of the click, and whether the click was held. */ /*! @@ -93,21 +87,15 @@ static const int AUTO_REPEAT_INTERVAL = 100; */ /*! - \qmlsignal Qt.labs.controls::AbstractButton::clicked(MouseEvent mouse) + \qmlsignal Qt.labs.controls::AbstractButton::clicked() This signal is emitted when the button is interactively clicked by the user. - - The mouse parameter provides information about the click, including the x - and y position of the release of the click, and whether the click was held. */ /*! - \qmlsignal Qt.labs.controls::AbstractButton::doubleClicked(MouseEvent mouse) + \qmlsignal Qt.labs.controls::AbstractButton::doubleClicked() This signal is emitted when the button is interactively double clicked by the user. - - The mouse parameter provides information about the click, including the x - and y position of the release of the click, and whether the click was held. */ QQuickAbstractButtonPrivate::QQuickAbstractButtonPrivate() : @@ -462,9 +450,7 @@ void QQuickAbstractButton::keyPressEvent(QKeyEvent *event) d->repeatButton = Qt::NoButton; } - QQuickMouseEvent me(d->pressPoint.x(), d->pressPoint.y(), Qt::NoButton, QGuiApplication::mouseButtons(), event->modifiers()); - emit pressed(&me); - event->setAccepted(me.isAccepted()); + emit pressed(); } } @@ -475,12 +461,9 @@ void QQuickAbstractButton::keyReleaseEvent(QKeyEvent *event) if (event->key() == Qt::Key_Space) { setPressed(false); - QQuickMouseEvent mre(d->pressPoint.x(), d->pressPoint.y(), Qt::NoButton, QGuiApplication::mouseButtons(), event->modifiers()); - emit released(&mre); - QQuickMouseEvent mce(d->pressPoint.x(), d->pressPoint.y(), Qt::NoButton, QGuiApplication::mouseButtons(), event->modifiers(), true /* isClick */); - emit clicked(&mce); + emit released(); + emit clicked(); nextCheckState(); - event->setAccepted(mre.isAccepted() || mce.isAccepted()); if (d->autoRepeat) d->stopPressRepeat(); @@ -494,9 +477,7 @@ void QQuickAbstractButton::mousePressEvent(QMouseEvent *event) setPressed(true); d->pressPoint = event->pos(); - QQuickMouseEvent me(event->x(), event->y(), event->button(), event->buttons(), event->modifiers()); - emit pressed(&me); - event->setAccepted(me.isAccepted()); + emit pressed(); if (d->autoRepeat) { d->startRepeatDelay(); @@ -522,11 +503,8 @@ void QQuickAbstractButton::mouseReleaseEvent(QMouseEvent *event) setPressed(false); if (wasPressed) { - QQuickMouseEvent mre(event->x(), event->y(), event->button(), event->buttons(), event->modifiers()); - emit released(&mre); - QQuickMouseEvent mce(event->x(), event->y(), event->button(), event->buttons(), event->modifiers(), true /* isClick */); - emit clicked(&mce); - event->setAccepted(mre.isAccepted() || mce.isAccepted()); + emit released(); + emit clicked(); } else { emit canceled(); } @@ -541,10 +519,7 @@ void QQuickAbstractButton::mouseReleaseEvent(QMouseEvent *event) void QQuickAbstractButton::mouseDoubleClickEvent(QMouseEvent *event) { QQuickControl::mouseDoubleClickEvent(event); - - QQuickMouseEvent me(event->x(), event->y(), event->button(), event->buttons(), event->modifiers(), true /* isClick */); - emit doubleClicked(&me); - event->setAccepted(me.isAccepted()); + emit doubleClicked(); } void QQuickAbstractButton::mouseUngrabEvent() @@ -565,12 +540,9 @@ void QQuickAbstractButton::timerEvent(QTimerEvent *event) if (event->timerId() == d->delayTimer) { d->startPressRepeat(); } else if (event->timerId() == d->repeatTimer) { - QQuickMouseEvent mre(d->pressPoint.x(), d->pressPoint.y(), d->repeatButton, QGuiApplication::mouseButtons(), QGuiApplication::keyboardModifiers()); - emit released(&mre); - QQuickMouseEvent mce(d->pressPoint.x(), d->pressPoint.y(), d->repeatButton, QGuiApplication::mouseButtons(), QGuiApplication::keyboardModifiers(), true /* isClick */); - emit clicked(&mce); - QQuickMouseEvent mpe(d->pressPoint.x(), d->pressPoint.y(), d->repeatButton, QGuiApplication::mouseButtons(), QGuiApplication::keyboardModifiers()); - emit pressed(&mpe); + emit released(); + emit clicked(); + emit pressed(); } } diff --git a/src/templates/qquickabstractbutton_p.h b/src/templates/qquickabstractbutton_p.h index 9c0ba134..b50f5ec7 100644 --- a/src/templates/qquickabstractbutton_p.h +++ b/src/templates/qquickabstractbutton_p.h @@ -52,7 +52,6 @@ QT_BEGIN_NAMESPACE -class QQuickMouseEvent; class QQuickAbstractButtonPrivate; class Q_LABSTEMPLATES_EXPORT QQuickAbstractButton : public QQuickControl @@ -103,11 +102,11 @@ public Q_SLOTS: void toggle(); Q_SIGNALS: - void pressed(QQuickMouseEvent *mouse); - void released(QQuickMouseEvent *mouse); + void pressed(); + void released(); void canceled(); - void clicked(QQuickMouseEvent *mouse); - void doubleClicked(QQuickMouseEvent *mouse); + void clicked(); + void doubleClicked(); void textChanged(); void pressedChanged(); void checkedChanged(); diff --git a/src/templates/qquickapplicationwindow.cpp b/src/templates/qquickapplicationwindow.cpp index c6183fce..96087fc9 100644 --- a/src/templates/qquickapplicationwindow.cpp +++ b/src/templates/qquickapplicationwindow.cpp @@ -464,6 +464,13 @@ bool QQuickApplicationWindow::isComponentComplete() const return d->complete; } +void QQuickApplicationWindow::classBegin() +{ + Q_D(QQuickApplicationWindow); + QQuickWindowQmlImpl::classBegin(); + d->resolveFont(); +} + void QQuickApplicationWindow::componentComplete() { Q_D(QQuickApplicationWindow); diff --git a/src/templates/qquickapplicationwindow_p.h b/src/templates/qquickapplicationwindow_p.h index f1410344..960e5714 100644 --- a/src/templates/qquickapplicationwindow_p.h +++ b/src/templates/qquickapplicationwindow_p.h @@ -109,6 +109,7 @@ Q_SIGNALS: protected: bool isComponentComplete() const; + void classBegin() override; void componentComplete() override; void resizeEvent(QResizeEvent *event) override; diff --git a/src/templates/qquickcombobox.cpp b/src/templates/qquickcombobox.cpp index 3283a46e..a8c66ce6 100644 --- a/src/templates/qquickcombobox.cpp +++ b/src/templates/qquickcombobox.cpp @@ -119,13 +119,43 @@ QT_BEGIN_NAMESPACE \sa highlightedIndex */ +class QQuickComboBoxDelegateModel : public QQmlDelegateModel +{ +public: + explicit QQuickComboBoxDelegateModel(QQuickComboBox *combo); + QString stringValue(int index, const QString &role) override; + +private: + QQuickComboBox *combo; +}; + +QQuickComboBoxDelegateModel::QQuickComboBoxDelegateModel(QQuickComboBox *combo) : + QQmlDelegateModel(qmlContext(combo), combo), combo(combo) +{ +} + +QString QQuickComboBoxDelegateModel::stringValue(int index, const QString &role) +{ + QVariant model = combo->model(); + if (model.userType() == QMetaType::QVariantList) { + QVariant object = model.toList().value(index); + if (object.userType() == QMetaType::QVariantMap) { + QVariantMap data = object.toMap(); + if (data.count() == 1 && role == QLatin1String("modelData")) + return data.first().toString(); + return data.value(role).toString(); + } + } + return QQmlDelegateModel::stringValue(index, role); +} + class QQuickComboBoxPrivate : public QQuickControlPrivate { Q_DECLARE_PUBLIC(QQuickComboBox) public: QQuickComboBoxPrivate() : pressed(false), ownModel(false), hasDisplayText(false), - hideTimer(0), highlightedIndex(-1), currentIndex(-1), delegateModel(nullptr), + highlightedIndex(-1), currentIndex(-1), delegateModel(nullptr), delegate(nullptr), popup(nullptr) { } bool isPopupVisible() const; @@ -133,7 +163,6 @@ public: void hidePopup(bool accept); void togglePopup(bool accept); - void pressedOutside(); void itemClicked(); void initItem(int index, QObject *object); @@ -148,7 +177,6 @@ public: bool pressed; bool ownModel; bool hasDisplayText; - int hideTimer; int highlightedIndex; int currentIndex; QVariant model; @@ -196,13 +224,6 @@ void QQuickComboBoxPrivate::togglePopup(bool accept) showPopup(); } -void QQuickComboBoxPrivate::pressedOutside() -{ - Q_Q(QQuickComboBox); - if (hideTimer <= 0) - hideTimer = q->startTimer(0); -} - void QQuickComboBoxPrivate::itemClicked() { Q_Q(QQuickComboBox); @@ -302,7 +323,7 @@ void QQuickComboBoxPrivate::createDelegateModel() delegateModel = model.value<QQmlInstanceModel *>(); if (!delegateModel && model.isValid()) { - QQmlDelegateModel *dataModel = new QQmlDelegateModel(qmlContext(q), q); + QQmlDelegateModel *dataModel = new QQuickComboBoxDelegateModel(q); dataModel->setModel(model); dataModel->setDelegate(delegate); if (q->isComponentComplete()) @@ -589,7 +610,7 @@ void QQuickComboBox::setPopup(QQuickPopup *popup) if (d->popup != popup) { delete d->popup; if (popup) - QObjectPrivate::connect(popup, &QQuickPopup::pressedOutside, d, &QQuickComboBoxPrivate::pressedOutside); + popup->setClosePolicy(QQuickPopup::OnEscape | QQuickPopup::OnPressOutsideParent); d->popup = popup; emit popupChanged(); } @@ -709,8 +730,6 @@ void QQuickComboBox::keyPressEvent(QKeyEvent *event) d->increase(); event->accept(); break; - case Qt::Key_Escape: - event->accept(); default: break; } @@ -775,18 +794,6 @@ void QQuickComboBox::mouseUngrabEvent() setPressed(false); } -void QQuickComboBox::timerEvent(QTimerEvent *event) -{ - Q_D(QQuickComboBox); - QQuickControl::timerEvent(event); - if (event->timerId() == d->hideTimer) { - killTimer(d->hideTimer); - d->hideTimer = 0; - if (!d->pressed) - d->hidePopup(false); - } -} - void QQuickComboBox::componentComplete() { Q_D(QQuickComboBox); diff --git a/src/templates/qquickcombobox_p.h b/src/templates/qquickcombobox_p.h index 3381791e..431dccb0 100644 --- a/src/templates/qquickcombobox_p.h +++ b/src/templates/qquickcombobox_p.h @@ -131,7 +131,6 @@ protected: void mouseMoveEvent(QMouseEvent *event) override; void mouseReleaseEvent(QMouseEvent *event) override; void mouseUngrabEvent() override; - void timerEvent(QTimerEvent *event) override; void componentComplete() override; diff --git a/src/templates/qquickitemdelegate.cpp b/src/templates/qquickitemdelegate.cpp index f25a117f..98364fad 100644 --- a/src/templates/qquickitemdelegate.cpp +++ b/src/templates/qquickitemdelegate.cpp @@ -35,6 +35,9 @@ ****************************************************************************/ #include "qquickitemdelegate_p.h" +#include "qquickcontrol_p_p.h" + +#include <QtGui/qpa/qplatformtheme.h> QT_BEGIN_NAMESPACE @@ -63,6 +66,11 @@ QQuickItemDelegate::QQuickItemDelegate(QQuickItem *parent) : QQuickAbstractButto { } +QFont QQuickItemDelegate::defaultFont() const +{ + return QQuickControlPrivate::themeFont(QPlatformTheme::ItemViewFont); +} + #ifndef QT_NO_ACCESSIBILITY QAccessible::Role QQuickItemDelegate::accessibleRole() const { diff --git a/src/templates/qquickitemdelegate_p.h b/src/templates/qquickitemdelegate_p.h index be293047..24d90c20 100644 --- a/src/templates/qquickitemdelegate_p.h +++ b/src/templates/qquickitemdelegate_p.h @@ -62,6 +62,8 @@ public: explicit QQuickItemDelegate(QQuickItem *parent = nullptr); protected: + QFont defaultFont() const override; + #ifndef QT_NO_ACCESSIBILITY QAccessible::Role accessibleRole() const override; #endif diff --git a/src/templates/qquickmenu.cpp b/src/templates/qquickmenu.cpp index beda1489..7aeebd2f 100644 --- a/src/templates/qquickmenu.cpp +++ b/src/templates/qquickmenu.cpp @@ -68,19 +68,20 @@ QT_BEGIN_NAMESPACE id: fileButton text: "File" onClicked: menu.open() - } - Menu { - id: menu - contentItem.y: fileButton.height - MenuItem { - text: "New..." - } - MenuItem { - text: "Open..." - } - MenuItem { - text: "Save" + Menu { + id: menu + y: fileButton.height + + MenuItem { + text: "New..." + } + MenuItem { + text: "Open..." + } + MenuItem { + text: "Save" + } } } \endcode @@ -301,8 +302,7 @@ QQuickMenu::QQuickMenu(QObject *parent) : QQuickPopup(*(new QQuickMenuPrivate), parent) { Q_D(QQuickMenu); - connect(this, &QQuickMenu::pressedOutside, this, &QQuickMenu::close); - connect(this, &QQuickMenu::releasedOutside, this, &QQuickMenu::close); + setClosePolicy(OnEscape | OnPressOutside | OnReleaseOutside); QObjectPrivate::connect(this, &QQuickMenu::visibleChanged, d, &QQuickMenuPrivate::onMenuVisibleChanged); } @@ -513,10 +513,6 @@ bool QQuickMenu::eventFilter(QObject *object, QEvent *event) QMetaObject::invokeMethod(d->contentItem, "incrementCurrentIndex"); return true; - case Qt::Key_Escape: - close(); - return true; - default: break; } diff --git a/src/templates/qquickoverlay.cpp b/src/templates/qquickoverlay.cpp index 8b19e8e9..23895d9c 100644 --- a/src/templates/qquickoverlay.cpp +++ b/src/templates/qquickoverlay.cpp @@ -52,6 +52,7 @@ public: void popupAboutToShow(); void popupAboutToHide(); + void closePopup(QQuickPopup *popup, QMouseEvent *event); void drawerPositionChange(); void resizeBackground(); @@ -89,6 +90,30 @@ void QQuickOverlayPrivate::popupAboutToHide() QQmlProperty::write(background, QStringLiteral("opacity"), 0.0); } +void QQuickOverlayPrivate::closePopup(QQuickPopup *popup, QMouseEvent *event) +{ + Q_Q(QQuickOverlay); + const bool isPress = event->type() == QEvent::MouseButtonPress; + const bool onOutside = popup->closePolicy().testFlag(isPress ? QQuickPopup::OnPressOutside : QQuickPopup::OnReleaseOutside); + const bool onOutsideParent = popup->closePolicy().testFlag(isPress ? QQuickPopup::OnPressOutsideParent : QQuickPopup::OnReleaseOutsideParent); + if (onOutside || onOutsideParent) { + QQuickItem *popupItem = popup->popupItem(); + QQuickItem *parentItem = popup->parentItem(); + + if (onOutside && onOutsideParent) { + if (!popupItem->contains(q->mapToItem(popupItem, event->pos())) && + (!parentItem || !parentItem->contains(q->mapToItem(parentItem, event->pos())))) + popup->close(); + } else if (onOutside) { + if (!popupItem->contains(q->mapToItem(popupItem, event->pos()))) + popup->close(); + } else if (onOutsideParent) { + if (!parentItem || !parentItem->contains(q->mapToItem(parentItem, event->pos()))) + popup->close(); + } + } +} + void QQuickOverlayPrivate::drawerPositionChange() { Q_Q(QQuickOverlay); @@ -182,15 +207,11 @@ void QQuickOverlay::itemChange(ItemChange change, const ItemChangeData &data) if (popup->isModal()) ++d->modalPopups; - connect(this, &QQuickOverlay::pressed, popup, &QQuickPopup::pressedOutside); - connect(this, &QQuickOverlay::released, popup, &QQuickPopup::releasedOutside); QObjectPrivate::connect(popup, &QQuickPopup::aboutToShow, d, &QQuickOverlayPrivate::popupAboutToShow); QObjectPrivate::connect(popup, &QQuickPopup::aboutToHide, d, &QQuickOverlayPrivate::popupAboutToHide); } else if (change == ItemChildRemovedChange) { Q_ASSERT(popup == d->popups.value(data.item)); - disconnect(this, &QQuickOverlay::pressed, popup, &QQuickPopup::pressedOutside); - disconnect(this, &QQuickOverlay::released, popup, &QQuickPopup::releasedOutside); QObjectPrivate::disconnect(popup, &QQuickPopup::aboutToShow, d, &QQuickOverlayPrivate::popupAboutToShow); QObjectPrivate::disconnect(popup, &QQuickPopup::aboutToHide, d, &QQuickOverlayPrivate::popupAboutToHide); @@ -225,6 +246,9 @@ void QQuickOverlay::mousePressEvent(QMouseEvent *event) Q_D(QQuickOverlay); event->setAccepted(d->modalPopups > 0); emit pressed(); + + foreach (QQuickPopup *popup, d->popups) + d->closePopup(popup, event); } void QQuickOverlay::mouseMoveEvent(QMouseEvent *event) @@ -238,6 +262,9 @@ void QQuickOverlay::mouseReleaseEvent(QMouseEvent *event) Q_D(QQuickOverlay); event->setAccepted(d->modalPopups > 0); emit released(); + + foreach (QQuickPopup *popup, d->popups) + d->closePopup(popup, event); } void QQuickOverlay::wheelEvent(QWheelEvent *event) @@ -267,7 +294,9 @@ bool QQuickOverlay::childMouseEventFilter(QQuickItem *item, QEvent *event) QQuickPopup *popup = d->popups.value(popupItem); if (popup) { - emit popup->pressedOutside(); + QQuickPopup::ClosePolicy policy = popup->closePolicy(); + if (policy.testFlag(QQuickPopup::OnPressOutside) || policy.testFlag(QQuickPopup::OnPressOutsideParent)) + popup->close(); if (!modalBlocked && popup->isModal()) modalBlocked = true; diff --git a/src/templates/qquickpopup.cpp b/src/templates/qquickpopup.cpp index 93e5a63a..ea74743a 100644 --- a/src/templates/qquickpopup.cpp +++ b/src/templates/qquickpopup.cpp @@ -82,6 +82,7 @@ QQuickPopupPrivate::QQuickPopupPrivate() , bottomPadding(0) , contentWidth(0) , contentHeight(0) + , closePolicy(QQuickPopup::OnEscape) , parentItem(nullptr) , background(nullptr) , contentItem(nullptr) @@ -502,6 +503,7 @@ QQuickPopup::~QQuickPopup() { Q_D(QQuickPopup); d->positioner.setParentItem(nullptr); + delete d->popupItem; } /*! @@ -545,9 +547,6 @@ void QQuickPopup::open() d->overlay = static_cast<QQuickOverlay *>(applicationWindow->overlay()); d->popupItem->setParentItem(d->overlay); d->positioner.setParentItem(d->parentItem); - // TODO: add Popup::transformOrigin? - if (d->contentItem) - d->popupItem->setTransformOrigin(d->contentItem->transformOrigin()); emit aboutToShow(); d->transitionManager.transitionEnter(); emit visibleChanged(); @@ -907,6 +906,12 @@ void QQuickPopup::resetBottomPadding() d->setBottomPadding(0, true); } +QQuickItem *QQuickPopup::popupItem() const +{ + Q_D(const QQuickPopup); + return d->popupItem; +} + /*! \qmlproperty Item Qt.labs.popups::Popup::parent @@ -1094,6 +1099,62 @@ void QQuickPopup::setVisible(bool visible) } /*! + \qmlproperty enumeration Qt.labs.controls::Popup::closePolicy + + This property determines the circumstances under which the popup closes. + The flags can be combined to allow several ways of closing the popup. + + The available values are: + \value Popup.NoAutoClose The popup will only close when manually instructed to do so. + \value Popup.OnPressOutside The popup will close when the mouse is pressed outside of it. + \value Popup.OnPressOutsideParent The popup will close when the mouse is pressed outside of its parent. + \value Popup.OnReleaseOutside The popup will close when the mouse is released outside of it. + \value Popup.OnReleaseOutsideParent The popup will close when the mouse is released outside of its parent. + \value Popup.OnEscape The popup will close when the escape key is pressed while the popup + has active focus. + + The default value is \c Popup.OnEscape. +*/ +QQuickPopup::ClosePolicy QQuickPopup::closePolicy() const +{ + Q_D(const QQuickPopup); + return d->closePolicy; +} + +void QQuickPopup::setClosePolicy(ClosePolicy policy) +{ + Q_D(QQuickPopup); + if (d->closePolicy == policy) + return; + d->closePolicy = policy; + emit closePolicyChanged(); +} + +/*! + \qmlproperty enumeration Qt.labs.controls::Popup::transformOrigin + + This property holds the origin point for transformations in enter and exit transitions. + + Nine transform origins are available, as shown in the image below. + The default transform origin is \c Popup.Center. + + \image qtlabscontrols-popup-transformorigin.png + + \sa enter, exit, Item::transformOrigin +*/ +QQuickPopup::TransformOrigin QQuickPopup::transformOrigin() const +{ + Q_D(const QQuickPopup); + return static_cast<TransformOrigin>(d->popupItem->transformOrigin()); +} + +void QQuickPopup::setTransformOrigin(TransformOrigin origin) +{ + Q_D(QQuickPopup); + d->popupItem->setTransformOrigin(static_cast<QQuickItem::TransformOrigin>(origin)); +} + +/*! \qmlproperty Transition Qt.labs.controls::Popup::enter This property holds the transition that is applied to the content item @@ -1165,7 +1226,14 @@ void QQuickPopup::focusOutEvent(QFocusEvent *event) void QQuickPopup::keyPressEvent(QKeyEvent *event) { + Q_D(QQuickPopup); event->accept(); + + if (event->key() != Qt::Key_Escape) + return; + + if (d->closePolicy.testFlag(OnEscape)) + close(); } void QQuickPopup::keyReleaseEvent(QKeyEvent *event) diff --git a/src/templates/qquickpopup_p.h b/src/templates/qquickpopup_p.h index e94b63f1..233978c8 100644 --- a/src/templates/qquickpopup_p.h +++ b/src/templates/qquickpopup_p.h @@ -90,6 +90,8 @@ class Q_LABSTEMPLATES_EXPORT QQuickPopup : public QObject, public QQmlParserStat Q_PROPERTY(bool focus READ hasFocus WRITE setFocus NOTIFY focusChanged) Q_PROPERTY(bool modal READ isModal WRITE setModal NOTIFY modalChanged) Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY visibleChanged) + Q_PROPERTY(ClosePolicy closePolicy READ closePolicy WRITE setClosePolicy NOTIFY closePolicyChanged FINAL) + Q_PROPERTY(TransformOrigin transformOrigin READ transformOrigin WRITE setTransformOrigin) Q_PROPERTY(QQuickTransition *enter READ enter WRITE setEnter NOTIFY enterChanged FINAL) Q_PROPERTY(QQuickTransition *exit READ exit WRITE setExit NOTIFY exitChanged FINAL) Q_CLASSINFO("DefaultProperty", "contentData") @@ -147,6 +149,8 @@ public: void setBottomPadding(qreal padding); void resetBottomPadding(); + QQuickItem *popupItem() const; + QQuickItem *parentItem() const; void setParentItem(QQuickItem *parent); @@ -168,6 +172,31 @@ public: bool isVisible() const; void setVisible(bool visible); + enum ClosePolicyFlag { + NoAutoClose = 0x00, + OnPressOutside = 0x01, + OnPressOutsideParent = 0x02, + OnReleaseOutside = 0x04, + OnReleaseOutsideParent = 0x08, + OnEscape = 0x10 + }; + Q_DECLARE_FLAGS(ClosePolicy, ClosePolicyFlag) + Q_FLAG(ClosePolicy) + + ClosePolicy closePolicy() const; + void setClosePolicy(ClosePolicy policy); + + // keep in sync with Item.TransformOrigin + enum TransformOrigin { + TopLeft, Top, TopRight, + Left, Center, Right, + BottomLeft, Bottom, BottomRight + }; + Q_ENUM(TransformOrigin) + + TransformOrigin transformOrigin() const; + void setTransformOrigin(TransformOrigin); + QQuickTransition *enter() const; void setEnter(QQuickTransition *transition); @@ -201,13 +230,10 @@ Q_SIGNALS: void focusChanged(); void modalChanged(); void visibleChanged(); + void closePolicyChanged(); void enterChanged(); void exitChanged(); - void pressedOutside(); - void releasedOutside(); - void clickedOutside(); - void aboutToShow(); void aboutToHide(); @@ -239,6 +265,8 @@ private: friend class QQuickPopupItem; }; +Q_DECLARE_OPERATORS_FOR_FLAGS(QQuickPopup::ClosePolicy) + QT_END_NAMESPACE QML_DECLARE_TYPE(QQuickPopup) diff --git a/src/templates/qquickpopup_p_p.h b/src/templates/qquickpopup_p_p.h index 910fca9e..5817cbd5 100644 --- a/src/templates/qquickpopup_p_p.h +++ b/src/templates/qquickpopup_p_p.h @@ -183,6 +183,7 @@ public: qreal bottomPadding; qreal contentWidth; qreal contentHeight; + QQuickPopup::ClosePolicy closePolicy; QQuickItem *parentItem; QQuickItem *background; QQuickItem *contentItem; diff --git a/src/templates/qquickswitch.cpp b/src/templates/qquickswitch.cpp index 8544d7ca..f5c1a605 100644 --- a/src/templates/qquickswitch.cpp +++ b/src/templates/qquickswitch.cpp @@ -139,9 +139,8 @@ bool QQuickSwitchPrivate::handleMouseReleaseEvent(QQuickItem *child, QMouseEvent child->setKeepMouseGrab(false); event->accept(); } else { - QQuickMouseEvent me(event->x(), event->y(), event->button(), event->buttons(), event->modifiers(), true /* isClick */); - emit q->clicked(&me); - event->setAccepted(me.isAccepted()); + emit q->clicked(); + event->accept(); q->toggle(); } return true; diff --git a/tests/auto/applicationwindow/applicationwindow.pro b/tests/auto/applicationwindow/applicationwindow.pro index 5a664b63..eabe81bf 100644 --- a/tests/auto/applicationwindow/applicationwindow.pro +++ b/tests/auto/applicationwindow/applicationwindow.pro @@ -4,7 +4,7 @@ SOURCES += tst_applicationwindow.cpp osx:CONFIG -= app_bundle -QT += core-private gui-private qml-private quick-private labstemplates-private testlib +QT += core-private gui-private qml-private quick-private labstemplates-private labscontrols-private testlib include (../shared/util.pri) diff --git a/tests/auto/applicationwindow/tst_applicationwindow.cpp b/tests/auto/applicationwindow/tst_applicationwindow.cpp index 11d45182..4b392e99 100644 --- a/tests/auto/applicationwindow/tst_applicationwindow.cpp +++ b/tests/auto/applicationwindow/tst_applicationwindow.cpp @@ -41,12 +41,14 @@ #include <QtQml/qqmlcontext.h> #include <QtQuick/qquickview.h> #include <QtQuick/private/qquickitem_p.h> +#include <QtGui/private/qguiapplication_p.h> #include <QtLabsTemplates/private/qquickapplicationwindow_p.h> #include <QtLabsTemplates/private/qquickoverlay_p.h> #include <QtLabsTemplates/private/qquickcontrol_p.h> #include <QtLabsTemplates/private/qquicklabel_p.h> #include <QtLabsTemplates/private/qquicktextarea_p.h> #include <QtLabsTemplates/private/qquicktextfield_p.h> +#include <QtLabsControls/private/qquickproxytheme_p.h> #include "../shared/util.h" #include "../shared/visualtestutil.h" @@ -65,6 +67,7 @@ private slots: void implicitFill(); void attachedProperties(); void font(); + void defaultFont(); void locale(); void activeFocusControl_data(); void activeFocusControl(); @@ -492,6 +495,36 @@ void tst_applicationwindow::font() QCOMPARE(item6->font(), font); } +class TestTheme : public QQuickProxyTheme +{ +public: + TestTheme(QPlatformTheme *theme) : QQuickProxyTheme(theme), m_font("Courier") + { QGuiApplicationPrivate::platform_theme = this; } + ~TestTheme() { QGuiApplicationPrivate::platform_theme = theme(); } + + const QFont *font(Font type = SystemFont) const override + { + Q_UNUSED(type); + return &m_font; + } + + QFont m_font; +}; + +void tst_applicationwindow::defaultFont() +{ + TestTheme theme(QGuiApplicationPrivate::platform_theme); + + QQmlEngine engine; + QQmlComponent component(&engine); + component.setData("import Qt.labs.controls 1.0; ApplicationWindow { }", QUrl()); + + QScopedPointer<QQuickApplicationWindow> window; + window.reset(static_cast<QQuickApplicationWindow *>(component.create())); + QVERIFY(!window.isNull()); + QCOMPARE(window->font(), *theme.font()); +} + void tst_applicationwindow::locale() { QQmlEngine engine; diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro index 3b3ee04a..ec9d4111 100644 --- a/tests/auto/auto.pro +++ b/tests/auto/auto.pro @@ -7,6 +7,7 @@ SUBDIRS += \ controls \ material \ menu \ + popup \ pressandhold \ sanity \ snippets \ diff --git a/tests/auto/controls/data/tst_button.qml b/tests/auto/controls/data/tst_button.qml index 1faf1956..45fad8cb 100644 --- a/tests/auto/controls/data/tst_button.qml +++ b/tests/auto/controls/data/tst_button.qml @@ -163,86 +163,10 @@ TestCase { control.destroy() } - Component { - id: eventButton - Button { - property var lastPress - property var lastRelease - property var lastClick - property var lastDoubleClick - - function reset() { - lastPress = undefined - lastRelease = undefined - lastClick = undefined - lastDoubleClick = undefined - } - - onPressed: { lastPress = { x: mouse.x, y: mouse.y, button: mouse.button, buttons: mouse.buttons, modifiers: mouse.modifiers, wasHeld: mouse.wasHeld, isClick: mouse.isClick } } - onReleased: { lastRelease = { x: mouse.x, y: mouse.y, button: mouse.button, buttons: mouse.buttons, modifiers: mouse.modifiers, wasHeld: mouse.wasHeld, isClick: mouse.isClick } } - onClicked: { lastClick = { x: mouse.x, y: mouse.y, button: mouse.button, buttons: mouse.buttons, modifiers: mouse.modifiers, wasHeld: mouse.wasHeld, isClick: mouse.isClick } } - onDoubleClicked: { lastDoubleClick = { x: mouse.x, y: mouse.y, button: mouse.button, buttons: mouse.buttons, modifiers: mouse.modifiers, wasHeld: mouse.wasHeld, isClick: mouse.isClick } } - } - } - function eventErrorMessage(actual, expected) { return "actual event:" + JSON.stringify(actual) + ", expected event:" + JSON.stringify(expected) } - function test_events() { - var control = eventButton.createObject(testCase) - verify(control) - - control.forceActiveFocus() - verify(control.activeFocus) - - mousePress(control, control.width / 2, control.height / 2, Qt.LeftButton) - var expected = { x: Math.round(control.width / 2), y: Math.round(control.height / 2), button: Qt.LeftButton, buttons: Qt.LeftButton, modifiers: Qt.NoModifier, wasHeld: false, isClick: false } - compare(control.lastPress, expected, eventErrorMessage(control.lastPress, expected)) - compare(control.lastRelease, undefined) - compare(control.lastClick, undefined) - compare(control.lastDoubleClick, undefined) - - control.reset() - - mouseMove(control, control.width / 3, control.height / 3, Qt.LeftButton) - compare(control.lastPress, undefined) - compare(control.lastRelease, undefined) - compare(control.lastClick, undefined) - compare(control.lastDoubleClick, undefined) - - control.reset() - - mouseRelease(control, control.width / 4, control.height / 4, Qt.LeftButton) - compare(control.lastPress, undefined) - expected = { x: Math.round(control.width / 4), y: Math.round(control.height / 4), button: Qt.LeftButton, buttons: Qt.NoButton, modifiers: Qt.NoModifier, wasHeld: false, isClick: false } - compare(control.lastRelease, expected, eventErrorMessage(control.lastRelease, expected)) - expected = { x: Math.round(control.width / 4), y: Math.round(control.height / 4), button: Qt.LeftButton, buttons: Qt.NoButton, modifiers: Qt.NoModifier, wasHeld: false, isClick: true } - compare(control.lastClick, expected, eventErrorMessage(control.lastClick, expected)) - compare(control.lastDoubleClick, undefined) - - control.reset() - - keyPress(Qt.Key_Space) - expected = { x: Math.round(control.width / 2), y: Math.round(control.height / 2), button: Qt.NoButton, buttons: Qt.NoButton, modifiers: Qt.NoModifier, wasHeld: false, isClick: false } - compare(control.lastPress, expected, eventErrorMessage(control.lastPress, expected)) - compare(control.lastRelease, undefined) - compare(control.lastClick, undefined) - compare(control.lastDoubleClick, undefined) - - control.reset() - - keyRelease(Qt.Key_Space) - compare(control.lastPress, undefined) - expected = { x: Math.round(control.width / 2), y: Math.round(control.height / 2), button: Qt.NoButton, buttons: Qt.NoButton, modifiers: Qt.NoModifier, wasHeld: false, isClick: false } - compare(control.lastRelease, expected, eventErrorMessage(control.lastRelease, expected)) - expected = { x: Math.round(control.width / 2), y: Math.round(control.height / 2), button: Qt.NoButton, buttons: Qt.NoButton, modifiers: Qt.NoModifier, wasHeld: false, isClick: true } - compare(control.lastClick, expected, eventErrorMessage(control.lastClick, expected)) - compare(control.lastDoubleClick, undefined) - - control.destroy() - } - SignalSpy { id: clickSpy; signalName: "clicked" } function test_autoRepeat() { diff --git a/tests/auto/controls/data/tst_combobox.qml b/tests/auto/controls/data/tst_combobox.qml index d74c52aa..55ac3e8d 100644 --- a/tests/auto/controls/data/tst_combobox.qml +++ b/tests/auto/controls/data/tst_combobox.qml @@ -69,7 +69,7 @@ TestCase { id: comboBox ComboBox { delegate: ItemDelegate { - width: parent.width + width: popup.width } } } @@ -137,6 +137,36 @@ TestCase { control.destroy() } + function test_objects() { + var control = comboBox.createObject(window.contentItem) + verify(control) + + var items = [ + { text: "Apple" }, + { text: "Orange" }, + { text: "Banana" } + ] + + control.model = items + compare(control.model, items) + + compare(control.count, 3) + compare(control.currentIndex, 0) + compare(control.currentText, "Apple") + + control.currentIndex = 2 + compare(control.currentIndex, 2) + compare(control.currentText, "Banana") + + control.model = null + compare(control.model, null) + compare(control.count, 0) + compare(control.currentIndex, -1) + compare(control.currentText, "") + + control.destroy() + } + function test_number() { var control = comboBox.createObject(window.contentItem) verify(control) @@ -201,11 +231,24 @@ TestCase { ListElement { name: "Banana"; color: "yellow" } } - function test_textRole() { + property var fruitarray: [ + { name: "Apple", color: "red" }, + { name: "Orange", color: "orange" }, + { name: "Banana", color: "yellow" } + ] + + function test_textRole_data() { + return [ + { tag: "ListModel", model: fruitmodel }, + { tag: "ObjectArray", model: fruitarray } + ] + } + + function test_textRole(data) { var control = comboBox.createObject(window.contentItem) verify(control) - control.model = fruitmodel + control.model = data.model compare(control.count, 3) compare(control.currentIndex, 0) compare(control.currentText, "") diff --git a/tests/auto/controls/data/tst_frame.qml b/tests/auto/controls/data/tst_frame.qml index feb6cf11..d50a0dfc 100644 --- a/tests/auto/controls/data/tst_frame.qml +++ b/tests/auto/controls/data/tst_frame.qml @@ -57,7 +57,7 @@ TestCase { Component { id: oneChildFrame - GroupBox { + Frame { Item { implicitWidth: 100 implicitHeight: 30 @@ -67,7 +67,7 @@ TestCase { Component { id: twoChildrenFrame - GroupBox { + Frame { Item { implicitWidth: 100 implicitHeight: 30 @@ -79,6 +79,16 @@ TestCase { } } + Component { + id: contentFrame + Frame { + contentItem: Item { + implicitWidth: 100 + implicitHeight: 30 + } + } + } + function test_empty() { var control = frame.createObject(testCase) verify(control) @@ -113,4 +123,16 @@ TestCase { control.destroy() } + + function test_contentItem() { + var control = contentFrame.createObject(testCase) + verify(control) + + compare(control.contentWidth, 100) + compare(control.contentHeight, 30) + verify(control.implicitWidth > 100) + verify(control.implicitHeight > 30) + + control.destroy() + } } diff --git a/tests/auto/controls/data/tst_groupbox.qml b/tests/auto/controls/data/tst_groupbox.qml index 55568923..0f0e33fb 100644 --- a/tests/auto/controls/data/tst_groupbox.qml +++ b/tests/auto/controls/data/tst_groupbox.qml @@ -79,6 +79,16 @@ TestCase { } } + Component { + id: contentBox + GroupBox { + contentItem: Item { + implicitWidth: 100 + implicitHeight: 30 + } + } + } + function test_empty() { var control = groupBox.createObject(testCase) verify(control) @@ -113,4 +123,16 @@ TestCase { control.destroy() } + + function test_contentItem() { + var control = contentBox.createObject(testCase) + verify(control) + + compare(control.contentWidth, 100) + compare(control.contentHeight, 30) + verify(control.implicitWidth > 100) + verify(control.implicitHeight > 30) + + control.destroy() + } } diff --git a/tests/auto/controls/data/tst_pane.qml b/tests/auto/controls/data/tst_pane.qml index 18fd1cf0..1fdec049 100644 --- a/tests/auto/controls/data/tst_pane.qml +++ b/tests/auto/controls/data/tst_pane.qml @@ -57,7 +57,7 @@ TestCase { Component { id: oneChildPane - GroupBox { + Pane { Item { implicitWidth: 100 implicitHeight: 30 @@ -67,7 +67,7 @@ TestCase { Component { id: twoChildrenPane - GroupBox { + Pane { Item { implicitWidth: 100 implicitHeight: 30 @@ -80,6 +80,16 @@ TestCase { } Component { + id: contentPane + Pane { + contentItem: Item { + implicitWidth: 100 + implicitHeight: 30 + } + } + } + + Component { id: pressPane MouseArea { width: 200 @@ -127,6 +137,18 @@ TestCase { control.destroy() } + function test_contentItem() { + var control = contentPane.createObject(testCase) + verify(control) + + compare(control.contentWidth, 100) + compare(control.contentHeight, 30) + verify(control.implicitWidth > 100) + verify(control.implicitHeight > 30) + + control.destroy() + } + function test_press() { var control = pressPane.createObject(testCase) verify(control) diff --git a/tests/auto/controls/data/tst_toolbar.qml b/tests/auto/controls/data/tst_toolbar.qml index ac116a86..128aa403 100644 --- a/tests/auto/controls/data/tst_toolbar.qml +++ b/tests/auto/controls/data/tst_toolbar.qml @@ -57,7 +57,7 @@ TestCase { Component { id: oneChildBar - GroupBox { + ToolBar { Item { implicitWidth: 100 implicitHeight: 30 @@ -67,7 +67,7 @@ TestCase { Component { id: twoChildrenBar - GroupBox { + ToolBar { Item { implicitWidth: 100 implicitHeight: 30 @@ -79,6 +79,16 @@ TestCase { } } + Component { + id: contentBar + ToolBar { + contentItem: Item { + implicitWidth: 100 + implicitHeight: 30 + } + } + } + function test_empty() { var control = toolBar.createObject(testCase) verify(control) @@ -96,8 +106,8 @@ TestCase { compare(control.contentWidth, 100) compare(control.contentHeight, 30) - verify(control.implicitWidth > 100) - verify(control.implicitHeight > 30) + verify(control.implicitWidth >= 100) + verify(control.implicitHeight >= 30) control.destroy() } @@ -108,8 +118,20 @@ TestCase { compare(control.contentWidth, 0) compare(control.contentHeight, 0) - verify(control.implicitWidth > 0) - verify(control.implicitHeight > 0) + verify(control.implicitWidth >= 0) + verify(control.implicitHeight >= 0) + + control.destroy() + } + + function test_contentItem() { + var control = contentBar.createObject(testCase) + verify(control) + + compare(control.contentWidth, 100) + compare(control.contentHeight, 30) + verify(control.implicitWidth >= 100) + verify(control.implicitHeight >= 30) control.destroy() } diff --git a/tests/auto/menu/tst_menu.cpp b/tests/auto/menu/tst_menu.cpp index d072af4b..825867cf 100644 --- a/tests/auto/menu/tst_menu.cpp +++ b/tests/auto/menu/tst_menu.cpp @@ -89,7 +89,7 @@ void tst_menu::mouse() QVERIFY(window->overlay()->childItems().contains(menu->contentItem()->parentItem())); QQuickItem *firstItem = menu->itemAt(0); - QSignalSpy clickedSpy(firstItem, SIGNAL(clicked(QQuickMouseEvent*))); + QSignalSpy clickedSpy(firstItem, SIGNAL(clicked())); QSignalSpy triggeredSpy(firstItem, SIGNAL(triggered())); QSignalSpy visibleSpy(menu, SIGNAL(visibleChanged())); diff --git a/tests/auto/popup/data/applicationwindow.qml b/tests/auto/popup/data/applicationwindow.qml new file mode 100644 index 00000000..34dbe7e8 --- /dev/null +++ b/tests/auto/popup/data/applicationwindow.qml @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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 +import Qt.labs.controls 1.0 + +ApplicationWindow { + width: 400 + height: 400 + + property alias popup: popup + property alias button: button + + Button { + id: button + text: "Open" + anchors.centerIn: parent + anchors.verticalCenterOffset: -height + + Popup { + id: popup + y: parent.height + + Text { + color: "white" + text: "Hello, world!" + + MouseArea { + anchors.fill: parent + onClicked: popup.close() + } + } + } + } +} diff --git a/tests/auto/popup/popup.pro b/tests/auto/popup/popup.pro new file mode 100644 index 00000000..87aca3b3 --- /dev/null +++ b/tests/auto/popup/popup.pro @@ -0,0 +1,14 @@ +CONFIG += testcase +TARGET = tst_popup +SOURCES += tst_popup.cpp + +osx:CONFIG -= app_bundle + +QT += core-private gui-private qml-private quick-private testlib labstemplates-private + +include (../shared/util.pri) + +TESTDATA = data/* + +OTHER_FILES += \ + data/* diff --git a/tests/auto/popup/tst_popup.cpp b/tests/auto/popup/tst_popup.cpp new file mode 100644 index 00000000..61bf999c --- /dev/null +++ b/tests/auto/popup/tst_popup.cpp @@ -0,0 +1,228 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtTest/qtest.h> +#include <QtTest/qsignalspy.h> +#include "../shared/util.h" +#include "../shared/visualtestutil.h" + +#include <QtLabsTemplates/private/qquickapplicationwindow_p.h> +#include <QtLabsTemplates/private/qquickoverlay_p.h> +#include <QtLabsTemplates/private/qquickpopup_p.h> +#include <QtLabsTemplates/private/qquickbutton_p.h> + +using namespace QQuickVisualTestUtil; + +class tst_popup : public QQmlDataTest +{ + Q_OBJECT + +private slots: + void visible(); + void overlay(); + void closePolicy_data(); + void closePolicy(); +}; + +void tst_popup::visible() +{ + QQuickApplicationHelper helper(this, QStringLiteral("applicationwindow.qml")); + + QQuickApplicationWindow *window = helper.window; + window->show(); + QVERIFY(QTest::qWaitForWindowActive(window)); + + QQuickPopup *popup = helper.window->property("popup").value<QQuickPopup*>(); + QVERIFY(popup); + QQuickItem *popupItem = popup->popupItem(); + + popup->open(); + QVERIFY(popup->isVisible()); + QVERIFY(window->overlay()->childItems().contains(popupItem)); + + popup->close(); + QVERIFY(!popup->isVisible()); + QVERIFY(!window->overlay()->childItems().contains(popupItem)); + + popup->setVisible(true); + QVERIFY(popup->isVisible()); + QVERIFY(window->overlay()->childItems().contains(popupItem)); + + popup->setVisible(false); + QVERIFY(!popup->isVisible()); + QVERIFY(!window->overlay()->childItems().contains(popupItem)); +} + +void tst_popup::overlay() +{ + QQuickApplicationHelper helper(this, QStringLiteral("applicationwindow.qml")); + + QQuickApplicationWindow *window = helper.window; + window->show(); + QVERIFY(QTest::qWaitForWindowActive(window)); + + QQuickItem *overlay = window->overlay(); + QSignalSpy overlayPressedSignal(overlay, SIGNAL(pressed())); + QSignalSpy overlayReleasedSignal(overlay, SIGNAL(released())); + QVERIFY(overlayPressedSignal.isValid()); + QVERIFY(overlayReleasedSignal.isValid()); + + QTest::mousePress(window, Qt::LeftButton); + QCOMPARE(overlayPressedSignal.count(), 1); + QCOMPARE(overlayReleasedSignal.count(), 0); + + QTest::mouseRelease(window, Qt::LeftButton); + QCOMPARE(overlayPressedSignal.count(), 1); + QCOMPARE(overlayReleasedSignal.count(), 0); // no modal popups open + + QQuickPopup *popup = helper.window->property("popup").value<QQuickPopup*>(); + QVERIFY(popup); + + QQuickButton *button = helper.window->property("button").value<QQuickButton*>(); + QVERIFY(button); + + popup->setModal(true); + + popup->open(); + QVERIFY(popup->isVisible()); + + QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, QPoint(1, 1)); + QCOMPARE(overlayPressedSignal.count(), 2); + QCOMPARE(overlayReleasedSignal.count(), 0); + + QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, QPoint(1, 1)); + QCOMPARE(overlayPressedSignal.count(), 2); + QCOMPARE(overlayReleasedSignal.count(), 1); + + QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, QPoint(button->x() + popup->x() + popup->width() / 2, + button->y() + popup->y() + popup->height() / 2)); + QCOMPARE(overlayPressedSignal.count(), 2); + QCOMPARE(overlayReleasedSignal.count(), 1); + + QVERIFY(!popup->isVisible()); +} + +Q_DECLARE_METATYPE(QQuickPopup::ClosePolicy) + +void tst_popup::closePolicy_data() +{ + qRegisterMetaType<QQuickPopup::ClosePolicy>(); + + QTest::addColumn<QQuickPopup::ClosePolicy>("closePolicy"); + + QTest::newRow("NoAutoClose") << static_cast<QQuickPopup::ClosePolicy>(QQuickPopup::NoAutoClose); + QTest::newRow("OnPressOutside") << static_cast<QQuickPopup::ClosePolicy>(QQuickPopup::OnPressOutside); + QTest::newRow("OnPressOutsideParent") << static_cast<QQuickPopup::ClosePolicy>(QQuickPopup::OnPressOutsideParent); + QTest::newRow("OnPressOutside|Parent") << static_cast<QQuickPopup::ClosePolicy>(QQuickPopup::OnPressOutside | QQuickPopup::OnPressOutsideParent); + QTest::newRow("OnReleaseOutside") << static_cast<QQuickPopup::ClosePolicy>(QQuickPopup::OnReleaseOutside); + QTest::newRow("OnReleaseOutside|Parent") << static_cast<QQuickPopup::ClosePolicy>(QQuickPopup::OnReleaseOutside | QQuickPopup::OnReleaseOutsideParent); + QTest::newRow("OnEscape") << static_cast<QQuickPopup::ClosePolicy>(QQuickPopup::OnEscape); +} + +void tst_popup::closePolicy() +{ + QFETCH(QQuickPopup::ClosePolicy, closePolicy); + + QQuickApplicationHelper helper(this, QStringLiteral("applicationwindow.qml")); + + QQuickApplicationWindow *window = helper.window; + window->show(); + QVERIFY(QTest::qWaitForWindowActive(window)); + + QQuickPopup *popup = helper.window->property("popup").value<QQuickPopup*>(); + QVERIFY(popup); + + QQuickButton *button = helper.window->property("button").value<QQuickButton*>(); + QVERIFY(button); + + popup->setModal(true); + popup->setFocus(true); + popup->setClosePolicy(closePolicy); + + popup->open(); + QVERIFY(popup->isVisible()); + + // press outside popup and its parent + QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, QPoint(1, 1)); + if (closePolicy.testFlag(QQuickPopup::OnPressOutside) || closePolicy.testFlag(QQuickPopup::OnPressOutsideParent)) + QVERIFY(!popup->isVisible()); + else + QVERIFY(popup->isVisible()); + + popup->open(); + QVERIFY(popup->isVisible()); + + // release outside popup and its parent + QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, QPoint(1, 1)); + if (closePolicy.testFlag(QQuickPopup::OnReleaseOutside)) + QVERIFY(!popup->isVisible()); + else + QVERIFY(popup->isVisible()); + + popup->open(); + QVERIFY(popup->isVisible()); + + // press outside popup but inside its parent + QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, QPoint(button->x(), button->y())); + if (closePolicy.testFlag(QQuickPopup::OnPressOutside) && !closePolicy.testFlag(QQuickPopup::OnPressOutsideParent)) + QVERIFY(!popup->isVisible()); + else + QVERIFY(popup->isVisible()); + + popup->open(); + QVERIFY(popup->isVisible()); + + // release outside popup but inside its parent + QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, QPoint(button->x(), button->y())); + if (closePolicy.testFlag(QQuickPopup::OnReleaseOutside) && !closePolicy.testFlag(QQuickPopup::OnReleaseOutsideParent)) + QVERIFY(!popup->isVisible()); + else + QVERIFY(popup->isVisible()); + + popup->open(); + QVERIFY(popup->isVisible()); + + // escape + QTest::keyClick(window, Qt::Key_Escape); + if (closePolicy.testFlag(QQuickPopup::OnEscape)) + QVERIFY(!popup->isVisible()); + else + QVERIFY(popup->isVisible()); +} + +QTEST_MAIN(tst_popup) + +#include "tst_popup.moc" diff --git a/tests/manual/manual.pro b/tests/manual/manual.pro index b974ae29..a85fd870 100644 --- a/tests/manual/manual.pro +++ b/tests/manual/manual.pro @@ -3,3 +3,5 @@ SUBDIRS += \ gifs \ fonts \ testbench + +qtHaveModule(widgets): SUBDIRS += viewinqwidget diff --git a/tests/manual/viewinqwidget/main.cpp b/tests/manual/viewinqwidget/main.cpp new file mode 100644 index 00000000..3611e071 --- /dev/null +++ b/tests/manual/viewinqwidget/main.cpp @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QApplication> +#include <QHBoxLayout> +#include <QVBoxLayout> +#include <QDebug> +#include <QDesktopWidget> +#include <QGroupBox> +#include <QQmlApplicationEngine> +#include <QQmlError> +#include <QQuickView> +#include <QQuickWidget> + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + + QWidget widget; + widget.setWindowTitle(QT_VERSION_STR); + + QHBoxLayout *hLayout = new QHBoxLayout(&widget); + QGroupBox *groupBox = new QGroupBox("QuickWidget", &widget); + QVBoxLayout *vLayout = new QVBoxLayout(groupBox); + QQuickWidget *quickWidget = new QQuickWidget(groupBox); + quickWidget->setMinimumSize(360, 520); + vLayout->addWidget(quickWidget); + quickWidget->setResizeMode(QQuickWidget::SizeRootObjectToView); + quickWidget->setSource(QUrl(QLatin1String("qrc:/main.qml"))); + if (quickWidget->status() == QQuickWidget::Error) { + qWarning() << quickWidget->errors(); + return 1; + } + hLayout->addWidget(groupBox); + + const QUrl gallerySource(QLatin1String("qrc:/gallery.qml")); + QQmlApplicationEngine engine(gallerySource); + QObject *root = engine.rootObjects().value(0, nullptr); + if (!root || !root->isWindowType()) { + qWarning() << "Load error" << gallerySource; + return 1; + } + groupBox = new QGroupBox("QQuickView/createWindowContainer", &widget); + vLayout = new QVBoxLayout(groupBox); + QWidget *container = QWidget::createWindowContainer(qobject_cast<QWindow *>(root), groupBox); + container->setMinimumSize(360, 520); + vLayout->addWidget(container); + hLayout->addWidget(groupBox); + + const QRect availableGeometry = QApplication::desktop()->availableGeometry(&widget); + widget.move(availableGeometry.center() - QPoint(widget.sizeHint().width() / 2, widget.sizeHint().height() / 2)); + + widget.show(); + + return app.exec(); +} diff --git a/tests/manual/viewinqwidget/main.qml b/tests/manual/viewinqwidget/main.qml new file mode 100644 index 00000000..36a0b133 --- /dev/null +++ b/tests/manual/viewinqwidget/main.qml @@ -0,0 +1,49 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.6 +import Qt.labs.controls 1.0 + +Item { + visible: true + width: 360 + height: 520 + + ComboBox { + model: ["First", "Second", "Third"] + anchors.centerIn: parent + } +} diff --git a/tests/manual/viewinqwidget/viewinqwidget.pro b/tests/manual/viewinqwidget/viewinqwidget.pro new file mode 100644 index 00000000..9b7cba00 --- /dev/null +++ b/tests/manual/viewinqwidget/viewinqwidget.pro @@ -0,0 +1,6 @@ +QT += qml quick widgets quickwidgets +TARGET = viewinqwidget +SOURCES += $$PWD/main.cpp +OTHER_FILES += main.qml +RESOURCES += viewinqwidget.qrc \ + ../../../examples/controls/gallery/gallery.qrc diff --git a/tests/manual/viewinqwidget/viewinqwidget.qrc b/tests/manual/viewinqwidget/viewinqwidget.qrc new file mode 100644 index 00000000..5f6483ac --- /dev/null +++ b/tests/manual/viewinqwidget/viewinqwidget.qrc @@ -0,0 +1,5 @@ +<RCC> + <qresource prefix="/"> + <file>main.qml</file> + </qresource> +</RCC> |