diff options
545 files changed, 20975 insertions, 2334 deletions
@@ -30,15 +30,20 @@ /tests/auto/applicationwindow/tst_applicationwindow /tests/auto/calendar/tst_calendar /tests/auto/controls/default/tst_default +/tests/auto/controls/fusion/tst_fusion /tests/auto/controls/material/tst_material /tests/auto/controls/universal/tst_universal /tests/auto/cursor/tst_cursor /tests/auto/drawer/tst_drawer /tests/auto/focus/tst_focus /tests/auto/menu/tst_menu +/tests/auto/palette/tst_palette /tests/auto/platform/tst_platform /tests/auto/popup/tst_popup /tests/auto/pressandhold/tst_pressandhold +/tests/auto/qquickcolor/tst_qquickcolor +/tests/auto/qquickiconimage/tst_qquickiconimage +/tests/auto/qquickiconlabel/tst_qquickiconlabel /tests/auto/qquickmaterialstyle/tst_qquickmaterialstyle /tests/auto/qquickmaterialstyleconf/tst_qquickmaterialstyleconf /tests/auto/qquickstyle/tst_qquickstyle diff --git a/.qmake.conf b/.qmake.conf index fde5be19..00c9f8dd 100644 --- a/.qmake.conf +++ b/.qmake.conf @@ -4,4 +4,4 @@ DEFINES += QT_NO_FOREACH QQC2_SOURCE_TREE = $$PWD -MODULE_VERSION = 5.9.1 +MODULE_VERSION = 5.10.0 diff --git a/examples/quickcontrols2/gallery/gallery.cpp b/examples/quickcontrols2/gallery/gallery.cpp index 7b70f1c8..b4d59685 100644 --- a/examples/quickcontrols2/gallery/gallery.cpp +++ b/examples/quickcontrols2/gallery/gallery.cpp @@ -53,6 +53,7 @@ #include <QQmlContext> #include <QSettings> #include <QQuickStyle> +#include <QIcon> int main(int argc, char *argv[]) { @@ -62,6 +63,8 @@ int main(int argc, char *argv[]) QGuiApplication app(argc, argv); + QIcon::setThemeName("gallery"); + QSettings settings; QString style = QQuickStyle::name(); if (!style.isEmpty()) diff --git a/examples/quickcontrols2/gallery/gallery.pro b/examples/quickcontrols2/gallery/gallery.pro index 45496a35..705eeae0 100644 --- a/examples/quickcontrols2/gallery/gallery.pro +++ b/examples/quickcontrols2/gallery/gallery.pro @@ -8,8 +8,9 @@ SOURCES += \ RESOURCES += \ gallery.qml \ qtquickcontrols2.conf \ + icons/gallery/index.theme \ + $$files(icons/*.png, true) \ $$files(images/*.png) \ - $$files(images/+material/*.png) \ $$files(pages/*.qml) target.path = $$[QT_INSTALL_EXAMPLES]/quickcontrols2/gallery diff --git a/examples/quickcontrols2/gallery/gallery.qml b/examples/quickcontrols2/gallery/gallery.qml index 9f253ab3..5344b74e 100644 --- a/examples/quickcontrols2/gallery/gallery.qml +++ b/examples/quickcontrols2/gallery/gallery.qml @@ -50,7 +50,7 @@ import QtQuick 2.9 import QtQuick.Layouts 1.3 -import QtQuick.Controls 2.2 +import QtQuick.Controls 2.3 import QtQuick.Controls.Material 2.1 import QtQuick.Controls.Universal 2.1 import Qt.labs.settings 1.0 @@ -89,12 +89,7 @@ ApplicationWindow { anchors.fill: parent ToolButton { - contentItem: Image { - fillMode: Image.Pad - horizontalAlignment: Image.AlignHCenter - verticalAlignment: Image.AlignVCenter - source: stackView.depth > 1 ? "images/back.png" : "images/drawer.png" - } + icon.name: stackView.depth > 1 ? "back" : "drawer" onClicked: { if (stackView.depth > 1) { stackView.pop() @@ -116,12 +111,7 @@ ApplicationWindow { } ToolButton { - contentItem: Image { - fillMode: Image.Pad - horizontalAlignment: Image.AlignHCenter - verticalAlignment: Image.AlignVCenter - source: "images/menu.png" - } + icon.name: "menu" onClicked: optionsMenu.open() Menu { diff --git a/examples/quickcontrols2/gallery/images/back.png b/examples/quickcontrols2/gallery/icons/gallery/20x20/back.png Binary files differindex db43e273..db43e273 100644 --- a/examples/quickcontrols2/gallery/images/back.png +++ b/examples/quickcontrols2/gallery/icons/gallery/20x20/back.png diff --git a/examples/quickcontrols2/gallery/images/drawer.png b/examples/quickcontrols2/gallery/icons/gallery/20x20/drawer.png Binary files differindex 1e974efa..1e974efa 100644 --- a/examples/quickcontrols2/gallery/images/drawer.png +++ b/examples/quickcontrols2/gallery/icons/gallery/20x20/drawer.png diff --git a/examples/quickcontrols2/gallery/images/menu.png b/examples/quickcontrols2/gallery/icons/gallery/20x20/menu.png Binary files differindex a10473d9..a10473d9 100644 --- a/examples/quickcontrols2/gallery/images/menu.png +++ b/examples/quickcontrols2/gallery/icons/gallery/20x20/menu.png diff --git a/examples/quickcontrols2/gallery/images/back@2x.png b/examples/quickcontrols2/gallery/icons/gallery/20x20@2/back.png Binary files differindex c55ab315..c55ab315 100644 --- a/examples/quickcontrols2/gallery/images/back@2x.png +++ b/examples/quickcontrols2/gallery/icons/gallery/20x20@2/back.png diff --git a/examples/quickcontrols2/gallery/images/drawer@2x.png b/examples/quickcontrols2/gallery/icons/gallery/20x20@2/drawer.png Binary files differindex eba3b6cc..eba3b6cc 100644 --- a/examples/quickcontrols2/gallery/images/drawer@2x.png +++ b/examples/quickcontrols2/gallery/icons/gallery/20x20@2/drawer.png diff --git a/examples/quickcontrols2/gallery/images/menu@2x.png b/examples/quickcontrols2/gallery/icons/gallery/20x20@2/menu.png Binary files differindex 649c2a08..649c2a08 100644 --- a/examples/quickcontrols2/gallery/images/menu@2x.png +++ b/examples/quickcontrols2/gallery/icons/gallery/20x20@2/menu.png diff --git a/examples/quickcontrols2/gallery/images/back@3x.png b/examples/quickcontrols2/gallery/icons/gallery/20x20@3/back.png Binary files differindex b228eb87..b228eb87 100644 --- a/examples/quickcontrols2/gallery/images/back@3x.png +++ b/examples/quickcontrols2/gallery/icons/gallery/20x20@3/back.png diff --git a/examples/quickcontrols2/gallery/images/drawer@3x.png b/examples/quickcontrols2/gallery/icons/gallery/20x20@3/drawer.png Binary files differindex 3584ed6d..3584ed6d 100644 --- a/examples/quickcontrols2/gallery/images/drawer@3x.png +++ b/examples/quickcontrols2/gallery/icons/gallery/20x20@3/drawer.png diff --git a/examples/quickcontrols2/gallery/images/menu@3x.png b/examples/quickcontrols2/gallery/icons/gallery/20x20@3/menu.png Binary files differindex 9554b695..9554b695 100644 --- a/examples/quickcontrols2/gallery/images/menu@3x.png +++ b/examples/quickcontrols2/gallery/icons/gallery/20x20@3/menu.png diff --git a/examples/quickcontrols2/gallery/images/back@4x.png b/examples/quickcontrols2/gallery/icons/gallery/20x20@4/back.png Binary files differindex dd157e78..dd157e78 100644 --- a/examples/quickcontrols2/gallery/images/back@4x.png +++ b/examples/quickcontrols2/gallery/icons/gallery/20x20@4/back.png diff --git a/examples/quickcontrols2/gallery/images/drawer@4x.png b/examples/quickcontrols2/gallery/icons/gallery/20x20@4/drawer.png Binary files differindex 60d93aff..60d93aff 100644 --- a/examples/quickcontrols2/gallery/images/drawer@4x.png +++ b/examples/quickcontrols2/gallery/icons/gallery/20x20@4/drawer.png diff --git a/examples/quickcontrols2/gallery/images/menu@4x.png b/examples/quickcontrols2/gallery/icons/gallery/20x20@4/menu.png Binary files differindex 187c171c..187c171c 100644 --- a/examples/quickcontrols2/gallery/images/menu@4x.png +++ b/examples/quickcontrols2/gallery/icons/gallery/20x20@4/menu.png diff --git a/examples/quickcontrols2/gallery/icons/gallery/index.theme b/examples/quickcontrols2/gallery/icons/gallery/index.theme new file mode 100644 index 00000000..a1bcd5e0 --- /dev/null +++ b/examples/quickcontrols2/gallery/icons/gallery/index.theme @@ -0,0 +1,24 @@ +[Icon Theme] +Name=Gallery +Comment=Qt Quick Controls 2 Gallery Example Icon Theme + +Directories=20x20,20x20@2,20x20@3,20x20@4 + +[20x20] +Size=20 +Type=Fixed + +[20x20@2] +Size=20 +Scale=2 +Type=Fixed + +[20x20@3] +Size=20 +Scale=3 +Type=Fixed + +[20x20@4] +Size=20 +Scale=4 +Type=Fixed diff --git a/examples/quickcontrols2/gallery/images/+material/back.png b/examples/quickcontrols2/gallery/images/+material/back.png Binary files differdeleted file mode 100644 index ebc1000f..00000000 --- a/examples/quickcontrols2/gallery/images/+material/back.png +++ /dev/null diff --git a/examples/quickcontrols2/gallery/images/+material/back@2x.png b/examples/quickcontrols2/gallery/images/+material/back@2x.png Binary files differdeleted file mode 100644 index cf6163c8..00000000 --- a/examples/quickcontrols2/gallery/images/+material/back@2x.png +++ /dev/null diff --git a/examples/quickcontrols2/gallery/images/+material/back@3x.png b/examples/quickcontrols2/gallery/images/+material/back@3x.png Binary files differdeleted file mode 100644 index 96376a5a..00000000 --- a/examples/quickcontrols2/gallery/images/+material/back@3x.png +++ /dev/null diff --git a/examples/quickcontrols2/gallery/images/+material/back@4x.png b/examples/quickcontrols2/gallery/images/+material/back@4x.png Binary files differdeleted file mode 100644 index 578ac14f..00000000 --- a/examples/quickcontrols2/gallery/images/+material/back@4x.png +++ /dev/null diff --git a/examples/quickcontrols2/gallery/images/+material/drawer.png b/examples/quickcontrols2/gallery/images/+material/drawer.png Binary files differdeleted file mode 100644 index 615cc817..00000000 --- a/examples/quickcontrols2/gallery/images/+material/drawer.png +++ /dev/null diff --git a/examples/quickcontrols2/gallery/images/+material/drawer@2x.png b/examples/quickcontrols2/gallery/images/+material/drawer@2x.png Binary files differdeleted file mode 100644 index b1dd106d..00000000 --- a/examples/quickcontrols2/gallery/images/+material/drawer@2x.png +++ /dev/null diff --git a/examples/quickcontrols2/gallery/images/+material/drawer@3x.png b/examples/quickcontrols2/gallery/images/+material/drawer@3x.png Binary files differdeleted file mode 100644 index 289889bf..00000000 --- a/examples/quickcontrols2/gallery/images/+material/drawer@3x.png +++ /dev/null diff --git a/examples/quickcontrols2/gallery/images/+material/drawer@4x.png b/examples/quickcontrols2/gallery/images/+material/drawer@4x.png Binary files differdeleted file mode 100644 index 215e6a82..00000000 --- a/examples/quickcontrols2/gallery/images/+material/drawer@4x.png +++ /dev/null diff --git a/examples/quickcontrols2/gallery/images/+material/menu.png b/examples/quickcontrols2/gallery/images/+material/menu.png Binary files differdeleted file mode 100644 index f02429e9..00000000 --- a/examples/quickcontrols2/gallery/images/+material/menu.png +++ /dev/null diff --git a/examples/quickcontrols2/gallery/images/+material/menu@2x.png b/examples/quickcontrols2/gallery/images/+material/menu@2x.png Binary files differdeleted file mode 100644 index 9309ad9a..00000000 --- a/examples/quickcontrols2/gallery/images/+material/menu@2x.png +++ /dev/null diff --git a/examples/quickcontrols2/gallery/images/+material/menu@3x.png b/examples/quickcontrols2/gallery/images/+material/menu@3x.png Binary files differdeleted file mode 100644 index 7bddf71f..00000000 --- a/examples/quickcontrols2/gallery/images/+material/menu@3x.png +++ /dev/null diff --git a/examples/quickcontrols2/gallery/images/+material/menu@4x.png b/examples/quickcontrols2/gallery/images/+material/menu@4x.png Binary files differdeleted file mode 100644 index e5c23a3b..00000000 --- a/examples/quickcontrols2/gallery/images/+material/menu@4x.png +++ /dev/null diff --git a/src/imports/calendar/qtlabscalendarplugin.cpp b/src/imports/calendar/qtlabscalendarplugin.cpp index 6d2d5b97..178118fb 100644 --- a/src/imports/calendar/qtlabscalendarplugin.cpp +++ b/src/imports/calendar/qtlabscalendarplugin.cpp @@ -58,7 +58,7 @@ class QtLabsCalendarPlugin: public QQmlExtensionPlugin public: QtLabsCalendarPlugin(QObject *parent = nullptr); - void registerTypes(const char *uri); + void registerTypes(const char *uri) override; }; QtLabsCalendarPlugin::QtLabsCalendarPlugin(QObject *parent) : QQmlExtensionPlugin(parent) diff --git a/src/imports/controls/AbstractButton.qml b/src/imports/controls/AbstractButton.qml index 96987cf2..e5214d37 100644 --- a/src/imports/controls/AbstractButton.qml +++ b/src/imports/controls/AbstractButton.qml @@ -35,7 +35,7 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T +import QtQuick.Templates 2.3 as T T.AbstractButton { id: control diff --git a/src/imports/controls/Action.qml b/src/imports/controls/Action.qml new file mode 100644 index 00000000..3ee2e44a --- /dev/null +++ b/src/imports/controls/Action.qml @@ -0,0 +1,40 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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.9 +import QtQuick.Templates 2.3 as T + +T.Action { } diff --git a/src/imports/controls/ActionGroup.qml b/src/imports/controls/ActionGroup.qml new file mode 100644 index 00000000..6f4dfa40 --- /dev/null +++ b/src/imports/controls/ActionGroup.qml @@ -0,0 +1,40 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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.9 +import QtQuick.Templates 2.3 as T + +T.ActionGroup { } diff --git a/src/imports/controls/ApplicationWindow.qml b/src/imports/controls/ApplicationWindow.qml index af3986ac..6698fcb3 100644 --- a/src/imports/controls/ApplicationWindow.qml +++ b/src/imports/controls/ApplicationWindow.qml @@ -36,9 +36,9 @@ import QtQuick 2.9 import QtQuick.Window 2.3 -import QtQuick.Controls 2.2 -import QtQuick.Controls.impl 2.2 -import QtQuick.Templates 2.2 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Templates 2.3 as T T.ApplicationWindow { id: window diff --git a/src/imports/controls/BusyIndicator.qml b/src/imports/controls/BusyIndicator.qml index 234c2e01..e3757703 100644 --- a/src/imports/controls/BusyIndicator.qml +++ b/src/imports/controls/BusyIndicator.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Controls 2.2 -import QtQuick.Controls.impl 2.2 -import QtQuick.Templates 2.2 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Templates 2.3 as T T.BusyIndicator { id: control @@ -51,6 +51,8 @@ T.BusyIndicator { implicitWidth: 48 implicitHeight: 48 + pen: Default.textColor + fill: Default.textColor opacity: control.running ? 1 : 0 visible: control.running || animator.running Behavior on opacity { OpacityAnimator { id: animator; duration: 250 } } diff --git a/src/imports/controls/Button.qml b/src/imports/controls/Button.qml index 6c150d5d..b1670c9a 100644 --- a/src/imports/controls/Button.qml +++ b/src/imports/controls/Button.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Controls 2.2 -import QtQuick.Controls.impl 2.2 -import QtQuick.Templates 2.2 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Templates 2.3 as T T.Button { id: control @@ -51,17 +51,25 @@ T.Button { padding: 6 leftPadding: padding + 2 rightPadding: padding + 2 + spacing: 6 - contentItem: Text { + icon.width: 24 + icon.height: 24 + icon.color: Color.transparent(checked || highlighted ? Default.textLightColor : + visualFocus ? Default.focusColor : down ? Default.textDarkColor : Default.textColor, + enabled || highlighted || checked ? 1 : 0.3) + + contentItem: IconLabel { + spacing: control.spacing + mirrored: control.mirrored + display: control.display + + icon: control.icon text: control.text font: control.font - opacity: enabled || control.highlighted || control.checked ? 1 : 0.3 - color: control.checked || control.highlighted ? - Default.textLightColor : - (control.visualFocus ? Default.focusColor : (control.down ? Default.textDarkColor : Default.textColor)) - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - elide: Text.ElideRight + color: Color.transparent(control.checked || control.highlighted ? Default.textLightColor : + control.visualFocus ? Default.focusColor : control.down ? Default.textDarkColor : Default.textColor, + enabled || control.highlighted || control.checked ? 1 : 0.3) } background: Rectangle { diff --git a/src/imports/controls/ButtonGroup.qml b/src/imports/controls/ButtonGroup.qml new file mode 100644 index 00000000..5c8550b3 --- /dev/null +++ b/src/imports/controls/ButtonGroup.qml @@ -0,0 +1,40 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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.9 +import QtQuick.Templates 2.3 as T + +T.ButtonGroup { } diff --git a/src/imports/controls/CheckBox.qml b/src/imports/controls/CheckBox.qml index 7945ca72..808f82ba 100644 --- a/src/imports/controls/CheckBox.qml +++ b/src/imports/controls/CheckBox.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls 2.2 -import QtQuick.Controls.impl 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 T.CheckBox { id: control diff --git a/src/imports/controls/CheckDelegate.qml b/src/imports/controls/CheckDelegate.qml index 05a0baf6..6ae09ace 100644 --- a/src/imports/controls/CheckDelegate.qml +++ b/src/imports/controls/CheckDelegate.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls 2.2 -import QtQuick.Controls.impl 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 T.CheckDelegate { id: control @@ -52,17 +52,23 @@ T.CheckDelegate { padding: 12 spacing: 12 - contentItem: Text { + icon.width: 24 + icon.height: 24 + icon.color: enabled ? Default.textDarkColor : Default.textDisabledColor + + contentItem: IconLabel { leftPadding: control.mirrored ? control.indicator.width + control.spacing : 0 rightPadding: !control.mirrored ? control.indicator.width + control.spacing : 0 + spacing: control.spacing + mirrored: control.mirrored + display: control.display + alignment: control.display === IconLabel.IconOnly || control.display === IconLabel.TextUnderIcon ? Qt.AlignCenter : Qt.AlignLeft + + icon: control.icon text: control.text font: control.font color: control.enabled ? Default.textDarkColor : Default.textDisabledColor - elide: Text.ElideRight - visible: control.text - horizontalAlignment: Text.AlignLeft - verticalAlignment: Text.AlignVCenter } indicator: CheckIndicator { diff --git a/src/imports/controls/CheckIndicator.qml b/src/imports/controls/CheckIndicator.qml index 0be3e6cd..2bc87fe6 100644 --- a/src/imports/controls/CheckIndicator.qml +++ b/src/imports/controls/CheckIndicator.qml @@ -35,8 +35,8 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Controls 2.2 -import QtQuick.Controls.impl 2.2 +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 Rectangle { id: indicator @@ -55,12 +55,11 @@ Rectangle { : (control.down ? Default.indicatorFramePressedColor : Default.indicatorFrameColor)) : "transparent" opacity: enabled ? 1 : 0.3 - Image { + ColorImage { x: (parent.width - width) / 2 y: (parent.height - height) / 2 - source: "image://default/check/" + (control.visualFocus ? Default.focusColor : Default.textColor) - sourceSize.width: width - sourceSize.height: height + color: control.visualFocus ? Default.focusColor : Default.textColor + source: "qrc:/qt-project.org/imports/QtQuick/Controls.2/images/check.png" visible: control.checkState === Qt.Checked } diff --git a/src/imports/controls/ComboBox.qml b/src/imports/controls/ComboBox.qml index 6a885320..a3735880 100644 --- a/src/imports/controls/ComboBox.qml +++ b/src/imports/controls/ComboBox.qml @@ -36,9 +36,9 @@ import QtQuick 2.9 import QtQuick.Window 2.3 -import QtQuick.Controls 2.2 -import QtQuick.Controls.impl 2.2 -import QtQuick.Templates 2.2 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Templates 2.3 as T T.ComboBox { id: control @@ -61,12 +61,11 @@ T.ComboBox { hoverEnabled: control.hoverEnabled } - indicator: Image { + indicator: ColorImage { x: control.mirrored ? control.padding : control.width - width - control.padding y: control.topPadding + (control.availableHeight - height) / 2 - source: "image://default/double-arrow/" + (!control.editable && control.visualFocus ? Default.focusColor : Default.textColor) - sourceSize.width: width - sourceSize.height: height + color: !control.editable && control.visualFocus ? Default.focusColor : Default.textColor + source: "qrc:/qt-project.org/imports/QtQuick/Controls.2/images/double-arrow.png" opacity: enabled ? 1 : 0.3 } @@ -100,7 +99,7 @@ T.ComboBox { } background: Rectangle { - implicitWidth: 120 + implicitWidth: 140 implicitHeight: 40 color: !control.editable && control.visualFocus ? (control.pressed ? Default.focusPressedColor : Default.focusLightColor) : @@ -122,7 +121,6 @@ T.ComboBox { implicitHeight: contentHeight model: control.popup.visible ? control.delegateModel : null currentIndex: control.highlightedIndex - highlightRangeMode: ListView.ApplyRange highlightMoveDuration: 0 Rectangle { diff --git a/src/imports/controls/Container.qml b/src/imports/controls/Container.qml index 5844e0a2..a1f15d19 100644 --- a/src/imports/controls/Container.qml +++ b/src/imports/controls/Container.qml @@ -35,7 +35,7 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T +import QtQuick.Templates 2.3 as T T.Container { id: control diff --git a/src/imports/controls/Control.qml b/src/imports/controls/Control.qml index 85f40ae5..b747840b 100644 --- a/src/imports/controls/Control.qml +++ b/src/imports/controls/Control.qml @@ -35,7 +35,7 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T +import QtQuick.Templates 2.3 as T T.Control { id: control diff --git a/src/imports/controls/DelayButton.qml b/src/imports/controls/DelayButton.qml index 4a569fcf..0c66a5a2 100644 --- a/src/imports/controls/DelayButton.qml +++ b/src/imports/controls/DelayButton.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Controls 2.2 -import QtQuick.Controls.impl 2.2 -import QtQuick.Templates 2.2 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Templates 2.3 as T T.DelayButton { id: control diff --git a/src/imports/controls/Dial.qml b/src/imports/controls/Dial.qml index affcfa62..f33ebf72 100644 --- a/src/imports/controls/Dial.qml +++ b/src/imports/controls/Dial.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Controls 2.2 -import QtQuick.Controls.impl 2.2 -import QtQuick.Templates 2.2 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Templates 2.3 as T T.Dial { id: control @@ -45,7 +45,7 @@ T.Dial { implicitWidth: 184 implicitHeight: 184 - background: DialRing { + background: DialImpl { width: control.availableWidth height: control.availableHeight color: control.visualFocus ? Default.focusColor : Default.frameDarkColor @@ -53,15 +53,14 @@ T.Dial { opacity: control.enabled ? 1 : 0.3 } - handle: Image { + handle: ColorImage { id: handleItem x: background.x + background.width / 2 - handle.width / 2 y: background.y + background.height / 2 - handle.height / 2 width: 14 height: 10 - source: "image://default/dial-indicator/" + (control.visualFocus ? Default.focusColor : Default.textColor) - sourceSize.width: width - sourceSize.height: height + color: control.visualFocus ? Default.focusColor : Default.textColor + source: "qrc:/qt-project.org/imports/QtQuick/Controls.2/images/dial-indicator.png" antialiasing: true opacity: control.enabled ? 1 : 0.3 transform: [ diff --git a/src/imports/controls/Dialog.qml b/src/imports/controls/Dialog.qml index 84c33b63..f2ebae34 100644 --- a/src/imports/controls/Dialog.qml +++ b/src/imports/controls/Dialog.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls 2.2 -import QtQuick.Controls.impl 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 T.Dialog { id: control diff --git a/src/imports/controls/DialogButtonBox.qml b/src/imports/controls/DialogButtonBox.qml index ba9fa52f..51c17d05 100644 --- a/src/imports/controls/DialogButtonBox.qml +++ b/src/imports/controls/DialogButtonBox.qml @@ -35,7 +35,7 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T +import QtQuick.Templates 2.3 as T T.DialogButtonBox { id: control diff --git a/src/imports/controls/Drawer.qml b/src/imports/controls/Drawer.qml index b3240ca3..8368838a 100644 --- a/src/imports/controls/Drawer.qml +++ b/src/imports/controls/Drawer.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Controls 2.2 -import QtQuick.Controls.impl 2.2 -import QtQuick.Templates 2.2 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Templates 2.3 as T T.Drawer { id: control diff --git a/src/imports/controls/Frame.qml b/src/imports/controls/Frame.qml index 5add003f..c4b871d5 100644 --- a/src/imports/controls/Frame.qml +++ b/src/imports/controls/Frame.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Controls 2.2 -import QtQuick.Controls.impl 2.2 -import QtQuick.Templates 2.2 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Templates 2.3 as T T.Frame { id: control diff --git a/src/imports/controls/GroupBox.qml b/src/imports/controls/GroupBox.qml index ee81250b..c991b251 100644 --- a/src/imports/controls/GroupBox.qml +++ b/src/imports/controls/GroupBox.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Controls 2.2 -import QtQuick.Controls.impl 2.2 -import QtQuick.Templates 2.2 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Templates 2.3 as T T.GroupBox { id: control diff --git a/src/imports/controls/ItemDelegate.qml b/src/imports/controls/ItemDelegate.qml index 6ee03ca2..26309a9a 100644 --- a/src/imports/controls/ItemDelegate.qml +++ b/src/imports/controls/ItemDelegate.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Controls 2.2 -import QtQuick.Controls.impl 2.2 -import QtQuick.Templates 2.2 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Templates 2.3 as T T.ItemDelegate { id: control @@ -50,19 +50,22 @@ T.ItemDelegate { baselineOffset: contentItem.y + contentItem.baselineOffset padding: 12 - spacing: 12 + spacing: 8 - contentItem: Text { - leftPadding: control.mirrored ? (control.indicator ? control.indicator.width : 0) + control.spacing : 0 - rightPadding: !control.mirrored ? (control.indicator ? control.indicator.width : 0) + control.spacing : 0 + icon.width: 24 + icon.height: 24 + icon.color: enabled ? Default.textDarkColor : Default.textDisabledColor + contentItem: IconLabel { + spacing: control.spacing + mirrored: control.mirrored + display: control.display + alignment: control.display === IconLabel.IconOnly || control.display === IconLabel.TextUnderIcon ? Qt.AlignCenter : Qt.AlignLeft + + icon: control.icon text: control.text font: control.font color: control.enabled ? Default.textDarkColor : Default.textDisabledColor - elide: Text.ElideRight - visible: control.text - horizontalAlignment: Text.AlignLeft - verticalAlignment: Text.AlignVCenter } background: Rectangle { diff --git a/src/imports/controls/Label.qml b/src/imports/controls/Label.qml index d2052774..db6b25bf 100644 --- a/src/imports/controls/Label.qml +++ b/src/imports/controls/Label.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Controls 2.2 -import QtQuick.Controls.impl 2.2 -import QtQuick.Templates 2.2 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Templates 2.3 as T T.Label { id: control diff --git a/src/imports/controls/Menu.qml b/src/imports/controls/Menu.qml index dc428629..31c9230a 100644 --- a/src/imports/controls/Menu.qml +++ b/src/imports/controls/Menu.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Controls 2.2 -import QtQuick.Controls.impl 2.2 -import QtQuick.Templates 2.2 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Templates 2.3 as T T.Menu { id: control @@ -49,6 +49,8 @@ T.Menu { margins: 0 + delegate: MenuItem { } + contentItem: ListView { implicitHeight: contentHeight model: control.contentModel diff --git a/src/imports/controls/MenuItem.qml b/src/imports/controls/MenuItem.qml index d2420d86..c60bc708 100644 --- a/src/imports/controls/MenuItem.qml +++ b/src/imports/controls/MenuItem.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Controls 2.2 -import QtQuick.Controls.impl 2.2 -import QtQuick.Templates 2.2 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Templates 2.3 as T T.MenuItem { id: control @@ -50,18 +50,25 @@ T.MenuItem { baselineOffset: contentItem.y + contentItem.baselineOffset padding: 6 + spacing: 6 - contentItem: Text { + icon.width: 24 + icon.height: 24 + icon.color: enabled ? Default.textDarkColor : Default.textDisabledColor + + contentItem: IconLabel { leftPadding: control.checkable && !control.mirrored ? control.indicator.width + control.spacing : 0 rightPadding: control.checkable && control.mirrored ? control.indicator.width + control.spacing : 0 + spacing: control.spacing + mirrored: control.mirrored + display: control.display + alignment: Qt.AlignLeft + + icon: control.icon text: control.text font: control.font color: control.enabled ? Default.textDarkColor : Default.textDisabledColor - elide: Text.ElideRight - visible: control.text - horizontalAlignment: Text.AlignLeft - verticalAlignment: Text.AlignVCenter } indicator: Image { diff --git a/src/imports/controls/MenuSeparator.qml b/src/imports/controls/MenuSeparator.qml index f0c588b2..f3916673 100644 --- a/src/imports/controls/MenuSeparator.qml +++ b/src/imports/controls/MenuSeparator.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Controls 2.2 -import QtQuick.Controls.impl 2.2 -import QtQuick.Templates 2.2 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Templates 2.3 as T T.MenuSeparator { id: control diff --git a/src/imports/controls/Page.qml b/src/imports/controls/Page.qml index 64c16bf4..4e8ce753 100644 --- a/src/imports/controls/Page.qml +++ b/src/imports/controls/Page.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Controls 2.2 -import QtQuick.Controls.impl 2.2 -import QtQuick.Templates 2.2 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Templates 2.3 as T T.Page { id: control diff --git a/src/imports/controls/PageIndicator.qml b/src/imports/controls/PageIndicator.qml index 3ff7d0c1..a702794f 100644 --- a/src/imports/controls/PageIndicator.qml +++ b/src/imports/controls/PageIndicator.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Controls 2.2 -import QtQuick.Controls.impl 2.2 -import QtQuick.Templates 2.2 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Templates 2.3 as T T.PageIndicator { id: control diff --git a/src/imports/controls/Pane.qml b/src/imports/controls/Pane.qml index 7ed7f0d8..eaad8e99 100644 --- a/src/imports/controls/Pane.qml +++ b/src/imports/controls/Pane.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Controls 2.2 -import QtQuick.Controls.impl 2.2 -import QtQuick.Templates 2.2 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Templates 2.3 as T T.Pane { id: control diff --git a/src/imports/controls/Popup.qml b/src/imports/controls/Popup.qml index 4a7a1dfd..7a94aaab 100644 --- a/src/imports/controls/Popup.qml +++ b/src/imports/controls/Popup.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Controls 2.2 -import QtQuick.Controls.impl 2.2 -import QtQuick.Templates 2.2 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Templates 2.3 as T T.Popup { id: control diff --git a/src/imports/controls/ProgressBar.qml b/src/imports/controls/ProgressBar.qml index eae6c019..78778c72 100644 --- a/src/imports/controls/ProgressBar.qml +++ b/src/imports/controls/ProgressBar.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls 2.2 -import QtQuick.Controls.impl 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 T.ProgressBar { id: control @@ -53,6 +53,7 @@ T.ProgressBar { scale: control.mirrored ? -1 : 1 progress: control.position indeterminate: control.visible && control.indeterminate + color: Default.textColor } background: Rectangle { diff --git a/src/imports/controls/RadioButton.qml b/src/imports/controls/RadioButton.qml index 878a0fe3..a0829ab6 100644 --- a/src/imports/controls/RadioButton.qml +++ b/src/imports/controls/RadioButton.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Controls 2.2 -import QtQuick.Controls.impl 2.2 -import QtQuick.Templates 2.2 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Templates 2.3 as T T.RadioButton { id: control diff --git a/src/imports/controls/RadioDelegate.qml b/src/imports/controls/RadioDelegate.qml index 03cd83bd..b3aeb2b3 100644 --- a/src/imports/controls/RadioDelegate.qml +++ b/src/imports/controls/RadioDelegate.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Controls 2.2 -import QtQuick.Controls.impl 2.2 -import QtQuick.Templates 2.2 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Templates 2.3 as T T.RadioDelegate { id: control @@ -52,17 +52,23 @@ T.RadioDelegate { padding: 12 spacing: 12 - contentItem: Text { + icon.width: 24 + icon.height: 24 + icon.color: enabled ? Default.textDarkColor : Default.textDisabledColor + + contentItem: IconLabel { leftPadding: control.mirrored ? control.indicator.width + control.spacing : 0 rightPadding: !control.mirrored ? control.indicator.width + control.spacing : 0 + spacing: control.spacing + mirrored: control.mirrored + display: control.display + alignment: control.display === IconLabel.IconOnly || control.display === IconLabel.TextUnderIcon ? Qt.AlignCenter : Qt.AlignLeft + + icon: control.icon text: control.text font: control.font color: control.enabled ? Default.textDarkColor : Default.textDisabledColor - elide: Text.ElideRight - visible: control.text - horizontalAlignment: Text.AlignLeft - verticalAlignment: Text.AlignVCenter } indicator: RadioIndicator { diff --git a/src/imports/controls/RadioIndicator.qml b/src/imports/controls/RadioIndicator.qml index d9889fba..96ff4bb6 100644 --- a/src/imports/controls/RadioIndicator.qml +++ b/src/imports/controls/RadioIndicator.qml @@ -35,8 +35,8 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Controls 2.2 -import QtQuick.Controls.impl 2.2 +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 Rectangle { implicitWidth: 28 diff --git a/src/imports/controls/RangeSlider.qml b/src/imports/controls/RangeSlider.qml index b38cb0f6..3a3c2202 100644 --- a/src/imports/controls/RangeSlider.qml +++ b/src/imports/controls/RangeSlider.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Controls 2.2 -import QtQuick.Controls.impl 2.2 -import QtQuick.Templates 2.2 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Templates 2.3 as T T.RangeSlider { id: control @@ -52,8 +52,8 @@ T.RangeSlider { padding: 6 first.handle: Rectangle { - x: control.leftPadding + (horizontal ? control.first.visualPosition * (control.availableWidth - width) : (control.availableWidth - width) / 2) - y: control.topPadding + (horizontal ? (control.availableHeight - height) / 2 : control.first.visualPosition * (control.availableHeight - height)) + x: control.leftPadding + (control.horizontal ? control.first.visualPosition * (control.availableWidth - width) : (control.availableWidth - width) / 2) + y: control.topPadding + (control.horizontal ? (control.availableHeight - height) / 2 : control.first.visualPosition * (control.availableHeight - height)) implicitWidth: 28 implicitHeight: 28 radius: width / 2 @@ -64,13 +64,11 @@ T.RangeSlider { color: control.enabled ? (first.pressed ? (activeFocus ? Default.focusPressedColor : Default.indicatorPressedColor) : (activeFocus ? Default.focusLightColor : Default.backgroundColor)) : Default.indicatorDisabledColor - - readonly property bool horizontal: control.orientation === Qt.Horizontal } second.handle: Rectangle { - x: control.leftPadding + (horizontal ? control.second.visualPosition * (control.availableWidth - width) : (control.availableWidth - width) / 2) - y: control.topPadding + (horizontal ? (control.availableHeight - height) / 2 : control.second.visualPosition * (control.availableHeight - height)) + x: control.leftPadding + (control.horizontal ? control.second.visualPosition * (control.availableWidth - width) : (control.availableWidth - width) / 2) + y: control.topPadding + (control.horizontal ? (control.availableHeight - height) / 2 : control.second.visualPosition * (control.availableHeight - height)) implicitWidth: 28 implicitHeight: 28 radius: width / 2 @@ -81,28 +79,24 @@ T.RangeSlider { color: control.enabled ? (second.pressed ? (activeFocus ? Default.focusPressedColor : Default.indicatorPressedColor) : (activeFocus ? Default.focusLightColor : Default.backgroundColor)) : Default.indicatorDisabledColor - - readonly property bool horizontal: control.orientation === Qt.Horizontal } background: Rectangle { - x: control.leftPadding + (horizontal ? 0 : (control.availableWidth - width) / 2) - y: control.topPadding + (horizontal ? (control.availableHeight - height) / 2 : 0) - implicitWidth: horizontal ? 200 : 6 - implicitHeight: horizontal ? 6 : 200 - width: horizontal ? control.availableWidth : implicitWidth - height: horizontal ? implicitHeight : control.availableHeight + x: control.leftPadding + (control.horizontal ? 0 : (control.availableWidth - width) / 2) + y: control.topPadding + (control.horizontal ? (control.availableHeight - height) / 2 : 0) + implicitWidth: control.horizontal ? 200 : 6 + implicitHeight: control.horizontal ? 6 : 200 + width: control.horizontal ? control.availableWidth : implicitWidth + height: control.horizontal ? implicitHeight : control.availableHeight radius: 3 color: Default.buttonColor - scale: horizontal && control.mirrored ? -1 : 1 - - readonly property bool horizontal: control.orientation === Qt.Horizontal + scale: control.horizontal && control.mirrored ? -1 : 1 Rectangle { - x: parent.horizontal ? control.first.position * parent.width + 3 : 0 - y: parent.horizontal ? 0 : control.second.visualPosition * parent.height + 3 - width: parent.horizontal ? control.second.position * parent.width - control.first.position * parent.width - 6 : 6 - height: parent.horizontal ? 6 : control.second.position * parent.height - control.first.position * parent.height - 6 + x: control.horizontal ? control.first.position * parent.width + 3 : 0 + y: control.horizontal ? 0 : control.second.visualPosition * parent.height + 3 + width: control.horizontal ? control.second.position * parent.width - control.first.position * parent.width - 6 : 6 + height: control.horizontal ? 6 : control.second.position * parent.height - control.first.position * parent.height - 6 color: Default.textColor } diff --git a/src/imports/controls/RoundButton.qml b/src/imports/controls/RoundButton.qml index 6b4000b1..62c5556e 100644 --- a/src/imports/controls/RoundButton.qml +++ b/src/imports/controls/RoundButton.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Controls 2.2 -import QtQuick.Controls.impl 2.2 -import QtQuick.Templates 2.2 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Templates 2.3 as T T.RoundButton { id: control @@ -49,15 +49,27 @@ T.RoundButton { baselineOffset: contentItem.y + contentItem.baselineOffset padding: 6 + spacing: 6 - contentItem: Text { + icon.width: 24 + icon.height: 24 + icon.color: Color.transparent(checked || highlighted ? Default.textLightColor + : visualFocus ? Default.focusColor + : down ? Default.textDarkColor : Default.textColor, + enabled || highlighted || checked ? 1 : 0.3) + + contentItem: IconLabel { + spacing: control.spacing + mirrored: control.mirrored + display: control.display + + icon: control.icon text: control.text font: control.font - opacity: enabled || control.highlighted || control.checked ? 1 : 0.3 - color: control.checked || control.highlighted ? Default.textLightColor : (control.visualFocus ? Default.focusColor : (control.down ? Default.textDarkColor : Default.textColor)) - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - elide: Text.ElideRight + color: Color.transparent(control.checked || control.highlighted ? Default.textLightColor + : control.visualFocus ? Default.focusColor + : control.down ? Default.textDarkColor : Default.textColor, + enabled || control.highlighted || control.checked ? 1 : 0.3) } background: Rectangle { diff --git a/src/imports/controls/ScrollBar.qml b/src/imports/controls/ScrollBar.qml index 79e3e1ee..54e9b6fa 100644 --- a/src/imports/controls/ScrollBar.qml +++ b/src/imports/controls/ScrollBar.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Controls 2.2 -import QtQuick.Controls.impl 2.2 -import QtQuick.Templates 2.2 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Templates 2.3 as T T.ScrollBar { id: control diff --git a/src/imports/controls/ScrollIndicator.qml b/src/imports/controls/ScrollIndicator.qml index 12ec2d40..c233c16f 100644 --- a/src/imports/controls/ScrollIndicator.qml +++ b/src/imports/controls/ScrollIndicator.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Controls 2.2 -import QtQuick.Controls.impl 2.2 -import QtQuick.Templates 2.2 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Templates 2.3 as T T.ScrollIndicator { id: control diff --git a/src/imports/controls/ScrollView.qml b/src/imports/controls/ScrollView.qml index e10c5328..6167801e 100644 --- a/src/imports/controls/ScrollView.qml +++ b/src/imports/controls/ScrollView.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Controls 2.2 -import QtQuick.Controls.impl 2.2 -import QtQuick.Templates 2.2 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Templates 2.3 as T T.ScrollView { id: control diff --git a/src/imports/controls/Slider.qml b/src/imports/controls/Slider.qml index 37145cad..399b25c7 100644 --- a/src/imports/controls/Slider.qml +++ b/src/imports/controls/Slider.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Controls 2.2 -import QtQuick.Controls.impl 2.2 -import QtQuick.Templates 2.2 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Templates 2.3 as T T.Slider { id: control @@ -50,8 +50,8 @@ T.Slider { padding: 6 handle: Rectangle { - x: control.leftPadding + (horizontal ? control.visualPosition * (control.availableWidth - width) : (control.availableWidth - width) / 2) - y: control.topPadding + (horizontal ? (control.availableHeight - height) / 2 : control.visualPosition * (control.availableHeight - height)) + x: control.leftPadding + (control.horizontal ? control.visualPosition * (control.availableWidth - width) : (control.availableWidth - width) / 2) + y: control.topPadding + (control.horizontal ? (control.availableHeight - height) / 2 : control.visualPosition * (control.availableHeight - height)) implicitWidth: 28 implicitHeight: 28 radius: width / 2 @@ -62,21 +62,26 @@ T.Slider { border.color: control.enabled ? (control.visualFocus ? Default.focusColor : (control.pressed ? Default.indicatorFramePressedColor : Default.indicatorFrameColor)) : Default.indicatorFrameDisabledColor - - readonly property bool horizontal: control.orientation === Qt.Horizontal } background: Rectangle { - x: control.leftPadding + (horizontal ? 0 : (control.availableWidth - width) / 2) - y: control.topPadding + (horizontal ? (control.availableHeight - height) / 2 : 0) - implicitWidth: horizontal ? 200 : 6 - implicitHeight: horizontal ? 6 : 200 - width: horizontal ? control.availableWidth : implicitWidth - height: horizontal ? implicitHeight : control.availableHeight + x: control.leftPadding + (control.horizontal ? 0 : (control.availableWidth - width) / 2) + y: control.topPadding + (control.horizontal ? (control.availableHeight - height) / 2 : 0) + implicitWidth: control.horizontal ? 200 : 6 + implicitHeight: control.horizontal ? 6 : 200 + width: control.horizontal ? control.availableWidth : implicitWidth + height: control.horizontal ? implicitHeight : control.availableHeight radius: 3 color: Default.buttonColor - scale: horizontal && control.mirrored ? -1 : 1 + scale: control.horizontal && control.mirrored ? -1 : 1 + + Rectangle { + y: control.horizontal ? 0 : control.visualPosition * parent.height + width: control.horizontal ? control.position * parent.width : 6 + height: control.horizontal ? 6 : control.position * parent.height - readonly property bool horizontal: control.orientation === Qt.Horizontal + radius: 3 + color: Default.textColor + } } } diff --git a/src/imports/controls/SpinBox.qml b/src/imports/controls/SpinBox.qml index 9aca4d7c..ef00924c 100644 --- a/src/imports/controls/SpinBox.qml +++ b/src/imports/controls/SpinBox.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Controls 2.2 -import QtQuick.Controls.impl 2.2 -import QtQuick.Templates 2.2 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Templates 2.3 as T T.SpinBox { id: control diff --git a/src/imports/controls/StackView.qml b/src/imports/controls/StackView.qml index 6d52aaed..71cf1f42 100644 --- a/src/imports/controls/StackView.qml +++ b/src/imports/controls/StackView.qml @@ -35,8 +35,8 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Controls 2.2 -import QtQuick.Templates 2.2 as T +import QtQuick.Controls 2.3 +import QtQuick.Templates 2.3 as T T.StackView { id: control diff --git a/src/imports/controls/SwipeDelegate.qml b/src/imports/controls/SwipeDelegate.qml index d9f72da9..01f21130 100644 --- a/src/imports/controls/SwipeDelegate.qml +++ b/src/imports/controls/SwipeDelegate.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Controls 2.2 -import QtQuick.Controls.impl 2.2 -import QtQuick.Templates 2.2 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Templates 2.3 as T T.SwipeDelegate { id: control @@ -52,22 +52,27 @@ T.SwipeDelegate { padding: 12 spacing: 12 + icon.width: 24 + icon.height: 24 + icon.color: control.enabled ? Default.textDarkColor : Default.textDisabledColor + swipe.transition: Transition { SmoothedAnimation { velocity: 3; easing.type: Easing.InOutCubic } } - contentItem: Text { - leftPadding: control.mirrored ? (control.indicator ? control.indicator.width : 0) + control.spacing : 0 - rightPadding: !control.mirrored ? (control.indicator ? control.indicator.width : 0) + control.spacing : 0 + contentItem: IconLabel { + spacing: control.spacing + mirrored: control.mirrored + display: control.display + alignment: control.display === IconLabel.IconOnly || control.display === IconLabel.TextUnderIcon ? Qt.AlignCenter : Qt.AlignLeft + icon: control.icon text: control.text font: control.font color: control.enabled ? Default.textDarkColor : Default.textDisabledColor - elide: Text.ElideRight - visible: control.text - horizontalAlignment: Text.AlignLeft - verticalAlignment: Text.AlignVCenter } background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 color: control.visualFocus ? (control.down ? Default.focusPressedColor : Default.delegateFocusColor) : (control.down ? Default.delegatePressedColor : Default.backgroundColor) diff --git a/src/imports/controls/SwipeView.qml b/src/imports/controls/SwipeView.qml index 4ccef22b..e395b8a2 100644 --- a/src/imports/controls/SwipeView.qml +++ b/src/imports/controls/SwipeView.qml @@ -35,8 +35,8 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Controls 2.2 -import QtQuick.Templates 2.2 as T +import QtQuick.Controls 2.3 +import QtQuick.Templates 2.3 as T T.SwipeView { id: control diff --git a/src/imports/controls/Switch.qml b/src/imports/controls/Switch.qml index 55b08039..3afa7d21 100644 --- a/src/imports/controls/Switch.qml +++ b/src/imports/controls/Switch.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls 2.2 -import QtQuick.Controls.impl 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 T.Switch { id: control diff --git a/src/imports/controls/SwitchDelegate.qml b/src/imports/controls/SwitchDelegate.qml index 6536ac53..d54c00fa 100644 --- a/src/imports/controls/SwitchDelegate.qml +++ b/src/imports/controls/SwitchDelegate.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls 2.2 -import QtQuick.Controls.impl 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 T.SwitchDelegate { id: control @@ -52,23 +52,29 @@ T.SwitchDelegate { padding: 12 spacing: 12 + icon.width: 24 + icon.height: 24 + icon.color: enabled ? Default.textDarkColor : Default.textDisabledColor + indicator: SwitchIndicator { x: text ? (control.mirrored ? control.leftPadding : control.width - width - control.rightPadding) : control.leftPadding + (control.availableWidth - width) / 2 y: control.topPadding + (control.availableHeight - height) / 2 control: control } - contentItem: Text { - leftPadding: control.indicator && !control.mirrored ? 0 : control.indicator.width + control.spacing - rightPadding: control.indicator && control.mirrored ? 0 : control.indicator.width + control.spacing + contentItem: IconLabel { + leftPadding: control.mirrored ? control.indicator.width + control.spacing : 0 + rightPadding: !control.mirrored ? control.indicator.width + control.spacing : 0 + + spacing: control.spacing + mirrored: control.mirrored + display: control.display + alignment: control.display === IconLabel.IconOnly || control.display === IconLabel.TextUnderIcon ? Qt.AlignCenter : Qt.AlignLeft + icon: control.icon text: control.text font: control.font color: control.enabled ? Default.textDarkColor : Default.textDisabledColor - elide: Text.ElideRight - visible: control.text - horizontalAlignment: Text.AlignLeft - verticalAlignment: Text.AlignVCenter } background: Rectangle { diff --git a/src/imports/controls/SwitchIndicator.qml b/src/imports/controls/SwitchIndicator.qml index 347b2293..795e68ef 100644 --- a/src/imports/controls/SwitchIndicator.qml +++ b/src/imports/controls/SwitchIndicator.qml @@ -35,8 +35,8 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Controls 2.2 -import QtQuick.Controls.impl 2.2 +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 Item { implicitWidth: 56 diff --git a/src/imports/controls/TabBar.qml b/src/imports/controls/TabBar.qml index 6e6b7d74..8b899d66 100644 --- a/src/imports/controls/TabBar.qml +++ b/src/imports/controls/TabBar.qml @@ -35,7 +35,7 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T +import QtQuick.Templates 2.3 as T T.TabBar { id: control @@ -46,7 +46,6 @@ T.TabBar { contentHeight + topPadding + bottomPadding) spacing: 1 - contentHeight: 40 contentItem: ListView { model: control.contentModel diff --git a/src/imports/controls/TabButton.qml b/src/imports/controls/TabButton.qml index acdda056..2350d0d0 100644 --- a/src/imports/controls/TabButton.qml +++ b/src/imports/controls/TabButton.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Controls 2.2 -import QtQuick.Controls.impl 2.2 -import QtQuick.Templates 2.2 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Templates 2.3 as T T.TabButton { id: control @@ -49,15 +49,22 @@ T.TabButton { baselineOffset: contentItem.y + contentItem.baselineOffset padding: 6 + spacing: 6 - contentItem: Text { + icon.width: 24 + icon.height: 24 + icon.color: Color.transparent(!checked ? Default.textLightColor : down ? Default.textDarkColor : Default.textColor, enabled ? 1 : 0.3) + + contentItem: IconLabel { + spacing: control.spacing + mirrored: control.mirrored + display: control.display + + icon: control.icon text: control.text font: control.font - elide: Text.ElideRight - opacity: enabled ? 1 : 0.3 - color: !control.checked ? Default.textLightColor : control.down ? Default.textDarkColor : Default.textColor - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter + color: Color.transparent(!control.checked ? Default.textLightColor : control.down ? Default.textDarkColor : Default.textColor, + enabled ? 1 : 0.3) } background: Rectangle { diff --git a/src/imports/controls/TextArea.qml b/src/imports/controls/TextArea.qml index cbba5912..4f30457f 100644 --- a/src/imports/controls/TextArea.qml +++ b/src/imports/controls/TextArea.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Controls 2.2 -import QtQuick.Controls.impl 2.2 -import QtQuick.Templates 2.2 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Templates 2.3 as T T.TextArea { id: control diff --git a/src/imports/controls/TextField.qml b/src/imports/controls/TextField.qml index 980ff172..4e4bd681 100644 --- a/src/imports/controls/TextField.qml +++ b/src/imports/controls/TextField.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Controls 2.2 -import QtQuick.Controls.impl 2.2 -import QtQuick.Templates 2.2 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Templates 2.3 as T T.TextField { id: control diff --git a/src/imports/controls/ToolBar.qml b/src/imports/controls/ToolBar.qml index e3d4fec3..2e5bd912 100644 --- a/src/imports/controls/ToolBar.qml +++ b/src/imports/controls/ToolBar.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Controls 2.2 -import QtQuick.Controls.impl 2.2 -import QtQuick.Templates 2.2 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Templates 2.3 as T T.ToolBar { id: control diff --git a/src/imports/controls/ToolButton.qml b/src/imports/controls/ToolButton.qml index 6199607a..345fdb9a 100644 --- a/src/imports/controls/ToolButton.qml +++ b/src/imports/controls/ToolButton.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Controls 2.2 -import QtQuick.Controls.impl 2.2 -import QtQuick.Templates 2.2 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Templates 2.3 as T T.ToolButton { id: control @@ -49,14 +49,21 @@ T.ToolButton { baselineOffset: contentItem.y + contentItem.baselineOffset padding: 6 + spacing: 6 - contentItem: Text { + icon.width: 24 + icon.height: 24 + icon.color: enabled ? (visualFocus ? Default.focusColor : Default.textDarkColor) : Default.textDisabledLightColor + + contentItem: IconLabel { + spacing: control.spacing + mirrored: control.mirrored + display: control.display + + icon: control.icon text: control.text font: control.font color: control.enabled ? (control.visualFocus ? Default.focusColor : Default.textDarkColor) : Default.textDisabledLightColor - elide: Text.ElideRight - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter } background: Rectangle { diff --git a/src/imports/controls/ToolSeparator.qml b/src/imports/controls/ToolSeparator.qml index 3c588558..b1d5dd7b 100644 --- a/src/imports/controls/ToolSeparator.qml +++ b/src/imports/controls/ToolSeparator.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Controls 2.2 -import QtQuick.Controls.impl 2.2 -import QtQuick.Templates 2.2 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Templates 2.3 as T T.ToolSeparator { id: control diff --git a/src/imports/controls/ToolTip.qml b/src/imports/controls/ToolTip.qml index 587fc042..5e3614b2 100644 --- a/src/imports/controls/ToolTip.qml +++ b/src/imports/controls/ToolTip.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Controls 2.2 -import QtQuick.Controls.impl 2.2 -import QtQuick.Templates 2.2 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Templates 2.3 as T T.ToolTip { id: control diff --git a/src/imports/controls/Tumbler.qml b/src/imports/controls/Tumbler.qml index 3659e770..be69c9e0 100644 --- a/src/imports/controls/Tumbler.qml +++ b/src/imports/controls/Tumbler.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Controls 2.2 -import QtQuick.Controls.impl 2.2 -import QtQuick.Templates 2.2 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Templates 2.3 as T T.Tumbler { id: control diff --git a/src/imports/controls/controls.pri b/src/imports/controls/controls.pri index 1dfe1911..8c127643 100644 --- a/src/imports/controls/controls.pri +++ b/src/imports/controls/controls.pri @@ -1,20 +1,25 @@ HEADERS += \ - $$PWD/qquickdialring_p.h \ $$PWD/qquickdefaultbusyindicator_p.h \ + $$PWD/qquickdefaultdial_p.h \ $$PWD/qquickdefaultprogressbar_p.h \ - $$PWD/qquickdefaultstyle_p.h + $$PWD/qquickdefaultstyle_p.h \ + $$PWD/qquickdefaulttheme_p.h SOURCES += \ - $$PWD/qquickdialring.cpp \ $$PWD/qquickdefaultbusyindicator.cpp \ + $$PWD/qquickdefaultdial.cpp \ $$PWD/qquickdefaultprogressbar.cpp \ - $$PWD/qquickdefaultstyle.cpp + $$PWD/qquickdefaultstyle.cpp \ + $$PWD/qquickdefaulttheme.cpp QML_CONTROLS = \ $$PWD/AbstractButton.qml \ + $$PWD/Action.qml \ + $$PWD/ActionGroup.qml \ $$PWD/ApplicationWindow.qml \ $$PWD/BusyIndicator.qml \ $$PWD/Button.qml \ + $$PWD/ButtonGroup.qml \ $$PWD/CheckBox.qml \ $$PWD/CheckDelegate.qml \ $$PWD/CheckIndicator.qml \ diff --git a/src/imports/controls/controls.pro b/src/imports/controls/controls.pro index 8024bbf8..b75e4f56 100644 --- a/src/imports/controls/controls.pro +++ b/src/imports/controls/controls.pro @@ -1,6 +1,6 @@ TARGET = qtquickcontrols2plugin TARGETPATH = QtQuick/Controls.2 -IMPORT_VERSION = 2.2 +IMPORT_VERSION = 2.3 QT += qml quick QT_PRIVATE += core-private gui-private qml-private quick-private quicktemplates2-private quickcontrols2-private diff --git a/src/imports/controls/dependencies.json b/src/imports/controls/dependencies.json index 4c9cfcd3..8cec519e 100644 --- a/src/imports/controls/dependencies.json +++ b/src/imports/controls/dependencies.json @@ -12,6 +12,6 @@ { "name": "QtQuick.Templates", "type": "module", - "version": "2.2" + "version": "2.3" } ] diff --git a/src/imports/controls/doc/images/qtquickcontrols2-button-icononly.png b/src/imports/controls/doc/images/qtquickcontrols2-button-icononly.png Binary files differnew file mode 100644 index 00000000..91a21d17 --- /dev/null +++ b/src/imports/controls/doc/images/qtquickcontrols2-button-icononly.png diff --git a/src/imports/controls/doc/images/qtquickcontrols2-button-textbesideicon.png b/src/imports/controls/doc/images/qtquickcontrols2-button-textbesideicon.png Binary files differnew file mode 100644 index 00000000..1d46133f --- /dev/null +++ b/src/imports/controls/doc/images/qtquickcontrols2-button-textbesideicon.png diff --git a/src/imports/controls/doc/images/qtquickcontrols2-button-textonly.png b/src/imports/controls/doc/images/qtquickcontrols2-button-textonly.png Binary files differnew file mode 100644 index 00000000..4449e748 --- /dev/null +++ b/src/imports/controls/doc/images/qtquickcontrols2-button-textonly.png diff --git a/src/imports/controls/doc/images/qtquickcontrols2-fusion-palettes.png b/src/imports/controls/doc/images/qtquickcontrols2-fusion-palettes.png Binary files differnew file mode 100644 index 00000000..d649e137 --- /dev/null +++ b/src/imports/controls/doc/images/qtquickcontrols2-fusion-palettes.png diff --git a/src/imports/controls/doc/images/qtquickcontrols2-fusion-violet.png b/src/imports/controls/doc/images/qtquickcontrols2-fusion-violet.png Binary files differnew file mode 100644 index 00000000..4186a78f --- /dev/null +++ b/src/imports/controls/doc/images/qtquickcontrols2-fusion-violet.png diff --git a/src/imports/controls/doc/images/qtquickcontrols2-fusion.png b/src/imports/controls/doc/images/qtquickcontrols2-fusion.png Binary files differnew file mode 100644 index 00000000..037069b5 --- /dev/null +++ b/src/imports/controls/doc/images/qtquickcontrols2-fusion.png diff --git a/src/imports/controls/doc/snippets/qtquickcontrols2-action.qml b/src/imports/controls/doc/snippets/qtquickcontrols2-action.qml new file mode 100644 index 00000000..e4ef4f5b --- /dev/null +++ b/src/imports/controls/doc/snippets/qtquickcontrols2-action.qml @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: https://www.gnu.org/licenses/fdl-1.3.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.9 +import QtQuick.Controls 2.3 + +Item { + //! [action] + Action { + id: copyAction + text: qsTr("&Copy") + icon.name: "edit-copy" + shortcut: StandardKey.Copy + onTriggered: window.activeFocusItem.copy() + } + //! [action] + + //! [toolbutton] + ToolButton { + id: toolButton + action: copyAction + } + //! [toolbutton] + + //! [menuitem] + MenuItem { + id: menuItem + action: copyAction + text: qsTr("&Copy selected Text") + } + //! [menuitem] +} diff --git a/src/imports/controls/doc/snippets/qtquickcontrols2-button-icononly.qml b/src/imports/controls/doc/snippets/qtquickcontrols2-button-icononly.qml new file mode 100644 index 00000000..0a58d4ad --- /dev/null +++ b/src/imports/controls/doc/snippets/qtquickcontrols2-button-icononly.qml @@ -0,0 +1,34 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.9 +import QtQuick.Controls 2.3 + +Button { + icon.source: "qrc:/qt-project.org/imports/QtQuick/Controls.2/images/check.png" + display: Button.IconOnly +} diff --git a/src/imports/controls/doc/snippets/qtquickcontrols2-button-textbesideicon.qml b/src/imports/controls/doc/snippets/qtquickcontrols2-button-textbesideicon.qml new file mode 100644 index 00000000..308837f7 --- /dev/null +++ b/src/imports/controls/doc/snippets/qtquickcontrols2-button-textbesideicon.qml @@ -0,0 +1,35 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.9 +import QtQuick.Controls 2.3 + +Button { + text: "Button" + icon.source: "qrc:/qt-project.org/imports/QtQuick/Controls.2/images/check.png" + display: Button.TextBesideIcon +} diff --git a/src/imports/controls/doc/snippets/qtquickcontrols2-button-textonly.qml b/src/imports/controls/doc/snippets/qtquickcontrols2-button-textonly.qml new file mode 100644 index 00000000..89d335e4 --- /dev/null +++ b/src/imports/controls/doc/snippets/qtquickcontrols2-button-textonly.qml @@ -0,0 +1,34 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.9 +import QtQuick.Controls 2.3 + +Button { + text: "Button" + display: Button.TextOnly +} diff --git a/src/imports/controls/doc/src/includes/qquickicon.qdocinc b/src/imports/controls/doc/src/includes/qquickicon.qdocinc new file mode 100644 index 00000000..a6ab90bb --- /dev/null +++ b/src/imports/controls/doc/src/includes/qquickicon.qdocinc @@ -0,0 +1,42 @@ +//! [grouped-properties] +\table +\header + \li Name + \li Description +\row + \li name + \li This property holds the name of the icon to use. + + The icon will be loaded from the platform theme. If the icon is found + in the theme, it will always be used; even if \l icon.source is also set. + If the icon is not found, \l icon.source will be used instead. + + For more information on theme icons, see \l {QIcon::fromTheme()}. +\row + \li source + \li This property holds the name of the icon to use. + + The icon will be loaded as a regular image. + + If \l icon.name is set and refers to a valid theme icon, it will always + be used instead of this property. +\row + \li width + \li This property holds the width of the icon. + + The icon's width will never exceed this value, though it will + shrink when necessary. +\row + \li height + \li This property holds the height of the icon. + + The icon's height will never exceed this value, though it will + shrink when necessary. +\row + \li color + \li This property holds the color of the icon. + + The icon is tinted with the specified color, unless the color is + set to \c "transparent". +\endtable +//! [grouped-properties] diff --git a/src/imports/controls/doc/src/qtquickcontrols2-configuration.qdoc b/src/imports/controls/doc/src/qtquickcontrols2-configuration.qdoc index 36bce98d..358b09ce 100644 --- a/src/imports/controls/doc/src/qtquickcontrols2-configuration.qdoc +++ b/src/imports/controls/doc/src/qtquickcontrols2-configuration.qdoc @@ -63,6 +63,136 @@ \include qquickuniversalstyle.qdocinc conf + The default \l {Control::font}{font} can be specified in a \c Font sub-group + in each style's section in the configuration file. The \c Font sub-group can + be defined in two alternative ways: + + \code + [Default] + Font\Family=Open Sans + Font\PixelSize=20 + + [Material\Font] + Family=Open Sans + PixelSize=20 + \endcode + + Supported font attributes: + \table + \header + \li Variable + \li Description + \row + \li \c Family + \li The \l {QFont::family}{font family}. + \row + \li \c PointSize + \li The \l {QFont::pointSizeF}{point size}. + \row + \li \c PixelSize + \li The \l {QFont::pixelSize}{pixel size}. + \row + \li \c StyleHint + \li The \l {QFont::styleHint}{style hint}. + Available values: \c SansSerif, \c Helvetica, \c Serif, \c Times, \c TypeWriter, \c Courier, + \c OldEnglish, \c Decorative, \c Monospace, \c Fantasy, \c Cursive. + \row + \li \c Weight + \li The \l {QFont::}{weight}. Qt uses a weighting scale from \c 0 to \c 99 similar to, + but not the same as, the scales used in Windows or CSS. A weight of \c 0 will be thin, + whilst \c 99 will be extremely black. + Available pre-defined weights: \c Thin (0), \c ExtraLight (12), \c Light (25), \c Normal (50), + \c Medium (57), \c DemiBold (63), \c Bold (75), \c ExtraBold (81), + \c Black (87). + \row + \li \c Style + \li The \l {QFont::}{style}. + Available values: \c StyleNormal, \c StyleItalic, \c StyleOblique. + \endtable + + The default \l {Control::palette}{palette} can be specified in a \c Palette sub-group + in each style's section in the configuration file. The \c Palette sub-group can be + defined in two alternative ways: + + \code + [Fusion] + Palette\Window=#dedede + Palette\WindowText=#212121 + \endcode + + or: + \code + [Fusion\Palette] + Window=#dedede + WindowText=#212121 + \endcode + + Supported palette attributes: + \table + \header + \li Variable + \li Description + \row + \li \l {QPalette::ColorRole}{\c Window} + \li A general background color. + \row + \li \l {QPalette::ColorRole}{\c WindowText} + \li A general foreground color. + \row + \li \l {QPalette::ColorRole}{\c Base} + \li Used mostly as the background color for text editor controls and items views. + It is usually white or another light color. + \row + \li \l {QPalette::ColorRole}{\c Text} + \li The foreground color used with \c Base. This is usually the same as the \c WindowText, + in which case it must provide good contrast with \c Window and \c Base. + \row + \li \l {QPalette::ColorRole}{\c Button} + \li The general button background color. This background can be different from \c Window + as some styles require a different background color for buttons. + \row + \li \l {QPalette::ColorRole}{\c ButtonText} + \li A foreground color used with the \c Button color. + \row + \li \l {QPalette::ColorRole}{\c BrightText} + \li A text color that is very different from \c WindowText, and contrasts well with e.g. \c Dark. + Typically used for text that needs to be drawn where \c Text, \c WindowText or \c ButtonText + would give poor contrast, such as on highlighted buttons. + \row + \li \l {QPalette::ColorRole}{\c ToolTipBase} + \li Used as the background color for tooltips. + \row + \li \l {QPalette::ColorRole}{\c ToolTipText} + \li Used as the foreground color for tooltips. + + \row + \li \l {QPalette::ColorRole}{\c Light} + \li Lighter than \c Button. + \row + \li \l {QPalette::ColorRole}{\c Midlight} + \li Between \c Button and \c Light. + \row + \li \l {QPalette::ColorRole}{\c Dark} + \li Darker than \c Button. + \row + \li \l {QPalette::ColorRole}{\c Mid} + \li Between \c Button and \c Dark. + \row + \li \l {QPalette::ColorRole}{\c Shadow} + \li A very dark color. + + \row + \li \l {QPalette::ColorRole}{\c Highlight} + \li A color to indicate a selected item or the current item. + \row + \li \l {QPalette::ColorRole}{\c HighlightedText} + \li A text color that contrasts with \c Highlight. + + \row + \li \l {QPalette::ColorRole}{\c Link} + \li A text color used for hyperlinks. + \endtable + In order to make it possible for Qt Quick Controls 2 to find the configuration file, it must be built into application's resources using the \l {The Qt Resource System}. Here's an example \c .qrc file: diff --git a/src/imports/controls/doc/src/qtquickcontrols2-differences.qdoc b/src/imports/controls/doc/src/qtquickcontrols2-differences.qdoc index e6e2977f..419fd991 100644 --- a/src/imports/controls/doc/src/qtquickcontrols2-differences.qdoc +++ b/src/imports/controls/doc/src/qtquickcontrols2-differences.qdoc @@ -203,15 +203,9 @@ \li Remarks \row \li \l [QML QtQuickControls] {Action} - \li \mdash + \li \l [QML QtQuickControls2] {Action} \li \l [QML QtQuick] {Shortcut} \br\sup {(Qt Quick)} - \li \list - \li \b {Qt Quick Controls 1}: \c Action is an abstract user interface - action that is bound to buttons and menu items, and can provide - shortcuts. - \li \b {Qt Quick}: \c Shortcut provides the shortcut functionality that - was previously only provided by \c Action. - \endlist + \li \row \li \l [QML QtQuickControls] {ApplicationWindow} \li \l [QML QtQuickControls2] {ApplicationWindow} @@ -250,9 +244,10 @@ \row \li \l [QML QtQuickControls] {ExclusiveGroup} \li \mdash - \li \l [QML QtQuickControls2] {ButtonGroup} \br\sup {(Qt Quick Controls 2)} + \li \l [QML QtQuickControls2] {ActionGroup},\br + \l [QML QtQuickControls2] {ButtonGroup} \br\sup {(Qt Quick Controls 2)} \li \list - \li \b {Qt Quick Controls 2}: \c ButtonGroup offers similar functionality. + \li \b {Qt Quick Controls 2}: \c ActionGroup and \c ButtonGroup offer similar functionality. \endlist \row \li \l [QML QtQuickControls] {GroupBox} @@ -521,6 +516,13 @@ \li \row \li \mdash + \li \l [QML QtQuickControls2] {ActionGroup} + \li \l [QML QtQuickControls] {ExclusiveGroup} \br\sup {(Qt Quick Controls 1)} + \li \list + \li \b {Qt Quick Controls 1}: \c ExclusiveGroup offers similar functionality. + \endlist + \row + \li \mdash \li \l [QML QtQuickControls2] {ButtonGroup} \li \l [QML QtQuickControls] {ExclusiveGroup} \br\sup {(Qt Quick Controls 1)} \li \list diff --git a/src/imports/controls/doc/src/qtquickcontrols2-fusion.qdoc b/src/imports/controls/doc/src/qtquickcontrols2-fusion.qdoc new file mode 100644 index 00000000..d5d6657a --- /dev/null +++ b/src/imports/controls/doc/src/qtquickcontrols2-fusion.qdoc @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: https://www.gnu.org/licenses/fdl-1.3.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \page qtquickcontrols2-fusion.html + \title Fusion Style + + The Fusion style is a desktop-oriented style. + + The Fusion style is a platform-agnostic style that offers a desktop-oriented + look'n'feel. It implements the same design language as the \l {Fusion Style Widget Gallery} + {Fusion style for Qt Widgets}. + + \image qtquickcontrols2-fusion.png + + To run an application with the Fusion style, see + \l {Using Styles in Qt Quick Controls 2}. + + \note The Fusion style is not a native desktop style. The style runs on any + platform, and looks similar everywhere. Minor differences may occur due to + differences in the standard system palettes, available fonts, and font + rendering engines. + + \section2 Customization + + The Fusion style uses the standard system \l {Control::palette}{palettes} + to provide colors that match the desktop environment. + + \image qtquickcontrols2-fusion-palettes.png + + Custom palettes can be specified for any \l {Control::palette}{control}, + \l {Popup::palette}{popup}, or \l {ApplicationWindow::palette}{application window}. + Explicit palette attributes are automatically propagated from parent to children, + overriding any system defaults for that attribute. In the following example, + the window and all three switches appear with a violet highlight color: + + \table + \row + \li + \qml + import QtQuick 2.7 + import QtQuick.Controls 2.3 + + ApplicationWindow { + visible: true + + palette.highlight: "violet" + + Column { + anchors.centerIn: parent + + Switch { text: qsTr("First"); checked: true } + Switch { text: qsTr("Second"); checked: true } + Switch { text: qsTr("Third") } + } + } + \endqml + \li + \image qtquickcontrols2-fusion-violet.png + \endtable + + \b {See also} \l {Default Style}, \l {Material Style}, \l {Universal Style} + + \section1 Related Information + + \list + \li \l{Styling Qt Quick Controls 2} + \endlist +*/ diff --git a/src/imports/controls/doc/src/qtquickcontrols2-index.qdoc b/src/imports/controls/doc/src/qtquickcontrols2-index.qdoc index 868e77e0..81318cde 100644 --- a/src/imports/controls/doc/src/qtquickcontrols2-index.qdoc +++ b/src/imports/controls/doc/src/qtquickcontrols2-index.qdoc @@ -46,21 +46,31 @@ <img src="images/qtquickcontrols2-default.png" alt="Default" width="100%"/> </a> </td> - <td style="border:0px; padding-right:25px;"> + <td style="border:0px"> <a href="qtquickcontrols2-material.html"> <img src="images/qtquickcontrols2-material.png" alt="Material" width="100%"/> </a> </td> - <td style="border:0px;"> + </tr> + <tr> + <td style="border:0px">Default Style</td> + <td style="border:0px">Material Style</td> + </tr> + <tr> + <td style="border:0px; padding-top:45px; padding-right:25px;"> + <a href="qtquickcontrols2-fusion.html"> + <img src="images/qtquickcontrols2-fusion.png" alt="Fusion" width="100%"/> + </a> + </td> + <td style="border:0px; padding-top:45px; "> <a href="qtquickcontrols2-universal.html"> <img src="images/qtquickcontrols2-universal.png" alt="Universal" width="100%"/> </a> </td> </tr> <tr> - <td style="border:0px">Default</td> - <td style="border:0px">Material</td> - <td style="border:0px">Universal</td> + <td style="border:0px">Fusion Style</td> + <td style="border:0px">Universal Style</td> </tr> </table> \endraw @@ -71,7 +81,7 @@ application using the following import statement in your \c {.qml} file: \code - import QtQuick.Controls 2.2 + import QtQuick.Controls 2.3 \endcode The \l{Qt Quick Controls 2 C++ Classes}{C++ classes} can be included into @@ -122,6 +132,11 @@ \li 2.2 \li 1.0 \row + \li 5.10 + \li 2.10 + \li 2.3 + \li 1.0 + \row \li ... \li ... \li ... diff --git a/src/imports/controls/doc/src/qtquickcontrols2-material.qdoc b/src/imports/controls/doc/src/qtquickcontrols2-material.qdoc index 065f3fe9..f661a28d 100644 --- a/src/imports/controls/doc/src/qtquickcontrols2-material.qdoc +++ b/src/imports/controls/doc/src/qtquickcontrols2-material.qdoc @@ -32,7 +32,7 @@ The Material Style is based on the Google Material Design Guidelines. \l{detailed-desc-material}{More...} - \styleimport {QtQuick.Controls.Material 2.2} {Qt 5.7} + \styleimport {QtQuick.Controls.Material 2.3} {Qt 5.7} \section1 Attached Properties diff --git a/src/imports/controls/doc/src/qtquickcontrols2-qmltypes.qdoc b/src/imports/controls/doc/src/qtquickcontrols2-qmltypes.qdoc index 3b69da04..4bdccecc 100644 --- a/src/imports/controls/doc/src/qtquickcontrols2-qmltypes.qdoc +++ b/src/imports/controls/doc/src/qtquickcontrols2-qmltypes.qdoc @@ -26,7 +26,7 @@ ****************************************************************************/ /*! - \qmlmodule QtQuick.Controls 2.2 + \qmlmodule QtQuick.Controls 2.3 \title Qt Quick Controls 2 QML Types \ingroup qmlmodules \brief Provides QML types for user interfaces (Qt Quick Controls 2). @@ -39,7 +39,7 @@ using the following import statement in your .qml file: \badcode - import QtQuick.Controls 2.2 + import QtQuick.Controls 2.3 \endcode \section1 QML Types diff --git a/src/imports/controls/doc/src/qtquickcontrols2-styles.qdoc b/src/imports/controls/doc/src/qtquickcontrols2-styles.qdoc index 42d8bc62..472b02c9 100644 --- a/src/imports/controls/doc/src/qtquickcontrols2-styles.qdoc +++ b/src/imports/controls/doc/src/qtquickcontrols2-styles.qdoc @@ -34,7 +34,7 @@ \raw HTML <table style="background:transparent; border:0px"> <tr> - <td style="border:0px"> + <td style="border:0px; padding-right:25px"> <a href="qtquickcontrols2-default.html"> <img src="images/qtquickcontrols2-default.png" width="45%"/> </a> @@ -44,11 +44,6 @@ <img src="images/qtquickcontrols2-material.png" width="75%"/> </a> </td> - <td style="border:0px"> - <a href="qtquickcontrols2-universal.html"> - <img src="images/qtquickcontrols2-universal.png" width="75%"/> - </a> - </td> </tr> <tr> <td style="border:0px"> @@ -61,6 +56,25 @@ based on the <a href="https://www.google.com/design/spec/material-design/introduction.html"> Google Material Design Guidelines</a>, but requires more system resources than the Default style. </td> + </tr> + <tr> + <td style="border:0px; padding-top:45px; padding-right:25px;"> + <a href="qtquickcontrols2-fusion.html"> + <img src="images/qtquickcontrols2-fusion.png" width="75%"/> + </a> + </td> + <td style="border:0px; padding-top:45px;"> + <a href="qtquickcontrols2-universal.html"> + <img src="images/qtquickcontrols2-universal.png" width="75%"/> + </a> + </td> + </tr> + <tr> + <td style="border:0px"> + The <a href="qtquickcontrols2-fusion.html">Fusion</a> style is + a platform-agnostic style that offers a desktop-oriented look'n'feel + for Qt Quick Controls 2. + </td> <td style="border:0px"> The <a href="qtquickcontrols2-universal.html">Universal</a> style offers an appealing design based on the <a href="https://dev.windows.com/design">Microsoft Universal Design Guidelines</a>, @@ -136,6 +150,7 @@ \section1 Related Information \list \li \l {Default Style} + \li \l {Fusion Style} \li \l {Material Style} \li \l {Universal Style} \li \l {Using File Selectors with Qt Quick Controls 2} diff --git a/src/imports/controls/doc/src/qtquickcontrols2-universal.qdoc b/src/imports/controls/doc/src/qtquickcontrols2-universal.qdoc index 8f3d2330..b4fe4dfa 100644 --- a/src/imports/controls/doc/src/qtquickcontrols2-universal.qdoc +++ b/src/imports/controls/doc/src/qtquickcontrols2-universal.qdoc @@ -32,7 +32,7 @@ The Universal Style is based on the Microsoft Universal Design Guidelines. \l {detailed-desc-universal}{More...} - \styleimport {QtQuick.Controls.Universal 2.2} {Qt 5.7} + \styleimport {QtQuick.Controls.Universal 2.3} {Qt 5.7} \section1 Attached Properties diff --git a/src/imports/controls/fusion/ApplicationWindow.qml b/src/imports/controls/fusion/ApplicationWindow.qml new file mode 100644 index 00000000..8ba73b1d --- /dev/null +++ b/src/imports/controls/fusion/ApplicationWindow.qml @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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.9 +import QtQuick.Window 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls.Fusion 2.3 +import QtQuick.Controls.Fusion.impl 2.3 + +T.ApplicationWindow { + id: window + + color: palette.window + + overlay.modal: Rectangle { + color: Fusion.topShadow + } + + overlay.modeless: Rectangle { + color: Fusion.topShadow + } +} diff --git a/src/imports/controls/fusion/BusyIndicator.qml b/src/imports/controls/fusion/BusyIndicator.qml new file mode 100644 index 00000000..89c08ca8 --- /dev/null +++ b/src/imports/controls/fusion/BusyIndicator.qml @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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.9 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Fusion 2.3 +import QtQuick.Controls.Fusion.impl 2.3 + +T.BusyIndicator { + id: control + + implicitWidth: contentItem.implicitWidth + leftPadding + rightPadding + implicitHeight: contentItem.implicitHeight + topPadding + bottomPadding + + padding: 6 + + contentItem: BusyIndicatorImpl { + implicitWidth: 28 + implicitHeight: 28 + color: control.palette.text + + opacity: control.running ? 1 : 0 + visible: control.running || opacityAnimator.running + Behavior on opacity { OpacityAnimator { id: opacityAnimator; duration: 250 } } + + RotationAnimator on rotation { + running: control.running || opacityAnimator.running + from: 0 + to: 360 + duration: 1000 + loops: Animation.Infinite + } + } +} diff --git a/src/imports/controls/fusion/Button.qml b/src/imports/controls/fusion/Button.qml new file mode 100644 index 00000000..e402d64e --- /dev/null +++ b/src/imports/controls/fusion/Button.qml @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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.9 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Fusion 2.3 +import QtQuick.Controls.Fusion.impl 2.3 + +T.Button { + id: control + + implicitWidth: Math.max(background ? background.implicitWidth : 0, + contentItem.implicitWidth + leftPadding + rightPadding) + implicitHeight: Math.max(background ? background.implicitHeight : 0, + contentItem.implicitHeight + topPadding + bottomPadding) + baselineOffset: contentItem.y + contentItem.baselineOffset + + padding: 4 + spacing: 6 + + icon.width: 16 + icon.height: 16 + + contentItem: IconLabel { + spacing: control.spacing + mirrored: control.mirrored + display: control.display + + icon: control.icon + text: control.text + font: control.font + color: control.palette.buttonText + } + + background: ButtonPanel { + implicitWidth: 80 + implicitHeight: 24 + + control: control + visible: !control.flat || control.down || control.checked || control.highlighted || control.visualFocus || control.hovered + } +} diff --git a/src/imports/controls/fusion/ButtonPanel.qml b/src/imports/controls/fusion/ButtonPanel.qml new file mode 100644 index 00000000..c590756e --- /dev/null +++ b/src/imports/controls/fusion/ButtonPanel.qml @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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.9 +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Fusion 2.3 +import QtQuick.Controls.Fusion.impl 2.3 + +Rectangle { + id: panel + + property Item control + property bool highlighted: control.highlighted + + visible: !control.flat || control.down || control.checked + + color: Fusion.buttonColor(control.palette, panel.highlighted, control.down || control.checked, control.hovered) + gradient: control.down || control.checked ? null : buttonGradient + + Gradient { + id: buttonGradient + GradientStop { + position: 0 + color: Fusion.gradientStart(Fusion.buttonColor(control.palette, panel.highlighted, control.down, control.hovered)) + } + GradientStop { + position: 1 + color: Fusion.gradientStop(Fusion.buttonColor(control.palette, panel.highlighted, control.down, control.hovered)) + } + } + + radius: 2 + border.color: Fusion.buttonOutline(control.palette, panel.highlighted || control.visualFocus, control.enabled) + + Rectangle { + x: 1; y: 1 + width: parent.width - 2 + height: parent.height - 2 + border.color: Fusion.innerContrastLine + color: "transparent" + radius: 2 + } +} diff --git a/src/imports/controls/fusion/CheckBox.qml b/src/imports/controls/fusion/CheckBox.qml new file mode 100644 index 00000000..235e2efa --- /dev/null +++ b/src/imports/controls/fusion/CheckBox.qml @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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.9 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Fusion 2.3 +import QtQuick.Controls.Fusion.impl 2.3 + +T.CheckBox { + id: control + + implicitWidth: Math.max(background ? background.implicitWidth : 0, + contentItem.implicitWidth + leftPadding + rightPadding) + implicitHeight: Math.max(background ? background.implicitHeight : 0, + Math.max(contentItem.implicitHeight, + indicator ? indicator.implicitHeight : 0) + topPadding + bottomPadding) + baselineOffset: contentItem.y + contentItem.baselineOffset + + padding: 6 + spacing: 6 + + indicator: CheckIndicator { + x: text ? (control.mirrored ? control.width - width - control.rightPadding : control.leftPadding) : control.leftPadding + (control.availableWidth - width) / 2 + y: control.topPadding + (control.availableHeight - height) / 2 + control: control + } + + contentItem: Text { + leftPadding: control.indicator && !control.mirrored ? control.indicator.width + control.spacing : 0 + rightPadding: control.indicator && control.mirrored ? control.indicator.width + control.spacing : 0 + + text: control.text + font: control.font + color: control.palette.windowText + elide: Text.ElideRight + visible: control.text + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } +} diff --git a/src/imports/controls/fusion/CheckDelegate.qml b/src/imports/controls/fusion/CheckDelegate.qml new file mode 100644 index 00000000..8841d5bf --- /dev/null +++ b/src/imports/controls/fusion/CheckDelegate.qml @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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.9 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Fusion 2.3 +import QtQuick.Controls.Fusion.impl 2.3 + +T.CheckDelegate { + id: control + + implicitWidth: Math.max(background ? background.implicitWidth : 0, + contentItem.implicitWidth + leftPadding + rightPadding) + implicitHeight: Math.max(background ? background.implicitHeight : 0, + Math.max(contentItem.implicitHeight, + indicator ? indicator.implicitHeight : 0) + topPadding + bottomPadding) + baselineOffset: contentItem.y + contentItem.baselineOffset + + padding: 6 + spacing: 6 + + icon.width: 16 + icon.height: 16 + + contentItem: IconLabel { + leftPadding: control.mirrored ? control.indicator.width + control.spacing : 0 + rightPadding: !control.mirrored ? control.indicator.width + control.spacing : 0 + + spacing: control.spacing + mirrored: control.mirrored + display: control.display + alignment: control.display === IconLabel.IconOnly || control.display === IconLabel.TextUnderIcon ? Qt.AlignCenter : Qt.AlignLeft + + icon: control.icon + text: control.text + font: control.font + color: control.highlighted ? Fusion.highlightedText(control.palette) : control.palette.text + } + + indicator: CheckIndicator { + x: control.mirrored ? control.leftPadding : control.width - width - control.rightPadding + y: control.topPadding + (control.availableHeight - height) / 2 + + control: control + } + + background: Rectangle { + implicitWidth: 100 + implicitHeight: 20 + color: control.down ? Fusion.buttonColor(control.palette, false, true, true) + : control.highlighted ? Fusion.highlight(control.palette) : control.palette.base + } +} diff --git a/src/imports/controls/fusion/CheckIndicator.qml b/src/imports/controls/fusion/CheckIndicator.qml new file mode 100644 index 00000000..54175205 --- /dev/null +++ b/src/imports/controls/fusion/CheckIndicator.qml @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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.9 +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Fusion 2.3 +import QtQuick.Controls.Fusion.impl 2.3 + +Rectangle { + id: indicator + + property Item control + readonly property color pressedColor: Fusion.mergedColors(control.palette.base, control.palette.windowText, 85) + readonly property color checkMarkColor: Qt.darker(control.palette.text, 1.2) + + implicitWidth: 14 + implicitHeight: 14 + + color: control.down ? indicator.pressedColor : control.palette.base + border.color: control.visualFocus ? Fusion.highlightedOutline(control.palette) + : Qt.lighter(Fusion.outline(control.palette), 1.1) + + Rectangle { + x: 1; y: 1 + width: parent.width - 2 + height: 1 + color: Fusion.topShadow + visible: control.enabled && !control.down + } + + ColorImage { + x: (parent.width - width) / 2 + y: (parent.height - height) / 2 + color: Color.transparent(indicator.checkMarkColor, 210 / 255) + source: "qrc:/qt-project.org/imports/QtQuick/Controls.2/Fusion/images/checkmark.png" + visible: control.checkState === Qt.Checked || (control.checked && control.checkState === undefined) + } + + Rectangle { + x: 3; y: 3 + width: parent.width - 6 + height: parent.width - 6 + + visible: control.checkState === Qt.PartiallyChecked + + gradient: Gradient { + GradientStop { + position: 0 + color: Color.transparent(indicator.checkMarkColor, 80 / 255) + } + GradientStop { + position: 1 + color: Color.transparent(indicator.checkMarkColor, 140 / 255) + } + } + border.color: Color.transparent(indicator.checkMarkColor, 180 / 255) + } +} diff --git a/src/imports/controls/fusion/ComboBox.qml b/src/imports/controls/fusion/ComboBox.qml new file mode 100644 index 00000000..3244678a --- /dev/null +++ b/src/imports/controls/fusion/ComboBox.qml @@ -0,0 +1,177 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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.9 +import QtQuick.Window 2.3 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Fusion 2.3 +import QtQuick.Controls.Fusion.impl 2.3 + +T.ComboBox { + id: control + + implicitWidth: Math.max(background ? background.implicitWidth : 0, + contentItem.implicitWidth + leftPadding + rightPadding) + implicitHeight: Math.max(background ? background.implicitHeight : 0, + Math.max(contentItem.implicitHeight, + indicator ? indicator.implicitHeight : 0) + topPadding + bottomPadding) + baselineOffset: contentItem.y + contentItem.baselineOffset + + leftPadding: padding + (!control.mirrored || !indicator || !indicator.visible ? 0 : indicator.width + spacing) + rightPadding: padding + (control.mirrored || !indicator || !indicator.visible ? 0 : indicator.width + spacing) + + delegate: MenuItem { + width: parent.width + text: control.textRole ? (Array.isArray(control.model) ? modelData[control.textRole] : model[control.textRole]) : modelData + highlighted: control.highlightedIndex === index + hoverEnabled: control.hoverEnabled + } + + indicator: ColorImage { + x: control.mirrored ? control.padding : control.width - width - control.padding + y: control.topPadding + (control.availableHeight - height) / 2 + color: control.editable ? control.palette.text : control.palette.buttonText + source: "qrc:/qt-project.org/imports/QtQuick/Controls.2/Fusion/images/arrow.png" + width: 20 + fillMode: Image.Pad + } + + contentItem: T.TextField { + topPadding: 4 + leftPadding: 4 - control.padding + rightPadding: 4 - control.padding + bottomPadding: 4 + + text: control.editable ? control.editText : control.displayText + + enabled: control.editable + autoScroll: control.editable + readOnly: control.popup.visible + inputMethodHints: control.inputMethodHints + validator: control.validator + + font: control.font + color: control.editable ? control.palette.text : control.palette.buttonText + selectionColor: control.palette.highlight + selectedTextColor: control.palette.highlightedText + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + + background: PaddedRectangle { + clip: true + radius: 2 + padding: 1 + leftPadding: control.mirrored ? -2 : padding + rightPadding: !control.mirrored ? -2 : padding + color: control.palette.base + visible: control.editable && !control.flat + + Rectangle { + x: parent.width - width + y: 1 + width: 1 + height: parent.height - 2 + color: Fusion.buttonOutline(control.palette, control.activeFocus, control.enabled) + } + + Rectangle { + x: 1 + y: 1 + width: parent.width - 3 + height: 1 + color: Fusion.topShadow + } + } + + Rectangle { + x: 1 - control.leftPadding + y: 1 + width: control.width - 2 + height: control.height - 2 + color: "transparent" + border.color: Color.transparent(Fusion.highlightedOutline(control.palette), 40 / 255) + visible: control.activeFocus + radius: 1.7 + } + } + + background: ButtonPanel { + implicitWidth: 120 + implicitHeight: 24 + + control: control + visible: !control.flat || control.down + // ### TODO: fix control.contentItem.activeFocus + highlighted: control.visualFocus || control.contentItem.activeFocus + } + + popup: T.Popup { + id: popup + width: control.width + height: Math.min(contentItem.implicitHeight + 2, control.Window.height - topMargin - bottomMargin) + topMargin: 6 + bottomMargin: 6 + palette: control.palette + padding: 1 + + contentItem: ListView { + clip: true + implicitHeight: contentHeight + model: control.popup.visible ? control.delegateModel : null + currentIndex: control.highlightedIndex + highlightRangeMode: ListView.ApplyRange + highlightMoveDuration: 0 + + T.ScrollBar.vertical: ScrollBar { } + } + + background: Rectangle { + color: popup.palette.window + border.color: Fusion.outline(control.palette) + + Rectangle { + z: -1 + x: 1; y: 1 + width: parent.width + height: parent.height + color: control.palette.shadow + opacity: 0.2 + } + } + } +} diff --git a/src/imports/controls/fusion/DelayButton.qml b/src/imports/controls/fusion/DelayButton.qml new file mode 100644 index 00000000..db9257e8 --- /dev/null +++ b/src/imports/controls/fusion/DelayButton.qml @@ -0,0 +1,137 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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.9 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Fusion 2.3 +import QtQuick.Controls.Fusion.impl 2.3 + +T.DelayButton { + id: control + + implicitWidth: Math.max(background ? background.implicitWidth : 0, + contentItem.implicitWidth + leftPadding + rightPadding) + implicitHeight: Math.max(background ? background.implicitHeight : 0, + contentItem.implicitHeight + topPadding + bottomPadding) + baselineOffset: contentItem.y + contentItem.baselineOffset + + padding: 6 + + transition: Transition { + NumberAnimation { + duration: control.delay * (control.pressed ? 1.0 - control.progress : 0.3 * control.progress) + } + } + + contentItem: Item { + implicitWidth: label.implicitWidth + implicitHeight: label.implicitHeight + + Item { + x: -control.leftPadding + (control.mirrored ? 0 : control.progress * control.width) + width: control.width + height: parent.height + + clip: control.progress > 0 + visible: control.mirrored ? control.progress > 0 : control.progress < 1 + + Text { + id: label + x: -parent.x + width: control.availableWidth + height: parent.height + + text: control.text + font: control.font + color: control.mirrored ? control.palette.brightText : control.palette.buttonText + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + elide: Text.ElideRight + } + } + + Item { + x: -control.leftPadding + width: (control.mirrored ? 1.0 - control.progress : control.progress) * control.width + height: parent.height + + clip: control.progress > 0 + visible: control.mirrored ? control.progress < 1 : control.progress > 0 + + Text { + x: -parent.x + width: control.availableWidth + height: parent.height + + text: control.text + font: control.font + color: control.mirrored ? control.palette.buttonText : control.palette.brightText + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + elide: Text.ElideRight + } + } + } + + background: ButtonPanel { + implicitWidth: 80 + implicitHeight: 24 + + control: control + highlighted: false + scale: control.mirrored ? -1 : 1 + + Rectangle { + width: control.progress * parent.width + height: parent.height + + radius: 2 + border.color: Qt.darker(Fusion.highlight(control.palette), 1.4) + gradient: Gradient { + GradientStop { + position: 0 + color: Qt.lighter(Fusion.highlight(control.palette), 1.2) + } + GradientStop { + position: 1 + color: Fusion.highlight(control.palette) + } + } + } + } +} diff --git a/src/imports/controls/fusion/Dial.qml b/src/imports/controls/fusion/Dial.qml new file mode 100644 index 00000000..ec83cccf --- /dev/null +++ b/src/imports/controls/fusion/Dial.qml @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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.9 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Fusion 2.3 +import QtQuick.Controls.Fusion.impl 2.3 + +T.Dial { + id: control + + implicitWidth: 100 + implicitHeight: 100 + + background: DialImpl { + palette: control.palette + highlight: control.visualFocus + } + + handle: KnobImpl { + x: background.x + background.width / 2 - handle.width / 2 + y: background.y + background.height / 2 - handle.height / 2 + width: control.width / 7 + height: control.height / 7 + palette: control.palette + transform: [ + Translate { + y: -Math.min(background.width, background.height) * 0.42 + handle.height + }, + Rotation { + angle: control.angle + origin.x: handle.width / 2 + origin.y: handle.height / 2 + } + ] + } +} diff --git a/src/imports/controls/fusion/Dialog.qml b/src/imports/controls/fusion/Dialog.qml new file mode 100644 index 00000000..a0c9ef18 --- /dev/null +++ b/src/imports/controls/fusion/Dialog.qml @@ -0,0 +1,95 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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.9 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Fusion 2.3 +import QtQuick.Controls.Fusion.impl 2.3 + +T.Dialog { + id: control + + implicitWidth: Math.max(background ? background.implicitWidth : 0, + header && header.visible ? header.implicitWidth : 0, + footer && footer.visible ? footer.implicitWidth : 0, + contentWidth > 0 ? contentWidth + leftPadding + rightPadding : 0) + implicitHeight: Math.max(background ? background.implicitHeight : 0, + (header && header.visible ? header.implicitHeight + spacing : 0) + + (footer && footer.visible ? footer.implicitHeight + spacing : 0) + + (contentHeight > 0 ? contentHeight + topPadding + bottomPadding : 0)) + + contentWidth: contentItem.implicitWidth || (contentChildren.length === 1 ? contentChildren[0].implicitWidth : 0) + contentHeight: contentItem.implicitHeight || (contentChildren.length === 1 ? contentChildren[0].implicitHeight : 0) + + padding: 6 + + background: Rectangle { + color: control.palette.window + border.color: control.palette.mid + radius: 2 + + Rectangle { + z: -1 + x: 1; y: 1 + width: parent.width + height: parent.height + color: control.palette.shadow + opacity: 0.2 + radius: 2 + } + } + + header: Label { + text: control.title + visible: control.title + elide: Label.ElideRight + font.bold: true + padding: 6 + background: Rectangle { + x: 1; y: 1 + width: parent.width - 2 + height: parent.height - 1 + color: control.palette.window + radius: 2 + } + } + + footer: DialogButtonBox { + visible: count > 0 + } +} diff --git a/src/imports/controls/fusion/DialogButtonBox.qml b/src/imports/controls/fusion/DialogButtonBox.qml new file mode 100644 index 00000000..b4a6afd8 --- /dev/null +++ b/src/imports/controls/fusion/DialogButtonBox.qml @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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.9 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Fusion 2.3 +import QtQuick.Controls.Fusion.impl 2.3 + +T.DialogButtonBox { + id: control + + implicitWidth: Math.max(background ? background.implicitWidth : 0, + contentItem.implicitWidth + leftPadding + rightPadding) + implicitHeight: Math.max(background ? background.implicitHeight : 0, + contentItem.implicitHeight + topPadding + bottomPadding) + + spacing: 6 + padding: 6 + alignment: Qt.AlignRight + + delegate: Button { } + + contentItem: ListView { + implicitWidth: contentWidth + implicitHeight: 24 + + model: control.contentModel + spacing: control.spacing + orientation: ListView.Horizontal + boundsBehavior: Flickable.StopAtBounds + snapMode: ListView.SnapToItem + } + + background: Rectangle { + implicitHeight: 32 + x: 1; y: 1 + width: parent.width - 2 + height: parent.height - 2 + color: control.palette.window + radius: 2 + } +} diff --git a/src/imports/controls/fusion/Drawer.qml b/src/imports/controls/fusion/Drawer.qml new file mode 100644 index 00000000..4115ec06 --- /dev/null +++ b/src/imports/controls/fusion/Drawer.qml @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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.9 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Fusion 2.3 +import QtQuick.Controls.Fusion.impl 2.3 + +T.Drawer { + id: control + + parent: T.ApplicationWindow.overlay + + implicitWidth: Math.max(background ? background.implicitWidth : 0, contentWidth + leftPadding + rightPadding) + implicitHeight: Math.max(background ? background.implicitHeight : 0, contentHeight + topPadding + bottomPadding) + + contentWidth: contentItem.implicitWidth || (contentChildren.length === 1 ? contentChildren[0].implicitWidth : 0) + contentHeight: contentItem.implicitHeight || (contentChildren.length === 1 ? contentChildren[0].implicitHeight : 0) + + topPadding: control.edge === Qt.BottomEdge + leftPadding: control.edge === Qt.RightEdge + rightPadding: control.edge === Qt.LeftEdge + bottomPadding: control.edge === Qt.TopEdge + + enter: Transition { SmoothedAnimation { velocity: 5 } } + exit: Transition { SmoothedAnimation { velocity: 5 } } + + background: Rectangle { + color: control.palette.window + readonly property bool horizontal: control.edge === Qt.LeftEdge || control.edge === Qt.RightEdge + Rectangle { + width: parent.horizontal ? 1 : parent.width + height: parent.horizontal ? parent.height : 1 + color: control.palette.mid + x: control.edge === Qt.LeftEdge ? parent.width - 1 : 0 + y: control.edge === Qt.TopEdge ? parent.height - 1 : 0 + } + Rectangle { + width: parent.horizontal ? 1 : parent.width + height: parent.horizontal ? parent.height : 1 + color: control.palette.shadow + opacity: 0.2 + x: control.edge === Qt.LeftEdge ? parent.width : 0 + y: control.edge === Qt.TopEdge ? parent.height : 0 + } + } +} diff --git a/src/imports/controls/fusion/Frame.qml b/src/imports/controls/fusion/Frame.qml new file mode 100644 index 00000000..b5837baa --- /dev/null +++ b/src/imports/controls/fusion/Frame.qml @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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.9 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Fusion 2.3 +import QtQuick.Controls.Fusion.impl 2.3 + +T.Frame { + id: control + + implicitWidth: Math.max(background ? background.implicitWidth : 0, contentWidth + leftPadding + rightPadding) + implicitHeight: Math.max(background ? background.implicitHeight : 0, contentHeight + topPadding + bottomPadding) + + contentWidth: contentItem.implicitWidth || (contentChildren.length === 1 ? contentChildren[0].implicitWidth : 0) + contentHeight: contentItem.implicitHeight || (contentChildren.length === 1 ? contentChildren[0].implicitHeight : 0) + + padding: 9 + + background: Rectangle { + color: "transparent" + border.color: Qt.lighter(Fusion.outline(control.palette), 1.08) + } +} diff --git a/src/imports/controls/fusion/GroupBox.qml b/src/imports/controls/fusion/GroupBox.qml new file mode 100644 index 00000000..93dc751d --- /dev/null +++ b/src/imports/controls/fusion/GroupBox.qml @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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.9 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Fusion 2.3 +import QtQuick.Controls.Fusion.impl 2.3 + +T.GroupBox { + id: control + + implicitWidth: Math.max(background ? background.implicitWidth : 0, + label ? label.implicitWidth + leftPadding + rightPadding : 0, + contentWidth + leftPadding + rightPadding) + implicitHeight: Math.max(background ? background.implicitHeight : 0, contentHeight + topPadding + bottomPadding) + + contentWidth: contentItem.implicitWidth || (contentChildren.length === 1 ? contentChildren[0].implicitWidth : 0) + contentHeight: contentItem.implicitHeight || (contentChildren.length === 1 ? contentChildren[0].implicitHeight : 0) + + spacing: 6 + padding: 9 + topPadding: padding + (label && label.implicitWidth > 0 ? label.implicitHeight + spacing : 0) + + label: Text { + x: control.leftPadding + width: control.availableWidth + + text: control.title + font: control.font + color: control.palette.windowText + elide: Text.ElideRight + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + background: Rectangle { + y: control.topPadding - control.padding + width: parent.width + height: parent.height - control.topPadding + control.padding + + radius: 2 + color: Color.transparent("black", 3 / 255) + border.color: Qt.lighter(Fusion.outline(control.palette), 1.08) + } +} diff --git a/src/imports/controls/fusion/ItemDelegate.qml b/src/imports/controls/fusion/ItemDelegate.qml new file mode 100644 index 00000000..9a0c0784 --- /dev/null +++ b/src/imports/controls/fusion/ItemDelegate.qml @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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.9 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Fusion 2.3 +import QtQuick.Controls.Fusion.impl 2.3 + +T.ItemDelegate { + id: control + + implicitWidth: Math.max(background ? background.implicitWidth : 0, + contentItem.implicitWidth + leftPadding + rightPadding) + implicitHeight: Math.max(background ? background.implicitHeight : 0, + Math.max(contentItem.implicitHeight, + indicator ? indicator.implicitHeight : 0) + topPadding + bottomPadding) + baselineOffset: contentItem.y + contentItem.baselineOffset + + padding: 6 + spacing: 6 + + icon.width: 16 + icon.height: 16 + + contentItem: IconLabel { + spacing: control.spacing + mirrored: control.mirrored + display: control.display + alignment: control.display === IconLabel.IconOnly || control.display === IconLabel.TextUnderIcon ? Qt.AlignCenter : Qt.AlignLeft + + icon: control.icon + text: control.text + font: control.font + color: control.highlighted ? Fusion.highlightedText(control.palette) : control.palette.text + } + + background: Rectangle { + implicitWidth: 100 + implicitHeight: 20 + color: control.down ? Fusion.buttonColor(control.palette, false, true, true) + : control.highlighted ? Fusion.highlight(control.palette) : control.palette.base + } +} diff --git a/src/imports/controls/fusion/Label.qml b/src/imports/controls/fusion/Label.qml new file mode 100644 index 00000000..a4295d1c --- /dev/null +++ b/src/imports/controls/fusion/Label.qml @@ -0,0 +1,49 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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.9 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Fusion 2.3 +import QtQuick.Controls.Fusion.impl 2.3 + +T.Label { + id: control + + color: control.palette.windowText + linkColor: control.palette.link +} diff --git a/src/imports/controls/fusion/Menu.qml b/src/imports/controls/fusion/Menu.qml new file mode 100644 index 00000000..3fd4caa2 --- /dev/null +++ b/src/imports/controls/fusion/Menu.qml @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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.9 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Fusion 2.3 +import QtQuick.Controls.Fusion.impl 2.3 + +T.Menu { + id: control + + implicitWidth: Math.max(background ? background.implicitWidth : 0, + contentItem ? contentItem.implicitWidth + leftPadding + rightPadding : 0) + implicitHeight: Math.max(background ? background.implicitHeight : 0, + contentItem ? contentItem.implicitHeight : 0) + topPadding + bottomPadding + + margins: 0 + padding: 1 + + delegate: MenuItem { } + + contentItem: ListView { + implicitHeight: contentHeight + model: control.contentModel + // TODO: improve this? + interactive: ApplicationWindow.window ? contentHeight > ApplicationWindow.window.height : false + clip: true + keyNavigationWraps: false + currentIndex: -1 + + ScrollIndicator.vertical: ScrollIndicator {} + } + + background: Rectangle { + implicitWidth: 200 + implicitHeight: 20 + + color: control.palette.base + border.color: Fusion.outline(control.palette) + + Rectangle { + z: -1 + x: 1; y: 1 + width: parent.width + height: parent.height + color: control.palette.shadow + opacity: 0.2 + } + } +} diff --git a/src/imports/controls/fusion/MenuItem.qml b/src/imports/controls/fusion/MenuItem.qml new file mode 100644 index 00000000..6cdc8992 --- /dev/null +++ b/src/imports/controls/fusion/MenuItem.qml @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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.9 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Fusion 2.3 +import QtQuick.Controls.Fusion.impl 2.3 + +T.MenuItem { + id: control + + implicitWidth: Math.max(background ? background.implicitWidth : 0, + contentItem.implicitWidth + leftPadding + rightPadding) + implicitHeight: Math.max(background ? background.implicitHeight : 0, + Math.max(contentItem.implicitHeight, + indicator ? indicator.implicitHeight : 0) + topPadding + bottomPadding) + baselineOffset: contentItem.y + contentItem.baselineOffset + + padding: 6 + spacing: 6 + + icon.width: 16 + icon.height: 16 + + contentItem: IconLabel { + leftPadding: !control.mirrored ? control.indicator.width + control.spacing : 0 + rightPadding: control.mirrored ? control.indicator.width + control.spacing : 0 + + spacing: control.spacing + mirrored: control.mirrored + display: control.display + alignment: Qt.AlignLeft + + icon: control.icon + text: control.text + font: control.font + color: control.down || control.hovered || control.highlighted ? Fusion.highlightedText(control.palette) : control.palette.text + } + + indicator: CheckIndicator { + x: control.mirrored ? control.width - width - control.rightPadding : control.leftPadding + y: control.topPadding + (control.availableHeight - height) / 2 + + control: control + visible: control.checkable + } + + background: Rectangle { + implicitWidth: 200 + implicitHeight: 20 + + color: Fusion.highlight(control.palette) + visible: control.down || control.hovered || control.highlighted + } +} diff --git a/src/imports/controls/fusion/MenuSeparator.qml b/src/imports/controls/fusion/MenuSeparator.qml new file mode 100644 index 00000000..d15a1015 --- /dev/null +++ b/src/imports/controls/fusion/MenuSeparator.qml @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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.9 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Fusion 2.3 +import QtQuick.Controls.Fusion.impl 2.3 + +T.MenuSeparator { + id: control + + implicitWidth: Math.max(background ? background.implicitWidth : 0, contentItem.implicitWidth + leftPadding + rightPadding) + implicitHeight: Math.max(background ? background.implicitHeight : 0, contentItem.implicitHeight + topPadding + bottomPadding) + + padding: 5 + topPadding: 1 + bottomPadding: 1 + + contentItem: Rectangle { + implicitWidth: 188 + implicitHeight: 1 + color: Qt.lighter(Fusion.darkShade, 1.06) + } +} diff --git a/src/imports/controls/fusion/Page.qml b/src/imports/controls/fusion/Page.qml new file mode 100644 index 00000000..501e91cb --- /dev/null +++ b/src/imports/controls/fusion/Page.qml @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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.9 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Fusion 2.3 +import QtQuick.Controls.Fusion.impl 2.3 + +T.Page { + id: control + + implicitWidth: Math.max(background ? background.implicitWidth : 0, + Math.max(contentWidth, + header && header.visible ? header.implicitWidth : 0, + footer && footer.visible ? footer.implicitWidth : 0) + leftPadding + rightPadding) + implicitHeight: Math.max(background ? background.implicitHeight : 0, + contentHeight + topPadding + bottomPadding + + (header && header.visible ? header.implicitHeight + spacing : 0) + + (footer && footer.visible ? footer.implicitHeight + spacing : 0)) + + contentWidth: contentItem.implicitWidth || (contentChildren.length === 1 ? contentChildren[0].implicitWidth : 0) + contentHeight: contentItem.implicitHeight || (contentChildren.length === 1 ? contentChildren[0].implicitHeight : 0) + + background: Rectangle { + color: palette.window + } +} diff --git a/src/imports/controls/fusion/PageIndicator.qml b/src/imports/controls/fusion/PageIndicator.qml new file mode 100644 index 00000000..812bb172 --- /dev/null +++ b/src/imports/controls/fusion/PageIndicator.qml @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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.9 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Fusion 2.3 +import QtQuick.Controls.Fusion.impl 2.3 + +T.PageIndicator { + id: control + + implicitWidth: Math.max(background ? background.implicitWidth : 0, + contentItem.implicitWidth + leftPadding + rightPadding) + implicitHeight: Math.max(background ? background.implicitHeight : 0, + contentItem.implicitHeight + topPadding + bottomPadding) + + padding: 4 + spacing: 4 + + delegate: Rectangle { + implicitWidth: 6 + implicitHeight: 6 + + radius: width / 2 + color: control.palette.shadow + + opacity: index === currentIndex ? 0.95 : pressed ? 0.75 : 0.45 + Behavior on opacity { OpacityAnimator { duration: 100 } } + } + + contentItem: Row { + spacing: control.spacing + + Repeater { + model: control.count + delegate: control.delegate + } + } +} diff --git a/src/imports/controls/fusion/Pane.qml b/src/imports/controls/fusion/Pane.qml new file mode 100644 index 00000000..683386b8 --- /dev/null +++ b/src/imports/controls/fusion/Pane.qml @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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.9 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Fusion 2.3 +import QtQuick.Controls.Fusion.impl 2.3 + +T.Pane { + id: control + + implicitWidth: Math.max(background ? background.implicitWidth : 0, contentWidth + leftPadding + rightPadding) + implicitHeight: Math.max(background ? background.implicitHeight : 0, contentHeight + topPadding + bottomPadding) + + contentWidth: contentItem.implicitWidth || (contentChildren.length === 1 ? contentChildren[0].implicitWidth : 0) + contentHeight: contentItem.implicitHeight || (contentChildren.length === 1 ? contentChildren[0].implicitHeight : 0) + + padding: 9 + + background: Rectangle { + color: palette.window + } +} diff --git a/src/imports/controls/fusion/Popup.qml b/src/imports/controls/fusion/Popup.qml new file mode 100644 index 00000000..64c9fe49 --- /dev/null +++ b/src/imports/controls/fusion/Popup.qml @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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.9 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Fusion 2.3 +import QtQuick.Controls.Fusion.impl 2.3 + +T.Popup { + id: control + + implicitWidth: Math.max(background ? background.implicitWidth : 0, + contentWidth > 0 ? contentWidth + leftPadding + rightPadding : 0) + implicitHeight: Math.max(background ? background.implicitHeight : 0, + contentHeight > 0 ? contentHeight + topPadding + bottomPadding : 0) + + contentWidth: contentItem.implicitWidth || (contentChildren.length === 1 ? contentChildren[0].implicitWidth : 0) + contentHeight: contentItem.implicitHeight || (contentChildren.length === 1 ? contentChildren[0].implicitHeight : 0) + + padding: 6 + + background: Rectangle { + color: control.palette.window + border.color: control.palette.mid + radius: 2 + } +} diff --git a/src/imports/controls/fusion/ProgressBar.qml b/src/imports/controls/fusion/ProgressBar.qml new file mode 100644 index 00000000..55fab03e --- /dev/null +++ b/src/imports/controls/fusion/ProgressBar.qml @@ -0,0 +1,118 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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.9 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Fusion 2.3 +import QtQuick.Controls.Fusion.impl 2.3 + +T.ProgressBar { + id: control + + implicitWidth: Math.max(background ? background.implicitWidth : 0, + contentItem ? contentItem.implicitWidth + leftPadding + rightPadding : 0) + implicitHeight: Math.max(background ? background.implicitHeight : 0, + contentItem ? contentItem.implicitHeight + topPadding + bottomPadding : 0) + + contentItem: Item { + implicitWidth: 120 + implicitHeight: 24 + scale: control.mirrored ? -1 : 1 + + Rectangle { + height: parent.height + width: (control.indeterminate ? 1.0 : control.position) * parent.width + + radius: 2 + border.color: Qt.darker(Fusion.highlight(control.palette), 1.4) + gradient: Gradient { + GradientStop { + position: 0 + color: Qt.lighter(Fusion.highlight(control.palette), 1.2) + } + GradientStop { + position: 1 + color: Fusion.highlight(control.palette) + } + } + } + + Item { + x: 1; y: 1 + width: parent.width - 2 + height: parent.height - 2 + visible: control.indeterminate + clip: true + + ColorImage { + id: mask + width: Math.ceil(parent.width / implicitWidth + 1) * implicitWidth + height: parent.height + + mirror: control.mirrored + fillMode: Image.TileHorizontally + source: "qrc:/qt-project.org/imports/QtQuick/Controls.2/Fusion/images/progressmask.png" + color: Color.transparent(Qt.lighter(Fusion.highlight(control.palette), 1.2), 160 / 255) + + visible: control.indeterminate + NumberAnimation on x { + running: control.indeterminate && control.visible + from: -mask.implicitWidth + to: 0 + loops: Animation.Infinite + duration: 750 + } + } + } + } + + background: Rectangle { + implicitWidth: 120 + implicitHeight: 24 + + radius: 2 + color: control.palette.base + border.color: Fusion.outline(control.palette) + + Rectangle { + x: 1; y: 1; height: 1 + width: parent.width - 2 + color: Fusion.topShadow + } + } +} diff --git a/src/imports/controls/fusion/RadioButton.qml b/src/imports/controls/fusion/RadioButton.qml new file mode 100644 index 00000000..cf4040f3 --- /dev/null +++ b/src/imports/controls/fusion/RadioButton.qml @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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.9 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Fusion 2.3 +import QtQuick.Controls.Fusion.impl 2.3 + +T.RadioButton { + id: control + + implicitWidth: Math.max(background ? background.implicitWidth : 0, + contentItem.implicitWidth + leftPadding + rightPadding) + implicitHeight: Math.max(background ? background.implicitHeight : 0, + Math.max(contentItem.implicitHeight, + indicator ? indicator.implicitHeight : 0) + topPadding + bottomPadding) + baselineOffset: contentItem.y + contentItem.baselineOffset + + padding: 6 + spacing: 6 + + indicator: RadioIndicator { + x: text ? (control.mirrored ? control.width - width - control.rightPadding : control.leftPadding) : control.leftPadding + (control.availableWidth - width) / 2 + y: control.topPadding + (control.availableHeight - height) / 2 + control: control + } + + contentItem: Text { + leftPadding: control.indicator && !control.mirrored ? control.indicator.width + control.spacing : 0 + rightPadding: control.indicator && control.mirrored ? control.indicator.width + control.spacing : 0 + + text: control.text + font: control.font + color: control.palette.windowText + elide: Text.ElideRight + visible: control.text + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } +} diff --git a/src/imports/controls/fusion/RadioDelegate.qml b/src/imports/controls/fusion/RadioDelegate.qml new file mode 100644 index 00000000..8d66d22e --- /dev/null +++ b/src/imports/controls/fusion/RadioDelegate.qml @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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.9 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Fusion 2.3 +import QtQuick.Controls.Fusion.impl 2.3 + +T.RadioDelegate { + id: control + + implicitWidth: Math.max(background ? background.implicitWidth : 0, + contentItem.implicitWidth + leftPadding + rightPadding) + implicitHeight: Math.max(background ? background.implicitHeight : 0, + Math.max(contentItem.implicitHeight, + indicator ? indicator.implicitHeight : 0) + topPadding + bottomPadding) + baselineOffset: contentItem.y + contentItem.baselineOffset + + padding: 6 + spacing: 6 + + icon.width: 16 + icon.height: 16 + + contentItem: IconLabel { + leftPadding: control.mirrored ? control.indicator.width + control.spacing : 0 + rightPadding: !control.mirrored ? control.indicator.width + control.spacing : 0 + + spacing: control.spacing + mirrored: control.mirrored + display: control.display + alignment: control.display === IconLabel.IconOnly || control.display === IconLabel.TextUnderIcon ? Qt.AlignCenter : Qt.AlignLeft + + icon: control.icon + text: control.text + font: control.font + color: control.highlighted ? Fusion.highlightedText(control.palette) : control.palette.text + } + + indicator: RadioIndicator { + x: control.mirrored ? control.leftPadding : control.width - width - control.rightPadding + y: control.topPadding + (control.availableHeight - height) / 2 + + control: control + } + + background: Rectangle { + implicitWidth: 100 + implicitHeight: 20 + color: control.down ? Fusion.buttonColor(control.palette, false, true, true) + : control.highlighted ? Fusion.highlight(control.palette) : control.palette.base + } +} diff --git a/src/imports/controls/fusion/RadioIndicator.qml b/src/imports/controls/fusion/RadioIndicator.qml new file mode 100644 index 00000000..a3c9ecd0 --- /dev/null +++ b/src/imports/controls/fusion/RadioIndicator.qml @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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.9 +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Fusion 2.3 +import QtQuick.Controls.Fusion.impl 2.3 + +Rectangle { + id: indicator + + property Item control + readonly property color pressedColor: Fusion.mergedColors(control.palette.base, control.palette.windowText, 85) + readonly property color checkMarkColor: Qt.darker(control.palette.text, 1.2) + + implicitWidth: 14 + implicitHeight: 14 + + radius: width / 2 + color: control.down ? indicator.pressedColor : control.palette.base + border.color: control.visualFocus ? Fusion.highlightedOutline(control.palette) + : Qt.darker(control.palette.window, 1.5) + + Rectangle { + y: 1 + width: parent.width + height: parent.height - 1 + radius: width / 2 + color: "transparent" + border.color: Fusion.topShadow + visible: control.enabled && !control.down + } + + Rectangle { + x: (parent.width - width) / 2 + y: (parent.height - height) / 2 + width: parent.width / 2.32 + height: parent.height / 2.32 + radius: width / 2 + color: Color.transparent(indicator.checkMarkColor, 180 / 255) + border.color: Color.transparent(indicator.checkMarkColor, 200 / 255) + visible: control.checked + } +} diff --git a/src/imports/controls/fusion/RangeSlider.qml b/src/imports/controls/fusion/RangeSlider.qml new file mode 100644 index 00000000..ea9975e8 --- /dev/null +++ b/src/imports/controls/fusion/RangeSlider.qml @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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.9 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Fusion 2.3 +import QtQuick.Controls.Fusion.impl 2.3 + +T.RangeSlider { + id: control + + implicitWidth: Math.max(background ? background.implicitWidth : 0, + Math.max(first.handle ? first.handle.implicitWidth : 0, + second.handle ? second.handle.implicitWidth : 0) + leftPadding + rightPadding) + implicitHeight: Math.max(background ? background.implicitHeight : 0, + Math.max(first.handle ? first.handle.implicitHeight : 0, + second.handle ? second.handle.implicitHeight : 0) + topPadding + bottomPadding) + + first.handle: SliderHandle { + x: control.leftPadding + Math.round(control.horizontal ? control.first.visualPosition * (control.availableWidth - width) : (control.availableWidth - width) / 2) + y: control.topPadding + Math.round(control.horizontal ? (control.availableHeight - height) / 2 : control.first.visualPosition * (control.availableHeight - height)) + + palette: control.palette + pressed: control.first.pressed + hovered: control.first.hovered + vertical: control.vertical + visualFocus: activeFocus + } + + second.handle: SliderHandle { + x: control.leftPadding + Math.round(control.horizontal ? control.second.visualPosition * (control.availableWidth - width) : (control.availableWidth - width) / 2) + y: control.topPadding + Math.round(control.horizontal ? (control.availableHeight - height) / 2 : control.second.visualPosition * (control.availableHeight - height)) + + palette: control.palette + pressed: control.second.pressed + hovered: control.second.hovered + vertical: control.vertical + visualFocus: activeFocus + } + + background: SliderGroove { + control: control + offset: control.first.position + progress: control.second.position + visualProgress: control.second.visualPosition + } +} diff --git a/src/imports/controls/fusion/RoundButton.qml b/src/imports/controls/fusion/RoundButton.qml new file mode 100644 index 00000000..c17fd72c --- /dev/null +++ b/src/imports/controls/fusion/RoundButton.qml @@ -0,0 +1,102 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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.9 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Fusion 2.3 +import QtQuick.Controls.Fusion.impl 2.3 + +T.RoundButton { + id: control + + implicitWidth: Math.max(background ? background.implicitWidth : 0, + contentItem.implicitWidth + leftPadding + rightPadding) + implicitHeight: Math.max(background ? background.implicitHeight : 0, + contentItem.implicitHeight + topPadding + bottomPadding) + baselineOffset: contentItem.y + contentItem.baselineOffset + + padding: 6 + spacing: 6 + + icon.width: 16 + icon.height: 16 + + contentItem: IconLabel { + spacing: control.spacing + mirrored: control.mirrored + display: control.display + + icon: control.icon + text: control.text + font: control.font + color: control.palette.buttonText + } + + background: Rectangle { + implicitWidth: 32 + implicitHeight: 32 + visible: !control.flat || control.down || control.checked + + color: Fusion.buttonColor(control.palette, control.highlighted, control.down || control.checked, control.hovered) + gradient: control.down || control.checked ? null : buttonGradient + + Gradient { + id: buttonGradient + GradientStop { + position: 0 + color: Fusion.gradientStart(Fusion.buttonColor(control.palette, control.highlighted, control.down, control.hovered)) + } + GradientStop { + position: 1 + color: Fusion.gradientStop(Fusion.buttonColor(control.palette, control.highlighted, control.down, control.hovered)) + } + } + + radius: control.radius + border.color: Fusion.buttonOutline(control.palette, control.highlighted || control.visualFocus, control.enabled) + + Rectangle { + x: 1; y: 1 + width: parent.width - 2 + height: parent.height - 2 + border.color: Fusion.innerContrastLine + color: "transparent" + radius: control.radius + } + } +} diff --git a/src/imports/controls/fusion/ScrollBar.qml b/src/imports/controls/fusion/ScrollBar.qml new file mode 100644 index 00000000..071f362d --- /dev/null +++ b/src/imports/controls/fusion/ScrollBar.qml @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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.9 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Fusion 2.3 +import QtQuick.Controls.Fusion.impl 2.3 + +T.ScrollBar { + id: control + + implicitWidth: Math.max(background ? background.implicitWidth : 0, + contentItem.implicitWidth + leftPadding + rightPadding) + implicitHeight: Math.max(background ? background.implicitHeight : 0, + contentItem.implicitHeight + topPadding + bottomPadding) + + padding: 2 + visible: control.policy !== T.ScrollBar.AlwaysOff + + contentItem: Rectangle { + id: handle + + implicitWidth: control.interactive ? 6 : 2 + implicitHeight: control.interactive ? 6 : 2 + + radius: width / 2 + color: control.pressed ? control.palette.dark : control.palette.mid + opacity: 0.0 + + states: State { + name: "active" + when: control.policy === T.ScrollBar.AlwaysOn || (control.active && control.size < 1.0) + PropertyChanges { target: handle; opacity: 0.75 } + } + + transitions: Transition { + from: "active" + SequentialAnimation { + PauseAnimation { duration: 450 } + NumberAnimation { target: handle; duration: 200; property: "opacity"; to: 0.0 } + } + } + } +} diff --git a/src/imports/controls/fusion/ScrollIndicator.qml b/src/imports/controls/fusion/ScrollIndicator.qml new file mode 100644 index 00000000..a23687ab --- /dev/null +++ b/src/imports/controls/fusion/ScrollIndicator.qml @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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.9 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Fusion 2.3 +import QtQuick.Controls.Fusion.impl 2.3 + +T.ScrollIndicator { + id: control + + implicitWidth: Math.max(background ? background.implicitWidth : 0, + contentItem.implicitWidth + leftPadding + rightPadding) + implicitHeight: Math.max(background ? background.implicitHeight : 0, + contentItem.implicitHeight + topPadding + bottomPadding) + + padding: 2 + + contentItem: Rectangle { + id: indicator + + implicitWidth: 2 + implicitHeight: 2 + + color: control.palette.mid + visible: control.size < 1.0 + opacity: 0.0 + + states: State { + name: "active" + when: control.active + PropertyChanges { target: indicator; opacity: 0.75 } + } + + transitions: [ + Transition { + from: "active" + SequentialAnimation { + PauseAnimation { duration: 450 } + NumberAnimation { target: indicator; duration: 200; property: "opacity"; to: 0.0 } + } + } + ] + } +} diff --git a/src/imports/controls/fusion/ScrollView.qml b/src/imports/controls/fusion/ScrollView.qml new file mode 100644 index 00000000..d38e4537 --- /dev/null +++ b/src/imports/controls/fusion/ScrollView.qml @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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.9 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Fusion 2.3 +import QtQuick.Controls.Fusion.impl 2.3 + +T.ScrollView { + id: control + + implicitWidth: Math.max(background ? background.implicitWidth : 0, contentWidth + leftPadding + rightPadding) + implicitHeight: Math.max(background ? background.implicitHeight : 0, contentHeight + topPadding + bottomPadding) + + contentWidth: contentItem.implicitWidth || (contentChildren.length === 1 ? contentChildren[0].implicitWidth : -1) + contentHeight: contentItem.implicitHeight || (contentChildren.length === 1 ? contentChildren[0].implicitHeight : -1) + + ScrollBar.vertical: ScrollBar { + parent: control + x: control.mirrored ? 0 : control.width - width + y: control.topPadding + height: control.availableHeight + active: control.ScrollBar.horizontal.active + } + + ScrollBar.horizontal: ScrollBar { + parent: control + x: control.leftPadding + y: control.height - height + width: control.availableWidth + active: control.ScrollBar.vertical.active + } +} diff --git a/src/imports/controls/fusion/Slider.qml b/src/imports/controls/fusion/Slider.qml new file mode 100644 index 00000000..37a3ef14 --- /dev/null +++ b/src/imports/controls/fusion/Slider.qml @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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.9 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Fusion 2.3 +import QtQuick.Controls.Fusion.impl 2.3 + +T.Slider { + id: control + + implicitWidth: Math.max(background ? background.implicitWidth : 0, + (handle ? handle.implicitWidth : 0) + leftPadding + rightPadding) + implicitHeight: Math.max(background ? background.implicitHeight : 0, + (handle ? handle.implicitHeight : 0) + topPadding + bottomPadding) + + handle: SliderHandle { + x: control.leftPadding + Math.round(control.horizontal ? control.visualPosition * (control.availableWidth - width) : (control.availableWidth - width) / 2) + y: control.topPadding + Math.round(control.horizontal ? (control.availableHeight - height) / 2 : control.visualPosition * (control.availableHeight - height)) + + palette: control.palette + pressed: control.pressed + hovered: control.hovered + vertical: control.vertical + visualFocus: control.visualFocus + } + + background: SliderGroove { + control: control + progress: control.position + visualProgress: control.visualPosition + } +} diff --git a/src/imports/controls/fusion/SliderGroove.qml b/src/imports/controls/fusion/SliderGroove.qml new file mode 100644 index 00000000..c243ccc3 --- /dev/null +++ b/src/imports/controls/fusion/SliderGroove.qml @@ -0,0 +1,94 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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.9 +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Fusion 2.3 +import QtQuick.Controls.Fusion.impl 2.3 + +Rectangle { + id: groove + + property Item control + property real offset + property real progress + property real visualProgress + + x: control.horizontal ? 0 : (control.availableWidth - width) / 2 + y: control.horizontal ? (control.availableHeight - height) / 2 : 0 + + implicitWidth: control.horizontal ? 160 : 5 + implicitHeight: control.horizontal ? 5 : 160 + width: control.horizontal ? control.availableWidth : implicitWidth + height: control.horizontal ? implicitHeight : control.availableHeight + + radius: 2 + border.color: Fusion.outline(control.palette) + scale: control.horizontal && control.mirrored ? -1 : 1 + + gradient: Gradient { + GradientStop { + position: 0 + color: Qt.darker(Fusion.grooveColor(control.palette), 1.1) + } + GradientStop { + position: 1 + color: Qt.lighter(Fusion.grooveColor(control.palette), 1.1) + } + } + + Rectangle { + x: control.horizontal ? groove.offset * parent.width : 0 + y: control.horizontal ? 0 : groove.visualProgress * parent.height + width: control.horizontal ? groove.progress * parent.width - groove.offset * parent.width : 5 + height: control.horizontal ? 5 : groove.progress * parent.height - groove.offset * parent.height + + radius: 2 + border.color: Qt.darker(Fusion.highlightedOutline(control.palette), 1.1) + + gradient: Gradient { + GradientStop { + position: 0 + color: Fusion.highlight(control.palette) + } + GradientStop { + position: 1 + color: Qt.lighter(Fusion.highlight(control.palette), 1.2) + } + } + } +} diff --git a/src/imports/controls/fusion/SliderHandle.qml b/src/imports/controls/fusion/SliderHandle.qml new file mode 100644 index 00000000..71aff706 --- /dev/null +++ b/src/imports/controls/fusion/SliderHandle.qml @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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.9 +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Fusion 2.3 +import QtQuick.Controls.Fusion.impl 2.3 + +Rectangle { + id: handle + + property var palette + property bool pressed + property bool hovered + property bool vertical + property bool visualFocus + + implicitWidth: 13 + implicitHeight: 13 + + gradient: Gradient { + GradientStop { + position: 0 + color: Fusion.gradientStart(Fusion.buttonColor(handle.palette, handle.visualFocus, handle.pressed, handle.hovered)) + } + GradientStop { + position: 1 + color: Fusion.gradientStop(Fusion.buttonColor(handle.palette, handle.visualFocus, handle.pressed, handle.hovered)) + } + } + rotation: handle.vertical ? -90 : 0 + border.width: 1 + border.color: "transparent" + radius: 2 + + Rectangle { + width: parent.width + height: parent.height + border.color: handle.visualFocus ? Fusion.highlightedOutline(handle.palette) : Fusion.outline(handle.palette) + color: "transparent" + radius: 2 + + Rectangle { + x: 1; y: 1 + width: parent.width - 2 + height: parent.height - 2 + border.color: Fusion.innerContrastLine + color: "transparent" + radius: 2 + } + } +} diff --git a/src/imports/controls/fusion/SpinBox.qml b/src/imports/controls/fusion/SpinBox.qml new file mode 100644 index 00000000..ce11d244 --- /dev/null +++ b/src/imports/controls/fusion/SpinBox.qml @@ -0,0 +1,183 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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.9 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Fusion 2.3 +import QtQuick.Controls.Fusion.impl 2.3 + +T.SpinBox { + id: control + + implicitWidth: Math.max(background ? background.implicitWidth : 0, + contentItem.implicitWidth + 2 * padding + + Math.max(up.indicator ? up.indicator.implicitWidth : 0, + down.indicator ? down.indicator.implicitWidth : 0)) + implicitHeight: Math.max(contentItem.implicitHeight + topPadding + bottomPadding, + background ? background.implicitHeight : 0, + (up.indicator ? up.indicator.implicitHeight : 0 + + down.indicator ? down.indicator.implicitHeight : 0)) + baselineOffset: contentItem.y + contentItem.baselineOffset + + padding: 4 + leftPadding: padding + (control.mirrored ? (up.indicator ? up.indicator.width : 0) : (down.indicator ? down.indicator.width : 0)) + rightPadding: padding + (control.mirrored ? (down.indicator ? down.indicator.width : 0) : (up.indicator ? up.indicator.width : 0)) + + validator: IntValidator { + locale: control.locale.name + bottom: Math.min(control.from, control.to) + top: Math.max(control.from, control.to) + } + + contentItem: TextInput { + z: 2 + text: control.textFromValue(control.value, control.locale) + + font: control.font + color: control.palette.text + selectionColor: control.palette.highlight + selectedTextColor: control.palette.highlightedText + horizontalAlignment: Qt.AlignHCenter + verticalAlignment: Qt.AlignVCenter + + readOnly: !control.editable + validator: control.validator + inputMethodHints: control.inputMethodHints + } + + up.indicator: PaddedRectangle { + x: control.mirrored ? 1 : parent.width - width - 1 + y: 1 + height: parent.height / 2 - 1 + implicitWidth: 16 + implicitHeight: 10 + + radius: 1.7 + clip: true + topPadding: -2 + leftPadding: -2 + color: control.up.pressed ? Fusion.buttonColor(control.palette, false, true, true) : "transparent" + + ColorImage { + scale: -1 + width: parent.width + height: parent.height + opacity: enabled ? 1.0 : 0.5 + color: control.palette.buttonText + source: "qrc:/qt-project.org/imports/QtQuick/Controls.2/Fusion/images/arrow.png" + fillMode: Image.Pad + } + } + + down.indicator: PaddedRectangle { + x: control.mirrored ? 1 : parent.width - width - 1 + y: parent.height - height - 1 + height: parent.height / 2 - 1 + implicitWidth: 16 + implicitHeight: 10 + + radius: 1.7 + clip: true + topPadding: -2 + leftPadding: -2 + color: control.down.pressed ? Fusion.buttonColor(control.palette, false, true, true) : "transparent" + + ColorImage { + width: parent.width + height: parent.height + opacity: enabled ? 1.0 : 0.5 + color: control.palette.buttonText + source: "qrc:/qt-project.org/imports/QtQuick/Controls.2/Fusion/images/arrow.png" + fillMode: Image.Pad + } + } + + background: Rectangle { + implicitWidth: 120 + implicitHeight: 24 + + radius: 2 + color: control.palette.base + border.color: control.activeFocus ? Fusion.highlightedOutline(control.palette) : Fusion.outline(control.palette) + + Rectangle { + x: 2 + y: 1 + width: parent.width - 4 + height: 1 + color: Fusion.topShadow + } + + Rectangle { + x: control.mirrored ? 1 : parent.width - width - 1 + y: 1 + width: Math.max(up.indicator ? up.indicator.width : 0, + down.indicator ? down.indicator.width : 0) + 1 + height: parent.height - 2 + + radius: 2 + gradient: Gradient { + GradientStop { + position: 0 + color: Fusion.gradientStart(Fusion.buttonColor(control.palette, control.visualFocus, false, control.up.hovered || control.down.hovered)) + } + GradientStop { + position: 1 + color: Fusion.gradientStop(Fusion.buttonColor(control.palette, control.visualFocus, false, control.up.hovered || control.down.hovered)) + } + } + + Rectangle { + x: control.mirrored ? parent.width - 1 : 0 + height: parent.height + width: 1 + color: Fusion.outline(control.palette) + } + } + + Rectangle { + x: 1; y: 1 + width: parent.width - 2 + height: parent.height - 2 + color: "transparent" + border.color: Color.transparent(Fusion.highlightedOutline(control.palette), 40 / 255) + visible: control.activeFocus + radius: 1.7 + } + } +} diff --git a/src/imports/controls/fusion/SwipeDelegate.qml b/src/imports/controls/fusion/SwipeDelegate.qml new file mode 100644 index 00000000..f279963b --- /dev/null +++ b/src/imports/controls/fusion/SwipeDelegate.qml @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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.9 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Fusion 2.3 +import QtQuick.Controls.Fusion.impl 2.3 + +T.SwipeDelegate { + id: control + + implicitWidth: Math.max(background ? background.implicitWidth : 0, + contentItem.implicitWidth + leftPadding + rightPadding) + implicitHeight: Math.max(background ? background.implicitHeight : 0, + Math.max(contentItem.implicitHeight, + indicator ? indicator.implicitHeight : 0) + topPadding + bottomPadding) + baselineOffset: contentItem.y + contentItem.baselineOffset + + padding: 6 + spacing: 6 + + icon.width: 16 + icon.height: 16 + + swipe.transition: Transition { SmoothedAnimation { velocity: 3; easing.type: Easing.InOutCubic } } + + contentItem: IconLabel { + spacing: control.spacing + mirrored: control.mirrored + display: control.display + alignment: control.display === IconLabel.IconOnly || control.display === IconLabel.TextUnderIcon ? Qt.AlignCenter : Qt.AlignLeft + + icon: control.icon + text: control.text + font: control.font + color: control.highlighted ? Fusion.highlightedText(control.palette) : control.palette.text + } + + background: Rectangle { + implicitWidth: 100 + implicitHeight: 20 + color: control.down ? Fusion.buttonColor(control.palette, false, true, true) + : control.highlighted ? Fusion.highlight(control.palette) : control.palette.base + } +} diff --git a/src/imports/controls/fusion/Switch.qml b/src/imports/controls/fusion/Switch.qml new file mode 100644 index 00000000..3bb7607d --- /dev/null +++ b/src/imports/controls/fusion/Switch.qml @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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.9 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Fusion 2.3 +import QtQuick.Controls.Fusion.impl 2.3 + +T.Switch { + id: control + + implicitWidth: Math.max(background ? background.implicitWidth : 0, + contentItem.implicitWidth + leftPadding + rightPadding) + implicitHeight: Math.max(background ? background.implicitHeight : 0, + Math.max(contentItem.implicitHeight, + indicator ? indicator.implicitHeight : 0) + topPadding + bottomPadding) + baselineOffset: contentItem.y + contentItem.baselineOffset + + padding: 6 + spacing: 6 + + indicator: SwitchIndicator { + x: text ? (control.mirrored ? control.width - width - control.rightPadding : control.leftPadding) : control.leftPadding + (control.availableWidth - width) / 2 + y: control.topPadding + (control.availableHeight - height) / 2 + control: control + } + + contentItem: Text { + leftPadding: control.indicator && !control.mirrored ? control.indicator.width + control.spacing : 0 + rightPadding: control.indicator && control.mirrored ? control.indicator.width + control.spacing : 0 + + text: control.text + font: control.font + color: control.palette.text + elide: Text.ElideRight + visible: control.text + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } +} diff --git a/src/imports/controls/fusion/SwitchDelegate.qml b/src/imports/controls/fusion/SwitchDelegate.qml new file mode 100644 index 00000000..fde4b38f --- /dev/null +++ b/src/imports/controls/fusion/SwitchDelegate.qml @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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.9 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Fusion 2.3 +import QtQuick.Controls.Fusion.impl 2.3 + +T.SwitchDelegate { + id: control + + implicitWidth: Math.max(background ? background.implicitWidth : 0, + contentItem.implicitWidth + leftPadding + rightPadding) + implicitHeight: Math.max(background ? background.implicitHeight : 0, + Math.max(contentItem.implicitHeight, + indicator ? indicator.implicitHeight : 0) + topPadding + bottomPadding) + baselineOffset: contentItem.y + contentItem.baselineOffset + + padding: 6 + spacing: 6 + + icon.width: 16 + icon.height: 16 + + indicator: SwitchIndicator { + x: text ? (control.mirrored ? control.leftPadding : control.width - width - control.rightPadding) : control.leftPadding + (control.availableWidth - width) / 2 + y: control.topPadding + (control.availableHeight - height) / 2 + control: control + } + + contentItem: IconLabel { + leftPadding: control.mirrored ? control.indicator.width + control.spacing : 0 + rightPadding: !control.mirrored ? control.indicator.width + control.spacing : 0 + + spacing: control.spacing + mirrored: control.mirrored + display: control.display + alignment: control.display === IconLabel.IconOnly || control.display === IconLabel.TextUnderIcon ? Qt.AlignCenter : Qt.AlignLeft + + icon: control.icon + text: control.text + font: control.font + color: control.highlighted ? Fusion.highlightedText(control.palette) : control.palette.text + } + + background: Rectangle { + implicitWidth: 100 + implicitHeight: 20 + color: control.down ? Fusion.buttonColor(control.palette, false, true, true) + : control.highlighted ? Fusion.highlight(control.palette) : control.palette.base + } +} diff --git a/src/imports/controls/fusion/SwitchIndicator.qml b/src/imports/controls/fusion/SwitchIndicator.qml new file mode 100644 index 00000000..a674afe4 --- /dev/null +++ b/src/imports/controls/fusion/SwitchIndicator.qml @@ -0,0 +1,137 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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.9 +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Fusion 2.3 +import QtQuick.Controls.Fusion.impl 2.3 + +Rectangle { + id: indicator + + property Item control + readonly property color pressedColor: Fusion.mergedColors(control.palette.base, control.palette.windowText, 85) + readonly property color checkMarkColor: Qt.darker(control.palette.text, 1.2) + + implicitWidth: 40 + implicitHeight: 16 + + radius: 2 + border.color: Fusion.outline(control.palette) + + gradient: Gradient { + GradientStop { + position: 0 + color: Qt.darker(Fusion.grooveColor(control.palette), 1.1) + } + GradientStop { + position: 1 + color: Qt.lighter(Fusion.grooveColor(control.palette), 1.1) + } + } + + Rectangle { + x: control.mirrored ? handle.x : 0 + width: control.mirrored ? parent.width - handle.x : handle.x + handle.width + height: parent.height + + opacity: control.checked ? 1 : 0 + Behavior on opacity { + enabled: !control.down + NumberAnimation { duration: 80 } + } + + radius: 2 + border.color: Qt.darker(Fusion.highlightedOutline(control.palette), 1.1) + border.width: control.enabled ? 1 : 0 + + gradient: Gradient { + GradientStop { + position: 0 + color: Fusion.highlight(control.palette) + } + GradientStop { + position: 1 + color: Qt.lighter(Fusion.highlight(control.palette), 1.2) + } + } + } + + Rectangle { + id: handle + x: Math.max(0, Math.min(parent.width - width, control.visualPosition * parent.width - (width / 2))) + y: (parent.height - height) / 2 + width: 20 + height: 16 + radius: 2 + + gradient: Gradient { + GradientStop { + position: 0 + color: Fusion.gradientStart(Fusion.buttonColor(control.palette, control.visualFocus, control.pressed, control.hovered)) + } + GradientStop { + position: 1 + color: Fusion.gradientStop(Fusion.buttonColor(control.palette, control.visualFocus, control.pressed, control.hovered)) + } + } + border.width: 1 + border.color: "transparent" + + Rectangle { + width: parent.width + height: parent.height + border.color: control.visualFocus ? Fusion.highlightedOutline(control.palette) : Fusion.outline(control.palette) + color: "transparent" + radius: 2 + + Rectangle { + x: 1; y: 1 + width: parent.width - 2 + height: parent.height - 2 + border.color: Fusion.innerContrastLine + color: "transparent" + radius: 2 + } + } + + Behavior on x { + enabled: !control.down + SmoothedAnimation { velocity: 200 } + } + } +} diff --git a/src/imports/controls/fusion/TabBar.qml b/src/imports/controls/fusion/TabBar.qml new file mode 100644 index 00000000..d28c55e4 --- /dev/null +++ b/src/imports/controls/fusion/TabBar.qml @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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.9 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Fusion 2.3 +import QtQuick.Controls.Fusion.impl 2.3 + +T.TabBar { + id: control + + implicitWidth: Math.max(background ? background.implicitWidth : 0, + contentWidth + leftPadding + rightPadding) + implicitHeight: Math.max(background ? background.implicitHeight : 0, + contentHeight + topPadding + bottomPadding) + + spacing: -1 + + contentItem: ListView { + model: control.contentModel + currentIndex: control.currentIndex + + spacing: control.spacing + orientation: ListView.Horizontal + boundsBehavior: Flickable.StopAtBounds + flickableDirection: Flickable.AutoFlickIfNeeded + snapMode: ListView.SnapToItem + + highlightMoveDuration: 0 + highlightRangeMode: ListView.ApplyRange + preferredHighlightBegin: 40 + preferredHighlightEnd: width - 40 + } + + background: Item { + implicitHeight: 21 + + Rectangle { + width: parent.width + height: 1 + y: control.position === T.TabBar.Header ? parent.height - 1 : 0 + color: Fusion.outline(control.palette) + } + } +} diff --git a/src/imports/controls/fusion/TabButton.qml b/src/imports/controls/fusion/TabButton.qml new file mode 100644 index 00000000..fab406dc --- /dev/null +++ b/src/imports/controls/fusion/TabButton.qml @@ -0,0 +1,110 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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.9 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Fusion 2.3 +import QtQuick.Controls.Fusion.impl 2.3 + +T.TabButton { + id: control + + implicitWidth: Math.max(background ? background.implicitWidth : 0, + contentItem.implicitWidth + leftPadding + rightPadding) + implicitHeight: Math.max(background ? background.implicitHeight : 0, + contentItem.implicitHeight + topPadding + bottomPadding) + baselineOffset: contentItem.y + contentItem.baselineOffset + + padding: 2 + leftPadding: 4 + rightPadding: 4 + spacing: 6 + + icon.width: 16 + icon.height: 16 + + z: checked + + contentItem: IconLabel { + spacing: control.spacing + mirrored: control.mirrored + display: control.display + + icon: control.icon + text: control.text + font: control.font + color: control.palette.buttonText + } + + background: Rectangle { + y: control.checked || control.TabBar.position !== T.TabBar.Header ? 0 : 2 + implicitHeight: 21 + height: control.height - (control.checked ? 0 : 2) + + border.color: Qt.lighter(Fusion.outline(control.palette), 1.1) + gradient: control.checked ? selectedGradient : normalGradient + + Gradient { + id: selectedGradient + GradientStop { + position: 0 + color: Qt.lighter(Fusion.tabFrameColor(control.palette), 1.04) + } + GradientStop { + position: 1 + color: Fusion.tabFrameColor(control.palette) + } + } + + Gradient { + id: normalGradient + GradientStop { + position: 0 + color: Qt.darker(Fusion.tabFrameColor(control.palette), 1.08) + } + GradientStop { + position: 0.85 + color: Qt.darker(Fusion.tabFrameColor(control.palette), 1.08) + } + GradientStop { + position: 1 + color: Qt.darker(Fusion.tabFrameColor(control.palette), 1.16) + } + } + } +} diff --git a/src/imports/controls/fusion/TextArea.qml b/src/imports/controls/fusion/TextArea.qml new file mode 100644 index 00000000..bf1de555 --- /dev/null +++ b/src/imports/controls/fusion/TextArea.qml @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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.9 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Fusion 2.3 +import QtQuick.Controls.Fusion.impl 2.3 + +T.TextArea { + id: control + + implicitWidth: Math.max(contentWidth + leftPadding + rightPadding, + background ? background.implicitWidth : 0, + placeholder.implicitWidth + leftPadding + rightPadding) + implicitHeight: Math.max(contentHeight + topPadding + bottomPadding, + background ? background.implicitHeight : 0, + placeholder.implicitHeight + topPadding + bottomPadding) + + padding: 6 + leftPadding: padding + 4 + + color: control.palette.text + selectionColor: control.palette.highlight + selectedTextColor: control.palette.highlightedText + + PlaceholderText { + id: placeholder + x: control.leftPadding + y: control.topPadding + width: control.width - (control.leftPadding + control.rightPadding) + height: control.height - (control.topPadding + control.bottomPadding) + + opacity: 0.5 + text: control.placeholderText + font: control.font + color: control.palette.text + verticalAlignment: control.verticalAlignment + visible: !control.length && !control.preeditText && (!control.activeFocus || control.horizontalAlignment !== Qt.AlignHCenter) + elide: Text.ElideRight + } +} diff --git a/src/imports/controls/fusion/TextField.qml b/src/imports/controls/fusion/TextField.qml new file mode 100644 index 00000000..49e38c1e --- /dev/null +++ b/src/imports/controls/fusion/TextField.qml @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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.9 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Fusion 2.3 +import QtQuick.Controls.Fusion.impl 2.3 + +T.TextField { + id: control + + implicitWidth: Math.max(background ? background.implicitWidth : 0, + placeholderText ? placeholder.implicitWidth + leftPadding + rightPadding : 0) + || contentWidth + leftPadding + rightPadding + implicitHeight: Math.max(contentHeight + topPadding + bottomPadding, + background ? background.implicitHeight : 0, + placeholder.implicitHeight + topPadding + bottomPadding) + + padding: 4 + + color: control.palette.text + selectionColor: control.palette.highlight + selectedTextColor: control.palette.highlightedText + verticalAlignment: TextInput.AlignVCenter + + PlaceholderText { + id: placeholder + x: control.leftPadding + y: control.topPadding + width: control.width - (control.leftPadding + control.rightPadding) + height: control.height - (control.topPadding + control.bottomPadding) + + opacity: 0.5 + text: control.placeholderText + font: control.font + color: control.palette.text + verticalAlignment: control.verticalAlignment + visible: !control.length && !control.preeditText && (!control.activeFocus || control.horizontalAlignment !== Qt.AlignHCenter) + elide: Text.ElideRight + } + + background: Rectangle { + implicitWidth: 120 + implicitHeight: 24 + + radius: 2 + color: control.palette.base + border.color: control.activeFocus ? Fusion.highlightedOutline(control.palette) : Fusion.outline(control.palette) + + Rectangle { + x: 1; y: 1 + width: parent.width - 2 + height: parent.height - 2 + color: "transparent" + border.color: Color.transparent(Fusion.highlightedOutline(control.palette), 40 / 255) + visible: control.activeFocus + radius: 1.7 + } + + Rectangle { + x: 2 + y: 1 + width: parent.width - 4 + height: 1 + color: Fusion.topShadow + } + } +} diff --git a/src/imports/controls/fusion/ToolBar.qml b/src/imports/controls/fusion/ToolBar.qml new file mode 100644 index 00000000..0181a509 --- /dev/null +++ b/src/imports/controls/fusion/ToolBar.qml @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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.9 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Fusion 2.3 +import QtQuick.Controls.Fusion.impl 2.3 + +T.ToolBar { + id: control + + implicitWidth: Math.max(background ? background.implicitWidth : 0, contentWidth + leftPadding + rightPadding) + implicitHeight: Math.max(background ? background.implicitHeight : 0, contentHeight + topPadding + bottomPadding) + + contentWidth: contentItem.implicitWidth || (contentChildren.length === 1 ? contentChildren[0].implicitWidth : 0) + contentHeight: contentItem.implicitHeight || (contentChildren.length === 1 ? contentChildren[0].implicitHeight : 0) + + leftPadding: 6 + rightPadding: 6 + topPadding: control.position === T.ToolBar.Footer ? 1 : 0 + bottomPadding: control.position === T.ToolBar.Header ? 1 : 0 + + background: Rectangle { + implicitHeight: 26 + + gradient: Gradient { + GradientStop { + position: 0 + color: Qt.lighter(control.palette.window, 1.04) + } + GradientStop { + position: 1 + color: control.palette.window + } + } + + Rectangle { + width: parent.width + height: 1 + color: control.position === T.ToolBar.Header ? Fusion.lightShade : Fusion.darkShade + } + + Rectangle { + y: parent.height - height + width: parent.width + height: 1 + color: control.position === T.ToolBar.Header ? Fusion.darkShade : Fusion.lightShade + } + } +} diff --git a/src/imports/controls/fusion/ToolButton.qml b/src/imports/controls/fusion/ToolButton.qml new file mode 100644 index 00000000..aa7516b0 --- /dev/null +++ b/src/imports/controls/fusion/ToolButton.qml @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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.9 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Fusion 2.3 +import QtQuick.Controls.Fusion.impl 2.3 + +T.ToolButton { + id: control + + implicitWidth: Math.max(background ? background.implicitWidth : 0, + contentItem.implicitWidth + leftPadding + rightPadding) + implicitHeight: Math.max(background ? background.implicitHeight : 0, + contentItem.implicitHeight + topPadding + bottomPadding) + baselineOffset: contentItem.y + contentItem.baselineOffset + + padding: 6 + spacing: 6 + + icon.width: 16 + icon.height: 16 + + contentItem: IconLabel { + spacing: control.spacing + mirrored: control.mirrored + display: control.display + + icon: control.icon + text: control.text + font: control.font + color: control.palette.buttonText + } + + background: ButtonPanel { + implicitWidth: 20 + implicitHeight: 20 + + control: control + visible: control.down || control.checked || control.highlighted || control.visualFocus || control.hovered + } +} diff --git a/src/imports/controls/fusion/ToolSeparator.qml b/src/imports/controls/fusion/ToolSeparator.qml new file mode 100644 index 00000000..70509f3f --- /dev/null +++ b/src/imports/controls/fusion/ToolSeparator.qml @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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.9 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Fusion 2.3 +import QtQuick.Controls.Fusion.impl 2.3 + +T.ToolSeparator { + id: control + + implicitWidth: Math.max(background ? background.implicitWidth : 0, contentItem.implicitWidth + leftPadding + rightPadding) + implicitHeight: Math.max(background ? background.implicitHeight : 0, contentItem.implicitHeight + topPadding + bottomPadding) + + padding: vertical ? 6 : 2 + topPadding: vertical ? 2 : 6 + bottomPadding: vertical ? 2 : 6 + + contentItem: Rectangle { + implicitWidth: vertical ? 2 : 8 + implicitHeight: vertical ? 8 : 2 + color: Qt.darker(control.palette.window, 1.1) + + Rectangle { + x: 1 + width: 1 + height: parent.height + color: Qt.lighter(control.palette.window, 1.1) + } + } +} diff --git a/src/imports/controls/fusion/ToolTip.qml b/src/imports/controls/fusion/ToolTip.qml new file mode 100644 index 00000000..8e9be597 --- /dev/null +++ b/src/imports/controls/fusion/ToolTip.qml @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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.9 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Fusion 2.3 +import QtQuick.Controls.Fusion.impl 2.3 + +T.ToolTip { + id: control + + x: parent ? (parent.width - implicitWidth) / 2 : 0 + y: -implicitHeight - 3 + + implicitWidth: Math.max(background ? background.implicitWidth : 0, + contentItem.implicitWidth + leftPadding + rightPadding) + implicitHeight: Math.max(background ? background.implicitHeight : 0, + contentItem.implicitHeight + topPadding + bottomPadding) + + margins: 6 + padding: 6 + + closePolicy: T.Popup.CloseOnEscape | T.Popup.CloseOnPressOutsideParent | T.Popup.CloseOnReleaseOutsideParent + + contentItem: Text { + text: control.text + font: control.font + color: control.palette.toolTipText + // TODO: wrapMode: Label.Wrap + } + + background: Rectangle { + color: control.palette.toolTipBase + border.color: control.palette.toolTipText + + Rectangle { + z: -1 + x: 1; y: 1 + width: parent.width + height: parent.height + color: control.palette.shadow + opacity: 0.5 + } + } +} diff --git a/src/imports/controls/fusion/Tumbler.qml b/src/imports/controls/fusion/Tumbler.qml new file mode 100644 index 00000000..77a0c93c --- /dev/null +++ b/src/imports/controls/fusion/Tumbler.qml @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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.9 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Fusion 2.3 +import QtQuick.Controls.Fusion.impl 2.3 + +T.Tumbler { + id: control + implicitWidth: 60 + implicitHeight: 200 + + delegate: Text { + id: label + text: modelData + color: control.palette.windowText + font: control.font + opacity: (1.0 - Math.abs(Tumbler.displacement) / (visibleItemCount / 2)) * (control.enabled ? 1 : 0.6) + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + } + + contentItem: TumblerView { + id: tumblerView + model: control.model + delegate: control.delegate + path: Path { + startX: tumblerView.width / 2 + startY: -tumblerView.delegateHeight / 2 + PathLine { + x: tumblerView.width / 2 + y: (control.visibleItemCount + 1) * tumblerView.delegateHeight - tumblerView.delegateHeight / 2 + } + } + + property real delegateHeight: control.availableHeight / control.visibleItemCount + } +} diff --git a/src/imports/controls/fusion/fusion.pri b/src/imports/controls/fusion/fusion.pri new file mode 100644 index 00000000..9902e971 --- /dev/null +++ b/src/imports/controls/fusion/fusion.pri @@ -0,0 +1,65 @@ +HEADERS += \ + $$PWD/qquickfusionbusyindicator_p.h \ + $$PWD/qquickfusiondial_p.h \ + $$PWD/qquickfusionknob_p.h \ + $$PWD/qquickfusionstyle_p.h \ + $$PWD/qquickfusiontheme_p.h + +SOURCES += \ + $$PWD/qquickfusionbusyindicator.cpp \ + $$PWD/qquickfusiondial.cpp \ + $$PWD/qquickfusionknob.cpp \ + $$PWD/qquickfusionstyle.cpp \ + $$PWD/qquickfusiontheme.cpp + +QML_FILES += \ + $$PWD/ApplicationWindow.qml \ + $$PWD/BusyIndicator.qml \ + $$PWD/Button.qml \ + $$PWD/ButtonPanel.qml \ + $$PWD/CheckBox.qml \ + $$PWD/CheckDelegate.qml \ + $$PWD/CheckIndicator.qml \ + $$PWD/ComboBox.qml \ + $$PWD/DelayButton.qml \ + $$PWD/Dial.qml \ + $$PWD/Dialog.qml \ + $$PWD/DialogButtonBox.qml \ + $$PWD/Drawer.qml \ + $$PWD/Frame.qml \ + $$PWD/GroupBox.qml \ + $$PWD/ItemDelegate.qml \ + $$PWD/Label.qml \ + $$PWD/Menu.qml \ + $$PWD/MenuItem.qml \ + $$PWD/MenuSeparator.qml \ + $$PWD/Page.qml \ + $$PWD/PageIndicator.qml \ + $$PWD/Pane.qml \ + $$PWD/Popup.qml \ + $$PWD/ProgressBar.qml \ + $$PWD/RadioButton.qml \ + $$PWD/RadioDelegate.qml \ + $$PWD/RadioIndicator.qml \ + $$PWD/RangeSlider.qml \ + $$PWD/RoundButton.qml \ + $$PWD/ScrollBar.qml \ + $$PWD/ScrollIndicator.qml \ + $$PWD/ScrollView.qml \ + $$PWD/Slider.qml \ + $$PWD/SliderGroove.qml \ + $$PWD/SliderHandle.qml \ + $$PWD/SpinBox.qml \ + $$PWD/SwipeDelegate.qml \ + $$PWD/SwitchDelegate.qml \ + $$PWD/SwitchIndicator.qml \ + $$PWD/Switch.qml \ + $$PWD/TabBar.qml \ + $$PWD/TabButton.qml \ + $$PWD/TextArea.qml \ + $$PWD/TextField.qml \ + $$PWD/ToolBar.qml \ + $$PWD/ToolButton.qml \ + $$PWD/ToolSeparator.qml \ + $$PWD/ToolTip.qml \ + $$PWD/Tumbler.qml diff --git a/src/imports/controls/fusion/fusion.pro b/src/imports/controls/fusion/fusion.pro new file mode 100644 index 00000000..c2b649cf --- /dev/null +++ b/src/imports/controls/fusion/fusion.pro @@ -0,0 +1,25 @@ +TARGET = qtquickcontrols2fusionstyleplugin +TARGETPATH = QtQuick/Controls.2/Fusion +IMPORT_VERSION = 2.3 + +QT += qml quick +QT_PRIVATE += core-private gui-private qml-private quick-private quicktemplates2-private quickcontrols2-private + +DEFINES += QT_NO_CAST_TO_ASCII QT_NO_CAST_FROM_ASCII + +include(fusion.pri) + +OTHER_FILES += \ + qmldir \ + $$QML_FILES + +SOURCES += \ + $$PWD/qtquickcontrols2fusionstyleplugin.cpp + +RESOURCES += \ + $$PWD/qtquickcontrols2fusionstyle.qrc + +CONFIG += no_cxx_module +load(qml_plugin) + +requires(qtConfig(quickcontrols2-fusion)) diff --git a/src/imports/controls/fusion/images/arrow.png b/src/imports/controls/fusion/images/arrow.png Binary files differnew file mode 100644 index 00000000..ad8cdc95 --- /dev/null +++ b/src/imports/controls/fusion/images/arrow.png diff --git a/src/imports/controls/fusion/images/arrow.svg b/src/imports/controls/fusion/images/arrow.svg new file mode 100644 index 00000000..44383924 --- /dev/null +++ b/src/imports/controls/fusion/images/arrow.svg @@ -0,0 +1,75 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="10" + height="6" + viewBox="0 0 10 6" + id="svg2" + version="1.1" + inkscape:version="0.91 r13725" + inkscape:export-filename="/Users/jpnurmi/Downloads/arrow@4x.png" + inkscape:export-xdpi="360" + inkscape:export-ydpi="360" + sodipodi:docname="arrow.svg"> + <defs + id="defs4" /> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="31.678384" + inkscape:cx="7.9810383" + inkscape:cy="3.0344775" + inkscape:document-units="px" + inkscape:current-layer="layer1" + showgrid="true" + units="px" + inkscape:snap-to-guides="true" + inkscape:snap-page="true" + inkscape:window-width="1440" + inkscape:window-height="851" + inkscape:window-x="0" + inkscape:window-y="1" + inkscape:window-maximized="1"> + <inkscape:grid + type="xygrid" + id="grid3336" /> + </sodipodi:namedview> + <metadata + id="metadata7"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1" + transform="translate(0,-1046.3622)"> + <path + transform="matrix(1.2371791,0,0,0.85714284,1.0769252,150.19463)" + style="fill:#000000;fill-opacity:0.7254902" + inkscape:transform-center-y="1.4999605" + d="m 3.1709837,1051.3622 -3.2331616,-4.6667 6.4663233,0 z" + id="path3365" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccc" /> + </g> +</svg> diff --git a/src/imports/controls/fusion/images/arrow@2x.png b/src/imports/controls/fusion/images/arrow@2x.png Binary files differnew file mode 100644 index 00000000..4f94c58f --- /dev/null +++ b/src/imports/controls/fusion/images/arrow@2x.png diff --git a/src/imports/controls/fusion/images/arrow@3x.png b/src/imports/controls/fusion/images/arrow@3x.png Binary files differnew file mode 100644 index 00000000..68928ea9 --- /dev/null +++ b/src/imports/controls/fusion/images/arrow@3x.png diff --git a/src/imports/controls/fusion/images/arrow@4x.png b/src/imports/controls/fusion/images/arrow@4x.png Binary files differnew file mode 100644 index 00000000..edde50f3 --- /dev/null +++ b/src/imports/controls/fusion/images/arrow@4x.png diff --git a/src/imports/controls/fusion/images/checkmark.png b/src/imports/controls/fusion/images/checkmark.png Binary files differnew file mode 100644 index 00000000..9cb04883 --- /dev/null +++ b/src/imports/controls/fusion/images/checkmark.png diff --git a/src/imports/controls/fusion/images/checkmark.svg b/src/imports/controls/fusion/images/checkmark.svg new file mode 100644 index 00000000..f1afdc4f --- /dev/null +++ b/src/imports/controls/fusion/images/checkmark.svg @@ -0,0 +1,72 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="14" + height="14" + viewBox="0 0 14 14" + id="svg3386" + version="1.1" + inkscape:version="0.91 r13725" + inkscape:export-filename="/Users/jpnurmi/Downloads/checkmark@4x.png" + inkscape:export-xdpi="360" + inkscape:export-ydpi="360" + sodipodi:docname="checkmark.svg"> + <defs + id="defs3388" /> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="32" + inkscape:cx="1.9865044" + inkscape:cy="6.0706667" + inkscape:document-units="px" + inkscape:current-layer="layer1" + showgrid="false" + units="px" + inkscape:snap-page="true" + inkscape:snap-grids="true" + inkscape:snap-to-guides="true" + inkscape:window-width="1440" + inkscape:window-height="851" + inkscape:window-x="0" + inkscape:window-y="1" + inkscape:window-maximized="1" /> + <metadata + id="metadata3391"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1" + transform="translate(0,-1038.3622)"> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.79999995;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 5,1045.3622 2,4 2.5,-8" + id="path4198" + inkscape:connector-curvature="0" + sodipodi:nodetypes="ccc" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + </g> +</svg> diff --git a/src/imports/controls/fusion/images/checkmark@2x.png b/src/imports/controls/fusion/images/checkmark@2x.png Binary files differnew file mode 100644 index 00000000..ae9a7749 --- /dev/null +++ b/src/imports/controls/fusion/images/checkmark@2x.png diff --git a/src/imports/controls/fusion/images/checkmark@3x.png b/src/imports/controls/fusion/images/checkmark@3x.png Binary files differnew file mode 100644 index 00000000..4a67e88a --- /dev/null +++ b/src/imports/controls/fusion/images/checkmark@3x.png diff --git a/src/imports/controls/fusion/images/checkmark@4x.png b/src/imports/controls/fusion/images/checkmark@4x.png Binary files differnew file mode 100644 index 00000000..0890d2ba --- /dev/null +++ b/src/imports/controls/fusion/images/checkmark@4x.png diff --git a/src/imports/controls/fusion/images/progressmask.png b/src/imports/controls/fusion/images/progressmask.png Binary files differnew file mode 100644 index 00000000..683f9e2f --- /dev/null +++ b/src/imports/controls/fusion/images/progressmask.png diff --git a/src/imports/controls/fusion/images/progressmask.svg b/src/imports/controls/fusion/images/progressmask.svg new file mode 100644 index 00000000..a0dfc426 --- /dev/null +++ b/src/imports/controls/fusion/images/progressmask.svg @@ -0,0 +1,74 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="31" + height="22" + viewBox="0 0 8.202083 5.8208335" + version="1.1" + id="svg8" + inkscape:export-filename="/home/jpnurmi/Projects/qt-dev/qtquickcontrols2/src/imports/controls/fusion/images/progressmask@4x.png" + inkscape:export-xdpi="384" + inkscape:export-ydpi="384" + inkscape:version="0.92.1 r" + sodipodi:docname="progressmask.svg"> + <defs + id="defs2" /> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="15.839192" + inkscape:cx="61.144853" + inkscape:cy="14.574824" + inkscape:document-units="mm" + inkscape:current-layer="layer1" + showgrid="false" + units="px" + inkscape:pagecheckerboard="true" + inkscape:window-width="3840" + inkscape:window-height="2031" + inkscape:window-x="0" + inkscape:window-y="55" + inkscape:window-maximized="1" /> + <metadata + id="metadata5"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1" + transform="translate(0,-291.17915)"> + <path + style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:4.5;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 0,296.99998 4.7625,-5.82083" + id="path4485" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:4.5;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 8.2020833,296.99998 4.7624997,-5.82083" + id="path4485-3" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" /> + </g> +</svg> diff --git a/src/imports/controls/fusion/images/progressmask@2x.png b/src/imports/controls/fusion/images/progressmask@2x.png Binary files differnew file mode 100644 index 00000000..e101f5de --- /dev/null +++ b/src/imports/controls/fusion/images/progressmask@2x.png diff --git a/src/imports/controls/fusion/images/progressmask@3x.png b/src/imports/controls/fusion/images/progressmask@3x.png Binary files differnew file mode 100644 index 00000000..784f01c0 --- /dev/null +++ b/src/imports/controls/fusion/images/progressmask@3x.png diff --git a/src/imports/controls/fusion/images/progressmask@4x.png b/src/imports/controls/fusion/images/progressmask@4x.png Binary files differnew file mode 100644 index 00000000..8af0b2c2 --- /dev/null +++ b/src/imports/controls/fusion/images/progressmask@4x.png diff --git a/src/imports/controls/fusion/qmldir b/src/imports/controls/fusion/qmldir new file mode 100644 index 00000000..c37b9f9f --- /dev/null +++ b/src/imports/controls/fusion/qmldir @@ -0,0 +1,4 @@ +module QtQuick.Controls.Fusion +plugin qtquickcontrols2fusionstyleplugin +classname QtQuickControls2FusionStylePlugin +depends QtQuick.Controls 2.3 diff --git a/src/imports/controls/fusion/qquickfusionbusyindicator.cpp b/src/imports/controls/fusion/qquickfusionbusyindicator.cpp new file mode 100644 index 00000000..7254b7b7 --- /dev/null +++ b/src/imports/controls/fusion/qquickfusionbusyindicator.cpp @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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 "qquickfusionbusyindicator_p.h" + +#include <QtGui/qpainter.h> + +QT_BEGIN_NAMESPACE + +QQuickFusionBusyIndicator::QQuickFusionBusyIndicator(QQuickItem *parent) + : QQuickPaintedItem(parent) +{ +} + +QColor QQuickFusionBusyIndicator::color() const +{ + return m_color; +} + +void QQuickFusionBusyIndicator::setColor(const QColor &color) +{ + if (color == m_color) + return; + + m_color = color; + update(); +} + +void QQuickFusionBusyIndicator::paint(QPainter *painter) +{ + const qreal w = width(); + const qreal h = height(); + if (w <= 0 || h <= 0 || !isVisible()) + return; + + const qreal sz = qMin(w, h); + const qreal dx = (w - sz) / 2; + const qreal dy = (h - sz) / 2; + const int hpw = qRound(qMax(1.0, sz / 14)) & -1; + const int pw = 2 * hpw; + const QRectF bounds(dx + hpw, dy + hpw, sz - pw - 1, sz - pw - 1); + + QConicalGradient gradient; + gradient.setCenter(QPointF(dx + sz / 2, dy + sz / 2)); + gradient.setColorAt(0, m_color); + gradient.setColorAt(0.1, m_color); + gradient.setColorAt(1, Qt::transparent); + + painter->translate(0.5, 0.5); + painter->setRenderHint(QPainter::Antialiasing, true); + painter->setPen(QPen(gradient, pw, Qt::SolidLine)); + painter->drawArc(bounds, 0, 360 * 16); + painter->setPen(QPen(m_color, pw, Qt::SolidLine, Qt::RoundCap)); + painter->drawArc(bounds, 0, 20 * 16); +} + +QT_END_NAMESPACE diff --git a/src/imports/controls/fusion/qquickfusionbusyindicator_p.h b/src/imports/controls/fusion/qquickfusionbusyindicator_p.h new file mode 100644 index 00000000..c8af3311 --- /dev/null +++ b/src/imports/controls/fusion/qquickfusionbusyindicator_p.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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 QQUICKFUSIONBUSYINDICATOR_P_H +#define QQUICKFUSIONBUSYINDICATOR_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 <QtGui/qcolor.h> +#include <QtQuick/qquickpainteditem.h> + +QT_BEGIN_NAMESPACE + +class QQuickFusionBusyIndicator : public QQuickPaintedItem +{ + Q_OBJECT + Q_PROPERTY(QColor color READ color WRITE setColor FINAL) + +public: + explicit QQuickFusionBusyIndicator(QQuickItem *parent = nullptr); + + QColor color() const; + void setColor(const QColor &color); + + void paint(QPainter *painter) override; + +private: + QColor m_color; +}; + +QT_END_NAMESPACE + +#endif // QQUICKFUSIONBUSYINDICATOR_P_H diff --git a/src/imports/controls/fusion/qquickfusiondial.cpp b/src/imports/controls/fusion/qquickfusiondial.cpp new file mode 100644 index 00000000..014078e6 --- /dev/null +++ b/src/imports/controls/fusion/qquickfusiondial.cpp @@ -0,0 +1,152 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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 "qquickfusiondial_p.h" + +#include <QtGui/qpainter.h> +#include <QtGui/private/qmath_p.h> + +QT_BEGIN_NAMESPACE + +QQuickFusionDial::QQuickFusionDial(QQuickItem *parent) + : QQuickPaintedItem(parent), + m_highlight(false) +{ +} + +bool QQuickFusionDial::highlight() const +{ + return m_highlight; +} + +void QQuickFusionDial::setHighlight(bool highlight) +{ + if (m_highlight == highlight) + return; + + m_highlight = highlight; + update(); +} + +QPalette QQuickFusionDial::palette() const +{ + return m_palette; +} + +void QQuickFusionDial::setPalette(const QPalette &palette) +{ + if (palette == m_palette) + return; + + m_palette = palette; + update(); +} + +// based on QStyleHelper::drawDial() +void QQuickFusionDial::paint(QPainter *painter) +{ + const int width = QQuickItem::width(); + const int height = QQuickItem::height(); + if (width <= 0 || height <= 0 || !isVisible()) + return; + + QColor buttonColor = m_palette.button().color(); + const bool enabled = isEnabled(); + qreal r = qMin(width, height) / 2; + r -= r/50; + const qreal penSize = r/20.0; + + painter->setRenderHint(QPainter::Antialiasing); + + const qreal d_ = r / 6; + const qreal dx = d_ + (width - 2 * r) / 2 + 1; + const qreal dy = d_ + (height - 2 * r) / 2 + 1; + + QRectF br = QRectF(dx + 0.5, dy + 0.5, + int(r * 2 - 2 * d_ - 2), + int(r * 2 - 2 * d_ - 2)); + buttonColor.setHsv(buttonColor .hue(), + qMin(140, buttonColor .saturation()), + qMax(180, buttonColor.value())); + + if (enabled) { + // Drop shadow + qreal shadowSize = qMax(1.0, penSize/2.0); + QRectF shadowRect= br.adjusted(-2*shadowSize, -2*shadowSize, + 2*shadowSize, 2*shadowSize); + QRadialGradient shadowGradient(shadowRect.center().x(), + shadowRect.center().y(), shadowRect.width()/2.0, + shadowRect.center().x(), shadowRect.center().y()); + shadowGradient.setColorAt(qreal(0.91), QColor(0, 0, 0, 40)); + shadowGradient.setColorAt(qreal(1.0), Qt::transparent); + painter->setBrush(shadowGradient); + painter->setPen(Qt::NoPen); + painter->translate(shadowSize, shadowSize); + painter->drawEllipse(shadowRect); + painter->translate(-shadowSize, -shadowSize); + + // Main gradient + QRadialGradient gradient(br.center().x() - br.width()/3, dy, + br.width()*1.3, br.center().x(), + br.center().y() - br.height()/2); + gradient.setColorAt(0, buttonColor.lighter(110)); + gradient.setColorAt(qreal(0.5), buttonColor); + gradient.setColorAt(qreal(0.501), buttonColor.darker(102)); + gradient.setColorAt(1, buttonColor.darker(115)); + painter->setBrush(gradient); + } else { + painter->setBrush(Qt::NoBrush); + } + + painter->setPen(QPen(buttonColor.darker(280))); + painter->drawEllipse(br); + painter->setBrush(Qt::NoBrush); + painter->setPen(buttonColor.lighter(110)); + painter->drawEllipse(br.adjusted(1, 1, -1, -1)); + + if (m_highlight) { + QColor highlight = m_palette.highlight().color(); + highlight.setHsv(highlight.hue(), + qMin(160, highlight.saturation()), + qMax(230, highlight.value())); + highlight.setAlpha(127); + painter->setPen(QPen(highlight, 2.0)); + painter->setBrush(Qt::NoBrush); + painter->drawEllipse(br.adjusted(-1, -1, 1, 1)); + } +} + +QT_END_NAMESPACE diff --git a/src/imports/controls/fusion/qquickfusiondial_p.h b/src/imports/controls/fusion/qquickfusiondial_p.h new file mode 100644 index 00000000..d3216521 --- /dev/null +++ b/src/imports/controls/fusion/qquickfusiondial_p.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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 QQUICKFUSIONDIAL_P_H +#define QQUICKFUSIONDIAL_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 <QtGui/qpalette.h> +#include <QtQuick/qquickpainteditem.h> + +QT_BEGIN_NAMESPACE + +class QQuickFusionDial : public QQuickPaintedItem +{ + Q_OBJECT + Q_PROPERTY(bool highlight READ highlight WRITE setHighlight FINAL) + Q_PROPERTY(QPalette palette READ palette WRITE setPalette FINAL) + +public: + explicit QQuickFusionDial(QQuickItem *parent = nullptr); + + bool highlight() const; + void setHighlight(bool highlight); + + QPalette palette() const; + void setPalette(const QPalette &palette); + + void paint(QPainter *painter) override; + +private: + bool m_highlight; + QPalette m_palette; +}; + +QT_END_NAMESPACE + +#endif // QQUICKFUSIONDIAL_P_H diff --git a/src/imports/controls/fusion/qquickfusionknob.cpp b/src/imports/controls/fusion/qquickfusionknob.cpp new file mode 100644 index 00000000..9f1824a6 --- /dev/null +++ b/src/imports/controls/fusion/qquickfusionknob.cpp @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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 "qquickfusionknob_p.h" + +#include <QtCore/qmath.h> +#include <QtGui/qpainter.h> + +QT_BEGIN_NAMESPACE + +QQuickFusionKnob::QQuickFusionKnob(QQuickItem *parent) + : QQuickPaintedItem(parent) +{ +} + +QPalette QQuickFusionKnob::palette() const +{ + return m_palette; +} + +void QQuickFusionKnob::setPalette(const QPalette &palette) +{ + if (palette == m_palette) + return; + + m_palette = palette; + update(); +} + +// extracted from QStyleHelper::drawDial() +void QQuickFusionKnob::paint(QPainter *painter) +{ + const qreal w = width(); + const qreal h = height(); + if (w <= 0 || h <= 0) + return; + + QColor color = m_palette.color(QPalette::Button); + color.setHsv(color.hue(), + qMin(140, color .saturation()), + qMax(180, color.value())); + color = color.lighter(104); + color.setAlphaF(qreal(0.8)); + + const qreal sz = qMin(w, h); + QRectF rect(0, 0, sz, sz); + rect.moveCenter(QPointF(w / 2.0, h / 2.0)); + const QPointF center = rect.center(); + + QRadialGradient gradient(center.x() + rect.width() / 2, + center.y() + rect.width(), + rect.width() * 2, + center.x(), center.y()); + gradient.setColorAt(1, color.darker(140)); + gradient.setColorAt(qreal(0.4), color.darker(120)); + gradient.setColorAt(0, color.darker(110)); + + painter->setRenderHint(QPainter::Antialiasing); + painter->setBrush(gradient); + painter->setPen(QColor(255, 255, 255, 150)); + painter->drawEllipse(rect); + painter->setPen(QColor(0, 0, 0, 80)); + painter->drawEllipse(rect.adjusted(1, 1, -1, -1)); +} + +QT_END_NAMESPACE diff --git a/src/imports/controls/fusion/qquickfusionknob_p.h b/src/imports/controls/fusion/qquickfusionknob_p.h new file mode 100644 index 00000000..062aaf21 --- /dev/null +++ b/src/imports/controls/fusion/qquickfusionknob_p.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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 QQUICKFUSIONKNOB_P_H +#define QQUICKFUSIONKNOB_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 <QtGui/qpalette.h> +#include <QtQuick/qquickpainteditem.h> + +QT_BEGIN_NAMESPACE + +class QQuickFusionKnob : public QQuickPaintedItem +{ + Q_OBJECT + Q_PROPERTY(QPalette palette READ palette WRITE setPalette FINAL) + +public: + explicit QQuickFusionKnob(QQuickItem *parent = nullptr); + + QPalette palette() const; + void setPalette(const QPalette &palette); + + void paint(QPainter *painter) override; + +private: + QPalette m_palette; +}; + +QT_END_NAMESPACE + +#endif // QQUICKFUSIONKNOB_P_H diff --git a/src/imports/controls/fusion/qquickfusionstyle.cpp b/src/imports/controls/fusion/qquickfusionstyle.cpp new file mode 100644 index 00000000..a66665fc --- /dev/null +++ b/src/imports/controls/fusion/qquickfusionstyle.cpp @@ -0,0 +1,172 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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 "qquickfusionstyle_p.h" + +#include <QtGui/qcolor.h> +#include <QtGui/qpalette.h> +#include <QtGui/qpa/qplatformtheme.h> +#include <QtGui/private/qguiapplication_p.h> + +QT_BEGIN_NAMESPACE + +// On mac we want a standard blue color used when the system palette is used +static bool isMacSystemPalette(const QPalette &palette) +{ + Q_UNUSED(palette); +#if defined(Q_OS_MACOS) + const QPalette *themePalette = QGuiApplicationPrivate::platformTheme()->palette(); + if (themePalette && themePalette->color(QPalette::Normal, QPalette::Highlight) == + palette.color(QPalette::Normal, QPalette::Highlight) && + themePalette->color(QPalette::Normal, QPalette::HighlightedText) == + palette.color(QPalette::Normal, QPalette::HighlightedText)) + return true; +#endif + return false; +} + +QQuickFusionStyle::QQuickFusionStyle(QObject *parent) + : QObject(parent) +{ +} + +QColor QQuickFusionStyle::lightShade() +{ + return QColor(255, 255, 255, 90); +} + +QColor QQuickFusionStyle::darkShade() +{ + return QColor(0, 0, 0, 60); +} + +QColor QQuickFusionStyle::topShadow() +{ + return QColor(0, 0, 0, 18); +} + +QColor QQuickFusionStyle::innerContrastLine() +{ + return QColor(255, 255, 255, 30); +} + +QColor QQuickFusionStyle::highlight(const QPalette &palette) +{ + if (isMacSystemPalette(palette)) + return QColor(60, 140, 230); + return palette.color(QPalette::Highlight); +} + +QColor QQuickFusionStyle::highlightedText(const QPalette &palette) +{ + if (isMacSystemPalette(palette)) + return Qt::white; + return palette.color(QPalette::HighlightedText); +} + +QColor QQuickFusionStyle::outline(const QPalette &palette) +{ + if (palette.window().style() == Qt::TexturePattern) + return QColor(0, 0, 0, 160); + return palette.background().color().darker(140); +} + +QColor QQuickFusionStyle::highlightedOutline(const QPalette &palette) +{ + QColor highlightedOutline = highlight(palette).darker(125); + if (highlightedOutline.value() > 160) + highlightedOutline.setHsl(highlightedOutline.hue(), highlightedOutline.saturation(), 160); + return highlightedOutline; +} + +QColor QQuickFusionStyle::tabFrameColor(const QPalette &palette) +{ + if (palette.window().style() == Qt::TexturePattern) + return QColor(255, 255, 255, 8); + return buttonColor(palette).lighter(104); +} + +QColor QQuickFusionStyle::buttonColor(const QPalette &palette, bool highlighted, bool down, bool hovered) +{ + QColor buttonColor = palette.button().color(); + int val = qGray(buttonColor.rgb()); + buttonColor = buttonColor.lighter(100 + qMax(1, (180 - val)/6)); + buttonColor.setHsv(buttonColor.hue(), buttonColor.saturation() * 0.75, buttonColor.value()); + if (highlighted) + buttonColor = mergedColors(buttonColor, highlightedOutline(palette).lighter(130), 90); + if (!hovered) + buttonColor = buttonColor.darker(104); + if (down) + buttonColor = buttonColor.darker(110); + return buttonColor; +} + +QColor QQuickFusionStyle::buttonOutline(const QPalette &palette, bool highlighted, bool enabled) +{ + QColor darkOutline = enabled && highlighted ? highlightedOutline(palette) : outline(palette); + return !enabled ? darkOutline.lighter(115) : darkOutline; +} + +QColor QQuickFusionStyle::gradientStart(const QColor &baseColor) +{ + return baseColor.lighter(124); +} + +QColor QQuickFusionStyle::gradientStop(const QColor &baseColor) +{ + return baseColor.lighter(102); +} + +QColor QQuickFusionStyle::mergedColors(const QColor &colorA, const QColor &colorB, int factor) +{ + const int maxFactor = 100; + QColor tmp = colorA; + tmp.setRed((tmp.red() * factor) / maxFactor + (colorB.red() * (maxFactor - factor)) / maxFactor); + tmp.setGreen((tmp.green() * factor) / maxFactor + (colorB.green() * (maxFactor - factor)) / maxFactor); + tmp.setBlue((tmp.blue() * factor) / maxFactor + (colorB.blue() * (maxFactor - factor)) / maxFactor); + return tmp; +} + +QColor QQuickFusionStyle::grooveColor(const QPalette &palette) +{ + QColor color = buttonColor(palette); + color.setHsv(color.hue(), + qMin(255, color.saturation()), + qMin<int>(255, color.value() * 0.9)); + return color; +} + +QT_END_NAMESPACE diff --git a/src/imports/controls/fusion/qquickfusionstyle_p.h b/src/imports/controls/fusion/qquickfusionstyle_p.h new file mode 100644 index 00000000..e0a99cc6 --- /dev/null +++ b/src/imports/controls/fusion/qquickfusionstyle_p.h @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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 QQUICKFUSIONSTYLE_P_H +#define QQUICKFUSIONSTYLE_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 <QtCore/qobject.h> +#include <QtGui/qcolor.h> + +QT_BEGIN_NAMESPACE + +class QQuickFusionStyle : public QObject +{ + Q_OBJECT + Q_PROPERTY(QColor lightShade READ lightShade CONSTANT) + Q_PROPERTY(QColor darkShade READ darkShade CONSTANT) + Q_PROPERTY(QColor topShadow READ topShadow CONSTANT) + Q_PROPERTY(QColor innerContrastLine READ innerContrastLine CONSTANT) + +public: + explicit QQuickFusionStyle(QObject *parent = nullptr); + + static QColor lightShade(); + static QColor darkShade(); + static QColor topShadow(); + static QColor innerContrastLine(); + + Q_INVOKABLE static QColor highlight(const QPalette &palette); + Q_INVOKABLE static QColor highlightedText(const QPalette &palette); + Q_INVOKABLE static QColor outline(const QPalette &palette); + Q_INVOKABLE static QColor highlightedOutline(const QPalette &palette); + Q_INVOKABLE static QColor tabFrameColor(const QPalette &palette); + Q_INVOKABLE static QColor buttonColor(const QPalette &palette, bool highlighted = false, bool down = false, bool hovered = false); + Q_INVOKABLE static QColor buttonOutline(const QPalette &palette, bool highlighted = false, bool enabled = true); + Q_INVOKABLE static QColor gradientStart(const QColor &baseColor); + Q_INVOKABLE static QColor gradientStop(const QColor &baseColor); + Q_INVOKABLE static QColor mergedColors(const QColor &colorA, const QColor &colorB, int factor = 50); + Q_INVOKABLE static QColor grooveColor(const QPalette &palette); +}; + +QT_END_NAMESPACE + +#endif // QQUICKFUSIONSTYLE_P_H diff --git a/src/imports/controls/fusion/qquickfusiontheme.cpp b/src/imports/controls/fusion/qquickfusiontheme.cpp new file mode 100644 index 00000000..31494efb --- /dev/null +++ b/src/imports/controls/fusion/qquickfusiontheme.cpp @@ -0,0 +1,46 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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 "qquickfusiontheme_p.h" + +QT_BEGIN_NAMESPACE + +QQuickFusionTheme::QQuickFusionTheme() + : QQuickTheme(QStringLiteral("Fusion")) +{ +} + +QT_END_NAMESPACE diff --git a/src/imports/controls/fusion/qquickfusiontheme_p.h b/src/imports/controls/fusion/qquickfusiontheme_p.h new file mode 100644 index 00000000..5dcfcf61 --- /dev/null +++ b/src/imports/controls/fusion/qquickfusiontheme_p.h @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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 QQUICKFUSIONTHEME_P_H +#define QQUICKFUSIONTHEME_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 <QtCore/qvariant.h> +#include <QtGui/qpalette.h> +#include <QtQuickControls2/private/qquicktheme_p.h> + +QT_BEGIN_NAMESPACE + +class QQuickFusionTheme : public QQuickTheme +{ +public: + explicit QQuickFusionTheme(); +}; + +QT_END_NAMESPACE + +#endif // QQUICKFUSIONTHEME_P_H diff --git a/src/imports/controls/fusion/qtquickcontrols2fusionstyle.qrc b/src/imports/controls/fusion/qtquickcontrols2fusionstyle.qrc new file mode 100644 index 00000000..74c8e671 --- /dev/null +++ b/src/imports/controls/fusion/qtquickcontrols2fusionstyle.qrc @@ -0,0 +1,16 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource prefix="qt-project.org/imports/QtQuick/Controls.2/Fusion"> + <file>images/arrow.png</file> + <file>images/arrow@2x.png</file> + <file>images/arrow@3x.png</file> + <file>images/arrow@4x.png</file> + <file>images/checkmark.png</file> + <file>images/checkmark@2x.png</file> + <file>images/checkmark@3x.png</file> + <file>images/checkmark@4x.png</file> + <file>images/progressmask.png</file> + <file>images/progressmask@2x.png</file> + <file>images/progressmask@3x.png</file> + <file>images/progressmask@4x.png</file> +</qresource> +</RCC> diff --git a/src/imports/controls/fusion/qtquickcontrols2fusionstyleplugin.cpp b/src/imports/controls/fusion/qtquickcontrols2fusionstyleplugin.cpp new file mode 100644 index 00000000..1fcacc5e --- /dev/null +++ b/src/imports/controls/fusion/qtquickcontrols2fusionstyleplugin.cpp @@ -0,0 +1,121 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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 <QtQuickControls2/private/qquickstyleplugin_p.h> +#include <QtQml/qqml.h> + +#include "qquickfusionbusyindicator_p.h" +#include "qquickfusiondial_p.h" +#include "qquickfusionknob_p.h" +#include "qquickfusionstyle_p.h" +#include "qquickfusiontheme_p.h" + +static inline void initResources() +{ + Q_INIT_RESOURCE(qtquickcontrols2fusionstyle); +#ifdef QT_STATIC + Q_INIT_RESOURCE(qmake_QtQuick_Controls_2_Fusion); +#endif +} + +QT_BEGIN_NAMESPACE + +static QObject *styleSingleton(QQmlEngine *engine, QJSEngine *scriptEngine) +{ + Q_UNUSED(engine); + Q_UNUSED(scriptEngine); + return new QQuickFusionStyle; +} + +class QtQuickControls2FusionStylePlugin: public QQuickStylePlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) + +public: + QtQuickControls2FusionStylePlugin(QObject *parent = nullptr); + + void registerTypes(const char *uri) override; + void initializeEngine(QQmlEngine *engine, const char *uri) override; + + QString name() const override; + QQuickProxyTheme *createTheme() const override; +}; + +QtQuickControls2FusionStylePlugin::QtQuickControls2FusionStylePlugin(QObject *parent) : QQuickStylePlugin(parent) +{ + initResources(); +} + +void QtQuickControls2FusionStylePlugin::registerTypes(const char *uri) +{ + qmlRegisterModule(uri, 2, QT_VERSION_MINOR - 7); // Qt 5.10->2.3, 5.11->2.4... +} + +void QtQuickControls2FusionStylePlugin::initializeEngine(QQmlEngine *engine, const char *uri) +{ + QQuickStylePlugin::initializeEngine(engine, uri); + + QByteArray import = QByteArray(uri) + ".impl"; + qmlRegisterModule(import, 2, QT_VERSION_MINOR - 7); // Qt 5.10->2.3, 5.11->2.4... + + qmlRegisterSingletonType<QQuickFusionStyle>(import, 2, 3, "Fusion", styleSingleton); + + qmlRegisterType<QQuickFusionBusyIndicator>(import, 2, 3, "BusyIndicatorImpl"); + qmlRegisterType<QQuickFusionDial>(import, 2, 3, "DialImpl"); + qmlRegisterType<QQuickFusionKnob>(import, 2, 3, "KnobImpl"); + + qmlRegisterType(typeUrl(QStringLiteral("ButtonPanel.qml")), import, 2, 3, "ButtonPanel"); + qmlRegisterType(typeUrl(QStringLiteral("CheckIndicator.qml")), import, 2, 3, "CheckIndicator"); + qmlRegisterType(typeUrl(QStringLiteral("RadioIndicator.qml")), import, 2, 3, "RadioIndicator"); + qmlRegisterType(typeUrl(QStringLiteral("SliderGroove.qml")), import, 2, 3, "SliderGroove"); + qmlRegisterType(typeUrl(QStringLiteral("SliderHandle.qml")), import, 2, 3, "SliderHandle"); + qmlRegisterType(typeUrl(QStringLiteral("SwitchIndicator.qml")), import, 2, 3, "SwitchIndicator"); +} + +QString QtQuickControls2FusionStylePlugin::name() const +{ + return QStringLiteral("fusion"); +} + +QQuickProxyTheme *QtQuickControls2FusionStylePlugin::createTheme() const +{ + return new QQuickFusionTheme; +} + +QT_END_NAMESPACE + +#include "qtquickcontrols2fusionstyleplugin.moc" diff --git a/src/imports/controls/material/ApplicationWindow.qml b/src/imports/controls/material/ApplicationWindow.qml index 0d56ed2c..45f1b59a 100644 --- a/src/imports/controls/material/ApplicationWindow.qml +++ b/src/imports/controls/material/ApplicationWindow.qml @@ -36,8 +36,8 @@ import QtQuick 2.9 import QtQuick.Window 2.3 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Material 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls.Material 2.3 T.ApplicationWindow { id: window diff --git a/src/imports/controls/material/BoxShadow.qml b/src/imports/controls/material/BoxShadow.qml index aa9fd0fa..b2ceeaeb 100644 --- a/src/imports/controls/material/BoxShadow.qml +++ b/src/imports/controls/material/BoxShadow.qml @@ -35,8 +35,8 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Controls.Material 2.2 -import QtQuick.Controls.Material.impl 2.2 +import QtQuick.Controls.Material 2.3 +import QtQuick.Controls.Material.impl 2.3 /* A implementation of CSS's box-shadow, used by ElevationEffect for a Material Design diff --git a/src/imports/controls/material/BusyIndicator.qml b/src/imports/controls/material/BusyIndicator.qml index f1cf8eb5..6ffd65cc 100644 --- a/src/imports/controls/material/BusyIndicator.qml +++ b/src/imports/controls/material/BusyIndicator.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Material 2.2 -import QtQuick.Controls.Material.impl 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls.Material 2.3 +import QtQuick.Controls.Material.impl 2.3 T.BusyIndicator { id: control diff --git a/src/imports/controls/material/Button.qml b/src/imports/controls/material/Button.qml index e5821375..7d5ff57d 100644 --- a/src/imports/controls/material/Button.qml +++ b/src/imports/controls/material/Button.qml @@ -35,9 +35,11 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Material 2.2 -import QtQuick.Controls.Material.impl 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Material 2.3 +import QtQuick.Controls.Material.impl 2.3 T.Button { id: control @@ -52,20 +54,29 @@ T.Button { padding: 12 leftPadding: padding - 4 rightPadding: padding - 4 + spacing: 6 + + icon.width: 24 + icon.height: 24 + icon.color: !enabled ? Material.hintTextColor : + flat && highlighted ? Material.accentColor : + highlighted ? Material.primaryHighlightedTextColor : Material.foreground Material.elevation: flat ? control.down || control.hovered ? 2 : 0 : control.down ? 8 : 2 Material.background: flat ? "transparent" : undefined - contentItem: Text { + contentItem: IconLabel { + spacing: control.spacing + mirrored: control.mirrored + display: control.display + + icon: control.icon text: control.text font: control.font color: !control.enabled ? control.Material.hintTextColor : control.flat && control.highlighted ? control.Material.accentColor : control.highlighted ? control.Material.primaryHighlightedTextColor : control.Material.foreground - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - elide: Text.ElideRight } // TODO: Add a proper ripple/ink effect for mouse/touch input and focus state diff --git a/src/imports/controls/material/CheckBox.qml b/src/imports/controls/material/CheckBox.qml index e1c559da..543122b8 100644 --- a/src/imports/controls/material/CheckBox.qml +++ b/src/imports/controls/material/CheckBox.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Material 2.2 -import QtQuick.Controls.Material.impl 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls.Material 2.3 +import QtQuick.Controls.Material.impl 2.3 T.CheckBox { id: control diff --git a/src/imports/controls/material/CheckDelegate.qml b/src/imports/controls/material/CheckDelegate.qml index 545ca64a..5e6aabef 100644 --- a/src/imports/controls/material/CheckDelegate.qml +++ b/src/imports/controls/material/CheckDelegate.qml @@ -35,9 +35,11 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Material 2.2 -import QtQuick.Controls.Material.impl 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Material 2.3 +import QtQuick.Controls.Material.impl 2.3 T.CheckDelegate { id: control @@ -54,23 +56,29 @@ T.CheckDelegate { bottomPadding: 14 spacing: 16 + icon.width: 24 + icon.height: 24 + icon.color: enabled ? Material.foreground : Material.hintTextColor + indicator: CheckIndicator { x: text ? (control.mirrored ? control.leftPadding : control.width - width - control.rightPadding) : control.leftPadding + (control.availableWidth - width) / 2 y: control.topPadding + (control.availableHeight - height) / 2 control: control } - contentItem: Text { + contentItem: IconLabel { leftPadding: !control.mirrored ? 0 : control.indicator.width + control.spacing rightPadding: control.mirrored ? 0 : control.indicator.width + control.spacing + spacing: control.spacing + mirrored: control.mirrored + display: control.display + alignment: control.display === IconLabel.IconOnly || control.display === IconLabel.TextUnderIcon ? Qt.AlignCenter : Qt.AlignLeft + + icon: control.icon text: control.text font: control.font color: control.enabled ? control.Material.foreground : control.Material.hintTextColor - elide: Text.ElideRight - visible: control.text - horizontalAlignment: Text.AlignLeft - verticalAlignment: Text.AlignVCenter } background: Rectangle { diff --git a/src/imports/controls/material/CheckIndicator.qml b/src/imports/controls/material/CheckIndicator.qml index 8fe860f0..b8d4a972 100644 --- a/src/imports/controls/material/CheckIndicator.qml +++ b/src/imports/controls/material/CheckIndicator.qml @@ -35,8 +35,8 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Controls.Material 2.2 -import QtQuick.Controls.Material.impl 2.2 +import QtQuick.Controls.Material 2.3 +import QtQuick.Controls.Material.impl 2.3 Rectangle { id: indicatorItem diff --git a/src/imports/controls/material/ComboBox.qml b/src/imports/controls/material/ComboBox.qml index da9fd73c..57d5a61b 100644 --- a/src/imports/controls/material/ComboBox.qml +++ b/src/imports/controls/material/ComboBox.qml @@ -36,10 +36,11 @@ import QtQuick 2.9 import QtQuick.Window 2.3 -import QtQuick.Controls 2.2 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Material 2.2 -import QtQuick.Controls.Material.impl 2.2 +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls.Material 2.3 +import QtQuick.Controls.Material.impl 2.3 T.ComboBox { id: control @@ -67,12 +68,11 @@ T.ComboBox { hoverEnabled: control.hoverEnabled } - indicator: Image { + indicator: ColorImage { x: control.mirrored ? control.padding : control.width - width - control.padding y: control.topPadding + (control.availableHeight - height) / 2 - source: "image://material/drop-indicator/" + (control.enabled ? control.Material.foreground : control.Material.hintTextColor) - sourceSize.width: width - sourceSize.height: height + color: control.enabled ? control.Material.foreground : control.Material.hintTextColor + source: "qrc:/qt-project.org/imports/QtQuick/Controls.2/Material/images/drop-indicator.png" } contentItem: T.TextField { @@ -163,7 +163,6 @@ T.ComboBox { implicitHeight: contentHeight model: control.popup.visible ? control.delegateModel : null currentIndex: control.highlightedIndex - highlightRangeMode: ListView.ApplyRange highlightMoveDuration: 0 T.ScrollIndicator.vertical: ScrollIndicator { } diff --git a/src/imports/controls/material/CursorDelegate.qml b/src/imports/controls/material/CursorDelegate.qml index 2af44017..032f01c7 100644 --- a/src/imports/controls/material/CursorDelegate.qml +++ b/src/imports/controls/material/CursorDelegate.qml @@ -35,7 +35,7 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Controls.Material 2.2 +import QtQuick.Controls.Material 2.3 Rectangle { id: cursor diff --git a/src/imports/controls/material/DelayButton.qml b/src/imports/controls/material/DelayButton.qml index 16f240a2..df4dc3fe 100644 --- a/src/imports/controls/material/DelayButton.qml +++ b/src/imports/controls/material/DelayButton.qml @@ -35,9 +35,11 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Material 2.2 -import QtQuick.Controls.Material.impl 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Material 2.3 +import QtQuick.Controls.Material.impl 2.3 T.DelayButton { id: control diff --git a/src/imports/controls/material/Dial.qml b/src/imports/controls/material/Dial.qml index e0632e62..4c4fb239 100644 --- a/src/imports/controls/material/Dial.qml +++ b/src/imports/controls/material/Dial.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Material 2.2 -import QtQuick.Controls.Material.impl 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls.Material 2.3 +import QtQuick.Controls.Material.impl 2.3 T.Dial { id: control diff --git a/src/imports/controls/material/Dialog.qml b/src/imports/controls/material/Dialog.qml index a97cb2fd..68f856c6 100644 --- a/src/imports/controls/material/Dialog.qml +++ b/src/imports/controls/material/Dialog.qml @@ -35,10 +35,11 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls 2.2 -import QtQuick.Controls.Material 2.2 -import QtQuick.Controls.Material.impl 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Material 2.3 +import QtQuick.Controls.Material.impl 2.3 T.Dialog { id: control diff --git a/src/imports/controls/material/DialogButtonBox.qml b/src/imports/controls/material/DialogButtonBox.qml index c4b3e0ad..0b1321a2 100644 --- a/src/imports/controls/material/DialogButtonBox.qml +++ b/src/imports/controls/material/DialogButtonBox.qml @@ -35,10 +35,11 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls 2.2 -import QtQuick.Controls.Material 2.2 -import QtQuick.Controls.Material.impl 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Material 2.3 +import QtQuick.Controls.Material.impl 2.3 T.DialogButtonBox { id: control diff --git a/src/imports/controls/material/Drawer.qml b/src/imports/controls/material/Drawer.qml index dc06c895..78b6f2b8 100644 --- a/src/imports/controls/material/Drawer.qml +++ b/src/imports/controls/material/Drawer.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Material 2.2 -import QtQuick.Controls.Material.impl 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls.Material 2.3 +import QtQuick.Controls.Material.impl 2.3 T.Drawer { id: control diff --git a/src/imports/controls/material/ElevationEffect.qml b/src/imports/controls/material/ElevationEffect.qml index 0d0c1992..1d60a102 100644 --- a/src/imports/controls/material/ElevationEffect.qml +++ b/src/imports/controls/material/ElevationEffect.qml @@ -35,8 +35,8 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Controls.Material 2.2 -import QtQuick.Controls.Material.impl 2.2 +import QtQuick.Controls.Material 2.3 +import QtQuick.Controls.Material.impl 2.3 /* An effect for standard Material Design elevation shadows. Useful for using as \c layer.effect. diff --git a/src/imports/controls/material/Frame.qml b/src/imports/controls/material/Frame.qml index 760fc6d2..56cbdcaa 100644 --- a/src/imports/controls/material/Frame.qml +++ b/src/imports/controls/material/Frame.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Material 2.2 -import QtQuick.Controls.Material.impl 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls.Material 2.3 +import QtQuick.Controls.Material.impl 2.3 T.Frame { id: control diff --git a/src/imports/controls/material/GroupBox.qml b/src/imports/controls/material/GroupBox.qml index e7055404..67bf2090 100644 --- a/src/imports/controls/material/GroupBox.qml +++ b/src/imports/controls/material/GroupBox.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Material 2.2 -import QtQuick.Controls.Material.impl 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls.Material 2.3 +import QtQuick.Controls.Material.impl 2.3 T.GroupBox { id: control diff --git a/src/imports/controls/material/ItemDelegate.qml b/src/imports/controls/material/ItemDelegate.qml index 59d51c36..09471fae 100644 --- a/src/imports/controls/material/ItemDelegate.qml +++ b/src/imports/controls/material/ItemDelegate.qml @@ -35,9 +35,11 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Material 2.2 -import QtQuick.Controls.Material.impl 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Material 2.3 +import QtQuick.Controls.Material.impl 2.3 T.ItemDelegate { id: control @@ -52,17 +54,20 @@ T.ItemDelegate { padding: 16 spacing: 16 - contentItem: Text { - leftPadding: control.checkable && !control.mirrored ? (control.indicator ? control.indicator.width : 0) + control.spacing : 0 - rightPadding: control.checkable && control.mirrored ? (control.indicator ? control.indicator.width : 0) + control.spacing : 0 + icon.width: 24 + icon.height: 24 + icon.color: enabled ? Material.foreground : Material.hintTextColor + contentItem: IconLabel { + spacing: control.spacing + mirrored: control.mirrored + display: control.display + alignment: control.display === IconLabel.IconOnly || control.display === IconLabel.TextUnderIcon ? Qt.AlignCenter : Qt.AlignLeft + + icon: control.icon text: control.text font: control.font color: control.enabled ? control.Material.foreground : control.Material.hintTextColor - elide: Text.ElideRight - visible: control.text - horizontalAlignment: Text.AlignLeft - verticalAlignment: Text.AlignVCenter } background: Rectangle { diff --git a/src/imports/controls/material/Label.qml b/src/imports/controls/material/Label.qml index 4433e248..ddbe80c4 100644 --- a/src/imports/controls/material/Label.qml +++ b/src/imports/controls/material/Label.qml @@ -35,8 +35,8 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Material 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls.Material 2.3 T.Label { id: control diff --git a/src/imports/controls/material/Menu.qml b/src/imports/controls/material/Menu.qml index 3e76c81d..1d0d368a 100644 --- a/src/imports/controls/material/Menu.qml +++ b/src/imports/controls/material/Menu.qml @@ -35,10 +35,10 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Controls 2.2 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Material 2.2 -import QtQuick.Controls.Material.impl 2.2 +import QtQuick.Controls 2.3 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls.Material 2.3 +import QtQuick.Controls.Material.impl 2.3 T.Menu { id: control @@ -56,6 +56,8 @@ T.Menu { transformOrigin: Item.Top + delegate: MenuItem { } + enter: Transition { // grow_fade_in NumberAnimation { property: "scale"; from: 0.9; to: 1.0; easing.type: Easing.OutQuint; duration: 220 } diff --git a/src/imports/controls/material/MenuItem.qml b/src/imports/controls/material/MenuItem.qml index 5a136231..b91718b6 100644 --- a/src/imports/controls/material/MenuItem.qml +++ b/src/imports/controls/material/MenuItem.qml @@ -35,9 +35,11 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Material 2.2 -import QtQuick.Controls.Material.impl 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Material 2.3 +import QtQuick.Controls.Material.impl 2.3 T.MenuItem { id: control @@ -54,6 +56,10 @@ T.MenuItem { bottomPadding: 12 spacing: 16 + icon.width: 24 + icon.height: 24 + icon.color: enabled ? Material.foreground : Material.hintTextColor + indicator: CheckIndicator { x: text ? (control.mirrored ? control.width - width - control.rightPadding : control.leftPadding) : control.leftPadding + (control.availableWidth - width) / 2 y: control.topPadding + (control.availableHeight - height) / 2 @@ -61,17 +67,19 @@ T.MenuItem { control: control } - contentItem: Text { + contentItem: IconLabel { leftPadding: control.checkable && !control.mirrored ? control.indicator.width + control.spacing : 0 rightPadding: control.checkable && control.mirrored ? control.indicator.width + control.spacing : 0 + spacing: control.spacing + mirrored: control.mirrored + display: control.display + alignment: Qt.AlignLeft + + icon: control.icon text: control.text font: control.font color: control.enabled ? control.Material.foreground : control.Material.hintTextColor - elide: Text.ElideRight - visible: control.text - horizontalAlignment: Text.AlignLeft - verticalAlignment: Text.AlignVCenter } background: Rectangle { diff --git a/src/imports/controls/material/MenuSeparator.qml b/src/imports/controls/material/MenuSeparator.qml index fd0febbe..b00ae79b 100644 --- a/src/imports/controls/material/MenuSeparator.qml +++ b/src/imports/controls/material/MenuSeparator.qml @@ -35,8 +35,8 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Material 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls.Material 2.3 T.MenuSeparator { id: control diff --git a/src/imports/controls/material/Page.qml b/src/imports/controls/material/Page.qml index 825b9f90..cb2ae6f9 100644 --- a/src/imports/controls/material/Page.qml +++ b/src/imports/controls/material/Page.qml @@ -35,8 +35,8 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Material 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls.Material 2.3 T.Page { id: control diff --git a/src/imports/controls/material/PageIndicator.qml b/src/imports/controls/material/PageIndicator.qml index 15acae5e..55a60e51 100644 --- a/src/imports/controls/material/PageIndicator.qml +++ b/src/imports/controls/material/PageIndicator.qml @@ -35,8 +35,8 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Material 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls.Material 2.3 T.PageIndicator { id: control diff --git a/src/imports/controls/material/Pane.qml b/src/imports/controls/material/Pane.qml index 925778fa..6109f65d 100644 --- a/src/imports/controls/material/Pane.qml +++ b/src/imports/controls/material/Pane.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Material 2.2 -import QtQuick.Controls.Material.impl 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls.Material 2.3 +import QtQuick.Controls.Material.impl 2.3 T.Pane { id: control diff --git a/src/imports/controls/material/Popup.qml b/src/imports/controls/material/Popup.qml index cfcf00cb..49b39a6c 100644 --- a/src/imports/controls/material/Popup.qml +++ b/src/imports/controls/material/Popup.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Material 2.2 -import QtQuick.Controls.Material.impl 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls.Material 2.3 +import QtQuick.Controls.Material.impl 2.3 T.Popup { id: control diff --git a/src/imports/controls/material/ProgressBar.qml b/src/imports/controls/material/ProgressBar.qml index 1bc03016..daa2c74b 100644 --- a/src/imports/controls/material/ProgressBar.qml +++ b/src/imports/controls/material/ProgressBar.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Material 2.2 -import QtQuick.Controls.Material.impl 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls.Material 2.3 +import QtQuick.Controls.Material.impl 2.3 T.ProgressBar { id: control diff --git a/src/imports/controls/material/RadioButton.qml b/src/imports/controls/material/RadioButton.qml index d178654f..81cd302b 100644 --- a/src/imports/controls/material/RadioButton.qml +++ b/src/imports/controls/material/RadioButton.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Material 2.2 -import QtQuick.Controls.Material.impl 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls.Material 2.3 +import QtQuick.Controls.Material.impl 2.3 T.RadioButton { id: control diff --git a/src/imports/controls/material/RadioDelegate.qml b/src/imports/controls/material/RadioDelegate.qml index fb4f33dc..7b163ea8 100644 --- a/src/imports/controls/material/RadioDelegate.qml +++ b/src/imports/controls/material/RadioDelegate.qml @@ -35,9 +35,11 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Material 2.2 -import QtQuick.Controls.Material.impl 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Material 2.3 +import QtQuick.Controls.Material.impl 2.3 T.RadioDelegate { id: control @@ -54,23 +56,29 @@ T.RadioDelegate { bottomPadding: 8 spacing: 16 + icon.width: 24 + icon.height: 24 + icon.color: enabled ? Material.foreground : Material.hintTextColor + indicator: RadioIndicator { x: text ? (control.mirrored ? control.leftPadding : control.width - width - control.rightPadding) : control.leftPadding + (control.availableWidth - width) / 2 y: control.topPadding + (control.availableHeight - height) / 2 control: control } - contentItem: Text { + contentItem: IconLabel { leftPadding: !control.mirrored ? 0 : control.indicator.width + control.spacing rightPadding: control.mirrored ? 0 : control.indicator.width + control.spacing + spacing: control.spacing + mirrored: control.mirrored + display: control.display + alignment: control.display === IconLabel.IconOnly || control.display === IconLabel.TextUnderIcon ? Qt.AlignCenter : Qt.AlignLeft + + icon: control.icon text: control.text font: control.font color: control.enabled ? control.Material.foreground : control.Material.hintTextColor - elide: Text.ElideRight - visible: control.text - horizontalAlignment: Text.AlignLeft - verticalAlignment: Text.AlignVCenter } background: Rectangle { diff --git a/src/imports/controls/material/RadioIndicator.qml b/src/imports/controls/material/RadioIndicator.qml index 82b01ad3..2da77446 100644 --- a/src/imports/controls/material/RadioIndicator.qml +++ b/src/imports/controls/material/RadioIndicator.qml @@ -35,8 +35,8 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Controls.Material 2.2 -import QtQuick.Controls.Material.impl 2.2 +import QtQuick.Controls.Material 2.3 +import QtQuick.Controls.Material.impl 2.3 Rectangle { implicitWidth: 20 diff --git a/src/imports/controls/material/RangeSlider.qml b/src/imports/controls/material/RangeSlider.qml index 0b38ad6d..6e631843 100644 --- a/src/imports/controls/material/RangeSlider.qml +++ b/src/imports/controls/material/RangeSlider.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Material 2.2 -import QtQuick.Controls.Material.impl 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls.Material 2.3 +import QtQuick.Controls.Material.impl 2.3 T.RangeSlider { id: control @@ -52,8 +52,8 @@ T.RangeSlider { padding: 6 first.handle: SliderHandle { - x: control.leftPadding + (horizontal ? control.first.visualPosition * (control.availableWidth - width) : (control.availableWidth - width) / 2) - y: control.topPadding + (horizontal ? (control.availableHeight - height) / 2 : control.first.visualPosition * (control.availableHeight - height)) + x: control.leftPadding + (control.horizontal ? control.first.visualPosition * (control.availableWidth - width) : (control.availableWidth - width) / 2) + y: control.topPadding + (control.horizontal ? (control.availableHeight - height) / 2 : control.first.visualPosition * (control.availableHeight - height)) value: first.value handleHasFocus: activeFocus handlePressed: first.pressed @@ -61,8 +61,8 @@ T.RangeSlider { } second.handle: SliderHandle { - x: control.leftPadding + (horizontal ? control.second.visualPosition * (control.availableWidth - width) : (control.availableWidth - width) / 2) - y: control.topPadding + (horizontal ? (control.availableHeight - height) / 2 : control.second.visualPosition * (control.availableHeight - height)) + x: control.leftPadding + (control.horizontal ? control.second.visualPosition * (control.availableWidth - width) : (control.availableWidth - width) / 2) + y: control.topPadding + (control.horizontal ? (control.availableHeight - height) / 2 : control.second.visualPosition * (control.availableHeight - height)) value: second.value handleHasFocus: activeFocus handlePressed: second.pressed @@ -70,22 +70,20 @@ T.RangeSlider { } background: Rectangle { - x: control.leftPadding + (horizontal ? 0 : (control.availableWidth - width) / 2) - y: control.topPadding + (horizontal ? (control.availableHeight - height) / 2 : 0) - implicitWidth: horizontal ? 200 : 48 - implicitHeight: horizontal ? 48 : 200 - width: horizontal ? control.availableWidth : 1 - height: horizontal ? 1 : control.availableHeight + x: control.leftPadding + (control.horizontal ? 0 : (control.availableWidth - width) / 2) + y: control.topPadding + (control.horizontal ? (control.availableHeight - height) / 2 : 0) + implicitWidth: control.horizontal ? 200 : 48 + implicitHeight: control.horizontal ? 48 : 200 + width: control.horizontal ? control.availableWidth : 1 + height: control.horizontal ? 1 : control.availableHeight color: control.Material.foreground - scale: horizontal && control.mirrored ? -1 : 1 - - readonly property bool horizontal: control.orientation === Qt.Horizontal + scale:control.horizontal && control.mirrored ? -1 : 1 Rectangle { - x: parent.horizontal ? control.first.position * parent.width : -1 - y: parent.horizontal ? -1 : control.second.visualPosition * parent.height + 3 - width: parent.horizontal ? control.second.position * parent.width - control.first.position * parent.width - 3 : 3 - height: parent.horizontal ? 3 : control.second.position * parent.height - control.first.position * parent.height - 3 + x: control.horizontal ? control.first.position * parent.width : -1 + y: control.horizontal ? -1 : control.second.visualPosition * parent.height + 3 + width: control.horizontal ? control.second.position * parent.width - control.first.position * parent.width - 3 : 3 + height: control.horizontal ? 3 : control.second.position * parent.height - control.first.position * parent.height - 3 color: control.Material.accentColor } diff --git a/src/imports/controls/material/RoundButton.qml b/src/imports/controls/material/RoundButton.qml index 9660a1e4..f36ef614 100644 --- a/src/imports/controls/material/RoundButton.qml +++ b/src/imports/controls/material/RoundButton.qml @@ -35,9 +35,11 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Material 2.2 -import QtQuick.Controls.Material.impl 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Material 2.3 +import QtQuick.Controls.Material.impl 2.3 T.RoundButton { id: control @@ -50,20 +52,29 @@ T.RoundButton { // external vertical padding is 6 (to increase touch area) padding: 12 + spacing: 6 + + icon.width: 24 + icon.height: 24 + icon.color: !enabled ? Material.hintTextColor : + flat && highlighted ? Material.accentColor : + highlighted ? Material.primaryHighlightedTextColor : Material.foreground Material.elevation: flat ? control.down || control.hovered ? 2 : 0 : control.down ? 12 : 6 Material.background: flat ? "transparent" : undefined - contentItem: Text { + contentItem: IconLabel { + spacing: control.spacing + mirrored: control.mirrored + display: control.display + + icon: control.icon text: control.text font: control.font color: !control.enabled ? control.Material.hintTextColor : control.flat && control.highlighted ? control.Material.accentColor : control.highlighted ? control.Material.primaryHighlightedTextColor : control.Material.foreground - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - elide: Text.ElideRight } // TODO: Add a proper ripple/ink effect for mouse/touch input and focus state diff --git a/src/imports/controls/material/ScrollBar.qml b/src/imports/controls/material/ScrollBar.qml index 156c5781..1b014b87 100644 --- a/src/imports/controls/material/ScrollBar.qml +++ b/src/imports/controls/material/ScrollBar.qml @@ -35,8 +35,8 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Material 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls.Material 2.3 T.ScrollBar { id: control diff --git a/src/imports/controls/material/ScrollIndicator.qml b/src/imports/controls/material/ScrollIndicator.qml index effb18ad..38bb5a65 100644 --- a/src/imports/controls/material/ScrollIndicator.qml +++ b/src/imports/controls/material/ScrollIndicator.qml @@ -35,8 +35,8 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Material 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls.Material 2.3 T.ScrollIndicator { id: control diff --git a/src/imports/controls/material/Slider.qml b/src/imports/controls/material/Slider.qml index cb60dba6..f7bdfeb1 100644 --- a/src/imports/controls/material/Slider.qml +++ b/src/imports/controls/material/Slider.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Material 2.2 -import QtQuick.Controls.Material.impl 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls.Material 2.3 +import QtQuick.Controls.Material.impl 2.3 T.Slider { id: control @@ -50,8 +50,8 @@ T.Slider { padding: 6 handle: SliderHandle { - x: control.leftPadding + (horizontal ? control.visualPosition * (control.availableWidth - width) : (control.availableWidth - width) / 2) - y: control.topPadding + (horizontal ? (control.availableHeight - height) / 2 : control.visualPosition * (control.availableHeight - height)) + x: control.leftPadding + (control.horizontal ? control.visualPosition * (control.availableWidth - width) : (control.availableWidth - width) / 2) + y: control.topPadding + (control.horizontal ? (control.availableHeight - height) / 2 : control.visualPosition * (control.availableHeight - height)) value: control.value handleHasFocus: control.visualFocus handlePressed: control.pressed @@ -59,22 +59,20 @@ T.Slider { } background: Rectangle { - x: control.leftPadding + (horizontal ? 0 : (control.availableWidth - width) / 2) - y: control.topPadding + (horizontal ? (control.availableHeight - height) / 2 : 0) - implicitWidth: horizontal ? 200 : 48 - implicitHeight: horizontal ? 48 : 200 - width: horizontal ? control.availableWidth : 1 - height: horizontal ? 1 : control.availableHeight + x: control.leftPadding + (control.horizontal ? 0 : (control.availableWidth - width) / 2) + y: control.topPadding + (control.horizontal ? (control.availableHeight - height) / 2 : 0) + implicitWidth: control.horizontal ? 200 : 48 + implicitHeight: control.horizontal ? 48 : 200 + width: control.horizontal ? control.availableWidth : 1 + height: control.horizontal ? 1 : control.availableHeight color: control.Material.foreground - scale: horizontal && control.mirrored ? -1 : 1 - - readonly property bool horizontal: control.orientation === Qt.Horizontal + scale: control.horizontal && control.mirrored ? -1 : 1 Rectangle { - x: parent.horizontal ? 0 : (parent.width - width) / 2 - y: parent.horizontal ? (parent.height - height) / 2 : control.visualPosition * parent.height - width: parent.horizontal ? control.position * parent.width : 3 - height: parent.horizontal ? 3 : control.position * parent.height + x: control.horizontal ? 0 : (parent.width - width) / 2 + y: control.horizontal ? (parent.height - height) / 2 : control.visualPosition * parent.height + width: control.horizontal ? control.position * parent.width : 3 + height: control.horizontal ? 3 : control.position * parent.height color: control.Material.accentColor } diff --git a/src/imports/controls/material/SliderHandle.qml b/src/imports/controls/material/SliderHandle.qml index dd4de4a2..7ab4b1a2 100644 --- a/src/imports/controls/material/SliderHandle.qml +++ b/src/imports/controls/material/SliderHandle.qml @@ -35,8 +35,8 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Controls.Material 2.2 -import QtQuick.Controls.Material.impl 2.2 +import QtQuick.Controls.Material 2.3 +import QtQuick.Controls.Material.impl 2.3 Item { id: root @@ -48,7 +48,6 @@ Item { property bool handlePressed: false property bool handleHovered: false readonly property int initialSize: 13 - readonly property bool horizontal: control.orientation === Qt.Horizontal readonly property var control: parent Rectangle { diff --git a/src/imports/controls/material/SpinBox.qml b/src/imports/controls/material/SpinBox.qml index f0dfba08..816dcb14 100644 --- a/src/imports/controls/material/SpinBox.qml +++ b/src/imports/controls/material/SpinBox.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Material 2.2 -import QtQuick.Controls.Material.impl 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls.Material 2.3 +import QtQuick.Controls.Material.impl 2.3 T.SpinBox { id: control diff --git a/src/imports/controls/material/StackView.qml b/src/imports/controls/material/StackView.qml index 03cd384d..6cc5634a 100644 --- a/src/imports/controls/material/StackView.qml +++ b/src/imports/controls/material/StackView.qml @@ -35,7 +35,7 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T +import QtQuick.Templates 2.3 as T T.StackView { id: control diff --git a/src/imports/controls/material/SwipeDelegate.qml b/src/imports/controls/material/SwipeDelegate.qml index d9014fcd..08f07e1f 100644 --- a/src/imports/controls/material/SwipeDelegate.qml +++ b/src/imports/controls/material/SwipeDelegate.qml @@ -35,9 +35,11 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Material 2.2 -import QtQuick.Controls.Material.impl 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Material 2.3 +import QtQuick.Controls.Material.impl 2.3 T.SwipeDelegate { id: control @@ -54,19 +56,22 @@ T.SwipeDelegate { bottomPadding: 8 spacing: 16 + icon.width: 24 + icon.height: 24 + icon.color: enabled ? Material.foreground : Material.hintTextColor + swipe.transition: Transition { SmoothedAnimation { velocity: 3; easing.type: Easing.InOutCubic } } - contentItem: Text { - leftPadding: !control.mirrored ? (control.indicator ? control.indicator.width + control.spacing : 0) : 0 - rightPadding: control.mirrored ? (control.indicator ? control.indicator.width + control.spacing : 0) : 0 + contentItem: IconLabel { + spacing: control.spacing + mirrored: control.mirrored + display: control.display + alignment: control.display === IconLabel.IconOnly || control.display === IconLabel.TextUnderIcon ? Qt.AlignCenter : Qt.AlignLeft + icon: control.icon text: control.text font: control.font color: control.enabled ? control.Material.foreground : control.Material.hintTextColor - elide: Text.ElideRight - visible: control.text - horizontalAlignment: Text.AlignLeft - verticalAlignment: Text.AlignVCenter } background: Rectangle { diff --git a/src/imports/controls/material/SwipeView.qml b/src/imports/controls/material/SwipeView.qml index 293cce46..26a1de0b 100644 --- a/src/imports/controls/material/SwipeView.qml +++ b/src/imports/controls/material/SwipeView.qml @@ -35,7 +35,7 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T +import QtQuick.Templates 2.3 as T T.SwipeView { id: control diff --git a/src/imports/controls/material/Switch.qml b/src/imports/controls/material/Switch.qml index c4f279ee..7207c940 100644 --- a/src/imports/controls/material/Switch.qml +++ b/src/imports/controls/material/Switch.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Controls.Material 2.2 -import QtQuick.Controls.Material.impl 2.2 -import QtQuick.Templates 2.2 as T +import QtQuick.Controls.Material 2.3 +import QtQuick.Controls.Material.impl 2.3 +import QtQuick.Templates 2.3 as T T.Switch { id: control diff --git a/src/imports/controls/material/SwitchDelegate.qml b/src/imports/controls/material/SwitchDelegate.qml index 717ee250..f96a67ac 100644 --- a/src/imports/controls/material/SwitchDelegate.qml +++ b/src/imports/controls/material/SwitchDelegate.qml @@ -35,9 +35,11 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Material 2.2 -import QtQuick.Controls.Material.impl 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Material 2.3 +import QtQuick.Controls.Material.impl 2.3 T.SwitchDelegate { id: control @@ -54,23 +56,29 @@ T.SwitchDelegate { bottomPadding: 8 spacing: 16 + icon.width: 24 + icon.height: 24 + icon.color: enabled ? Material.foreground : Material.hintTextColor + indicator: SwitchIndicator { x: text ? (control.mirrored ? control.leftPadding : control.width - width - control.rightPadding) : control.leftPadding + (control.availableWidth - width) / 2 y: control.topPadding + (control.availableHeight - height) / 2 control: control } - contentItem: Text { + contentItem: IconLabel { leftPadding: !control.mirrored ? 0 : control.indicator.width + control.spacing rightPadding: control.mirrored ? 0 : control.indicator.width + control.spacing + spacing: control.spacing + mirrored: control.mirrored + display: control.display + alignment: control.display === IconLabel.IconOnly || control.display === IconLabel.TextUnderIcon ? Qt.AlignCenter : Qt.AlignLeft + + icon: control.icon text: control.text font: control.font color: control.enabled ? control.Material.foreground : control.Material.hintTextColor - elide: Text.ElideRight - visible: control.text - horizontalAlignment: Text.AlignLeft - verticalAlignment: Text.AlignVCenter } background: Rectangle { diff --git a/src/imports/controls/material/SwitchIndicator.qml b/src/imports/controls/material/SwitchIndicator.qml index 0ac7aee3..5a1cf868 100644 --- a/src/imports/controls/material/SwitchIndicator.qml +++ b/src/imports/controls/material/SwitchIndicator.qml @@ -35,8 +35,8 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Controls.Material 2.2 -import QtQuick.Controls.Material.impl 2.2 +import QtQuick.Controls.Material 2.3 +import QtQuick.Controls.Material.impl 2.3 Item { id: indicator diff --git a/src/imports/controls/material/TabBar.qml b/src/imports/controls/material/TabBar.qml index db076447..dcdda818 100644 --- a/src/imports/controls/material/TabBar.qml +++ b/src/imports/controls/material/TabBar.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Material 2.2 -import QtQuick.Controls.Material.impl 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls.Material 2.3 +import QtQuick.Controls.Material.impl 2.3 T.TabBar { id: control @@ -48,7 +48,6 @@ T.TabBar { contentHeight + topPadding + bottomPadding) spacing: 1 - contentHeight: 48 contentItem: ListView { model: control.contentModel diff --git a/src/imports/controls/material/TabButton.qml b/src/imports/controls/material/TabButton.qml index d83fc441..96546d3f 100644 --- a/src/imports/controls/material/TabButton.qml +++ b/src/imports/controls/material/TabButton.qml @@ -35,9 +35,11 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Material 2.2 -import QtQuick.Controls.Material.impl 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Material 2.3 +import QtQuick.Controls.Material.impl 2.3 T.TabButton { id: control @@ -49,14 +51,21 @@ T.TabButton { baselineOffset: contentItem.y + contentItem.baselineOffset padding: 12 + spacing: 6 - contentItem: Text { + icon.width: 24 + icon.height: 24 + icon.color: !enabled ? Material.hintTextColor : down || checked ? Material.accentColor : Material.foreground + + contentItem: IconLabel { + spacing: control.spacing + mirrored: control.mirrored + display: control.display + + icon: control.icon text: control.text font: control.font - elide: Text.ElideRight color: !control.enabled ? control.Material.hintTextColor : control.down || control.checked ? control.Material.accentColor : control.Material.foreground - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter } background: Ripple { diff --git a/src/imports/controls/material/TextArea.qml b/src/imports/controls/material/TextArea.qml index 34c633b6..989341e9 100644 --- a/src/imports/controls/material/TextArea.qml +++ b/src/imports/controls/material/TextArea.qml @@ -35,11 +35,11 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls 2.2 -import QtQuick.Controls.impl 2.2 -import QtQuick.Controls.Material 2.2 -import QtQuick.Controls.Material.impl 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Material 2.3 +import QtQuick.Controls.Material.impl 2.3 T.TextArea { id: control diff --git a/src/imports/controls/material/TextField.qml b/src/imports/controls/material/TextField.qml index f5c77f86..9f18afef 100644 --- a/src/imports/controls/material/TextField.qml +++ b/src/imports/controls/material/TextField.qml @@ -35,11 +35,11 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls 2.2 -import QtQuick.Controls.impl 2.2 -import QtQuick.Controls.Material 2.2 -import QtQuick.Controls.Material.impl 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Material 2.3 +import QtQuick.Controls.Material.impl 2.3 T.TextField { id: control diff --git a/src/imports/controls/material/ToolBar.qml b/src/imports/controls/material/ToolBar.qml index 228a2692..c8c1b6b6 100644 --- a/src/imports/controls/material/ToolBar.qml +++ b/src/imports/controls/material/ToolBar.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Material 2.2 -import QtQuick.Controls.Material.impl 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls.Material 2.3 +import QtQuick.Controls.Material.impl 2.3 T.ToolBar { id: control diff --git a/src/imports/controls/material/ToolButton.qml b/src/imports/controls/material/ToolButton.qml index eaff0b1c..158aea1b 100644 --- a/src/imports/controls/material/ToolButton.qml +++ b/src/imports/controls/material/ToolButton.qml @@ -35,9 +35,11 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Material 2.2 -import QtQuick.Controls.Material.impl 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Material 2.3 +import QtQuick.Controls.Material.impl 2.3 T.ToolButton { id: control @@ -49,15 +51,22 @@ T.ToolButton { baselineOffset: contentItem.y + contentItem.baselineOffset padding: 6 + spacing: 6 - contentItem: Text { + icon.width: 24 + icon.height: 24 + icon.color: !enabled ? Material.hintTextColor : checked || highlighted ? Material.accent : Material.foreground + + contentItem: IconLabel { + spacing: control.spacing + mirrored: control.mirrored + display: control.display + + icon: control.icon text: control.text font: control.font color: !control.enabled ? control.Material.hintTextColor : control.checked || control.highlighted ? control.Material.accent : control.Material.foreground - elide: Text.ElideRight - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter } background: Ripple { diff --git a/src/imports/controls/material/ToolSeparator.qml b/src/imports/controls/material/ToolSeparator.qml index 808ddf4f..f8a5d9bb 100644 --- a/src/imports/controls/material/ToolSeparator.qml +++ b/src/imports/controls/material/ToolSeparator.qml @@ -35,8 +35,8 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Material 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls.Material 2.3 T.ToolSeparator { id: control diff --git a/src/imports/controls/material/ToolTip.qml b/src/imports/controls/material/ToolTip.qml index a1c2b0ef..13a35701 100644 --- a/src/imports/controls/material/ToolTip.qml +++ b/src/imports/controls/material/ToolTip.qml @@ -35,8 +35,8 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Material 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls.Material 2.3 T.ToolTip { id: control diff --git a/src/imports/controls/material/Tumbler.qml b/src/imports/controls/material/Tumbler.qml index 9b1309ab..a0334488 100644 --- a/src/imports/controls/material/Tumbler.qml +++ b/src/imports/controls/material/Tumbler.qml @@ -35,10 +35,10 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Controls 2.2 -import QtQuick.Controls.impl 2.2 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Material 2.2 +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls.Material 2.3 T.Tumbler { id: control diff --git a/src/imports/controls/material/material.pro b/src/imports/controls/material/material.pro index b7610cd9..5d036b61 100644 --- a/src/imports/controls/material/material.pro +++ b/src/imports/controls/material/material.pro @@ -1,6 +1,6 @@ TARGET = qtquickcontrols2materialstyleplugin TARGETPATH = QtQuick/Controls.2/Material -IMPORT_VERSION = 2.2 +IMPORT_VERSION = 2.3 QT += qml quick QT_PRIVATE += core-private gui-private qml-private quick-private quicktemplates2-private quickcontrols2-private diff --git a/src/imports/controls/material/qmldir b/src/imports/controls/material/qmldir index 839ca3af..a5bae170 100644 --- a/src/imports/controls/material/qmldir +++ b/src/imports/controls/material/qmldir @@ -1,4 +1,4 @@ module QtQuick.Controls.Material plugin qtquickcontrols2materialstyleplugin classname QtQuickControls2MaterialStylePlugin -depends QtQuick.Controls 2.2 +depends QtQuick.Controls 2.3 diff --git a/src/imports/controls/material/qquickmaterialstyle.cpp b/src/imports/controls/material/qquickmaterialstyle.cpp index eeadb5f3..08d88ec7 100644 --- a/src/imports/controls/material/qquickmaterialstyle.cpp +++ b/src/imports/controls/material/qquickmaterialstyle.cpp @@ -39,7 +39,7 @@ #include <QtCore/qdebug.h> #include <QtCore/qsettings.h> #include <QtQml/qqmlinfo.h> -#include <QtQuickControls2/private/qquickstyleattached_p.h> +#include <QtQuickControls2/private/qquickstyle_p.h> QT_BEGIN_NAMESPACE @@ -419,16 +419,14 @@ static const QRgb rippleColorDark = 0x20FFFFFF; static const QRgb spinBoxDisabledIconColorLight = 0xFFCCCCCC; static const QRgb spinBoxDisabledIconColorDark = 0xFF666666; -extern bool qt_is_dark_system_theme(); - static QQuickMaterialStyle::Theme effectiveTheme(QQuickMaterialStyle::Theme theme) { if (theme == QQuickMaterialStyle::System) - theme = qt_is_dark_system_theme() ? QQuickMaterialStyle::Dark : QQuickMaterialStyle::Light; + theme = QQuickStylePrivate::isDarkSystemTheme() ? QQuickMaterialStyle::Dark : QQuickMaterialStyle::Light; return theme; } -QQuickMaterialStyle::QQuickMaterialStyle(QObject *parent) : QQuickStyleAttached(parent), +QQuickMaterialStyle::QQuickMaterialStyle(QObject *parent) : QQuickAttachedObject(parent), m_explicitTheme(false), m_explicitPrimary(false), m_explicitAccent(false), @@ -463,7 +461,7 @@ QQuickMaterialStyle::Theme QQuickMaterialStyle::theme() const void QQuickMaterialStyle::setTheme(Theme theme) { if (theme == System) - theme = qt_is_dark_system_theme() ? Dark : Light; + theme = QQuickStylePrivate::isDarkSystemTheme() ? Dark : Light; m_explicitTheme = true; if (m_theme == theme) @@ -500,8 +498,8 @@ void QQuickMaterialStyle::inheritTheme(Theme theme) void QQuickMaterialStyle::propagateTheme() { - const auto styles = childStyles(); - for (QQuickStyleAttached *child : styles) { + const auto styles = attachedChildren(); + for (QQuickAttachedObject *child : styles) { QQuickMaterialStyle *material = qobject_cast<QQuickMaterialStyle *>(child); if (material) material->inheritTheme(m_theme); @@ -514,7 +512,7 @@ void QQuickMaterialStyle::resetTheme() return; m_explicitTheme = false; - QQuickMaterialStyle *material = qobject_cast<QQuickMaterialStyle *>(parentStyle()); + QQuickMaterialStyle *material = qobject_cast<QQuickMaterialStyle *>(attachedParent()); inheritTheme(material ? material->theme() : globalTheme); } @@ -555,8 +553,8 @@ void QQuickMaterialStyle::inheritPrimary(uint primary, bool custom) void QQuickMaterialStyle::propagatePrimary() { - const auto styles = childStyles(); - for (QQuickStyleAttached *child : styles) { + const auto styles = attachedChildren(); + for (QQuickAttachedObject *child : styles) { QQuickMaterialStyle *material = qobject_cast<QQuickMaterialStyle *>(child); if (material) material->inheritPrimary(m_primary, m_customPrimary); @@ -570,7 +568,7 @@ void QQuickMaterialStyle::resetPrimary() m_customPrimary = false; m_explicitPrimary = false; - QQuickMaterialStyle *material = qobject_cast<QQuickMaterialStyle *>(parentStyle()); + QQuickMaterialStyle *material = qobject_cast<QQuickMaterialStyle *>(attachedParent()); if (material) inheritPrimary(material->m_primary, material->m_customPrimary); else @@ -614,8 +612,8 @@ void QQuickMaterialStyle::inheritAccent(uint accent, bool custom) void QQuickMaterialStyle::propagateAccent() { - const auto styles = childStyles(); - for (QQuickStyleAttached *child : styles) { + const auto styles = attachedChildren(); + for (QQuickAttachedObject *child : styles) { QQuickMaterialStyle *material = qobject_cast<QQuickMaterialStyle *>(child); if (material) material->inheritAccent(m_accent, m_customAccent); @@ -629,7 +627,7 @@ void QQuickMaterialStyle::resetAccent() m_customAccent = false; m_explicitAccent = false; - QQuickMaterialStyle *material = qobject_cast<QQuickMaterialStyle *>(parentStyle()); + QQuickMaterialStyle *material = qobject_cast<QQuickMaterialStyle *>(attachedParent()); if (material) inheritAccent(material->m_accent, material->m_customAccent); else @@ -679,8 +677,8 @@ void QQuickMaterialStyle::inheritForeground(uint foreground, bool custom, bool h void QQuickMaterialStyle::propagateForeground() { - const auto styles = childStyles(); - for (QQuickStyleAttached *child : styles) { + const auto styles = attachedChildren(); + for (QQuickAttachedObject *child : styles) { QQuickMaterialStyle *material = qobject_cast<QQuickMaterialStyle *>(child); if (material) material->inheritForeground(m_foreground, m_customForeground, m_hasForeground); @@ -695,7 +693,7 @@ void QQuickMaterialStyle::resetForeground() m_hasForeground = false; m_customForeground = false; m_explicitForeground = false; - QQuickMaterialStyle *material = qobject_cast<QQuickMaterialStyle *>(parentStyle()); + QQuickMaterialStyle *material = qobject_cast<QQuickMaterialStyle *>(attachedParent()); inheritForeground(material ? material->m_foreground : globalForeground, true, material ? material->m_hasForeground : false); } @@ -738,8 +736,8 @@ void QQuickMaterialStyle::inheritBackground(uint background, bool custom, bool h void QQuickMaterialStyle::propagateBackground() { - const auto styles = childStyles(); - for (QQuickStyleAttached *child : styles) { + const auto styles = attachedChildren(); + for (QQuickAttachedObject *child : styles) { QQuickMaterialStyle *material = qobject_cast<QQuickMaterialStyle *>(child); if (material) material->inheritBackground(m_background, m_customBackground, m_hasBackground); @@ -754,7 +752,7 @@ void QQuickMaterialStyle::resetBackground() m_hasBackground = false; m_customBackground = false; m_explicitBackground = false; - QQuickMaterialStyle *material = qobject_cast<QQuickMaterialStyle *>(parentStyle()); + QQuickMaterialStyle *material = qobject_cast<QQuickMaterialStyle *>(attachedParent()); inheritBackground(material ? material->m_background : globalBackground, true, material ? material->m_hasBackground : false); } @@ -1137,7 +1135,7 @@ QColor QQuickMaterialStyle::shade(const QColor &color, Shade shade) const } } -void QQuickMaterialStyle::parentStyleChange(QQuickStyleAttached *newParent, QQuickStyleAttached *oldParent) +void QQuickMaterialStyle::attachedParentChange(QQuickAttachedObject *newParent, QQuickAttachedObject *oldParent) { Q_UNUSED(oldParent); QQuickMaterialStyle *material = qobject_cast<QQuickMaterialStyle *>(newParent); @@ -1171,7 +1169,7 @@ void QQuickMaterialStyle::init() { static bool globalsInitialized = false; if (!globalsInitialized) { - QSharedPointer<QSettings> settings = QQuickStyleAttached::settings(QStringLiteral("Material")); + QSharedPointer<QSettings> settings = QQuickStylePrivate::settings(QStringLiteral("Material")); bool ok = false; QByteArray themeValue = resolveSetting("QT_QUICK_CONTROLS_MATERIAL_THEME", settings, QStringLiteral("Theme")); @@ -1248,7 +1246,7 @@ void QQuickMaterialStyle::init() globalsInitialized = true; } - QQuickStyleAttached::init(); // TODO: lazy init? + QQuickAttachedObject::init(); // TODO: lazy init? } bool QQuickMaterialStyle::variantToRgba(const QVariant &var, const char *name, QRgb *rgba, bool *custom) const diff --git a/src/imports/controls/material/qquickmaterialstyle_p.h b/src/imports/controls/material/qquickmaterialstyle_p.h index bb494697..2374eefb 100644 --- a/src/imports/controls/material/qquickmaterialstyle_p.h +++ b/src/imports/controls/material/qquickmaterialstyle_p.h @@ -49,11 +49,11 @@ // #include <QtGui/qcolor.h> -#include <QtQuickControls2/private/qquickstyleattached_p.h> +#include <QtQuickControls2/private/qquickattachedobject_p.h> QT_BEGIN_NAMESPACE -class QQuickMaterialStyle : public QQuickStyleAttached +class QQuickMaterialStyle : public QQuickAttachedObject { Q_OBJECT Q_PROPERTY(Theme theme READ theme WRITE setTheme RESET resetTheme NOTIFY themeChanged FINAL) @@ -236,7 +236,7 @@ Q_SIGNALS: void paletteChanged(); protected: - void parentStyleChange(QQuickStyleAttached *newParent, QQuickStyleAttached *oldParent) override; + void attachedParentChange(QQuickAttachedObject *newParent, QQuickAttachedObject *oldParent) override; private: void init(); diff --git a/src/imports/controls/material/qquickmaterialtheme.cpp b/src/imports/controls/material/qquickmaterialtheme.cpp index 3ea41779..7ef2f0e7 100644 --- a/src/imports/controls/material/qquickmaterialtheme.cpp +++ b/src/imports/controls/material/qquickmaterialtheme.cpp @@ -42,8 +42,8 @@ QT_BEGIN_NAMESPACE -QQuickMaterialTheme::QQuickMaterialTheme(QPlatformTheme *theme) - : QQuickProxyTheme(theme) +QQuickMaterialTheme::QQuickMaterialTheme() + : QQuickTheme(QStringLiteral("Material")) { QFont font; font.setFamily(QLatin1String("Roboto")); @@ -65,22 +65,29 @@ QQuickMaterialTheme::QQuickMaterialTheme(QPlatformTheme *theme) } systemFont.setPixelSize(14); + systemFont = resolveFont(systemFont); buttonFont.setPixelSize(14); buttonFont.setCapitalization(QFont::AllUppercase); buttonFont.setWeight(QFont::Medium); + buttonFont = resolveFont(buttonFont); toolTipFont.setPixelSize(14); toolTipFont.setWeight(QFont::Medium); + toolTipFont = resolveFont(toolTipFont); itemViewFont.setPixelSize(14); itemViewFont.setWeight(QFont::Medium); + itemViewFont = resolveFont(itemViewFont); listViewFont.setPixelSize(16); + listViewFont = resolveFont(listViewFont); menuItemFont.setPixelSize(16); + menuItemFont = resolveFont(menuItemFont); editorFont.setPixelSize(16); + editorFont = resolveFont(editorFont); } const QFont *QQuickMaterialTheme::font(QPlatformTheme::Font type) const @@ -110,14 +117,7 @@ QVariant QQuickMaterialTheme::themeHint(ThemeHint hint) const { switch (hint) { case QPlatformTheme::DialogButtonBoxLayout: - // https://material.io/guidelines/components/dialogs.html#dialogs-specs - // As per spec, affirmative actions are placed to the right, dismissive - // actions are placed directly to the left of affirmative actions. - // In the Android sources, there are additional type of actions - - // neutral, which are placed to the left. - // Rules for macOS seems to be the most suitable here and are also used - // in the Android QPA plugin. - return QVariant(QPlatformDialogHelper::MacLayout); + return QVariant(QPlatformDialogHelper::AndroidLayout); default: return QQuickProxyTheme::themeHint(hint); } diff --git a/src/imports/controls/material/qquickmaterialtheme_p.h b/src/imports/controls/material/qquickmaterialtheme_p.h index d505d4ff..0e791386 100644 --- a/src/imports/controls/material/qquickmaterialtheme_p.h +++ b/src/imports/controls/material/qquickmaterialtheme_p.h @@ -50,14 +50,14 @@ #include <QtCore/qvariant.h> #include <QtGui/qfont.h> -#include <QtQuickControls2/private/qquickproxytheme_p.h> +#include <QtQuickControls2/private/qquicktheme_p.h> QT_BEGIN_NAMESPACE -class QQuickMaterialTheme : public QQuickProxyTheme +class QQuickMaterialTheme : public QQuickTheme { public: - explicit QQuickMaterialTheme(QPlatformTheme *theme = nullptr); + explicit QQuickMaterialTheme(); const QFont *font(Font type = SystemFont) const override; diff --git a/src/imports/controls/material/qtquickcontrols2materialstyleplugin.cpp b/src/imports/controls/material/qtquickcontrols2materialstyleplugin.cpp index 3f3a66b0..7eae0826 100644 --- a/src/imports/controls/material/qtquickcontrols2materialstyleplugin.cpp +++ b/src/imports/controls/material/qtquickcontrols2materialstyleplugin.cpp @@ -44,7 +44,6 @@ #include <QtQuickControls2/private/qquickstyleselector_p.h> #include <QtQuickControls2/private/qquickpaddedrectangle_p.h> -#include <QtQuickControls2/private/qquickcolorimageprovider_p.h> static inline void initResources() { @@ -86,12 +85,9 @@ void QtQuickControls2MaterialStylePlugin::initializeEngine(QQmlEngine *engine, c { QQuickStylePlugin::initializeEngine(engine, uri); - engine->addImageProvider(name(), new QQuickColorImageProvider(QStringLiteral(":/qt-project.org/imports/QtQuick/Controls.2/Material/images"))); - QByteArray import = QByteArray(uri) + ".impl"; qmlRegisterModule(import, 2, QT_VERSION_MINOR - 7); // Qt 5.7->2.0, 5.8->2.1, 5.9->2.2... - qmlRegisterType<QQuickPaddedRectangle>(import, 2, 0, "PaddedRectangle"); qmlRegisterType<QQuickMaterialBusyIndicator>(import, 2, 0, "BusyIndicatorImpl"); qmlRegisterType<QQuickMaterialProgressBar>(import, 2, 0, "ProgressBarImpl"); qmlRegisterType<QQuickMaterialRipple>(import, 2, 0, "Ripple"); diff --git a/src/imports/controls/plugins.qmltypes b/src/imports/controls/plugins.qmltypes index 1e1b9d0f..bc73734e 100644 --- a/src/imports/controls/plugins.qmltypes +++ b/src/imports/controls/plugins.qmltypes @@ -4,20 +4,53 @@ import QtQuick.tooling 1.2 // It is used for QML tooling purposes only. // // This file was auto-generated by: -// 'qmlplugindump -nonrelocatable QtQuick.Controls 2.2 -merge ../templates/plugins.qmltypes -dependencies dependencies.json' +// 'qmlplugindump -nonrelocatable QtQuick.Controls 2.3 -merge ../templates/plugins.qmltypes -dependencies dependencies.json' Module { dependencies: [ "QtQuick 2.9", - "QtQuick.Templates 2.2", + "QtQuick.Templates 2.3", "QtQuick.Window 2.2" ] Component { + name: "QQuickColor" + prototype: "QObject" + exports: ["QtQuick.Controls.impl/Color 2.3"] + isCreatable: false + isSingleton: true + exportMetaObjectRevisions: [0] + Method { + name: "transparent" + type: "QColor" + Parameter { name: "color"; type: "QColor" } + Parameter { name: "opacity"; type: "double" } + } + } + Component { + name: "QQuickColorImage" + defaultProperty: "data" + prototype: "QQuickImage" + exports: ["QtQuick.Controls.impl/ColorImage 2.3"] + exportMetaObjectRevisions: [0] + Property { name: "color"; type: "QColor" } + } + Component { name: "QQuickDefaultBusyIndicator" defaultProperty: "data" prototype: "QQuickItem" exports: ["QtQuick.Controls.impl/BusyIndicatorImpl 2.0"] exportMetaObjectRevisions: [0] + Property { name: "pen"; type: "QColor" } + Property { name: "fill"; type: "QColor" } + } + Component { + name: "QQuickDefaultDial" + defaultProperty: "data" + prototype: "QQuickPaintedItem" + exports: ["QtQuick.Controls.impl/DialImpl 2.0"] + exportMetaObjectRevisions: [0] + Property { name: "progress"; type: "double" } + Property { name: "color"; type: "QColor" } } Component { name: "QQuickDefaultProgressBar" @@ -27,6 +60,7 @@ Module { exportMetaObjectRevisions: [0] Property { name: "indeterminate"; type: "bool" } Property { name: "progress"; type: "double" } + Property { name: "color"; type: "QColor" } } Component { name: "QQuickDefaultStyle" @@ -76,13 +110,53 @@ Module { Property { name: "disabledLightColor"; type: "QColor"; isReadonly: true } } Component { - name: "QQuickDialRing" + name: "QQuickIconImage" defaultProperty: "data" - prototype: "QQuickPaintedItem" - exports: ["QtQuick.Controls.impl/DialRing 2.0"] + prototype: "QQuickImage" + exports: ["QtQuick.Controls.impl/IconImage 2.3"] exportMetaObjectRevisions: [0] - Property { name: "progress"; type: "double" } + Property { name: "name"; type: "string" } + Property { name: "color"; type: "QColor" } + } + Component { + name: "QQuickIconLabel" + defaultProperty: "data" + prototype: "QQuickItem" + exports: ["QtQuick.Controls.impl/IconLabel 2.3"] + exportMetaObjectRevisions: [0] + Enum { + name: "Display" + values: { + "IconOnly": 0, + "TextOnly": 1, + "TextBesideIcon": 2, + "TextUnderIcon": 3 + } + } + Property { name: "icon"; type: "QQuickIcon" } + Property { name: "text"; type: "string" } + Property { name: "font"; type: "QFont" } Property { name: "color"; type: "QColor" } + Property { name: "display"; type: "Display" } + Property { name: "spacing"; type: "double" } + Property { name: "mirrored"; type: "bool" } + Property { name: "alignment"; type: "Qt::Alignment" } + Property { name: "topPadding"; type: "double" } + Property { name: "leftPadding"; type: "double" } + Property { name: "rightPadding"; type: "double" } + Property { name: "bottomPadding"; type: "double" } + } + Component { + name: "QQuickPaddedRectangle" + defaultProperty: "data" + prototype: "QQuickRectangle" + exports: ["QtQuick.Controls.impl/PaddedRectangle 2.3"] + exportMetaObjectRevisions: [0] + 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" } } Component { name: "QQuickPlaceholderText" @@ -110,6 +184,20 @@ Module { defaultProperty: "data" } Component { + prototype: "QQuickAction" + name: "QtQuick.Controls/Action 2.3" + exports: ["QtQuick.Controls/Action 2.3"] + exportMetaObjectRevisions: [3] + isComposite: true + } + Component { + prototype: "QQuickActionGroup" + name: "QtQuick.Controls/ActionGroup 2.3" + exports: ["QtQuick.Controls/ActionGroup 2.3"] + exportMetaObjectRevisions: [3] + isComposite: true + } + Component { prototype: "QQuickApplicationWindow" name: "QtQuick.Controls/ApplicationWindow 2.0" exports: ["QtQuick.Controls/ApplicationWindow 2.0"] @@ -134,6 +222,13 @@ Module { defaultProperty: "data" } Component { + prototype: "QQuickButtonGroup" + name: "QtQuick.Controls/ButtonGroup 2.0" + exports: ["QtQuick.Controls/ButtonGroup 2.0"] + exportMetaObjectRevisions: [0] + isComposite: true + } + Component { prototype: "QQuickCheckBox" name: "QtQuick.Controls/CheckBox 2.0" exports: ["QtQuick.Controls/CheckBox 2.0"] @@ -527,9 +622,19 @@ Module { prototype: "QQuickControl" exports: [ "QtQuick.Templates/AbstractButton 2.0", - "QtQuick.Templates/AbstractButton 2.2" + "QtQuick.Templates/AbstractButton 2.2", + "QtQuick.Templates/AbstractButton 2.3" ] - exportMetaObjectRevisions: [0, 2] + exportMetaObjectRevisions: [0, 2, 3] + Enum { + name: "Display" + values: { + "IconOnly": 0, + "TextOnly": 1, + "TextBesideIcon": 2, + "TextUnderIcon": 3 + } + } Property { name: "text"; type: "string" } Property { name: "down"; type: "bool" } Property { name: "pressed"; type: "bool"; isReadonly: true } @@ -537,6 +642,9 @@ Module { Property { name: "checkable"; type: "bool" } Property { name: "autoExclusive"; type: "bool" } Property { name: "indicator"; type: "QQuickItem"; isPointer: true } + Property { name: "icon"; revision: 3; type: "QQuickIcon" } + Property { name: "display"; revision: 3; type: "Display" } + Property { name: "action"; revision: 3; type: "QQuickAction"; isPointer: true } Signal { name: "pressed" } Signal { name: "released" } Signal { name: "canceled" } @@ -544,14 +652,104 @@ Module { Signal { name: "toggled"; revision: 2 } Signal { name: "pressAndHold" } Signal { name: "doubleClicked" } + Signal { name: "iconChanged"; revision: 3 } + Signal { name: "displayChanged"; revision: 3 } + Signal { name: "actionChanged"; revision: 3 } Method { name: "toggle" } } Component { + name: "QQuickAction" + prototype: "QObject" + exports: ["QtQuick.Templates/Action 2.3"] + exportMetaObjectRevisions: [0] + Property { name: "text"; type: "string" } + Property { name: "icon"; type: "QQuickIcon" } + Property { name: "enabled"; type: "bool" } + Property { name: "checked"; type: "bool" } + Property { name: "checkable"; type: "bool" } + Property { name: "shortcut"; type: "QVariant" } + Signal { + name: "textChanged" + Parameter { name: "text"; type: "string" } + } + Signal { + name: "iconChanged" + Parameter { name: "icon"; type: "QQuickIcon" } + } + Signal { + name: "enabledChanged" + Parameter { name: "enabled"; type: "bool" } + } + Signal { + name: "checkedChanged" + Parameter { name: "checked"; type: "bool" } + } + Signal { + name: "checkableChanged" + Parameter { name: "checkable"; type: "bool" } + } + Signal { + name: "shortcutChanged" + Parameter { name: "shortcut"; type: "QKeySequence" } + } + Signal { + name: "toggled" + Parameter { name: "source"; type: "QObject"; isPointer: true } + } + Signal { name: "toggled" } + Signal { + name: "triggered" + Parameter { name: "source"; type: "QObject"; isPointer: true } + } + Signal { name: "triggered" } + Method { + name: "toggle" + Parameter { name: "source"; type: "QObject"; isPointer: true } + } + Method { name: "toggle" } + Method { + name: "trigger" + Parameter { name: "source"; type: "QObject"; isPointer: true } + } + Method { name: "trigger" } + } + Component { + name: "QQuickActionGroup" + prototype: "QObject" + exports: ["QtQuick.Templates/ActionGroup 2.3"] + exportMetaObjectRevisions: [0] + attachedType: "QQuickActionGroupAttached" + Property { name: "checkedAction"; type: "QQuickAction"; isPointer: true } + Property { name: "actions"; type: "QQuickAction"; isList: true; isReadonly: true } + Property { name: "exclusive"; type: "bool" } + Property { name: "enabled"; type: "bool" } + Signal { + name: "triggered" + Parameter { name: "action"; type: "QQuickAction"; isPointer: true } + } + Method { + name: "addAction" + Parameter { name: "action"; type: "QQuickAction"; isPointer: true } + } + Method { + name: "removeAction" + Parameter { name: "action"; type: "QQuickAction"; isPointer: true } + } + } + Component { + name: "QQuickActionGroupAttached" + prototype: "QObject" + Property { name: "group"; type: "QQuickActionGroup"; isPointer: true } + } + Component { name: "QQuickApplicationWindow" defaultProperty: "contentData" prototype: "QQuickWindowQmlImpl" - exports: ["QtQuick.Templates/ApplicationWindow 2.0"] - exportMetaObjectRevisions: [0] + exports: [ + "QtQuick.Templates/ApplicationWindow 2.0", + "QtQuick.Templates/ApplicationWindow 2.3" + ] + exportMetaObjectRevisions: [0, 3] attachedType: "QQuickApplicationWindowAttached" Property { name: "background"; type: "QQuickItem"; isPointer: true } Property { name: "contentItem"; type: "QQuickItem"; isReadonly: true; isPointer: true } @@ -562,6 +760,8 @@ Module { Property { name: "overlay"; type: "QQuickOverlay"; isReadonly: true; isPointer: true } Property { name: "font"; type: "QFont" } Property { name: "locale"; type: "QLocale" } + Property { name: "palette"; revision: 3; type: "QPalette" } + Signal { name: "paletteChanged"; revision: 3 } } Component { name: "QQuickApplicationWindowAttached" @@ -596,12 +796,15 @@ Module { prototype: "QObject" exports: [ "QtQuick.Templates/ButtonGroup 2.0", - "QtQuick.Templates/ButtonGroup 2.1" + "QtQuick.Templates/ButtonGroup 2.1", + "QtQuick.Templates/ButtonGroup 2.3" ] - exportMetaObjectRevisions: [0, 1] + exportMetaObjectRevisions: [0, 1, 3] attachedType: "QQuickButtonGroupAttached" Property { name: "checkedButton"; type: "QQuickAbstractButton"; isPointer: true } Property { name: "buttons"; type: "QQuickAbstractButton"; isList: true; isReadonly: true } + Property { name: "exclusive"; revision: 3; type: "bool" } + Signal { name: "exclusiveChanged"; revision: 3 } Signal { name: "clicked" revision: 1 @@ -712,9 +915,10 @@ Module { prototype: "QQuickControl" exports: [ "QtQuick.Templates/Container 2.0", - "QtQuick.Templates/Container 2.1" + "QtQuick.Templates/Container 2.1", + "QtQuick.Templates/Container 2.3" ] - exportMetaObjectRevisions: [0, 1] + exportMetaObjectRevisions: [0, 1, 3] Property { name: "count"; type: "int"; isReadonly: true } Property { name: "contentModel"; type: "QVariant"; isReadonly: true } Property { name: "contentData"; type: "QObject"; isList: true; isReadonly: true } @@ -748,6 +952,12 @@ Module { } Method { name: "removeItem" + Parameter { name: "item"; type: "QVariant" } + } + Method { + name: "takeItem" + revision: 3 + type: "QQuickItem*" Parameter { name: "index"; type: "int" } } } @@ -755,8 +965,11 @@ Module { name: "QQuickControl" defaultProperty: "data" prototype: "QQuickItem" - exports: ["QtQuick.Templates/Control 2.0"] - exportMetaObjectRevisions: [0] + exports: [ + "QtQuick.Templates/Control 2.0", + "QtQuick.Templates/Control 2.3" + ] + exportMetaObjectRevisions: [0, 3] Property { name: "font"; type: "QFont" } Property { name: "availableWidth"; type: "double"; isReadonly: true } Property { name: "availableHeight"; type: "double"; isReadonly: true } @@ -776,6 +989,8 @@ Module { Property { name: "wheelEnabled"; type: "bool" } Property { name: "background"; type: "QQuickItem"; isPointer: true } Property { name: "contentItem"; type: "QQuickItem"; isPointer: true } + Property { name: "palette"; revision: 3; type: "QPalette" } + Signal { name: "paletteChanged"; revision: 3 } } Component { name: "QQuickDelayButton" @@ -822,23 +1037,52 @@ Module { name: "QQuickDialog" defaultProperty: "contentData" prototype: "QQuickPopup" - exports: ["QtQuick.Templates/Dialog 2.1"] - exportMetaObjectRevisions: [0] + exports: [ + "QtQuick.Templates/Dialog 2.1", + "QtQuick.Templates/Dialog 2.3" + ] + exportMetaObjectRevisions: [0, 3] + Enum { + name: "StandardCode" + values: { + "Rejected": 0, + "Accepted": 1 + } + } Property { name: "title"; type: "string" } Property { name: "header"; type: "QQuickItem"; isPointer: true } Property { name: "footer"; type: "QQuickItem"; isPointer: true } Property { name: "standardButtons"; type: "QPlatformDialogHelper::StandardButtons" } + Property { name: "result"; revision: 3; type: "int" } Signal { name: "accepted" } Signal { name: "rejected" } + Signal { name: "applied"; revision: 3 } + Signal { name: "reset"; revision: 3 } + Signal { name: "discarded"; revision: 3 } + Signal { name: "helpRequested"; revision: 3 } + Signal { name: "resultChanged"; revision: 3 } Method { name: "accept" } Method { name: "reject" } + Method { + name: "done" + Parameter { name: "result"; type: "int" } + } + Method { + name: "standardButton" + revision: 3 + type: "QQuickAbstractButton*" + Parameter { name: "button"; type: "QPlatformDialogHelper::StandardButton" } + } } Component { name: "QQuickDialogButtonBox" defaultProperty: "contentData" prototype: "QQuickContainer" - exports: ["QtQuick.Templates/DialogButtonBox 2.1"] - exportMetaObjectRevisions: [0] + exports: [ + "QtQuick.Templates/DialogButtonBox 2.1", + "QtQuick.Templates/DialogButtonBox 2.3" + ] + exportMetaObjectRevisions: [0, 0] attachedType: "QQuickDialogButtonBoxAttached" Enum { name: "Position" @@ -854,6 +1098,9 @@ Module { Signal { name: "accepted" } Signal { name: "rejected" } Signal { name: "helpRequested" } + Signal { name: "applied"; revision: 3 } + Signal { name: "reset"; revision: 3 } + Signal { name: "discarded"; revision: 3 } Signal { name: "clicked" Parameter { name: "button"; type: "QQuickAbstractButton"; isPointer: true } @@ -917,16 +1164,20 @@ Module { exportMetaObjectRevisions: [0] Property { name: "font"; type: "QFont" } Property { name: "background"; type: "QQuickItem"; isPointer: true } + Property { name: "palette"; revision: 3; type: "QPalette" } + Signal { name: "paletteChanged"; revision: 3 } } Component { name: "QQuickMenu" defaultProperty: "contentData" prototype: "QQuickPopup" - exports: ["QtQuick.Templates/Menu 2.0"] - exportMetaObjectRevisions: [0] + exports: ["QtQuick.Templates/Menu 2.0", "QtQuick.Templates/Menu 2.3"] + exportMetaObjectRevisions: [0, 3] Property { name: "contentModel"; type: "QVariant"; isReadonly: true } Property { name: "contentData"; type: "QObject"; isList: true; isReadonly: true } Property { name: "title"; type: "string" } + Property { name: "delegate"; revision: 3; type: "QQmlComponent"; isPointer: true } + Signal { name: "delegateChanged"; revision: 3 } Method { name: "itemAt" type: "QQuickItem*" @@ -948,17 +1199,33 @@ Module { } Method { name: "removeItem" + Parameter { name: "item"; type: "QVariant" } + } + Method { + name: "takeItem" + revision: 3 + type: "QQuickItem*" Parameter { name: "index"; type: "int" } } + Method { + name: "popup" + revision: 3 + Parameter { name: "args"; type: "QQmlV4Function"; isPointer: true } + } } Component { name: "QQuickMenuItem" defaultProperty: "data" prototype: "QQuickAbstractButton" - exports: ["QtQuick.Templates/MenuItem 2.0"] - exportMetaObjectRevisions: [0] + exports: [ + "QtQuick.Templates/MenuItem 2.0", + "QtQuick.Templates/MenuItem 2.3" + ] + exportMetaObjectRevisions: [0, 3] Property { name: "highlighted"; type: "bool" } + Property { name: "menu"; revision: 3; type: "QQuickMenu"; isReadonly: true; isPointer: true } Signal { name: "triggered" } + Signal { name: "menuChanged"; revision: 3 } } Component { name: "QQuickMenuSeparator" @@ -1020,9 +1287,10 @@ Module { prototype: "QObject" exports: [ "QtQuick.Templates/Popup 2.0", - "QtQuick.Templates/Popup 2.1" + "QtQuick.Templates/Popup 2.1", + "QtQuick.Templates/Popup 2.3" ] - exportMetaObjectRevisions: [0, 1] + exportMetaObjectRevisions: [0, 1, 3] Enum { name: "ClosePolicy" values: { @@ -1072,6 +1340,7 @@ Module { Property { name: "bottomPadding"; type: "double" } Property { name: "locale"; type: "QLocale" } Property { name: "font"; type: "QFont" } + Property { name: "palette"; revision: 3; type: "QPalette" } Property { name: "parent"; type: "QQuickItem"; isPointer: true } Property { name: "background"; type: "QQuickItem"; isPointer: true } Property { name: "contentItem"; type: "QQuickItem"; isPointer: true } @@ -1083,6 +1352,7 @@ Module { Property { name: "modal"; type: "bool" } Property { name: "dim"; type: "bool" } Property { name: "visible"; type: "bool" } + Property { name: "opened"; revision: 3; type: "bool"; isReadonly: true } Property { name: "opacity"; type: "double" } Property { name: "scale"; type: "double" } Property { name: "closePolicy"; type: "ClosePolicy" } @@ -1090,6 +1360,8 @@ Module { Property { name: "enter"; type: "QQuickTransition"; isPointer: true } Property { name: "exit"; type: "QQuickTransition"; isPointer: true } Signal { name: "spacingChanged"; revision: 1 } + Signal { name: "paletteChanged"; revision: 3 } + Signal { name: "openedChanged"; revision: 3 } Signal { name: "windowChanged" Parameter { name: "window"; type: "QQuickWindow"; isPointer: true } @@ -1140,9 +1412,10 @@ Module { exports: [ "QtQuick.Templates/RangeSlider 2.0", "QtQuick.Templates/RangeSlider 2.1", - "QtQuick.Templates/RangeSlider 2.2" + "QtQuick.Templates/RangeSlider 2.2", + "QtQuick.Templates/RangeSlider 2.3" ] - exportMetaObjectRevisions: [0, 1, 2] + exportMetaObjectRevisions: [0, 1, 2, 3] Enum { name: "SnapMode" values: { @@ -1158,6 +1431,8 @@ Module { Property { name: "stepSize"; type: "double" } Property { name: "snapMode"; type: "SnapMode" } Property { name: "orientation"; type: "Qt::Orientation" } + Property { name: "horizontal"; revision: 3; type: "bool"; isReadonly: true } + Property { name: "vertical"; revision: 3; type: "bool"; isReadonly: true } Property { name: "live"; revision: 2; type: "bool" } Signal { name: "liveChanged"; revision: 2 } Method { @@ -1193,9 +1468,10 @@ Module { prototype: "QQuickControl" exports: [ "QtQuick.Templates/ScrollBar 2.0", - "QtQuick.Templates/ScrollBar 2.2" + "QtQuick.Templates/ScrollBar 2.2", + "QtQuick.Templates/ScrollBar 2.3" ] - exportMetaObjectRevisions: [0, 2] + exportMetaObjectRevisions: [0, 2, 3] attachedType: "QQuickScrollBarAttached" Enum { name: "SnapMode" @@ -1222,6 +1498,8 @@ Module { Property { name: "snapMode"; revision: 2; type: "SnapMode" } Property { name: "interactive"; revision: 2; type: "bool" } Property { name: "policy"; revision: 2; type: "Policy" } + Property { name: "horizontal"; revision: 3; type: "bool"; isReadonly: true } + Property { name: "vertical"; revision: 3; type: "bool"; isReadonly: true } Signal { name: "snapModeChanged"; revision: 2 } Signal { name: "interactiveChanged"; revision: 2 } Signal { name: "policyChanged"; revision: 2 } @@ -1246,13 +1524,18 @@ Module { name: "QQuickScrollIndicator" defaultProperty: "data" prototype: "QQuickControl" - exports: ["QtQuick.Templates/ScrollIndicator 2.0"] - exportMetaObjectRevisions: [0] + exports: [ + "QtQuick.Templates/ScrollIndicator 2.0", + "QtQuick.Templates/ScrollIndicator 2.3" + ] + exportMetaObjectRevisions: [0, 3] attachedType: "QQuickScrollIndicatorAttached" Property { name: "size"; type: "double" } Property { name: "position"; type: "double" } Property { name: "active"; type: "bool" } Property { name: "orientation"; type: "Qt::Orientation" } + Property { name: "horizontal"; revision: 3; type: "bool"; isReadonly: true } + Property { name: "vertical"; revision: 3; type: "bool"; isReadonly: true } Method { name: "setSize" Parameter { name: "size"; type: "double" } @@ -1286,9 +1569,10 @@ Module { exports: [ "QtQuick.Templates/Slider 2.0", "QtQuick.Templates/Slider 2.1", - "QtQuick.Templates/Slider 2.2" + "QtQuick.Templates/Slider 2.2", + "QtQuick.Templates/Slider 2.3" ] - exportMetaObjectRevisions: [0, 1, 2] + exportMetaObjectRevisions: [0, 1, 2, 3] Enum { name: "SnapMode" values: { @@ -1306,6 +1590,8 @@ Module { Property { name: "snapMode"; type: "SnapMode" } Property { name: "live"; revision: 2; type: "bool" } Property { name: "pressed"; type: "bool" } + Property { name: "horizontal"; revision: 3; type: "bool"; isReadonly: true } + Property { name: "vertical"; revision: 3; type: "bool"; isReadonly: true } Property { name: "orientation"; type: "Qt::Orientation" } Property { name: "handle"; type: "QQuickItem"; isPointer: true } Signal { name: "liveChanged"; revision: 2 } @@ -1326,9 +1612,10 @@ Module { exports: [ "QtQuick.Templates/SpinBox 2.0", "QtQuick.Templates/SpinBox 2.1", - "QtQuick.Templates/SpinBox 2.2" + "QtQuick.Templates/SpinBox 2.2", + "QtQuick.Templates/SpinBox 2.3" ] - exportMetaObjectRevisions: [0, 1, 2] + exportMetaObjectRevisions: [0, 1, 2, 3] Property { name: "from"; type: "int" } Property { name: "to"; type: "int" } Property { name: "value"; type: "int" } @@ -1341,9 +1628,11 @@ Module { Property { name: "down"; type: "QQuickSpinButton"; isReadonly: true; isPointer: true } Property { name: "inputMethodHints"; revision: 2; type: "Qt::InputMethodHints" } Property { name: "inputMethodComposing"; revision: 2; type: "bool"; isReadonly: true } + Property { name: "wrap"; revision: 3; type: "bool" } Signal { name: "valueModified"; revision: 2 } Signal { name: "inputMethodHintsChanged"; revision: 2 } Signal { name: "inputMethodComposingChanged"; revision: 2 } + Signal { name: "wrapChanged"; revision: 3 } Method { name: "increase" } Method { name: "decrease" } } @@ -1401,6 +1690,12 @@ Module { Property { name: "pushExit"; type: "QQuickTransition"; isPointer: true } Property { name: "replaceEnter"; type: "QQuickTransition"; isPointer: true } Property { name: "replaceExit"; type: "QQuickTransition"; isPointer: true } + Property { name: "empty"; revision: 3; type: "bool"; isReadonly: true } + Signal { name: "emptyChanged"; revision: 3 } + Method { + name: "clear" + Parameter { name: "operation"; type: "Operation" } + } Method { name: "clear" } Method { name: "get" @@ -1512,6 +1807,8 @@ Module { attachedType: "QQuickSwipeViewAttached" Property { name: "interactive"; revision: 1; type: "bool" } Property { name: "orientation"; revision: 2; type: "Qt::Orientation" } + Property { name: "horizontal"; revision: 3; type: "bool"; isReadonly: true } + Property { name: "vertical"; revision: 3; type: "bool"; isReadonly: true } Signal { name: "interactiveChanged"; revision: 1 } Signal { name: "orientationChanged"; revision: 2 } } @@ -1551,6 +1848,7 @@ Module { "QtQuick.Templates/TabBar 2.2" ] exportMetaObjectRevisions: [0, 2] + attachedType: "QQuickTabBarAttached" Enum { name: "Position" values: { @@ -1565,6 +1863,13 @@ Module { Signal { name: "contentHeightChanged"; revision: 2 } } Component { + name: "QQuickTabBarAttached" + prototype: "QObject" + Property { name: "index"; type: "int"; isReadonly: true } + Property { name: "tabBar"; type: "QQuickTabBar"; isReadonly: true; isPointer: true } + Property { name: "position"; type: "QQuickTabBar::Position"; isReadonly: true } + } + Component { name: "QQuickTabButton" defaultProperty: "data" prototype: "QQuickAbstractButton" @@ -1589,6 +1894,7 @@ Module { Property { name: "focusReason"; type: "Qt::FocusReason" } Property { name: "hovered"; revision: 1; type: "bool"; isReadonly: true } Property { name: "hoverEnabled"; revision: 1; type: "bool" } + Property { name: "palette"; revision: 3; type: "QPalette" } Signal { name: "implicitWidthChanged3" } Signal { name: "implicitHeightChanged3" } Signal { name: "hoveredChanged"; revision: 1 } @@ -1607,6 +1913,7 @@ Module { revision: 1 Parameter { name: "event"; type: "QQuickMouseEvent"; isPointer: true } } + Signal { name: "paletteChanged"; revision: 3 } } Component { name: "QQuickTextAreaAttached" @@ -1630,6 +1937,7 @@ Module { Property { name: "focusReason"; type: "Qt::FocusReason" } Property { name: "hovered"; revision: 1; type: "bool"; isReadonly: true } Property { name: "hoverEnabled"; revision: 1; type: "bool" } + Property { name: "palette"; revision: 3; type: "QPalette" } Signal { name: "implicitWidthChanged3" } Signal { name: "implicitHeightChanged3" } Signal { name: "hoveredChanged"; revision: 1 } @@ -1648,6 +1956,7 @@ Module { revision: 1 Parameter { name: "event"; type: "QQuickMouseEvent"; isPointer: true } } + Signal { name: "paletteChanged"; revision: 3 } } Component { name: "QQuickToolBar" diff --git a/src/imports/controls/qmldir b/src/imports/controls/qmldir index 32f0d20d..9930b8d8 100644 --- a/src/imports/controls/qmldir +++ b/src/imports/controls/qmldir @@ -1,5 +1,5 @@ module QtQuick.Controls plugin qtquickcontrols2plugin classname QtQuickControls2Plugin -depends QtQuick.Templates 2.2 +depends QtQuick.Templates 2.3 designersupported diff --git a/src/imports/controls/qquickdefaultbusyindicator.cpp b/src/imports/controls/qquickdefaultbusyindicator.cpp index 315b2b8b..138e94e8 100644 --- a/src/imports/controls/qquickdefaultbusyindicator.cpp +++ b/src/imports/controls/qquickdefaultbusyindicator.cpp @@ -45,7 +45,6 @@ QT_BEGIN_NAMESPACE static const int CircleCount = 10; static const int TotalDuration = 100 * CircleCount * 2; static const QRgb TransparentColor = 0x00000000; -static const QRgb FillColor = 0xFF353637; static QPointF moveCircle(const QPointF &pos, qreal rotation, qreal distance) { @@ -59,6 +58,10 @@ public: void updateCurrentTime(int time) override; void sync(QQuickItem *item) override; + +private: + QColor m_pen; + QColor m_fill; }; QQuickDefaultBusyIndicatorNode::QQuickDefaultBusyIndicatorNode(QQuickDefaultBusyIndicator *item) @@ -92,8 +95,9 @@ void QQuickDefaultBusyIndicatorNode::updateCurrentTime(int time) Q_ASSERT(rectNode->type() == QSGNode::GeometryNodeType); const bool fill = (firstPhaseProgress > qreal(i) / CircleCount) || (secondPhaseProgress > 0 && secondPhaseProgress < qreal(i) / CircleCount); - rectNode->setColor(QColor::fromRgba(fill ? FillColor : TransparentColor)); - rectNode->setPenWidth(fill ? 0 : 1); + rectNode->setColor(fill ? m_fill : QColor::fromRgba(TransparentColor)); + rectNode->setPenColor(m_pen); + rectNode->setPenWidth(1); rectNode->update(); transformNode = static_cast<QSGTransformNode*>(transformNode->nextSibling()); @@ -109,6 +113,9 @@ void QQuickDefaultBusyIndicatorNode::sync(QQuickItem *item) const qreal dy = (h - sz) / 2; const int circleRadius = sz / 12; + m_pen = static_cast<QQuickDefaultBusyIndicator *>(item)->pen(); + m_fill = static_cast<QQuickDefaultBusyIndicator *>(item)->fill(); + QSGTransformNode *transformNode = static_cast<QSGTransformNode *>(firstChild()); for (int i = 0; i < CircleCount; ++i) { Q_ASSERT(transformNode->type() == QSGNode::TransformNodeType); @@ -136,6 +143,34 @@ QQuickDefaultBusyIndicator::QQuickDefaultBusyIndicator(QQuickItem *parent) : setFlag(ItemHasContents); } +QColor QQuickDefaultBusyIndicator::pen() const +{ + return m_pen; +} + +void QQuickDefaultBusyIndicator::setPen(const QColor &pen) +{ + if (pen == m_pen) + return; + + m_pen = pen; + update(); +} + +QColor QQuickDefaultBusyIndicator::fill() const +{ + return m_fill; +} + +void QQuickDefaultBusyIndicator::setFill(const QColor &fill) +{ + if (fill == m_fill) + return; + + m_fill = fill; + update(); +} + int QQuickDefaultBusyIndicator::elapsed() const { return m_elapsed; diff --git a/src/imports/controls/qquickdefaultbusyindicator_p.h b/src/imports/controls/qquickdefaultbusyindicator_p.h index 7daeabd1..e214020c 100644 --- a/src/imports/controls/qquickdefaultbusyindicator_p.h +++ b/src/imports/controls/qquickdefaultbusyindicator_p.h @@ -55,10 +55,18 @@ QT_BEGIN_NAMESPACE class QQuickDefaultBusyIndicator : public QQuickItem { Q_OBJECT + Q_PROPERTY(QColor pen READ pen WRITE setPen FINAL) + Q_PROPERTY(QColor fill READ fill WRITE setFill FINAL) public: explicit QQuickDefaultBusyIndicator(QQuickItem *parent = nullptr); + QColor pen() const; + void setPen(const QColor &pen); + + QColor fill() const; + void setFill(const QColor &fill); + int elapsed() const; protected: @@ -67,6 +75,8 @@ protected: private: int m_elapsed; + QColor m_pen; + QColor m_fill; }; QT_END_NAMESPACE diff --git a/src/imports/controls/qquickdialring.cpp b/src/imports/controls/qquickdefaultdial.cpp index 2c6e7921..845e634d 100644 --- a/src/imports/controls/qquickdialring.cpp +++ b/src/imports/controls/qquickdefaultdial.cpp @@ -34,7 +34,7 @@ ** ****************************************************************************/ -#include "qquickdialring_p.h" +#include "qquickdefaultdial_p.h" #include <QtCore/qmath.h> #include <QtGui/qpainter.h> @@ -42,44 +42,42 @@ QT_BEGIN_NAMESPACE -QQuickDialRing::QQuickDialRing(QQuickItem *parent) : +QQuickDefaultDial::QQuickDefaultDial(QQuickItem *parent) : QQuickPaintedItem(parent), m_progress(0), m_color(Qt::black) { } -qreal QQuickDialRing::progress() const +qreal QQuickDefaultDial::progress() const { return m_progress; } -void QQuickDialRing::setProgress(qreal progress) +void QQuickDefaultDial::setProgress(qreal progress) { if (progress == m_progress) return; m_progress = progress; update(); - emit progressChanged(); } -QColor QQuickDialRing::color() const +QColor QQuickDefaultDial::color() const { return m_color; } -void QQuickDialRing::setColor(const QColor &color) +void QQuickDefaultDial::setColor(const QColor &color) { if (color == m_color) return; m_color = color; update(); - emit colorChanged(); } -void QQuickDialRing::paint(QPainter *painter) +void QQuickDefaultDial::paint(QPainter *painter) { if (width() <= 0 || height() <= 0) return; diff --git a/src/imports/controls/qquickdialring_p.h b/src/imports/controls/qquickdefaultdial_p.h index 5b2f49ba..10490610 100644 --- a/src/imports/controls/qquickdialring_p.h +++ b/src/imports/controls/qquickdefaultdial_p.h @@ -34,8 +34,8 @@ ** ****************************************************************************/ -#ifndef QQUICKDIALRING_P_H -#define QQUICKDIALRING_P_H +#ifndef QQUICKDEFAULTDIAL_P_H +#define QQUICKDEFAULTDIAL_P_H // // W A R N I N G @@ -53,14 +53,14 @@ QT_BEGIN_NAMESPACE -class QQuickDialRing : public QQuickPaintedItem +class QQuickDefaultDial : public QQuickPaintedItem { Q_OBJECT - Q_PROPERTY(qreal progress READ progress WRITE setProgress NOTIFY progressChanged) - Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged) + Q_PROPERTY(qreal progress READ progress WRITE setProgress FINAL) + Q_PROPERTY(QColor color READ color WRITE setColor FINAL) public: - QQuickDialRing(QQuickItem *parent = nullptr); + explicit QQuickDefaultDial(QQuickItem *parent = nullptr); qreal progress() const; void setProgress(qreal progress); @@ -70,10 +70,6 @@ public: void paint(QPainter *painter) override; -Q_SIGNALS: - void progressChanged(); - void colorChanged(); - private: qreal m_progress; QColor m_color; @@ -81,4 +77,4 @@ private: QT_END_NAMESPACE -#endif // QQUICKDIALRING_P_H +#endif // QQUICKDEFAULTDIAL_P_H diff --git a/src/imports/controls/qquickdefaultprogressbar.cpp b/src/imports/controls/qquickdefaultprogressbar.cpp index a34b6a28..f5bd1db8 100644 --- a/src/imports/controls/qquickdefaultprogressbar.cpp +++ b/src/imports/controls/qquickdefaultprogressbar.cpp @@ -51,7 +51,6 @@ static const int BlockSpan = Blocks * (BlockWidth + BlockRestingSpacing) - Block static const int TotalDuration = 4000; static const int SecondPhaseStart = TotalDuration * 0.4; static const int ThirdPhaseStart = TotalDuration * 0.6; -static const QRgb FillColor = 0x353637; static inline qreal blockStartX(int blockIndex) { @@ -178,7 +177,7 @@ void QQuickDefaultProgressBarNode::sync(QQuickItem *item) QSGInternalRectangleNode *rectNode = static_cast<QSGInternalRectangleNode*>(transformNode->firstChild()); if (!rectNode) { rectNode = d->sceneGraphContext()->createInternalRectangleNode(); - rectNode->setColor(FillColor); + rectNode->setColor(bar->color()); transformNode->appendChildNode(rectNode); } @@ -200,7 +199,7 @@ void QQuickDefaultProgressBarNode::sync(QQuickItem *item) QSGInternalRectangleNode *rectNode = static_cast<QSGInternalRectangleNode *>(firstChild()); if (!rectNode) { rectNode = d->sceneGraphContext()->createInternalRectangleNode(); - rectNode->setColor(FillColor); + rectNode->setColor(bar->color()); appendChildNode(rectNode); } @@ -229,7 +228,6 @@ void QQuickDefaultProgressBar::setProgress(qreal progress) m_progress = progress; update(); - emit progressChanged(); } bool QQuickDefaultProgressBar::isIndeterminate() const @@ -245,7 +243,20 @@ void QQuickDefaultProgressBar::setIndeterminate(bool indeterminate) m_indeterminate = indeterminate; setClip(m_indeterminate); update(); - emit indeterminateChanged(); +} + +QColor QQuickDefaultProgressBar::color() const +{ + return m_color; +} + +void QQuickDefaultProgressBar::setColor(const QColor &color) +{ + if (color == m_color) + return; + + m_color = color; + update(); } void QQuickDefaultProgressBar::itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &data) diff --git a/src/imports/controls/qquickdefaultprogressbar_p.h b/src/imports/controls/qquickdefaultprogressbar_p.h index 4fb9ae0b..dbdf5ad4 100644 --- a/src/imports/controls/qquickdefaultprogressbar_p.h +++ b/src/imports/controls/qquickdefaultprogressbar_p.h @@ -55,8 +55,9 @@ QT_BEGIN_NAMESPACE class QQuickDefaultProgressBar : public QQuickItem { Q_OBJECT - Q_PROPERTY(bool indeterminate READ isIndeterminate WRITE setIndeterminate NOTIFY indeterminateChanged FINAL) - Q_PROPERTY(qreal progress READ progress WRITE setProgress NOTIFY progressChanged FINAL) + Q_PROPERTY(bool indeterminate READ isIndeterminate WRITE setIndeterminate FINAL) + Q_PROPERTY(qreal progress READ progress WRITE setProgress FINAL) + Q_PROPERTY(QColor color READ color WRITE setColor FINAL) public: explicit QQuickDefaultProgressBar(QQuickItem *parent = nullptr); @@ -67,9 +68,8 @@ public: qreal progress() const; void setProgress(qreal progress); -Q_SIGNALS: - void progressChanged(); - void indeterminateChanged(); + QColor color() const; + void setColor(const QColor &color); protected: void itemChange(ItemChange change, const ItemChangeData &data) override; @@ -78,6 +78,7 @@ protected: private: qreal m_progress; bool m_indeterminate; + QColor m_color; }; QT_END_NAMESPACE diff --git a/src/imports/controls/qquickdefaulttheme.cpp b/src/imports/controls/qquickdefaulttheme.cpp new file mode 100644 index 00000000..f9cdcddc --- /dev/null +++ b/src/imports/controls/qquickdefaulttheme.cpp @@ -0,0 +1,46 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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 "qquickdefaulttheme_p.h" + +QT_BEGIN_NAMESPACE + +QQuickDefaultTheme::QQuickDefaultTheme() + : QQuickTheme(QStringLiteral("Default")) +{ +} + +QT_END_NAMESPACE diff --git a/src/imports/controls/qquickdefaulttheme_p.h b/src/imports/controls/qquickdefaulttheme_p.h new file mode 100644 index 00000000..e0811dcb --- /dev/null +++ b/src/imports/controls/qquickdefaulttheme_p.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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 QQUICKDEFAULTTHEME_P_H +#define QQUICKDEFAULTTHEME_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 <QtQuickControls2/private/qquicktheme_p.h> + +QT_BEGIN_NAMESPACE + +class QQuickDefaultTheme : public QQuickTheme +{ +public: + explicit QQuickDefaultTheme(); +}; + +QT_END_NAMESPACE + +#endif // QQUICKDEFAULTTHEME_P_H diff --git a/src/imports/controls/qtquickcontrols2plugin.cpp b/src/imports/controls/qtquickcontrols2plugin.cpp index 848f55b5..a7bf096f 100644 --- a/src/imports/controls/qtquickcontrols2plugin.cpp +++ b/src/imports/controls/qtquickcontrols2plugin.cpp @@ -36,20 +36,24 @@ #include <QtCore/private/qfileselector_p.h> #include <QtQuickControls2/qquickstyle.h> +#include <QtQuickControls2/private/qquickcolor_p.h> +#include <QtQuickControls2/private/qquickcolorimage_p.h> +#include <QtQuickControls2/private/qquickiconimage_p.h> +#include <QtQuickControls2/private/qquickpaddedrectangle_p.h> #include <QtQuickControls2/private/qquickplaceholdertext_p.h> +#include <QtQuickControls2/private/qquickiconlabel_p.h> #include <QtQuickControls2/private/qquickstyle_p.h> #include <QtQuickControls2/private/qquickstyleplugin_p.h> #include <QtQuickControls2/private/qquickstyleselector_p.h> -#include <QtQuickControls2/private/qquickcolorimageprovider_p.h> #if QT_CONFIG(quick_listview) && QT_CONFIG(quick_pathview) #include <QtQuickControls2/private/qquicktumblerview_p.h> #endif -#include <QtQuickTemplates2/private/qquickbuttongroup_p.h> #include "qquickdefaultbusyindicator_p.h" +#include "qquickdefaultdial_p.h" #include "qquickdefaultprogressbar_p.h" #include "qquickdefaultstyle_p.h" -#include "qquickdialring_p.h" +#include "qquickdefaulttheme_p.h" static inline void initResources() { @@ -68,8 +72,11 @@ class QtQuickControls2Plugin: public QQuickStylePlugin public: QtQuickControls2Plugin(QObject *parent = nullptr); - void registerTypes(const char *uri); - void initializeEngine(QQmlEngine *engine, const char *uri); + void registerTypes(const char *uri) override; + void initializeEngine(QQmlEngine *engine, const char *uri) override; + + QString name() const override; + QQuickProxyTheme *createTheme() const override; }; QtQuickControls2Plugin::QtQuickControls2Plugin(QObject *parent) : QQuickStylePlugin(parent) @@ -94,8 +101,7 @@ void QtQuickControls2Plugin::registerTypes(const char *uri) qmlRegisterType(selector.select(QStringLiteral("ApplicationWindow.qml")), uri, 2, 0, "ApplicationWindow"); qmlRegisterType(selector.select(QStringLiteral("BusyIndicator.qml")), uri, 2, 0, "BusyIndicator"); qmlRegisterType(selector.select(QStringLiteral("Button.qml")), uri, 2, 0, "Button"); - qmlRegisterType<QQuickButtonGroup>(uri, 2, 0, "ButtonGroup"); - qmlRegisterType<QQuickButtonGroupAttached>(); + qmlRegisterType(selector.select(QStringLiteral("ButtonGroup.qml")), uri, 2, 0, "ButtonGroup"); qmlRegisterType(selector.select(QStringLiteral("CheckBox.qml")), uri, 2, 0, "CheckBox"); qmlRegisterType(selector.select(QStringLiteral("CheckDelegate.qml")), uri, 2, 0, "CheckDelegate"); qmlRegisterType(selector.select(QStringLiteral("ComboBox.qml")), uri, 2, 0, "ComboBox"); @@ -138,7 +144,6 @@ void QtQuickControls2Plugin::registerTypes(const char *uri) #endif // QtQuick.Controls 2.1 (new types in Qt 5.8) - qmlRegisterType<QQuickButtonGroup,1 >(uri, 2, 1, "ButtonGroup"); qmlRegisterType(selector.select(QStringLiteral("Dialog.qml")), uri, 2, 1, "Dialog"); qmlRegisterType(selector.select(QStringLiteral("DialogButtonBox.qml")), uri, 2, 1, "DialogButtonBox"); qmlRegisterType(selector.select(QStringLiteral("MenuSeparator.qml")), uri, 2, 1, "MenuSeparator"); @@ -148,6 +153,10 @@ void QtQuickControls2Plugin::registerTypes(const char *uri) // QtQuick.Controls 2.2 (new types in Qt 5.9) qmlRegisterType(selector.select(QStringLiteral("DelayButton.qml")), uri, 2, 2, "DelayButton"); qmlRegisterType(selector.select(QStringLiteral("ScrollView.qml")), uri, 2, 2, "ScrollView"); + + // QtQuick.Controls 2.3 (new types in Qt 5.10) + qmlRegisterType(selector.select(QStringLiteral("Action.qml")), uri, 2, 3, "Action"); + qmlRegisterType(selector.select(QStringLiteral("ActionGroup.qml")), uri, 2, 3, "ActionGroup"); } static QObject *styleSingleton(QQmlEngine *engine, QJSEngine *scriptEngine) @@ -157,18 +166,23 @@ static QObject *styleSingleton(QQmlEngine *engine, QJSEngine *scriptEngine) return new QQuickDefaultStyle; } -void QtQuickControls2Plugin::initializeEngine(QQmlEngine *engine, const char *uri) +static QObject *colorSingleton(QQmlEngine *engine, QJSEngine *scriptEngine) { - Q_UNUSED(uri); + Q_UNUSED(engine); + Q_UNUSED(scriptEngine); + return new QQuickColor; +} - engine->addImageProvider(QStringLiteral("default"), new QQuickColorImageProvider(QStringLiteral(":/qt-project.org/imports/QtQuick/Controls.2/images"))); +void QtQuickControls2Plugin::initializeEngine(QQmlEngine *engine, const char *uri) +{ + QQuickStylePlugin::initializeEngine(engine, uri); const QByteArray import = QByteArray(uri) + ".impl"; qmlRegisterModule(import, 2, QT_VERSION_MINOR - 7); // Qt 5.7->2.0, 5.8->2.1, 5.9->2.2... qmlRegisterType<QQuickDefaultBusyIndicator>(import, 2, 0, "BusyIndicatorImpl"); + qmlRegisterType<QQuickDefaultDial>(import, 2, 0, "DialImpl"); qmlRegisterType<QQuickDefaultProgressBar>(import, 2, 0, "ProgressBarImpl"); - qmlRegisterType<QQuickDialRing>(import, 2, 0, "DialRing"); qmlRegisterType<QQuickPlaceholderText>(import, 2, 2, "PlaceholderText"); #if QT_CONFIG(quick_listview) && QT_CONFIG(quick_pathview) qmlRegisterType<QQuickTumblerView>(import, 2, 1, "TumblerView"); @@ -177,6 +191,22 @@ void QtQuickControls2Plugin::initializeEngine(QQmlEngine *engine, const char *ur qmlRegisterType(typeUrl(QStringLiteral("CheckIndicator.qml")), import, 2, 0, "CheckIndicator"); qmlRegisterType(typeUrl(QStringLiteral("RadioIndicator.qml")), import, 2, 0, "RadioIndicator"); qmlRegisterType(typeUrl(QStringLiteral("SwitchIndicator.qml")), import, 2, 0, "SwitchIndicator"); + + qmlRegisterType<QQuickColorImage>(import, 2, 3, "ColorImage"); + qmlRegisterType<QQuickIconImage>(import, 2, 3, "IconImage"); + qmlRegisterSingletonType<QQuickColor>(import, 2, 3, "Color", colorSingleton); + qmlRegisterType<QQuickIconLabel>(import, 2, 3, "IconLabel"); + qmlRegisterType<QQuickPaddedRectangle>(import, 2, 3, "PaddedRectangle"); +} + +QString QtQuickControls2Plugin::name() const +{ + return QStringLiteral("default"); +} + +QQuickProxyTheme *QtQuickControls2Plugin::createTheme() const +{ + return new QQuickDefaultTheme; } QT_END_NAMESPACE diff --git a/src/imports/controls/universal/ApplicationWindow.qml b/src/imports/controls/universal/ApplicationWindow.qml index 3f3926de..c9bd4cec 100644 --- a/src/imports/controls/universal/ApplicationWindow.qml +++ b/src/imports/controls/universal/ApplicationWindow.qml @@ -36,9 +36,9 @@ import QtQuick 2.9 import QtQuick.Window 2.3 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Universal 2.2 -import QtQuick.Controls.Universal.impl 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls.Universal 2.3 +import QtQuick.Controls.Universal.impl 2.3 T.ApplicationWindow { id: window diff --git a/src/imports/controls/universal/BusyIndicator.qml b/src/imports/controls/universal/BusyIndicator.qml index 8f0574fe..ae7977d1 100644 --- a/src/imports/controls/universal/BusyIndicator.qml +++ b/src/imports/controls/universal/BusyIndicator.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Universal 2.2 -import QtQuick.Controls.Universal.impl 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls.Universal 2.3 +import QtQuick.Controls.Universal.impl 2.3 T.BusyIndicator { id: control diff --git a/src/imports/controls/universal/Button.qml b/src/imports/controls/universal/Button.qml index 0bf3621b..27d8aa78 100644 --- a/src/imports/controls/universal/Button.qml +++ b/src/imports/controls/universal/Button.qml @@ -35,8 +35,10 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Universal 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Universal 2.3 T.Button { id: control @@ -50,18 +52,23 @@ T.Button { padding: 8 topPadding: padding - 4 bottomPadding: padding - 4 + spacing: 8 + + icon.width: 20 + icon.height: 20 + icon.color: Color.transparent(Universal.foreground, enabled ? 1.0 : 0.2) property bool useSystemFocusVisuals: true - contentItem: Text { + contentItem: IconLabel { + spacing: control.spacing + mirrored: control.mirrored + display: control.display + + icon: control.icon text: control.text font: control.font - elide: Text.ElideRight - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - - opacity: enabled ? 1.0 : 0.2 - color: control.Universal.foreground + color: Color.transparent(control.Universal.foreground, enabled ? 1.0 : 0.2) } background: Rectangle { diff --git a/src/imports/controls/universal/CheckBox.qml b/src/imports/controls/universal/CheckBox.qml index 8f4b248d..5557ab59 100644 --- a/src/imports/controls/universal/CheckBox.qml +++ b/src/imports/controls/universal/CheckBox.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Universal 2.2 -import QtQuick.Controls.Universal.impl 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls.Universal 2.3 +import QtQuick.Controls.Universal.impl 2.3 T.CheckBox { id: control diff --git a/src/imports/controls/universal/CheckDelegate.qml b/src/imports/controls/universal/CheckDelegate.qml index d3d8690e..72edd60f 100644 --- a/src/imports/controls/universal/CheckDelegate.qml +++ b/src/imports/controls/universal/CheckDelegate.qml @@ -35,9 +35,11 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Universal 2.2 -import QtQuick.Controls.Universal.impl 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Universal 2.3 +import QtQuick.Controls.Universal.impl 2.3 T.CheckDelegate { id: control @@ -55,25 +57,29 @@ T.CheckDelegate { topPadding: padding - 1 bottomPadding: padding + 1 + icon.width: 20 + icon.height: 20 + icon.color: Color.transparent(Universal.foreground, enabled ? 1.0 : 0.2) + indicator: CheckIndicator { x: text ? (control.mirrored ? control.leftPadding : control.width - width - control.rightPadding) : control.leftPadding + (control.availableWidth - width) / 2 y: control.topPadding + (control.availableHeight - height) / 2 control: control } - contentItem: Text { + contentItem: IconLabel { leftPadding: !control.mirrored ? 0 : control.indicator.width + control.spacing rightPadding: control.mirrored ? 0 : control.indicator.width + control.spacing + spacing: control.spacing + mirrored: control.mirrored + display: control.display + alignment: control.display === IconLabel.IconOnly || control.display === IconLabel.TextUnderIcon ? Qt.AlignCenter : Qt.AlignLeft + + icon: control.icon text: control.text font: control.font - elide: Text.ElideRight - visible: control.text - horizontalAlignment: Text.AlignLeft - verticalAlignment: Text.AlignVCenter - - opacity: enabled ? 1.0 : 0.2 - color: control.Universal.foreground + color: Color.transparent(control.Universal.foreground, enabled ? 1.0 : 0.2) } background: Rectangle { diff --git a/src/imports/controls/universal/CheckIndicator.qml b/src/imports/controls/universal/CheckIndicator.qml index eac150e2..e9288bf9 100644 --- a/src/imports/controls/universal/CheckIndicator.qml +++ b/src/imports/controls/universal/CheckIndicator.qml @@ -35,8 +35,10 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Universal 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Universal 2.3 Rectangle { implicitWidth: 20 @@ -53,14 +55,13 @@ Rectangle { property Item control readonly property bool partiallyChecked: control.checkState === Qt.PartiallyChecked - Image { + ColorImage { x: (parent.width - width) / 2 y: (parent.height - height) / 2 visible: control.checkState === Qt.Checked - source: "image://universal/checkmark/" + (!control.enabled ? control.Universal.baseLowColor : control.Universal.chromeWhiteColor) - sourceSize.width: width - sourceSize.height: height + color: !control.enabled ? control.Universal.baseLowColor : control.Universal.chromeWhiteColor + source: "qrc:/qt-project.org/imports/QtQuick/Controls.2/Universal/images/checkmark.png" } Rectangle { diff --git a/src/imports/controls/universal/ComboBox.qml b/src/imports/controls/universal/ComboBox.qml index a2ba0236..1888f8d4 100644 --- a/src/imports/controls/universal/ComboBox.qml +++ b/src/imports/controls/universal/ComboBox.qml @@ -36,9 +36,10 @@ import QtQuick 2.9 import QtQuick.Window 2.3 -import QtQuick.Controls 2.2 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Universal 2.2 +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls.Universal 2.3 T.ComboBox { id: control @@ -62,12 +63,11 @@ T.ComboBox { hoverEnabled: control.hoverEnabled } - indicator: Image { + indicator: ColorImage { x: control.mirrored ? control.padding : control.width - width - control.padding y: control.topPadding + (control.availableHeight - height) / 2 - source: "image://universal/downarrow/" + (!control.enabled ? control.Universal.baseLowColor : control.Universal.baseMediumHighColor) - sourceSize.width: width - sourceSize.height: height + color: !control.enabled ? control.Universal.baseLowColor : control.Universal.baseMediumHighColor + source: "qrc:/qt-project.org/imports/QtQuick/Controls.2/Universal/images/downarrow.png" Rectangle { z: -1 @@ -145,7 +145,6 @@ T.ComboBox { implicitHeight: contentHeight model: control.popup.visible ? control.delegateModel : null currentIndex: control.highlightedIndex - highlightRangeMode: ListView.ApplyRange highlightMoveDuration: 0 T.ScrollIndicator.vertical: ScrollIndicator { } diff --git a/src/imports/controls/universal/DelayButton.qml b/src/imports/controls/universal/DelayButton.qml index 9d43be44..5582348d 100644 --- a/src/imports/controls/universal/DelayButton.qml +++ b/src/imports/controls/universal/DelayButton.qml @@ -35,8 +35,8 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Universal 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls.Universal 2.3 T.DelayButton { id: control diff --git a/src/imports/controls/universal/Dial.qml b/src/imports/controls/universal/Dial.qml index 2ffb4167..fb48a57a 100644 --- a/src/imports/controls/universal/Dial.qml +++ b/src/imports/controls/universal/Dial.qml @@ -35,8 +35,8 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Universal 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls.Universal 2.3 T.Dial { id: control diff --git a/src/imports/controls/universal/Dialog.qml b/src/imports/controls/universal/Dialog.qml index 07ae56a6..4f8a6180 100644 --- a/src/imports/controls/universal/Dialog.qml +++ b/src/imports/controls/universal/Dialog.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls 2.2 -import QtQuick.Controls.Universal 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.Universal 2.3 T.Dialog { id: control diff --git a/src/imports/controls/universal/DialogButtonBox.qml b/src/imports/controls/universal/DialogButtonBox.qml index 4ce41ad6..2049cca0 100644 --- a/src/imports/controls/universal/DialogButtonBox.qml +++ b/src/imports/controls/universal/DialogButtonBox.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls 2.2 -import QtQuick.Controls.Universal 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.Universal 2.3 T.DialogButtonBox { id: control diff --git a/src/imports/controls/universal/Drawer.qml b/src/imports/controls/universal/Drawer.qml index 3543887e..5ef0b325 100644 --- a/src/imports/controls/universal/Drawer.qml +++ b/src/imports/controls/universal/Drawer.qml @@ -35,8 +35,8 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Universal 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls.Universal 2.3 T.Drawer { id: control diff --git a/src/imports/controls/universal/Frame.qml b/src/imports/controls/universal/Frame.qml index 7d7d55a7..45d18a52 100644 --- a/src/imports/controls/universal/Frame.qml +++ b/src/imports/controls/universal/Frame.qml @@ -35,8 +35,8 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Universal 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls.Universal 2.3 T.Frame { id: control diff --git a/src/imports/controls/universal/GroupBox.qml b/src/imports/controls/universal/GroupBox.qml index 420cf22d..14a92c47 100644 --- a/src/imports/controls/universal/GroupBox.qml +++ b/src/imports/controls/universal/GroupBox.qml @@ -35,8 +35,8 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Universal 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls.Universal 2.3 T.GroupBox { id: control diff --git a/src/imports/controls/universal/ItemDelegate.qml b/src/imports/controls/universal/ItemDelegate.qml index 69b2cd9d..5c4c3ba9 100644 --- a/src/imports/controls/universal/ItemDelegate.qml +++ b/src/imports/controls/universal/ItemDelegate.qml @@ -35,8 +35,10 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Universal 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Universal 2.3 T.ItemDelegate { id: control @@ -54,19 +56,20 @@ T.ItemDelegate { topPadding: padding - 1 bottomPadding: padding + 1 - contentItem: Text { - leftPadding: !control.mirrored ? (control.indicator ? control.indicator.width : 0) + control.spacing : 0 - rightPadding: control.mirrored ? (control.indicator ? control.indicator.width : 0) + control.spacing : 0 + icon.width: 20 + icon.height: 20 + icon.color: Color.transparent(Universal.foreground, enabled ? 1.0 : 0.2) + contentItem: IconLabel { + spacing: control.spacing + mirrored: control.mirrored + display: control.display + alignment: control.display === IconLabel.IconOnly || control.display === IconLabel.TextUnderIcon ? Qt.AlignCenter : Qt.AlignLeft + + icon: control.icon text: control.text font: control.font - elide: Text.ElideRight - visible: control.text - horizontalAlignment: Text.AlignLeft - verticalAlignment: Text.AlignVCenter - - opacity: enabled ? 1.0 : 0.2 - color: control.Universal.foreground + color: Color.transparent(control.Universal.foreground, enabled ? 1.0 : 0.2) } background: Rectangle { diff --git a/src/imports/controls/universal/Label.qml b/src/imports/controls/universal/Label.qml index 3cfa9317..99159b79 100644 --- a/src/imports/controls/universal/Label.qml +++ b/src/imports/controls/universal/Label.qml @@ -35,8 +35,8 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Universal 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls.Universal 2.3 T.Label { id: control diff --git a/src/imports/controls/universal/Menu.qml b/src/imports/controls/universal/Menu.qml index 0ca475f5..d7a27563 100644 --- a/src/imports/controls/universal/Menu.qml +++ b/src/imports/controls/universal/Menu.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Controls 2.2 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Universal 2.2 +import QtQuick.Controls 2.3 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls.Universal 2.3 T.Menu { id: control @@ -49,6 +49,8 @@ T.Menu { margins: 0 + delegate: MenuItem { } + contentItem: ListView { implicitHeight: contentHeight model: control.contentModel diff --git a/src/imports/controls/universal/MenuItem.qml b/src/imports/controls/universal/MenuItem.qml index 35e2f2ba..ac3c4e98 100644 --- a/src/imports/controls/universal/MenuItem.qml +++ b/src/imports/controls/universal/MenuItem.qml @@ -35,8 +35,10 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Universal 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Universal 2.3 T.MenuItem { id: control @@ -53,27 +55,32 @@ T.MenuItem { bottomPadding: padding + 1 spacing: 12 - contentItem: Text { - leftPadding: !control.mirrored ? control.indicator.width + control.spacing : 0 - rightPadding: control.mirrored ? control.indicator.width + control.spacing : 0 + icon.width: 20 + icon.height: 20 + icon.color: !enabled ? Universal.baseLowColor : Universal.baseHighColor + contentItem: IconLabel { + leftPadding: control.checkable && !control.mirrored ? control.indicator.width + control.spacing : 0 + rightPadding: control.checkable && control.mirrored ? control.indicator.width + control.spacing : 0 + + spacing: control.spacing + mirrored: control.mirrored + display: control.display + alignment: Qt.AlignLeft + + icon: control.icon text: control.text font: control.font color: !control.enabled ? control.Universal.baseLowColor : control.Universal.baseHighColor - elide: Text.ElideRight - visible: control.text - horizontalAlignment: Text.AlignLeft - verticalAlignment: Text.AlignVCenter } - indicator: Image { + indicator: ColorImage { x: control.text ? (control.mirrored ? control.width - width - control.rightPadding : control.leftPadding) : control.leftPadding + (control.availableWidth - width) / 2 y: control.topPadding + (control.availableHeight - height) / 2 visible: control.checked - source: !control.checkable ? "" : "image://universal/checkmark/" + (!control.enabled ? control.Universal.baseLowColor : control.down ? control.Universal.baseHighColor : control.Universal.baseMediumHighColor) - sourceSize.width: width - sourceSize.height: height + color: !control.enabled ? control.Universal.baseLowColor : control.down ? control.Universal.baseHighColor : control.Universal.baseMediumHighColor + source: !control.checkable ? "" : "qrc:/qt-project.org/imports/QtQuick/Controls.2/Universal/images/checkmark.png" } background: Rectangle { diff --git a/src/imports/controls/universal/MenuSeparator.qml b/src/imports/controls/universal/MenuSeparator.qml index 18d12528..e73444c8 100644 --- a/src/imports/controls/universal/MenuSeparator.qml +++ b/src/imports/controls/universal/MenuSeparator.qml @@ -35,8 +35,8 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Universal 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls.Universal 2.3 T.MenuSeparator { id: control diff --git a/src/imports/controls/universal/Page.qml b/src/imports/controls/universal/Page.qml index 1f006f16..cf5b0e22 100644 --- a/src/imports/controls/universal/Page.qml +++ b/src/imports/controls/universal/Page.qml @@ -35,8 +35,8 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Universal 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls.Universal 2.3 T.Page { id: control diff --git a/src/imports/controls/universal/PageIndicator.qml b/src/imports/controls/universal/PageIndicator.qml index f6a6baa6..2d65c23e 100644 --- a/src/imports/controls/universal/PageIndicator.qml +++ b/src/imports/controls/universal/PageIndicator.qml @@ -35,8 +35,8 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Universal 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls.Universal 2.3 T.PageIndicator { id: control diff --git a/src/imports/controls/universal/Pane.qml b/src/imports/controls/universal/Pane.qml index 67a66c93..f952b2a9 100644 --- a/src/imports/controls/universal/Pane.qml +++ b/src/imports/controls/universal/Pane.qml @@ -35,8 +35,8 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Universal 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls.Universal 2.3 T.Pane { id: control diff --git a/src/imports/controls/universal/Popup.qml b/src/imports/controls/universal/Popup.qml index 0e42219c..f844d8e1 100644 --- a/src/imports/controls/universal/Popup.qml +++ b/src/imports/controls/universal/Popup.qml @@ -35,8 +35,8 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Universal 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls.Universal 2.3 T.Popup { id: control diff --git a/src/imports/controls/universal/ProgressBar.qml b/src/imports/controls/universal/ProgressBar.qml index 58545d61..e3689fc6 100644 --- a/src/imports/controls/universal/ProgressBar.qml +++ b/src/imports/controls/universal/ProgressBar.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Universal 2.2 -import QtQuick.Controls.Universal.impl 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls.Universal 2.3 +import QtQuick.Controls.Universal.impl 2.3 T.ProgressBar { id: control diff --git a/src/imports/controls/universal/RadioButton.qml b/src/imports/controls/universal/RadioButton.qml index 5d778660..db0209fb 100644 --- a/src/imports/controls/universal/RadioButton.qml +++ b/src/imports/controls/universal/RadioButton.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Universal 2.2 -import QtQuick.Controls.Universal.impl 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls.Universal 2.3 +import QtQuick.Controls.Universal.impl 2.3 T.RadioButton { id: control diff --git a/src/imports/controls/universal/RadioDelegate.qml b/src/imports/controls/universal/RadioDelegate.qml index e8b0216c..924080f6 100644 --- a/src/imports/controls/universal/RadioDelegate.qml +++ b/src/imports/controls/universal/RadioDelegate.qml @@ -35,9 +35,11 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Universal 2.2 -import QtQuick.Controls.Universal.impl 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Universal 2.3 +import QtQuick.Controls.Universal.impl 2.3 T.RadioDelegate { id: control @@ -55,25 +57,29 @@ T.RadioDelegate { topPadding: padding - 1 bottomPadding: padding + 1 + icon.width: 20 + icon.height: 20 + icon.color: Color.transparent(Universal.foreground, enabled ? 1.0 : 0.2) + indicator: RadioIndicator { x: text ? (control.mirrored ? control.leftPadding : control.width - width - control.rightPadding) : control.leftPadding + (control.availableWidth - width) / 2 y: control.topPadding + (control.availableHeight - height) / 2 control: control } - contentItem: Text { + contentItem: IconLabel { leftPadding: !control.mirrored ? 0 : control.indicator.width + control.spacing rightPadding: control.mirrored ? 0 : control.indicator.width + control.spacing + spacing: control.spacing + mirrored: control.mirrored + display: control.display + alignment: control.display === IconLabel.IconOnly || control.display === IconLabel.TextUnderIcon ? Qt.AlignCenter : Qt.AlignLeft + + icon: control.icon text: control.text font: control.font - elide: Text.ElideRight - visible: control.text - horizontalAlignment: Text.AlignLeft - verticalAlignment: Text.AlignVCenter - - opacity: enabled ? 1.0 : 0.2 - color: control.Universal.foreground + color: Color.transparent(control.Universal.foreground, enabled ? 1.0 : 0.2) } background: Rectangle { diff --git a/src/imports/controls/universal/RadioIndicator.qml b/src/imports/controls/universal/RadioIndicator.qml index 220983da..676dcd07 100644 --- a/src/imports/controls/universal/RadioIndicator.qml +++ b/src/imports/controls/universal/RadioIndicator.qml @@ -35,7 +35,7 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Controls.Universal 2.2 +import QtQuick.Controls.Universal 2.3 Rectangle { implicitWidth: 20 diff --git a/src/imports/controls/universal/RangeSlider.qml b/src/imports/controls/universal/RangeSlider.qml index d2cf7a65..6aab392f 100644 --- a/src/imports/controls/universal/RangeSlider.qml +++ b/src/imports/controls/universal/RangeSlider.qml @@ -35,8 +35,8 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Universal 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls.Universal 2.3 T.RangeSlider { id: control @@ -51,13 +51,11 @@ T.RangeSlider { padding: 6 first.handle: Rectangle { - implicitWidth: horizontal ? 8 : 24 - implicitHeight: horizontal ? 24 : 8 + implicitWidth: control.horizontal ? 8 : 24 + implicitHeight: control.horizontal ? 24 : 8 - readonly property bool horizontal: control.orientation === Qt.Horizontal - - x: control.leftPadding + (horizontal ? control.first.visualPosition * (control.availableWidth - width) : (control.availableWidth - width) / 2) - y: control.topPadding + (horizontal ? (control.availableHeight - height) / 2 : control.first.visualPosition * (control.availableHeight - height)) + x: control.leftPadding + (control.horizontal ? control.first.visualPosition * (control.availableWidth - width) : (control.availableWidth - width) / 2) + y: control.topPadding + (control.horizontal ? (control.availableHeight - height) / 2 : control.first.visualPosition * (control.availableHeight - height)) radius: 4 color: control.first.pressed ? control.Universal.chromeHighColor : @@ -66,13 +64,11 @@ T.RangeSlider { } second.handle: Rectangle { - implicitWidth: horizontal ? 8 : 24 - implicitHeight: horizontal ? 24 : 8 - - readonly property bool horizontal: control.orientation === Qt.Horizontal + implicitWidth: control.horizontal ? 8 : 24 + implicitHeight: control.horizontal ? 24 : 8 - x: control.leftPadding + (horizontal ? control.second.visualPosition * (control.availableWidth - width) : (control.availableWidth - width) / 2) - y: control.topPadding + (horizontal ? (control.availableHeight - height) / 2 : control.second.visualPosition * (control.availableHeight - height)) + x: control.leftPadding + (control.horizontal ? control.second.visualPosition * (control.availableWidth - width) : (control.availableWidth - width) / 2) + y: control.topPadding + (control.horizontal ? (control.availableHeight - height) / 2 : control.second.visualPosition * (control.availableHeight - height)) radius: 4 color: control.second.pressed ? control.Universal.chromeHighColor : @@ -81,33 +77,31 @@ T.RangeSlider { } background: Item { - implicitWidth: horizontal ? 200 : 18 - implicitHeight: horizontal ? 18 : 200 - - readonly property bool horizontal: control.orientation === Qt.Horizontal + implicitWidth: control.horizontal ? 200 : 18 + implicitHeight: control.horizontal ? 18 : 200 - x: control.leftPadding + (horizontal ? 0 : (control.availableWidth - width) / 2) - y: control.topPadding + (horizontal ? (control.availableHeight - height) / 2 : 0) - width: horizontal ? control.availableWidth : implicitWidth - height: horizontal ? implicitHeight : control.availableHeight + x: control.leftPadding + (control.horizontal ? 0 : (control.availableWidth - width) / 2) + y: control.topPadding + (control.horizontal ? (control.availableHeight - height) / 2 : 0) + width: control.horizontal ? control.availableWidth : implicitWidth + height: control.horizontal ? implicitHeight : control.availableHeight - scale: horizontal && control.mirrored ? -1 : 1 + scale: control.horizontal && control.mirrored ? -1 : 1 Rectangle { - x: parent.horizontal ? 0 : (parent.width - width) / 2 - y: parent.horizontal ? (parent.height - height) / 2 : 0 - width: parent.horizontal ? parent.width : 2 // SliderBackgroundThemeHeight - height: !parent.horizontal ? parent.height : 2 // SliderBackgroundThemeHeight + x: control.horizontal ? 0 : (parent.width - width) / 2 + y: control.horizontal ? (parent.height - height) / 2 : 0 + width: control.horizontal ? parent.width : 2 // SliderBackgroundThemeHeight + height: control.vertical ? parent.height : 2 // SliderBackgroundThemeHeight color: control.hovered && !control.pressed ? control.Universal.baseMediumColor : control.enabled ? control.Universal.baseMediumLowColor : control.Universal.chromeDisabledHighColor } Rectangle { - x: parent.horizontal ? control.first.position * parent.width : (parent.width - width) / 2 - y: parent.horizontal ? (parent.height - height) / 2 : control.second.visualPosition * parent.height - width: parent.horizontal ? control.second.position * parent.width - control.first.position * parent.width : 2 // SliderBackgroundThemeHeight - height: !parent.horizontal ? control.second.position * parent.height - control.first.position * parent.height : 2 // SliderBackgroundThemeHeight + x: control.horizontal ? control.first.position * parent.width : (parent.width - width) / 2 + y: control.horizontal ? (parent.height - height) / 2 : control.second.visualPosition * parent.height + width: control.horizontal ? control.second.position * parent.width - control.first.position * parent.width : 2 // SliderBackgroundThemeHeight + height: control.vertical ? control.second.position * parent.height - control.first.position * parent.height : 2 // SliderBackgroundThemeHeight color: control.enabled ? control.Universal.accent : control.Universal.chromeDisabledHighColor } diff --git a/src/imports/controls/universal/RoundButton.qml b/src/imports/controls/universal/RoundButton.qml index d70c4cda..ac5f2545 100644 --- a/src/imports/controls/universal/RoundButton.qml +++ b/src/imports/controls/universal/RoundButton.qml @@ -35,8 +35,10 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Universal 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Universal 2.3 T.RoundButton { id: control @@ -48,18 +50,23 @@ T.RoundButton { baselineOffset: contentItem.y + contentItem.baselineOffset padding: 8 + spacing: 8 + + icon.width: 20 + icon.height: 20 + icon.color: Color.transparent(Universal.foreground, enabled ? 1.0 : 0.2) property bool useSystemFocusVisuals: true - contentItem: Text { + contentItem: IconLabel { + spacing: control.spacing + mirrored: control.mirrored + display: control.display + + icon: control.icon text: control.text font: control.font - elide: Text.ElideRight - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - - opacity: enabled ? 1.0 : 0.2 - color: control.Universal.foreground + color: Color.transparent(control.Universal.foreground, enabled ? 1.0 : 0.2) } background: Rectangle { diff --git a/src/imports/controls/universal/ScrollBar.qml b/src/imports/controls/universal/ScrollBar.qml index 981e382a..c6ca874e 100644 --- a/src/imports/controls/universal/ScrollBar.qml +++ b/src/imports/controls/universal/ScrollBar.qml @@ -35,8 +35,8 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Universal 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls.Universal 2.3 T.ScrollBar { id: control diff --git a/src/imports/controls/universal/ScrollIndicator.qml b/src/imports/controls/universal/ScrollIndicator.qml index 2f30ebe5..6c15050b 100644 --- a/src/imports/controls/universal/ScrollIndicator.qml +++ b/src/imports/controls/universal/ScrollIndicator.qml @@ -35,8 +35,8 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Universal 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls.Universal 2.3 T.ScrollIndicator { id: control diff --git a/src/imports/controls/universal/Slider.qml b/src/imports/controls/universal/Slider.qml index e02065e5..bc483c3a 100644 --- a/src/imports/controls/universal/Slider.qml +++ b/src/imports/controls/universal/Slider.qml @@ -35,8 +35,8 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Universal 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls.Universal 2.3 T.Slider { id: control @@ -51,13 +51,11 @@ T.Slider { property bool useSystemFocusVisuals: true handle: Rectangle { - implicitWidth: horizontal ? 8 : 24 - implicitHeight: horizontal ? 24 : 8 + implicitWidth: control.horizontal ? 8 : 24 + implicitHeight: control.horizontal ? 24 : 8 - readonly property bool horizontal: control.orientation === Qt.Horizontal - - x: control.leftPadding + (horizontal ? control.visualPosition * (control.availableWidth - width) : (control.availableWidth - width) / 2) - y: control.topPadding + (horizontal ? (control.availableHeight - height) / 2 : control.visualPosition * (control.availableHeight - height)) + x: control.leftPadding + (control.horizontal ? control.visualPosition * (control.availableWidth - width) : (control.availableWidth - width) / 2) + y: control.topPadding + (control.horizontal ? (control.availableHeight - height) / 2 : control.visualPosition * (control.availableHeight - height)) radius: 4 color: control.pressed ? control.Universal.chromeHighColor : @@ -66,33 +64,31 @@ T.Slider { } background: Item { - implicitWidth: horizontal ? 200 : 18 - implicitHeight: horizontal ? 18 : 200 - - readonly property bool horizontal: control.orientation === Qt.Horizontal + implicitWidth: control.horizontal ? 200 : 18 + implicitHeight: control.horizontal ? 18 : 200 - x: control.leftPadding + (horizontal ? 0 : (control.availableWidth - width) / 2) - y: control.topPadding + (horizontal ? (control.availableHeight - height) / 2 : 0) - width: horizontal ? control.availableWidth : implicitWidth - height: horizontal ? implicitHeight : control.availableHeight + x: control.leftPadding + (control.horizontal ? 0 : (control.availableWidth - width) / 2) + y: control.topPadding + (control.horizontal ? (control.availableHeight - height) / 2 : 0) + width: control.horizontal ? control.availableWidth : implicitWidth + height: control.horizontal ? implicitHeight : control.availableHeight - scale: horizontal && control.mirrored ? -1 : 1 + scale: control.horizontal && control.mirrored ? -1 : 1 Rectangle { - x: parent.horizontal ? 0 : (parent.width - width) / 2 - y: parent.horizontal ? (parent.height - height) / 2 : 0 - width: parent.horizontal ? parent.width : 2 // SliderTrackThemeHeight - height: !parent.horizontal ? parent.height : 2 // SliderTrackThemeHeight + x: control.horizontal ? 0 : (parent.width - width) / 2 + y: control.horizontal ? (parent.height - height) / 2 : 0 + width: control.horizontal ? parent.width : 2 // SliderTrackThemeHeight + height: !control.horizontal ? parent.height : 2 // SliderTrackThemeHeight color: control.hovered && !control.pressed ? control.Universal.baseMediumColor : control.enabled ? control.Universal.baseMediumLowColor : control.Universal.chromeDisabledHighColor } Rectangle { - x: parent.horizontal ? 0 : (parent.width - width) / 2 - y: parent.horizontal ? (parent.height - height) / 2 : control.visualPosition * parent.height - width: parent.horizontal ? control.position * parent.width : 2 // SliderTrackThemeHeight - height: !parent.horizontal ? control.position * parent.height : 2 // SliderTrackThemeHeight + x: control.horizontal ? 0 : (parent.width - width) / 2 + y: control.horizontal ? (parent.height - height) / 2 : control.visualPosition * parent.height + width: control.horizontal ? control.position * parent.width : 2 // SliderTrackThemeHeight + height: !control.horizontal ? control.position * parent.height : 2 // SliderTrackThemeHeight color: control.enabled ? control.Universal.accent : control.Universal.chromeDisabledHighColor } diff --git a/src/imports/controls/universal/SpinBox.qml b/src/imports/controls/universal/SpinBox.qml index 0cbfdd16..499afc82 100644 --- a/src/imports/controls/universal/SpinBox.qml +++ b/src/imports/controls/universal/SpinBox.qml @@ -35,8 +35,10 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Universal 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Universal 2.3 T.SpinBox { id: control @@ -99,14 +101,12 @@ T.SpinBox { opacity: control.activeFocus && !control.up.pressed ? 0.4 : 1.0 } - Image { + ColorImage { x: (parent.width - width) / 2 y: (parent.height - height) / 2 - source: "image://universal/" + (control.mirrored ? "left" : "right") + "arrow/" - + (!enabled ? control.Universal.chromeDisabledLowColor : - control.activeFocus ? control.Universal.chromeBlackHighColor : control.Universal.baseHighColor) - sourceSize.width: width - sourceSize.height: height + color: !enabled ? control.Universal.chromeDisabledLowColor : + control.activeFocus ? control.Universal.chromeBlackHighColor : control.Universal.baseHighColor + source: "qrc:/qt-project.org/imports/QtQuick/Controls.2/Universal/images/" + (control.mirrored ? "left" : "right") + "arrow.png" } } @@ -127,14 +127,12 @@ T.SpinBox { opacity: control.activeFocus && !control.down.pressed ? 0.4 : 1.0 } - Image { + ColorImage { x: (parent.width - width) / 2 y: (parent.height - height) / 2 - source: "image://universal/" + (control.mirrored ? "right" : "left") + "arrow/" - + (!enabled ? control.Universal.chromeDisabledLowColor : - control.activeFocus ? control.Universal.chromeBlackHighColor : control.Universal.baseHighColor) - sourceSize.width: width - sourceSize.height: height + color: !enabled ? control.Universal.chromeDisabledLowColor : + control.activeFocus ? control.Universal.chromeBlackHighColor : control.Universal.baseHighColor + source: "qrc:/qt-project.org/imports/QtQuick/Controls.2/Universal/images/" + (control.mirrored ? "right" : "left") + "arrow.png" } } diff --git a/src/imports/controls/universal/StackView.qml b/src/imports/controls/universal/StackView.qml index 071e1737..3e951c67 100644 --- a/src/imports/controls/universal/StackView.qml +++ b/src/imports/controls/universal/StackView.qml @@ -35,8 +35,8 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Universal 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls.Universal 2.3 T.StackView { id: control diff --git a/src/imports/controls/universal/SwipeDelegate.qml b/src/imports/controls/universal/SwipeDelegate.qml index cec5c132..246d4a15 100644 --- a/src/imports/controls/universal/SwipeDelegate.qml +++ b/src/imports/controls/universal/SwipeDelegate.qml @@ -35,8 +35,10 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Universal 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Universal 2.3 T.SwipeDelegate { id: control @@ -54,21 +56,22 @@ T.SwipeDelegate { topPadding: padding - 1 bottomPadding: padding + 1 + icon.width: 20 + icon.height: 20 + icon.color: Color.transparent(Universal.foreground, enabled ? 1.0 : 0.2) + swipe.transition: Transition { SmoothedAnimation { velocity: 3; easing.type: Easing.InOutCubic } } - contentItem: Text { - leftPadding: !control.mirrored ? (control.indicator ? control.indicator.width : 0) + control.spacing : 0 - rightPadding: control.mirrored ? (control.indicator ? control.indicator.width : 0) + control.spacing : 0 + contentItem: IconLabel { + spacing: control.spacing + mirrored: control.mirrored + display: control.display + alignment: control.display === IconLabel.IconOnly || control.display === IconLabel.TextUnderIcon ? Qt.AlignCenter : Qt.AlignLeft + icon: control.icon text: control.text font: control.font - elide: Text.ElideRight - visible: control.text - horizontalAlignment: Text.AlignLeft - verticalAlignment: Text.AlignVCenter - - opacity: enabled ? 1.0 : 0.2 - color: control.Universal.foreground + color: Color.transparent(control.Universal.foreground, enabled ? 1.0 : 0.2) } background: Rectangle { diff --git a/src/imports/controls/universal/Switch.qml b/src/imports/controls/universal/Switch.qml index ad07d0df..2b05d45f 100644 --- a/src/imports/controls/universal/Switch.qml +++ b/src/imports/controls/universal/Switch.qml @@ -35,9 +35,9 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Universal 2.2 -import QtQuick.Controls.Universal.impl 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls.Universal 2.3 +import QtQuick.Controls.Universal.impl 2.3 T.Switch { id: control diff --git a/src/imports/controls/universal/SwitchDelegate.qml b/src/imports/controls/universal/SwitchDelegate.qml index a4ba85db..ec4f37b4 100644 --- a/src/imports/controls/universal/SwitchDelegate.qml +++ b/src/imports/controls/universal/SwitchDelegate.qml @@ -35,9 +35,11 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Universal 2.2 -import QtQuick.Controls.Universal.impl 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Universal 2.3 +import QtQuick.Controls.Universal.impl 2.3 T.SwitchDelegate { id: control @@ -55,25 +57,29 @@ T.SwitchDelegate { topPadding: padding - 1 bottomPadding: padding + 1 + icon.width: 20 + icon.height: 20 + icon.color: Color.transparent(Universal.foreground, enabled ? 1.0 : 0.2) + indicator: SwitchIndicator { x: text ? (control.mirrored ? control.leftPadding : control.width - width - control.rightPadding) : control.leftPadding + (control.availableWidth - width) / 2 y: control.topPadding + (control.availableHeight - height) / 2 control: control } - contentItem: Text { + contentItem: IconLabel { leftPadding: !control.mirrored ? 0 : control.indicator.width + control.spacing rightPadding: control.mirrored ? 0 : control.indicator.width + control.spacing + spacing: control.spacing + mirrored: control.mirrored + display: control.display + alignment: control.display === IconLabel.IconOnly || control.display === IconLabel.TextUnderIcon ? Qt.AlignCenter : Qt.AlignLeft + + icon: control.icon text: control.text font: control.font - elide: Text.ElideRight - visible: control.text - horizontalAlignment: Text.AlignLeft - verticalAlignment: Text.AlignVCenter - - opacity: enabled ? 1.0 : 0.2 - color: control.Universal.foreground + color: Color.transparent(control.Universal.foreground, enabled ? 1.0 : 0.2) } background: Rectangle { diff --git a/src/imports/controls/universal/SwitchIndicator.qml b/src/imports/controls/universal/SwitchIndicator.qml index 1eb2f9b5..6e66f16d 100644 --- a/src/imports/controls/universal/SwitchIndicator.qml +++ b/src/imports/controls/universal/SwitchIndicator.qml @@ -35,8 +35,8 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Universal 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls.Universal 2.3 Item { implicitWidth: 44 diff --git a/src/imports/controls/universal/TabBar.qml b/src/imports/controls/universal/TabBar.qml index c0de7fb2..9c6fa217 100644 --- a/src/imports/controls/universal/TabBar.qml +++ b/src/imports/controls/universal/TabBar.qml @@ -35,8 +35,8 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Universal 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls.Universal 2.3 T.TabBar { id: control @@ -46,8 +46,6 @@ T.TabBar { implicitHeight: Math.max(background ? background.implicitHeight : 0, contentHeight + topPadding + bottomPadding) - contentHeight: 48 - contentItem: PathView { model: control.contentModel currentIndex: control.currentIndex diff --git a/src/imports/controls/universal/TabButton.qml b/src/imports/controls/universal/TabButton.qml index ef982c60..054f65f5 100644 --- a/src/imports/controls/universal/TabButton.qml +++ b/src/imports/controls/universal/TabButton.qml @@ -35,8 +35,10 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Universal 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Universal 2.3 T.TabButton { id: control @@ -48,15 +50,22 @@ T.TabButton { baselineOffset: contentItem.y + contentItem.baselineOffset padding: 12 // PivotItemMargin + spacing: 8 - contentItem: Text { + icon.width: 20 + icon.height: 20 + icon.color: Color.transparent(control.hovered ? control.Universal.baseMediumHighColor : control.Universal.foreground, + control.checked || control.down || control.hovered ? 1.0 : 0.2) + + contentItem: IconLabel { + spacing: control.spacing + mirrored: control.mirrored + display: control.display + + icon: control.icon text: control.text font: control.font - elide: Text.ElideRight - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - - opacity: control.checked || control.down || control.hovered ? 1.0 : 0.2 - color: control.hovered ? control.Universal.baseMediumHighColor : control.Universal.foreground + color: Color.transparent(control.hovered ? control.Universal.baseMediumHighColor : control.Universal.foreground, + control.checked || control.down || control.hovered ? 1.0 : 0.2) } } diff --git a/src/imports/controls/universal/TextArea.qml b/src/imports/controls/universal/TextArea.qml index a173e676..f356dd3a 100644 --- a/src/imports/controls/universal/TextArea.qml +++ b/src/imports/controls/universal/TextArea.qml @@ -35,10 +35,10 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls 2.2 -import QtQuick.Controls.impl 2.2 -import QtQuick.Controls.Universal 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Universal 2.3 T.TextArea { id: control diff --git a/src/imports/controls/universal/TextField.qml b/src/imports/controls/universal/TextField.qml index 476630fd..01ce2601 100644 --- a/src/imports/controls/universal/TextField.qml +++ b/src/imports/controls/universal/TextField.qml @@ -35,10 +35,10 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls 2.2 -import QtQuick.Controls.impl 2.2 -import QtQuick.Controls.Universal 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Universal 2.3 T.TextField { id: control diff --git a/src/imports/controls/universal/ToolBar.qml b/src/imports/controls/universal/ToolBar.qml index f6bec475..d41ca17f 100644 --- a/src/imports/controls/universal/ToolBar.qml +++ b/src/imports/controls/universal/ToolBar.qml @@ -35,8 +35,8 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Universal 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls.Universal 2.3 T.ToolBar { id: control diff --git a/src/imports/controls/universal/ToolButton.qml b/src/imports/controls/universal/ToolButton.qml index 9b07490f..cd0b2ca9 100644 --- a/src/imports/controls/universal/ToolButton.qml +++ b/src/imports/controls/universal/ToolButton.qml @@ -35,8 +35,10 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Universal 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 +import QtQuick.Controls.Universal 2.3 T.ToolButton { id: control @@ -48,18 +50,23 @@ T.ToolButton { baselineOffset: contentItem.y + contentItem.baselineOffset padding: 6 + spacing: 8 + + icon.width: 20 + icon.height: 20 + icon.color: Color.transparent(Universal.foreground, enabled ? 1.0 : 0.2) property bool useSystemFocusVisuals: true - contentItem: Text { + contentItem: IconLabel { + spacing: control.spacing + mirrored: control.mirrored + display: control.display + + icon: control.icon text: control.text font: control.font - elide: Text.ElideRight - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - - opacity: enabled ? 1.0 : 0.2 - color: control.Universal.foreground + color: Color.transparent(control.Universal.foreground, enabled ? 1.0 : 0.2) } background: Rectangle { diff --git a/src/imports/controls/universal/ToolSeparator.qml b/src/imports/controls/universal/ToolSeparator.qml index 8d36d95b..965b9690 100644 --- a/src/imports/controls/universal/ToolSeparator.qml +++ b/src/imports/controls/universal/ToolSeparator.qml @@ -35,8 +35,8 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Universal 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls.Universal 2.3 T.ToolSeparator { id: control diff --git a/src/imports/controls/universal/ToolTip.qml b/src/imports/controls/universal/ToolTip.qml index 6f8f27f4..cb131919 100644 --- a/src/imports/controls/universal/ToolTip.qml +++ b/src/imports/controls/universal/ToolTip.qml @@ -35,8 +35,8 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Universal 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls.Universal 2.3 T.ToolTip { id: control diff --git a/src/imports/controls/universal/Tumbler.qml b/src/imports/controls/universal/Tumbler.qml index 45bcb6c8..bf31e68a 100644 --- a/src/imports/controls/universal/Tumbler.qml +++ b/src/imports/controls/universal/Tumbler.qml @@ -35,10 +35,10 @@ ****************************************************************************/ import QtQuick 2.9 -import QtQuick.Templates 2.2 as T -import QtQuick.Controls.Universal 2.2 -import QtQuick.Controls 2.2 -import QtQuick.Controls.impl 2.2 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls.Universal 2.3 +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 T.Tumbler { id: control diff --git a/src/imports/controls/universal/qmldir b/src/imports/controls/universal/qmldir index da4a89d6..271eafa9 100644 --- a/src/imports/controls/universal/qmldir +++ b/src/imports/controls/universal/qmldir @@ -1,4 +1,4 @@ module QtQuick.Controls.Universal plugin qtquickcontrols2universalstyleplugin classname QtQuickControls2UniversalStylePlugin -depends QtQuick.Controls 2.2 +depends QtQuick.Controls 2.3 diff --git a/src/imports/controls/universal/qquickuniversalstyle.cpp b/src/imports/controls/universal/qquickuniversalstyle.cpp index c581a784..157d5ddb 100644 --- a/src/imports/controls/universal/qquickuniversalstyle.cpp +++ b/src/imports/controls/universal/qquickuniversalstyle.cpp @@ -39,7 +39,7 @@ #include <QtCore/qdebug.h> #include <QtCore/qsettings.h> #include <QtQml/qqmlinfo.h> -#include <QtQuickControls2/private/qquickstyleattached_p.h> +#include <QtQuickControls2/private/qquickstyle_p.h> QT_BEGIN_NAMESPACE @@ -132,12 +132,10 @@ static QRgb qquickuniversal_accent_color(QQuickUniversalStyle::Color accent) return colors[accent]; } -extern bool qt_is_dark_system_theme(); - static QQuickUniversalStyle::Theme qquickuniversal_effective_theme(QQuickUniversalStyle::Theme theme) { if (theme == QQuickUniversalStyle::System) - theme = qt_is_dark_system_theme() ? QQuickUniversalStyle::Dark : QQuickUniversalStyle::Light; + theme = QQuickStylePrivate::isDarkSystemTheme() ? QQuickUniversalStyle::Dark : QQuickUniversalStyle::Light; return theme; } @@ -153,7 +151,7 @@ static QRgb GlobalBackground = qquickuniversal_light_color(QQuickUniversalStyle: static bool HasGlobalForeground = false; static bool HasGlobalBackground = false; -QQuickUniversalStyle::QQuickUniversalStyle(QObject *parent) : QQuickStyleAttached(parent), +QQuickUniversalStyle::QQuickUniversalStyle(QObject *parent) : QQuickAttachedObject(parent), m_explicitTheme(false), m_explicitAccent(false), m_explicitForeground(false), m_explicitBackground(false), m_hasForeground(HasGlobalForeground), m_hasBackground(HasGlobalBackground), m_theme(GlobalTheme), m_accent(GlobalAccent), m_foreground(GlobalForeground), m_background(GlobalBackground) @@ -201,8 +199,8 @@ void QQuickUniversalStyle::inheritTheme(Theme theme) void QQuickUniversalStyle::propagateTheme() { - const auto styles = childStyles(); - for (QQuickStyleAttached *child : styles) { + const auto styles = attachedChildren(); + for (QQuickAttachedObject *child : styles) { QQuickUniversalStyle *universal = qobject_cast<QQuickUniversalStyle *>(child); if (universal) universal->inheritTheme(m_theme); @@ -215,7 +213,7 @@ void QQuickUniversalStyle::resetTheme() return; m_explicitTheme = false; - QQuickUniversalStyle *universal = qobject_cast<QQuickUniversalStyle *>(parentStyle()); + QQuickUniversalStyle *universal = qobject_cast<QQuickUniversalStyle *>(attachedParent()); inheritTheme(universal ? universal->theme() : GlobalTheme); } @@ -251,8 +249,8 @@ void QQuickUniversalStyle::inheritAccent(QRgb accent) void QQuickUniversalStyle::propagateAccent() { - const auto styles = childStyles(); - for (QQuickStyleAttached *child : styles) { + const auto styles = attachedChildren(); + for (QQuickAttachedObject *child : styles) { QQuickUniversalStyle *universal = qobject_cast<QQuickUniversalStyle *>(child); if (universal) universal->inheritAccent(m_accent); @@ -265,7 +263,7 @@ void QQuickUniversalStyle::resetAccent() return; m_explicitAccent = false; - QQuickUniversalStyle *universal = qobject_cast<QQuickUniversalStyle *>(parentStyle()); + QQuickUniversalStyle *universal = qobject_cast<QQuickUniversalStyle *>(attachedParent()); inheritAccent(universal ? universal->m_accent : GlobalAccent); } @@ -305,8 +303,8 @@ void QQuickUniversalStyle::inheritForeground(QRgb foreground, bool has) void QQuickUniversalStyle::propagateForeground() { - const auto styles = childStyles(); - for (QQuickStyleAttached *child : styles) { + const auto styles = attachedChildren(); + for (QQuickAttachedObject *child : styles) { QQuickUniversalStyle *universal = qobject_cast<QQuickUniversalStyle *>(child); if (universal) universal->inheritForeground(m_foreground, m_hasForeground); @@ -320,7 +318,7 @@ void QQuickUniversalStyle::resetForeground() m_hasForeground = false; m_explicitForeground = false; - QQuickUniversalStyle *universal = qobject_cast<QQuickUniversalStyle *>(parentStyle()); + QQuickUniversalStyle *universal = qobject_cast<QQuickUniversalStyle *>(attachedParent()); inheritForeground(universal ? universal->m_foreground : GlobalForeground, universal ? universal->m_hasForeground : false); } @@ -360,8 +358,8 @@ void QQuickUniversalStyle::inheritBackground(QRgb background, bool has) void QQuickUniversalStyle::propagateBackground() { - const auto styles = childStyles(); - for (QQuickStyleAttached *child : styles) { + const auto styles = attachedChildren(); + for (QQuickAttachedObject *child : styles) { QQuickUniversalStyle *universal = qobject_cast<QQuickUniversalStyle *>(child); if (universal) universal->inheritBackground(m_background, m_hasBackground); @@ -375,7 +373,7 @@ void QQuickUniversalStyle::resetBackground() m_hasBackground = false; m_explicitBackground = false; - QQuickUniversalStyle *universal = qobject_cast<QQuickUniversalStyle *>(parentStyle()); + QQuickUniversalStyle *universal = qobject_cast<QQuickUniversalStyle *>(attachedParent()); inheritBackground(universal ? universal->m_background : GlobalBackground, universal ? universal->m_hasBackground : false); } @@ -509,7 +507,7 @@ QColor QQuickUniversalStyle::systemColor(SystemColor role) const return QColor::fromRgba(m_theme == QQuickUniversalStyle::Dark ? qquickuniversal_dark_color(role) : qquickuniversal_light_color(role)); } -void QQuickUniversalStyle::parentStyleChange(QQuickStyleAttached *newParent, QQuickStyleAttached *oldParent) +void QQuickUniversalStyle::attachedParentChange(QQuickAttachedObject *newParent, QQuickAttachedObject *oldParent) { Q_UNUSED(oldParent); QQuickUniversalStyle *universal = qobject_cast<QQuickUniversalStyle *>(newParent); @@ -542,7 +540,7 @@ void QQuickUniversalStyle::init() { static bool globalsInitialized = false; if (!globalsInitialized) { - QSharedPointer<QSettings> settings = QQuickStyleAttached::settings(QStringLiteral("Universal")); + QSharedPointer<QSettings> settings = QQuickStylePrivate::settings(QStringLiteral("Universal")); bool ok = false; QByteArray themeValue = resolveSetting("QT_QUICK_CONTROLS_UNIVERSAL_THEME", settings, QStringLiteral("Theme")); @@ -597,7 +595,7 @@ void QQuickUniversalStyle::init() globalsInitialized = true; } - QQuickStyleAttached::init(); // TODO: lazy init? + QQuickAttachedObject::init(); // TODO: lazy init? } bool QQuickUniversalStyle::variantToRgba(const QVariant &var, const char *name, QRgb *rgba) const diff --git a/src/imports/controls/universal/qquickuniversalstyle_p.h b/src/imports/controls/universal/qquickuniversalstyle_p.h index 508e8297..196048ef 100644 --- a/src/imports/controls/universal/qquickuniversalstyle_p.h +++ b/src/imports/controls/universal/qquickuniversalstyle_p.h @@ -49,13 +49,13 @@ // #include <QtGui/qcolor.h> -#include <QtQuickControls2/private/qquickstyleattached_p.h> +#include <QtQuickControls2/private/qquickattachedobject_p.h> QT_BEGIN_NAMESPACE class QQuickUniversalStylePrivate; -class QQuickUniversalStyle : public QQuickStyleAttached +class QQuickUniversalStyle : public QQuickAttachedObject { Q_OBJECT Q_PROPERTY(Theme theme READ theme WRITE setTheme RESET resetTheme NOTIFY themeChanged FINAL) @@ -208,7 +208,7 @@ Q_SIGNALS: void paletteChanged(); protected: - void parentStyleChange(QQuickStyleAttached *newParent, QQuickStyleAttached *oldParent) override; + void attachedParentChange(QQuickAttachedObject *newParent, QQuickAttachedObject *oldParent) override; private: void init(); diff --git a/src/imports/controls/universal/qquickuniversaltheme.cpp b/src/imports/controls/universal/qquickuniversaltheme.cpp index a7bcbb8c..549840b6 100644 --- a/src/imports/controls/universal/qquickuniversaltheme.cpp +++ b/src/imports/controls/universal/qquickuniversaltheme.cpp @@ -41,8 +41,8 @@ QT_BEGIN_NAMESPACE -QQuickUniversalTheme::QQuickUniversalTheme(QPlatformTheme *theme) - : QQuickProxyTheme(theme) +QQuickUniversalTheme::QQuickUniversalTheme() + : QQuickTheme(QStringLiteral("Universal")) { const QFont font(QLatin1String("Segoe UI")); if (QFontInfo(font).family() == QLatin1String("Segoe UI")) { @@ -53,12 +53,15 @@ QQuickUniversalTheme::QQuickUniversalTheme(QPlatformTheme *theme) } systemFont.setPixelSize(15); + systemFont = resolveFont(systemFont); groupBoxTitleFont.setPixelSize(15); groupBoxTitleFont.setWeight(QFont::DemiBold); + groupBoxTitleFont = resolveFont(groupBoxTitleFont); tabButtonFont.setPixelSize(24); tabButtonFont.setWeight(QFont::Light); + tabButtonFont = resolveFont(tabButtonFont); } const QFont *QQuickUniversalTheme::font(QPlatformTheme::Font type) const diff --git a/src/imports/controls/universal/qquickuniversaltheme_p.h b/src/imports/controls/universal/qquickuniversaltheme_p.h index 3ac32598..f15dee3e 100644 --- a/src/imports/controls/universal/qquickuniversaltheme_p.h +++ b/src/imports/controls/universal/qquickuniversaltheme_p.h @@ -49,14 +49,14 @@ // #include <QtGui/qfont.h> -#include <QtQuickControls2/private/qquickproxytheme_p.h> +#include <QtQuickControls2/private/qquicktheme_p.h> QT_BEGIN_NAMESPACE -class QQuickUniversalTheme : public QQuickProxyTheme +class QQuickUniversalTheme : public QQuickTheme { public: - explicit QQuickUniversalTheme(QPlatformTheme *theme = nullptr); + explicit QQuickUniversalTheme(); const QFont *font(Font type = SystemFont) const override; diff --git a/src/imports/controls/universal/qtquickcontrols2universalstyleplugin.cpp b/src/imports/controls/universal/qtquickcontrols2universalstyleplugin.cpp index 017a1aad..55255181 100644 --- a/src/imports/controls/universal/qtquickcontrols2universalstyleplugin.cpp +++ b/src/imports/controls/universal/qtquickcontrols2universalstyleplugin.cpp @@ -42,8 +42,6 @@ #include "qquickuniversalstyle_p.h" #include "qquickuniversaltheme_p.h" -#include <QtQuickControls2/private/qquickcolorimageprovider_p.h> - static inline void initResources() { Q_INIT_RESOURCE(qtquickcontrols2universalstyleplugin); @@ -84,8 +82,6 @@ void QtQuickControls2UniversalStylePlugin::initializeEngine(QQmlEngine *engine, { QQuickStylePlugin::initializeEngine(engine, uri); - engine->addImageProvider(name(), new QQuickColorImageProvider(QStringLiteral(":/qt-project.org/imports/QtQuick/Controls.2/Universal/images"))); - QByteArray import = QByteArray(uri) + ".impl"; qmlRegisterModule(import, 2, QT_VERSION_MINOR - 7); // Qt 5.7->2.0, 5.8->2.1, 5.9->2.2... diff --git a/src/imports/controls/universal/universal.pro b/src/imports/controls/universal/universal.pro index e1b61c04..016fa085 100644 --- a/src/imports/controls/universal/universal.pro +++ b/src/imports/controls/universal/universal.pro @@ -1,6 +1,6 @@ TARGET = qtquickcontrols2universalstyleplugin TARGETPATH = QtQuick/Controls.2/Universal -IMPORT_VERSION = 2.2 +IMPORT_VERSION = 2.3 QT += qml quick QT_PRIVATE += core-private gui-private qml-private quick-private quicktemplates2-private quickcontrols2-private diff --git a/src/imports/imports.pro b/src/imports/imports.pro index e1da66c9..dfba46ac 100644 --- a/src/imports/imports.pro +++ b/src/imports/imports.pro @@ -6,5 +6,6 @@ SUBDIRS += \ templates SUBDIRS += \ + controls/fusion/fusion.pro \ controls/material/material.pro \ controls/universal/universal.pro diff --git a/src/imports/platform/widgets/qwidgetplatformmenu.cpp b/src/imports/platform/widgets/qwidgetplatformmenu.cpp index 1aacb0ff..e5fe734f 100644 --- a/src/imports/platform/widgets/qwidgetplatformmenu.cpp +++ b/src/imports/platform/widgets/qwidgetplatformmenu.cpp @@ -44,7 +44,7 @@ QT_BEGIN_NAMESPACE QWidgetPlatformMenu::QWidgetPlatformMenu(QObject *parent) - : m_tag(reinterpret_cast<quintptr>(this)), m_menu(new QMenu) + : m_menu(new QMenu) { setParent(parent); @@ -95,16 +95,6 @@ void QWidgetPlatformMenu::syncSeparatorsCollapsible(bool enable) m_menu->setSeparatorsCollapsible(enable); } -quintptr QWidgetPlatformMenu::tag() const -{ - return m_tag; -} - -void QWidgetPlatformMenu::setTag(quintptr tag) -{ - m_tag = tag; -} - void QWidgetPlatformMenu::setText(const QString &text) { m_menu->setTitle(text); diff --git a/src/imports/platform/widgets/qwidgetplatformmenu_p.h b/src/imports/platform/widgets/qwidgetplatformmenu_p.h index 1df9ef78..4d58f528 100644 --- a/src/imports/platform/widgets/qwidgetplatformmenu_p.h +++ b/src/imports/platform/widgets/qwidgetplatformmenu_p.h @@ -70,9 +70,6 @@ public: void syncMenuItem(QPlatformMenuItem *item) override; void syncSeparatorsCollapsible(bool enable) override; - quintptr tag()const override; - void setTag(quintptr tag) override; - void setText(const QString &text) override; void setIcon(const QIcon &icon) override; void setEnabled(bool enabled) override; @@ -92,7 +89,6 @@ public: QPlatformMenu *createSubMenu() const override; private: - quintptr m_tag; QScopedPointer<QMenu> m_menu; QVector<QWidgetPlatformMenuItem *> m_items; }; diff --git a/src/imports/platform/widgets/qwidgetplatformmenuitem.cpp b/src/imports/platform/widgets/qwidgetplatformmenuitem.cpp index 8519c899..9de899f2 100644 --- a/src/imports/platform/widgets/qwidgetplatformmenuitem.cpp +++ b/src/imports/platform/widgets/qwidgetplatformmenuitem.cpp @@ -43,7 +43,7 @@ QT_BEGIN_NAMESPACE QWidgetPlatformMenuItem::QWidgetPlatformMenuItem(QObject *parent) - : m_tag(reinterpret_cast<quintptr>(this)), m_action(new QAction) + : m_action(new QAction) { setParent(parent); connect(m_action.data(), &QAction::hovered, this, &QPlatformMenuItem::hovered); @@ -59,16 +59,6 @@ QAction *QWidgetPlatformMenuItem::action() const return m_action.data(); } -quintptr QWidgetPlatformMenuItem::tag() const -{ - return m_tag; -} - -void QWidgetPlatformMenuItem::setTag(quintptr tag) -{ - m_tag = tag; -} - void QWidgetPlatformMenuItem::setText(const QString &text) { m_action->setText(text); diff --git a/src/imports/platform/widgets/qwidgetplatformmenuitem_p.h b/src/imports/platform/widgets/qwidgetplatformmenuitem_p.h index 752f8a03..43b3fc17 100644 --- a/src/imports/platform/widgets/qwidgetplatformmenuitem_p.h +++ b/src/imports/platform/widgets/qwidgetplatformmenuitem_p.h @@ -64,9 +64,6 @@ public: QAction *action() const; - quintptr tag()const override; - void setTag(quintptr tag) override; - void setText(const QString &text) override; void setIcon(const QIcon &icon) override; void setMenu(QPlatformMenu *menu) override; @@ -83,7 +80,6 @@ public: void setIconSize(int size) override; private: - quintptr m_tag; QScopedPointer<QAction> m_action; }; diff --git a/src/imports/templates/doc/src/qtquicktemplates2-qmltypes.qdoc b/src/imports/templates/doc/src/qtquicktemplates2-qmltypes.qdoc index 19725fa4..52796425 100644 --- a/src/imports/templates/doc/src/qtquicktemplates2-qmltypes.qdoc +++ b/src/imports/templates/doc/src/qtquicktemplates2-qmltypes.qdoc @@ -26,7 +26,7 @@ ****************************************************************************/ /*! - \qmlmodule QtQuick.Templates 2.2 + \qmlmodule QtQuick.Templates 2.3 \title Qt Quick Templates 2 QML Types \ingroup qmlmodules \brief Provides QML types for templates (Qt Quick Templates). @@ -38,7 +38,7 @@ \c .qml file: \badcode - import QtQuick.Templates 2.2 as T + import QtQuick.Templates 2.3 as T \endcode For the sake of clarity, there is a one-to-one mapping between the types diff --git a/src/imports/templates/plugins.qmltypes b/src/imports/templates/plugins.qmltypes index 712cf3b6..fa9e89dd 100644 --- a/src/imports/templates/plugins.qmltypes +++ b/src/imports/templates/plugins.qmltypes @@ -4,7 +4,7 @@ import QtQuick.tooling 1.2 // It is used for QML tooling purposes only. // // This file was auto-generated by: -// 'qmlplugindump -nonrelocatable -dependencies dependencies.json QtQuick.Templates 2.2' +// 'qmlplugindump -nonrelocatable -dependencies dependencies.json QtQuick.Templates 2.3' Module { dependencies: ["QtQuick 2.9", "QtQuick.Window 2.2"] @@ -14,9 +14,19 @@ Module { prototype: "QQuickControl" exports: [ "QtQuick.Templates/AbstractButton 2.0", - "QtQuick.Templates/AbstractButton 2.2" + "QtQuick.Templates/AbstractButton 2.2", + "QtQuick.Templates/AbstractButton 2.3" ] - exportMetaObjectRevisions: [0, 2] + exportMetaObjectRevisions: [0, 2, 3] + Enum { + name: "Display" + values: { + "IconOnly": 0, + "TextOnly": 1, + "TextBesideIcon": 2, + "TextUnderIcon": 3 + } + } Property { name: "text"; type: "string" } Property { name: "down"; type: "bool" } Property { name: "pressed"; type: "bool"; isReadonly: true } @@ -24,6 +34,9 @@ Module { Property { name: "checkable"; type: "bool" } Property { name: "autoExclusive"; type: "bool" } Property { name: "indicator"; type: "QQuickItem"; isPointer: true } + Property { name: "icon"; revision: 3; type: "QQuickIcon" } + Property { name: "display"; revision: 3; type: "Display" } + Property { name: "action"; revision: 3; type: "QQuickAction"; isPointer: true } Signal { name: "pressed" } Signal { name: "released" } Signal { name: "canceled" } @@ -31,14 +44,104 @@ Module { Signal { name: "toggled"; revision: 2 } Signal { name: "pressAndHold" } Signal { name: "doubleClicked" } + Signal { name: "iconChanged"; revision: 3 } + Signal { name: "displayChanged"; revision: 3 } + Signal { name: "actionChanged"; revision: 3 } Method { name: "toggle" } } Component { + name: "QQuickAction" + prototype: "QObject" + exports: ["QtQuick.Templates/Action 2.3"] + exportMetaObjectRevisions: [0] + Property { name: "text"; type: "string" } + Property { name: "icon"; type: "QQuickIcon" } + Property { name: "enabled"; type: "bool" } + Property { name: "checked"; type: "bool" } + Property { name: "checkable"; type: "bool" } + Property { name: "shortcut"; type: "QVariant" } + Signal { + name: "textChanged" + Parameter { name: "text"; type: "string" } + } + Signal { + name: "iconChanged" + Parameter { name: "icon"; type: "QQuickIcon" } + } + Signal { + name: "enabledChanged" + Parameter { name: "enabled"; type: "bool" } + } + Signal { + name: "checkedChanged" + Parameter { name: "checked"; type: "bool" } + } + Signal { + name: "checkableChanged" + Parameter { name: "checkable"; type: "bool" } + } + Signal { + name: "shortcutChanged" + Parameter { name: "shortcut"; type: "QKeySequence" } + } + Signal { + name: "toggled" + Parameter { name: "source"; type: "QObject"; isPointer: true } + } + Signal { name: "toggled" } + Signal { + name: "triggered" + Parameter { name: "source"; type: "QObject"; isPointer: true } + } + Signal { name: "triggered" } + Method { + name: "toggle" + Parameter { name: "source"; type: "QObject"; isPointer: true } + } + Method { name: "toggle" } + Method { + name: "trigger" + Parameter { name: "source"; type: "QObject"; isPointer: true } + } + Method { name: "trigger" } + } + Component { + name: "QQuickActionGroup" + prototype: "QObject" + exports: ["QtQuick.Templates/ActionGroup 2.3"] + exportMetaObjectRevisions: [0] + attachedType: "QQuickActionGroupAttached" + Property { name: "checkedAction"; type: "QQuickAction"; isPointer: true } + Property { name: "actions"; type: "QQuickAction"; isList: true; isReadonly: true } + Property { name: "exclusive"; type: "bool" } + Property { name: "enabled"; type: "bool" } + Signal { + name: "triggered" + Parameter { name: "action"; type: "QQuickAction"; isPointer: true } + } + Method { + name: "addAction" + Parameter { name: "action"; type: "QQuickAction"; isPointer: true } + } + Method { + name: "removeAction" + Parameter { name: "action"; type: "QQuickAction"; isPointer: true } + } + } + Component { + name: "QQuickActionGroupAttached" + prototype: "QObject" + Property { name: "group"; type: "QQuickActionGroup"; isPointer: true } + } + Component { name: "QQuickApplicationWindow" defaultProperty: "contentData" prototype: "QQuickWindowQmlImpl" - exports: ["QtQuick.Templates/ApplicationWindow 2.0"] - exportMetaObjectRevisions: [0] + exports: [ + "QtQuick.Templates/ApplicationWindow 2.0", + "QtQuick.Templates/ApplicationWindow 2.3" + ] + exportMetaObjectRevisions: [0, 3] attachedType: "QQuickApplicationWindowAttached" Property { name: "background"; type: "QQuickItem"; isPointer: true } Property { name: "contentItem"; type: "QQuickItem"; isReadonly: true; isPointer: true } @@ -49,6 +152,8 @@ Module { Property { name: "overlay"; type: "QQuickOverlay"; isReadonly: true; isPointer: true } Property { name: "font"; type: "QFont" } Property { name: "locale"; type: "QLocale" } + Property { name: "palette"; revision: 3; type: "QPalette" } + Signal { name: "paletteChanged"; revision: 3 } } Component { name: "QQuickApplicationWindowAttached" @@ -83,12 +188,15 @@ Module { prototype: "QObject" exports: [ "QtQuick.Templates/ButtonGroup 2.0", - "QtQuick.Templates/ButtonGroup 2.1" + "QtQuick.Templates/ButtonGroup 2.1", + "QtQuick.Templates/ButtonGroup 2.3" ] - exportMetaObjectRevisions: [0, 1] + exportMetaObjectRevisions: [0, 1, 3] attachedType: "QQuickButtonGroupAttached" Property { name: "checkedButton"; type: "QQuickAbstractButton"; isPointer: true } Property { name: "buttons"; type: "QQuickAbstractButton"; isList: true; isReadonly: true } + Property { name: "exclusive"; revision: 3; type: "bool" } + Signal { name: "exclusiveChanged"; revision: 3 } Signal { name: "clicked" revision: 1 @@ -199,9 +307,10 @@ Module { prototype: "QQuickControl" exports: [ "QtQuick.Templates/Container 2.0", - "QtQuick.Templates/Container 2.1" + "QtQuick.Templates/Container 2.1", + "QtQuick.Templates/Container 2.3" ] - exportMetaObjectRevisions: [0, 1] + exportMetaObjectRevisions: [0, 1, 3] Property { name: "count"; type: "int"; isReadonly: true } Property { name: "contentModel"; type: "QVariant"; isReadonly: true } Property { name: "contentData"; type: "QObject"; isList: true; isReadonly: true } @@ -235,6 +344,12 @@ Module { } Method { name: "removeItem" + Parameter { name: "item"; type: "QVariant" } + } + Method { + name: "takeItem" + revision: 3 + type: "QQuickItem*" Parameter { name: "index"; type: "int" } } } @@ -242,8 +357,11 @@ Module { name: "QQuickControl" defaultProperty: "data" prototype: "QQuickItem" - exports: ["QtQuick.Templates/Control 2.0"] - exportMetaObjectRevisions: [0] + exports: [ + "QtQuick.Templates/Control 2.0", + "QtQuick.Templates/Control 2.3" + ] + exportMetaObjectRevisions: [0, 3] Property { name: "font"; type: "QFont" } Property { name: "availableWidth"; type: "double"; isReadonly: true } Property { name: "availableHeight"; type: "double"; isReadonly: true } @@ -263,6 +381,8 @@ Module { Property { name: "wheelEnabled"; type: "bool" } Property { name: "background"; type: "QQuickItem"; isPointer: true } Property { name: "contentItem"; type: "QQuickItem"; isPointer: true } + Property { name: "palette"; revision: 3; type: "QPalette" } + Signal { name: "paletteChanged"; revision: 3 } } Component { name: "QQuickDelayButton" @@ -309,23 +429,52 @@ Module { name: "QQuickDialog" defaultProperty: "contentData" prototype: "QQuickPopup" - exports: ["QtQuick.Templates/Dialog 2.1"] - exportMetaObjectRevisions: [0] + exports: [ + "QtQuick.Templates/Dialog 2.1", + "QtQuick.Templates/Dialog 2.3" + ] + exportMetaObjectRevisions: [0, 3] + Enum { + name: "StandardCode" + values: { + "Rejected": 0, + "Accepted": 1 + } + } Property { name: "title"; type: "string" } Property { name: "header"; type: "QQuickItem"; isPointer: true } Property { name: "footer"; type: "QQuickItem"; isPointer: true } Property { name: "standardButtons"; type: "QPlatformDialogHelper::StandardButtons" } + Property { name: "result"; revision: 3; type: "int" } Signal { name: "accepted" } Signal { name: "rejected" } + Signal { name: "applied"; revision: 3 } + Signal { name: "reset"; revision: 3 } + Signal { name: "discarded"; revision: 3 } + Signal { name: "helpRequested"; revision: 3 } + Signal { name: "resultChanged"; revision: 3 } Method { name: "accept" } Method { name: "reject" } + Method { + name: "done" + Parameter { name: "result"; type: "int" } + } + Method { + name: "standardButton" + revision: 3 + type: "QQuickAbstractButton*" + Parameter { name: "button"; type: "QPlatformDialogHelper::StandardButton" } + } } Component { name: "QQuickDialogButtonBox" defaultProperty: "contentData" prototype: "QQuickContainer" - exports: ["QtQuick.Templates/DialogButtonBox 2.1"] - exportMetaObjectRevisions: [0] + exports: [ + "QtQuick.Templates/DialogButtonBox 2.1", + "QtQuick.Templates/DialogButtonBox 2.3" + ] + exportMetaObjectRevisions: [0, 0] attachedType: "QQuickDialogButtonBoxAttached" Enum { name: "Position" @@ -341,6 +490,9 @@ Module { Signal { name: "accepted" } Signal { name: "rejected" } Signal { name: "helpRequested" } + Signal { name: "applied"; revision: 3 } + Signal { name: "reset"; revision: 3 } + Signal { name: "discarded"; revision: 3 } Signal { name: "clicked" Parameter { name: "button"; type: "QQuickAbstractButton"; isPointer: true } @@ -404,16 +556,20 @@ Module { exportMetaObjectRevisions: [0] Property { name: "font"; type: "QFont" } Property { name: "background"; type: "QQuickItem"; isPointer: true } + Property { name: "palette"; revision: 3; type: "QPalette" } + Signal { name: "paletteChanged"; revision: 3 } } Component { name: "QQuickMenu" defaultProperty: "contentData" prototype: "QQuickPopup" - exports: ["QtQuick.Templates/Menu 2.0"] - exportMetaObjectRevisions: [0] + exports: ["QtQuick.Templates/Menu 2.0", "QtQuick.Templates/Menu 2.3"] + exportMetaObjectRevisions: [0, 3] Property { name: "contentModel"; type: "QVariant"; isReadonly: true } Property { name: "contentData"; type: "QObject"; isList: true; isReadonly: true } Property { name: "title"; type: "string" } + Property { name: "delegate"; revision: 3; type: "QQmlComponent"; isPointer: true } + Signal { name: "delegateChanged"; revision: 3 } Method { name: "itemAt" type: "QQuickItem*" @@ -435,17 +591,33 @@ Module { } Method { name: "removeItem" + Parameter { name: "item"; type: "QVariant" } + } + Method { + name: "takeItem" + revision: 3 + type: "QQuickItem*" Parameter { name: "index"; type: "int" } } + Method { + name: "popup" + revision: 3 + Parameter { name: "args"; type: "QQmlV4Function"; isPointer: true } + } } Component { name: "QQuickMenuItem" defaultProperty: "data" prototype: "QQuickAbstractButton" - exports: ["QtQuick.Templates/MenuItem 2.0"] - exportMetaObjectRevisions: [0] + exports: [ + "QtQuick.Templates/MenuItem 2.0", + "QtQuick.Templates/MenuItem 2.3" + ] + exportMetaObjectRevisions: [0, 3] Property { name: "highlighted"; type: "bool" } + Property { name: "menu"; revision: 3; type: "QQuickMenu"; isReadonly: true; isPointer: true } Signal { name: "triggered" } + Signal { name: "menuChanged"; revision: 3 } } Component { name: "QQuickMenuSeparator" @@ -507,9 +679,10 @@ Module { prototype: "QObject" exports: [ "QtQuick.Templates/Popup 2.0", - "QtQuick.Templates/Popup 2.1" + "QtQuick.Templates/Popup 2.1", + "QtQuick.Templates/Popup 2.3" ] - exportMetaObjectRevisions: [0, 1] + exportMetaObjectRevisions: [0, 1, 3] Enum { name: "ClosePolicy" values: { @@ -559,6 +732,7 @@ Module { Property { name: "bottomPadding"; type: "double" } Property { name: "locale"; type: "QLocale" } Property { name: "font"; type: "QFont" } + Property { name: "palette"; revision: 3; type: "QPalette" } Property { name: "parent"; type: "QQuickItem"; isPointer: true } Property { name: "background"; type: "QQuickItem"; isPointer: true } Property { name: "contentItem"; type: "QQuickItem"; isPointer: true } @@ -570,6 +744,7 @@ Module { Property { name: "modal"; type: "bool" } Property { name: "dim"; type: "bool" } Property { name: "visible"; type: "bool" } + Property { name: "opened"; revision: 3; type: "bool"; isReadonly: true } Property { name: "opacity"; type: "double" } Property { name: "scale"; type: "double" } Property { name: "closePolicy"; type: "ClosePolicy" } @@ -577,6 +752,8 @@ Module { Property { name: "enter"; type: "QQuickTransition"; isPointer: true } Property { name: "exit"; type: "QQuickTransition"; isPointer: true } Signal { name: "spacingChanged"; revision: 1 } + Signal { name: "paletteChanged"; revision: 3 } + Signal { name: "openedChanged"; revision: 3 } Signal { name: "windowChanged" Parameter { name: "window"; type: "QQuickWindow"; isPointer: true } @@ -627,9 +804,10 @@ Module { exports: [ "QtQuick.Templates/RangeSlider 2.0", "QtQuick.Templates/RangeSlider 2.1", - "QtQuick.Templates/RangeSlider 2.2" + "QtQuick.Templates/RangeSlider 2.2", + "QtQuick.Templates/RangeSlider 2.3" ] - exportMetaObjectRevisions: [0, 1, 2] + exportMetaObjectRevisions: [0, 1, 2, 3] Enum { name: "SnapMode" values: { @@ -645,6 +823,8 @@ Module { Property { name: "stepSize"; type: "double" } Property { name: "snapMode"; type: "SnapMode" } Property { name: "orientation"; type: "Qt::Orientation" } + Property { name: "horizontal"; revision: 3; type: "bool"; isReadonly: true } + Property { name: "vertical"; revision: 3; type: "bool"; isReadonly: true } Property { name: "live"; revision: 2; type: "bool" } Signal { name: "liveChanged"; revision: 2 } Method { @@ -680,9 +860,10 @@ Module { prototype: "QQuickControl" exports: [ "QtQuick.Templates/ScrollBar 2.0", - "QtQuick.Templates/ScrollBar 2.2" + "QtQuick.Templates/ScrollBar 2.2", + "QtQuick.Templates/ScrollBar 2.3" ] - exportMetaObjectRevisions: [0, 2] + exportMetaObjectRevisions: [0, 2, 3] attachedType: "QQuickScrollBarAttached" Enum { name: "SnapMode" @@ -709,6 +890,8 @@ Module { Property { name: "snapMode"; revision: 2; type: "SnapMode" } Property { name: "interactive"; revision: 2; type: "bool" } Property { name: "policy"; revision: 2; type: "Policy" } + Property { name: "horizontal"; revision: 3; type: "bool"; isReadonly: true } + Property { name: "vertical"; revision: 3; type: "bool"; isReadonly: true } Signal { name: "snapModeChanged"; revision: 2 } Signal { name: "interactiveChanged"; revision: 2 } Signal { name: "policyChanged"; revision: 2 } @@ -733,13 +916,18 @@ Module { name: "QQuickScrollIndicator" defaultProperty: "data" prototype: "QQuickControl" - exports: ["QtQuick.Templates/ScrollIndicator 2.0"] - exportMetaObjectRevisions: [0] + exports: [ + "QtQuick.Templates/ScrollIndicator 2.0", + "QtQuick.Templates/ScrollIndicator 2.3" + ] + exportMetaObjectRevisions: [0, 3] attachedType: "QQuickScrollIndicatorAttached" Property { name: "size"; type: "double" } Property { name: "position"; type: "double" } Property { name: "active"; type: "bool" } Property { name: "orientation"; type: "Qt::Orientation" } + Property { name: "horizontal"; revision: 3; type: "bool"; isReadonly: true } + Property { name: "vertical"; revision: 3; type: "bool"; isReadonly: true } Method { name: "setSize" Parameter { name: "size"; type: "double" } @@ -773,9 +961,10 @@ Module { exports: [ "QtQuick.Templates/Slider 2.0", "QtQuick.Templates/Slider 2.1", - "QtQuick.Templates/Slider 2.2" + "QtQuick.Templates/Slider 2.2", + "QtQuick.Templates/Slider 2.3" ] - exportMetaObjectRevisions: [0, 1, 2] + exportMetaObjectRevisions: [0, 1, 2, 3] Enum { name: "SnapMode" values: { @@ -793,6 +982,8 @@ Module { Property { name: "snapMode"; type: "SnapMode" } Property { name: "live"; revision: 2; type: "bool" } Property { name: "pressed"; type: "bool" } + Property { name: "horizontal"; revision: 3; type: "bool"; isReadonly: true } + Property { name: "vertical"; revision: 3; type: "bool"; isReadonly: true } Property { name: "orientation"; type: "Qt::Orientation" } Property { name: "handle"; type: "QQuickItem"; isPointer: true } Signal { name: "liveChanged"; revision: 2 } @@ -813,9 +1004,10 @@ Module { exports: [ "QtQuick.Templates/SpinBox 2.0", "QtQuick.Templates/SpinBox 2.1", - "QtQuick.Templates/SpinBox 2.2" + "QtQuick.Templates/SpinBox 2.2", + "QtQuick.Templates/SpinBox 2.3" ] - exportMetaObjectRevisions: [0, 1, 2] + exportMetaObjectRevisions: [0, 1, 2, 3] Property { name: "from"; type: "int" } Property { name: "to"; type: "int" } Property { name: "value"; type: "int" } @@ -828,9 +1020,11 @@ Module { Property { name: "down"; type: "QQuickSpinButton"; isReadonly: true; isPointer: true } Property { name: "inputMethodHints"; revision: 2; type: "Qt::InputMethodHints" } Property { name: "inputMethodComposing"; revision: 2; type: "bool"; isReadonly: true } + Property { name: "wrap"; revision: 3; type: "bool" } Signal { name: "valueModified"; revision: 2 } Signal { name: "inputMethodHintsChanged"; revision: 2 } Signal { name: "inputMethodComposingChanged"; revision: 2 } + Signal { name: "wrapChanged"; revision: 3 } Method { name: "increase" } Method { name: "decrease" } } @@ -888,6 +1082,12 @@ Module { Property { name: "pushExit"; type: "QQuickTransition"; isPointer: true } Property { name: "replaceEnter"; type: "QQuickTransition"; isPointer: true } Property { name: "replaceExit"; type: "QQuickTransition"; isPointer: true } + Property { name: "empty"; revision: 3; type: "bool"; isReadonly: true } + Signal { name: "emptyChanged"; revision: 3 } + Method { + name: "clear" + Parameter { name: "operation"; type: "Operation" } + } Method { name: "clear" } Method { name: "get" @@ -999,6 +1199,8 @@ Module { attachedType: "QQuickSwipeViewAttached" Property { name: "interactive"; revision: 1; type: "bool" } Property { name: "orientation"; revision: 2; type: "Qt::Orientation" } + Property { name: "horizontal"; revision: 3; type: "bool"; isReadonly: true } + Property { name: "vertical"; revision: 3; type: "bool"; isReadonly: true } Signal { name: "interactiveChanged"; revision: 1 } Signal { name: "orientationChanged"; revision: 2 } } @@ -1038,6 +1240,7 @@ Module { "QtQuick.Templates/TabBar 2.2" ] exportMetaObjectRevisions: [0, 2] + attachedType: "QQuickTabBarAttached" Enum { name: "Position" values: { @@ -1052,6 +1255,13 @@ Module { Signal { name: "contentHeightChanged"; revision: 2 } } Component { + name: "QQuickTabBarAttached" + prototype: "QObject" + Property { name: "index"; type: "int"; isReadonly: true } + Property { name: "tabBar"; type: "QQuickTabBar"; isReadonly: true; isPointer: true } + Property { name: "position"; type: "QQuickTabBar::Position"; isReadonly: true } + } + Component { name: "QQuickTabButton" defaultProperty: "data" prototype: "QQuickAbstractButton" @@ -1076,6 +1286,7 @@ Module { Property { name: "focusReason"; type: "Qt::FocusReason" } Property { name: "hovered"; revision: 1; type: "bool"; isReadonly: true } Property { name: "hoverEnabled"; revision: 1; type: "bool" } + Property { name: "palette"; revision: 3; type: "QPalette" } Signal { name: "implicitWidthChanged3" } Signal { name: "implicitHeightChanged3" } Signal { name: "hoveredChanged"; revision: 1 } @@ -1094,6 +1305,7 @@ Module { revision: 1 Parameter { name: "event"; type: "QQuickMouseEvent"; isPointer: true } } + Signal { name: "paletteChanged"; revision: 3 } } Component { name: "QQuickTextAreaAttached" @@ -1117,6 +1329,7 @@ Module { Property { name: "focusReason"; type: "Qt::FocusReason" } Property { name: "hovered"; revision: 1; type: "bool"; isReadonly: true } Property { name: "hoverEnabled"; revision: 1; type: "bool" } + Property { name: "palette"; revision: 3; type: "QPalette" } Signal { name: "implicitWidthChanged3" } Signal { name: "implicitHeightChanged3" } Signal { name: "hoveredChanged"; revision: 1 } @@ -1135,6 +1348,7 @@ Module { revision: 1 Parameter { name: "event"; type: "QQuickMouseEvent"; isPointer: true } } + Signal { name: "paletteChanged"; revision: 3 } } Component { name: "QQuickToolBar" diff --git a/src/imports/templates/qquicktemplates2valuetypeprovider.cpp b/src/imports/templates/qquicktemplates2valuetypeprovider.cpp new file mode 100644 index 00000000..6debdbc4 --- /dev/null +++ b/src/imports/templates/qquicktemplates2valuetypeprovider.cpp @@ -0,0 +1,159 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Templates 2 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 "qquicktemplates2valuetypeprovider_p.h" + +#include <QtQml/private/qqmlvaluetype_p.h> +#include <QtQuickTemplates2/private/qquickpalette_p.h> + +QT_BEGIN_NAMESPACE + +#if defined(QT_NO_DEBUG) && !defined(QT_FORCE_ASSERTS) + #define ASSERT_VALID_SIZE(size, min) Q_UNUSED(size) +#else + #define ASSERT_VALID_SIZE(size, min) Q_ASSERT(size >= min) +#endif + +const QMetaObject *QQuickTemplates2ValueTypeProvider::getMetaObjectForMetaType(int type) +{ + switch (type) { + case QMetaType::QPalette: + return &QQuickPalette::staticMetaObject; + default: + break; + } + + return nullptr; +} + +bool QQuickTemplates2ValueTypeProvider::init(int type, QVariant& dst) +{ + switch (type) { + case QMetaType::QPalette: + dst.setValue<QPalette>(QPalette()); + return true; + default: break; + } + + return false; +} + +template<typename T> +bool typedEqual(const void *lhs, const QVariant& rhs) +{ + return (*(reinterpret_cast<const T *>(lhs)) == rhs.value<T>()); +} + +bool QQuickTemplates2ValueTypeProvider::equal(int type, const void *lhs, const QVariant &rhs) +{ + switch (type) { + case QMetaType::QPalette: + return typedEqual<QPalette>(lhs, rhs); + default: break; + } + + return false; +} + +template<typename T> +bool typedStore(const void *src, void *dst, size_t dstSize) +{ + ASSERT_VALID_SIZE(dstSize, sizeof(T)); + const T *srcT = reinterpret_cast<const T *>(src); + T *dstT = reinterpret_cast<T *>(dst); + new (dstT) T(*srcT); + return true; +} + +bool QQuickTemplates2ValueTypeProvider::store(int type, const void *src, void *dst, size_t dstSize) +{ + switch (type) { + case QMetaType::QPalette: + return typedStore<QPalette>(src, dst, dstSize); + default: break; + } + + return false; +} + +template<typename T> +bool typedRead(const QVariant& src, int dstType, void *dst) +{ + T *dstT = reinterpret_cast<T *>(dst); + if (src.type() == static_cast<uint>(dstType)) { + *dstT = src.value<T>(); + } else { + *dstT = T(); + } + return true; +} + +bool QQuickTemplates2ValueTypeProvider::read(const QVariant &src, void *dst, int dstType) +{ + switch (dstType) { + case QMetaType::QPalette: + return typedRead<QPalette>(src, dstType, dst); + default: break; + } + + return false; +} + +template<typename T> +bool typedWrite(const void *src, QVariant& dst) +{ + const T *srcT = reinterpret_cast<const T *>(src); + if (dst.value<T>() != *srcT) { + dst = *srcT; + return true; + } + return false; +} + +bool QQuickTemplates2ValueTypeProvider::write(int type, const void *src, QVariant& dst) +{ + switch (type) { + case QMetaType::QPalette: + return typedWrite<QPalette>(src, dst); + default: break; + } + + return false; +} + +#undef ASSERT_VALID_SIZE + +QT_END_NAMESPACE diff --git a/src/imports/templates/qquicktemplates2valuetypeprovider_p.h b/src/imports/templates/qquicktemplates2valuetypeprovider_p.h new file mode 100644 index 00000000..6b072029 --- /dev/null +++ b/src/imports/templates/qquicktemplates2valuetypeprovider_p.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Templates 2 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 QQUICKTEMPLATES2VALUETYPEPROVIDER_P_H +#define QQUICKTEMPLATES2VALUETYPEPROVIDER_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtQml/private/qqmlglobal_p.h> + +QT_BEGIN_NAMESPACE + +class QQuickTemplates2ValueTypeProvider : public QQmlValueTypeProvider +{ +public: + const QMetaObject *getMetaObjectForMetaType(int type) override; + bool init(int type, QVariant& dst) override; + bool equal(int type, const void *lhs, const QVariant &rhs) override; + bool store(int type, const void *src, void *dst, size_t dstSize) override; + bool read(const QVariant &src, void *dst, int dstType) override; + bool write(int type, const void *src, QVariant& dst) override; +}; + +QT_END_NAMESPACE + +#endif // QQUICKTEMPLATES2VALUETYPEPROVIDER_P_H diff --git a/src/imports/templates/qtquicktemplates2plugin.cpp b/src/imports/templates/qtquicktemplates2plugin.cpp index 263d7fde..e7e08e32 100644 --- a/src/imports/templates/qtquicktemplates2plugin.cpp +++ b/src/imports/templates/qtquicktemplates2plugin.cpp @@ -35,8 +35,11 @@ ****************************************************************************/ #include <QtQml/qqmlextensionplugin.h> +#include <QtQml/private/qqmlglobal_p.h> #include <QtQuickTemplates2/private/qquickabstractbutton_p.h> +#include <QtQuickTemplates2/private/qquickaction_p.h> +#include <QtQuickTemplates2/private/qquickactiongroup_p.h> #include <QtQuickTemplates2/private/qquickapplicationwindow_p.h> #include <QtQuickTemplates2/private/qquickbusyindicator_p.h> #include <QtQuickTemplates2/private/qquickbutton_p.h> @@ -53,6 +56,7 @@ #include <QtQuickTemplates2/private/qquickdrawer_p.h> #include <QtQuickTemplates2/private/qquickframe_p.h> #include <QtQuickTemplates2/private/qquickgroupbox_p.h> +#include <QtQuickTemplates2/private/qquickicon_p.h> #include <QtQuickTemplates2/private/qquickitemdelegate_p.h> #include <QtQuickTemplates2/private/qquicklabel_p.h> #include <QtQuickTemplates2/private/qquickmenu_p.h> @@ -92,6 +96,8 @@ #include <QtQuickTemplates2/private/qquicktumbler_p.h> #endif +#include "qquicktemplates2valuetypeprovider_p.h" + static inline void initResources() { #ifdef QT_STATIC @@ -108,6 +114,22 @@ extern void qt_quick_set_shortcut_context_matcher(ShortcutContextMatcher matcher QT_BEGIN_NAMESPACE +static QQmlValueTypeProvider *valueTypeProvider() +{ + static QQuickTemplates2ValueTypeProvider provider; + return &provider; +} + +static void initProviders() +{ + QQml_addValueTypeProvider(valueTypeProvider()); +} + +static void cleanupProviders() +{ + QQml_removeValueTypeProvider(valueTypeProvider()); +} + class QtQuickTemplates2Plugin: public QQmlExtensionPlugin { Q_OBJECT @@ -117,7 +139,7 @@ public: QtQuickTemplates2Plugin(QObject *parent = nullptr); ~QtQuickTemplates2Plugin(); - void registerTypes(const char *uri); + void registerTypes(const char *uri) override; private: #if QT_CONFIG(shortcut) @@ -128,6 +150,7 @@ private: QtQuickTemplates2Plugin::QtQuickTemplates2Plugin(QObject *parent) : QQmlExtensionPlugin(parent) { initResources(); + initProviders(); #if QT_CONFIG(shortcut) originalContextMatcher = qt_quick_shortcut_context_matcher(); @@ -137,6 +160,8 @@ QtQuickTemplates2Plugin::QtQuickTemplates2Plugin(QObject *parent) : QQmlExtensio QtQuickTemplates2Plugin::~QtQuickTemplates2Plugin() { + cleanupProviders(); + #if QT_CONFIG(shortcut) qt_quick_set_shortcut_context_matcher(originalContextMatcher); #endif @@ -186,21 +211,21 @@ void QtQuickTemplates2Plugin::registerTypes(const char *uri) qmlRegisterType<QQuickSpinButton>(); qmlRegisterType<QQuickStackView>(uri, 2, 0, "StackView"); qmlRegisterType<QQuickStackViewAttached>(); - qmlRegisterType<QQuickSwipeDelegate>(uri, 2, 0, "SwipeDelegate"); qmlRegisterType<QQuickSwipe>(); - qmlRegisterType<QQuickSwipeViewAttached>(); + qmlRegisterType<QQuickSwipeDelegate>(uri, 2, 0, "SwipeDelegate"); qmlRegisterType<QQuickSwipeView>(uri, 2, 0, "SwipeView"); + qmlRegisterType<QQuickSwipeViewAttached>(); qmlRegisterType<QQuickSwitch>(uri, 2, 0, "Switch"); qmlRegisterType<QQuickSwitchDelegate>(uri, 2, 0, "SwitchDelegate"); qmlRegisterType<QQuickTabBar>(uri, 2, 0, "TabBar"); qmlRegisterType<QQuickTabButton>(uri, 2, 0, "TabButton"); - qmlRegisterType<QQuickTextAreaAttached>(); qmlRegisterType<QQuickTextArea>(uri, 2, 0, "TextArea"); + qmlRegisterType<QQuickTextAreaAttached>(); qmlRegisterType<QQuickTextField>(uri, 2, 0, "TextField"); qmlRegisterType<QQuickToolBar>(uri, 2, 0, "ToolBar"); qmlRegisterType<QQuickToolButton>(uri, 2, 0, "ToolButton"); - qmlRegisterType<QQuickToolTipAttached>(); qmlRegisterType<QQuickToolTip>(uri, 2, 0, "ToolTip"); + qmlRegisterType<QQuickToolTipAttached>(); #if QT_CONFIG(quick_listview) && QT_CONFIG(quick_pathview) qmlRegisterType<QQuickTumblerAttached>(); qmlRegisterType<QQuickTumbler>(uri, 2, 0, "Tumbler"); @@ -209,10 +234,10 @@ void QtQuickTemplates2Plugin::registerTypes(const char *uri) // NOTE: register the latest revisions of all template/control base classes to // make revisioned properties available to their subclasses (synced with Qt 5.7) qmlRegisterRevision<QQuickItem, 7>(uri, 2, 0); - qmlRegisterRevision<QQuickWindow, 2>(uri, 2, 0); qmlRegisterRevision<QQuickText, 6>(uri, 2, 0); qmlRegisterRevision<QQuickTextInput, 7>(uri, 2, 0); qmlRegisterRevision<QQuickTextEdit, 7>(uri, 2, 0); + qmlRegisterRevision<QQuickWindow, 2>(uri, 2, 0); qmlRegisterRevision<QWindow, 3>(uri, 2, 0); // QtQuick.Templates 2.1 (new types and revisions in Qt 5.8) @@ -262,6 +287,26 @@ void QtQuickTemplates2Plugin::registerTypes(const char *uri) qmlRegisterRevision<QQuickText, 9>(uri, 2, 2); qmlRegisterRevision<QQuickTextInput, 9>(uri, 2, 2); qmlRegisterRevision<QQuickWindowQmlImpl, 2>(uri, 2, 2); + + // QtQuick.Templates 2.3 (new types and revisions in Qt 5.10) + qmlRegisterType<QQuickAbstractButton, 3>(uri, 2, 3, "AbstractButton"); + qmlRegisterType<QQuickAction>(uri, 2, 3, "Action"); + qmlRegisterType<QQuickActionGroup>(uri, 2, 3, "ActionGroup"); + qmlRegisterType<QQuickApplicationWindow, 3>(uri, 2, 3, "ApplicationWindow"); + qmlRegisterType<QQuickButtonGroup, 3>(uri, 2, 3, "ButtonGroup"); + qmlRegisterType<QQuickControl, 3>(uri, 2, 3, "Control"); + qmlRegisterType<QQuickContainer, 3>(uri, 2, 3, "Container"); + qmlRegisterType<QQuickDialog, 3>(uri, 2, 3, "Dialog"); + qmlRegisterType<QQuickDialogButtonBox>(uri, 2, 3, "DialogButtonBox"); + qRegisterMetaType<QQuickIcon>(); + qmlRegisterType<QQuickMenu, 3>(uri, 2, 3, "Menu"); + qmlRegisterType<QQuickMenuItem, 3>(uri, 2, 3, "MenuItem"); + qmlRegisterType<QQuickPopup, 3>(uri, 2, 3, "Popup"); + qmlRegisterType<QQuickRangeSlider, 3>(uri, 2, 3, "RangeSlider"); + qmlRegisterType<QQuickScrollBar, 3>(uri, 2, 3, "ScrollBar"); + qmlRegisterType<QQuickScrollIndicator, 3>(uri, 2, 3, "ScrollIndicator"); + qmlRegisterType<QQuickSlider, 3>(uri, 2, 3, "Slider"); + qmlRegisterType<QQuickSpinBox, 3>(uri, 2, 3, "SpinBox"); } QT_END_NAMESPACE diff --git a/src/imports/templates/templates.pro b/src/imports/templates/templates.pro index 28207807..4ff0a76e 100644 --- a/src/imports/templates/templates.pro +++ b/src/imports/templates/templates.pro @@ -1,6 +1,6 @@ TARGET = qtquicktemplates2plugin TARGETPATH = QtQuick/Templates.2 -IMPORT_VERSION = 2.2 +IMPORT_VERSION = 2.3 QT += qml quick QT_PRIVATE += core-private gui-private qml-private quick-private quicktemplates2-private @@ -10,7 +10,11 @@ DEFINES += QT_NO_CAST_TO_ASCII QT_NO_CAST_FROM_ASCII OTHER_FILES += \ qmldir +HEADERS += \ + $$PWD/qquicktemplates2valuetypeprovider_p.h + SOURCES += \ + $$PWD/qquicktemplates2valuetypeprovider.cpp \ $$PWD/qtquicktemplates2plugin.cpp CONFIG += no_cxx_module diff --git a/src/quickcontrols2/configure.json b/src/quickcontrols2/configure.json index 9384a52b..0f26d39c 100644 --- a/src/quickcontrols2/configure.json +++ b/src/quickcontrols2/configure.json @@ -3,6 +3,7 @@ "commandline": { "options": { + "style-fusion": { "type": "boolean", "name": "quickcontrols2-fusion" }, "style-material": { "type": "boolean", "name": "quickcontrols2-material" }, "style-universal": { "type": "boolean", "name": "quickcontrols2-universal" } } @@ -13,6 +14,13 @@ "label": "Default", "output": [ "privateFeature" ] }, + "quickcontrols2-fusion": { + "label": "Fusion", + "purpose": "Provides the platform agnostic desktop-oriented Fusion style.", + "section": "Quick Controls 2", + "condition": "features.quickcontrols2-default", + "output": [ "privateFeature" ] + }, "quickcontrols2-material": { "label": "Material", "purpose": "Provides a style based on the Material Design guidelines.", @@ -36,7 +44,7 @@ { "message": "Styles", "type": "featureList", - "args": "quickcontrols2-default quickcontrols2-material quickcontrols2-universal" + "args": "quickcontrols2-default quickcontrols2-fusion quickcontrols2-material quickcontrols2-universal" } ] } diff --git a/src/quickcontrols2/qquickattachedobject.cpp b/src/quickcontrols2/qquickattachedobject.cpp new file mode 100644 index 00000000..bada982e --- /dev/null +++ b/src/quickcontrols2/qquickattachedobject.cpp @@ -0,0 +1,249 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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 "qquickattachedobject_p.h" + +#include <QtQuick/qquickwindow.h> +#include <QtQuick/private/qquickitem_p.h> +#include <QtQuickTemplates2/private/qquickpopup_p.h> + +QT_BEGIN_NAMESPACE + +static QQuickAttachedObject *attachedObject(const QMetaObject *type, QObject *object, bool create = false) +{ + if (!object) + return nullptr; + int idx = -1; + return qobject_cast<QQuickAttachedObject *>(qmlAttachedPropertiesObject(&idx, object, type, create)); +} + +static QQuickAttachedObject *findAttachedParent(const QMetaObject *type, QObject *object) +{ + QQuickItem *item = qobject_cast<QQuickItem *>(object); + if (item) { + // lookup parent items and popups + QQuickItem *parent = item->parentItem(); + while (parent) { + QQuickAttachedObject *attached = attachedObject(type, parent); + if (attached) + return attached; + + QQuickPopup *popup = qobject_cast<QQuickPopup *>(parent->parent()); + if (popup) + return attachedObject(type, popup); + + parent = parent->parentItem(); + } + + // fallback to item's window + QQuickAttachedObject *attached = attachedObject(type, item->window()); + if (attached) + return attached; + } else { + // lookup popup's window + QQuickPopup *popup = qobject_cast<QQuickPopup *>(object); + if (popup) + return attachedObject(type, popup->popupItem()->window()); + } + + // lookup parent window + QQuickWindow *window = qobject_cast<QQuickWindow *>(object); + if (window) { + QQuickWindow *parentWindow = qobject_cast<QQuickWindow *>(window->parent()); + if (parentWindow) { + QQuickAttachedObject *attached = attachedObject(type, window); + if (attached) + return attached; + } + } + + // fallback to engine (global) + if (object) { + QQmlEngine *engine = qmlEngine(object); + if (engine) { + QByteArray name = QByteArray("_q_") + type->className(); + QQuickAttachedObject *attached = engine->property(name).value<QQuickAttachedObject *>(); + if (!attached) { + attached = attachedObject(type, engine, true); + engine->setProperty(name, QVariant::fromValue(attached)); + } + return attached; + } + } + + return nullptr; +} + +static QList<QQuickAttachedObject *> findAttachedChildren(const QMetaObject *type, QObject *object) +{ + QList<QQuickAttachedObject *> children; + + QQuickItem *item = qobject_cast<QQuickItem *>(object); + if (!item) { + QQuickWindow *window = qobject_cast<QQuickWindow *>(object); + if (window) { + item = window->contentItem(); + + const auto windowChildren = window->children(); + for (QObject *child : windowChildren) { + QQuickWindow *childWindow = qobject_cast<QQuickWindow *>(child); + if (childWindow) { + QQuickAttachedObject *attached = attachedObject(type, childWindow); + if (attached) + children += attached; + } + } + } + } + + if (item) { + const auto childItems = item->childItems(); + for (QQuickItem *child : childItems) { + QQuickAttachedObject *attached = attachedObject(type, child); + if (attached) + children += attached; + else + children += findAttachedChildren(type, child); + } + } + + return children; +} + +static QQuickItem *findAttachedItem(QObject *parent) +{ + QQuickItem *item = qobject_cast<QQuickItem *>(parent); + if (!item) { + QQuickPopup *popup = qobject_cast<QQuickPopup *>(parent); + if (popup) + item = popup->popupItem(); + } + return item; +} + +QQuickAttachedObject::QQuickAttachedObject(QObject *parent) : QObject(parent) +{ + attachTo(parent); +} + +QQuickAttachedObject::QQuickAttachedObject(QObjectPrivate &dd, QObject *parent) + : QObject(dd, parent) +{ + attachTo(parent); +} + +QQuickAttachedObject::~QQuickAttachedObject() +{ + detachFrom(parent()); + setAttachedParent(nullptr); +} + +QList<QQuickAttachedObject *> QQuickAttachedObject::attachedChildren() const +{ + return m_attachedChildren; +} + +QQuickAttachedObject *QQuickAttachedObject::attachedParent() const +{ + return m_attachedParent; +} + +void QQuickAttachedObject::setAttachedParent(QQuickAttachedObject *parent) +{ + if (m_attachedParent != parent) { + QQuickAttachedObject *oldParent = m_attachedParent; + if (m_attachedParent) + m_attachedParent->m_attachedChildren.removeOne(this); + m_attachedParent = parent; + if (parent) + parent->m_attachedChildren.append(this); + attachedParentChange(parent, oldParent); + } +} + +void QQuickAttachedObject::init() +{ + QQuickAttachedObject *attachedParent = findAttachedParent(metaObject(), parent()); + if (attachedParent) + setAttachedParent(attachedParent); + + const QList<QQuickAttachedObject *> attachedChildren = findAttachedChildren(metaObject(), parent()); + for (QQuickAttachedObject *child : attachedChildren) + child->setAttachedParent(this); +} + +void QQuickAttachedObject::attachedParentChange(QQuickAttachedObject *newParent, QQuickAttachedObject *oldParent) +{ + Q_UNUSED(newParent); + Q_UNUSED(oldParent); +} + +void QQuickAttachedObject::itemWindowChanged(QQuickWindow *window) +{ + QQuickAttachedObject *attachedParent = nullptr; + QQuickItem *item = qobject_cast<QQuickItem *>(sender()); + if (item) + attachedParent = findAttachedParent(metaObject(), item); + if (!attachedParent) + attachedParent = attachedObject(metaObject(), window); + setAttachedParent(attachedParent); +} + +void QQuickAttachedObject::itemParentChanged(QQuickItem *item, QQuickItem *parent) +{ + Q_UNUSED(parent); + setAttachedParent(findAttachedParent(metaObject(), item)); +} + +void QQuickAttachedObject::attachTo(QObject *object) +{ + QQuickItem *item = findAttachedItem(object); + if (item) { + connect(item, &QQuickItem::windowChanged, this, &QQuickAttachedObject::itemWindowChanged); + QQuickItemPrivate::get(item)->addItemChangeListener(this, QQuickItemPrivate::Parent); + } +} + +void QQuickAttachedObject::detachFrom(QObject *object) +{ + QQuickItem *item = findAttachedItem(object); + if (item) { + disconnect(item, &QQuickItem::windowChanged, this, &QQuickAttachedObject::itemWindowChanged); + QQuickItemPrivate::get(item)->removeItemChangeListener(this, QQuickItemPrivate::Parent); + } +} + +QT_END_NAMESPACE diff --git a/src/quickcontrols2/qquickstyleattached_p.h b/src/quickcontrols2/qquickattachedobject_p.h index ed5a5417..5d4194ef 100644 --- a/src/quickcontrols2/qquickstyleattached_p.h +++ b/src/quickcontrols2/qquickattachedobject_p.h @@ -34,8 +34,8 @@ ** ****************************************************************************/ -#ifndef QQUICKSTYLEATTACHED_P_H -#define QQUICKSTYLEATTACHED_P_H +#ifndef QQUICKATTACHEDOBJECT_P_H +#define QQUICKATTACHEDOBJECT_P_H // // W A R N I N G @@ -52,43 +52,44 @@ #include <QtCore/qlist.h> #include <QtCore/qobject.h> #include <QtCore/qpointer.h> -#include <QtCore/qsharedpointer.h> #include <QtQuick/private/qquickitemchangelistener_p.h> #include <QtQuickControls2/private/qtquickcontrols2global_p.h> QT_BEGIN_NAMESPACE -class QSettings; class QQuickWindow; -class Q_QUICKCONTROLS2_PRIVATE_EXPORT QQuickStyleAttached : public QObject, public QQuickItemChangeListener +class Q_QUICKCONTROLS2_PRIVATE_EXPORT QQuickAttachedObject : public QObject, public QQuickItemChangeListener { Q_OBJECT public: - explicit QQuickStyleAttached(QObject *parent = nullptr); - ~QQuickStyleAttached(); + explicit QQuickAttachedObject(QObject *parent = nullptr); + ~QQuickAttachedObject(); - static QSharedPointer<QSettings> settings(const QString &group = QString()); + QList<QQuickAttachedObject *> attachedChildren() const; -protected: - void init(); + QQuickAttachedObject *attachedParent() const; + void setAttachedParent(QQuickAttachedObject *parent); - QList<QQuickStyleAttached *> childStyles() const; +protected: + QQuickAttachedObject(QObjectPrivate &dd, QObject *parent = nullptr); - QQuickStyleAttached *parentStyle() const; - void setParentStyle(QQuickStyleAttached *style); + void init(); - virtual void parentStyleChange(QQuickStyleAttached *newParent, QQuickStyleAttached *oldParent); + virtual void attachedParentChange(QQuickAttachedObject *newParent, QQuickAttachedObject *oldParent); void itemWindowChanged(QQuickWindow *window); void itemParentChanged(QQuickItem *item, QQuickItem *parent) override; private: - QList<QQuickStyleAttached *> m_childStyles; - QPointer<QQuickStyleAttached> m_parentStyle; + void attachTo(QObject *object); + void detachFrom(QObject *object); + + QList<QQuickAttachedObject *> m_attachedChildren; + QPointer<QQuickAttachedObject> m_attachedParent; }; QT_END_NAMESPACE -#endif // QQUICKSTYLEATTACHED_P_H +#endif // QQUICKATTACHEDOBJECT_P_H diff --git a/src/quickcontrols2/qquickcolor.cpp b/src/quickcontrols2/qquickcolor.cpp new file mode 100644 index 00000000..bede2a88 --- /dev/null +++ b/src/quickcontrols2/qquickcolor.cpp @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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 "qquickcolor_p.h" + +QT_BEGIN_NAMESPACE + +QQuickColor::QQuickColor(QObject *parent) : + QObject(parent) +{ +} + +QColor QQuickColor::transparent(const QColor &color, qreal opacity) const +{ + return QColor(color.red(), color.green(), color.blue(), qBound(0.0, opacity, 1.0) * 255); +} + +QT_END_NAMESPACE diff --git a/src/quickcontrols2/qquickcolorimageprovider_p.h b/src/quickcontrols2/qquickcolor_p.h index 4b7a34b9..85578359 100644 --- a/src/quickcontrols2/qquickcolorimageprovider_p.h +++ b/src/quickcontrols2/qquickcolor_p.h @@ -34,8 +34,8 @@ ** ****************************************************************************/ -#ifndef QQUICKCOLORIMAGEPROVIDER_P_H -#define QQUICKCOLORIMAGEPROVIDER_P_H +#ifndef QQUICKCOLOR_P_H +#define QQUICKCOLOR_P_H // // W A R N I N G @@ -48,22 +48,22 @@ // We mean it. // -#include <QtQuick/qquickimageprovider.h> +#include <QtCore/qobject.h> +#include <QtGui/qcolor.h> #include <QtQuickControls2/private/qtquickcontrols2global_p.h> QT_BEGIN_NAMESPACE -class Q_QUICKCONTROLS2_PRIVATE_EXPORT QQuickColorImageProvider : public QQuickImageProvider +class Q_QUICKCONTROLS2_PRIVATE_EXPORT QQuickColor : public QObject { -public: - QQuickColorImageProvider(const QString &path); + Q_OBJECT - QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize) override; +public: + explicit QQuickColor(QObject *parent = nullptr); -private: - QString m_path; + Q_INVOKABLE QColor transparent(const QColor &color, qreal opacity) const; }; QT_END_NAMESPACE -#endif // QQUICKOCOLORIMAGEPROVIDER_P_H +#endif // QQUICKCOLOR_P_H diff --git a/src/quickcontrols2/qquickcolorimageprovider.cpp b/src/quickcontrols2/qquickcolorimage.cpp index a6e941b3..430ba6ea 100644 --- a/src/quickcontrols2/qquickcolorimageprovider.cpp +++ b/src/quickcontrols2/qquickcolorimage.cpp @@ -34,47 +34,46 @@ ** ****************************************************************************/ -#include "qquickcolorimageprovider_p.h" +#include "qquickcolorimage_p.h" -#include <QtCore/qdebug.h> -#include <QtGui/qpainter.h> -#include <QtGui/qguiapplication.h> -#include <QtGui/qscreen.h> -#include <QtGui/qicon.h> +#include <QtQuick/private/qquickimagebase_p_p.h> QT_BEGIN_NAMESPACE -QQuickColorImageProvider::QQuickColorImageProvider(const QString &path) - : QQuickImageProvider(Image), m_path(path) +QQuickColorImage::QQuickColorImage(QQuickItem *parent) + : QQuickImage(parent), m_color(Qt::transparent) { } -QImage QQuickColorImageProvider::requestImage(const QString &id, QSize *size, const QSize &requestedSize) +QColor QQuickColorImage::color() const { - Q_UNUSED(requestedSize); - - int sep = id.indexOf(QLatin1Char('/')); - const QStringRef name = id.leftRef(sep); - qreal dpr = qApp->primaryScreen()->devicePixelRatio(); - QString file = qt_findAtNxFile(m_path + QLatin1Char('/') + name + QLatin1String(".png"), dpr); + return m_color; +} - QImage image(file); - if (image.isNull()) { - qWarning() << "QQuickColorImageProvider: unknown id:" << id; - return QImage(); - } +void QQuickColorImage::setColor(const QColor &color) +{ + if (m_color == color) + return; - if (size) - *size = image.size(); + m_color = color; + if (isComponentComplete()) + load(); + emit colorChanged(); +} - const QString color = id.mid(sep + 1); - if (!color.isEmpty()) { - QPainter painter(&image); - painter.setCompositionMode(QPainter::CompositionMode_SourceIn); - painter.fillRect(image.rect(), QColor(color)); +void QQuickColorImage::pixmapChange() +{ + QQuickImage::pixmapChange(); + if (m_color.alpha() > 0) { + QQuickImageBasePrivate *d = static_cast<QQuickImageBasePrivate *>(QQuickItemPrivate::get(this)); + QImage image = d->pix.image(); + if (!image.isNull()) { + QPainter painter(&image); + painter.setCompositionMode(QPainter::CompositionMode_SourceIn); + painter.fillRect(image.rect(), m_color); + d->pix.setImage(image); + } } - - return image; } QT_END_NAMESPACE diff --git a/src/quickcontrols2/qquickcolorimage_p.h b/src/quickcontrols2/qquickcolorimage_p.h new file mode 100644 index 00000000..8b0f769d --- /dev/null +++ b/src/quickcontrols2/qquickcolorimage_p.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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 QQUICKCOLORIMAGE_P_H +#define QQUICKCOLORIMAGE_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 <QtGui/qcolor.h> +#include <QtQuick/private/qquickimage_p.h> +#include <QtQuickControls2/private/qtquickcontrols2global_p.h> + +QT_BEGIN_NAMESPACE + +class Q_QUICKCONTROLS2_PRIVATE_EXPORT QQuickColorImage : public QQuickImage +{ + Q_OBJECT + Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged FINAL) + +public: + explicit QQuickColorImage(QQuickItem *parent = nullptr); + + QColor color() const; + void setColor(const QColor &color); + +Q_SIGNALS: + void colorChanged(); + +protected: + void pixmapChange() override; + +private: + QColor m_color; +}; + +QT_END_NAMESPACE + +#endif // QQUICKCOLORIMAGE_P_H diff --git a/src/quickcontrols2/qquickiconimage.cpp b/src/quickcontrols2/qquickiconimage.cpp new file mode 100644 index 00000000..c628c7ae --- /dev/null +++ b/src/quickcontrols2/qquickiconimage.cpp @@ -0,0 +1,221 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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 "qquickiconimage_p.h" +#include "qquickiconimage_p_p.h" + +#include <QtCore/qmath.h> +#include <QtQuick/private/qquickimagebase_p_p.h> + +QT_BEGIN_NAMESPACE + +QQuickIconImagePrivate::QQuickIconImagePrivate() + : color(Qt::transparent), + updatingIcon(false), + isThemeIcon(false), + updatingFillMode(false) +{ +} + +bool QQuickIconImagePrivate::updateDevicePixelRatio(qreal targetDevicePixelRatio) +{ + if (isThemeIcon) { + devicePixelRatio = calculateDevicePixelRatio(); + return true; + } + + return QQuickImagePrivate::updateDevicePixelRatio(targetDevicePixelRatio); +} + +void QQuickIconImagePrivate::updateIcon() +{ + Q_Q(QQuickIconImage); + // Both geometryChanged() and QQuickImageBase::sourceSizeChanged() + // (which we connect to updateIcon() in the constructor) can be called as a result + // of updateIcon() changing the various sizes, so we must check that we're not recursing. + if (updatingIcon) + return; + + updatingIcon = true; + + QSize size = sourcesize; + // If no size is specified for theme icons, it will use the smallest available size. + if (size.width() <= 0) + size.setWidth(q->width()); + if (size.height() <= 0) + size.setHeight(q->height()); + + const qreal dpr = calculateDevicePixelRatio(); + const QIconLoaderEngineEntry *entry = QIconLoaderEngine::entryForSize(icon, size * dpr, qCeil(dpr)); + + if (entry) { + QQmlContext *context = qmlContext(q); + const QUrl entryUrl = QUrl::fromLocalFile(entry->filename); + url = context ? context->resolvedUrl(entryUrl) : entryUrl; + isThemeIcon = true; + } else { + url = source; + isThemeIcon = false; + } + q->load(); + + updatingIcon = false; +} + +void QQuickIconImagePrivate::updateFillMode() +{ + Q_Q(QQuickIconImage); + // If we start with a sourceSize of 28x28 and then set sourceSize.width to 24, the fillMode + // will change to PreserveAspectFit (because pixmapSize.width() > width()), which causes the + // pixmap to be reloaded at its original size of 28x28, which causes the fillMode to change + // to Pad (because pixmapSize.width() <= width()), and so on. + if (updatingFillMode) + return; + + updatingFillMode = true; + + const QSize pixmapSize = QSize(pix.width(), pix.height()) / calculateDevicePixelRatio(); + if (pixmapSize.width() > q->width() || pixmapSize.height() > q->height()) + q->setFillMode(QQuickImage::PreserveAspectFit); + else + q->setFillMode(QQuickImage::Pad); + + updatingFillMode = false; +} + +qreal QQuickIconImagePrivate::calculateDevicePixelRatio() const +{ + Q_Q(const QQuickIconImage); + return q->window() ? q->window()->effectiveDevicePixelRatio() : qApp->devicePixelRatio(); +} + +QQuickIconImage::QQuickIconImage(QQuickItem *parent) + : QQuickImage(*(new QQuickIconImagePrivate), parent) +{ + Q_D(QQuickIconImage); + setFillMode(Pad); + QObjectPrivate::connect(this, &QQuickImageBase::sourceSizeChanged, d, &QQuickIconImagePrivate::updateIcon); +} + +QString QQuickIconImage::name() const +{ + Q_D(const QQuickIconImage); + return d->icon.iconName; +} + +void QQuickIconImage::setName(const QString &name) +{ + Q_D(QQuickIconImage); + if (d->icon.iconName == name) + return; + + d->icon = QIconLoader::instance()->loadIcon(name); + if (isComponentComplete()) + d->updateIcon(); + emit nameChanged(); +} + +QColor QQuickIconImage::color() const +{ + Q_D(const QQuickIconImage); + return d->color; +} + +void QQuickIconImage::setColor(const QColor &color) +{ + Q_D(QQuickIconImage); + if (d->color == color) + return; + + d->color = color; + if (isComponentComplete()) + d->updateIcon(); + emit colorChanged(); +} + +void QQuickIconImage::setSource(const QUrl &source) +{ + Q_D(QQuickIconImage); + if (d->source == source) + return; + + d->source = source; + if (isComponentComplete()) + d->updateIcon(); + emit sourceChanged(source); +} + +void QQuickIconImage::componentComplete() +{ + Q_D(QQuickIconImage); + QQuickImage::componentComplete(); + d->updateIcon(); +} + +void QQuickIconImage::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) +{ + Q_D(QQuickIconImage); + QQuickImage::geometryChanged(newGeometry, oldGeometry); + if (isComponentComplete() && newGeometry.size() != oldGeometry.size()) + d->updateIcon(); +} + +void QQuickIconImage::itemChange(ItemChange change, const ItemChangeData &value) +{ + Q_D(QQuickIconImage); + if (change == ItemDevicePixelRatioHasChanged) + d->updateIcon(); + QQuickImage::itemChange(change, value); +} + +void QQuickIconImage::pixmapChange() +{ + Q_D(QQuickIconImage); + QQuickImage::pixmapChange(); + d->updateFillMode(); + + if (d->color.alpha() > 0) { + QImage image = d->pix.image(); + if (!image.isNull()) { + QPainter painter(&image); + painter.setCompositionMode(QPainter::CompositionMode_SourceIn); + painter.fillRect(image.rect(), d->color); + d->pix.setImage(image); + } + } +} + +QT_END_NAMESPACE diff --git a/src/quickcontrols2/qquickiconimage_p.h b/src/quickcontrols2/qquickiconimage_p.h new file mode 100644 index 00000000..b1af767e --- /dev/null +++ b/src/quickcontrols2/qquickiconimage_p.h @@ -0,0 +1,94 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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 QQUICKICONIMAGE_P_H +#define QQUICKICONIMAGE_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/private/qquickimage_p.h> +#include <QtQuickControls2/private/qtquickcontrols2global_p.h> + +QT_BEGIN_NAMESPACE + +class QQuickIconImagePrivate; + +class Q_QUICKCONTROLS2_PRIVATE_EXPORT QQuickIconImage : public QQuickImage +{ + Q_OBJECT + Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged FINAL) + Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged FINAL) + +public: + explicit QQuickIconImage(QQuickItem *parent = nullptr); + + QString name() const; + void setName(const QString &name); + + QColor color() const; + void setColor(const QColor &color); + + void setSource(const QUrl &url) override; + +Q_SIGNALS: + void nameChanged(); + void colorChanged(); + +protected: + void componentComplete() override; + void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override; + void itemChange(ItemChange change, const ItemChangeData &value) override; + void pixmapChange() override; + +private: + Q_DISABLE_COPY(QQuickIconImage) + Q_DECLARE_PRIVATE(QQuickIconImage) +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QQuickIconImage) + +#endif // QQUICKICONIMAGE_P_H diff --git a/src/quickcontrols2/qquickiconimage_p_p.h b/src/quickcontrols2/qquickiconimage_p_p.h new file mode 100644 index 00000000..8e8012bf --- /dev/null +++ b/src/quickcontrols2/qquickiconimage_p_p.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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 QQUICKICONIMAGE_P_P_H +#define QQUICKICONIMAGE_P_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/private/qquickimage_p_p.h> +#include <QtQuickControls2/private/qtquickcontrols2global_p.h> +#include <QtGui/private/qiconloader_p.h> + +QT_BEGIN_NAMESPACE + +class Q_QUICKCONTROLS2_PRIVATE_EXPORT QQuickIconImagePrivate : public QQuickImagePrivate +{ + Q_DECLARE_PUBLIC(QQuickIconImage) + +public: + QQuickIconImagePrivate(); + + void updateIcon(); + void updateFillMode(); + qreal calculateDevicePixelRatio() const; + bool updateDevicePixelRatio(qreal targetDevicePixelRatio) override; + + QUrl source; + QColor color; + QThemeIconInfo icon; + bool updatingIcon; + bool isThemeIcon; + bool updatingFillMode; +}; + +QT_END_NAMESPACE + +#endif // QQUICKICONIMAGE_P_P_H diff --git a/src/quickcontrols2/qquickiconlabel.cpp b/src/quickcontrols2/qquickiconlabel.cpp new file mode 100644 index 00000000..06d74d43 --- /dev/null +++ b/src/quickcontrols2/qquickiconlabel.cpp @@ -0,0 +1,634 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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 "qquickiconlabel_p.h" +#include "qquickiconlabel_p_p.h" +#include "qquickiconimage_p.h" + +#include <QtGui/private/qguiapplication_p.h> +#include <QtQuick/private/qquickitem_p.h> +#include <QtQuick/private/qquicktext_p.h> + +QT_BEGIN_NAMESPACE + +static void beginClass(QQuickItem *item) +{ + if (QQmlParserStatus *parserStatus = qobject_cast<QQmlParserStatus *>(item)) + parserStatus->classBegin(); +} + +static void completeComponent(QQuickItem *item) +{ + if (QQmlParserStatus *parserStatus = qobject_cast<QQmlParserStatus *>(item)) + parserStatus->componentComplete(); +} + +QQuickIconLabelPrivate::QQuickIconLabelPrivate() + : mirrored(false), + display(QQuickIconLabel::TextBesideIcon), + alignment(Qt::AlignCenter), + spacing(0), + topPadding(0), + leftPadding(0), + rightPadding(0), + bottomPadding(0), + image(nullptr), + label(nullptr) +{ +} + +bool QQuickIconLabelPrivate::hasIcon() const +{ + return display != QQuickIconLabel::TextOnly && !icon.isEmpty(); +} + +bool QQuickIconLabelPrivate::hasText() const +{ + return display != QQuickIconLabel::IconOnly && !text.isEmpty(); +} + +bool QQuickIconLabelPrivate::createImage() +{ + Q_Q(QQuickIconLabel); + if (image) + return false; + + image = new QQuickIconImage(q); + watchChanges(image); + beginClass(image); + image->setObjectName(QStringLiteral("image")); + image->setName(icon.name()); + image->setSource(icon.source()); + image->setSourceSize(QSize(icon.width(), icon.height())); + image->setColor(icon.color()); + QQmlEngine::setContextForObject(image, qmlContext(q)); + if (componentComplete) + completeComponent(image); + return true; +} + +bool QQuickIconLabelPrivate::destroyImage() +{ + if (!image) + return false; + + unwatchChanges(image); + delete image; + image = nullptr; + return true; +} + +bool QQuickIconLabelPrivate::updateImage() +{ + if (!hasIcon()) + return destroyImage(); + return createImage(); +} + +void QQuickIconLabelPrivate::syncImage() +{ + if (!image || icon.isEmpty()) + return; + + image->setName(icon.name()); + image->setSource(icon.source()); + image->setSourceSize(QSize(icon.width(), icon.height())); + image->setColor(icon.color()); +} + +void QQuickIconLabelPrivate::updateOrSyncImage() +{ + if (updateImage()) { + if (componentComplete) { + updateImplicitSize(); + layout(); + } + } else { + syncImage(); + } +} + +bool QQuickIconLabelPrivate::createLabel() +{ + Q_Q(QQuickIconLabel); + if (label) + return false; + + label = new QQuickText(q); + watchChanges(label); + beginClass(label); + label->setObjectName(QStringLiteral("label")); + label->setFont(font); + label->setColor(color); + label->setElideMode(QQuickText::ElideRight); + label->setText(text); + if (componentComplete) + completeComponent(label); + return true; +} + +bool QQuickIconLabelPrivate::destroyLabel() +{ + if (!label) + return false; + + unwatchChanges(label); + delete label; + label = nullptr; + return true; +} + +bool QQuickIconLabelPrivate::updateLabel() +{ + if (!hasText()) + return destroyLabel(); + return createLabel(); +} + +void QQuickIconLabelPrivate::syncLabel() +{ + if (!label) + return; + + label->setText(text); +} + +void QQuickIconLabelPrivate::updateOrSyncLabel() +{ + if (updateLabel()) { + if (componentComplete) { + updateImplicitSize(); + layout(); + } + } else { + syncLabel(); + } +} + +void QQuickIconLabelPrivate::updateImplicitSize() +{ + Q_Q(QQuickIconLabel); + const bool showIcon = image && hasIcon(); + const bool showText = label && hasText(); + const qreal horizontalPadding = leftPadding + rightPadding; + const qreal verticalPadding = topPadding + bottomPadding; + const qreal iconImplicitWidth = showIcon ? image->implicitWidth() : 0; + const qreal iconImplicitHeight = showIcon ? image->implicitHeight() : 0; + const qreal textImplicitWidth = showText ? label->implicitWidth() : 0; + const qreal textImplicitHeight = showText ? label->implicitHeight() : 0; + const qreal effectiveSpacing = showText && showIcon && image->implicitWidth() > 0 ? spacing : 0; + const qreal implicitWidth = display == QQuickIconLabel::TextBesideIcon ? iconImplicitWidth + textImplicitWidth + effectiveSpacing + : qMax(iconImplicitWidth, textImplicitWidth); + const qreal implicitHeight = display == QQuickIconLabel::TextUnderIcon ? iconImplicitHeight + textImplicitHeight + effectiveSpacing + : qMax(iconImplicitHeight, textImplicitHeight); + q->setImplicitSize(implicitWidth + horizontalPadding, implicitHeight + verticalPadding); +} + +// adapted from QStyle::alignedRect() +static QRectF alignedRect(bool mirrored, Qt::Alignment alignment, const QSizeF &size, const QRectF &rectangle) +{ + alignment = QGuiApplicationPrivate::visualAlignment(mirrored ? Qt::RightToLeft : Qt::LeftToRight, alignment); + qreal x = rectangle.x(); + qreal y = rectangle.y(); + const qreal w = size.width(); + const qreal h = size.height(); + if ((alignment & Qt::AlignVCenter) == Qt::AlignVCenter) + y += rectangle.height() / 2 - h / 2; + else if ((alignment & Qt::AlignBottom) == Qt::AlignBottom) + y += rectangle.height() - h; + if ((alignment & Qt::AlignRight) == Qt::AlignRight) + x += rectangle.width() - w; + else if ((alignment & Qt::AlignHCenter) == Qt::AlignHCenter) + x += rectangle.width() / 2 - w / 2; + return QRectF(x, y, w, h); +} + +void QQuickIconLabelPrivate::layout() +{ + if (!componentComplete) + return; + + const qreal availableWidth = width - leftPadding - rightPadding; + const qreal availableHeight = height - topPadding - bottomPadding; + + switch (display) { + case QQuickIconLabel::IconOnly: + if (image) { + const QRectF iconRect = alignedRect(mirrored, alignment, + QSizeF(qMin(image->implicitWidth(), availableWidth), + qMin(image->implicitHeight(), availableHeight)), + QRectF(leftPadding, topPadding, availableWidth, availableHeight)); + image->setSize(iconRect.size()); + image->setPosition(iconRect.topLeft()); + } + break; + case QQuickIconLabel::TextOnly: + if (label) { + const QRectF textRect = alignedRect(mirrored, alignment, + QSizeF(qMin(label->implicitWidth(), availableWidth), + qMin(label->implicitHeight(), availableHeight)), + QRectF(leftPadding, topPadding, availableWidth, availableHeight)); + label->setSize(textRect.size()); + label->setPosition(textRect.topLeft()); + } + break; + + case QQuickIconLabel::TextUnderIcon: { + // Work out the sizes first, as the positions depend on them. + QSizeF iconSize; + QSizeF textSize; + if (image) { + iconSize.setWidth(qMin(image->implicitWidth(), availableWidth)); + iconSize.setHeight(qMin(image->implicitHeight(), availableHeight)); + } + qreal effectiveSpacing = 0; + if (label) { + if (!iconSize.isEmpty()) + effectiveSpacing = spacing; + textSize.setWidth(qMin(label->implicitWidth(), availableWidth)); + textSize.setHeight(qMin(label->implicitHeight(), availableHeight - iconSize.height() - effectiveSpacing)); + } + + QRectF combinedRect = alignedRect(mirrored, alignment, + QSizeF(qMax(iconSize.width(), textSize.width()), + iconSize.height() + effectiveSpacing + textSize.height()), + QRectF(leftPadding, topPadding, availableWidth, availableHeight)); + if (image) { + QRectF iconRect = alignedRect(mirrored, Qt::AlignHCenter | Qt::AlignTop, iconSize, combinedRect); + image->setSize(iconRect.size()); + image->setPosition(iconRect.topLeft()); + } + if (label) { + QRectF textRect = alignedRect(mirrored, Qt::AlignHCenter | Qt::AlignBottom, textSize, combinedRect); + label->setSize(textRect.size()); + label->setPosition(textRect.topLeft()); + } + break; + } + + case QQuickIconLabel::TextBesideIcon: + default: + // Work out the sizes first, as the positions depend on them. + QSizeF iconSize(0, 0); + QSizeF textSize(0, 0); + if (image) { + iconSize.setWidth(qMin(image->implicitWidth(), availableWidth)); + iconSize.setHeight(qMin(image->implicitHeight(), availableHeight)); + } + qreal effectiveSpacing = 0; + if (label) { + if (!iconSize.isEmpty()) + effectiveSpacing = spacing; + textSize.setWidth(qMin(label->implicitWidth(), availableWidth - iconSize.width() - effectiveSpacing)); + textSize.setHeight(qMin(label->implicitHeight(), availableHeight)); + } + + const QRectF combinedRect = alignedRect(mirrored, alignment, + QSizeF(iconSize.width() + effectiveSpacing + textSize.width(), + qMax(iconSize.height(), textSize.height())), + QRectF(leftPadding, topPadding, availableWidth, availableHeight)); + if (image) { + const QRectF iconRect = alignedRect(mirrored, Qt::AlignLeft | Qt::AlignVCenter, iconSize, combinedRect); + image->setSize(iconRect.size()); + image->setPosition(iconRect.topLeft()); + } + if (label) { + const QRectF textRect = alignedRect(mirrored, Qt::AlignRight | Qt::AlignVCenter, textSize, combinedRect); + label->setSize(textRect.size()); + label->setPosition(textRect.topLeft()); + } + break; + } +} + +static const QQuickItemPrivate::ChangeTypes itemChangeTypes = + QQuickItemPrivate::ImplicitWidth + | QQuickItemPrivate::ImplicitHeight + | QQuickItemPrivate::Destroyed; + +void QQuickIconLabelPrivate::watchChanges(QQuickItem *item) +{ + QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item); + itemPrivate->addItemChangeListener(this, itemChangeTypes); +} + +void QQuickIconLabelPrivate::unwatchChanges(QQuickItem* item) +{ + QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item); + itemPrivate->removeItemChangeListener(this, itemChangeTypes); +} + +void QQuickIconLabelPrivate::itemImplicitWidthChanged(QQuickItem *) +{ + updateImplicitSize(); + layout(); +} + +void QQuickIconLabelPrivate::itemImplicitHeightChanged(QQuickItem *) +{ + updateImplicitSize(); + layout(); +} + +void QQuickIconLabelPrivate::itemDestroyed(QQuickItem *item) +{ + unwatchChanges(item); + if (item == image) + image = nullptr; + else if (item == label) + label = nullptr; +} + +QQuickIconLabel::QQuickIconLabel(QQuickItem *parent) + : QQuickItem(*(new QQuickIconLabelPrivate), parent) +{ +} + +QQuickIconLabel::~QQuickIconLabel() +{ + Q_D(QQuickIconLabel); + if (d->image) + d->unwatchChanges(d->image); + if (d->label) + d->unwatchChanges(d->label); +} + +QQuickIcon QQuickIconLabel::icon() const +{ + Q_D(const QQuickIconLabel); + return d->icon; +} + +void QQuickIconLabel::setIcon(const QQuickIcon &icon) +{ + Q_D(QQuickIconLabel); + if (d->icon == icon) + return; + + d->icon = icon; + d->updateOrSyncImage(); +} + +QString QQuickIconLabel::text() const +{ + Q_D(const QQuickIconLabel); + return d->text; +} + +void QQuickIconLabel::setText(const QString text) +{ + Q_D(QQuickIconLabel); + if (d->text == text) + return; + + d->text = text; + d->updateOrSyncLabel(); +} + +QFont QQuickIconLabel::font() const +{ + Q_D(const QQuickIconLabel); + return d->font; +} + +void QQuickIconLabel::setFont(const QFont &font) +{ + Q_D(QQuickIconLabel); + if (d->font == font) + return; + + d->font = font; + if (d->label) + d->label->setFont(font); +} + +QColor QQuickIconLabel::color() const +{ + Q_D(const QQuickIconLabel); + return d->color; +} + +void QQuickIconLabel::setColor(const QColor &color) +{ + Q_D(QQuickIconLabel); + if (d->color == color) + return; + + d->color = color; + if (d->label) + d->label->setColor(color); +} + +QQuickIconLabel::Display QQuickIconLabel::display() const +{ + Q_D(const QQuickIconLabel); + return d->display; +} + +void QQuickIconLabel::setDisplay(Display display) +{ + Q_D(QQuickIconLabel); + if (d->display == display) + return; + + d->display = display; + d->updateImage(); + d->updateLabel(); + d->updateImplicitSize(); + d->layout(); +} + +qreal QQuickIconLabel::spacing() const +{ + Q_D(const QQuickIconLabel); + return d->spacing; +} + +void QQuickIconLabel::setSpacing(qreal spacing) +{ + Q_D(QQuickIconLabel); + if (qFuzzyCompare(d->spacing, spacing)) + return; + + d->spacing = spacing; + if (d->image && d->label) { + d->updateImplicitSize(); + d->layout(); + } +} + +bool QQuickIconLabel::isMirrored() const +{ + Q_D(const QQuickIconLabel); + return d->mirrored; +} + +void QQuickIconLabel::setMirrored(bool mirrored) +{ + Q_D(QQuickIconLabel); + if (d->mirrored == mirrored) + return; + + d->mirrored = mirrored; + d->layout(); +} + +Qt::Alignment QQuickIconLabel::alignment() const +{ + Q_D(const QQuickIconLabel); + return d->alignment; +} + +void QQuickIconLabel::setAlignment(Qt::Alignment alignment) +{ + Q_D(QQuickIconLabel); + const int valign = alignment & Qt::AlignVertical_Mask; + const int halign = alignment & Qt::AlignHorizontal_Mask; + const uint align = (valign ? valign : Qt::AlignVCenter) | (halign ? halign : Qt::AlignHCenter); + if (d->alignment == align) + return; + + d->alignment = static_cast<Qt::Alignment>(align); + d->layout(); +} + +qreal QQuickIconLabel::topPadding() const +{ + Q_D(const QQuickIconLabel); + return d->topPadding; +} + +void QQuickIconLabel::setTopPadding(qreal padding) +{ + Q_D(QQuickIconLabel); + if (qFuzzyCompare(d->topPadding, padding)) + return; + + d->topPadding = padding; + d->updateImplicitSize(); + d->layout(); +} + +void QQuickIconLabel::resetTopPadding() +{ + setTopPadding(0); +} + +qreal QQuickIconLabel::leftPadding() const +{ + Q_D(const QQuickIconLabel); + return d->leftPadding; +} + +void QQuickIconLabel::setLeftPadding(qreal padding) +{ + Q_D(QQuickIconLabel); + if (qFuzzyCompare(d->leftPadding, padding)) + return; + + d->leftPadding = padding; + d->updateImplicitSize(); + d->layout(); +} + +void QQuickIconLabel::resetLeftPadding() +{ + setLeftPadding(0); +} + +qreal QQuickIconLabel::rightPadding() const +{ + Q_D(const QQuickIconLabel); + return d->rightPadding; +} + +void QQuickIconLabel::setRightPadding(qreal padding) +{ + Q_D(QQuickIconLabel); + if (qFuzzyCompare(d->rightPadding, padding)) + return; + + d->rightPadding = padding; + d->updateImplicitSize(); + d->layout(); +} + +void QQuickIconLabel::resetRightPadding() +{ + setRightPadding(0); +} + +qreal QQuickIconLabel::bottomPadding() const +{ + Q_D(const QQuickIconLabel); + return d->bottomPadding; +} + +void QQuickIconLabel::setBottomPadding(qreal padding) +{ + Q_D(QQuickIconLabel); + if (qFuzzyCompare(d->bottomPadding, padding)) + return; + + d->bottomPadding = padding; + d->updateImplicitSize(); + d->layout(); +} + +void QQuickIconLabel::resetBottomPadding() +{ + setBottomPadding(0); +} + +void QQuickIconLabel::componentComplete() +{ + Q_D(QQuickIconLabel); + if (d->image) + completeComponent(d->image); + if (d->label) + completeComponent(d->label); + QQuickItem::componentComplete(); + d->layout(); +} + +void QQuickIconLabel::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) +{ + Q_D(QQuickIconLabel); + QQuickItem::geometryChanged(newGeometry, oldGeometry); + d->layout(); +} + +QT_END_NAMESPACE diff --git a/src/quickcontrols2/qquickiconlabel_p.h b/src/quickcontrols2/qquickiconlabel_p.h new file mode 100644 index 00000000..df79dbf2 --- /dev/null +++ b/src/quickcontrols2/qquickiconlabel_p.h @@ -0,0 +1,140 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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 QQUICKICONLABEL_P_H +#define QQUICKICONLABEL_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 <QtQuickControls2/private/qtquickcontrols2global_p.h> +#include <QtQuickTemplates2/private/qquickicon_p.h> + +QT_BEGIN_NAMESPACE + +class QQuickIconLabelPrivate; + +class Q_QUICKCONTROLS2_PRIVATE_EXPORT QQuickIconLabel : public QQuickItem +{ + Q_OBJECT + Q_PROPERTY(QQuickIcon icon READ icon WRITE setIcon FINAL) + Q_PROPERTY(QString text READ text WRITE setText FINAL) + Q_PROPERTY(QFont font READ font WRITE setFont FINAL) + Q_PROPERTY(QColor color READ color WRITE setColor FINAL) + Q_PROPERTY(Display display READ display WRITE setDisplay FINAL) + Q_PROPERTY(qreal spacing READ spacing WRITE setSpacing FINAL) + Q_PROPERTY(bool mirrored READ isMirrored WRITE setMirrored FINAL) + Q_PROPERTY(Qt::Alignment alignment READ alignment WRITE setAlignment FINAL) + Q_PROPERTY(qreal topPadding READ topPadding WRITE setTopPadding RESET resetTopPadding FINAL) + Q_PROPERTY(qreal leftPadding READ leftPadding WRITE setLeftPadding RESET resetLeftPadding FINAL) + Q_PROPERTY(qreal rightPadding READ rightPadding WRITE setRightPadding RESET resetRightPadding FINAL) + Q_PROPERTY(qreal bottomPadding READ bottomPadding WRITE setBottomPadding RESET resetBottomPadding FINAL) + +public: + enum Display { + IconOnly, + TextOnly, + TextBesideIcon, + TextUnderIcon + }; + Q_ENUM(Display) + + explicit QQuickIconLabel(QQuickItem *parent = nullptr); + ~QQuickIconLabel(); + + QQuickIcon icon() const; + void setIcon(const QQuickIcon &icon); + + QString text() const; + void setText(const QString text); + + QFont font() const; + void setFont(const QFont &font); + + QColor color() const; + void setColor(const QColor &color); + + Display display() const; + void setDisplay(Display display); + + qreal spacing() const; + void setSpacing(qreal spacing); + + bool isMirrored() const; + void setMirrored(bool mirrored); + + Qt::Alignment alignment() const; + void setAlignment(Qt::Alignment alignment); + + qreal topPadding() const; + void setTopPadding(qreal padding); + void resetTopPadding(); + + qreal leftPadding() const; + void setLeftPadding(qreal padding); + void resetLeftPadding(); + + qreal rightPadding() const; + void setRightPadding(qreal padding); + void resetRightPadding(); + + qreal bottomPadding() const; + void setBottomPadding(qreal padding); + void resetBottomPadding(); + +protected: + void componentComplete() override; + void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override; + +private: + Q_DISABLE_COPY(QQuickIconLabel) + Q_DECLARE_PRIVATE(QQuickIconLabel) +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QQuickIconLabel) + +#endif // QQUICKICONLABEL_P_H diff --git a/src/quickcontrols2/qquickiconlabel_p_p.h b/src/quickcontrols2/qquickiconlabel_p_p.h new file mode 100644 index 00000000..5762187c --- /dev/null +++ b/src/quickcontrols2/qquickiconlabel_p_p.h @@ -0,0 +1,113 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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 QQUICKICONLABEL_P_P_H +#define QQUICKICONLABEL_P_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/private/qquickitem_p.h> +#include <QtQuickControls2/private/qtquickcontrols2global_p.h> +#include <QtQuickControls2/private/qquickiconlabel_p.h> + +QT_BEGIN_NAMESPACE + +class QQuickText; +class QQuickIconImage; + +class QQuickIconLabelPrivate : public QQuickItemPrivate, public QQuickItemChangeListener +{ + Q_DECLARE_PUBLIC(QQuickIconLabel) + +public: + explicit QQuickIconLabelPrivate(); + + bool hasIcon() const; + bool hasText() const; + + bool createImage(); + bool destroyImage(); + bool updateImage(); + void syncImage(); + void updateOrSyncImage(); + + bool createLabel(); + bool destroyLabel(); + bool updateLabel(); + void syncLabel(); + void updateOrSyncLabel(); + + void updateImplicitSize(); + void layout(); + + void watchChanges(QQuickItem *item); + void unwatchChanges(QQuickItem *item); + void setPositioningDirty(); + + bool isLeftToRight() const; + + void itemImplicitWidthChanged(QQuickItem *) override; + void itemImplicitHeightChanged(QQuickItem *) override; + void itemDestroyed(QQuickItem *item) override; + + bool mirrored; + QQuickIconLabel::Display display; + Qt::Alignment alignment; + qreal spacing; + qreal topPadding; + qreal leftPadding; + qreal rightPadding; + qreal bottomPadding; + QFont font; + QColor color; + QString text; + QQuickIcon icon; + QQuickIconImage *image; + QQuickText *label; +}; + +QT_END_NAMESPACE + +#endif // QQUICKICONLABEL_P_P_H diff --git a/src/quickcontrols2/qquickproxytheme_p.h b/src/quickcontrols2/qquickproxytheme_p.h index 04f800f4..2d271e8c 100644 --- a/src/quickcontrols2/qquickproxytheme_p.h +++ b/src/quickcontrols2/qquickproxytheme_p.h @@ -53,7 +53,7 @@ QT_BEGIN_NAMESPACE -class Q_QUICKCONTROLS2_PRIVATE_EXPORT QQuickProxyTheme : public QPlatformTheme +class Q_QUICKCONTROLS2_PRIVATE_EXPORT QQuickProxyTheme : public QPlatformTheme { public: explicit QQuickProxyTheme(QPlatformTheme *theme = nullptr); diff --git a/src/quickcontrols2/qquickstyle.cpp b/src/quickcontrols2/qquickstyle.cpp index 184cbfc7..f154f0ce 100644 --- a/src/quickcontrols2/qquickstyle.cpp +++ b/src/quickcontrols2/qquickstyle.cpp @@ -36,13 +36,17 @@ #include "qquickstyle.h" #include "qquickstyle_p.h" -#include "qquickstyleattached_p.h" #include <QtCore/qdir.h> +#include <QtCore/qfile.h> #include <QtCore/qdebug.h> #include <QtCore/qsettings.h> +#include <QtCore/qfileselector.h> #include <QtCore/qlibraryinfo.h> +#include <QtGui/qcolor.h> +#include <QtGui/qpalette.h> #include <QtGui/private/qguiapplication_p.h> +#include <QtGui/qpa/qplatformtheme.h> #include <QtQml/private/qqmlmetatype_p.h> #include <QtQml/qqmlengine.h> #include <QtQml/qqmlfile.h> @@ -176,7 +180,7 @@ struct QQuickStyleSpec setFallbackStyle(QString::fromLatin1(qgetenv("QT_QUICK_CONTROLS_FALLBACK_STYLE")), "QT_QUICK_CONTROLS_FALLBACK_STYLE"); #if QT_CONFIG(settings) if (style.isEmpty() || fallbackStyle.isEmpty()) { - QSharedPointer<QSettings> settings = QQuickStyleAttached::settings(QStringLiteral("Controls")); + QSharedPointer<QSettings> settings = QQuickStylePrivate::settings(QStringLiteral("Controls")); if (settings) { if (style.isEmpty()) style = settings->value(QStringLiteral("Style")).toString(); @@ -313,6 +317,38 @@ QString QQuickStylePrivate::configFilePath() return styleSpec()->resolveConfigFilePath(); } +QSharedPointer<QSettings> QQuickStylePrivate::settings(const QString &group) +{ +#ifndef QT_NO_SETTINGS + const QString filePath = QQuickStylePrivate::configFilePath(); + if (QFile::exists(filePath)) { + QFileSelector selector; + QSettings *settings = new QSettings(selector.select(filePath), QSettings::IniFormat); + if (!group.isEmpty()) + settings->beginGroup(group); + return QSharedPointer<QSettings>(settings); + } +#endif // QT_NO_SETTINGS + return QSharedPointer<QSettings>(); +} + +static bool qt_is_dark_system_theme() +{ + if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) { + if (const QPalette *systemPalette = theme->palette(QPlatformTheme::SystemPalette)) { + const QColor textColor = systemPalette->color(QPalette::WindowText); + return textColor.red() > 128 && textColor.blue() > 128 && textColor.green() > 128; + } + } + return false; +} + +bool QQuickStylePrivate::isDarkSystemTheme() +{ + static bool dark = qt_is_dark_system_theme(); + return dark; +} + /*! Returns the name of the application style. diff --git a/src/quickcontrols2/qquickstyle_p.h b/src/quickcontrols2/qquickstyle_p.h index 316783c4..b92df3c2 100644 --- a/src/quickcontrols2/qquickstyle_p.h +++ b/src/quickcontrols2/qquickstyle_p.h @@ -49,10 +49,13 @@ // #include <QtCore/qurl.h> +#include <QtCore/qsharedpointer.h> #include <QtQuickControls2/private/qtquickcontrols2global_p.h> QT_BEGIN_NAMESPACE +class QSettings; + class Q_QUICKCONTROLS2_PRIVATE_EXPORT QQuickStylePrivate { public: @@ -62,6 +65,8 @@ public: static void init(const QUrl &baseUrl); static void reset(); static QString configFilePath(); + static QSharedPointer<QSettings> settings(const QString &group = QString()); + static bool isDarkSystemTheme(); }; QT_END_NAMESPACE diff --git a/src/quickcontrols2/qquickstyleattached.cpp b/src/quickcontrols2/qquickstyleattached.cpp deleted file mode 100644 index b9a66169..00000000 --- a/src/quickcontrols2/qquickstyleattached.cpp +++ /dev/null @@ -1,269 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Quick Controls 2 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 "qquickstyleattached_p.h" -#include "qquickstyle_p.h" - -#include <QtCore/qfile.h> -#include <QtCore/qsettings.h> -#include <QtCore/qfileselector.h> -#include <QtGui/qcolor.h> -#include <QtGui/qpalette.h> -#include <QtGui/private/qguiapplication_p.h> -#include <QtGui/qpa/qplatformtheme.h> -#include <QtQuick/qquickwindow.h> -#include <QtQuick/private/qquickitem_p.h> -#include <QtQuickTemplates2/private/qquickpopup_p.h> - -QT_BEGIN_NAMESPACE - -static bool isDarkSystemTheme() -{ - if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) { - if (const QPalette *systemPalette = theme->palette(QPlatformTheme::SystemPalette)) { - const QColor textColor = systemPalette->color(QPalette::WindowText); - return textColor.red() > 128 && textColor.blue() > 128 && textColor.green() > 128; - } - } - return false; -} - -Q_QUICKCONTROLS2_PRIVATE_EXPORT bool qt_is_dark_system_theme() -{ - static bool dark = isDarkSystemTheme(); - return dark; -} - -static QQuickStyleAttached *attachedStyle(const QMetaObject *type, QObject *object, bool create = false) -{ - if (!object) - return nullptr; - int idx = -1; - return qobject_cast<QQuickStyleAttached *>(qmlAttachedPropertiesObject(&idx, object, type, create)); -} - -static QQuickStyleAttached *findParentStyle(const QMetaObject *type, QObject *object) -{ - QQuickItem *item = qobject_cast<QQuickItem *>(object); - if (item) { - // lookup parent items and popups - QQuickItem *parent = item->parentItem(); - while (parent) { - QQuickStyleAttached *style = attachedStyle(type, parent); - if (style) - return style; - - QQuickPopup *popup = qobject_cast<QQuickPopup *>(parent->parent()); - if (popup) - return attachedStyle(type, popup); - - parent = parent->parentItem(); - } - - // fallback to item's window - QQuickStyleAttached *style = attachedStyle(type, item->window()); - if (style) - return style; - } else { - // lookup popup's window - QQuickPopup *popup = qobject_cast<QQuickPopup *>(object); - if (popup) - return attachedStyle(type, popup->popupItem()->window()); - } - - // lookup parent window - QQuickWindow *window = qobject_cast<QQuickWindow *>(object); - if (window) { - QQuickWindow *parentWindow = qobject_cast<QQuickWindow *>(window->parent()); - if (parentWindow) { - QQuickStyleAttached *style = attachedStyle(type, window); - if (style) - return style; - } - } - - // fallback to engine (global) - if (object) { - QQmlEngine *engine = qmlEngine(object); - if (engine) { - QByteArray name = QByteArray("_q_") + type->className(); - QQuickStyleAttached *style = engine->property(name).value<QQuickStyleAttached*>(); - if (!style) { - style = attachedStyle(type, engine, true); - engine->setProperty(name, QVariant::fromValue(style)); - } - return style; - } - } - - return nullptr; -} - -static QList<QQuickStyleAttached *> findChildStyles(const QMetaObject *type, QObject *object) -{ - QList<QQuickStyleAttached *> children; - - QQuickItem *item = qobject_cast<QQuickItem *>(object); - if (!item) { - QQuickWindow *window = qobject_cast<QQuickWindow *>(object); - if (window) { - item = window->contentItem(); - - const auto windowChildren = window->children(); - for (QObject *child : windowChildren) { - QQuickWindow *childWindow = qobject_cast<QQuickWindow *>(child); - if (childWindow) { - QQuickStyleAttached *style = attachedStyle(type, childWindow); - if (style) - children += style; - } - } - } - } - - if (item) { - const auto childItems = item->childItems(); - for (QQuickItem *child : childItems) { - QQuickStyleAttached *style = attachedStyle(type, child); - if (style) - children += style; - else - children += findChildStyles(type, child); - } - } - - return children; -} - -QQuickStyleAttached::QQuickStyleAttached(QObject *parent) : QObject(parent) -{ - QQuickItem *item = qobject_cast<QQuickItem *>(parent); - if (!item) { - QQuickPopup *popup = qobject_cast<QQuickPopup *>(parent); - if (popup) - item = popup->popupItem(); - } - - if (item) { - connect(item, &QQuickItem::windowChanged, this, &QQuickStyleAttached::itemWindowChanged); - QQuickItemPrivate::get(item)->addItemChangeListener(this, QQuickItemPrivate::Parent); - } -} - -QQuickStyleAttached::~QQuickStyleAttached() -{ - QQuickItem *item = qobject_cast<QQuickItem *>(parent()); - if (item) { - disconnect(item, &QQuickItem::windowChanged, this, &QQuickStyleAttached::itemWindowChanged); - QQuickItemPrivate::get(item)->removeItemChangeListener(this, QQuickItemPrivate::Parent); - } - - setParentStyle(nullptr); -} - -QSharedPointer<QSettings> QQuickStyleAttached::settings(const QString &group) -{ -#ifndef QT_NO_SETTINGS - const QString filePath = QQuickStylePrivate::configFilePath(); - if (QFile::exists(filePath)) { - QFileSelector selector; - QSettings *settings = new QSettings(selector.select(filePath), QSettings::IniFormat); - if (!group.isEmpty()) - settings->beginGroup(group); - return QSharedPointer<QSettings>(settings); - } -#endif // QT_NO_SETTINGS - return QSharedPointer<QSettings>(); -} - -QList<QQuickStyleAttached *> QQuickStyleAttached::childStyles() const -{ - return m_childStyles; -} - -QQuickStyleAttached *QQuickStyleAttached::parentStyle() const -{ - return m_parentStyle; -} - -void QQuickStyleAttached::setParentStyle(QQuickStyleAttached *style) -{ - if (m_parentStyle != style) { - QQuickStyleAttached *oldParent = m_parentStyle; - if (m_parentStyle) - m_parentStyle->m_childStyles.removeOne(this); - m_parentStyle = style; - if (style) - style->m_childStyles.append(this); - parentStyleChange(style, oldParent); - } -} - -void QQuickStyleAttached::init() -{ - QQuickStyleAttached *parentStyle = findParentStyle(metaObject(), parent()); - if (parentStyle) - setParentStyle(parentStyle); - - const QList<QQuickStyleAttached *> children = findChildStyles(metaObject(), parent()); - for (QQuickStyleAttached *child : children) - child->setParentStyle(this); -} - -void QQuickStyleAttached::parentStyleChange(QQuickStyleAttached *newParent, QQuickStyleAttached *oldParent) -{ - Q_UNUSED(newParent); - Q_UNUSED(oldParent); -} - -void QQuickStyleAttached::itemWindowChanged(QQuickWindow *window) -{ - QQuickStyleAttached *parentStyle = nullptr; - QQuickItem *item = qobject_cast<QQuickItem *>(sender()); - if (item) - parentStyle = findParentStyle(metaObject(), item); - if (!parentStyle) - parentStyle = attachedStyle(metaObject(), window); - setParentStyle(parentStyle); -} - -void QQuickStyleAttached::itemParentChanged(QQuickItem *item, QQuickItem *parent) -{ - Q_UNUSED(parent); - setParentStyle(findParentStyle(metaObject(), item)); -} - -QT_END_NAMESPACE diff --git a/src/quickcontrols2/qquickstyleplugin.cpp b/src/quickcontrols2/qquickstyleplugin.cpp index 1f01da52..fa8e9785 100644 --- a/src/quickcontrols2/qquickstyleplugin.cpp +++ b/src/quickcontrols2/qquickstyleplugin.cpp @@ -65,14 +65,23 @@ void QQuickStylePlugin::initializeEngine(QQmlEngine *engine, const char *uri) if (!m_theme.isNull()) return; - const QString style = name(); - if (!style.isEmpty() && style.compare(QQuickStyle::name(), Qt::CaseInsensitive) == 0) { + if (isCurrent()) { m_theme.reset(createTheme()); if (m_theme) QGuiApplicationPrivate::platform_theme = m_theme.data(); } } +bool QQuickStylePlugin::isCurrent() const +{ + QString style = QQuickStyle::name(); + if (style.isEmpty()) + style = QStringLiteral("Default"); + + const QString theme = name(); + return theme.compare(style, Qt::CaseInsensitive) == 0; +} + QString QQuickStylePlugin::name() const { return QString(); diff --git a/src/quickcontrols2/qquickstyleplugin_p.h b/src/quickcontrols2/qquickstyleplugin_p.h index cd5a77b6..9457b472 100644 --- a/src/quickcontrols2/qquickstyleplugin_p.h +++ b/src/quickcontrols2/qquickstyleplugin_p.h @@ -67,6 +67,7 @@ public: void registerTypes(const char *uri) override; void initializeEngine(QQmlEngine *engine, const char *uri) override; + bool isCurrent() const; virtual QString name() const; virtual QQuickProxyTheme *createTheme() const; diff --git a/src/quickcontrols2/qquickstyleselector.cpp b/src/quickcontrols2/qquickstyleselector.cpp index 6d04c190..0e403dc1 100644 --- a/src/quickcontrols2/qquickstyleselector.cpp +++ b/src/quickcontrols2/qquickstyleselector.cpp @@ -65,13 +65,21 @@ static QString ensureSlash(const QString &path) return path + QLatin1Char('/'); } +static QStringList prefixedPlatformSelectors(const QChar &prefix) +{ + QStringList selectors = QFileSelectorPrivate::platformSelectors(); + for (int i = 0; i < selectors.count(); ++i) + selectors[i].prepend(prefix); + return selectors; +} + static QStringList allSelectors(const QString &style = QString()) { - static const QStringList platformSelectors = QFileSelectorPrivate::platformSelectors(); + static const QStringList platformSelectors = prefixedPlatformSelectors(QLatin1Char('+')); QStringList selectors = platformSelectors; const QString locale = QLocale().name(); if (!locale.isEmpty()) - selectors += locale; + selectors += QLatin1Char('+') + locale; if (!style.isEmpty()) selectors.prepend(style); return selectors; diff --git a/src/quickcontrols2/qquicktheme.cpp b/src/quickcontrols2/qquicktheme.cpp new file mode 100644 index 00000000..06a66bfd --- /dev/null +++ b/src/quickcontrols2/qquicktheme.cpp @@ -0,0 +1,163 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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 "qquicktheme_p.h" +#include "qquickstyle_p.h" + +#include <QtCore/qmetaobject.h> +#include <QtCore/qsettings.h> + +#include <functional> + +QT_BEGIN_NAMESPACE + +#if QT_CONFIG(settings) +static void readValue(const QSharedPointer<QSettings> &settings, const QString &name, std::function<void(const QVariant &)> setValue) +{ + const QVariant var = settings->value(name); + if (var.isValid()) + setValue(var); +} + +template <typename Enum> +static Enum toEnumValue(const QVariant &var) +{ + // ### TODO: expose QFont enums to the meta object system using Q_ENUM + //QMetaEnum enumeration = QMetaEnum::fromType<Enum>(); + //bool ok = false; + //int value = enumeration.keyToValue(var.toByteArray(), &ok); + //if (!ok) + // value = var.toInt(); + //return static_cast<Enum>(value); + + return static_cast<Enum>(var.toInt()); +} + +QFont *readFont(const QSharedPointer<QSettings> &settings) +{ + const QVariant var = settings->value(QStringLiteral("Font")); + if (var.isValid()) + return new QFont(var.value<QFont>()); + + QFont f; + settings->beginGroup(QStringLiteral("Font")); + readValue(settings, QStringLiteral("Family"), [&f](const QVariant &var) { f.setFamily(var.toString()); }); + readValue(settings, QStringLiteral("PointSize"), [&f](const QVariant &var) { f.setPointSizeF(var.toReal()); }); + readValue(settings, QStringLiteral("PixelSize"), [&f](const QVariant &var) { f.setPixelSize(var.toInt()); }); + readValue(settings, QStringLiteral("StyleHint"), [&f](const QVariant &var) { f.setStyleHint(toEnumValue<QFont::StyleHint>(var.toInt())); }); + readValue(settings, QStringLiteral("Weight"), [&f](const QVariant &var) { f.setWeight(toEnumValue<QFont::Weight>(var)); }); + readValue(settings, QStringLiteral("Style"), [&f](const QVariant &var) { f.setStyle(toEnumValue<QFont::Style>(var.toInt())); }); + settings->endGroup(); + return new QFont(f); +} + +static void readColorGroup(const QSharedPointer<QSettings> &settings, QPalette::ColorGroup group, QPalette *palette) +{ + const QStringList keys = settings->childKeys(); + if (keys.isEmpty()) + return; + + static const int index = QPalette::staticMetaObject.indexOfEnumerator("ColorRole"); + Q_ASSERT(index != -1); + QMetaEnum metaEnum = QPalette::staticMetaObject.enumerator(index); + + for (const QString &key : keys) { + bool ok = false; + int role = metaEnum.keyToValue(key.toUtf8(), &ok); + if (ok) + palette->setColor(group, static_cast<QPalette::ColorRole>(role), settings->value(key).value<QColor>()); + } +} + +static QPalette *readPalette(const QSharedPointer<QSettings> &settings) +{ + QPalette p; + settings->beginGroup(QStringLiteral("Palette")); + readColorGroup(settings, QPalette::All, &p); + + settings->beginGroup(QStringLiteral("Normal")); + readColorGroup(settings, QPalette::Normal, &p); + settings->endGroup(); + + settings->beginGroup(QStringLiteral("Disabled")); + readColorGroup(settings, QPalette::Disabled, &p); + settings->endGroup(); + return new QPalette(p); +} + +#endif // QT_CONFIG(settings) + +QQuickTheme::QQuickTheme(const QString &style) + : QQuickProxyTheme() +{ +#if QT_CONFIG(settings) + QSharedPointer<QSettings> settings = QQuickStylePrivate::settings(style); + if (settings) { + m_styleFont.reset(readFont(settings)); + m_stylePalette.reset(readPalette(settings)); + } +#endif +} + +const QFont *QQuickTheme::font(Font type) const +{ + Q_UNUSED(type); + return m_styleFont.data(); +} + +const QPalette *QQuickTheme::palette(Palette type) const +{ + Q_UNUSED(type); + return m_stylePalette.data(); +} + +QFont QQuickTheme::resolveFont(const QFont &font) const +{ + if (!m_styleFont) + return font; + + return m_styleFont->resolve(font); +} + +QPalette QQuickTheme::resolvePalette(const QPalette &palette) const +{ + if (!m_stylePalette) + return palette; + + return m_stylePalette->resolve(palette); +} + +QT_END_NAMESPACE diff --git a/src/quickcontrols2/qquicktheme_p.h b/src/quickcontrols2/qquicktheme_p.h new file mode 100644 index 00000000..098ac7f1 --- /dev/null +++ b/src/quickcontrols2/qquicktheme_p.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 2 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 QQUICKTHEME_P_H +#define QQUICKTHEME_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 <QtQuickControls2/private/qquickproxytheme_p.h> +#include <QtCore/qscopedpointer.h> +#include <QtGui/qfont.h> +#include <QtGui/qpalette.h> + +QT_BEGIN_NAMESPACE + +class Q_QUICKCONTROLS2_PRIVATE_EXPORT QQuickTheme : public QQuickProxyTheme +{ +public: + QQuickTheme(const QString &name); + + const QFont *font(Font type = SystemFont) const override; + const QPalette *palette(Palette type = SystemPalette) const override; + +protected: + QFont resolveFont(const QFont &font) const; + QPalette resolvePalette(const QPalette &palette) const; + +private: + QScopedPointer<QFont> m_styleFont; + QScopedPointer<QPalette> m_stylePalette; +}; + +QT_END_NAMESPACE + +#endif // QQUICKTHEME_P_H diff --git a/src/quickcontrols2/quickcontrols2.pri b/src/quickcontrols2/quickcontrols2.pri index a618989e..31b8e66f 100644 --- a/src/quickcontrols2/quickcontrols2.pri +++ b/src/quickcontrols2/quickcontrols2.pri @@ -1,26 +1,36 @@ HEADERS += \ $$PWD/qquickanimatednode_p.h \ - $$PWD/qquickcolorimageprovider_p.h \ + $$PWD/qquickattachedobject_p.h \ + $$PWD/qquickcolor_p.h \ + $$PWD/qquickcolorimage_p.h \ + $$PWD/qquickiconimage_p.h \ + $$PWD/qquickiconimage_p_p.h \ + $$PWD/qquickiconlabel_p.h \ + $$PWD/qquickiconlabel_p_p.h \ + $$PWD/qquickpaddedrectangle_p.h \ $$PWD/qquickplaceholdertext_p.h \ $$PWD/qquickproxytheme_p.h \ $$PWD/qquickstyle.h \ $$PWD/qquickstyle_p.h \ - $$PWD/qquickstyleattached_p.h \ $$PWD/qquickstyleplugin_p.h \ $$PWD/qquickstyleselector_p.h \ $$PWD/qquickstyleselector_p_p.h \ - $$PWD/qquickpaddedrectangle_p.h + $$PWD/qquicktheme_p.h SOURCES += \ $$PWD/qquickanimatednode.cpp \ - $$PWD/qquickcolorimageprovider.cpp \ + $$PWD/qquickattachedobject.cpp \ + $$PWD/qquickcolor.cpp \ + $$PWD/qquickcolorimage.cpp \ + $$PWD/qquickiconimage.cpp \ + $$PWD/qquickiconlabel.cpp \ + $$PWD/qquickpaddedrectangle.cpp \ $$PWD/qquickplaceholdertext.cpp \ $$PWD/qquickproxytheme.cpp \ $$PWD/qquickstyle.cpp \ - $$PWD/qquickstyleattached.cpp \ $$PWD/qquickstyleplugin.cpp \ $$PWD/qquickstyleselector.cpp \ - $$PWD/qquickpaddedrectangle.cpp + $$PWD/qquicktheme.cpp qtConfig(quick-listview):qtConfig(quick-pathview) { HEADERS += \ diff --git a/src/quickcontrols2/quickcontrols2.pro b/src/quickcontrols2/quickcontrols2.pro index bdad3095..8aec9953 100644 --- a/src/quickcontrols2/quickcontrols2.pro +++ b/src/quickcontrols2/quickcontrols2.pro @@ -7,7 +7,7 @@ QT_PRIVATE += core-private gui-private qml-private quick-private quicktemplates2 DEFINES += QT_NO_CAST_TO_ASCII QT_NO_CAST_FROM_ASCII HEADERS += \ - $$PWD/qtquickcontrols2global.h + $$PWD/qtquickcontrols2global.h \ $$PWD/qtquickcontrols2global_p.h include(quickcontrols2.pri) diff --git a/src/quicktemplates2/qquickabstractbutton.cpp b/src/quicktemplates2/qquickabstractbutton.cpp index e819f355..23b73200 100644 --- a/src/quicktemplates2/qquickabstractbutton.cpp +++ b/src/quicktemplates2/qquickabstractbutton.cpp @@ -37,6 +37,8 @@ #include "qquickabstractbutton_p.h" #include "qquickabstractbutton_p_p.h" #include "qquickbuttongroup_p.h" +#include "qquickaction_p.h" +#include "qquickaction_p_p.h" #include <QtGui/qstylehints.h> #include <QtGui/qguiapplication.h> @@ -63,6 +65,56 @@ static const int AUTO_REPEAT_INTERVAL = 100; radio buttons and check boxes. As an abstract control, it has no delegate implementations, leaving them to the types that derive from it. + \section2 Button Icons + + AbstractButton provides the following properties through which icons can + be set: + + \list + \li \l icon.name + \li \l icon.source + \li \l icon.width + \li \l icon.height + \li \l icon.color + \endlist + + For applications that target platforms that support both + \l {QIcon::fromTheme()}{theme icons} and regular icons, + both \l icon.name and \l icon.source can be set to ensure that an icon will + always be found. If the icon is found in the theme, it will always be used; + even if \l icon.source is also set. If the icon is not found, + \l icon.source will be used instead. + + \code + Button { + icon.name: "edit-cut" + icon.source: "qrc:/icons/edit-cut.png" + } + \endcode + + Each \l {Styling Qt Quick Controls 2}{style} sets a default icon size and + color according to their guidelines, but it is possible to override these + by setting the \l icon.width, \l icon.height, and \l icon.color properties. + + The image that is loaded by an icon whose \c width and \c height are not set + depends on the type of icon in use. For theme icons, the closest available + size will be chosen. For regular icons, the behavior is the same as the + \l {Image::}{sourceSize} property of \l Image. + + The icon color is specified by default so that it matches the text color in + different states. In order to use an icon with the original colors, set the + color to \c "transparent". + + \code + Button { + icon.color: "transparent" + icon.source: "qrc:/icons/logo.png" + } + \endcode + + The \l display property can be used to control how the icon and text are + displayed within the button. + \sa ButtonGroup, {Button Controls} */ @@ -126,7 +178,9 @@ QQuickAbstractButtonPrivate::QQuickAbstractButtonPrivate() repeatTimer(0), pressButtons(Qt::NoButton), indicator(nullptr), - group(nullptr) + group(nullptr), + display(QQuickAbstractButton::TextBesideIcon), + action(nullptr) { } @@ -173,7 +227,7 @@ void QQuickAbstractButtonPrivate::handleRelease(const QPointF &point) if (wasPressed) { emit q->released(); if (!wasHeld) - emit q->clicked(); + trigger(); } else { emit q->canceled(); } @@ -249,6 +303,22 @@ void QQuickAbstractButtonPrivate::stopPressRepeat() } } +void QQuickAbstractButtonPrivate::click() +{ + Q_Q(QQuickAbstractButton); + if (effectiveEnable) + emit q->clicked(); +} + +void QQuickAbstractButtonPrivate::trigger() +{ + Q_Q(QQuickAbstractButton); + if (action && action->isEnabled()) + action->trigger(q); // -> click() + else if (effectiveEnable) + emit q->clicked(); +} + void QQuickAbstractButtonPrivate::toggle(bool value) { Q_Q(QQuickAbstractButton); @@ -453,6 +523,8 @@ void QQuickAbstractButton::setChecked(bool checked) setCheckable(true); d->checked = checked; + if (d->action) + d->action->setChecked(checked); setAccessibleProperty("checked", checked); buttonChange(ButtonCheckedChange); emit checkedChanged(); @@ -486,6 +558,8 @@ void QQuickAbstractButton::setCheckable(bool checkable) return; d->checkable = checkable; + if (d->action) + d->action->setCheckable(checkable); setAccessibleProperty("checkable", checkable); buttonChange(ButtonCheckableChange); emit checkableChanged(); @@ -566,6 +640,142 @@ void QQuickAbstractButton::setIndicator(QQuickItem *indicator) } /*! + \qmlpropertygroup QtQuick.Controls::AbstractButton::icon + \qmlproperty string QtQuick.Controls::AbstractButton::icon.name + \qmlproperty url QtQuick.Controls::AbstractButton::icon.source + \qmlproperty int QtQuick.Controls::AbstractButton::icon.width + \qmlproperty int QtQuick.Controls::AbstractButton::icon.height + \qmlproperty color QtQuick.Controls::AbstractButton::icon.color + + This property group was added in QtQuick.Controls 2.3. + + \include qquickicon.qdocinc grouped-properties + + \sa {Button Icons} +*/ + +QQuickIcon QQuickAbstractButton::icon() const +{ + Q_D(const QQuickAbstractButton); + return d->icon; +} + +void QQuickAbstractButton::setIcon(const QQuickIcon &icon) +{ + Q_D(QQuickAbstractButton); + if (d->icon == icon) + return; + + d->icon = icon; + emit iconChanged(); +} + +/*! + \since QtQuick.Controls 2.3 (Qt 5.10) + \qmlproperty enumeration QtQuick.Controls::AbstractButton::display + + This property determines how the \l icon and \l text are displayed within + the button. + + \table + \header \li Display \li Result + \row \li \c AbstractButton.IconOnly \li \image qtquickcontrols2-button-icononly.png + \row \li \c AbstractButton.TextOnly \li \image qtquickcontrols2-button-textonly.png + \row \li \c AbstractButton.TextBesideIcon \li \image qtquickcontrols2-button-textbesideicon.png + \endtable + + \sa {Control::}{spacing}, {Control::}{padding} +*/ +QQuickAbstractButton::Display QQuickAbstractButton::display() const +{ + Q_D(const QQuickAbstractButton); + return d->display; +} + +void QQuickAbstractButton::setDisplay(Display display) +{ + Q_D(QQuickAbstractButton); + if (display == d->display) + return; + + d->display = display; + emit displayChanged(); +} + +/*! + \since QtQuick.Controls 2.3 (Qt 5.10) + \qmlproperty Action QtQuick.Controls::AbstractButton::action + + This property holds the button action. + + \sa Action +*/ +QQuickAction *QQuickAbstractButton::action() const +{ + Q_D(const QQuickAbstractButton); + return d->action; +} + +void QQuickAbstractButton::setAction(QQuickAction *action) +{ + Q_D(QQuickAbstractButton); + if (d->action == action) + return; + + if (QQuickAction *oldAction = d->action.data()) { + QQuickActionPrivate::get(oldAction)->unregisterItem(this); + QObjectPrivate::disconnect(oldAction, &QQuickAction::triggered, d, &QQuickAbstractButtonPrivate::click); + + disconnect(oldAction, &QQuickAction::textChanged, this, &QQuickAbstractButton::setText); + disconnect(oldAction, &QQuickAction::iconChanged, this, &QQuickAbstractButton::setIcon); + disconnect(oldAction, &QQuickAction::checkedChanged, this, &QQuickAbstractButton::setChecked); + disconnect(oldAction, &QQuickAction::checkableChanged, this, &QQuickAbstractButton::setCheckable); + disconnect(oldAction, &QQuickAction::enabledChanged, this, &QQuickItem::setEnabled); + } + + if (action) { + QQuickActionPrivate::get(action)->registerItem(this); + QObjectPrivate::connect(action, &QQuickAction::triggered, d, &QQuickAbstractButtonPrivate::click); + + connect(action, &QQuickAction::textChanged, this, &QQuickAbstractButton::setText); + connect(action, &QQuickAction::iconChanged, this, &QQuickAbstractButton::setIcon); + connect(action, &QQuickAction::checkedChanged, this, &QQuickAbstractButton::setChecked); + connect(action, &QQuickAction::checkableChanged, this, &QQuickAbstractButton::setCheckable); + connect(action, &QQuickAction::enabledChanged, this, &QQuickItem::setEnabled); + + QQuickIcon actionIcon = action->icon(); + + QString name = actionIcon.name(); + if (!name.isEmpty()) + d->icon.setName(name); + + QUrl source = actionIcon.source(); + if (!source.isEmpty()) + d->icon.setSource(source); + + int width = actionIcon.width(); + if (width > 0) + d->icon.setWidth(width); + + int height = actionIcon.height(); + if (height) + d->icon.setHeight(height); + + QColor color = actionIcon.color(); + if (color != Qt::transparent) + d->icon.setColor(color); + + setText(action->text()); + setChecked(action->isChecked()); + setCheckable(action->isCheckable()); + setEnabled(action->isEnabled()); + } + + d->action = action; + emit actionChanged(); +} + +/*! \qmlmethod void QtQuick.Controls::AbstractButton::toggle() Toggles the checked state of the button. @@ -609,7 +819,7 @@ void QQuickAbstractButton::keyReleaseEvent(QKeyEvent *event) nextCheckState(); emit released(); - emit clicked(); + d->trigger(); if (d->autoRepeat) d->stopPressRepeat(); @@ -642,7 +852,7 @@ void QQuickAbstractButton::timerEvent(QTimerEvent *event) d->startPressRepeat(); } else if (event->timerId() == d->repeatTimer) { emit released(); - emit clicked(); + d->trigger(); emit pressed(); } } diff --git a/src/quicktemplates2/qquickabstractbutton_p.h b/src/quicktemplates2/qquickabstractbutton_p.h index 72038ee4..25827c9f 100644 --- a/src/quicktemplates2/qquickabstractbutton_p.h +++ b/src/quicktemplates2/qquickabstractbutton_p.h @@ -49,9 +49,11 @@ // #include <QtQuickTemplates2/private/qquickcontrol_p.h> +#include <QtQuickTemplates2/private/qquickicon_p.h> QT_BEGIN_NAMESPACE +class QQuickAction; class QQuickAbstractButtonPrivate; class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickAbstractButton : public QQuickControl @@ -64,6 +66,9 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickAbstractButton : public QQuickContr Q_PROPERTY(bool checkable READ isCheckable WRITE setCheckable NOTIFY checkableChanged FINAL) Q_PROPERTY(bool autoExclusive READ autoExclusive WRITE setAutoExclusive NOTIFY autoExclusiveChanged FINAL) Q_PROPERTY(QQuickItem *indicator READ indicator WRITE setIndicator NOTIFY indicatorChanged FINAL) + Q_PROPERTY(QQuickIcon icon READ icon WRITE setIcon NOTIFY iconChanged FINAL REVISION 3) + Q_PROPERTY(Display display READ display WRITE setDisplay NOTIFY displayChanged FINAL REVISION 3) + Q_PROPERTY(QQuickAction *action READ action WRITE setAction NOTIFY actionChanged FINAL REVISION 3) public: explicit QQuickAbstractButton(QQuickItem *parent = nullptr); @@ -94,6 +99,23 @@ public: QQuickItem *indicator() const; void setIndicator(QQuickItem *indicator); + QQuickIcon icon() const; + void setIcon(const QQuickIcon &icon); + + enum Display { + IconOnly, + TextOnly, + TextBesideIcon, + TextUnderIcon + }; + Q_ENUM(Display) + + Display display() const; + void setDisplay(Display display); + + QQuickAction *action() const; + void setAction(QQuickAction *action); + public Q_SLOTS: void toggle(); @@ -112,6 +134,9 @@ Q_SIGNALS: void checkableChanged(); void autoExclusiveChanged(); void indicatorChanged(); + Q_REVISION(3) void iconChanged(); + Q_REVISION(3) void displayChanged(); + Q_REVISION(3) void actionChanged(); protected: QQuickAbstractButton(QQuickAbstractButtonPrivate &dd, QQuickItem *parent); diff --git a/src/quicktemplates2/qquickabstractbutton_p_p.h b/src/quicktemplates2/qquickabstractbutton_p_p.h index 39af6896..f1fef5e5 100644 --- a/src/quicktemplates2/qquickabstractbutton_p_p.h +++ b/src/quicktemplates2/qquickabstractbutton_p_p.h @@ -53,6 +53,7 @@ QT_BEGIN_NAMESPACE +class QQuickAction; class QQuickButtonGroup; class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickAbstractButtonPrivate : public QQuickControlPrivate @@ -83,6 +84,8 @@ public: QQuickAbstractButton *findCheckedButton() const; QList<QQuickAbstractButton *> findExclusiveButtons() const; + void click(); + void trigger(); void toggle(bool value); QString text; @@ -98,10 +101,13 @@ public: int holdTimer; int delayTimer; int repeatTimer; + QQuickIcon icon; QPointF pressPoint; Qt::MouseButtons pressButtons; QQuickItem *indicator; QQuickButtonGroup *group; + QQuickAbstractButton::Display display; + QPointer<QQuickAction> action; }; QT_END_NAMESPACE diff --git a/src/quicktemplates2/qquickaction.cpp b/src/quicktemplates2/qquickaction.cpp new file mode 100644 index 00000000..fb6d7c3e --- /dev/null +++ b/src/quicktemplates2/qquickaction.cpp @@ -0,0 +1,553 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Templates 2 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 "qquickaction_p.h" +#include "qquickaction_p_p.h" +#include "qquickactiongroup_p.h" +#include "qquickshortcutcontext_p_p.h" + +#include <QtGui/qevent.h> +#include <QtGui/private/qshortcutmap_p.h> +#include <QtGui/private/qguiapplication_p.h> +#include <QtQuick/private/qquickitem_p.h> + +QT_BEGIN_NAMESPACE + +/*! + \qmltype Action + \inherits QtObject + \instantiates QQuickAction + \inqmlmodule QtQuick.Controls + \since 5.10 + \ingroup utilities + \brief Abstract user interface action. + + Action represents an abstract user interface action that can have shortcuts + and can be assigned to menu items and toolbar buttons. + + Actions may contain \l text, an \l icon, and a \l shortcut. Actions are normally + \l triggered by the user via menu items, toolbar buttons, or keyboard shortcuts. + A \l checkable Action toggles its \l checked state when triggered. + + \snippet qtquickcontrols2-action.qml action + + Action is commonly used to implement application commands that can be invoked + via menu items, toolbar buttons, and keyboard shortcuts. Since the user expects + the commands to be performed in the same way, regardless of the user interface + used, it is useful to represent the commands as shareable actions. + + Action can be also used to separate the logic and the visual presentation. For + example, when declaring buttons and menu items in \c .ui.qml files, actions can + be declared elsewhere and assigned from the outside. + + \snippet qtquickcontrols2-action.qml toolbutton + + When an action is paired with buttons and menu items, the \c enabled, \c checkable, + and \c checked states are synced automatically. For example, in a word processor, + if the user clicks a "Bold" toolbar button, the "Bold" menu item will automatically + be checked. Buttons and menu items get their \c text and \c icon from the action by + default. An action-specific \c text or \c icon can be overridden for a specific + control by specifying \c text or \c icon directly on the control. + + \snippet qtquickcontrols2-action.qml menuitem + + Since Action presents a user interface action, it is intended to be assigned to + a \l MenuItem, \l ToolButton, or any other control that inherits \l AbstractButton. + For keyboard shortcuts, the simpler \l Shortcut type is more appropriate. + + \sa MenuItem, ToolButton, Shortcut +*/ + +/*! + \qmlsignal QtQuick.Controls::Action::toggled(QtObject source) + + This signal is emitted when the action is toggled. The \a source argument + identifies the object that toggled the action. + + For example, if the action is assigned to a menu item and a toolbar button, the + action is toggled when the control is toggled, the shortcut is activated, or + when \l toggle() is called directly. +*/ + +/*! + \qmlsignal QtQuick.Controls::Action::triggered(QtObject source) + + This signal is emitted when the action is triggered. The \a source argument + identifies the object that triggered the action. + + For example, if the action is assigned to a menu item and a toolbar button, the + action is triggered when the control is clicked, the shortcut is activated, or + when \l trigger() is called directly. +*/ + +static QKeySequence variantToKeySequence(const QVariant &var) +{ + if (var.type() == QVariant::Int) + return QKeySequence(static_cast<QKeySequence::StandardKey>(var.toInt())); + return QKeySequence::fromString(var.toString()); +} + +QQuickActionPrivate::ShortcutEntry::ShortcutEntry(QObject *target) + : m_shortcutId(0), + m_target(target) +{ +} + +QQuickActionPrivate::ShortcutEntry::~ShortcutEntry() +{ + ungrab(); +} + +QObject *QQuickActionPrivate::ShortcutEntry::target() const +{ + return m_target; +} + +int QQuickActionPrivate::ShortcutEntry::shortcutId() const +{ + return m_shortcutId; +} + +void QQuickActionPrivate::ShortcutEntry::grab(const QKeySequence &shortcut, bool enabled) +{ + if (shortcut.isEmpty()) + return; + + Qt::ShortcutContext context = Qt::WindowShortcut; // TODO + m_shortcutId = QGuiApplicationPrivate::instance()->shortcutMap.addShortcut(m_target, shortcut, context, QQuickShortcutContext::matcher); + + if (!enabled) + QGuiApplicationPrivate::instance()->shortcutMap.setShortcutEnabled(false, m_shortcutId, m_target); +} + +void QQuickActionPrivate::ShortcutEntry::ungrab() +{ + if (!m_shortcutId) + return; + + QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(m_shortcutId, m_target); + m_shortcutId = 0; +} + +void QQuickActionPrivate::ShortcutEntry::setEnabled(bool enabled) +{ + if (!m_shortcutId) + return; + + QGuiApplicationPrivate::instance()->shortcutMap.setShortcutEnabled(enabled, m_shortcutId, m_target); +} + +QQuickActionPrivate::QQuickActionPrivate() + : explicitEnabled(false), + enabled(true), + checked(false), + checkable(false), + defaultShortcutEntry(nullptr), + group(nullptr) +{ +} + +QVariant QQuickActionPrivate::shortcut() const +{ + return vshortcut; +} + +void QQuickActionPrivate::setShortcut(const QVariant &var) +{ + Q_Q(QQuickAction); + if (vshortcut == var) + return; + + defaultShortcutEntry->ungrab(); + for (QQuickActionPrivate::ShortcutEntry *entry : qAsConst(shortcutEntries)) + entry->ungrab(); + + vshortcut = var.toString(); + keySequence = variantToKeySequence(var); + + defaultShortcutEntry->grab(keySequence, enabled); + for (QQuickActionPrivate::ShortcutEntry *entry : qAsConst(shortcutEntries)) + entry->grab(keySequence, enabled); + + emit q->shortcutChanged(keySequence); +} + +void QQuickActionPrivate::setEnabled(bool enable) +{ + Q_Q(QQuickAction); + if (enabled == enable) + return; + + enabled = enable; + + defaultShortcutEntry->setEnabled(enable); + for (QQuickActionPrivate::ShortcutEntry *entry : qAsConst(shortcutEntries)) + entry->setEnabled(enable); + + emit q->enabledChanged(enable); +} + +bool QQuickActionPrivate::watchItem(QQuickItem *item) +{ + Q_Q(QQuickAction); + if (!item) + return false; + + item->installEventFilter(q); + QQuickItemPrivate::get(item)->addItemChangeListener(this, QQuickItemPrivate::Visibility | QQuickItemPrivate::Destroyed); + return true; +} + +bool QQuickActionPrivate::unwatchItem(QQuickItem *item) +{ + Q_Q(QQuickAction); + if (!item) + return false; + + item->removeEventFilter(q); + QQuickItemPrivate::get(item)->removeItemChangeListener(this, QQuickItemPrivate::Visibility | QQuickItemPrivate::Destroyed); + return true; +} + +void QQuickActionPrivate::registerItem(QQuickItem *item) +{ + if (!watchItem(item)) + return; + + QQuickActionPrivate::ShortcutEntry *entry = new QQuickActionPrivate::ShortcutEntry(item); + if (item->isVisible()) + entry->grab(keySequence, enabled); + shortcutEntries += entry; + + updateDefaultShortcutEntry(); +} + +void QQuickActionPrivate::unregisterItem(QQuickItem *item) +{ + QQuickActionPrivate::ShortcutEntry *entry = findShortcutEntry(item); + if (!entry || !unwatchItem(item)) + return; + + shortcutEntries.removeOne(entry); + delete entry; + + updateDefaultShortcutEntry(); +} + +void QQuickActionPrivate::itemVisibilityChanged(QQuickItem *item) +{ + QQuickActionPrivate::ShortcutEntry *entry = findShortcutEntry(item); + if (!entry) + return; + + if (item->isVisible()) + entry->grab(keySequence, enabled); + else + entry->ungrab(); + + updateDefaultShortcutEntry(); +} + +void QQuickActionPrivate::itemDestroyed(QQuickItem *item) +{ + unregisterItem(item); +} + +bool QQuickActionPrivate::handleShortcutEvent(QObject *object, QShortcutEvent *event) +{ + Q_Q(QQuickAction); + if (event->key() != keySequence) + return false; + + QQuickActionPrivate::ShortcutEntry *entry = findShortcutEntry(object); + if (!entry || event->shortcutId() != entry->shortcutId()) + return false; + + q->trigger(entry->target()); + return true; +} + +QQuickActionPrivate::ShortcutEntry *QQuickActionPrivate::findShortcutEntry(QObject *target) const +{ + Q_Q(const QQuickAction); + if (target == q) + return defaultShortcutEntry; + for (QQuickActionPrivate::ShortcutEntry *entry : shortcutEntries) { + if (entry->target() == target) + return entry; + } + return nullptr; +} + +void QQuickActionPrivate::updateDefaultShortcutEntry() +{ + bool hasActiveShortcutEntries = false; + for (QQuickActionPrivate::ShortcutEntry *entry : qAsConst(shortcutEntries)) { + if (entry->shortcutId()) { + hasActiveShortcutEntries = true; + break; + } + } + + if (hasActiveShortcutEntries) + defaultShortcutEntry->ungrab(); + else if (!defaultShortcutEntry->shortcutId()) + defaultShortcutEntry->grab(keySequence, enabled); +} + +QQuickAction::QQuickAction(QObject *parent) + : QObject(*(new QQuickActionPrivate), parent) +{ + Q_D(QQuickAction); + d->defaultShortcutEntry = new QQuickActionPrivate::ShortcutEntry(this); +} + +QQuickAction::~QQuickAction() +{ + Q_D(QQuickAction); + if (d->group) + d->group->removeAction(this); + + for (QQuickActionPrivate::ShortcutEntry *entry : qAsConst(d->shortcutEntries)) + d->unwatchItem(qobject_cast<QQuickItem *>(entry->target())); + + qDeleteAll(d->shortcutEntries); + delete d->defaultShortcutEntry; +} + +/*! + \qmlproperty string QtQuick.Controls::Action::text + + This property holds a textual description of the action. +*/ +QString QQuickAction::text() const +{ + Q_D(const QQuickAction); + return d->text; +} + +void QQuickAction::setText(const QString &text) +{ + Q_D(QQuickAction); + if (d->text == text) + return; + + d->text = text; + emit textChanged(text); +} + +/*! + \qmlpropertygroup QtQuick.Controls::Action::icon + \qmlproperty string QtQuick.Controls::Action::icon.name + \qmlproperty url QtQuick.Controls::Action::icon.source + \qmlproperty int QtQuick.Controls::Action::icon.width + \qmlproperty int QtQuick.Controls::Action::icon.height + \qmlproperty color QtQuick.Controls::Action::icon.color + + \include qquickicon.qdocinc grouped-properties +*/ +QQuickIcon QQuickAction::icon() const +{ + Q_D(const QQuickAction); + return d->icon; +} + +void QQuickAction::setIcon(const QQuickIcon &icon) +{ + Q_D(QQuickAction); + if (d->icon == icon) + return; + + d->icon = icon; + emit iconChanged(icon); +} + +/*! + \qmlproperty bool QtQuick.Controls::Action::enabled + + This property holds whether the action is enabled. The default value is \c true. +*/ +bool QQuickAction::isEnabled() const +{ + Q_D(const QQuickAction); + return d->enabled && (!d->group || d->group->isEnabled()); +} + +void QQuickAction::setEnabled(bool enabled) +{ + Q_D(QQuickAction); + d->explicitEnabled = true; + d->setEnabled(enabled); +} + +void QQuickAction::resetEnabled() +{ + Q_D(QQuickAction); + if (!d->explicitEnabled) + return; + + d->explicitEnabled = false; + d->setEnabled(true); +} + +/*! + \qmlproperty bool QtQuick.Controls::Action::checked + + This property holds whether the action is checked. + + \sa checkable +*/ +bool QQuickAction::isChecked() const +{ + Q_D(const QQuickAction); + return d->checked; +} + +void QQuickAction::setChecked(bool checked) +{ + Q_D(QQuickAction); + if (d->checked == checked) + return; + + d->checked = checked; + emit checkedChanged(checked); +} + +/*! + \qmlproperty bool QtQuick.Controls::Action::checkable + + This property holds whether the action is checkable. The default value is \c false. + + A checkable action toggles between checked (on) and unchecked (off) when triggered. + + \sa checked +*/ +bool QQuickAction::isCheckable() const +{ + Q_D(const QQuickAction); + return d->checkable; +} + +void QQuickAction::setCheckable(bool checkable) +{ + Q_D(QQuickAction); + if (d->checkable == checkable) + return; + + d->checkable = checkable; + emit checkableChanged(checkable); +} + +/*! + \qmlproperty keysequence QtQuick.Controls::Action::shortcut + + This property holds the action's shortcut. The key sequence can be set + to one of the \l{QKeySequence::StandardKey}{standard keyboard shortcuts}, + or it can be described with a string containing a sequence of up to four + key presses that are needed to trigger the shortcut. + + \code + Action { + sequence: "Ctrl+E,Ctrl+W" + onTriggered: edit.wrapMode = TextEdit.Wrap + } + \endcode +*/ +QKeySequence QQuickAction::shortcut() const +{ + Q_D(const QQuickAction); + return d->keySequence; +} + +void QQuickAction::setShortcut(const QKeySequence &shortcut) +{ + Q_D(QQuickAction); + d->setShortcut(shortcut.toString()); +} + +/*! + \qmlmethod void QtQuick.Controls::Action::toggle(QtObject source = null) + + Toggles the action and emits \l toggled() if enabled, with an optional \a source object defined. +*/ +void QQuickAction::toggle(QObject *source) +{ + Q_D(QQuickAction); + if (!d->enabled) + return; + + if (d->checkable) + setChecked(!d->checked); + + emit toggled(source); +} + +/*! + \qmlmethod void QtQuick.Controls::Action::trigger(QtObject source = null) + + Triggers the action and emits \l triggered() if enabled, with an optional \a source object defined. +*/ +void QQuickAction::trigger(QObject *source) +{ + Q_D(QQuickAction); + if (!d->enabled) + return; + + if (d->checkable) + toggle(source); + + emit triggered(source); +} + +bool QQuickAction::event(QEvent *event) +{ + Q_D(QQuickAction); + if (event->type() != QEvent::Shortcut) + return QObject::event(event); + return d->handleShortcutEvent(this, static_cast<QShortcutEvent *>(event)); +} + +bool QQuickAction::eventFilter(QObject *object, QEvent *event) +{ + Q_D(QQuickAction); + if (event->type() != QEvent::Shortcut) + return false; + return d->handleShortcutEvent(object, static_cast<QShortcutEvent *>(event)); +} + +QT_END_NAMESPACE + +#include "moc_qquickaction_p.cpp" diff --git a/src/quicktemplates2/qquickaction_p.h b/src/quicktemplates2/qquickaction_p.h new file mode 100644 index 00000000..ce989bed --- /dev/null +++ b/src/quicktemplates2/qquickaction_p.h @@ -0,0 +1,122 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Templates 2 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 QQUICKACTION_P_H +#define QQUICKACTION_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 <QtQuickTemplates2/private/qtquicktemplates2global_p.h> +#include <QtQuickTemplates2/private/qquickicon_p.h> +#include <QtCore/qobject.h> +#include <QtQml/qqml.h> + +QT_BEGIN_NAMESPACE + +class QQuickIcon; +class QQuickActionPrivate; + +class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickAction : public QObject +{ + Q_OBJECT + Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged FINAL) + Q_PROPERTY(QQuickIcon icon READ icon WRITE setIcon NOTIFY iconChanged FINAL) + Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged RESET resetEnabled FINAL) + Q_PROPERTY(bool checked READ isChecked WRITE setChecked NOTIFY checkedChanged FINAL) + Q_PROPERTY(bool checkable READ isCheckable WRITE setCheckable NOTIFY checkableChanged FINAL) + Q_PRIVATE_PROPERTY(QQuickAction::d_func(), QVariant shortcut READ shortcut WRITE setShortcut NOTIFY shortcutChanged FINAL) + +public: + explicit QQuickAction(QObject *parent = nullptr); + ~QQuickAction(); + + QString text() const; + void setText(const QString &text); + + QQuickIcon icon() const; + void setIcon(const QQuickIcon &icon); + + bool isEnabled() const; + void setEnabled(bool enabled); + void resetEnabled(); + + bool isChecked() const; + void setChecked(bool checked); + + bool isCheckable() const; + void setCheckable(bool checkable); + + QKeySequence shortcut() const; + void setShortcut(const QKeySequence &shortcut); + +public Q_SLOTS: + void toggle(QObject *source = nullptr); + void trigger(QObject *source = nullptr); + +Q_SIGNALS: + void textChanged(const QString &text); + void iconChanged(const QQuickIcon &icon); + void enabledChanged(bool enabled); + void checkedChanged(bool checked); + void checkableChanged(bool checkable); + void shortcutChanged(const QKeySequence &shortcut); + + void toggled(QObject *source = nullptr); + void triggered(QObject *source = nullptr); + +protected: + bool event(QEvent *event) override; + bool eventFilter(QObject *object, QEvent *event) override; + +private: + Q_DISABLE_COPY(QQuickAction) + Q_DECLARE_PRIVATE(QQuickAction) +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QQuickAction) + +#endif // QQUICKACTION_P_H diff --git a/src/quicktemplates2/qquickaction_p_p.h b/src/quicktemplates2/qquickaction_p_p.h new file mode 100644 index 00000000..08c442ed --- /dev/null +++ b/src/quicktemplates2/qquickaction_p_p.h @@ -0,0 +1,127 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Templates 2 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 QQUICKACTION_P_P_H +#define QQUICKACTION_P_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 <QtCore/private/qobject_p.h> +#include <QtCore/qvariant.h> +#include <QtCore/qstring.h> +#include <QtGui/qkeysequence.h> +#include <QtQuick/private/qquickitemchangelistener_p.h> + +QT_BEGIN_NAMESPACE + +class QShortcutEvent; +class QQuickActionGroup; + +class QQuickActionPrivate : public QObjectPrivate, public QQuickItemChangeListener +{ + Q_DECLARE_PUBLIC(QQuickAction) + +public: + QQuickActionPrivate(); + + static QQuickActionPrivate *get(QQuickAction *action) + { + return action->d_func(); + } + + QVariant shortcut() const; + void setShortcut(const QVariant &shortcut); + + void setEnabled(bool enable); + + bool watchItem(QQuickItem *item); + bool unwatchItem(QQuickItem *item); + + void registerItem(QQuickItem *item); + void unregisterItem(QQuickItem *item); + + void itemVisibilityChanged(QQuickItem *item) override; + void itemDestroyed(QQuickItem *item) override; + + bool handleShortcutEvent(QObject *object, QShortcutEvent *event); + + class ShortcutEntry + { + public: + explicit ShortcutEntry(QObject *target); + ~ShortcutEntry(); + + QObject *target() const; + int shortcutId() const; + + void grab(const QKeySequence &vshortcut, bool enabled); + void ungrab(); + + void setEnabled(bool enabled); + + private: + int m_shortcutId; + QObject *m_target; + }; + + ShortcutEntry *findShortcutEntry(QObject *target) const; + void updateDefaultShortcutEntry(); + + bool explicitEnabled; + bool enabled; + bool checked; + bool checkable; + QString text; + QQuickIcon icon; + QVariant vshortcut; + QKeySequence keySequence; + ShortcutEntry *defaultShortcutEntry; + QVector<ShortcutEntry *> shortcutEntries; + QQuickActionGroup *group; +}; + +QT_END_NAMESPACE + +#endif // QQUICKACTION_P_P_H diff --git a/src/quicktemplates2/qquickactiongroup.cpp b/src/quicktemplates2/qquickactiongroup.cpp new file mode 100644 index 00000000..7a5e17ee --- /dev/null +++ b/src/quicktemplates2/qquickactiongroup.cpp @@ -0,0 +1,474 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Templates 2 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 "qquickactiongroup_p.h" + +#include <QtCore/private/qobject_p.h> +#include <QtCore/qmetaobject.h> +#include <QtCore/qvariant.h> +#include <QtQml/qqmlinfo.h> + +#include "qquickaction_p.h" +#include "qquickaction_p_p.h" + +QT_BEGIN_NAMESPACE + +/*! + \qmltype ActionGroup + \inherits QtObject + \instantiates QQuickActionGroup + \inqmlmodule QtQuick.Controls + \since 5.10 + \ingroup utilities + \brief Groups actions together. + + ActionGroup is a non-visual group of actions. A mutually \l exclusive + action group is used with actions where only one of the options can be + selected at a time. + + The most straight-forward way to use ActionGroup is to declare actions + as children of the group. + + \code + ActionGroup { + id: alignmentGroup + + Action { + checked: true + text: qsTr("Left") + } + + Action { + text: qsTr("Center") + } + + Action { + text: qsTr("Right") + } + } + \endcode + + Alternatively, the \l group attached property allows declaring the actions + elsewhere and assigning them to a specific group. + + \code + ActionGroup { id: alignmentGroup } + + Action { + checked: true + text: qsTr("Left") + ActionGroup.group: alignmentGroup + } + + Action { + text: qsTr("Center") + ActionGroup.group: alignmentGroup + } + + Action { + text: qsTr("Right") + ActionGroup.group: alignmentGroup + } + \endcode + + More advanced use cases can be handled using the \c addAction() and + \c removeAction() methods. + + \sa Action, ButtonGroup +*/ + +/*! + \qmlsignal QtQuick.Controls::ActionGroup::triggered(Action action) + + This signal is emitted when an \a action in the group has been triggered. + + This signal is convenient for implementing a common signal handler for + all actions in the same group. + + \code + ActionGroup { + onTriggered: console.log("triggered:", action.text) + + Action { text: "First" } + Action { text: "Second" } + Action { text: "Third" } + } + \endcode + + \sa Action::triggered() +*/ + +class QQuickActionGroupPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QQuickActionGroup) + +public: + QQuickActionGroupPrivate() + : enabled(true), + exclusive(true), + checkedAction(nullptr) + { + } + + void clear(); + void actionTriggered(); + void _q_updateCurrent(); + + static bool changeEnabled(QQuickAction *action, bool enabled); + + static void actions_append(QQmlListProperty<QQuickAction> *prop, QQuickAction *obj); + static int actions_count(QQmlListProperty<QQuickAction> *prop); + static QQuickAction *actions_at(QQmlListProperty<QQuickAction> *prop, int index); + static void actions_clear(QQmlListProperty<QQuickAction> *prop); + + bool enabled; + bool exclusive; + QQuickAction *checkedAction; + QVector<QQuickAction*> actions; +}; + +void QQuickActionGroupPrivate::clear() +{ + for (QQuickAction *action : qAsConst(actions)) { + QQuickActionPrivate::get(action)->group = nullptr; + QObjectPrivate::disconnect(action, &QQuickAction::triggered, this, &QQuickActionGroupPrivate::actionTriggered); + QObjectPrivate::disconnect(action, &QQuickAction::checkedChanged, this, &QQuickActionGroupPrivate::_q_updateCurrent); + } + actions.clear(); +} + +void QQuickActionGroupPrivate::actionTriggered() +{ + Q_Q(QQuickActionGroup); + QQuickAction *action = qobject_cast<QQuickAction*>(q->sender()); + if (action) + emit q->triggered(action); +} + +void QQuickActionGroupPrivate::_q_updateCurrent() +{ + Q_Q(QQuickActionGroup); + if (!exclusive) + return; + QQuickAction *action = qobject_cast<QQuickAction*>(q->sender()); + if (action && action->isChecked()) + q->setCheckedAction(action); + else if (!actions.contains(checkedAction)) + q->setCheckedAction(nullptr); +} + +bool QQuickActionGroupPrivate::changeEnabled(QQuickAction *action, bool enabled) +{ + return action->isEnabled() != enabled && (!enabled || !QQuickActionPrivate::get(action)->explicitEnabled); +} + +void QQuickActionGroupPrivate::actions_append(QQmlListProperty<QQuickAction> *prop, QQuickAction *obj) +{ + QQuickActionGroup *q = static_cast<QQuickActionGroup *>(prop->object); + q->addAction(obj); +} + +int QQuickActionGroupPrivate::actions_count(QQmlListProperty<QQuickAction> *prop) +{ + QQuickActionGroupPrivate *p = static_cast<QQuickActionGroupPrivate *>(prop->data); + return p->actions.count(); +} + +QQuickAction *QQuickActionGroupPrivate::actions_at(QQmlListProperty<QQuickAction> *prop, int index) +{ + QQuickActionGroupPrivate *p = static_cast<QQuickActionGroupPrivate *>(prop->data); + return p->actions.value(index); +} + +void QQuickActionGroupPrivate::actions_clear(QQmlListProperty<QQuickAction> *prop) +{ + QQuickActionGroupPrivate *p = static_cast<QQuickActionGroupPrivate *>(prop->data); + if (!p->actions.isEmpty()) { + p->clear(); + QQuickActionGroup *q = static_cast<QQuickActionGroup *>(prop->object); + // QTBUG-52358: don't clear the checked action immediately + QMetaObject::invokeMethod(q, "_q_updateCurrent", Qt::QueuedConnection); + emit q->actionsChanged(); + } +} + +QQuickActionGroup::QQuickActionGroup(QObject *parent) + : QObject(*(new QQuickActionGroupPrivate), parent) +{ +} + +QQuickActionGroup::~QQuickActionGroup() +{ + Q_D(QQuickActionGroup); + d->clear(); +} + +QQuickActionGroupAttached *QQuickActionGroup::qmlAttachedProperties(QObject *object) +{ + return new QQuickActionGroupAttached(object); +} + +/*! + \qmlproperty Action QtQuick.Controls::ActionGroup::checkedAction + + This property holds the currently selected action in an exclusive group, + or \c null if there is none or the group is non-exclusive. + + By default, it is the first checked action added to an exclusive action group. + + \sa exclusive +*/ +QQuickAction *QQuickActionGroup::checkedAction() const +{ + Q_D(const QQuickActionGroup); + return d->checkedAction; +} + +void QQuickActionGroup::setCheckedAction(QQuickAction *checkedAction) +{ + Q_D(QQuickActionGroup); + if (d->checkedAction == checkedAction) + return; + + if (d->checkedAction) + d->checkedAction->setChecked(false); + d->checkedAction = checkedAction; + if (checkedAction) + checkedAction->setChecked(true); + emit checkedActionChanged(); +} + +/*! + \qmlproperty list<Action> QtQuick.Controls::ActionGroup::actions + \default + + This property holds the list of actions in the group. + + \sa group +*/ +QQmlListProperty<QQuickAction> QQuickActionGroup::actions() +{ + Q_D(QQuickActionGroup); + return QQmlListProperty<QQuickAction>(this, d, + QQuickActionGroupPrivate::actions_append, + QQuickActionGroupPrivate::actions_count, + QQuickActionGroupPrivate::actions_at, + QQuickActionGroupPrivate::actions_clear); +} + +/*! + \qmlproperty bool QtQuick.Controls::ActionGroup::exclusive + + This property holds whether the action group is exclusive. The default value is \c true. + + If this property is \c true, then only one action in the group can be checked at any given time. + The user can trigger any action to check it, and that action will replace the existing one as + the checked action in the group. + + In an exclusive group, the user cannot uncheck the currently checked action by triggering it; + instead, another action in the group must be triggered to set the new checked action for that + group. + + In a non-exclusive group, checking and unchecking actions does not affect the other actions in + the group. Furthermore, the value of the \l checkedAction property is \c null. +*/ +bool QQuickActionGroup::isExclusive() const +{ + Q_D(const QQuickActionGroup); + return d->exclusive; +} + +void QQuickActionGroup::setExclusive(bool exclusive) +{ + Q_D(QQuickActionGroup); + if (d->exclusive == exclusive) + return; + + d->exclusive = exclusive; + emit exclusiveChanged(); +} + +/*! + \qmlproperty bool QtQuick.Controls::ActionGroup::enabled + + This property holds whether the action group is enabled. The default value is \c true. + + If this property is \c false, then all actions in the group are disabled. If this property + is \c true, all actions in the group are enabled, unless explicitly disabled. +*/ +bool QQuickActionGroup::isEnabled() const +{ + Q_D(const QQuickActionGroup); + return d->enabled; +} + +void QQuickActionGroup::setEnabled(bool enabled) +{ + Q_D(QQuickActionGroup); + if (d->enabled == enabled) + return; + + for (QQuickAction *action : qAsConst(d->actions)) { + if (d->changeEnabled(action, enabled)) + emit action->enabledChanged(enabled); + } + + d->enabled = enabled; + emit enabledChanged(); +} + +/*! + \qmlmethod void QtQuick.Controls::ActionGroup::addAction(Action action) + + Adds an \a action to the action group. + + \note Manually adding objects to a action group is typically unnecessary. + The \l actions property and the \l group attached property provide a + convenient and declarative syntax. + + \sa actions, group +*/ +void QQuickActionGroup::addAction(QQuickAction *action) +{ + Q_D(QQuickActionGroup); + if (!action || d->actions.contains(action)) + return; + + const bool enabledChange = d->changeEnabled(action, d->enabled); + + QQuickActionPrivate::get(action)->group = this; + QObjectPrivate::connect(action, &QQuickAction::triggered, d, &QQuickActionGroupPrivate::actionTriggered); + QObjectPrivate::connect(action, &QQuickAction::checkedChanged, d, &QQuickActionGroupPrivate::_q_updateCurrent); + + if (d->exclusive && action->isChecked()) + setCheckedAction(action); + if (enabledChange) + emit action->enabledChanged(action->isEnabled()); + + d->actions.append(action); + emit actionsChanged(); +} + +/*! + \qmlmethod void QtQuick.Controls::ActionGroup::removeAction(Action action) + + Removes an \a action from the action group. + + \note Manually removing objects from a action group is typically unnecessary. + The \l actions property and the \l group attached property provide a + convenient and declarative syntax. + + \sa actions, group +*/ +void QQuickActionGroup::removeAction(QQuickAction *action) +{ + Q_D(QQuickActionGroup); + if (!action || !d->actions.contains(action)) + return; + + const bool enabledChange = d->changeEnabled(action, d->enabled); + + QQuickActionPrivate::get(action)->group = nullptr; + QObjectPrivate::disconnect(action, &QQuickAction::triggered, d, &QQuickActionGroupPrivate::actionTriggered); + QObjectPrivate::disconnect(action, &QQuickAction::checkedChanged, d, &QQuickActionGroupPrivate::_q_updateCurrent); + + if (d->checkedAction == action) + setCheckedAction(nullptr); + if (enabledChange) + emit action->enabledChanged(action->isEnabled()); + + d->actions.removeOne(action); + emit actionsChanged(); +} + +class QQuickActionGroupAttachedPrivate : public QObjectPrivate +{ +public: + QQuickActionGroupAttachedPrivate() : group(nullptr) { } + + QQuickActionGroup *group; +}; + +QQuickActionGroupAttached::QQuickActionGroupAttached(QObject *parent) + : QObject(*(new QQuickActionGroupAttachedPrivate), parent) +{ +} + +/*! + \qmlattachedproperty ActionGroup QtQuick.Controls::ActionGroup::group + + This property attaches an action to an action group. + + \code + ActionGroup { id: group } + + Action { + checked: true + text: qsTr("Option A") + ActionGroup.group: group + } + + Action { + text: qsTr("Option B") + ActionGroup.group: group + } + \endcode + + \sa actions +*/ +QQuickActionGroup *QQuickActionGroupAttached::group() const +{ + Q_D(const QQuickActionGroupAttached); + return d->group; +} + +void QQuickActionGroupAttached::setGroup(QQuickActionGroup *group) +{ + Q_D(QQuickActionGroupAttached); + if (d->group == group) + return; + + if (d->group) + d->group->removeAction(qobject_cast<QQuickAction*>(parent())); + d->group = group; + if (group) + group->addAction(qobject_cast<QQuickAction*>(parent())); + emit groupChanged(); +} + +QT_END_NAMESPACE + +#include "moc_qquickactiongroup_p.cpp" diff --git a/src/quicktemplates2/qquickactiongroup_p.h b/src/quicktemplates2/qquickactiongroup_p.h new file mode 100644 index 00000000..42280831 --- /dev/null +++ b/src/quicktemplates2/qquickactiongroup_p.h @@ -0,0 +1,129 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Templates 2 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 QQUICKACTIONGROUP_P_H +#define QQUICKACTIONGROUP_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 <QtCore/qobject.h> +#include <QtQuickTemplates2/private/qtquicktemplates2global_p.h> +#include <QtQml/qqml.h> + +QT_BEGIN_NAMESPACE + +class QQuickAction; +class QQuickActionGroupPrivate; +class QQuickActionGroupAttached; +class QQuickActionGroupAttachedPrivate; + +class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickActionGroup : public QObject +{ + Q_OBJECT + Q_PROPERTY(QQuickAction *checkedAction READ checkedAction WRITE setCheckedAction NOTIFY checkedActionChanged FINAL) + Q_PROPERTY(QQmlListProperty<QQuickAction> actions READ actions NOTIFY actionsChanged FINAL) + Q_PROPERTY(bool exclusive READ isExclusive WRITE setExclusive NOTIFY exclusiveChanged FINAL) + Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged FINAL) + +public: + explicit QQuickActionGroup(QObject *parent = nullptr); + ~QQuickActionGroup(); + + static QQuickActionGroupAttached *qmlAttachedProperties(QObject *object); + + QQuickAction *checkedAction() const; + void setCheckedAction(QQuickAction *checkedAction); + + QQmlListProperty<QQuickAction> actions(); + + bool isExclusive() const; + void setExclusive(bool exclusive); + + bool isEnabled() const; + void setEnabled(bool enabled); + +public Q_SLOTS: + void addAction(QQuickAction *action); + void removeAction(QQuickAction *action); + +Q_SIGNALS: + void checkedActionChanged(); + void actionsChanged(); + void exclusiveChanged(); + void enabledChanged(); + void triggered(QQuickAction *action); + +private: + Q_DISABLE_COPY(QQuickActionGroup) + Q_DECLARE_PRIVATE(QQuickActionGroup) + + Q_PRIVATE_SLOT(d_func(), void _q_updateCurrent()) +}; + +class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickActionGroupAttached : public QObject +{ + Q_OBJECT + Q_PROPERTY(QQuickActionGroup *group READ group WRITE setGroup NOTIFY groupChanged FINAL) + +public: + explicit QQuickActionGroupAttached(QObject *parent = nullptr); + + QQuickActionGroup *group() const; + void setGroup(QQuickActionGroup *group); + +Q_SIGNALS: + void groupChanged(); + +private: + Q_DISABLE_COPY(QQuickActionGroupAttached) + Q_DECLARE_PRIVATE(QQuickActionGroupAttached) +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QQuickActionGroup) +QML_DECLARE_TYPEINFO(QQuickActionGroup, QML_HAS_ATTACHED_PROPERTIES) + +#endif // QQUICKACTIONGROUP_P_H diff --git a/src/quicktemplates2/qquickapplicationwindow.cpp b/src/quicktemplates2/qquickapplicationwindow.cpp index 0cd78502..ff062259 100644 --- a/src/quicktemplates2/qquickapplicationwindow.cpp +++ b/src/quicktemplates2/qquickapplicationwindow.cpp @@ -168,6 +168,14 @@ public: } void resolveFont(); + void updatePalette(const QPalette &p); + inline void setPalette_helper(const QPalette &p) { + if (palette.resolve() == p.resolve() && palette == p) + return; + updatePalette(p); + } + void resolvePalette(); + void _q_updateActiveFocus(); void setActiveFocusControl(QQuickItem *item); @@ -179,6 +187,7 @@ public: QQuickOverlay *overlay; QFont font; QLocale locale; + QPalette palette; QQuickItem *activeFocusControl; QQuickApplicationWindow *q_ptr; }; @@ -251,6 +260,53 @@ void QQuickApplicationWindowPrivate::itemImplicitHeightChanged(QQuickItem *item) relayout(); } +void QQuickApplicationWindowPrivate::updateFont(const QFont &f) +{ + Q_Q(QQuickApplicationWindow); + const bool changed = font != f; + font = f; + + QQuickControlPrivate::updateFontRecur(q->QQuickWindow::contentItem(), f); + + // TODO: internal QQuickPopupManager that provides reliable access to all QQuickPopup instances + const QList<QQuickPopup *> popups = q->findChildren<QQuickPopup *>(); + for (QQuickPopup *popup : popups) + QQuickControlPrivate::get(static_cast<QQuickControl *>(popup->popupItem()))->inheritFont(f); + + if (changed) + emit q->fontChanged(); +} + +void QQuickApplicationWindowPrivate::resolveFont() +{ + QFont resolvedFont = font.resolve(QQuickControlPrivate::themeFont(QPlatformTheme::SystemFont)); + setFont_helper(resolvedFont); +} + +void QQuickApplicationWindowPrivate::updatePalette(const QPalette &p) +{ + Q_Q(QQuickApplicationWindow); + const bool changed = palette != p; + palette = p; + + QQuickItem *rootItem = q->QQuickWindow::contentItem(); + QQuickControlPrivate::updatePaletteRecur(rootItem, p); + + // TODO: internal QQuickPopupManager that provides reliable access to all QQuickPopup instances + const QList<QQuickPopup *> popups = rootItem->findChildren<QQuickPopup *>(); + for (QQuickPopup *popup : popups) + QQuickControlPrivate::get(static_cast<QQuickControl *>(popup->popupItem()))->inheritPalette(p); + + if (changed) + emit q->paletteChanged(); +} + +void QQuickApplicationWindowPrivate::resolvePalette() +{ + QPalette resolvedPalette = palette.resolve(QQuickControlPrivate::themePalette(QPlatformTheme::SystemPalette)); + setPalette_helper(resolvedPalette); +} + void QQuickApplicationWindowPrivate::_q_updateActiveFocus() { Q_Q(QQuickApplicationWindow); @@ -614,28 +670,6 @@ void QQuickApplicationWindow::resetFont() setFont(QFont()); } -void QQuickApplicationWindowPrivate::resolveFont() -{ - QFont resolvedFont = font.resolve(QQuickControlPrivate::themeFont(QPlatformTheme::SystemFont)); - setFont_helper(resolvedFont); -} - -void QQuickApplicationWindowPrivate::updateFont(const QFont &f) -{ - Q_Q(QQuickApplicationWindow); - const bool changed = font != f; - font = f; - - QQuickControlPrivate::updateFontRecur(q->QQuickWindow::contentItem(), f); - - // TODO: internal QQuickPopupManager that provides reliable access to all QQuickPopup instances - const QList<QQuickPopup *> popups = q->findChildren<QQuickPopup *>(); - for (QQuickPopup *popup : popups) - QQuickControlPrivate::get(static_cast<QQuickControl *>(popup->popupItem()))->inheritFont(f); - - if (changed) - emit q->fontChanged(); -} /*! \qmlproperty Locale QtQuick.Controls::ApplicationWindow::locale @@ -679,6 +713,43 @@ void QQuickApplicationWindow::resetLocale() setLocale(QLocale()); } +/*! + \since QtQuick.Controls 2.3 (Qt 5.10) + \qmlproperty palette QtQuick.Controls::ApplicationWindow::palette + + This property holds the palette currently set for the window. + + The default palette depends on the system environment. QGuiApplication maintains a system/theme + palette which serves as a default for all application windows. You can also set the default palette + for windows by passing a custom palette to QGuiApplication::setPalette(), before loading any QML. + + ApplicationWindow propagates explicit palette properties to child controls. If you change a specific + property on the window's palette, that property propagates to all child controls in the window, + overriding any system defaults for that property. + + \sa Control::palette +*/ +QPalette QQuickApplicationWindow::palette() const +{ + Q_D(const QQuickApplicationWindow); + return d->palette; +} + +void QQuickApplicationWindow::setPalette(const QPalette &palette) +{ + Q_D(QQuickApplicationWindow); + if (d->palette.resolve() == palette.resolve() && d->palette == palette) + return; + + QPalette resolvedPalette = palette.resolve(QQuickControlPrivate::themePalette(QPlatformTheme::SystemPalette)); + d->setPalette_helper(resolvedPalette); +} + +void QQuickApplicationWindow::resetPalette() +{ + setPalette(QPalette()); +} + QQuickApplicationWindowAttached *QQuickApplicationWindow::qmlAttachedProperties(QObject *object) { return new QQuickApplicationWindowAttached(object); @@ -696,6 +767,7 @@ void QQuickApplicationWindow::classBegin() d->complete = false; QQuickWindowQmlImpl::classBegin(); d->resolveFont(); + d->resolvePalette(); } void QQuickApplicationWindow::componentComplete() diff --git a/src/quicktemplates2/qquickapplicationwindow_p.h b/src/quicktemplates2/qquickapplicationwindow_p.h index 07ddc67e..8747e70f 100644 --- a/src/quicktemplates2/qquickapplicationwindow_p.h +++ b/src/quicktemplates2/qquickapplicationwindow_p.h @@ -51,6 +51,7 @@ #include <QtQuick/private/qquickwindowmodule_p.h> #include <QtQuickTemplates2/private/qtquicktemplates2global_p.h> #include <QtGui/qfont.h> +#include <QtGui/qpalette.h> #include <QtCore/qlocale.h> QT_BEGIN_NAMESPACE @@ -72,6 +73,7 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickApplicationWindow : public QQuickWi Q_PROPERTY(QQuickOverlay *overlay READ overlay CONSTANT FINAL) Q_PROPERTY(QFont font READ font WRITE setFont RESET resetFont NOTIFY fontChanged FINAL) Q_PROPERTY(QLocale locale READ locale WRITE setLocale RESET resetLocale NOTIFY localeChanged FINAL) + Q_PROPERTY(QPalette palette READ palette WRITE setPalette RESET resetPalette NOTIFY paletteChanged FINAL REVISION 3) Q_CLASSINFO("DefaultProperty", "contentData") public: @@ -102,6 +104,10 @@ public: void setLocale(const QLocale &locale); void resetLocale(); + QPalette palette() const; + void setPalette(const QPalette &palette); + void resetPalette(); + static QQuickApplicationWindowAttached *qmlAttachedProperties(QObject *object); Q_SIGNALS: @@ -111,6 +117,7 @@ Q_SIGNALS: void footerChanged(); void fontChanged(); void localeChanged(); + Q_REVISION(3) void paletteChanged(); protected: bool isComponentComplete() const; diff --git a/src/quicktemplates2/qquickbutton.cpp b/src/quicktemplates2/qquickbutton.cpp index 1a614754..b5a8ac1c 100644 --- a/src/quicktemplates2/qquickbutton.cpp +++ b/src/quicktemplates2/qquickbutton.cpp @@ -77,6 +77,9 @@ QT_BEGIN_NAMESPACE } \endcode + In addition to displaying \l {AbstractButton::}{text}, buttons can also + display an \l [QML]{Button Icons}{icon}. + \sa {Customizing Button}, {Button Controls} */ @@ -119,6 +122,11 @@ QFont QQuickButton::defaultFont() const return QQuickControlPrivate::themeFont(QPlatformTheme::PushButtonFont); } +QPalette QQuickButton::defaultPalette() const +{ + return QQuickControlPrivate::themePalette(QPlatformTheme::ButtonPalette); +} + /*! \qmlproperty bool QtQuick.Controls::Button::highlighted diff --git a/src/quicktemplates2/qquickbutton_p.h b/src/quicktemplates2/qquickbutton_p.h index 93fb3c14..f1a34b10 100644 --- a/src/quicktemplates2/qquickbutton_p.h +++ b/src/quicktemplates2/qquickbutton_p.h @@ -81,6 +81,7 @@ protected: void buttonChange(ButtonChange change) override; QFont defaultFont() const override; + QPalette defaultPalette() const override; private: Q_DISABLE_COPY(QQuickButton) diff --git a/src/quicktemplates2/qquickbuttongroup.cpp b/src/quicktemplates2/qquickbuttongroup.cpp index f0813a17..ef35440f 100644 --- a/src/quicktemplates2/qquickbuttongroup.cpp +++ b/src/quicktemplates2/qquickbuttongroup.cpp @@ -154,7 +154,11 @@ class QQuickButtonGroupPrivate : public QObjectPrivate Q_DECLARE_PUBLIC(QQuickButtonGroup) public: - QQuickButtonGroupPrivate() : checkedButton(nullptr) { } + QQuickButtonGroupPrivate() + : exclusive(true), + checkedButton(nullptr) + { + } void clear(); void buttonClicked(); @@ -165,6 +169,7 @@ public: static QQuickAbstractButton *buttons_at(QQmlListProperty<QQuickAbstractButton> *prop, int index); static void buttons_clear(QQmlListProperty<QQuickAbstractButton> *prop); + bool exclusive; QQuickAbstractButton *checkedButton; QVector<QQuickAbstractButton*> buttons; }; @@ -190,6 +195,8 @@ void QQuickButtonGroupPrivate::buttonClicked() void QQuickButtonGroupPrivate::_q_updateCurrent() { Q_Q(QQuickButtonGroup); + if (!exclusive) + return; QQuickAbstractButton *button = qobject_cast<QQuickAbstractButton*>(q->sender()); if (button && button->isChecked()) q->setCheckedButton(button); @@ -246,9 +253,12 @@ QQuickButtonGroupAttached *QQuickButtonGroup::qmlAttachedProperties(QObject *obj /*! \qmlproperty AbstractButton QtQuick.Controls::ButtonGroup::checkedButton - This property holds the currently selected button, or \c null if there is none. + This property holds the currently selected button in an exclusive group, + or \c null if there is none or the group is non-exclusive. + + By default, it is the first checked button added to an exclusive button group. - By default, it is the first checked button added to the button group. + \sa exclusive */ QQuickAbstractButton *QQuickButtonGroup::checkedButton() const { @@ -308,6 +318,38 @@ QQmlListProperty<QQuickAbstractButton> QQuickButtonGroup::buttons() } /*! + \since QtQuick.Controls 2.3 (Qt 5.10) + \qmlproperty bool QtQuick.Controls::ButtonGroup::exclusive + + This property holds whether the button group is exclusive. The default value is \c true. + + If this property is \c true, then only one button in the group can be checked at any given time. + The user can click on any button to check it, and that button will replace the existing one as + the checked button in the group. + + In an exclusive group, the user cannot uncheck the currently checked button by clicking on it; + instead, another button in the group must be clicked to set the new checked button for that group. + + In a non-exclusive group, checking and unchecking buttons does not affect the other buttons in + the group. Furthermore, the value of the \l checkedButton property is \c null. +*/ +bool QQuickButtonGroup::isExclusive() const +{ + Q_D(const QQuickButtonGroup); + return d->exclusive; +} + +void QQuickButtonGroup::setExclusive(bool exclusive) +{ + Q_D(QQuickButtonGroup); + if (d->exclusive == exclusive) + return; + + d->exclusive = exclusive; + emit exclusiveChanged(); +} + +/*! \qmlmethod void QtQuick.Controls::ButtonGroup::addButton(AbstractButton button) Adds a \a button to the button group. @@ -328,7 +370,7 @@ void QQuickButtonGroup::addButton(QQuickAbstractButton *button) QObjectPrivate::connect(button, &QQuickAbstractButton::clicked, d, &QQuickButtonGroupPrivate::buttonClicked); QObjectPrivate::connect(button, &QQuickAbstractButton::checkedChanged, d, &QQuickButtonGroupPrivate::_q_updateCurrent); - if (button->isChecked()) + if (d->exclusive && button->isChecked()) setCheckedButton(button); d->buttons.append(button); diff --git a/src/quicktemplates2/qquickbuttongroup_p.h b/src/quicktemplates2/qquickbuttongroup_p.h index 21deb035..cd46d8f7 100644 --- a/src/quicktemplates2/qquickbuttongroup_p.h +++ b/src/quicktemplates2/qquickbuttongroup_p.h @@ -62,8 +62,9 @@ class QQuickButtonGroupAttachedPrivate; class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickButtonGroup : public QObject { Q_OBJECT - Q_PROPERTY(QQuickAbstractButton *checkedButton READ checkedButton WRITE setCheckedButton NOTIFY checkedButtonChanged) + Q_PROPERTY(QQuickAbstractButton *checkedButton READ checkedButton WRITE setCheckedButton NOTIFY checkedButtonChanged FINAL) Q_PROPERTY(QQmlListProperty<QQuickAbstractButton> buttons READ buttons NOTIFY buttonsChanged FINAL) + Q_PROPERTY(bool exclusive READ isExclusive WRITE setExclusive NOTIFY exclusiveChanged FINAL REVISION 3) public: explicit QQuickButtonGroup(QObject *parent = nullptr); @@ -76,6 +77,9 @@ public: QQmlListProperty<QQuickAbstractButton> buttons(); + bool isExclusive() const; + void setExclusive(bool exclusive); + public Q_SLOTS: void addButton(QQuickAbstractButton *button); void removeButton(QQuickAbstractButton *button); @@ -83,6 +87,7 @@ public Q_SLOTS: Q_SIGNALS: void checkedButtonChanged(); void buttonsChanged(); + Q_REVISION(3) void exclusiveChanged(); Q_REVISION(1) void clicked(QQuickAbstractButton *button); private: diff --git a/src/quicktemplates2/qquickcheckbox.cpp b/src/quicktemplates2/qquickcheckbox.cpp index e0c7faf1..2e0c401a 100644 --- a/src/quicktemplates2/qquickcheckbox.cpp +++ b/src/quicktemplates2/qquickcheckbox.cpp @@ -174,6 +174,11 @@ QFont QQuickCheckBox::defaultFont() const return QQuickControlPrivate::themeFont(QPlatformTheme::CheckBoxFont); } +QPalette QQuickCheckBox::defaultPalette() const +{ + return QQuickControlPrivate::themePalette(QPlatformTheme::CheckBoxPalette); +} + void QQuickCheckBox::buttonChange(ButtonChange change) { if (change == ButtonCheckedChange) diff --git a/src/quicktemplates2/qquickcheckbox_p.h b/src/quicktemplates2/qquickcheckbox_p.h index dfd935d3..979f096b 100644 --- a/src/quicktemplates2/qquickcheckbox_p.h +++ b/src/quicktemplates2/qquickcheckbox_p.h @@ -75,6 +75,7 @@ Q_SIGNALS: protected: QFont defaultFont() const override; + QPalette defaultPalette() const override; void buttonChange(ButtonChange change) override; void nextCheckState() override; diff --git a/src/quicktemplates2/qquickcombobox.cpp b/src/quicktemplates2/qquickcombobox.cpp index d987182c..a6f9f6ca 100644 --- a/src/quicktemplates2/qquickcombobox.cpp +++ b/src/quicktemplates2/qquickcombobox.cpp @@ -37,6 +37,7 @@ #include "qquickcombobox_p.h" #include "qquickcontrol_p_p.h" #include "qquickabstractbutton_p.h" +#include "qquickabstractbutton_p_p.h" #include "qquickpopup_p_p.h" #include <QtCore/qregexp.h> @@ -50,6 +51,7 @@ #include <QtQml/private/qqmldelegatemodel_p.h> #include <QtQuick/private/qquickevents_p_p.h> #include <QtQuick/private/qquicktextinput_p.h> +#include <QtQuick/private/qquickitemview_p.h> QT_BEGIN_NAMESPACE @@ -221,6 +223,7 @@ public: void popupVisibleChanged(); void itemClicked(); + void itemHovered(); void createdItem(int index, QObject *object); void modelUpdated(); @@ -253,6 +256,7 @@ public: bool hasDown; bool pressed; bool ownModel; + bool keyNavigating; bool hasDisplayText; bool hasCurrentIndex; int highlightedIndex; @@ -291,6 +295,7 @@ QQuickComboBoxPrivate::QQuickComboBoxPrivate() hasDown(false), pressed(false), ownModel(false), + keyNavigating(false), hasDisplayText(false), hasCurrentIndex(false), highlightedIndex(-1), @@ -341,7 +346,15 @@ void QQuickComboBoxPrivate::popupVisibleChanged() if (isPopupVisible()) QGuiApplication::inputMethod()->reset(); + QQuickItemView *itemView = popup->findChild<QQuickItemView *>(); + if (itemView) + itemView->setHighlightRangeMode(QQuickItemView::NoHighlightRange); + updateHighlightedIndex(); + + if (itemView) + itemView->positionViewAtIndex(highlightedIndex, QQuickItemView::Beginning); + if (!hasDown) { q->setDown(pressed || isPopupVisible()); hasDown = false; @@ -358,6 +371,25 @@ void QQuickComboBoxPrivate::itemClicked() } } +void QQuickComboBoxPrivate::itemHovered() +{ + Q_Q(QQuickComboBox); + if (keyNavigating) + return; + + QQuickAbstractButton *button = qobject_cast<QQuickAbstractButton *>(q->sender()); + if (!button || !button->isHovered() || QQuickAbstractButtonPrivate::get(button)->touchId != -1) + return; + + int index = delegateModel->indexOf(button, nullptr); + if (index != -1) { + setHighlightedIndex(index, Highlight); + + if (QQuickItemView *itemView = popup->findChild<QQuickItemView *>()) + itemView->positionViewAtIndex(index, QQuickItemView::Contain); + } +} + void QQuickComboBoxPrivate::createdItem(int index, QObject *object) { Q_Q(QQuickComboBox); @@ -371,6 +403,7 @@ void QQuickComboBoxPrivate::createdItem(int index, QObject *object) if (button) { button->setFocusPolicy(Qt::NoFocus); connect(button, &QQuickAbstractButton::clicked, this, &QQuickComboBoxPrivate::itemClicked); + connect(button, &QQuickAbstractButton::hoveredChanged, this, &QQuickComboBoxPrivate::itemHovered); } if (index == currentIndex && !q->isEditable()) @@ -1163,6 +1196,9 @@ void QQuickComboBox::setPopup(QQuickPopup *popup) QQuickPopupPrivate::get(popup)->allowVerticalFlip = true; popup->setClosePolicy(QQuickPopup::CloseOnEscape | QQuickPopup::CloseOnPressOutsideParent); QObjectPrivate::connect(popup, &QQuickPopup::visibleChanged, d, &QQuickComboBoxPrivate::popupVisibleChanged); + + if (QQuickItemView *itemView = popup->findChild<QQuickItemView *>()) + itemView->setHighlightRangeMode(QQuickItemView::NoHighlightRange); } d->popup = popup; emit popupChanged(); @@ -1454,14 +1490,17 @@ void QQuickComboBox::keyPressEvent(QKeyEvent *event) event->accept(); break; case Qt::Key_Up: + d->keyNavigating = true; d->decrementCurrentIndex(); event->accept(); break; case Qt::Key_Down: + d->keyNavigating = true; d->incrementCurrentIndex(); event->accept(); break; case Qt::Key_Home: + d->keyNavigating = true; if (d->isPopupVisible()) d->setHighlightedIndex(0, Highlight); else @@ -1469,6 +1508,7 @@ void QQuickComboBox::keyPressEvent(QKeyEvent *event) event->accept(); break; case Qt::Key_End: + d->keyNavigating = true; if (d->isPopupVisible()) d->setHighlightedIndex(count() - 1, Highlight); else @@ -1488,6 +1528,8 @@ void QQuickComboBox::keyReleaseEvent(QKeyEvent *event) { Q_D(QQuickComboBox); QQuickControl::keyReleaseEvent(event); + + d->keyNavigating = false; if (!d->popup || event->isAutoRepeat()) return; @@ -1588,6 +1630,11 @@ QFont QQuickComboBox::defaultFont() const return QQuickControlPrivate::themeFont(QPlatformTheme::ComboMenuItemFont); } +QPalette QQuickComboBox::defaultPalette() const +{ + return QQuickControlPrivate::themePalette(QPlatformTheme::ComboBoxPalette); +} + #if QT_CONFIG(accessibility) QAccessible::Role QQuickComboBox::accessibleRole() const { diff --git a/src/quicktemplates2/qquickcombobox_p.h b/src/quicktemplates2/qquickcombobox_p.h index 851392aa..ce9ff17e 100644 --- a/src/quicktemplates2/qquickcombobox_p.h +++ b/src/quicktemplates2/qquickcombobox_p.h @@ -192,6 +192,7 @@ protected: void localeChange(const QLocale &newLocale, const QLocale &oldLocale) override; QFont defaultFont() const override; + QPalette defaultPalette() const override; #if QT_CONFIG(accessibility) QAccessible::Role accessibleRole() const override; diff --git a/src/quicktemplates2/qquickcontainer.cpp b/src/quicktemplates2/qquickcontainer.cpp index 6177d200..9b8298c2 100644 --- a/src/quicktemplates2/qquickcontainer.cpp +++ b/src/quicktemplates2/qquickcontainer.cpp @@ -253,13 +253,17 @@ void QQuickContainerPrivate::insertItem(int index, QQuickItem *item) q->itemAdded(index, item); - if (contentModel->count() == 1 && currentIndex == -1) + int count = contentModel->count(); + for (int i = index + 1; i < count; ++i) + q->itemMoved(i, itemAt(i)); + + if (count == 1 && currentIndex == -1) q->setCurrentIndex(index); updatingCurrent = false; } -void QQuickContainerPrivate::moveItem(int from, int to) +void QQuickContainerPrivate::moveItem(int from, int to, QQuickItem *item) { Q_Q(QQuickContainer); int oldCurrent = currentIndex; @@ -267,6 +271,16 @@ void QQuickContainerPrivate::moveItem(int from, int to) updatingCurrent = true; + q->itemMoved(to, item); + + if (from < to) { + for (int i = from; i < to; ++i) + q->itemMoved(i, itemAt(i)); + } else { + for (int i = from; i > to; --i) + q->itemMoved(i, itemAt(i)); + } + if (from == oldCurrent) q->setCurrentIndex(to); else if (from < oldCurrent && to >= oldCurrent) @@ -300,6 +314,10 @@ void QQuickContainerPrivate::removeItem(int index, QQuickItem *item) q->itemRemoved(index, item); + int count = contentModel->count(); + for (int i = index; i < count; ++i) + q->itemMoved(i, itemAt(i)); + if (currentChanged) emit q->currentIndexChanged(); @@ -476,7 +494,7 @@ void QQuickContainer::insertItem(int index, QQuickItem *item) if (oldIndex < index) --index; if (oldIndex != index) - d->moveItem(oldIndex, index); + d->moveItem(oldIndex, index, item); } else { d->insertItem(index, item); } @@ -497,26 +515,65 @@ void QQuickContainer::moveItem(int from, int to) to = count - 1; if (from != to) - d->moveItem(from, to); + d->moveItem(from, to, d->itemAt(from)); } /*! + \deprecated \qmlmethod void QtQuick.Controls::Container::removeItem(int index) - Removes an item at \a index. + Use Container::removeItem(Item) or Container::takeItem(int) instead. +*/ +void QQuickContainer::removeItem(const QVariant &var) +{ + if (var.userType() == QMetaType::Nullptr) + return; + + if (QQuickItem *item = var.value<QQuickItem *>()) + removeItem(item); + else + takeItem(var.toInt()); +} + +/*! + \since QtQuick.Controls 2.3 (Qt 5.10) + \qmlmethod void QtQuick.Controls::Container::removeItem(Item item) + + Removes and destroys the specified \a item. +*/ +void QQuickContainer::removeItem(QQuickItem *item) +{ + Q_D(QQuickContainer); + if (!item) + return; + + const int index = d->contentModel->indexOf(item, nullptr); + if (index == -1) + return; + + d->removeItem(index, item); + item->deleteLater(); +} + +/*! + \since QtQuick.Controls 2.3 (Qt 5.10) + \qmlmethod Item QtQuick.Controls::Container::takeItem(int index) + + Removes and returns the item at \a index. \note The ownership of the item is transferred to the caller. */ -void QQuickContainer::removeItem(int index) +QQuickItem *QQuickContainer::takeItem(int index) { Q_D(QQuickContainer); const int count = d->contentModel->count(); if (index < 0 || index >= count) - return; + return nullptr; QQuickItem *item = itemAt(index); if (item) d->removeItem(index, item); + return item; } /*! @@ -735,6 +792,12 @@ void QQuickContainer::itemAdded(int index, QQuickItem *item) Q_UNUSED(item); } +void QQuickContainer::itemMoved(int index, QQuickItem *item) +{ + Q_UNUSED(index); + Q_UNUSED(item); +} + void QQuickContainer::itemRemoved(int index, QQuickItem *item) { Q_UNUSED(index); diff --git a/src/quicktemplates2/qquickcontainer_p.h b/src/quicktemplates2/qquickcontainer_p.h index 6db45589..5ac585c2 100644 --- a/src/quicktemplates2/qquickcontainer_p.h +++ b/src/quicktemplates2/qquickcontainer_p.h @@ -75,7 +75,9 @@ public: Q_INVOKABLE void addItem(QQuickItem *item); Q_INVOKABLE void insertItem(int index, QQuickItem *item); Q_INVOKABLE void moveItem(int from, int to); - Q_INVOKABLE void removeItem(int index); + Q_INVOKABLE void removeItem(const QVariant &item); // ### Qt 6: remove + void removeItem(QQuickItem *item); // ### Qt 6: Q_INVOKABLE + Q_REVISION(3) Q_INVOKABLE QQuickItem *takeItem(int index); QVariant contentModel() const; QQmlListProperty<QObject> contentData(); @@ -103,6 +105,7 @@ protected: virtual bool isContent(QQuickItem *item) const; virtual void itemAdded(int index, QQuickItem *item); + virtual void itemMoved(int index, QQuickItem *item); virtual void itemRemoved(int index, QQuickItem *item); private: diff --git a/src/quicktemplates2/qquickcontainer_p_p.h b/src/quicktemplates2/qquickcontainer_p_p.h index 38c6b3e4..cbc04f9a 100644 --- a/src/quicktemplates2/qquickcontainer_p_p.h +++ b/src/quicktemplates2/qquickcontainer_p_p.h @@ -66,7 +66,7 @@ public: QQuickItem *itemAt(int index) const; void insertItem(int index, QQuickItem *item); - void moveItem(int from, int to); + void moveItem(int from, int to, QQuickItem *item); void removeItem(int index, QQuickItem *item); void _q_currentIndexChanged(); diff --git a/src/quicktemplates2/qquickcontrol.cpp b/src/quicktemplates2/qquickcontrol.cpp index a2b16a10..06f8c8a2 100644 --- a/src/quicktemplates2/qquickcontrol.cpp +++ b/src/quicktemplates2/qquickcontrol.cpp @@ -130,8 +130,7 @@ QQuickControlPrivate::QQuickControlPrivate() focusPolicy(Qt::NoFocus), focusReason(Qt::OtherFocusReason), background(nullptr), - contentItem(nullptr), - accessibleAttached(nullptr) + contentItem(nullptr) { #if QT_CONFIG(accessibility) QAccessible::installActivationObserver(this); @@ -314,29 +313,6 @@ QAccessible::Role QQuickControlPrivate::accessibleRole() const Q_Q(const QQuickControl); return q->accessibleRole(); } - -QAccessible::Role QQuickControl::accessibleRole() const -{ - return QAccessible::NoRole; -} - -void QQuickControl::accessibilityActiveChanged(bool active) -{ - Q_D(QQuickControl); - if (d->accessibleAttached || !active) - return; - - d->accessibleAttached = qobject_cast<QQuickAccessibleAttached *>(qmlAttachedPropertiesObject<QQuickAccessibleAttached>(this, true)); - - // QQuickControl relies on the existence of a QQuickAccessibleAttached object. - // However, qmlAttachedPropertiesObject(create=true) creates an instance only - // for items that have been created by a QML engine. Therefore we create the - // object by hand for items created in C++ (QQuickPopupItem, for instance). - if (!d->accessibleAttached) - d->accessibleAttached = new QQuickAccessibleAttached(this); - - d->accessibleAttached->setRole(accessibleRole()); -} #endif /*! @@ -395,11 +371,11 @@ void QQuickControlPrivate::resolveFont() inheritFont(parentFont(q)); } -void QQuickControlPrivate::inheritFont(const QFont &f) +void QQuickControlPrivate::inheritFont(const QFont &font) { Q_Q(QQuickControl); - QFont parentFont = extra.isAllocated() ? extra->font.resolve(f) : f; - parentFont.resolve(extra.isAllocated() ? extra->font.resolve() | f.resolve() : f.resolve()); + QFont parentFont = extra.isAllocated() ? extra->requestedFont.resolve(font) : font; + parentFont.resolve(extra.isAllocated() ? extra->requestedFont.resolve() | font.resolve() : font.resolve()); const QFont defaultFont = q->defaultFont(); const QFont resolvedFont = parentFont.resolve(defaultFont); @@ -412,35 +388,192 @@ void QQuickControlPrivate::inheritFont(const QFont &f) Assign \a font to this control, and propagate it to all children. */ -void QQuickControlPrivate::updateFont(const QFont &f) +void QQuickControlPrivate::updateFont(const QFont &font) { Q_Q(QQuickControl); - QFont old = resolvedFont; - resolvedFont = f; + QFont oldFont = resolvedFont; + resolvedFont = font; - if (old != f) - q->fontChange(f, old); + if (oldFont != font) + q->fontChange(font, oldFont); - QQuickControlPrivate::updateFontRecur(q, f); + QQuickControlPrivate::updateFontRecur(q, font); - if (old != f) + if (oldFont != font) emit q->fontChanged(); } -void QQuickControlPrivate::updateFontRecur(QQuickItem *item, const QFont &f) +void QQuickControlPrivate::updateFontRecur(QQuickItem *item, const QFont &font) +{ + const auto childItems = item->childItems(); + for (QQuickItem *child : childItems) { + if (QQuickControl *control = qobject_cast<QQuickControl *>(child)) + QQuickControlPrivate::get(control)->inheritFont(font); + else if (QQuickLabel *label = qobject_cast<QQuickLabel *>(child)) + QQuickLabelPrivate::get(label)->inheritFont(font); + else if (QQuickTextArea *textArea = qobject_cast<QQuickTextArea *>(child)) + QQuickTextAreaPrivate::get(textArea)->inheritFont(font); + else if (QQuickTextField *textField = qobject_cast<QQuickTextField *>(child)) + QQuickTextFieldPrivate::get(textField)->inheritFont(font); + else + QQuickControlPrivate::updateFontRecur(child, font); + } +} + +/*! + \internal + + Returns the palette that the item inherits from its ancestors and + QGuiApplication::palette. +*/ +QPalette QQuickControlPrivate::parentPalette(const QQuickItem *item) +{ + QQuickItem *p = item->parentItem(); + while (p) { + if (QQuickControl *control = qobject_cast<QQuickControl *>(p)) + return control->palette(); + else if (QQuickLabel *label = qobject_cast<QQuickLabel *>(p)) + return label->palette(); + else if (QQuickTextField *textField = qobject_cast<QQuickTextField *>(p)) + return textField->palette(); + else if (QQuickTextArea *textArea = qobject_cast<QQuickTextArea *>(p)) + return textArea->palette(); + + p = p->parentItem(); + } + + if (QQuickApplicationWindow *window = qobject_cast<QQuickApplicationWindow *>(item->window())) + return window->palette(); + + return themePalette(QPlatformTheme::SystemPalette); +} + +QPalette QQuickControlPrivate::themePalette(QPlatformTheme::Palette type) +{ + if (QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) { + if (const QPalette *palette = theme->palette(type)) { + QPalette p = *palette; + if (type == QPlatformTheme::SystemPalette) + p.resolve(0); + return p; + } + } + + return QPalette(); +} + +/*! + \internal + + Determine which palette is implicitly imposed on this control by its ancestors + and QGuiApplication::palette, resolve this against its own palette (attributes from + the implicit palette are copied over). Then propagate this palette to this + control's children. +*/ +void QQuickControlPrivate::resolvePalette() +{ + Q_Q(QQuickControl); + inheritPalette(parentPalette(q)); +} + +void QQuickControlPrivate::inheritPalette(const QPalette &palette) +{ + Q_Q(QQuickControl); + QPalette parentPalette = extra.isAllocated() ? extra->requestedPalette.resolve(palette) : palette; + parentPalette.resolve(extra.isAllocated() ? extra->requestedPalette.resolve() | palette.resolve() : palette.resolve()); + + const QPalette defaultPalette = q->defaultPalette(); + const QPalette resolvedPalette = parentPalette.resolve(defaultPalette); + + setPalette_helper(resolvedPalette); +} + +/*! + \internal + + Assign \a palette to this control, and propagate it to all children. +*/ +void QQuickControlPrivate::updatePalette(const QPalette &palette) +{ + Q_Q(QQuickControl); + QPalette oldPalette = resolvedPalette; + resolvedPalette = palette; + + if (oldPalette != palette) + q->paletteChange(palette, oldPalette); + + QQuickControlPrivate::updatePaletteRecur(q, palette); + + if (oldPalette != palette) + emit q->paletteChanged(); +} + +void QQuickControlPrivate::updatePaletteRecur(QQuickItem *item, const QPalette &palette) { const auto childItems = item->childItems(); for (QQuickItem *child : childItems) { if (QQuickControl *control = qobject_cast<QQuickControl *>(child)) - QQuickControlPrivate::get(control)->inheritFont(f); + QQuickControlPrivate::get(control)->inheritPalette(palette); else if (QQuickLabel *label = qobject_cast<QQuickLabel *>(child)) - QQuickLabelPrivate::get(label)->inheritFont(f); + QQuickLabelPrivate::get(label)->inheritPalette(palette); else if (QQuickTextArea *textArea = qobject_cast<QQuickTextArea *>(child)) - QQuickTextAreaPrivate::get(textArea)->inheritFont(f); + QQuickTextAreaPrivate::get(textArea)->inheritPalette(palette); else if (QQuickTextField *textField = qobject_cast<QQuickTextField *>(child)) - QQuickTextFieldPrivate::get(textField)->inheritFont(f); + QQuickTextFieldPrivate::get(textField)->inheritPalette(palette); else - QQuickControlPrivate::updateFontRecur(child, f); + QQuickControlPrivate::updatePaletteRecur(child, palette); + } +} + +QLocale QQuickControlPrivate::calcLocale(const QQuickItem *item) +{ + const QQuickItem *p = item; + while (p) { + if (const QQuickControl *control = qobject_cast<const QQuickControl *>(p)) + return control->locale(); + + QVariant v = p->property("locale"); + if (v.isValid() && v.userType() == QMetaType::QLocale) + return v.toLocale(); + + p = p->parentItem(); + } + + if (item) { + if (QQuickApplicationWindow *window = qobject_cast<QQuickApplicationWindow *>(item->window())) + return window->locale(); + } + + return QLocale(); +} + +void QQuickControlPrivate::updateLocale(const QLocale &l, bool e) +{ + Q_Q(QQuickControl); + if (!e && hasLocale) + return; + + QLocale old = q->locale(); + hasLocale = e; + if (old != l) { + bool wasMirrored = q->isMirrored(); + q->localeChange(l, old); + locale = l; + QQuickControlPrivate::updateLocaleRecur(q, l); + emit q->localeChanged(); + if (wasMirrored != q->isMirrored()) + q->mirrorChange(); + } +} + +void QQuickControlPrivate::updateLocaleRecur(QQuickItem *item, const QLocale &l) +{ + const auto childItems = item->childItems(); + for (QQuickItem *child : childItems) { + if (QQuickControl *control = qobject_cast<QQuickControl *>(child)) + QQuickControlPrivate::get(control)->updateLocale(l, false); + else + updateLocaleRecur(child, l); } } @@ -502,58 +635,40 @@ bool QQuickControlPrivate::calcHoverEnabled(const QQuickItem *item) } #endif -QString QQuickControl::accessibleName() const -{ -#if QT_CONFIG(accessibility) - Q_D(const QQuickControl); - if (d->accessibleAttached) - return d->accessibleAttached->name(); -#endif - return QString(); -} - -void QQuickControl::setAccessibleName(const QString &name) +/* + Cancels incubation recursively to avoid "Object destroyed during incubation" (QTBUG-50992) +*/ +static void cancelIncubation(QObject *object, QQmlContext *context) { -#if QT_CONFIG(accessibility) - Q_D(QQuickControl); - if (d->accessibleAttached) - d->accessibleAttached->setName(name); -#else - Q_UNUSED(name) -#endif + const auto children = object->children(); + for (QObject *child : children) + cancelIncubation(child, context); + QQmlIncubatorPrivate::cancel(object, context); } -QVariant QQuickControl::accessibleProperty(const char *propertyName) +void QQuickControlPrivate::destroyDelegate(QObject *delegate, QObject *parent) { -#if QT_CONFIG(accessibility) - Q_D(QQuickControl); - if (d->accessibleAttached) - return QQuickAccessibleAttached::property(this, propertyName); -#endif - Q_UNUSED(propertyName) - return QVariant(); -} + if (!delegate) + return; -bool QQuickControl::setAccessibleProperty(const char *propertyName, const QVariant &value) -{ -#if QT_CONFIG(accessibility) - Q_D(QQuickControl); - if (d->accessibleAttached) - return QQuickAccessibleAttached::setProperty(this, propertyName, value); -#endif - Q_UNUSED(propertyName) - Q_UNUSED(value) - return false; + QQmlContext *context = parent ? qmlContext(parent) : nullptr; + if (context) + cancelIncubation(delegate, context); + delete delegate; } QQuickControl::QQuickControl(QQuickItem *parent) : QQuickItem(*(new QQuickControlPrivate), parent) { + // ### TODO: ItemEnabledChanged? + connect(this, &QQuickItem::enabledChanged, this, &QQuickControl::paletteChanged); } QQuickControl::QQuickControl(QQuickControlPrivate &dd, QQuickItem *parent) : QQuickItem(dd, parent) { + // ### TODO: ItemEnabledChanged? + connect(this, &QQuickItem::enabledChanged, this, &QQuickControl::paletteChanged); } void QQuickControl::itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &value) @@ -570,6 +685,7 @@ void QQuickControl::itemChange(QQuickItem::ItemChange change, const QQuickItem:: case ItemParentHasChanged: if (value.item) { d->resolveFont(); + d->resolvePalette(); if (!d->hasLocale) d->updateLocale(QQuickControlPrivate::calcLocale(d->parentItem), false); // explicit=false #if QT_CONFIG(quicktemplates2_hover) @@ -632,10 +748,10 @@ QFont QQuickControl::font() const void QQuickControl::setFont(const QFont &font) { Q_D(QQuickControl); - if (d->extra.value().font.resolve() == font.resolve() && d->extra.value().font == font) + if (d->extra.value().requestedFont.resolve() == font.resolve() && d->extra.value().requestedFont == font) return; - d->extra.value().font = font; + d->extra.value().requestedFont = font; d->resolveFont(); } @@ -908,80 +1024,6 @@ void QQuickControl::resetLocale() d->updateLocale(QQuickControlPrivate::calcLocale(d->parentItem), false); // explicit=false } -QLocale QQuickControlPrivate::calcLocale(const QQuickItem *item) -{ - const QQuickItem *p = item; - while (p) { - if (const QQuickControl *control = qobject_cast<const QQuickControl *>(p)) - return control->locale(); - - QVariant v = p->property("locale"); - if (v.isValid() && v.userType() == QMetaType::QLocale) - return v.toLocale(); - - p = p->parentItem(); - } - - if (item) { - if (QQuickApplicationWindow *window = qobject_cast<QQuickApplicationWindow *>(item->window())) - return window->locale(); - } - - return QLocale(); -} - -/* - Cancels incubation recursively to avoid "Object destroyed during incubation" (QTBUG-50992) -*/ -static void cancelIncubation(QObject *object, QQmlContext *context) -{ - const auto children = object->children(); - for (QObject *child : children) - cancelIncubation(child, context); - QQmlIncubatorPrivate::cancel(object, context); -} - -void QQuickControlPrivate::destroyDelegate(QObject *delegate, QObject *parent) -{ - if (!delegate) - return; - - QQmlContext *context = parent ? qmlContext(parent) : nullptr; - if (context) - cancelIncubation(delegate, context); - delete delegate; -} - -void QQuickControlPrivate::updateLocale(const QLocale &l, bool e) -{ - Q_Q(QQuickControl); - if (!e && hasLocale) - return; - - QLocale old = q->locale(); - hasLocale = e; - if (old != l) { - bool wasMirrored = q->isMirrored(); - q->localeChange(l, old); - locale = l; - QQuickControlPrivate::updateLocaleRecur(q, l); - emit q->localeChanged(); - if (wasMirrored != q->isMirrored()) - q->mirrorChange(); - } -} - -void QQuickControlPrivate::updateLocaleRecur(QQuickItem *item, const QLocale &l) -{ - const auto childItems = item->childItems(); - for (QQuickItem *child : childItems) { - if (QQuickControl *control = qobject_cast<QQuickControl *>(child)) - QQuickControlPrivate::get(control)->updateLocale(l, false); - else - updateLocaleRecur(child, l); - } -} - /*! \qmlproperty bool QtQuick.Controls::Control::mirrored \readonly @@ -1275,11 +1317,72 @@ void QQuickControl::setContentItem(QQuickItem *item) d->setContentItem_helper(item, true); } +/*! + \since QtQuick.Controls 2.3 (Qt 5.10) + \qmlproperty palette QtQuick.Controls::Control::palette + + This property holds the palette currently set for the control. + + This property describes the control's requested palette. The palette is used by the control's + style when rendering standard components, and is available as a means to ensure that custom + controls can maintain consistency with the native platform's native look and feel. It's common + that different platforms, or different styles, define different palettes for an application. + + The default palette depends on the system environment. ApplicationWindow maintains a system/theme + palette which serves as a default for all controls. There may also be special palette defaults for + certain types of controls. You can also set the default palette for controls by passing a custom + palette to QGuiApplication::setPalette(), before loading any QML. + + Control propagates explicit palette properties from parent to children. If you change a specific + property on a control's palette, that property propagates to all of the control's children, + overriding any system defaults for that property. + + \code + Page { + palette.text: "red" + + Column { + Label { + text: qsTr("This will use red color...") + } + + Switch { + text: qsTr("... and so will this") + } + } + } + \endcode +*/ +QPalette QQuickControl::palette() const +{ + Q_D(const QQuickControl); + QPalette palette = d->resolvedPalette; + if (!isEnabled()) + palette.setCurrentColorGroup(QPalette::Disabled); + return palette; +} + +void QQuickControl::setPalette(const QPalette &palette) +{ + Q_D(QQuickControl); + if (d->extra.value().requestedPalette.resolve() == palette.resolve() && d->extra.value().requestedPalette == palette) + return; + + d->extra.value().requestedPalette = palette; + d->resolvePalette(); +} + +void QQuickControl::resetPalette() +{ + setPalette(QPalette()); +} + void QQuickControl::classBegin() { Q_D(QQuickControl); QQuickItem::classBegin(); d->resolveFont(); + d->resolvePalette(); } void QQuickControl::componentComplete() @@ -1294,7 +1397,7 @@ void QQuickControl::componentComplete() setAcceptHoverEvents(QQuickControlPrivate::calcHoverEnabled(d->parentItem)); #endif #if QT_CONFIG(accessibility) - if (!d->accessibleAttached && QAccessible::isActive()) + if (QAccessible::isActive()) accessibilityActiveChanged(true); #endif } @@ -1304,6 +1407,11 @@ QFont QQuickControl::defaultFont() const return QQuickControlPrivate::themeFont(QPlatformTheme::SystemFont); } +QPalette QQuickControl::defaultPalette() const +{ + return QQuickControlPrivate::themePalette(QPlatformTheme::SystemPalette); +} + void QQuickControl::focusInEvent(QFocusEvent *event) { QQuickItem::focusInEvent(event); @@ -1487,4 +1595,65 @@ void QQuickControl::localeChange(const QLocale &newLocale, const QLocale &oldLoc Q_UNUSED(oldLocale); } +void QQuickControl::paletteChange(const QPalette &newPalette, const QPalette &oldPalette) +{ + Q_UNUSED(newPalette); + Q_UNUSED(oldPalette); +} + +#if QT_CONFIG(accessibility) +QAccessible::Role QQuickControl::accessibleRole() const +{ + return QAccessible::NoRole; +} + +void QQuickControl::accessibilityActiveChanged(bool active) +{ + if (!active) + return; + + QQuickAccessibleAttached *accessibleAttached = qobject_cast<QQuickAccessibleAttached *>(qmlAttachedPropertiesObject<QQuickAccessibleAttached>(this, true)); + Q_ASSERT(accessibleAttached); + accessibleAttached->setRole(accessibleRole()); +} +#endif + +QString QQuickControl::accessibleName() const +{ +#if QT_CONFIG(accessibility) + if (QQuickAccessibleAttached *accessibleAttached = QQuickAccessibleAttached::attachedProperties(this)) + return accessibleAttached->name(); +#endif + return QString(); +} + +void QQuickControl::setAccessibleName(const QString &name) +{ +#if QT_CONFIG(accessibility) + if (QQuickAccessibleAttached *accessibleAttached = QQuickAccessibleAttached::attachedProperties(this)) + accessibleAttached->setName(name); +#else + Q_UNUSED(name) +#endif +} + +QVariant QQuickControl::accessibleProperty(const char *propertyName) +{ +#if QT_CONFIG(accessibility) + return QQuickAccessibleAttached::property(this, propertyName); +#endif + Q_UNUSED(propertyName) + return QVariant(); +} + +bool QQuickControl::setAccessibleProperty(const char *propertyName, const QVariant &value) +{ +#if QT_CONFIG(accessibility) + return QQuickAccessibleAttached::setProperty(this, propertyName, value); +#endif + Q_UNUSED(propertyName) + Q_UNUSED(value) + return false; +} + QT_END_NAMESPACE diff --git a/src/quicktemplates2/qquickcontrol_p.h b/src/quicktemplates2/qquickcontrol_p.h index 6ad89376..5207d46c 100644 --- a/src/quicktemplates2/qquickcontrol_p.h +++ b/src/quicktemplates2/qquickcontrol_p.h @@ -49,6 +49,7 @@ // #include <QtCore/qlocale.h> +#include <QtGui/qpalette.h> #include <QtQuick/qquickitem.h> #include <QtQuickTemplates2/private/qtquicktemplates2global_p.h> @@ -78,6 +79,7 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickControl : public QQuickItem Q_PROPERTY(bool wheelEnabled READ isWheelEnabled WRITE setWheelEnabled NOTIFY wheelEnabledChanged FINAL) Q_PROPERTY(QQuickItem *background READ background WRITE setBackground NOTIFY backgroundChanged FINAL) Q_PROPERTY(QQuickItem *contentItem READ contentItem WRITE setContentItem NOTIFY contentItemChanged FINAL) + Q_PROPERTY(QPalette palette READ palette WRITE setPalette RESET resetPalette NOTIFY paletteChanged FINAL REVISION 3) public: explicit QQuickControl(QQuickItem *parent = nullptr); @@ -143,6 +145,10 @@ public: QQuickItem *contentItem() const; void setContentItem(QQuickItem *item); + QPalette palette() const; + void setPalette(const QPalette &palette); + void resetPalette(); + Q_SIGNALS: void fontChanged(); void availableWidthChanged(); @@ -163,9 +169,11 @@ Q_SIGNALS: void wheelEnabledChanged(); void backgroundChanged(); void contentItemChanged(); + Q_REVISION(3) void paletteChanged(); protected: virtual QFont defaultFont() const; + virtual QPalette defaultPalette() const; QQuickControl(QQuickControlPrivate &dd, QQuickItem *parent); @@ -202,10 +210,11 @@ protected: virtual void paddingChange(const QMarginsF &newPadding, const QMarginsF &oldPadding); virtual void contentItemChange(QQuickItem *newItem, QQuickItem *oldItem); virtual void localeChange(const QLocale &newLocale, const QLocale &oldLocale); + virtual void paletteChange(const QPalette &newPalette, const QPalette &oldPalette); #if QT_CONFIG(accessibility) - virtual void accessibilityActiveChanged(bool active); virtual QAccessible::Role accessibleRole() const; + virtual void accessibilityActiveChanged(bool active); #endif // helper functions which avoid to check QT_CONFIG(accessibility) diff --git a/src/quicktemplates2/qquickcontrol_p_p.h b/src/quicktemplates2/qquickcontrol_p_p.h index 42924875..54346016 100644 --- a/src/quicktemplates2/qquickcontrol_p_p.h +++ b/src/quicktemplates2/qquickcontrol_p_p.h @@ -48,7 +48,7 @@ // We mean it. // -#include "qquickcontrol_p.h" +#include <QtQuickTemplates2/private/qquickcontrol_p.h> #include <QtQuick/private/qquickitem_p.h> #include <QtQml/private/qlazilyallocated_p.h> @@ -60,8 +60,6 @@ QT_BEGIN_NAMESPACE -class QQuickAccessibleAttached; - class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickControlPrivate : public QQuickItemPrivate #if QT_CONFIG(accessibility) , public QAccessible::ActivationObserver @@ -102,18 +100,30 @@ public: QAccessible::Role accessibleRole() const override; #endif - void updateFont(const QFont &f); - static void updateFontRecur(QQuickItem *item, const QFont &f); - inline void setFont_helper(const QFont &f) { - if (resolvedFont.resolve() == f.resolve() && resolvedFont == f) + virtual void resolveFont(); + void inheritFont(const QFont &font); + void updateFont(const QFont &font); + static void updateFontRecur(QQuickItem *item, const QFont &font); + inline void setFont_helper(const QFont &font) { + if (resolvedFont.resolve() == font.resolve() && resolvedFont == font) return; - updateFont(f); + updateFont(font); } - virtual void resolveFont(); - void inheritFont(const QFont &f); static QFont parentFont(const QQuickItem *item); static QFont themeFont(QPlatformTheme::Font type); + virtual void resolvePalette(); + void inheritPalette(const QPalette &palette); + void updatePalette(const QPalette &palette); + static void updatePaletteRecur(QQuickItem *item, const QPalette &palette); + inline void setPalette_helper(const QPalette &palette) { + if (resolvedPalette.resolve() == palette.resolve() && resolvedPalette == palette) + return; + updatePalette(palette); + } + static QPalette parentPalette(const QQuickItem *item); + static QPalette themePalette(QPlatformTheme::Palette type); + void updateLocale(const QLocale &l, bool e); static void updateLocaleRecur(QQuickItem *item, const QLocale &l); static QLocale calcLocale(const QQuickItem *item); @@ -128,11 +138,11 @@ public: struct ExtraData { ExtraData(); - QFont font; + QFont requestedFont; + QPalette requestedPalette; }; QLazilyAllocated<ExtraData> extra; - QFont resolvedFont; bool hasTopPadding; bool hasLeftPadding; bool hasRightPadding; @@ -151,11 +161,12 @@ public: qreal bottomPadding; qreal spacing; QLocale locale; + QFont resolvedFont; + QPalette resolvedPalette; Qt::FocusPolicy focusPolicy; Qt::FocusReason focusReason; QQuickItem *background; QQuickItem *contentItem; - QQuickAccessibleAttached *accessibleAttached; }; QT_END_NAMESPACE diff --git a/src/quicktemplates2/qquickdelaybutton.cpp b/src/quicktemplates2/qquickdelaybutton.cpp index f8a495b0..6e0baf56 100644 --- a/src/quicktemplates2/qquickdelaybutton.cpp +++ b/src/quicktemplates2/qquickdelaybutton.cpp @@ -268,4 +268,9 @@ QFont QQuickDelayButton::defaultFont() const return QQuickControlPrivate::themeFont(QPlatformTheme::PushButtonFont); } +QPalette QQuickDelayButton::defaultPalette() const +{ + return QQuickControlPrivate::themePalette(QPlatformTheme::ButtonPalette); +} + QT_END_NAMESPACE diff --git a/src/quicktemplates2/qquickdelaybutton_p.h b/src/quicktemplates2/qquickdelaybutton_p.h index 5ac0885d..0927eb4a 100644 --- a/src/quicktemplates2/qquickdelaybutton_p.h +++ b/src/quicktemplates2/qquickdelaybutton_p.h @@ -85,6 +85,7 @@ protected: void nextCheckState() override; QFont defaultFont() const override; + QPalette defaultPalette() const override; private: Q_DISABLE_COPY(QQuickDelayButton) diff --git a/src/quicktemplates2/qquickdialog.cpp b/src/quicktemplates2/qquickdialog.cpp index 3ac99caa..cce1ae47 100644 --- a/src/quicktemplates2/qquickdialog.cpp +++ b/src/quicktemplates2/qquickdialog.cpp @@ -37,6 +37,7 @@ #include "qquickdialog_p.h" #include "qquickdialog_p_p.h" #include "qquickdialogbuttonbox_p.h" +#include "qquickabstractbutton_p.h" #include "qquickpopupitem_p_p.h" QT_BEGIN_NAMESPACE @@ -115,6 +116,69 @@ QT_BEGIN_NAMESPACE \sa accepted() */ +/*! + \since QtQuick.Controls 2.3 (Qt 5.10) + \qmlsignal QtQuick.Controls::Dialog::applied() + + This signal is emitted when the \c Dialog.Apply standard button is clicked. + + \sa discarded(), reset() +*/ + +/*! + \since QtQuick.Controls 2.3 (Qt 5.10) + \qmlsignal QtQuick.Controls::Dialog::reset() + + This signal is emitted when the \c Dialog.Reset standard button is clicked. + + \sa discarded(), applied() +*/ + +/*! + \since QtQuick.Controls 2.3 (Qt 5.10) + \qmlsignal QtQuick.Controls::Dialog::discarded() + + This signal is emitted when the \c Dialog.Discard standard button is clicked. + + \sa reset(), applied() +*/ + +/*! + \since QtQuick.Controls 2.3 (Qt 5.10) + \qmlsignal QtQuick.Controls::Dialog::helpRequested() + + This signal is emitted when the \c Dialog.Help standard button is clicked. + + \sa accepted(), rejected() +*/ + +QPlatformDialogHelper::ButtonRole QQuickDialogPrivate::buttonRole(QQuickAbstractButton *button) +{ + const QQuickDialogButtonBoxAttached *attached = qobject_cast<QQuickDialogButtonBoxAttached *>(qmlAttachedPropertiesObject<QQuickDialogButtonBox>(button, false)); + return attached ? attached->buttonRole() : QPlatformDialogHelper::InvalidRole; +} + +void QQuickDialogPrivate::handleClick(QQuickAbstractButton *button) +{ + Q_Q(QQuickDialog); + switch (buttonRole(button)) { + case QPlatformDialogHelper::ApplyRole: + emit q->applied(); + break; + case QPlatformDialogHelper::ResetRole: + emit q->reset(); + break; + case QPlatformDialogHelper::DestructiveRole: + emit q->discarded(); + break; + case QPlatformDialogHelper::HelpRole: + emit q->helpRequested(); + break; + default: + break; + } +} + QQuickDialog::QQuickDialog(QObject *parent) : QQuickPopup(*(new QQuickDialogPrivate), parent) { @@ -188,12 +252,14 @@ void QQuickDialog::setHeader(QQuickItem *header) if (QQuickDialogButtonBox *buttonBox = qobject_cast<QQuickDialogButtonBox *>(oldHeader)) { disconnect(buttonBox, &QQuickDialogButtonBox::accepted, this, &QQuickDialog::accept); disconnect(buttonBox, &QQuickDialogButtonBox::rejected, this, &QQuickDialog::reject); + QObjectPrivate::disconnect(buttonBox, &QQuickDialogButtonBox::clicked, d, &QQuickDialogPrivate::handleClick); if (d->buttonBox == buttonBox) d->buttonBox = nullptr; } if (QQuickDialogButtonBox *buttonBox = qobject_cast<QQuickDialogButtonBox *>(header)) { connect(buttonBox, &QQuickDialogButtonBox::accepted, this, &QQuickDialog::accept); connect(buttonBox, &QQuickDialogButtonBox::rejected, this, &QQuickDialog::reject); + QObjectPrivate::connect(buttonBox, &QQuickDialogButtonBox::clicked, d, &QQuickDialogPrivate::handleClick); d->buttonBox = buttonBox; buttonBox->setStandardButtons(d->standardButtons); } @@ -235,12 +301,14 @@ void QQuickDialog::setFooter(QQuickItem *footer) if (QQuickDialogButtonBox *buttonBox = qobject_cast<QQuickDialogButtonBox *>(oldFooter)) { disconnect(buttonBox, &QQuickDialogButtonBox::accepted, this, &QQuickDialog::accept); disconnect(buttonBox, &QQuickDialogButtonBox::rejected, this, &QQuickDialog::reject); + QObjectPrivate::disconnect(buttonBox, &QQuickDialogButtonBox::clicked, d, &QQuickDialogPrivate::handleClick); if (d->buttonBox == buttonBox) d->buttonBox = nullptr; } if (QQuickDialogButtonBox *buttonBox = qobject_cast<QQuickDialogButtonBox *>(footer)) { connect(buttonBox, &QQuickDialogButtonBox::accepted, this, &QQuickDialog::accept); connect(buttonBox, &QQuickDialogButtonBox::rejected, this, &QQuickDialog::reject); + QObjectPrivate::connect(buttonBox, &QQuickDialogButtonBox::clicked, d, &QQuickDialogPrivate::handleClick); d->buttonBox = buttonBox; buttonBox->setStandardButtons(d->standardButtons); } @@ -301,16 +369,59 @@ void QQuickDialog::setStandardButtons(QPlatformDialogHelper::StandardButtons but } /*! + \since QtQuick.Controls 2.3 (Qt 5.10) + \qmlmethod AbstractButton QtQuick.Controls::Dialog::standardButton(StandardButton button) + + Returns the specified standard \a button, or \c null if it does not exist. + + \sa standardButtons +*/ +QQuickAbstractButton *QQuickDialog::standardButton(QPlatformDialogHelper::StandardButton button) const +{ + Q_D(const QQuickDialog); + if (!d->buttonBox) + return nullptr; + return d->buttonBox->standardButton(button); +} + +/*! + \since QtQuick.Controls 2.3 (Qt 5.10) + \qmlproperty int QtQuick.Controls::Dialog::result + + This property holds the result code. + + Standard result codes: + \value Dialog.Accepted The dialog was accepted. + \value Dialog.Rejected The dialog was rejected. + + \sa accept(), reject(), done() +*/ +int QQuickDialog::result() const +{ + Q_D(const QQuickDialog); + return d->result; +} + +void QQuickDialog::setResult(int result) +{ + Q_D(QQuickDialog); + if (d->result == result) + return; + + d->result = result; + emit resultChanged(); +} + +/*! \qmlmethod void QtQuick.Controls::Dialog::accept() Closes the dialog and emits the \l accepted() signal. - \sa reject() + \sa reject(), done() */ void QQuickDialog::accept() { - close(); - emit accepted(); + done(Accepted); } /*! @@ -318,12 +429,32 @@ void QQuickDialog::accept() Closes the dialog and emits the \l rejected() signal. - \sa accept() + \sa accept(), done() */ void QQuickDialog::reject() { + done(Rejected); +} + +/*! + \since QtQuick.Controls 2.3 (Qt 5.10) + \qmlmethod void QtQuick.Controls::Dialog::done(int result) + + Closes the dialog, sets the \a result, and emits \l accepted() or + \l rejected() depending on whether the result is \c Dialog.Accepted + or \c Dialog.Rejected, respectively. + + \sa accept(), reject(), result +*/ +void QQuickDialog::done(int result) +{ close(); - emit rejected(); + setResult(result); + + if (result == Accepted) + emit accepted(); + else if (result == Rejected) + emit rejected(); } void QQuickDialog::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) diff --git a/src/quicktemplates2/qquickdialog_p.h b/src/quicktemplates2/qquickdialog_p.h index 97c90a59..8032cf83 100644 --- a/src/quicktemplates2/qquickdialog_p.h +++ b/src/quicktemplates2/qquickdialog_p.h @@ -54,6 +54,7 @@ QT_BEGIN_NAMESPACE class QQuickDialogPrivate; +class QQuickAbstractButton; class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickDialog : public QQuickPopup { @@ -62,6 +63,7 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickDialog : public QQuickPopup Q_PROPERTY(QQuickItem *header READ header WRITE setHeader NOTIFY headerChanged FINAL) Q_PROPERTY(QQuickItem *footer READ footer WRITE setFooter NOTIFY footerChanged FINAL) Q_PROPERTY(QPlatformDialogHelper::StandardButtons standardButtons READ standardButtons WRITE setStandardButtons NOTIFY standardButtonsChanged FINAL) + Q_PROPERTY(int result READ result WRITE setResult NOTIFY resultChanged FINAL REVISION 3) Q_FLAGS(QPlatformDialogHelper::StandardButtons) public: @@ -78,19 +80,32 @@ public: QPlatformDialogHelper::StandardButtons standardButtons() const; void setStandardButtons(QPlatformDialogHelper::StandardButtons buttons); + Q_REVISION(3) Q_INVOKABLE QQuickAbstractButton *standardButton(QPlatformDialogHelper::StandardButton button) const; + + enum StandardCode { Rejected, Accepted }; + Q_ENUM(StandardCode) + + int result() const; + void setResult(int result); public Q_SLOTS: - void accept(); - void reject(); + virtual void accept(); + virtual void reject(); + virtual void done(int result); Q_SIGNALS: void accepted(); void rejected(); + Q_REVISION(3) void applied(); + Q_REVISION(3) void reset(); + Q_REVISION(3) void discarded(); + Q_REVISION(3) void helpRequested(); void titleChanged(); void headerChanged(); void footerChanged(); void standardButtonsChanged(); + Q_REVISION(3) void resultChanged(); protected: void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override; diff --git a/src/quicktemplates2/qquickdialog_p_p.h b/src/quicktemplates2/qquickdialog_p_p.h index 13885ca9..e26182ac 100644 --- a/src/quicktemplates2/qquickdialog_p_p.h +++ b/src/quicktemplates2/qquickdialog_p_p.h @@ -48,11 +48,14 @@ // We mean it. // +#include <QtQuickTemplates2/private/qquickdialog_p.h> #include <QtQuickTemplates2/private/qquickpopup_p_p.h> #include <QtQuickTemplates2/private/qquickpagelayout_p_p.h> +#include <QtGui/qpa/qplatformdialoghelper.h> QT_BEGIN_NAMESPACE +class QQuickAbstractButton; class QQuickDialogButtonBox; class QQuickDialogPrivate : public QQuickPopupPrivate @@ -60,13 +63,18 @@ class QQuickDialogPrivate : public QQuickPopupPrivate Q_DECLARE_PUBLIC(QQuickDialog) public: - QQuickDialogPrivate() : buttonBox(nullptr) { } + QQuickDialogPrivate() : result(0), buttonBox(nullptr) { } static QQuickDialogPrivate *get(QQuickDialog *dialog) { return dialog->d_func(); } + static QPlatformDialogHelper::ButtonRole buttonRole(QQuickAbstractButton *button); + + void handleClick(QQuickAbstractButton *button); + + int result; QString title; QQuickDialogButtonBox *buttonBox; QScopedPointer<QQuickPageLayout> layout; diff --git a/src/quicktemplates2/qquickdialogbuttonbox.cpp b/src/quicktemplates2/qquickdialogbuttonbox.cpp index 3c422268..7c2f17c4 100644 --- a/src/quicktemplates2/qquickdialogbuttonbox.cpp +++ b/src/quicktemplates2/qquickdialogbuttonbox.cpp @@ -38,6 +38,7 @@ #include "qquickdialogbuttonbox_p_p.h" #include "qquickabstractbutton_p.h" #include "qquickbutton_p.h" +#include "qquickdialog_p_p.h" #include <QtCore/qpointer.h> #include <QtGui/private/qguiapplication_p.h> @@ -122,6 +123,36 @@ QT_BEGIN_NAMESPACE */ /*! + \since QtQuick.Controls 2.3 (Qt 5.10) + \qmlsignal QtQuick.Controls::DialogButtonBox::applied() + + This signal is emitted when a button defined with the \c ApplyRole is + clicked. + + \sa discarded(), reset() +*/ + +/*! + \since QtQuick.Controls 2.3 (Qt 5.10) + \qmlsignal QtQuick.Controls::DialogButtonBox::reset() + + This signal is emitted when a button defined with the \c ResetRole is + clicked. + + \sa discarded(), applied() +*/ + +/*! + \since QtQuick.Controls 2.3 (Qt 5.10) + \qmlsignal QtQuick.Controls::DialogButtonBox::discarded() + + This signal is emitted when a button defined with the \c DiscardRole is + clicked. + + \sa reset(), applied() +*/ + +/*! \qmlsignal QtQuick.Controls::DialogButtonBox::helpRequested() This signal is emitted when a button defined with the \c HelpRole is clicked. @@ -137,12 +168,6 @@ QT_BEGIN_NAMESPACE \sa accepted(), rejected(), helpRequested() */ -static QPlatformDialogHelper::ButtonRole buttonRole(QQuickAbstractButton *button) -{ - const QQuickDialogButtonBoxAttached *attached = qobject_cast<QQuickDialogButtonBoxAttached *>(qmlAttachedPropertiesObject<QQuickDialogButtonBox>(button, false)); - return attached ? attached->buttonRole() : QPlatformDialogHelper::InvalidRole; -} - QQuickDialogButtonBoxPrivate::QQuickDialogButtonBoxPrivate() : alignment(0), position(QQuickDialogButtonBox::Footer), @@ -238,8 +263,8 @@ void QQuickDialogButtonBoxPrivate::updateLayout() struct ButtonLayout { bool operator()(QQuickAbstractButton *first, QQuickAbstractButton *second) { - const QPlatformDialogHelper::ButtonRole firstRole = buttonRole(first); - const QPlatformDialogHelper::ButtonRole secondRole = buttonRole(second); + const QPlatformDialogHelper::ButtonRole firstRole = QQuickDialogPrivate::buttonRole(first); + const QPlatformDialogHelper::ButtonRole secondRole = QQuickDialogPrivate::buttonRole(second); if (firstRole != secondRole && firstRole != QPlatformDialogHelper::InvalidRole && secondRole != QPlatformDialogHelper::InvalidRole) { const int *l = m_layout; @@ -283,7 +308,7 @@ void QQuickDialogButtonBoxPrivate::handleClick() // or change its role. Now changing the role is not possible yet, but arguably // both clicked and accepted/rejected/etc. should be emitted "atomically" // depending on whatever role the button had at the time of the click. - const QPlatformDialogHelper::ButtonRole role = buttonRole(button); + const QPlatformDialogHelper::ButtonRole role = QQuickDialogPrivate::buttonRole(button); QPointer<QQuickDialogButtonBox> guard(q); emit q->clicked(button); @@ -300,6 +325,15 @@ void QQuickDialogButtonBoxPrivate::handleClick() case QPlatformDialogHelper::NoRole: emit q->rejected(); break; + case QPlatformDialogHelper::ApplyRole: + emit q->applied(); + break; + case QPlatformDialogHelper::ResetRole: + emit q->reset(); + break; + case QPlatformDialogHelper::DestructiveRole: + emit q->discarded(); + break; case QPlatformDialogHelper::HelpRole: emit q->helpRequested(); break; diff --git a/src/quicktemplates2/qquickdialogbuttonbox_p.h b/src/quicktemplates2/qquickdialogbuttonbox_p.h index 9bd92c79..5d6e568e 100644 --- a/src/quicktemplates2/qquickdialogbuttonbox_p.h +++ b/src/quicktemplates2/qquickdialogbuttonbox_p.h @@ -98,6 +98,9 @@ Q_SIGNALS: void accepted(); void rejected(); void helpRequested(); + Q_REVISION(3) void applied(); + Q_REVISION(3) void reset(); + Q_REVISION(3) void discarded(); void clicked(QQuickAbstractButton *button); void positionChanged(); diff --git a/src/quicktemplates2/qquickdrawer_p_p.h b/src/quicktemplates2/qquickdrawer_p_p.h index bc4f91eb..110aa350 100644 --- a/src/quicktemplates2/qquickdrawer_p_p.h +++ b/src/quicktemplates2/qquickdrawer_p_p.h @@ -48,9 +48,9 @@ // We mean it. // -#include "qquickdrawer_p.h" -#include "qquickpopup_p_p.h" -#include "qquickvelocitycalculator_p_p.h" +#include <QtQuickTemplates2/private/qquickdrawer_p.h> +#include <QtQuickTemplates2/private/qquickpopup_p_p.h> +#include <QtQuickTemplates2/private/qquickvelocitycalculator_p_p.h> QT_BEGIN_NAMESPACE diff --git a/src/quicktemplates2/qquickgroupbox.cpp b/src/quicktemplates2/qquickgroupbox.cpp index 09bd49f6..c227afdc 100644 --- a/src/quicktemplates2/qquickgroupbox.cpp +++ b/src/quicktemplates2/qquickgroupbox.cpp @@ -153,6 +153,11 @@ QFont QQuickGroupBox::defaultFont() const return QQuickControlPrivate::themeFont(QPlatformTheme::GroupBoxTitleFont); } +QPalette QQuickGroupBox::defaultPalette() const +{ + return QQuickControlPrivate::themePalette(QPlatformTheme::GroupBoxPalette); +} + #if QT_CONFIG(accessibility) QAccessible::Role QQuickGroupBox::accessibleRole() const { diff --git a/src/quicktemplates2/qquickgroupbox_p.h b/src/quicktemplates2/qquickgroupbox_p.h index e35db1fc..b74389e4 100644 --- a/src/quicktemplates2/qquickgroupbox_p.h +++ b/src/quicktemplates2/qquickgroupbox_p.h @@ -75,6 +75,7 @@ Q_SIGNALS: protected: QFont defaultFont() const override; + QPalette defaultPalette() const override; #if QT_CONFIG(accessibility) QAccessible::Role accessibleRole() const override; diff --git a/src/quicktemplates2/qquickicon.cpp b/src/quicktemplates2/qquickicon.cpp new file mode 100644 index 00000000..0b0127d3 --- /dev/null +++ b/src/quicktemplates2/qquickicon.cpp @@ -0,0 +1,152 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Templates 2 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 "qquickicon_p.h" + +QT_BEGIN_NAMESPACE + +class QQuickIconPrivate : public QSharedData +{ +public: + QQuickIconPrivate() + : width(0), + height(0), + color(Qt::transparent) + { + } + + QString name; + QUrl source; + int width; + int height; + QColor color; +}; + +QQuickIcon::QQuickIcon() + : d(new QQuickIconPrivate) +{ +} + +QQuickIcon::QQuickIcon(const QQuickIcon &other) + : d(other.d) +{ +} + +QQuickIcon::~QQuickIcon() +{ +} + +QQuickIcon &QQuickIcon::operator=(const QQuickIcon &other) +{ + d = other.d; + return *this; +} + +bool QQuickIcon::operator==(const QQuickIcon &other) const +{ + return d == other.d || (d->name == other.d->name + && d->source == other.d->source + && d->width == other.d->width + && d->height == other.d->height + && d->color == other.d->color); +} + +bool QQuickIcon::operator!=(const QQuickIcon &other) const +{ + return !(*this == other); +} + +bool QQuickIcon::isEmpty() const +{ + return d->name.isEmpty() && d->source.isEmpty(); +} + +QString QQuickIcon::name() const +{ + return d->name; +} + +void QQuickIcon::setName(const QString &name) +{ + d->name = name; +} + +QUrl QQuickIcon::source() const +{ + return d->source; +} + +void QQuickIcon::setSource(const QUrl &source) +{ + d->source = source; +} + +int QQuickIcon::width() const +{ + return d->width; +} + +void QQuickIcon::setWidth(int width) +{ + d->width = width; +} + +int QQuickIcon::height() const +{ + return d->height; +} + +void QQuickIcon::setHeight(int height) +{ + d->height = height; +} + +QColor QQuickIcon::color() const +{ + return d->color; +} + +void QQuickIcon::setColor(const QColor &color) +{ + d->color = color; +} + +void QQuickIcon::resetColor() +{ + d->color = Qt::transparent; +} + +QT_END_NAMESPACE diff --git a/src/quicktemplates2/qquickicon_p.h b/src/quicktemplates2/qquickicon_p.h new file mode 100644 index 00000000..6e28f2a9 --- /dev/null +++ b/src/quicktemplates2/qquickicon_p.h @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Templates 2 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 QQUICKICON_P_H +#define QQUICKICON_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 <QtCore/qurl.h> +#include <QtCore/qstring.h> +#include <QtCore/qobjectdefs.h> +#include <QtCore/qshareddata.h> +#include <QtQuickTemplates2/private/qtquicktemplates2global_p.h> +#include <QtGui/qcolor.h> + +QT_BEGIN_NAMESPACE + +class QQuickIconPrivate; + +class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickIcon +{ + Q_GADGET + Q_PROPERTY(QString name READ name WRITE setName FINAL) + Q_PROPERTY(QUrl source READ source WRITE setSource FINAL) + Q_PROPERTY(int width READ width WRITE setWidth FINAL) + Q_PROPERTY(int height READ height WRITE setHeight FINAL) + Q_PROPERTY(QColor color READ color WRITE setColor RESET resetColor FINAL) + +public: + QQuickIcon(); + QQuickIcon(const QQuickIcon &other); + ~QQuickIcon(); + + QQuickIcon& operator=(const QQuickIcon &other); + bool operator==(const QQuickIcon &other) const; + bool operator!=(const QQuickIcon &other) const; + + bool isEmpty() const; + + QString name() const; + void setName(const QString &name); + + QUrl source() const; + void setSource(const QUrl &source); + + int width() const; + void setWidth(int width); + + int height() const; + void setHeight(int height); + + QColor color() const; + void setColor(const QColor &color); + void resetColor(); + +private: + QSharedDataPointer<QQuickIconPrivate> d; +}; + +QT_END_NAMESPACE + +#endif // QQUICKICON_P_H diff --git a/src/quicktemplates2/qquickitemdelegate.cpp b/src/quicktemplates2/qquickitemdelegate.cpp index 1b93c145..6eb04a46 100644 --- a/src/quicktemplates2/qquickitemdelegate.cpp +++ b/src/quicktemplates2/qquickitemdelegate.cpp @@ -57,7 +57,8 @@ QT_BEGIN_NAMESPACE ItemDelegate inherits its API from AbstractButton. For instance, you can set \l {AbstractButton::text}{text}, and react to \l {AbstractButton::clicked}{clicks} - using the AbstractButton API. + using the AbstractButton API. In addition to displaying text, item delegates + can also display an \l [QML]{Button Icons}{icon}. \snippet qtquickcontrols2-itemdelegate.qml 1 @@ -125,6 +126,11 @@ QFont QQuickItemDelegate::defaultFont() const return QQuickControlPrivate::themeFont(QPlatformTheme::ItemViewFont); } +QPalette QQuickItemDelegate::defaultPalette() const +{ + return QQuickControlPrivate::themePalette(QPlatformTheme::ItemViewPalette); +} + #if QT_CONFIG(accessibility) QAccessible::Role QQuickItemDelegate::accessibleRole() const { diff --git a/src/quicktemplates2/qquickitemdelegate_p.h b/src/quicktemplates2/qquickitemdelegate_p.h index a162ddee..5d52f764 100644 --- a/src/quicktemplates2/qquickitemdelegate_p.h +++ b/src/quicktemplates2/qquickitemdelegate_p.h @@ -70,6 +70,7 @@ Q_SIGNALS: protected: QFont defaultFont() const override; + QPalette defaultPalette() const override; #if QT_CONFIG(accessibility) QAccessible::Role accessibleRole() const override; diff --git a/src/quicktemplates2/qquicklabel.cpp b/src/quicktemplates2/qquicklabel.cpp index 45c7e5a4..8d964745 100644 --- a/src/quicktemplates2/qquicklabel.cpp +++ b/src/quicktemplates2/qquicklabel.cpp @@ -79,8 +79,7 @@ QT_BEGIN_NAMESPACE */ QQuickLabelPrivate::QQuickLabelPrivate() - : background(nullptr), - accessibleAttached(nullptr) + : background(nullptr) { #if QT_CONFIG(accessibility) QAccessible::installActivationObserver(this); @@ -108,25 +107,76 @@ void QQuickLabelPrivate::resolveFont() inheritFont(QQuickControlPrivate::parentFont(q)); } -void QQuickLabelPrivate::inheritFont(const QFont &f) +void QQuickLabelPrivate::inheritFont(const QFont &font) { - Q_Q(QQuickLabel); - QFont parentFont = font.resolve(f); - parentFont.resolve(font.resolve() | f.resolve()); + QFont parentFont = extra.isAllocated() ? extra->requestedFont.resolve(font) : font; + parentFont.resolve(extra.isAllocated() ? extra->requestedFont.resolve() | font.resolve() : font.resolve()); const QFont defaultFont = QQuickControlPrivate::themeFont(QPlatformTheme::LabelFont); const QFont resolvedFont = parentFont.resolve(defaultFont); - const bool changed = resolvedFont != sourceFont; - q->QQuickText::setFont(resolvedFont); - if (changed) + setFont_helper(resolvedFont); +} + +/*! + \internal + + Assign \a font to this control, and propagate it to all children. +*/ +void QQuickLabelPrivate::updateFont(const QFont &font) +{ + Q_Q(QQuickLabel); + QFont oldFont = sourceFont; + q->QQuickText::setFont(font); + + QQuickControlPrivate::updateFontRecur(q, font); + + if (oldFont != font) emit q->fontChanged(); } +/*! + \internal + + Determine which palette is implicitly imposed on this control by its ancestors + and QGuiApplication::palette, resolve this against its own palette (attributes from + the implicit palette are copied over). Then propagate this palette to this + control's children. +*/ +void QQuickLabelPrivate::resolvePalette() +{ + Q_Q(QQuickLabel); + inheritPalette(QQuickControlPrivate::parentPalette(q)); +} + +void QQuickLabelPrivate::inheritPalette(const QPalette &palette) +{ + QPalette parentPalette = extra.isAllocated() ? extra->requestedPalette.resolve(palette) : palette; + parentPalette.resolve(extra.isAllocated() ? extra->requestedPalette.resolve() | palette.resolve() : palette.resolve()); + + const QPalette defaultPalette = QQuickControlPrivate::themePalette(QPlatformTheme::LabelPalette); + const QPalette resolvedPalette = parentPalette.resolve(defaultPalette); + + setPalette_helper(resolvedPalette); +} + +void QQuickLabelPrivate::updatePalette(const QPalette &palette) +{ + Q_Q(QQuickLabel); + QPalette oldPalette = resolvedPalette; + resolvedPalette = palette; + + QQuickControlPrivate::updatePaletteRecur(q, palette); + + if (oldPalette != palette) + emit q->paletteChanged(); +} + void QQuickLabelPrivate::textChanged(const QString &text) { #if QT_CONFIG(accessibility) - if (accessibleAttached) + Q_Q(QQuickLabel); + if (QQuickAccessibleAttached *accessibleAttached = QQuickAccessibleAttached::attachedProperties(q)) accessibleAttached->setName(text); #else Q_UNUSED(text) @@ -136,17 +186,14 @@ void QQuickLabelPrivate::textChanged(const QString &text) #if QT_CONFIG(accessibility) void QQuickLabelPrivate::accessibilityActiveChanged(bool active) { - if (accessibleAttached || !active) + if (!active) return; Q_Q(QQuickLabel); - accessibleAttached = qobject_cast<QQuickAccessibleAttached *>(qmlAttachedPropertiesObject<QQuickAccessibleAttached>(q, true)); - if (accessibleAttached) { - accessibleAttached->setRole(accessibleRole()); - accessibleAttached->setName(text); - } else { - qWarning() << "QQuickLabel: " << q << " QQuickAccessibleAttached object creation failed!"; - } + QQuickAccessibleAttached *accessibleAttached = qobject_cast<QQuickAccessibleAttached *>(qmlAttachedPropertiesObject<QQuickAccessibleAttached>(q, true)); + Q_ASSERT(accessibleAttached); + accessibleAttached->setRole(accessibleRole()); + accessibleAttached->setName(text); } QAccessible::Role QQuickLabelPrivate::accessibleRole() const @@ -160,6 +207,9 @@ QQuickLabel::QQuickLabel(QQuickItem *parent) { Q_D(QQuickLabel); QObjectPrivate::connect(this, &QQuickText::textChanged, d, &QQuickLabelPrivate::textChanged); + + // ### TODO: ItemEnabledChanged? + connect(this, &QQuickItem::enabledChanged, this, &QQuickLabel::paletteChanged); } QFont QQuickLabel::font() const @@ -170,10 +220,10 @@ QFont QQuickLabel::font() const void QQuickLabel::setFont(const QFont &font) { Q_D(QQuickLabel); - if (d->font.resolve() == font.resolve() && d->font == font) + if (d->extra.value().requestedFont.resolve() == font.resolve() && d->extra.value().requestedFont == font) return; - d->font = font; + d->extra.value().requestedFont = font; d->resolveFont(); } @@ -210,11 +260,44 @@ void QQuickLabel::setBackground(QQuickItem *background) emit backgroundChanged(); } +/*! + \since QtQuick.Controls 2.3 (Qt 5.10) + \qmlproperty palette QtQuick.Controls::Label::palette + + This property holds the palette currently set for the label. + + \sa Control::palette +*/ +QPalette QQuickLabel::palette() const +{ + Q_D(const QQuickLabel); + QPalette palette = d->resolvedPalette; + if (!isEnabled()) + palette.setCurrentColorGroup(QPalette::Disabled); + return palette; +} + +void QQuickLabel::setPalette(const QPalette &palette) +{ + Q_D(QQuickLabel); + if (d->extra.value().requestedPalette.resolve() == palette.resolve() && d->extra.value().requestedPalette == palette) + return; + + d->extra.value().requestedPalette = palette; + d->resolvePalette(); +} + +void QQuickLabel::resetPalette() +{ + setPalette(QPalette()); +} + void QQuickLabel::classBegin() { Q_D(QQuickLabel); QQuickText::classBegin(); d->resolveFont(); + d->resolvePalette(); } void QQuickLabel::componentComplete() @@ -222,7 +305,7 @@ void QQuickLabel::componentComplete() Q_D(QQuickLabel); QQuickText::componentComplete(); #if QT_CONFIG(accessibility) - if (!d->accessibleAttached && QAccessible::isActive()) + if (QAccessible::isActive()) d->accessibilityActiveChanged(true); #endif } @@ -231,8 +314,10 @@ void QQuickLabel::itemChange(QQuickItem::ItemChange change, const QQuickItem::It { Q_D(QQuickLabel); QQuickText::itemChange(change, value); - if (change == ItemParentHasChanged && value.item) + if (change == ItemParentHasChanged && value.item) { d->resolveFont(); + d->resolvePalette(); + } } void QQuickLabel::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) diff --git a/src/quicktemplates2/qquicklabel_p.h b/src/quicktemplates2/qquicklabel_p.h index 04172900..a102c89a 100644 --- a/src/quicktemplates2/qquicklabel_p.h +++ b/src/quicktemplates2/qquicklabel_p.h @@ -48,6 +48,7 @@ // We mean it. // +#include <QtGui/qpalette.h> #include <QtQuick/private/qquicktext_p.h> #include <QtQuickTemplates2/private/qtquicktemplates2global_p.h> @@ -60,6 +61,7 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickLabel : public QQuickText Q_OBJECT Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY fontChanged) // override Q_PROPERTY(QQuickItem *background READ background WRITE setBackground NOTIFY backgroundChanged FINAL) + Q_PROPERTY(QPalette palette READ palette WRITE setPalette RESET resetPalette NOTIFY paletteChanged FINAL REVISION 3) public: explicit QQuickLabel(QQuickItem *parent = nullptr); @@ -70,9 +72,14 @@ public: QQuickItem *background() const; void setBackground(QQuickItem *background); + QPalette palette() const; + void setPalette(const QPalette &palette); + void resetPalette(); + Q_SIGNALS: void fontChanged(); void backgroundChanged(); + Q_REVISION(3) void paletteChanged(); protected: void classBegin() override; diff --git a/src/quicktemplates2/qquicklabel_p_p.h b/src/quicktemplates2/qquicklabel_p_p.h index c24c855b..a8214d77 100644 --- a/src/quicktemplates2/qquicklabel_p_p.h +++ b/src/quicktemplates2/qquicklabel_p_p.h @@ -48,6 +48,7 @@ // We mean it. // +#include <QtQml/private/qlazilyallocated_p.h> #include <QtQuick/private/qquicktext_p_p.h> #if QT_CONFIG(accessibility) @@ -56,8 +57,6 @@ QT_BEGIN_NAMESPACE -class QQuickAccessibleAttached; - class QQuickLabelPrivate : public QQuickTextPrivate #if QT_CONFIG(accessibility) , public QAccessible::ActivationObserver @@ -75,7 +74,22 @@ public: } void resolveFont(); - void inheritFont(const QFont &f); + void inheritFont(const QFont &font); + void updateFont(const QFont &font); + inline void setFont_helper(const QFont &font) { + if (sourceFont.resolve() == font.resolve() && sourceFont == font) + return; + updateFont(font); + } + + void resolvePalette(); + void inheritPalette(const QPalette &palette); + void updatePalette(const QPalette &palette); + inline void setPalette_helper(const QPalette &palette) { + if (resolvedPalette.resolve() == palette.resolve() && resolvedPalette == palette) + return; + updatePalette(palette); + } void textChanged(const QString &text); @@ -84,9 +98,14 @@ public: QAccessible::Role accessibleRole() const override; #endif - QFont font; + struct ExtraData { + QFont requestedFont; + QPalette requestedPalette; + }; + QLazilyAllocated<ExtraData> extra; + + QPalette resolvedPalette; QQuickItem *background; - QQuickAccessibleAttached *accessibleAttached; }; QT_END_NAMESPACE diff --git a/src/quicktemplates2/qquickmenu.cpp b/src/quicktemplates2/qquickmenu.cpp index 04305cea..c7dd0ea5 100644 --- a/src/quicktemplates2/qquickmenu.cpp +++ b/src/quicktemplates2/qquickmenu.cpp @@ -36,9 +36,20 @@ #include "qquickmenu_p.h" #include "qquickmenu_p_p.h" -#include "qquickmenuitem_p.h" +#include "qquickmenuitem_p_p.h" +#include "qquickpopupitem_p_p.h" +#include "qquickaction_p.h" #include <QtGui/qevent.h> +#include <QtGui/qcursor.h> +#include <QtGui/qpa/qplatformintegration.h> +#include <QtGui/private/qguiapplication_p.h> +#include <QtQml/qqmlcontext.h> +#include <QtQml/qqmlcomponent.h> +#include <QtQml/private/qqmlengine_p.h> +#include <QtQml/private/qv4scopedvalue_p.h> +#include <QtQml/private/qv4variantobject_p.h> +#include <QtQml/private/qv4qobjectwrapper_p.h> #include <QtQml/private/qqmlobjectmodel_p.h> #include <QtQuick/private/qquickitem_p.h> #include <QtQuick/private/qquickitemchangelistener_p.h> @@ -66,6 +77,37 @@ QT_BEGIN_NAMESPACE \li Popup menus; for example, a menu that is shown after clicking a button \endlist + When used as a context menu, the recommended way of opening the menu is to call + \l popup(). Unless a position is explicitly specified, the menu is positioned at + the mouse cursor on desktop platforms that have a mouse cursor available, and + otherwise centered over its parent item. + + \code + MouseArea { + anchors.fill: parent + acceptedButtons: Qt.LeftButton | Qt.RightButton + onClicked: { + if (mouse.button === Qt.RightButton) + contextMenu.popup() + } + onPressAndHold: { + if (mouse.source === Qt.MouseEventNotSynthesized) + contextMenu.popup() + } + + Menu { + id: contextMenu + MenuItem { text: "Cut" } + MenuItem { text: "Copy" } + MenuItem { text: "Paste" } + } + } + \endcode + + When used as a popup menu, it is easiest to specify the position by specifying + the desired \l {Popup::}{x} and \l {Popup::}{y} coordinates using the respective + properties, and call \l {Popup::}{open()} to open the menu. + \code Button { id: fileButton @@ -89,6 +131,17 @@ QT_BEGIN_NAMESPACE } \endcode + Since QtQuick.Controls 2.3 (Qt 5.10), it is also possible to declare + Action objects inside Menu: + + \code + Menu { + Action { text: "Cut" } + Action { text: "Copy" } + Action { text: "Paste" } + } + \endcode + Typically, menu items are statically declared as children of the menu, but Menu also provides API to \l {addItem}{add}, \l {insertItem}{insert}, \l {moveItem}{move} and \l {removeItem}{remove} items dynamically. The @@ -103,7 +156,8 @@ QT_BEGIN_NAMESPACE QQuickMenuPrivate::QQuickMenuPrivate() : contentItem(nullptr), - contentModel(nullptr) + contentModel(nullptr), + delegate(nullptr) { Q_Q(QQuickMenu); contentModel = new QQmlObjectModel(q); @@ -128,6 +182,7 @@ void QQuickMenuPrivate::insertItem(int index, QQuickItem *item) QQuickMenuItem *menuItem = qobject_cast<QQuickMenuItem *>(item); if (menuItem) { Q_Q(QQuickMenu); + QQuickMenuItemPrivate::get(menuItem)->setMenu(q); QObjectPrivate::connect(menuItem, &QQuickMenuItem::pressed, this, &QQuickMenuPrivate::onItemPressed); QObject::connect(menuItem, &QQuickMenuItem::triggered, q, &QQuickPopup::close); QObjectPrivate::connect(menuItem, &QQuickItem::activeFocusChanged, this, &QQuickMenuPrivate::onItemActiveFocusChanged); @@ -150,12 +205,37 @@ void QQuickMenuPrivate::removeItem(int index, QQuickItem *item) QQuickMenuItem *menuItem = qobject_cast<QQuickMenuItem *>(item); if (menuItem) { Q_Q(QQuickMenu); + QQuickMenuItemPrivate::get(menuItem)->setMenu(nullptr); QObjectPrivate::disconnect(menuItem, &QQuickMenuItem::pressed, this, &QQuickMenuPrivate::onItemPressed); QObject::disconnect(menuItem, &QQuickMenuItem::triggered, q, &QQuickPopup::close); QObjectPrivate::disconnect(menuItem, &QQuickItem::activeFocusChanged, this, &QQuickMenuPrivate::onItemActiveFocusChanged); } } +QQuickItem *QQuickMenuPrivate::createItem(QQuickAction *action) +{ + Q_Q(QQuickMenu); + if (!delegate) + return nullptr; + + QQmlContext *creationContext = delegate->creationContext(); + if (!creationContext) + creationContext = qmlContext(q); + QQmlContext *context = new QQmlContext(creationContext, q); + context->setContextObject(q); + + QObject *object = delegate->beginCreate(context); + if (QQuickItem *item = qobject_cast<QQuickItem *>(object)) { + if (QQuickAbstractButton *button = qobject_cast<QQuickAbstractButton*>(object)) + button->setAction(action); + delegate->completeCreate(); + return item; + } + + delete object; + return nullptr; +} + void QQuickMenuPrivate::resizeItem(QQuickItem *item) { if (!item || !contentItem) @@ -253,7 +333,13 @@ void QQuickMenuPrivate::contentData_append(QQmlListProperty<QObject> *prop, QObj { QQuickMenuPrivate *p = static_cast<QQuickMenuPrivate *>(prop->data); QQuickMenu *q = static_cast<QQuickMenu *>(prop->object); + QQuickItem *item = qobject_cast<QQuickItem *>(obj); + if (!item) { + if (QQuickAction *action = qobject_cast<QQuickAction *>(obj)) + item = p->createItem(action); + } + if (item) { if (QQuickItemPrivate::get(item)->isTransparentForPositioner()) { QQuickItemPrivate::get(item)->addItemChangeListener(p, QQuickItemPrivate::SiblingOrder); @@ -357,22 +443,61 @@ void QQuickMenu::moveItem(int from, int to) } /*! + \deprecated \qmlmethod void QtQuick.Controls::Menu::removeItem(int index) - Removes the item at \a index. + Use Menu::removeItem(Item) or Menu::takeItem(int) instead. +*/ +void QQuickMenu::removeItem(const QVariant &var) +{ + if (var.userType() == QMetaType::Nullptr) + return; + + if (QQuickItem *item = var.value<QQuickItem *>()) + removeItem(item); + else + takeItem(var.toInt()); +} + +/*! + \since QtQuick.Controls 2.3 (Qt 5.10) + \qmlmethod void QtQuick.Controls::Menu::removeItem(Item item) + + Removes and destroys the specified \a item. +*/ +void QQuickMenu::removeItem(QQuickItem *item) +{ + Q_D(QQuickMenu); + if (!item) + return; + + const int index = d->contentModel->indexOf(item, nullptr); + if (index == -1) + return; + + d->removeItem(index, item); + item->deleteLater(); +} + +/*! + \since QtQuick.Controls 2.3 (Qt 5.10) + \qmlmethod MenuItem QtQuick.Controls::Menu::takeItem(int index) + + Removes and returns the item at \a index. \note The ownership of the item is transferred to the caller. */ -void QQuickMenu::removeItem(int index) +QQuickItem *QQuickMenu::takeItem(int index) { Q_D(QQuickMenu); const int count = d->contentModel->count(); if (index < 0 || index >= count) - return; + return nullptr; QQuickItem *item = itemAt(index); if (item) d->removeItem(index, item); + return item; } /*! @@ -451,6 +576,135 @@ void QQuickMenu::setTitle(QString &title) emit titleChanged(); } +/*! + \since QtQuick.Controls 2.3 (Qt 5.10) + \qmlproperty Component QtQuick.Controls::Menu::delegate + + This property holds the component that is used to create items + to present actions. + + \code + Menu { + Action { text: "Cut" } + Action { text: "Copy" } + Action { text: "Paste" } + } + \endcode + + \sa Action +*/ +QQmlComponent *QQuickMenu::delegate() const +{ + Q_D(const QQuickMenu); + return d->delegate; +} + +void QQuickMenu::setDelegate(QQmlComponent *delegate) +{ + Q_D(QQuickMenu); + if (d->delegate == delegate) + return; + + d->delegate = delegate; + emit delegateChanged(); +} + +/*! + \since QtQuick.Controls 2.3 (Qt 5.10) + \qmlmethod void QtQuick.Controls::Menu::popup(MenuItem item = null) + + Opens the menu at the mouse cursor on desktop platforms that have a mouse cursor + available, and otherwise centers the menu over its parent item. + + The menu can be optionally aligned to a specific menu \a item. + + \sa Popup::open() +*/ + +/*! + \since QtQuick.Controls 2.3 (Qt 5.10) + \qmlmethod void QtQuick.Controls::Menu::popup(point pos, MenuItem item = null) + + Opens the menu at the specified position \a pos in the popups coordinate system, + that is, a coordinate relative to its parent item. + + The menu can be optionally aligned to a specific menu \a item. + + \sa Popup::open() +*/ + +/*! + \since QtQuick.Controls 2.3 (Qt 5.10) + \qmlmethod void QtQuick.Controls::Menu::popup(real x, real y, MenuItem item = null) + + Opens the menu at the specified position \a x, \a y in the popups coordinate system, + that is, a coordinate relative to its parent item. + + The menu can be optionally aligned to a specific menu \a item. + + \sa Popup::open() +*/ +void QQuickMenu::popup(QQmlV4Function *args) +{ + Q_D(QQuickMenu); + const int len = args->length(); + if (len > 3) { + args->v4engine()->throwTypeError(); + return; + } + + QV4::ExecutionEngine *v4 = args->v4engine(); + QV4::Scope scope(v4); + + QQmlNullableValue<QPointF> pos; + QQuickMenuItem *menuItem = nullptr; + + if (len > 0) { + // MenuItem item + QV4::ScopedValue lastArg(scope, (*args)[len - 1]); + const QV4::QObjectWrapper *obj = lastArg->as<QV4::QObjectWrapper>(); + if (obj) + menuItem = qobject_cast<QQuickMenuItem *>(obj->object()); + } + + if (len >= 2) { + // real x, real y + QV4::ScopedValue firstArg(scope, (*args)[0]); + QV4::ScopedValue secondArg(scope, (*args)[1]); + if (firstArg->isNumber() && secondArg->isNumber()) + pos = QPointF(firstArg->asDouble(), secondArg->asDouble()); + } + + if (pos.isNull && len >= 1) { + // point pos + QV4::ScopedValue firstArg(scope, (*args)[0]); + const QVariant var = v4->toVariant(firstArg, -1); + if (var.userType() == QMetaType::QPointF) + pos = var.toPointF(); + } + + // Unless the position has been explicitly specified, position the menu at + // the mouse cursor on desktop platforms that have a mouse cursor available + // and support multiple windows. +#if QT_CONFIG(cursor) + if (QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::MultipleWindows)) { + if (pos.isNull && d->parentItem) + pos = d->parentItem->mapFromGlobal(QCursor::pos()); + if (menuItem) + pos.value.ry() -= d->popupItem->mapFromItem(menuItem, QPointF(0, 0)).y(); + } +#endif + + // As a fallback, center the menu over its parent item. + if (pos.isNull && d->parentItem) + pos = QPointF((d->parentItem->width() - width()) / 2, (d->parentItem->height() - height()) / 2); + + if (!pos.isNull) + setPosition(pos); + + open(); +} + void QQuickMenu::componentComplete() { Q_D(QQuickMenu); @@ -525,6 +779,11 @@ void QQuickMenu::keyReleaseEvent(QKeyEvent *event) item->forceActiveFocus(); } +QPalette QQuickMenu::defaultPalette() const +{ + return QQuickControlPrivate::themePalette(QPlatformTheme::MenuPalette); +} + #if QT_CONFIG(accessibility) QAccessible::Role QQuickMenu::accessibleRole() const { diff --git a/src/quicktemplates2/qquickmenu_p.h b/src/quicktemplates2/qquickmenu_p.h index a899fe51..03cd8f2b 100644 --- a/src/quicktemplates2/qquickmenu_p.h +++ b/src/quicktemplates2/qquickmenu_p.h @@ -55,6 +55,7 @@ QT_BEGIN_NAMESPACE +class QQmlComponent; class QQuickMenuItem; class QQuickMenuPrivate; @@ -63,7 +64,8 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickMenu : public QQuickPopup Q_OBJECT Q_PROPERTY(QVariant contentModel READ contentModel CONSTANT FINAL) Q_PROPERTY(QQmlListProperty<QObject> contentData READ contentData FINAL) - Q_PROPERTY(QString title READ title WRITE setTitle NOTIFY titleChanged) + Q_PROPERTY(QString title READ title WRITE setTitle NOTIFY titleChanged FINAL) + Q_PROPERTY(QQmlComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged FINAL REVISION 3) Q_CLASSINFO("DefaultProperty", "contentData") public: @@ -73,7 +75,9 @@ public: Q_INVOKABLE void addItem(QQuickItem *item); Q_INVOKABLE void insertItem(int index, QQuickItem *item); Q_INVOKABLE void moveItem(int from, int to); - Q_INVOKABLE void removeItem(int index); + Q_INVOKABLE void removeItem(const QVariant &item); // ### Qt 6: remove + void removeItem(QQuickItem *item); // ### Qt 6: Q_INVOKABLE + Q_REVISION(3) Q_INVOKABLE QQuickItem *takeItem(int index); QVariant contentModel() const; QQmlListProperty<QObject> contentData(); @@ -81,6 +85,11 @@ public: QString title() const; void setTitle(QString &title); + QQmlComponent *delegate() const; + void setDelegate(QQmlComponent *delegate); + + Q_REVISION(3) Q_INVOKABLE void popup(QQmlV4Function *args); + protected: void componentComplete() override; void contentItemChange(QQuickItem *newItem, QQuickItem *oldItem) override; @@ -89,8 +98,11 @@ protected: Q_SIGNALS: void titleChanged(); + Q_REVISION(3) void delegateChanged(); protected: + QPalette defaultPalette() const override; + #if QT_CONFIG(accessibility) QAccessible::Role accessibleRole() const override; #endif diff --git a/src/quicktemplates2/qquickmenu_p_p.h b/src/quicktemplates2/qquickmenu_p_p.h index 504bc74d..ff781906 100644 --- a/src/quicktemplates2/qquickmenu_p_p.h +++ b/src/quicktemplates2/qquickmenu_p_p.h @@ -55,6 +55,9 @@ QT_BEGIN_NAMESPACE +class QQuickMenu; +class QQuickAction; +class QQmlComponent; class QQmlObjectModel; class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickMenuPrivate : public QQuickPopupPrivate @@ -68,6 +71,7 @@ public: void insertItem(int index, QQuickItem *item); void moveItem(int from, int to); void removeItem(int index, QQuickItem *item); + QQuickItem *createItem(QQuickAction *action); void resizeItem(QQuickItem *item); void resizeItems(); @@ -92,6 +96,7 @@ public: QQuickItem *contentItem; // TODO: cleanup QVector<QObject *> contentData; QQmlObjectModel *contentModel; + QQmlComponent *delegate; QString title; }; diff --git a/src/quicktemplates2/qquickmenuitem.cpp b/src/quicktemplates2/qquickmenuitem.cpp index e15640fb..e792f8bf 100644 --- a/src/quicktemplates2/qquickmenuitem.cpp +++ b/src/quicktemplates2/qquickmenuitem.cpp @@ -35,7 +35,7 @@ ****************************************************************************/ #include "qquickmenuitem_p.h" -#include "qquickabstractbutton_p_p.h" +#include "qquickmenuitem_p_p.h" #include <QtGui/qpa/qplatformtheme.h> #include <QtQuick/private/qquickevents_p_p.h> @@ -55,6 +55,10 @@ QT_BEGIN_NAMESPACE providing a familiar way to respond to menu items being \l triggered, for example. + MenuItem inherits its API from AbstractButton. For instance, you can set + \l {AbstractButton::text}{text} and \l [QML]{Button Icons}{icon} using the + AbstractButton API + \code Button { id: fileButton @@ -83,19 +87,20 @@ QT_BEGIN_NAMESPACE \sa {Customizing MenuItem}, {Menu Controls} */ -class QQuickMenuItemPrivate : public QQuickAbstractButtonPrivate +QQuickMenuItemPrivate::QQuickMenuItemPrivate() + : highlighted(false), + menu(nullptr) { - Q_DECLARE_PUBLIC(QQuickMenuItem) - -public: - QQuickMenuItemPrivate(); - - bool highlighted; -}; +} -QQuickMenuItemPrivate::QQuickMenuItemPrivate() - : highlighted(false) +void QQuickMenuItemPrivate::setMenu(QQuickMenu *newMenu) { + Q_Q(QQuickMenuItem); + if (menu == newMenu) + return; + + menu = newMenu; + emit q->menuChanged(); } /*! @@ -110,11 +115,6 @@ QQuickMenuItem::QQuickMenuItem(QQuickItem *parent) connect(this, &QQuickAbstractButton::clicked, this, &QQuickMenuItem::triggered); } -QFont QQuickMenuItem::defaultFont() const -{ - return QQuickControlPrivate::themeFont(QPlatformTheme::MenuItemFont); -} - /*! \qmlproperty bool QtQuick.Controls::MenuItem::highlighted @@ -141,6 +141,30 @@ void QQuickMenuItem::setHighlighted(bool highlighted) emit highlightedChanged(); } +/*! + \since QtQuick.Controls 2.3 (Qt 5.10) + \qmlproperty Menu QtQuick.Controls::MenuItem::menu + \readonly + + This property holds the menu that contains this menu item, + or \c null if the item is not in a menu. +*/ +QQuickMenu *QQuickMenuItem::menu() const +{ + Q_D(const QQuickMenuItem); + return d->menu; +} + +QFont QQuickMenuItem::defaultFont() const +{ + return QQuickControlPrivate::themeFont(QPlatformTheme::MenuItemFont); +} + +QPalette QQuickMenuItem::defaultPalette() const +{ + return QQuickControlPrivate::themePalette(QPlatformTheme::MenuPalette); +} + #if QT_CONFIG(accessibility) QAccessible::Role QQuickMenuItem::accessibleRole() const { diff --git a/src/quicktemplates2/qquickmenuitem_p.h b/src/quicktemplates2/qquickmenuitem_p.h index 76f41f9d..92b42488 100644 --- a/src/quicktemplates2/qquickmenuitem_p.h +++ b/src/quicktemplates2/qquickmenuitem_p.h @@ -52,12 +52,14 @@ QT_BEGIN_NAMESPACE +class QQuickMenu; class QQuickMenuItemPrivate; class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickMenuItem : public QQuickAbstractButton { Q_OBJECT Q_PROPERTY(bool highlighted READ isHighlighted WRITE setHighlighted NOTIFY highlightedChanged FINAL) + Q_PROPERTY(QQuickMenu *menu READ menu NOTIFY menuChanged FINAL REVISION 3) public: explicit QQuickMenuItem(QQuickItem *parent = nullptr); @@ -65,12 +67,16 @@ public: bool isHighlighted() const; void setHighlighted(bool highlighted); + QQuickMenu *menu() const; + Q_SIGNALS: void triggered(); void highlightedChanged(); + Q_REVISION(3) void menuChanged(); protected: QFont defaultFont() const override; + QPalette defaultPalette() const override; #if QT_CONFIG(accessibility) QAccessible::Role accessibleRole() const override; diff --git a/src/quicktemplates2/qquickmenuitem_p_p.h b/src/quicktemplates2/qquickmenuitem_p_p.h new file mode 100644 index 00000000..f1cded91 --- /dev/null +++ b/src/quicktemplates2/qquickmenuitem_p_p.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Templates 2 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 QQUICKMENUITEM_P_P_H +#define QQUICKMENUITEM_P_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 <QtQuickTemplates2/private/qquickmenuitem_p.h> +#include <QtQuickTemplates2/private/qquickabstractbutton_p_p.h> + +QT_BEGIN_NAMESPACE + +class QQuickMenu; + +class QQuickMenuItemPrivate : public QQuickAbstractButtonPrivate +{ + Q_DECLARE_PUBLIC(QQuickMenuItem) + +public: + QQuickMenuItemPrivate(); + + static QQuickMenuItemPrivate *get(QQuickMenuItem *item) + { + return item->d_func(); + } + + void setMenu(QQuickMenu *menu); + + bool highlighted; + QQuickMenu *menu; +}; + +QT_END_NAMESPACE + +#endif // QQUICKMENUITEM_P_P_H diff --git a/src/quicktemplates2/qquickmenuseparator.cpp b/src/quicktemplates2/qquickmenuseparator.cpp index 366f0a27..f80cc775 100644 --- a/src/quicktemplates2/qquickmenuseparator.cpp +++ b/src/quicktemplates2/qquickmenuseparator.cpp @@ -35,6 +35,7 @@ ****************************************************************************/ #include "qquickmenuseparator_p.h" +#include "qquickcontrol_p_p.h" QT_BEGIN_NAMESPACE @@ -70,6 +71,11 @@ QQuickMenuSeparator::QQuickMenuSeparator(QQuickItem *parent) { } +QPalette QQuickMenuSeparator::defaultPalette() const +{ + return QQuickControlPrivate::themePalette(QPlatformTheme::MenuPalette); +} + #if QT_CONFIG(accessibility) QAccessible::Role QQuickMenuSeparator::accessibleRole() const { diff --git a/src/quicktemplates2/qquickmenuseparator_p.h b/src/quicktemplates2/qquickmenuseparator_p.h index 42147f77..002b68ba 100644 --- a/src/quicktemplates2/qquickmenuseparator_p.h +++ b/src/quicktemplates2/qquickmenuseparator_p.h @@ -60,6 +60,8 @@ public: explicit QQuickMenuSeparator(QQuickItem *parent = nullptr); protected: + QPalette defaultPalette() const override; + #if QT_CONFIG(accessibility) QAccessible::Role accessibleRole() const override; #endif diff --git a/src/quicktemplates2/qquickoverlay_p_p.h b/src/quicktemplates2/qquickoverlay_p_p.h index 5553bda8..38284332 100644 --- a/src/quicktemplates2/qquickoverlay_p_p.h +++ b/src/quicktemplates2/qquickoverlay_p_p.h @@ -48,7 +48,7 @@ // We mean it. // -#include "qquickoverlay_p.h" +#include <QtQuickTemplates2/private/qquickoverlay_p.h> #include <QtQuick/private/qquickitem_p.h> #include <QtQuick/private/qquickitemchangelistener_p.h> diff --git a/src/quicktemplates2/qquickpalette.cpp b/src/quicktemplates2/qquickpalette.cpp new file mode 100644 index 00000000..018d6fdc --- /dev/null +++ b/src/quicktemplates2/qquickpalette.cpp @@ -0,0 +1,326 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Templates 2 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 "qquickpalette_p.h" + +QT_BEGIN_NAMESPACE + +QColor QQuickPalette::alternateBase() const +{ + return v.color(QPalette::AlternateBase); +} + +void QQuickPalette::setAlternateBase(const QColor &color) +{ + v.setColor(QPalette::All, QPalette::AlternateBase, color); +} + +void QQuickPalette::resetAlternateBase() +{ + v.resolve(v.resolve() & ~(1 << QPalette::AlternateBase)); +} + +QColor QQuickPalette::base() const +{ + return v.color(QPalette::Base); +} + +void QQuickPalette::setBase(const QColor &color) +{ + v.setColor(QPalette::All, QPalette::Base, color); +} + +void QQuickPalette::resetBase() +{ + v.resolve(v.resolve() & ~(1 << QPalette::Base)); +} + +QColor QQuickPalette::brightText() const +{ + return v.color(QPalette::BrightText); +} + +void QQuickPalette::setBrightText(const QColor &color) +{ + v.setColor(QPalette::All, QPalette::BrightText, color); +} + +void QQuickPalette::resetBrightText() +{ + v.resolve(v.resolve() & ~(1 << QPalette::BrightText)); +} + +QColor QQuickPalette::button() const +{ + return v.color(QPalette::Button); +} + +void QQuickPalette::setButton(const QColor &color) +{ + v.setColor(QPalette::All, QPalette::Button, color); +} + +void QQuickPalette::resetButton() +{ + v.resolve(v.resolve() & ~(1 << QPalette::Button)); +} + +QColor QQuickPalette::buttonText() const +{ + return v.color(QPalette::ButtonText); +} + +void QQuickPalette::setButtonText(const QColor &color) +{ + v.setColor(QPalette::All, QPalette::ButtonText, color); +} + +void QQuickPalette::resetButtonText() +{ + v.resolve(v.resolve() & ~(1 << QPalette::ButtonText)); +} + +QColor QQuickPalette::dark() const +{ + return v.color(QPalette::Dark); +} + +void QQuickPalette::setDark(const QColor &color) +{ + v.setColor(QPalette::All, QPalette::Dark, color); +} + +void QQuickPalette::resetDark() +{ + v.resolve(v.resolve() & ~(1 << QPalette::Dark)); +} + +QColor QQuickPalette::highlight() const +{ + return v.color(QPalette::Highlight); +} + +void QQuickPalette::setHighlight(const QColor &color) +{ + v.setColor(QPalette::All, QPalette::Highlight, color); +} + +void QQuickPalette::resetHighlight() +{ + v.resolve(v.resolve() & ~(1 << QPalette::Highlight)); +} + +QColor QQuickPalette::highlightedText() const +{ + return v.color(QPalette::HighlightedText); +} + +void QQuickPalette::setHighlightedText(const QColor &color) +{ + v.setColor(QPalette::All, QPalette::HighlightedText, color); +} + +void QQuickPalette::resetHighlightedText() +{ + v.resolve(v.resolve() & ~(1 << QPalette::HighlightedText)); +} + +QColor QQuickPalette::light() const +{ + return v.color(QPalette::Light); +} + +void QQuickPalette::setLight(const QColor &color) +{ + v.setColor(QPalette::All, QPalette::Light, color); +} + +void QQuickPalette::resetLight() +{ + v.resolve(v.resolve() & ~(1 << QPalette::Light)); +} + +QColor QQuickPalette::link() const +{ + return v.color(QPalette::Link); +} + +void QQuickPalette::setLink(const QColor &color) +{ + v.setColor(QPalette::All, QPalette::Link, color); +} + +void QQuickPalette::resetLink() +{ + v.resolve(v.resolve() & ~(1 << QPalette::Link)); +} + +QColor QQuickPalette::linkVisited() const +{ + return v.color(QPalette::LinkVisited); +} + +void QQuickPalette::setLinkVisited(const QColor &color) +{ + v.setColor(QPalette::All, QPalette::LinkVisited, color); +} + +void QQuickPalette::resetLinkVisited() +{ + v.resolve(v.resolve() & ~(1 << QPalette::LinkVisited)); +} + +QColor QQuickPalette::mid() const +{ + return v.color(QPalette::Mid); +} + +void QQuickPalette::setMid(const QColor &color) +{ + v.setColor(QPalette::All, QPalette::Mid, color); +} + +void QQuickPalette::resetMid() +{ + v.resolve(v.resolve() & ~(1 << QPalette::Mid)); +} + +QColor QQuickPalette::midlight() const +{ + return v.color(QPalette::Midlight); +} + +void QQuickPalette::setMidlight(const QColor &color) +{ + v.setColor(QPalette::All, QPalette::Midlight, color); +} + +void QQuickPalette::resetMidlight() +{ + v.resolve(v.resolve() & ~(1 << QPalette::Midlight)); +} + +QColor QQuickPalette::shadow() const +{ + return v.color(QPalette::Shadow); +} + +void QQuickPalette::setShadow(const QColor &color) +{ + v.setColor(QPalette::All, QPalette::Shadow, color); +} + +void QQuickPalette::resetShadow() +{ + v.resolve(v.resolve() & ~(1 << QPalette::Shadow)); +} + +QColor QQuickPalette::text() const +{ + return v.color(QPalette::Text); +} + +void QQuickPalette::setText(const QColor &color) +{ + v.setColor(QPalette::All, QPalette::Text, color); +} + +void QQuickPalette::resetText() +{ + v.resolve(v.resolve() & ~(1 << QPalette::Text)); +} + +QColor QQuickPalette::toolTipBase() const +{ + return v.color(QPalette::ToolTipBase); +} + +void QQuickPalette::setToolTipBase(const QColor &color) +{ + v.setColor(QPalette::All, QPalette::ToolTipBase, color); +} + +void QQuickPalette::resetToolTipBase() +{ + v.resolve(v.resolve() & ~(1 << QPalette::ToolTipBase)); +} + +QColor QQuickPalette::toolTipText() const +{ + return v.color(QPalette::ToolTipText); +} + +void QQuickPalette::setToolTipText(const QColor &color) +{ + v.setColor(QPalette::All, QPalette::ToolTipText, color); +} + +void QQuickPalette::resetToolTipText() +{ + v.resolve(v.resolve() & ~(1 << QPalette::ToolTipText)); +} + +QColor QQuickPalette::window() const +{ + return v.color(QPalette::Window); +} + +void QQuickPalette::setWindow(const QColor &color) +{ + v.setColor(QPalette::All, QPalette::Window, color); +} + +void QQuickPalette::resetWindow() +{ + v.resolve(v.resolve() & ~(1 << QPalette::Window)); +} + +QColor QQuickPalette::windowText() const +{ + return v.color(QPalette::WindowText); +} + +void QQuickPalette::setWindowText(const QColor &color) +{ + v.setColor(QPalette::All, QPalette::WindowText, color); +} + +void QQuickPalette::resetWindowText() +{ + v.resolve(v.resolve() & ~(1 << QPalette::WindowText)); +} + +QT_END_NAMESPACE diff --git a/src/quicktemplates2/qquickpalette_p.h b/src/quicktemplates2/qquickpalette_p.h new file mode 100644 index 00000000..d43e78a6 --- /dev/null +++ b/src/quicktemplates2/qquickpalette_p.h @@ -0,0 +1,163 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Templates 2 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 QQUICKPALETTE_P_H +#define QQUICKPALETTE_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 <QtGui/qcolor.h> +#include <QtGui/qpalette.h> +#include <QtQuickTemplates2/private/qtquicktemplates2global_p.h> + +QT_BEGIN_NAMESPACE + +class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickPalette +{ + Q_GADGET + Q_PROPERTY(QColor alternateBase READ alternateBase WRITE setAlternateBase RESET resetAlternateBase FINAL) + Q_PROPERTY(QColor base READ base WRITE setBase RESET resetBase FINAL) + Q_PROPERTY(QColor brightText READ brightText WRITE setBrightText RESET resetBrightText FINAL) + Q_PROPERTY(QColor button READ button WRITE setButton RESET resetButton FINAL) + Q_PROPERTY(QColor buttonText READ buttonText WRITE setButtonText RESET resetButtonText FINAL) + Q_PROPERTY(QColor dark READ dark WRITE setDark RESET resetDark FINAL) + Q_PROPERTY(QColor highlight READ highlight WRITE setHighlight RESET resetHighlight FINAL) + Q_PROPERTY(QColor highlightedText READ highlightedText WRITE setHighlightedText RESET resetHighlightedText FINAL) + Q_PROPERTY(QColor light READ light WRITE setLight RESET resetLight FINAL) + Q_PROPERTY(QColor link READ link WRITE setLink RESET resetLink FINAL) + Q_PROPERTY(QColor linkVisited READ linkVisited WRITE setLinkVisited RESET resetLinkVisited FINAL) + Q_PROPERTY(QColor mid READ mid WRITE setMid RESET resetMid FINAL) + Q_PROPERTY(QColor midlight READ midlight WRITE setMidlight RESET resetMidlight FINAL) + Q_PROPERTY(QColor shadow READ shadow WRITE setShadow RESET resetShadow FINAL) + Q_PROPERTY(QColor text READ text WRITE setText RESET resetText FINAL) + Q_PROPERTY(QColor toolTipBase READ toolTipBase WRITE setToolTipBase RESET resetToolTipBase FINAL) + Q_PROPERTY(QColor toolTipText READ toolTipText WRITE setToolTipText RESET resetToolTipText FINAL) + Q_PROPERTY(QColor window READ window WRITE setWindow RESET resetWindow FINAL) + Q_PROPERTY(QColor windowText READ windowText WRITE setWindowText RESET resetWindowText FINAL) + +public: + QColor alternateBase() const; + void setAlternateBase(const QColor &color); + void resetAlternateBase(); + + QColor base() const; + void setBase(const QColor &color); + void resetBase(); + + QColor brightText() const; + void setBrightText(const QColor &color); + void resetBrightText(); + + QColor button() const; + void setButton(const QColor &color); + void resetButton(); + + QColor buttonText() const; + void setButtonText(const QColor &color); + void resetButtonText(); + + QColor dark() const; + void setDark(const QColor &color); + void resetDark(); + + QColor highlight() const; + void setHighlight(const QColor &color); + void resetHighlight(); + + QColor highlightedText() const; + void setHighlightedText(const QColor &color); + void resetHighlightedText(); + + QColor light() const; + void setLight(const QColor &color); + void resetLight(); + + QColor link() const; + void setLink(const QColor &color); + void resetLink(); + + QColor linkVisited() const; + void setLinkVisited(const QColor &color); + void resetLinkVisited(); + + QColor mid() const; + void setMid(const QColor &color); + void resetMid(); + + QColor midlight() const; + void setMidlight(const QColor &color); + void resetMidlight(); + + QColor shadow() const; + void setShadow(const QColor &color); + void resetShadow(); + + QColor text() const; + void setText(const QColor &color); + void resetText(); + + QColor toolTipBase() const; + void setToolTipBase(const QColor &color); + void resetToolTipBase(); + + QColor toolTipText() const; + void setToolTipText(const QColor &color); + void resetToolTipText(); + + QColor window() const; + void setWindow(const QColor &color); + void resetWindow(); + + QColor windowText() const; + void setWindowText(const QColor &color); + void resetWindowText(); + +private: + QPalette v; +}; + +QT_END_NAMESPACE + +#endif // QQUICKPALETTE_P_H diff --git a/src/quicktemplates2/qquickpopup.cpp b/src/quicktemplates2/qquickpopup.cpp index e6d83350..840b9f19 100644 --- a/src/quicktemplates2/qquickpopup.cpp +++ b/src/quicktemplates2/qquickpopup.cpp @@ -457,6 +457,7 @@ bool QQuickPopupPrivate::prepareExitTransition() } transitionState = ExitTransition; emit q->aboutToHide(); + emit q->openedChanged(); } return true; } @@ -467,6 +468,7 @@ void QQuickPopupPrivate::finalizeEnterTransition() if (focus) popupItem->setFocus(true); transitionState = NoTransition; + emit q->openedChanged(); emit q->opened(); } @@ -657,6 +659,7 @@ QQuickPopup::~QQuickPopup() setParentItem(nullptr); d->popupItem->ungrabShortcut(); delete d->popupItem; + d->popupItem = nullptr; } /*! @@ -1351,6 +1354,53 @@ void QQuickPopup::resetFont() d->popupItem->resetFont(); } + +/*! + \since QtQuick.Controls 2.3 (Qt 5.10) + \qmlproperty palette QtQuick.Controls::Popup::palette + + This property holds the palette currently set for the popup. + + Popup propagates explicit palette properties to its children. If you change a specific + property on a popup's palette, that property propagates to all of the popup's children, + overriding any system defaults for that property. + + \code + Popup { + palette.text: "red" + + Column { + Label { + text: qsTr("This will use red color...") + } + + Switch { + text: qsTr("... and so will this") + } + } + } + \endcode + + \sa Control::palette, ApplicationWindow::palette +*/ +QPalette QQuickPopup::palette() const +{ + Q_D(const QQuickPopup); + return d->popupItem->palette(); +} + +void QQuickPopup::setPalette(const QPalette &palette) +{ + Q_D(QQuickPopup); + d->popupItem->setPalette(palette); +} + +void QQuickPopup::resetPalette() +{ + Q_D(QQuickPopup); + d->popupItem->resetPalette(); +} + QQuickWindow *QQuickPopup::window() const { Q_D(const QQuickPopup); @@ -1393,6 +1443,7 @@ void QQuickPopup::setParentItem(QQuickItem *parent) QQuickControlPrivate *p = QQuickControlPrivate::get(d->popupItem); p->resolveFont(); + p->resolvePalette(); if (QQuickApplicationWindow *window = qobject_cast<QQuickApplicationWindow *>(parent->window())) p->updateLocale(window->locale(), false); // explicit=false } else { @@ -1654,7 +1705,7 @@ void QQuickPopup::resetDim() This property holds whether the popup is visible. The default value is \c false. - \sa open(), close() + \sa open(), close(), opened */ bool QQuickPopup::isVisible() const { @@ -1679,6 +1730,21 @@ void QQuickPopup::setVisible(bool visible) } /*! + \since QtQuick.Controls 2.3 (Qt 5.10) + \qmlproperty bool QtQuick.Controls::Popup::opened + + This property holds whether the popup is fully open. The popup is considered opened + when it's visible and neither the \l enter nor \l exit transitions are running. + + \sa open(), close(), visible +*/ +bool QQuickPopup::isOpened() const +{ + Q_D(const QQuickPopup); + return d->transitionState == QQuickPopupPrivate::NoTransition && isVisible(); +} + +/*! \qmlproperty real QtQuick.Controls::Popup::opacity This property holds the opacity of the popup. Opacity is specified as a number between @@ -2108,6 +2174,13 @@ void QQuickPopup::paddingChange(const QMarginsF &newPadding, const QMarginsF &ol emit availableHeightChanged(); } +void QQuickPopup::paletteChange(const QPalette &newPalette, const QPalette &oldPalette) +{ + Q_UNUSED(newPalette); + Q_UNUSED(oldPalette); + emit paletteChanged(); +} + void QQuickPopup::spacingChange(qreal newSpacing, qreal oldSpacing) { Q_UNUSED(newSpacing); @@ -2120,6 +2193,11 @@ QFont QQuickPopup::defaultFont() const return QQuickControlPrivate::themeFont(QPlatformTheme::SystemFont); } +QPalette QQuickPopup::defaultPalette() const +{ + return QQuickControlPrivate::themePalette(QPlatformTheme::SystemPalette); +} + #if QT_CONFIG(accessibility) QAccessible::Role QQuickPopup::accessibleRole() const { diff --git a/src/quicktemplates2/qquickpopup_p.h b/src/quicktemplates2/qquickpopup_p.h index 12bbe91d..065647d5 100644 --- a/src/quicktemplates2/qquickpopup_p.h +++ b/src/quicktemplates2/qquickpopup_p.h @@ -53,6 +53,7 @@ #include <QtGui/qevent.h> #include <QtCore/qlocale.h> #include <QtGui/qfont.h> +#include <QtGui/qpalette.h> #include <QtQuickTemplates2/private/qtquicktemplates2global_p.h> #include <QtQml/qqml.h> #include <QtQml/qqmllist.h> @@ -97,6 +98,7 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickPopup : public QObject, public QQml Q_PROPERTY(qreal bottomPadding READ bottomPadding WRITE setBottomPadding RESET resetBottomPadding NOTIFY bottomPaddingChanged FINAL) Q_PROPERTY(QLocale locale READ locale WRITE setLocale RESET resetLocale NOTIFY localeChanged FINAL) Q_PROPERTY(QFont font READ font WRITE setFont RESET resetFont NOTIFY fontChanged FINAL) + Q_PROPERTY(QPalette palette READ palette WRITE setPalette RESET resetPalette NOTIFY paletteChanged FINAL REVISION 3) Q_PROPERTY(QQuickItem *parent READ parentItem WRITE setParentItem NOTIFY parentChanged FINAL) Q_PROPERTY(QQuickItem *background READ background WRITE setBackground NOTIFY backgroundChanged FINAL) Q_PROPERTY(QQuickItem *contentItem READ contentItem WRITE setContentItem NOTIFY contentItemChanged FINAL) @@ -108,10 +110,11 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickPopup : public QObject, public QQml Q_PROPERTY(bool modal READ isModal WRITE setModal NOTIFY modalChanged FINAL) Q_PROPERTY(bool dim READ dim WRITE setDim RESET resetDim NOTIFY dimChanged FINAL) Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY visibleChanged FINAL) + Q_PROPERTY(bool opened READ isOpened NOTIFY openedChanged FINAL REVISION 3) Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity NOTIFY opacityChanged FINAL) Q_PROPERTY(qreal scale READ scale WRITE setScale NOTIFY scaleChanged FINAL) Q_PROPERTY(ClosePolicy closePolicy READ closePolicy WRITE setClosePolicy NOTIFY closePolicyChanged FINAL) - Q_PROPERTY(TransformOrigin transformOrigin READ transformOrigin WRITE setTransformOrigin) + Q_PROPERTY(TransformOrigin transformOrigin READ transformOrigin WRITE setTransformOrigin FINAL) 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") @@ -207,6 +210,10 @@ public: void setFont(const QFont &font); void resetFont(); + QPalette palette() const; + void setPalette(const QPalette &palette); + void resetPalette(); + QQuickWindow *window() const; QQuickItem *popupItem() const; @@ -240,6 +247,8 @@ public: bool isVisible() const; virtual void setVisible(bool visible); + bool isOpened() const; + qreal opacity() const; void setOpacity(qreal opacity); @@ -311,6 +320,7 @@ Q_SIGNALS: void bottomPaddingChanged(); void fontChanged(); void localeChanged(); + Q_REVISION(3) void paletteChanged(); void parentChanged(); void backgroundChanged(); void contentItemChanged(); @@ -321,6 +331,7 @@ Q_SIGNALS: void modalChanged(); void dimChanged(); void visibleChanged(); + Q_REVISION(3) void openedChanged(); void opacityChanged(); void scaleChanged(); void closePolicyChanged(); @@ -364,9 +375,11 @@ protected: virtual void itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &data); virtual void marginsChange(const QMarginsF &newMargins, const QMarginsF &oldMargins); virtual void paddingChange(const QMarginsF &newPadding, const QMarginsF &oldPadding); + virtual void paletteChange(const QPalette &newPalette, const QPalette &oldPalette); virtual void spacingChange(qreal newSpacing, qreal oldSpacing); virtual QFont defaultFont() const; + virtual QPalette defaultPalette() const; #if QT_CONFIG(accessibility) virtual QAccessible::Role accessibleRole() const; diff --git a/src/quicktemplates2/qquickpopup_p_p.h b/src/quicktemplates2/qquickpopup_p_p.h index 316ea5bd..fa79003e 100644 --- a/src/quicktemplates2/qquickpopup_p_p.h +++ b/src/quicktemplates2/qquickpopup_p_p.h @@ -48,8 +48,8 @@ // We mean it. // -#include "qquickpopup_p.h" -#include "qquickcontrol_p.h" +#include <QtQuickTemplates2/private/qquickpopup_p.h> +#include <QtQuickTemplates2/private/qquickcontrol_p.h> #include <QtCore/private/qobject_p.h> #include <QtQuick/qquickitem.h> diff --git a/src/quicktemplates2/qquickpopupitem.cpp b/src/quicktemplates2/qquickpopupitem.cpp index 3a770bf7..8251ad2f 100644 --- a/src/quicktemplates2/qquickpopupitem.cpp +++ b/src/quicktemplates2/qquickpopupitem.cpp @@ -56,6 +56,7 @@ public: void implicitHeightChanged() override; void resolveFont() override; + void resolvePalette() override; QQuickItem *getContentItem() override; @@ -90,6 +91,14 @@ void QQuickPopupItemPrivate::resolveFont() inheritFont(window->font()); } +void QQuickPopupItemPrivate::resolvePalette() +{ + if (QQuickApplicationWindow *window = qobject_cast<QQuickApplicationWindow *>(popup->window())) + inheritPalette(window->palette()); + else + inheritPalette(themePalette(QPlatformTheme::SystemPalette)); +} + QQuickItem *QQuickPopupItemPrivate::getContentItem() { Q_Q(QQuickPopupItem); @@ -290,12 +299,25 @@ void QQuickPopupItem::paddingChange(const QMarginsF &newPadding, const QMarginsF d->popup->paddingChange(newPadding, oldPadding); } +void QQuickPopupItem::paletteChange(const QPalette &newPalette, const QPalette &oldPalette) +{ + Q_D(QQuickPopupItem); + QQuickControl::paletteChange(newPalette, oldPalette); + d->popup->paletteChange(newPalette, oldPalette); +} + QFont QQuickPopupItem::defaultFont() const { Q_D(const QQuickPopupItem); return d->popup->defaultFont(); } +QPalette QQuickPopupItem::defaultPalette() const +{ + Q_D(const QQuickPopupItem); + return d->popup->defaultPalette(); +} + #if QT_CONFIG(accessibility) QAccessible::Role QQuickPopupItem::accessibleRole() const { diff --git a/src/quicktemplates2/qquickpopupitem_p_p.h b/src/quicktemplates2/qquickpopupitem_p_p.h index 16321feb..00ccd78f 100644 --- a/src/quicktemplates2/qquickpopupitem_p_p.h +++ b/src/quicktemplates2/qquickpopupitem_p_p.h @@ -48,7 +48,7 @@ // We mean it. // -#include "qquickcontrol_p.h" +#include <QtQuickTemplates2/private/qquickcontrol_p.h> QT_BEGIN_NAMESPACE @@ -91,8 +91,10 @@ protected: void localeChange(const QLocale &newLocale, const QLocale &oldLocale) override; void itemChange(ItemChange change, const ItemChangeData &data) override; void paddingChange(const QMarginsF &newPadding, const QMarginsF &oldPadding) override; + void paletteChange(const QPalette &newPalette, const QPalette &oldPalette) override; QFont defaultFont() const override; + QPalette defaultPalette() const override; #if QT_CONFIG(accessibility) QAccessible::Role accessibleRole() const override; diff --git a/src/quicktemplates2/qquickradiobutton.cpp b/src/quicktemplates2/qquickradiobutton.cpp index c923fbbf..86be3ed6 100644 --- a/src/quicktemplates2/qquickradiobutton.cpp +++ b/src/quicktemplates2/qquickradiobutton.cpp @@ -102,6 +102,11 @@ QFont QQuickRadioButton::defaultFont() const return QQuickControlPrivate::themeFont(QPlatformTheme::RadioButtonFont); } +QPalette QQuickRadioButton::defaultPalette() const +{ + return QQuickControlPrivate::themePalette(QPlatformTheme::RadioButtonPalette); +} + #if QT_CONFIG(accessibility) QAccessible::Role QQuickRadioButton::accessibleRole() const { diff --git a/src/quicktemplates2/qquickradiobutton_p.h b/src/quicktemplates2/qquickradiobutton_p.h index 0fe4eb70..ea372687 100644 --- a/src/quicktemplates2/qquickradiobutton_p.h +++ b/src/quicktemplates2/qquickradiobutton_p.h @@ -61,6 +61,7 @@ public: protected: QFont defaultFont() const override; + QPalette defaultPalette() const override; #if QT_CONFIG(accessibility) QAccessible::Role accessibleRole() const override; diff --git a/src/quicktemplates2/qquickrangeslider.cpp b/src/quicktemplates2/qquickrangeslider.cpp index 3d767ed7..83317902 100644 --- a/src/quicktemplates2/qquickrangeslider.cpp +++ b/src/quicktemplates2/qquickrangeslider.cpp @@ -779,6 +779,8 @@ void QQuickRangeSlider::setSnapMode(SnapMode mode) Possible values: \value Qt.Horizontal Horizontal (default) \value Qt.Vertical Vertical + + \sa horizontal, vertical */ Qt::Orientation QQuickRangeSlider::orientation() const { @@ -797,6 +799,36 @@ void QQuickRangeSlider::setOrientation(Qt::Orientation orientation) } /*! + \since QtQuick.Controls 2.3 (Qt 5.10) + \qmlproperty bool QtQuick.Controls::RangeSlider::horizontal + \readonly + + This property holds whether the slider is horizontal. + + \sa orientation +*/ +bool QQuickRangeSlider::isHorizontal() const +{ + Q_D(const QQuickRangeSlider); + return d->orientation == Qt::Horizontal; +} + +/*! + \since QtQuick.Controls 2.3 (Qt 5.10) + \qmlproperty bool QtQuick.Controls::RangeSlider::vertical + \readonly + + This property holds whether the slider is vertical. + + \sa orientation +*/ +bool QQuickRangeSlider::isVertical() const +{ + Q_D(const QQuickRangeSlider); + return d->orientation == Qt::Vertical; +} + +/*! \since QtQuick.Controls 2.2 (Qt 5.9) \qmlproperty bool QtQuick.Controls::RangeSlider::live diff --git a/src/quicktemplates2/qquickrangeslider_p.h b/src/quicktemplates2/qquickrangeslider_p.h index c4bc52ff..3d4ebb2b 100644 --- a/src/quicktemplates2/qquickrangeslider_p.h +++ b/src/quicktemplates2/qquickrangeslider_p.h @@ -60,11 +60,13 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickRangeSlider : public QQuickControl Q_OBJECT Q_PROPERTY(qreal from READ from WRITE setFrom NOTIFY fromChanged FINAL) Q_PROPERTY(qreal to READ to WRITE setTo NOTIFY toChanged FINAL) - Q_PROPERTY(QQuickRangeSliderNode *first READ first CONSTANT) - Q_PROPERTY(QQuickRangeSliderNode *second READ second CONSTANT) + Q_PROPERTY(QQuickRangeSliderNode *first READ first CONSTANT FINAL) + Q_PROPERTY(QQuickRangeSliderNode *second READ second CONSTANT FINAL) Q_PROPERTY(qreal stepSize READ stepSize WRITE setStepSize NOTIFY stepSizeChanged FINAL) Q_PROPERTY(SnapMode snapMode READ snapMode WRITE setSnapMode NOTIFY snapModeChanged FINAL) Q_PROPERTY(Qt::Orientation orientation READ orientation WRITE setOrientation NOTIFY orientationChanged FINAL) + Q_PROPERTY(bool horizontal READ isHorizontal NOTIFY orientationChanged FINAL REVISION 3) + Q_PROPERTY(bool vertical READ isVertical NOTIFY orientationChanged FINAL REVISION 3) Q_PROPERTY(bool live READ live WRITE setLive NOTIFY liveChanged FINAL REVISION 2) public: @@ -95,6 +97,9 @@ public: Qt::Orientation orientation() const; void setOrientation(Qt::Orientation orientation); + bool isHorizontal() const; + bool isVertical() const; + bool live() const; void setLive(bool live); diff --git a/src/quicktemplates2/qquickscrollbar.cpp b/src/quicktemplates2/qquickscrollbar.cpp index 87ff4b0a..e75fed5a 100644 --- a/src/quicktemplates2/qquickscrollbar.cpp +++ b/src/quicktemplates2/qquickscrollbar.cpp @@ -438,6 +438,8 @@ void QQuickScrollBar::setPressed(bool pressed) This property is automatically set when the scroll bar is \l {Attaching ScrollBar to a Flickable}{attached to a flickable}. + + \sa horizontal, vertical */ Qt::Orientation QQuickScrollBar::orientation() const { @@ -559,6 +561,36 @@ void QQuickScrollBar::setPolicy(Policy policy) } /*! + \since QtQuick.Controls 2.3 (Qt 5.10) + \qmlproperty bool QtQuick.Controls::ScrollBar::horizontal + \readonly + + This property holds whether the scroll bar is horizontal. + + \sa orientation +*/ +bool QQuickScrollBar::isHorizontal() const +{ + Q_D(const QQuickScrollBar); + return d->orientation == Qt::Horizontal; +} + +/*! + \since QtQuick.Controls 2.3 (Qt 5.10) + \qmlproperty bool QtQuick.Controls::ScrollBar::vertical + \readonly + + This property holds whether the scroll bar is vertical. + + \sa orientation +*/ +bool QQuickScrollBar::isVertical() const +{ + Q_D(const QQuickScrollBar); + return d->orientation == Qt::Vertical; +} + +/*! \qmlmethod void QtQuick.Controls::ScrollBar::increase() Increases the position by \l stepSize or \c 0.1 if stepSize is \c 0.0. diff --git a/src/quicktemplates2/qquickscrollbar_p.h b/src/quicktemplates2/qquickscrollbar_p.h index 28c48428..9b417a2b 100644 --- a/src/quicktemplates2/qquickscrollbar_p.h +++ b/src/quicktemplates2/qquickscrollbar_p.h @@ -67,6 +67,8 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickScrollBar : public QQuickControl Q_PROPERTY(SnapMode snapMode READ snapMode WRITE setSnapMode NOTIFY snapModeChanged FINAL REVISION 2) Q_PROPERTY(bool interactive READ isInteractive WRITE setInteractive RESET resetInteractive NOTIFY interactiveChanged FINAL REVISION 2) Q_PROPERTY(Policy policy READ policy WRITE setPolicy NOTIFY policyChanged FINAL REVISION 2) + Q_PROPERTY(bool horizontal READ isHorizontal NOTIFY orientationChanged FINAL REVISION 3) + Q_PROPERTY(bool vertical READ isVertical NOTIFY orientationChanged FINAL REVISION 3) public: explicit QQuickScrollBar(QQuickItem *parent = nullptr); @@ -112,6 +114,9 @@ public: Policy policy() const; void setPolicy(Policy policy); + bool isHorizontal() const; + bool isVertical() const; + public Q_SLOTS: void increase(); void decrease(); diff --git a/src/quicktemplates2/qquickscrollindicator.cpp b/src/quicktemplates2/qquickscrollindicator.cpp index 347c2a68..d14138af 100644 --- a/src/quicktemplates2/qquickscrollindicator.cpp +++ b/src/quicktemplates2/qquickscrollindicator.cpp @@ -276,6 +276,8 @@ void QQuickScrollIndicator::setActive(bool active) This property is automatically set when the scroll indicator is \l {Attaching ScrollIndicator to a Flickable}{attached to a flickable}. + + \sa horizontal, vertical */ Qt::Orientation QQuickScrollIndicator::orientation() const { @@ -295,6 +297,36 @@ void QQuickScrollIndicator::setOrientation(Qt::Orientation orientation) emit orientationChanged(); } +/*! + \since QtQuick.Controls 2.3 (Qt 5.10) + \qmlproperty bool QtQuick.Controls::ScrollIndicator::horizontal + \readonly + + This property holds whether the scroll indicator is horizontal. + + \sa orientation +*/ +bool QQuickScrollIndicator::isHorizontal() const +{ + Q_D(const QQuickScrollIndicator); + return d->orientation == Qt::Horizontal; +} + +/*! + \since QtQuick.Controls 2.3 (Qt 5.10) + \qmlproperty bool QtQuick.Controls::ScrollIndicator::vertical + \readonly + + This property holds whether the scroll indicator is vertical. + + \sa orientation +*/ +bool QQuickScrollIndicator::isVertical() const +{ + Q_D(const QQuickScrollIndicator); + return d->orientation == Qt::Vertical; +} + class QQuickScrollIndicatorAttachedPrivate : public QObjectPrivate, public QQuickItemChangeListener { public: diff --git a/src/quicktemplates2/qquickscrollindicator_p.h b/src/quicktemplates2/qquickscrollindicator_p.h index bc6c5418..6f08ef31 100644 --- a/src/quicktemplates2/qquickscrollindicator_p.h +++ b/src/quicktemplates2/qquickscrollindicator_p.h @@ -63,6 +63,8 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickScrollIndicator : public QQuickCont Q_PROPERTY(qreal position READ position WRITE setPosition NOTIFY positionChanged FINAL) Q_PROPERTY(bool active READ isActive WRITE setActive NOTIFY activeChanged FINAL) Q_PROPERTY(Qt::Orientation orientation READ orientation WRITE setOrientation NOTIFY orientationChanged FINAL) + Q_PROPERTY(bool horizontal READ isHorizontal NOTIFY orientationChanged FINAL REVISION 3) + Q_PROPERTY(bool vertical READ isVertical NOTIFY orientationChanged FINAL REVISION 3) public: explicit QQuickScrollIndicator(QQuickItem *parent = nullptr); @@ -78,6 +80,9 @@ public: Qt::Orientation orientation() const; void setOrientation(Qt::Orientation orientation); + bool isHorizontal() const; + bool isVertical() const; + public Q_SLOTS: void setSize(qreal size); void setPosition(qreal position); diff --git a/src/quicktemplates2/qquickslider.cpp b/src/quicktemplates2/qquickslider.cpp index 91607853..e54e95cd 100644 --- a/src/quicktemplates2/qquickslider.cpp +++ b/src/quicktemplates2/qquickslider.cpp @@ -479,6 +479,36 @@ void QQuickSlider::setPressed(bool pressed) } /*! + \since QtQuick.Controls 2.3 (Qt 5.10) + \qmlproperty bool QtQuick.Controls::Slider::horizontal + \readonly + + This property holds whether the slider is horizontal. + + \sa orientation +*/ +bool QQuickSlider::isHorizontal() const +{ + Q_D(const QQuickSlider); + return d->orientation == Qt::Horizontal; +} + +/*! + \since QtQuick.Controls 2.3 (Qt 5.10) + \qmlproperty bool QtQuick.Controls::Slider::vertical + \readonly + + This property holds whether the slider is vertical. + + \sa orientation +*/ +bool QQuickSlider::isVertical() const +{ + Q_D(const QQuickSlider); + return d->orientation == Qt::Vertical; +} + +/*! \qmlproperty enumeration QtQuick.Controls::Slider::orientation This property holds the orientation. @@ -486,6 +516,8 @@ void QQuickSlider::setPressed(bool pressed) Possible values: \value Qt.Horizontal Horizontal (default) \value Qt.Vertical Vertical + + \sa horizontal, vertical */ Qt::Orientation QQuickSlider::orientation() const { diff --git a/src/quicktemplates2/qquickslider_p.h b/src/quicktemplates2/qquickslider_p.h index 6f0e6fc6..cb441ddd 100644 --- a/src/quicktemplates2/qquickslider_p.h +++ b/src/quicktemplates2/qquickslider_p.h @@ -66,6 +66,8 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickSlider : public QQuickControl Q_PROPERTY(SnapMode snapMode READ snapMode WRITE setSnapMode NOTIFY snapModeChanged FINAL) Q_PROPERTY(bool live READ live WRITE setLive NOTIFY liveChanged FINAL REVISION 2) Q_PROPERTY(bool pressed READ isPressed WRITE setPressed NOTIFY pressedChanged FINAL) + Q_PROPERTY(bool horizontal READ isHorizontal NOTIFY orientationChanged FINAL REVISION 3) + Q_PROPERTY(bool vertical READ isVertical NOTIFY orientationChanged FINAL REVISION 3) Q_PROPERTY(Qt::Orientation orientation READ orientation WRITE setOrientation NOTIFY orientationChanged FINAL) Q_PROPERTY(QQuickItem *handle READ handle WRITE setHandle NOTIFY handleChanged FINAL) @@ -103,6 +105,9 @@ public: bool isPressed() const; void setPressed(bool pressed); + bool isHorizontal() const; + bool isVertical() const; + Qt::Orientation orientation() const; void setOrientation(Qt::Orientation orientation); diff --git a/src/quicktemplates2/qquickspinbox.cpp b/src/quicktemplates2/qquickspinbox.cpp index dbb67c43..f7458011 100644 --- a/src/quicktemplates2/qquickspinbox.cpp +++ b/src/quicktemplates2/qquickspinbox.cpp @@ -108,6 +108,7 @@ class QQuickSpinBoxPrivate : public QQuickControlPrivate public: QQuickSpinBoxPrivate() : editable(false), + wrap(false), from(0), to(99), value(0), @@ -121,9 +122,10 @@ public: { } - int boundValue(int value) const; + int boundValue(int value, bool wrap) const; void updateValue(); - bool setValue(int value); + bool setValue(int value, bool wrap); + bool stepBy(int steps); int effectiveStepSize() const; @@ -143,6 +145,7 @@ public: void handleUngrab() override; bool editable; + bool wrap; int from; int to; int value; @@ -157,9 +160,20 @@ public: Qt::InputMethodHints inputMethodHints; }; -int QQuickSpinBoxPrivate::boundValue(int value) const +int QQuickSpinBoxPrivate::boundValue(int value, bool wrap) const { - return from > to ? qBound(to, value, from) : qBound(from, value, to); + bool inverted = from > to; + if (!wrap) + return inverted ? qBound(to, value, from) : qBound(from, value, to); + + int f = inverted ? to : from; + int t = inverted ? from : to; + if (value < f) + value = t; + else if (value > t) + value = f; + + return value; } void QQuickSpinBoxPrivate::updateValue() @@ -174,7 +188,7 @@ void QQuickSpinBoxPrivate::updateValue() QJSValue loc(v4, QQmlLocale::wrap(v4, locale)); QJSValue val = q->valueFromText().call(QJSValueList() << text.toString() << loc); const int oldValue = value; - q->setValue(val.toInt()); + setValue(val.toInt(), /* allowWrap = */ false); if (oldValue != value) emit q->valueModified(); } @@ -182,11 +196,11 @@ void QQuickSpinBoxPrivate::updateValue() } } -bool QQuickSpinBoxPrivate::setValue(int newValue) +bool QQuickSpinBoxPrivate::setValue(int newValue, bool allowWrap) { Q_Q(QQuickSpinBox); if (q->isComponentComplete()) - newValue = boundValue(newValue); + newValue = boundValue(newValue, allowWrap); if (value == newValue) return false; @@ -200,6 +214,11 @@ bool QQuickSpinBoxPrivate::setValue(int newValue) return true; } +bool QQuickSpinBoxPrivate::stepBy(int steps) +{ + return setValue(value + steps, wrap); +} + int QQuickSpinBoxPrivate::effectiveStepSize() const { return from > to ? -1 * stepSize : stepSize; @@ -217,7 +236,7 @@ void QQuickSpinBoxPrivate::updateUpEnabled() if (!upIndicator) return; - upIndicator->setEnabled(from < to ? value < to : value > to); + upIndicator->setEnabled(wrap || (from < to ? value < to : value > to)); } bool QQuickSpinBoxPrivate::downEnabled() const @@ -232,7 +251,7 @@ void QQuickSpinBoxPrivate::updateDownEnabled() if (!downIndicator) return; - downIndicator->setEnabled(from < to ? value > from : value < from); + downIndicator->setEnabled(wrap || (from < to ? value > from : value < from)); } void QQuickSpinBoxPrivate::updateHover(const QPointF &pos) @@ -373,7 +392,7 @@ void QQuickSpinBox::setFrom(int from) d->from = from; emit fromChanged(); if (isComponentComplete()) { - if (!d->setValue(d->value)) { + if (!d->setValue(d->value, /* allowWrap = */ false)) { d->updateUpEnabled(); d->updateDownEnabled(); } @@ -402,7 +421,7 @@ void QQuickSpinBox::setTo(int to) d->to = to; emit toChanged(); if (isComponentComplete()) { - if (!d->setValue(d->value)) { + if (!d->setValue(d->value, /* allowWrap = */false)) { d->updateUpEnabled(); d->updateDownEnabled(); } @@ -423,7 +442,7 @@ int QQuickSpinBox::value() const void QQuickSpinBox::setValue(int value) { Q_D(QQuickSpinBox); - d->setValue(value); + d->setValue(value, /* allowWrap = */ false); } /*! @@ -695,6 +714,34 @@ bool QQuickSpinBox::isInputMethodComposing() const } /*! + \since QtQuick.Controls 2.3 (Qt 5.10) + \qmlproperty bool QtQuick.Controls::SpinBox::wrap + + This property holds whether the spinbox wraps. The default value is \c false. + + If wrap is \c true, stepping past \l to changes the value to \l from and vice versa. +*/ +bool QQuickSpinBox::wrap() const +{ + Q_D(const QQuickSpinBox); + return d->wrap; +} + +void QQuickSpinBox::setWrap(bool wrap) +{ + Q_D(QQuickSpinBox); + if (d->wrap == wrap) + return; + + d->wrap = wrap; + if (d->value == d->from || d->value == d->to) { + d->updateUpEnabled(); + d->updateDownEnabled(); + } + emit wrapChanged(); +} + +/*! \qmlmethod void QtQuick.Controls::SpinBox::increase() Increases the value by \l stepSize, or \c 1 if stepSize is not defined. @@ -704,7 +751,7 @@ bool QQuickSpinBox::isInputMethodComposing() const void QQuickSpinBox::increase() { Q_D(QQuickSpinBox); - setValue(d->value + d->effectiveStepSize()); + d->stepBy(d->effectiveStepSize()); } /*! @@ -717,7 +764,7 @@ void QQuickSpinBox::increase() void QQuickSpinBox::decrease() { Q_D(QQuickSpinBox); - setValue(d->value - d->effectiveStepSize()); + d->stepBy(-d->effectiveStepSize()); } void QQuickSpinBox::focusInEvent(QFocusEvent *event) @@ -820,7 +867,7 @@ void QQuickSpinBox::wheelEvent(QWheelEvent *event) const int oldValue = d->value; const QPointF angle = event->angleDelta(); const qreal delta = (qFuzzyIsNull(angle.y()) ? angle.x() : angle.y()) / QWheelEvent::DefaultDeltasPerStep; - setValue(oldValue + qRound(d->effectiveStepSize() * delta)); + d->stepBy(qRound(d->effectiveStepSize() * delta)); if (d->value != oldValue) emit valueModified(); event->setAccepted(d->value != oldValue); @@ -867,6 +914,11 @@ QFont QQuickSpinBox::defaultFont() const return QQuickControlPrivate::themeFont(QPlatformTheme::EditorFont); } +QPalette QQuickSpinBox::defaultPalette() const +{ + return QQuickControlPrivate::themePalette(QPlatformTheme::TextLineEditPalette); +} + #if QT_CONFIG(accessibility) QAccessible::Role QQuickSpinBox::accessibleRole() const { diff --git a/src/quicktemplates2/qquickspinbox_p.h b/src/quicktemplates2/qquickspinbox_p.h index bd0d1ab2..13ba89a9 100644 --- a/src/quicktemplates2/qquickspinbox_p.h +++ b/src/quicktemplates2/qquickspinbox_p.h @@ -73,6 +73,7 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickSpinBox : public QQuickControl Q_PROPERTY(QQuickSpinButton *down READ down CONSTANT FINAL) Q_PROPERTY(Qt::InputMethodHints inputMethodHints READ inputMethodHints WRITE setInputMethodHints NOTIFY inputMethodHintsChanged FINAL REVISION 2) Q_PROPERTY(bool inputMethodComposing READ isInputMethodComposing NOTIFY inputMethodComposingChanged FINAL REVISION 2) + Q_PROPERTY(bool wrap READ wrap WRITE setWrap NOTIFY wrapChanged FINAL REVISION 3) public: explicit QQuickSpinBox(QQuickItem *parent = nullptr); @@ -109,6 +110,9 @@ public: bool isInputMethodComposing() const; + bool wrap() const; + void setWrap(bool wrap); + public Q_SLOTS: void increase(); void decrease(); @@ -125,6 +129,7 @@ Q_SIGNALS: Q_REVISION(2) void valueModified(); Q_REVISION(2) void inputMethodHintsChanged(); Q_REVISION(2) void inputMethodComposingChanged(); + Q_REVISION(3) void wrapChanged(); protected: void focusInEvent(QFocusEvent *event) override; @@ -143,6 +148,7 @@ protected: void contentItemChange(QQuickItem *newItem, QQuickItem *oldItem) override; QFont defaultFont() const override; + QPalette defaultPalette() const override; #if QT_CONFIG(accessibility) QAccessible::Role accessibleRole() const override; diff --git a/src/quicktemplates2/qquickstackview.cpp b/src/quicktemplates2/qquickstackview.cpp index ea4e36d0..674e6ee1 100644 --- a/src/quicktemplates2/qquickstackview.cpp +++ b/src/quicktemplates2/qquickstackview.cpp @@ -516,8 +516,9 @@ void QQuickStackView::push(QQmlV4Function *args) if (!d->elements.isEmpty()) exit = d->elements.top(); + int oldDepth = d->elements.count(); if (d->pushElements(elements)) { - emit depthChanged(); + d->depthChange(d->elements.count(), oldDepth); QQuickStackElement *enter = d->elements.top(); d->startTransition(QQuickStackTransition::pushEnter(operation, enter, this), QQuickStackTransition::pushExit(operation, exit, this), @@ -574,6 +575,7 @@ void QQuickStackView::pop(QQmlV4Function *args) return; } + int oldDepth = d->elements.count(); QQuickStackElement *exit = d->elements.pop(); QQuickStackElement *enter = d->elements.top(); @@ -612,7 +614,7 @@ void QQuickStackView::pop(QQmlV4Function *args) d->removing.insert(exit); previousItem = exit->item; } - emit depthChanged(); + d->depthChange(d->elements.count(), oldDepth); d->startTransition(QQuickStackTransition::popExit(operation, exit, this), QQuickStackTransition::popEnter(operation, enter, this), operation == Immediate); @@ -752,14 +754,13 @@ void QQuickStackView::replace(QQmlV4Function *args) return; } - int depth = d->elements.count(); + int oldDepth = d->elements.count(); QQuickStackElement* exit = nullptr; if (!d->elements.isEmpty()) exit = d->elements.pop(); if (exit != target ? d->replaceElements(target, elements) : d->pushElements(elements)) { - if (depth != d->elements.count()) - emit depthChanged(); + d->depthChange(d->elements.count(), oldDepth); if (exit) { exit->removal = true; d->removing.insert(exit); @@ -780,20 +781,51 @@ void QQuickStackView::replace(QQmlV4Function *args) } /*! - \qmlmethod void QtQuick.Controls::StackView::clear() + \since QtQuick.Controls 2.3 (Qt 5.10) + \qmlproperty bool QtQuick.Controls::StackView::empty + \readonly + + This property holds whether the stack is empty. + + \sa depth +*/ +bool QQuickStackView::isEmpty() const +{ + Q_D(const QQuickStackView); + return d->elements.isEmpty(); +} - Removes all items from the stack. No animations are applied. +/*! + \qmlmethod void QtQuick.Controls::StackView::clear(transition) + + Removes all items from the stack. + + Since QtQuick.Controls 2.3, a \a transition can be optionally specified. Supported transitions: + + \value StackView.Immediate Clear the stack immediately without any transition (default). + \value StackView.PushTransition Clear the stack with a push transition. + \value StackView.ReplaceTransition Clear the stack with a replace transition. + \value StackView.PopTransition Clear the stack with a pop transition. */ -void QQuickStackView::clear() +void QQuickStackView::clear(Operation operation) { Q_D(QQuickStackView); if (d->elements.isEmpty()) return; + if (operation != Immediate) { + QQuickStackElement *exit = d->elements.pop(); + exit->removal = true; + d->removing.insert(exit); + d->startTransition(QQuickStackTransition::popExit(operation, exit, this), + QQuickStackTransition::popEnter(operation, nullptr, this), false); + } + + int oldDepth = d->elements.count(); d->setCurrentItem(nullptr); qDeleteAll(d->elements); d->elements.clear(); - emit depthChanged(); + d->depthChange(0, oldDepth); } /*! @@ -990,6 +1022,7 @@ void QQuickStackView::componentComplete() QScopedValueRollback<QString> rollback(d->operation, QStringLiteral("initialItem")); QQuickStackElement *element = nullptr; QString error; + int oldDepth = d->elements.count(); if (QObject *o = d->initialItem.value<QObject *>()) element = QQuickStackElement::fromObject(o, this, &error); else if (d->initialItem.canConvert<QString>()) @@ -997,7 +1030,7 @@ void QQuickStackView::componentComplete() if (!error.isEmpty()) { d->warn(error); } else if (d->pushElement(element)) { - emit depthChanged(); + d->depthChange(d->elements.count(), oldDepth); d->setCurrentItem(element); element->setStatus(QQuickStackView::Active); } diff --git a/src/quicktemplates2/qquickstackview_p.cpp b/src/quicktemplates2/qquickstackview_p.cpp index 3c983d6b..f4405246 100644 --- a/src/quicktemplates2/qquickstackview_p.cpp +++ b/src/quicktemplates2/qquickstackview_p.cpp @@ -297,4 +297,15 @@ void QQuickStackViewPrivate::setBusy(bool b) emit q->busyChanged(); } +void QQuickStackViewPrivate::depthChange(int newDepth, int oldDepth) +{ + Q_Q(QQuickStackView); + if (newDepth == oldDepth) + return; + + emit q->depthChanged(); + if (newDepth == 0 || oldDepth == 0) + emit q->emptyChanged(); +} + QT_END_NAMESPACE diff --git a/src/quicktemplates2/qquickstackview_p.h b/src/quicktemplates2/qquickstackview_p.h index b74a162d..21c20f3a 100644 --- a/src/quicktemplates2/qquickstackview_p.h +++ b/src/quicktemplates2/qquickstackview_p.h @@ -72,6 +72,7 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickStackView : public QQuickControl Q_PROPERTY(QQuickTransition *pushExit READ pushExit WRITE setPushExit NOTIFY pushExitChanged FINAL) Q_PROPERTY(QQuickTransition *replaceEnter READ replaceEnter WRITE setReplaceEnter NOTIFY replaceEnterChanged FINAL) Q_PROPERTY(QQuickTransition *replaceExit READ replaceExit WRITE setReplaceExit NOTIFY replaceExitChanged FINAL) + Q_PROPERTY(bool empty READ isEmpty NOTIFY emptyChanged FINAL REVISION 3) public: explicit QQuickStackView(QQuickItem *parent = nullptr); @@ -134,8 +135,10 @@ public: Q_INVOKABLE void pop(QQmlV4Function *args); Q_INVOKABLE void replace(QQmlV4Function *args); + bool isEmpty() const; + public Q_SLOTS: - void clear(); + void clear(Operation operation = Immediate); Q_SIGNALS: void busyChanged(); @@ -147,6 +150,7 @@ Q_SIGNALS: void pushExitChanged(); void replaceEnterChanged(); void replaceExitChanged(); + Q_REVISION(3) void emptyChanged(); protected: void componentComplete() override; diff --git a/src/quicktemplates2/qquickstackview_p_p.h b/src/quicktemplates2/qquickstackview_p_p.h index 81ca9164..d86f35cd 100644 --- a/src/quicktemplates2/qquickstackview_p_p.h +++ b/src/quicktemplates2/qquickstackview_p_p.h @@ -92,6 +92,7 @@ public: void viewItemTransitionFinished(QQuickItemViewTransitionableItem *item) override; void setBusy(bool busy); + void depthChange(int newDepth, int oldDepth); bool busy; QString operation; diff --git a/src/quicktemplates2/qquickswipedelegate_p.h b/src/quicktemplates2/qquickswipedelegate_p.h index 5ba0604d..a9900eb8 100644 --- a/src/quicktemplates2/qquickswipedelegate_p.h +++ b/src/quicktemplates2/qquickswipedelegate_p.h @@ -60,7 +60,7 @@ class QQuickSwipeDelegateAttachedPrivate; class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickSwipeDelegate : public QQuickItemDelegate { Q_OBJECT - Q_PROPERTY(QQuickSwipe *swipe READ swipe CONSTANT) + Q_PROPERTY(QQuickSwipe *swipe READ swipe CONSTANT FINAL) public: explicit QQuickSwipeDelegate(QQuickItem *parent = nullptr); diff --git a/src/quicktemplates2/qquickswipeview.cpp b/src/quicktemplates2/qquickswipeview.cpp index f6efc7e4..ce586363 100644 --- a/src/quicktemplates2/qquickswipeview.cpp +++ b/src/quicktemplates2/qquickswipeview.cpp @@ -121,6 +121,32 @@ public: Qt::Orientation orientation; }; +class QQuickSwipeViewAttachedPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QQuickSwipeViewAttached) + +public: + QQuickSwipeViewAttachedPrivate() + : swipeView(nullptr), + index(-1), + currentIndex(-1) + { + } + + static QQuickSwipeViewAttachedPrivate *get(QQuickSwipeViewAttached *attached) + { + return attached->d_func(); + } + + void update(QQuickSwipeView *newView, int newIndex); + void updateCurrentIndex(); + void setCurrentIndex(int i); + + QQuickSwipeView *swipeView; + int index; + int currentIndex; +}; + void QQuickSwipeViewPrivate::resizeItems() { Q_Q(QQuickSwipeView); @@ -190,6 +216,8 @@ void QQuickSwipeView::setInteractive(bool interactive) Possible values: \value Qt.Horizontal Horizontal (default) \value Qt.Vertical Vertical + + \sa horizontal, vertical */ Qt::Orientation QQuickSwipeView::orientation() const { @@ -209,6 +237,36 @@ void QQuickSwipeView::setOrientation(Qt::Orientation orientation) emit orientationChanged(); } +/*! + \since QtQuick.Controls 2.3 (Qt 5.10) + \qmlproperty bool QtQuick.Controls::SwipeView::horizontal + \readonly + + This property holds whether the swipe view is horizontal. + + \sa orientation +*/ +bool QQuickSwipeView::isHorizontal() const +{ + Q_D(const QQuickSwipeView); + return d->orientation == Qt::Horizontal; +} + +/*! + \since QtQuick.Controls 2.3 (Qt 5.10) + \qmlproperty bool QtQuick.Controls::SwipeView::vertical + \readonly + + This property holds whether the swipe view is vertical. + + \sa orientation +*/ +bool QQuickSwipeView::isVertical() const +{ + Q_D(const QQuickSwipeView); + return d->orientation == Qt::Vertical; +} + QQuickSwipeViewAttached *QQuickSwipeView::qmlAttachedProperties(QObject *object) { return new QQuickSwipeViewAttached(object); @@ -221,12 +279,29 @@ void QQuickSwipeView::geometryChanged(const QRectF &newGeometry, const QRectF &o d->resizeItems(); } -void QQuickSwipeView::itemAdded(int, QQuickItem *item) +void QQuickSwipeView::itemAdded(int index, QQuickItem *item) { Q_D(QQuickSwipeView); QQuickItemPrivate::get(item)->setCulled(true); // QTBUG-51078, QTBUG-51669 if (isComponentComplete()) item->setSize(QSizeF(d->contentItem->width(), d->contentItem->height())); + QQuickSwipeViewAttached *attached = qobject_cast<QQuickSwipeViewAttached *>(qmlAttachedPropertiesObject<QQuickSwipeView>(item)); + if (attached) + QQuickSwipeViewAttachedPrivate::get(attached)->update(this, index); +} + +void QQuickSwipeView::itemMoved(int index, QQuickItem *item) +{ + QQuickSwipeViewAttached *attached = qobject_cast<QQuickSwipeViewAttached *>(qmlAttachedPropertiesObject<QQuickSwipeView>(item)); + if (attached) + QQuickSwipeViewAttachedPrivate::get(attached)->update(this, index); +} + +void QQuickSwipeView::itemRemoved(int, QQuickItem *item) +{ + QQuickSwipeViewAttached *attached = qobject_cast<QQuickSwipeViewAttached *>(qmlAttachedPropertiesObject<QQuickSwipeView>(item)); + if (attached) + QQuickSwipeViewAttachedPrivate::get(attached)->update(nullptr, -1); } #if QT_CONFIG(accessibility) @@ -283,85 +358,11 @@ QAccessible::Role QQuickSwipeView::accessibleRole() const It is attached to each child item of the SwipeView. */ -class QQuickSwipeViewAttachedPrivate : public QObjectPrivate, public QQuickItemChangeListener -{ - Q_DECLARE_PUBLIC(QQuickSwipeViewAttached) -public: - QQuickSwipeViewAttachedPrivate() - : item(nullptr), - swipeView(nullptr), - index(-1), - currentIndex(-1) - { - } - - ~QQuickSwipeViewAttachedPrivate() { - } - - void updateView(QQuickItem *parent); - - void itemChildAdded(QQuickItem *, QQuickItem *) override; - void itemChildRemoved(QQuickItem *, QQuickItem *) override; - void itemParentChanged(QQuickItem *, QQuickItem *) override; - void itemDestroyed(QQuickItem *) override; - - void updateIndex(); - void updateCurrentIndex(); - - void setView(QQuickSwipeView *view); - void setIndex(int i); - void setCurrentIndex(int i); - - QQuickItem *item; - QQuickSwipeView *swipeView; - int index; - int currentIndex; -}; - -void QQuickSwipeViewAttachedPrivate::updateIndex() -{ - setIndex(swipeView ? QQuickSwipeViewPrivate::get(swipeView)->contentModel->indexOf(item, nullptr) : -1); -} - void QQuickSwipeViewAttachedPrivate::updateCurrentIndex() { setCurrentIndex(swipeView ? swipeView->currentIndex() : -1); } -void QQuickSwipeViewAttachedPrivate::setView(QQuickSwipeView *view) -{ - if (view == swipeView) - return; - - if (swipeView) { - QQuickItemPrivate *p = QQuickItemPrivate::get(swipeView); - p->removeItemChangeListener(this, QQuickItemPrivate::Children); - - disconnect(swipeView, &QQuickSwipeView::currentIndexChanged, - this, &QQuickSwipeViewAttachedPrivate::updateCurrentIndex); - disconnect(swipeView, &QQuickSwipeView::contentChildrenChanged, - this, &QQuickSwipeViewAttachedPrivate::updateIndex); - } - - swipeView = view; - - if (swipeView) { - QQuickItemPrivate *p = QQuickItemPrivate::get(swipeView); - p->addItemChangeListener(this, QQuickItemPrivate::Children); - - connect(swipeView, &QQuickSwipeView::currentIndexChanged, - this, &QQuickSwipeViewAttachedPrivate::updateCurrentIndex); - connect(swipeView, &QQuickSwipeView::contentChildrenChanged, - this, &QQuickSwipeViewAttachedPrivate::updateIndex); - } - - Q_Q(QQuickSwipeViewAttached); - emit q->viewChanged(); - - updateIndex(); - updateCurrentIndex(); -} - void QQuickSwipeViewAttachedPrivate::setCurrentIndex(int i) { if (i == currentIndex) @@ -381,79 +382,37 @@ void QQuickSwipeViewAttachedPrivate::setCurrentIndex(int i) emit q->isPreviousItemChanged(); } -void QQuickSwipeViewAttachedPrivate::setIndex(int i) +void QQuickSwipeViewAttachedPrivate::update(QQuickSwipeView *newView, int newIndex) { - if (i == index) - return; - - index = i; Q_Q(QQuickSwipeViewAttached); - emit q->indexChanged(); -} + int oldIndex = index; + QQuickSwipeView *oldView = swipeView; -void QQuickSwipeViewAttachedPrivate::updateView(QQuickItem *parent) -{ - // parent can be, e.g.: - // - The contentItem of a ListView (typically the case) - // - A non-visual or weird type like TestCase, when child items are created from components - // wherein the attached properties are used - // - null, when the item was removed with removeItem() - QQuickSwipeView *view = nullptr; - if (parent) { - view = qobject_cast<QQuickSwipeView*>(parent); - if (!view) { - if (parent->parentItem() && parent->parentItem()->property("contentItem").isValid()) { - // The parent is the contentItem of some kind of view. - view = qobject_cast<QQuickSwipeView*>(parent->parentItem()->parentItem()); - } + index = newIndex; + swipeView = newView; + + if (oldView != newView) { + if (oldView) { + disconnect(oldView, &QQuickSwipeView::currentIndexChanged, + this, &QQuickSwipeViewAttachedPrivate::updateCurrentIndex); } + if (newView) { + connect(newView, &QQuickSwipeView::currentIndexChanged, + this, &QQuickSwipeViewAttachedPrivate::updateCurrentIndex); + } + emit q->viewChanged(); } + if (oldIndex != newIndex) + emit q->indexChanged(); - setView(view); -} - -void QQuickSwipeViewAttachedPrivate::itemChildAdded(QQuickItem *, QQuickItem *) -{ - updateIndex(); -} - -void QQuickSwipeViewAttachedPrivate::itemChildRemoved(QQuickItem *, QQuickItem *) -{ - updateIndex(); -} - -void QQuickSwipeViewAttachedPrivate::itemParentChanged(QQuickItem *, QQuickItem *parent) -{ - updateView(parent); -} - -void QQuickSwipeViewAttachedPrivate::itemDestroyed(QQuickItem *item) -{ - QQuickItemPrivate::get(item)->removeItemChangeListener(this, QQuickItemPrivate::Parent | QQuickItemPrivate::Destroyed); + updateCurrentIndex(); } QQuickSwipeViewAttached::QQuickSwipeViewAttached(QObject *parent) : QObject(*(new QQuickSwipeViewAttachedPrivate), parent) { - Q_D(QQuickSwipeViewAttached); - d->item = qobject_cast<QQuickItem *>(parent); - if (d->item) { - if (d->item->parentItem()) - d->updateView(d->item->parentItem()); - - QQuickItemPrivate *p = QQuickItemPrivate::get(d->item); - p->addItemChangeListener(d, QQuickItemPrivate::Parent | QQuickItemPrivate::Destroyed); - } else if (parent) { + if (!qobject_cast<QQuickItem *>(parent)) qmlWarning(parent) << "SwipeView: attached properties must be accessed from within a child item"; - } -} - -QQuickSwipeViewAttached::~QQuickSwipeViewAttached() -{ - Q_D(QQuickSwipeViewAttached); - QQuickItem *item = qobject_cast<QQuickItem *>(parent()); - if (item) - QQuickItemPrivate::get(item)->removeItemChangeListener(d, QQuickItemPrivate::Parent | QQuickItemPrivate::Destroyed); } QQuickSwipeView *QQuickSwipeViewAttached::view() const diff --git a/src/quicktemplates2/qquickswipeview_p.h b/src/quicktemplates2/qquickswipeview_p.h index e07ed7f0..543cb6aa 100644 --- a/src/quicktemplates2/qquickswipeview_p.h +++ b/src/quicktemplates2/qquickswipeview_p.h @@ -60,6 +60,8 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickSwipeView : public QQuickContainer Q_OBJECT Q_PROPERTY(bool interactive READ isInteractive WRITE setInteractive NOTIFY interactiveChanged FINAL REVISION 1) Q_PROPERTY(Qt::Orientation orientation READ orientation WRITE setOrientation NOTIFY orientationChanged FINAL REVISION 2) + Q_PROPERTY(bool horizontal READ isHorizontal NOTIFY orientationChanged FINAL REVISION 3) + Q_PROPERTY(bool vertical READ isVertical NOTIFY orientationChanged FINAL REVISION 3) public: explicit QQuickSwipeView(QQuickItem *parent = nullptr); @@ -70,6 +72,9 @@ public: Qt::Orientation orientation() const; void setOrientation(Qt::Orientation orientation); + bool isHorizontal() const; + bool isVertical() const; + static QQuickSwipeViewAttached *qmlAttachedProperties(QObject *object); Q_SIGNALS: @@ -79,6 +84,8 @@ Q_SIGNALS: protected: void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override; void itemAdded(int index, QQuickItem *item) override; + void itemMoved(int index, QQuickItem *item) override; + void itemRemoved(int index, QQuickItem *item) override; #if QT_CONFIG(accessibility) QAccessible::Role accessibleRole() const override; @@ -102,7 +109,6 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickSwipeViewAttached : public QObject public: explicit QQuickSwipeViewAttached(QObject *parent = nullptr); - ~QQuickSwipeViewAttached(); int index() const; bool isCurrentItem() const; diff --git a/src/quicktemplates2/qquickswitch.cpp b/src/quicktemplates2/qquickswitch.cpp index ece9802d..ae447de8 100644 --- a/src/quicktemplates2/qquickswitch.cpp +++ b/src/quicktemplates2/qquickswitch.cpp @@ -229,4 +229,10 @@ void QQuickSwitch::buttonChange(ButtonChange change) QQuickAbstractButton::buttonChange(change); } +QPalette QQuickSwitch::defaultPalette() const +{ + // ### TODO: add QPlatformTheme::SwitchPalette + return QQuickControlPrivate::themePalette(QPlatformTheme::CheckBoxPalette); +} + QT_END_NAMESPACE diff --git a/src/quicktemplates2/qquickswitch_p.h b/src/quicktemplates2/qquickswitch_p.h index 5b93cd32..ebcfea53 100644 --- a/src/quicktemplates2/qquickswitch_p.h +++ b/src/quicktemplates2/qquickswitch_p.h @@ -81,6 +81,8 @@ protected: void nextCheckState() override; void buttonChange(ButtonChange change) override; + QPalette defaultPalette() const override; + private: Q_DISABLE_COPY(QQuickSwitch) Q_DECLARE_PRIVATE(QQuickSwitch) diff --git a/src/quicktemplates2/qquicktabbar.cpp b/src/quicktemplates2/qquicktabbar.cpp index 65a4a863..814d14ea 100644 --- a/src/quicktemplates2/qquicktabbar.cpp +++ b/src/quicktemplates2/qquicktabbar.cpp @@ -116,6 +116,28 @@ public: QQuickTabBar::Position position; }; +class QQuickTabBarAttachedPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QQuickTabBarAttached) + +public: + QQuickTabBarAttachedPrivate() + : index(-1), + tabBar(nullptr) + { + } + + static QQuickTabBarAttachedPrivate *get(QQuickTabBarAttached *attached) + { + return attached->d_func(); + } + + void update(QQuickTabBar *tabBar, int index); + + int index; + QQuickTabBar *tabBar; +}; + QQuickTabBarPrivate::QQuickTabBarPrivate() : updatingLayout(false), hasContentWidth(false), @@ -152,38 +174,47 @@ void QQuickTabBarPrivate::updateLayout() qreal maxHeight = 0; qreal totalWidth = 0; qreal reservedWidth = 0; + int resizableCount = 0; - QVector<QQuickItem *> resizableItems; - resizableItems.reserve(count); + QVector<QQuickItem *> allItems; + allItems.reserve(count); for (int i = 0; i < count; ++i) { QQuickItem *item = q->itemAt(i); if (item) { QQuickItemPrivate *p = QQuickItemPrivate::get(item); if (!p->widthValid) { - resizableItems += item; + ++resizableCount; totalWidth += item->implicitWidth(); } else { reservedWidth += item->width(); totalWidth += item->width(); } maxHeight = qMax(maxHeight, item->implicitHeight()); + allItems += item; } } const qreal totalSpacing = qMax(0, count - 1) * spacing; totalWidth += totalSpacing; - if (!resizableItems.isEmpty()) { - const qreal itemWidth = (contentItem->width() - reservedWidth - totalSpacing) / resizableItems.count(); + const qreal itemWidth = (contentItem->width() - reservedWidth - totalSpacing) / qMax(1, resizableCount); - updatingLayout = true; - for (QQuickItem *item : qAsConst(resizableItems)) { + updatingLayout = true; + for (QQuickItem *item : qAsConst(allItems)) { + QQuickItemPrivate *p = QQuickItemPrivate::get(item); + if (!p->widthValid) { item->setWidth(itemWidth); - QQuickItemPrivate::get(item)->widthValid = false; + p->widthValid = false; + } + if (!p->heightValid) { + item->setHeight(hasContentHeight ? contentHeight : maxHeight); + p->heightValid = false; + } else { + item->setY((maxHeight - item->height()) / 2); } - updatingLayout = false; } + updatingLayout = false; bool contentWidthChange = false; if (!hasContentWidth && !qFuzzyCompare(contentWidth, totalWidth)) { @@ -342,6 +373,11 @@ void QQuickTabBar::resetContentHeight() d->updateLayout(); } +QQuickTabBarAttached *QQuickTabBar::qmlAttachedProperties(QObject *object) +{ + return new QQuickTabBarAttached(object); +} + void QQuickTabBar::updatePolish() { Q_D(QQuickTabBar); @@ -376,20 +412,38 @@ void QQuickTabBar::itemAdded(int index, QQuickItem *item) QQuickItemPrivate::get(item)->setCulled(true); // QTBUG-55129 if (QQuickTabButton *button = qobject_cast<QQuickTabButton *>(item)) QObjectPrivate::connect(button, &QQuickTabButton::checkedChanged, d, &QQuickTabBarPrivate::updateCurrentIndex); + QQuickTabBarAttached *attached = qobject_cast<QQuickTabBarAttached *>(qmlAttachedPropertiesObject<QQuickTabBar>(item)); + if (attached) + QQuickTabBarAttachedPrivate::get(attached)->update(this, index); if (isComponentComplete()) polish(); } +void QQuickTabBar::itemMoved(int index, QQuickItem *item) +{ + QQuickTabBarAttached *attached = qobject_cast<QQuickTabBarAttached *>(qmlAttachedPropertiesObject<QQuickTabBar>(item)); + if (attached) + QQuickTabBarAttachedPrivate::get(attached)->update(this, index); +} + void QQuickTabBar::itemRemoved(int index, QQuickItem *item) { Q_D(QQuickTabBar); Q_UNUSED(index); if (QQuickTabButton *button = qobject_cast<QQuickTabButton *>(item)) QObjectPrivate::disconnect(button, &QQuickTabButton::checkedChanged, d, &QQuickTabBarPrivate::updateCurrentIndex); + QQuickTabBarAttached *attached = qobject_cast<QQuickTabBarAttached *>(qmlAttachedPropertiesObject<QQuickTabBar>(item)); + if (attached) + QQuickTabBarAttachedPrivate::get(attached)->update(nullptr, -1); if (isComponentComplete()) polish(); } +QPalette QQuickTabBar::defaultPalette() const +{ + return QQuickControlPrivate::themePalette(QPlatformTheme::TabBarPalette); +} + #if QT_CONFIG(accessibility) QAccessible::Role QQuickTabBar::accessibleRole() const { @@ -397,4 +451,87 @@ QAccessible::Role QQuickTabBar::accessibleRole() const } #endif +/*! + \qmlattachedproperty int QtQuick.Controls::TabBar::index + \since QtQuick.Controls 2.3 (Qt 5.10) + \readonly + + This attached property holds the index of each tab button in the TabBar. + + It is attached to each tab button of the TabBar. +*/ + +/*! + \qmlattachedproperty TabBar QtQuick.Controls::TabBar::tabBar + \since QtQuick.Controls 2.3 (Qt 5.10) + \readonly + + This attached property holds the tab bar that manages this tab button. + + It is attached to each tab button of the TabBar. +*/ + +/*! + \qmlattachedproperty enumeration QtQuick.Controls::TabBar::position + \since QtQuick.Controls 2.3 (Qt 5.10) + \readonly + + This attached property holds the position of the tab bar. + + It is attached to each tab button of the TabBar. + + Possible values: + \value TabBar.Header The tab bar is at the top, as a window or page header. + \value TabBar.Footer The tab bar is at the bottom, as a window or page footer. +*/ + +void QQuickTabBarAttachedPrivate::update(QQuickTabBar *newTabBar, int newIndex) +{ + Q_Q(QQuickTabBarAttached); + const int oldIndex = index; + const QQuickTabBar *oldTabBar = tabBar; + const QQuickTabBar::Position oldPos = q->position(); + + index = newIndex; + tabBar = newTabBar; + + if (oldTabBar != newTabBar) { + if (oldTabBar) + QObject::disconnect(oldTabBar, &QQuickTabBar::positionChanged, q, &QQuickTabBarAttached::positionChanged); + if (newTabBar) + QObject::connect(newTabBar, &QQuickTabBar::positionChanged, q, &QQuickTabBarAttached::positionChanged); + emit q->tabBarChanged(); + } + + if (oldIndex != newIndex) + emit q->indexChanged(); + if (oldPos != q->position()) + emit q->positionChanged(); +} + +QQuickTabBarAttached::QQuickTabBarAttached(QObject *parent) + : QObject(*(new QQuickTabBarAttachedPrivate), parent) +{ +} + +int QQuickTabBarAttached::index() const +{ + Q_D(const QQuickTabBarAttached); + return d->index; +} + +QQuickTabBar *QQuickTabBarAttached::tabBar() const +{ + Q_D(const QQuickTabBarAttached); + return d->tabBar; +} + +QQuickTabBar::Position QQuickTabBarAttached::position() const +{ + Q_D(const QQuickTabBarAttached); + if (!d->tabBar) + return QQuickTabBar::Header; + return d->tabBar->position(); +} + QT_END_NAMESPACE diff --git a/src/quicktemplates2/qquicktabbar_p.h b/src/quicktemplates2/qquicktabbar_p.h index 0ffd53d5..0e4a3c58 100644 --- a/src/quicktemplates2/qquicktabbar_p.h +++ b/src/quicktemplates2/qquicktabbar_p.h @@ -53,6 +53,8 @@ QT_BEGIN_NAMESPACE class QQuickTabBarPrivate; +class QQuickTabBarAttached; +class QQuickTabBarAttachedPrivate; class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickTabBar : public QQuickContainer { @@ -81,6 +83,8 @@ public: void setContentHeight(qreal height); void resetContentHeight(); + static QQuickTabBarAttached *qmlAttachedProperties(QObject *object); + Q_SIGNALS: void positionChanged(); Q_REVISION(2) void contentWidthChanged(); @@ -92,8 +96,11 @@ protected: void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override; bool isContent(QQuickItem *item) const override; void itemAdded(int index, QQuickItem *item) override; + void itemMoved(int index, QQuickItem *item) override; void itemRemoved(int index, QQuickItem *item) override; + QPalette defaultPalette() const override; + #if QT_CONFIG(accessibility) QAccessible::Role accessibleRole() const override; #endif @@ -103,8 +110,33 @@ private: Q_DECLARE_PRIVATE(QQuickTabBar) }; +class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickTabBarAttached : public QObject +{ + Q_OBJECT + Q_PROPERTY(int index READ index NOTIFY indexChanged FINAL) + Q_PROPERTY(QQuickTabBar *tabBar READ tabBar NOTIFY tabBarChanged FINAL) + Q_PROPERTY(QQuickTabBar::Position position READ position NOTIFY positionChanged FINAL) + +public: + explicit QQuickTabBarAttached(QObject *parent = nullptr); + + int index() const; + QQuickTabBar *tabBar() const; + QQuickTabBar::Position position() const; + +Q_SIGNALS: + void indexChanged(); + void tabBarChanged(); + void positionChanged(); + +private: + Q_DISABLE_COPY(QQuickTabBarAttached) + Q_DECLARE_PRIVATE(QQuickTabBarAttached) +}; + QT_END_NAMESPACE QML_DECLARE_TYPE(QQuickTabBar) +QML_DECLARE_TYPEINFO(QQuickTabBar, QML_HAS_ATTACHED_PROPERTIES) #endif // QQUICKTABBAR_P_H diff --git a/src/quicktemplates2/qquicktabbutton.cpp b/src/quicktemplates2/qquicktabbutton.cpp index 9afe5363..617d4aea 100644 --- a/src/quicktemplates2/qquicktabbutton.cpp +++ b/src/quicktemplates2/qquicktabbutton.cpp @@ -75,6 +75,11 @@ QFont QQuickTabButton::defaultFont() const return QQuickControlPrivate::themeFont(QPlatformTheme::TabButtonFont); } +QPalette QQuickTabButton::defaultPalette() const +{ + return QQuickControlPrivate::themePalette(QPlatformTheme::TabBarPalette); +} + #if QT_CONFIG(accessibility) QAccessible::Role QQuickTabButton::accessibleRole() const { diff --git a/src/quicktemplates2/qquicktabbutton_p.h b/src/quicktemplates2/qquicktabbutton_p.h index 49ecee50..9ca9df9f 100644 --- a/src/quicktemplates2/qquicktabbutton_p.h +++ b/src/quicktemplates2/qquicktabbutton_p.h @@ -61,6 +61,7 @@ public: protected: QFont defaultFont() const override; + QPalette defaultPalette() const override; #if QT_CONFIG(accessibility) QAccessible::Role accessibleRole() const override; diff --git a/src/quicktemplates2/qquicktextarea.cpp b/src/quicktemplates2/qquicktextarea.cpp index 4a171603..eec25848 100644 --- a/src/quicktemplates2/qquicktextarea.cpp +++ b/src/quicktemplates2/qquicktextarea.cpp @@ -138,7 +138,6 @@ QQuickTextAreaPrivate::QQuickTextAreaPrivate() #endif background(nullptr), focusReason(Qt::OtherFocusReason), - accessibleAttached(nullptr), flickable(nullptr) { #if QT_CONFIG(accessibility) @@ -189,21 +188,71 @@ void QQuickTextAreaPrivate::resolveFont() inheritFont(QQuickControlPrivate::parentFont(q)); } -void QQuickTextAreaPrivate::inheritFont(const QFont &f) +void QQuickTextAreaPrivate::inheritFont(const QFont &font) { - Q_Q(QQuickTextArea); - QFont parentFont = font.resolve(f); - parentFont.resolve(font.resolve() | f.resolve()); + QFont parentFont = extra.isAllocated() ? extra->requestedFont.resolve(font) : font; + parentFont.resolve(extra.isAllocated() ? extra->requestedFont.resolve() | font.resolve() : font.resolve()); const QFont defaultFont = QQuickControlPrivate::themeFont(QPlatformTheme::EditorFont); const QFont resolvedFont = parentFont.resolve(defaultFont); - const bool changed = resolvedFont != sourceFont; - q->QQuickTextEdit::setFont(resolvedFont); - if (changed) + setFont_helper(resolvedFont); +} + +/*! + \internal + + Assign \a font to this control, and propagate it to all children. +*/ +void QQuickTextAreaPrivate::updateFont(const QFont &font) +{ + Q_Q(QQuickTextArea); + QFont oldFont = sourceFont; + q->QQuickTextEdit::setFont(font); + + QQuickControlPrivate::updateFontRecur(q, font); + + if (oldFont != font) emit q->fontChanged(); } +/*! + \internal + + Determine which palette is implicitly imposed on this control by its ancestors + and QGuiApplication::palette, resolve this against its own palette (attributes from + the implicit palette are copied over). Then propagate this palette to this + control's children. +*/ +void QQuickTextAreaPrivate::resolvePalette() +{ + Q_Q(QQuickTextArea); + inheritPalette(QQuickControlPrivate::parentPalette(q)); +} + +void QQuickTextAreaPrivate::inheritPalette(const QPalette &palette) +{ + QPalette parentPalette = extra.isAllocated() ? extra->requestedPalette.resolve(palette) : palette; + parentPalette.resolve(extra.isAllocated() ? extra->requestedPalette.resolve() | palette.resolve() : palette.resolve()); + + const QPalette defaultPalette = QQuickControlPrivate::themePalette(QPlatformTheme::TextEditPalette); + const QPalette resolvedPalette = parentPalette.resolve(defaultPalette); + + setPalette_helper(resolvedPalette); +} + +void QQuickTextAreaPrivate::updatePalette(const QPalette &palette) +{ + Q_Q(QQuickTextArea); + QPalette oldPalette = resolvedPalette; + resolvedPalette = palette; + + QQuickControlPrivate::updatePaletteRecur(q, palette); + + if (oldPalette != palette) + emit q->paletteChanged(); +} + #if QT_CONFIG(quicktemplates2_hover) void QQuickTextAreaPrivate::updateHoverEnabled(bool enabled, bool xplicit) { @@ -360,7 +409,7 @@ void QQuickTextAreaPrivate::readOnlyChanged(bool isReadOnly) { Q_UNUSED(isReadOnly); #if QT_CONFIG(accessibility) - if (accessibleAttached) + if (QQuickAccessibleAttached *accessibleAttached = QQuickAccessibleAttached::attachedProperties(q_func())) accessibleAttached->set_readOnly(isReadOnly); #endif #if QT_CONFIG(cursor) @@ -371,18 +420,15 @@ void QQuickTextAreaPrivate::readOnlyChanged(bool isReadOnly) #if QT_CONFIG(accessibility) void QQuickTextAreaPrivate::accessibilityActiveChanged(bool active) { - if (accessibleAttached || !active) + if (!active) return; Q_Q(QQuickTextArea); - accessibleAttached = qobject_cast<QQuickAccessibleAttached *>(qmlAttachedPropertiesObject<QQuickAccessibleAttached>(q, true)); - if (accessibleAttached) { - accessibleAttached->setRole(accessibleRole()); - accessibleAttached->set_readOnly(q->isReadOnly()); - accessibleAttached->setDescription(placeholder); - } else { - qWarning() << "QQuickTextArea: " << q << " QQuickAccessibleAttached object creation failed!"; - } + QQuickAccessibleAttached *accessibleAttached = qobject_cast<QQuickAccessibleAttached *>(qmlAttachedPropertiesObject<QQuickAccessibleAttached>(q, true)); + Q_ASSERT(accessibleAttached); + accessibleAttached->setRole(accessibleRole()); + accessibleAttached->set_readOnly(q->isReadOnly()); + accessibleAttached->setDescription(placeholder); } QAccessible::Role QQuickTextAreaPrivate::accessibleRole() const @@ -404,6 +450,9 @@ QQuickTextArea::QQuickTextArea(QQuickItem *parent) #endif QObjectPrivate::connect(this, &QQuickTextEdit::readOnlyChanged, d, &QQuickTextAreaPrivate::readOnlyChanged); + + // ### TODO: ItemEnabledChanged? + connect(this, &QQuickItem::enabledChanged, this, &QQuickTextArea::paletteChanged); } QQuickTextAreaAttached *QQuickTextArea::qmlAttachedProperties(QObject *object) @@ -419,10 +468,10 @@ QFont QQuickTextArea::font() const void QQuickTextArea::setFont(const QFont &font) { Q_D(QQuickTextArea); - if (d->font.resolve() == font.resolve() && d->font == font) + if (d->extra.value().requestedFont.resolve() == font.resolve() && d->extra.value().requestedFont == font) return; - d->font = font; + d->extra.value().requestedFont = font; d->resolveFont(); } @@ -479,8 +528,8 @@ void QQuickTextArea::setPlaceholderText(const QString &text) d->placeholder = text; #if QT_CONFIG(accessibility) - if (d->accessibleAttached) - d->accessibleAttached->setDescription(text); + if (QQuickAccessibleAttached *accessibleAttached = QQuickAccessibleAttached::attachedProperties(this)) + accessibleAttached->setDescription(text); #endif emit placeholderTextChanged(); } @@ -590,11 +639,44 @@ bool QQuickTextArea::contains(const QPointF &point) const return QQuickTextEdit::contains(point); } +/*! + \since QtQuick.Controls 2.3 (Qt 5.10) + \qmlproperty palette QtQuick.Controls::TextArea::palette + + This property holds the palette currently set for the text area. + + \sa Control::palette +*/ +QPalette QQuickTextArea::palette() const +{ + Q_D(const QQuickTextArea); + QPalette palette = d->resolvedPalette; + if (!isEnabled()) + palette.setCurrentColorGroup(QPalette::Disabled); + return palette; +} + +void QQuickTextArea::setPalette(const QPalette &palette) +{ + Q_D(QQuickTextArea); + if (d->extra.value().requestedPalette.resolve() == palette.resolve() && d->extra.value().requestedPalette == palette) + return; + + d->extra.value().requestedPalette = palette; + d->resolvePalette(); +} + +void QQuickTextArea::resetPalette() +{ + setPalette(QPalette()); +} + void QQuickTextArea::classBegin() { Q_D(QQuickTextArea); QQuickTextEdit::classBegin(); d->resolveFont(); + d->resolvePalette(); } void QQuickTextArea::componentComplete() @@ -606,7 +688,7 @@ void QQuickTextArea::componentComplete() setAcceptHoverEvents(QQuickControlPrivate::calcHoverEnabled(d->parentItem)); #endif #if QT_CONFIG(accessibility) - if (!d->accessibleAttached && QAccessible::isActive()) + if (QAccessible::isActive()) d->accessibilityActiveChanged(true); #endif } @@ -617,6 +699,7 @@ void QQuickTextArea::itemChange(QQuickItem::ItemChange change, const QQuickItem: QQuickTextEdit::itemChange(change, value); if (change == ItemParentHasChanged && value.item) { d->resolveFont(); + d->resolvePalette(); #if QT_CONFIG(quicktemplates2_hover) if (!d->explicitHoverEnabled) d->updateHoverEnabled(QQuickControlPrivate::calcHoverEnabled(d->parentItem), false); // explicit=false diff --git a/src/quicktemplates2/qquicktextarea_p.h b/src/quicktemplates2/qquicktextarea_p.h index af7c1d13..6193e3ca 100644 --- a/src/quicktemplates2/qquicktextarea_p.h +++ b/src/quicktemplates2/qquicktextarea_p.h @@ -48,6 +48,7 @@ // We mean it. // +#include <QtGui/qpalette.h> #include <QtQuick/private/qquicktextedit_p.h> #include <QtQuickTemplates2/private/qtquicktemplates2global_p.h> @@ -69,6 +70,7 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickTextArea : public QQuickTextEdit Q_PROPERTY(Qt::FocusReason focusReason READ focusReason WRITE setFocusReason NOTIFY focusReasonChanged FINAL) Q_PROPERTY(bool hovered READ isHovered NOTIFY hoveredChanged FINAL REVISION 1) Q_PROPERTY(bool hoverEnabled READ isHoverEnabled WRITE setHoverEnabled RESET resetHoverEnabled NOTIFY hoverEnabledChanged FINAL REVISION 1) + Q_PROPERTY(QPalette palette READ palette WRITE setPalette RESET resetPalette NOTIFY paletteChanged FINAL REVISION 3) public: explicit QQuickTextArea(QQuickItem *parent = nullptr); @@ -96,6 +98,10 @@ public: bool contains(const QPointF &point) const override; + QPalette palette() const; + void setPalette(const QPalette &palette); + void resetPalette(); + Q_SIGNALS: void fontChanged(); void implicitWidthChanged3(); @@ -108,6 +114,7 @@ Q_SIGNALS: void pressAndHold(QQuickMouseEvent *event); Q_REVISION(1) void pressed(QQuickMouseEvent *event); Q_REVISION(1) void released(QQuickMouseEvent *event); + Q_REVISION(3) void paletteChanged(); protected: void classBegin() override; diff --git a/src/quicktemplates2/qquicktextarea_p_p.h b/src/quicktemplates2/qquicktextarea_p_p.h index ef2c7237..32f53c4f 100644 --- a/src/quicktemplates2/qquicktextarea_p_p.h +++ b/src/quicktemplates2/qquicktextarea_p_p.h @@ -48,11 +48,12 @@ // We mean it. // +#include <QtQml/private/qlazilyallocated_p.h> #include <QtQuick/private/qquicktextedit_p_p.h> #include <QtQuick/private/qquickitemchangelistener_p.h> #include <QtQuickTemplates2/private/qquickpresshandler_p_p.h> -#include "qquicktextarea_p.h" +#include <QtQuickTemplates2/private/qquicktextarea_p.h> #if QT_CONFIG(accessibility) #include <QtGui/qaccessible.h> @@ -61,7 +62,6 @@ QT_BEGIN_NAMESPACE class QQuickFlickable; -class QQuickAccessibleAttached; class QQuickTextAreaPrivate : public QQuickTextEditPrivate, public QQuickItemChangeListener #if QT_CONFIG(accessibility) @@ -80,8 +80,24 @@ public: } void resizeBackground(); + void resolveFont(); - void inheritFont(const QFont &f); + void inheritFont(const QFont &font); + void updateFont(const QFont &font); + inline void setFont_helper(const QFont &font) { + if (sourceFont.resolve() == font.resolve() && sourceFont == font) + return; + updateFont(font); + } + + void resolvePalette(); + void inheritPalette(const QPalette &palette); + void updatePalette(const QPalette &palette); + inline void setPalette_helper(const QPalette &palette) { + if (resolvedPalette.resolve() == palette.resolve() && resolvedPalette == palette) + return; + updatePalette(palette); + } #if QT_CONFIG(quicktemplates2_hover) void updateHoverEnabled(bool h, bool e); @@ -112,12 +128,18 @@ public: bool hovered; bool explicitHoverEnabled; #endif - QFont font; + + struct ExtraData { + QFont requestedFont; + QPalette requestedPalette; + }; + QLazilyAllocated<ExtraData> extra; + + QPalette resolvedPalette; QQuickItem *background; QString placeholder; Qt::FocusReason focusReason; QQuickPressHandler pressHandler; - QQuickAccessibleAttached *accessibleAttached; QQuickFlickable *flickable; }; diff --git a/src/quicktemplates2/qquicktextfield.cpp b/src/quicktemplates2/qquicktextfield.cpp index 96f5cc37..1c350165 100644 --- a/src/quicktemplates2/qquicktextfield.cpp +++ b/src/quicktemplates2/qquicktextfield.cpp @@ -118,8 +118,7 @@ QQuickTextFieldPrivate::QQuickTextFieldPrivate() explicitHoverEnabled(false), #endif background(nullptr), - focusReason(Qt::OtherFocusReason), - accessibleAttached(nullptr) + focusReason(Qt::OtherFocusReason) { #if QT_CONFIG(accessibility) QAccessible::installActivationObserver(this); @@ -163,21 +162,71 @@ void QQuickTextFieldPrivate::resolveFont() inheritFont(QQuickControlPrivate::parentFont(q)); } -void QQuickTextFieldPrivate::inheritFont(const QFont &f) +void QQuickTextFieldPrivate::inheritFont(const QFont &font) { - Q_Q(QQuickTextField); - QFont parentFont = font.resolve(f); - parentFont.resolve(font.resolve() | f.resolve()); + QFont parentFont = extra.isAllocated() ? extra->requestedFont.resolve(font) : font; + parentFont.resolve(extra.isAllocated() ? extra->requestedFont.resolve() | font.resolve() : font.resolve()); const QFont defaultFont = QQuickControlPrivate::themeFont(QPlatformTheme::EditorFont); const QFont resolvedFont = parentFont.resolve(defaultFont); - const bool changed = resolvedFont != sourceFont; - q->QQuickTextInput::setFont(resolvedFont); - if (changed) + setFont_helper(resolvedFont); +} + +/*! + \internal + + Assign \a font to this control, and propagate it to all children. +*/ +void QQuickTextFieldPrivate::updateFont(const QFont &font) +{ + Q_Q(QQuickTextField); + QFont oldFont = sourceFont; + q->QQuickTextInput::setFont(font); + + QQuickControlPrivate::updateFontRecur(q, font); + + if (oldFont != font) emit q->fontChanged(); } +/*! + \internal + + Determine which palette is implicitly imposed on this control by its ancestors + and QGuiApplication::palette, resolve this against its own palette (attributes from + the implicit palette are copied over). Then propagate this palette to this + control's children. +*/ +void QQuickTextFieldPrivate::resolvePalette() +{ + Q_Q(QQuickTextField); + inheritPalette(QQuickControlPrivate::parentPalette(q)); +} + +void QQuickTextFieldPrivate::inheritPalette(const QPalette &palette) +{ + QPalette parentPalette = extra.isAllocated() ? extra->requestedPalette.resolve(palette) : palette; + parentPalette.resolve(extra.isAllocated() ? extra->requestedPalette.resolve() | palette.resolve() : palette.resolve()); + + const QPalette defaultPalette = QQuickControlPrivate::themePalette(QPlatformTheme::TextLineEditPalette); + const QPalette resolvedPalette = parentPalette.resolve(defaultPalette); + + setPalette_helper(resolvedPalette); +} + +void QQuickTextFieldPrivate::updatePalette(const QPalette &palette) +{ + Q_Q(QQuickTextField); + QPalette oldPalette = resolvedPalette; + resolvedPalette = palette; + + QQuickControlPrivate::updatePaletteRecur(q, palette); + + if (oldPalette != palette) + emit q->paletteChanged(); +} + #if QT_CONFIG(quicktemplates2_hover) void QQuickTextFieldPrivate::updateHoverEnabled(bool enabled, bool xplicit) { @@ -223,7 +272,7 @@ void QQuickTextFieldPrivate::readOnlyChanged(bool isReadOnly) { Q_UNUSED(isReadOnly); #if QT_CONFIG(accessibility) - if (accessibleAttached) + if (QQuickAccessibleAttached *accessibleAttached = QQuickAccessibleAttached::attachedProperties(q_func())) accessibleAttached->set_readOnly(isReadOnly); #endif #if QT_CONFIG(cursor) @@ -234,7 +283,7 @@ void QQuickTextFieldPrivate::readOnlyChanged(bool isReadOnly) void QQuickTextFieldPrivate::echoModeChanged(QQuickTextField::EchoMode echoMode) { #if QT_CONFIG(accessibility) - if (accessibleAttached) + if (QQuickAccessibleAttached *accessibleAttached = QQuickAccessibleAttached::attachedProperties(q_func())) accessibleAttached->set_passwordEdit((echoMode == QQuickTextField::Password || echoMode == QQuickTextField::PasswordEchoOnEdit) ? true : false); #else Q_UNUSED(echoMode) @@ -244,19 +293,16 @@ void QQuickTextFieldPrivate::echoModeChanged(QQuickTextField::EchoMode echoMode) #if QT_CONFIG(accessibility) void QQuickTextFieldPrivate::accessibilityActiveChanged(bool active) { - if (accessibleAttached || !active) + if (!active) return; Q_Q(QQuickTextField); - accessibleAttached = qobject_cast<QQuickAccessibleAttached *>(qmlAttachedPropertiesObject<QQuickAccessibleAttached>(q, true)); - if (accessibleAttached) { - accessibleAttached->setRole(accessibleRole()); - accessibleAttached->set_readOnly(m_readOnly); - accessibleAttached->set_passwordEdit((m_echoMode == QQuickTextField::Password || m_echoMode == QQuickTextField::PasswordEchoOnEdit) ? true : false); - accessibleAttached->setDescription(placeholder); - } else { - qWarning() << "QQuickTextField: " << q << " QQuickAccessibleAttached object creation failed!"; - } + QQuickAccessibleAttached *accessibleAttached = qobject_cast<QQuickAccessibleAttached *>(qmlAttachedPropertiesObject<QQuickAccessibleAttached>(q, true)); + Q_ASSERT(accessibleAttached); + accessibleAttached->setRole(accessibleRole()); + accessibleAttached->set_readOnly(m_readOnly); + accessibleAttached->set_passwordEdit((m_echoMode == QQuickTextField::Password || m_echoMode == QQuickTextField::PasswordEchoOnEdit) ? true : false); + accessibleAttached->setDescription(placeholder); } QAccessible::Role QQuickTextFieldPrivate::accessibleRole() const @@ -278,6 +324,9 @@ QQuickTextField::QQuickTextField(QQuickItem *parent) #endif QObjectPrivate::connect(this, &QQuickTextInput::readOnlyChanged, d, &QQuickTextFieldPrivate::readOnlyChanged); QObjectPrivate::connect(this, &QQuickTextInput::echoModeChanged, d, &QQuickTextFieldPrivate::echoModeChanged); + + // ### TODO: ItemEnabledChanged? + connect(this, &QQuickItem::enabledChanged, this, &QQuickTextField::paletteChanged); } QFont QQuickTextField::font() const @@ -288,10 +337,10 @@ QFont QQuickTextField::font() const void QQuickTextField::setFont(const QFont &font) { Q_D(QQuickTextField); - if (d->font.resolve() == font.resolve() && d->font == font) + if (d->extra.value().requestedFont.resolve() == font.resolve() && d->extra.value().requestedFont == font) return; - d->font = font; + d->extra.value().requestedFont = font; d->resolveFont(); } @@ -348,8 +397,8 @@ void QQuickTextField::setPlaceholderText(const QString &text) d->placeholder = text; #if QT_CONFIG(accessibility) - if (d->accessibleAttached) - d->accessibleAttached->setDescription(text); + if (QQuickAccessibleAttached *accessibleAttached = QQuickAccessibleAttached::attachedProperties(this)) + accessibleAttached->setDescription(text); #endif emit placeholderTextChanged(); } @@ -451,11 +500,44 @@ void QQuickTextField::resetHoverEnabled() #endif } +/*! + \since QtQuick.Controls 2.3 (Qt 5.10) + \qmlproperty palette QtQuick.Controls::TextField::palette + + This property holds the palette currently set for the text field. + + \sa Control::palette +*/ +QPalette QQuickTextField::palette() const +{ + Q_D(const QQuickTextField); + QPalette palette = d->resolvedPalette; + if (!isEnabled()) + palette.setCurrentColorGroup(QPalette::Disabled); + return palette; +} + +void QQuickTextField::setPalette(const QPalette &palette) +{ + Q_D(QQuickTextField); + if (d->extra.value().requestedPalette.resolve() == palette.resolve() && d->extra.value().requestedPalette == palette) + return; + + d->extra.value().requestedPalette = palette; + d->resolvePalette(); +} + +void QQuickTextField::resetPalette() +{ + setPalette(QPalette()); +} + void QQuickTextField::classBegin() { Q_D(QQuickTextField); QQuickTextInput::classBegin(); d->resolveFont(); + d->resolvePalette(); } void QQuickTextField::componentComplete() @@ -467,7 +549,7 @@ void QQuickTextField::componentComplete() setAcceptHoverEvents(QQuickControlPrivate::calcHoverEnabled(d->parentItem)); #endif #if QT_CONFIG(accessibility) - if (!d->accessibleAttached && QAccessible::isActive()) + if (QAccessible::isActive()) d->accessibilityActiveChanged(true); #endif } @@ -478,6 +560,7 @@ void QQuickTextField::itemChange(QQuickItem::ItemChange change, const QQuickItem QQuickTextInput::itemChange(change, value); if (change == ItemParentHasChanged && value.item) { d->resolveFont(); + d->resolvePalette(); #if QT_CONFIG(quicktemplates2_hover) if (!d->explicitHoverEnabled) d->updateHoverEnabled(QQuickControlPrivate::calcHoverEnabled(d->parentItem), false); // explicit=false diff --git a/src/quicktemplates2/qquicktextfield_p.h b/src/quicktemplates2/qquicktextfield_p.h index 24e6ce53..0629a158 100644 --- a/src/quicktemplates2/qquicktextfield_p.h +++ b/src/quicktemplates2/qquicktextfield_p.h @@ -48,6 +48,7 @@ // We mean it. // +#include <QtGui/qpalette.h> #include <QtQuick/private/qquicktextinput_p.h> #include <QtQuickTemplates2/private/qtquicktemplates2global_p.h> @@ -68,6 +69,7 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickTextField : public QQuickTextInput Q_PROPERTY(Qt::FocusReason focusReason READ focusReason WRITE setFocusReason NOTIFY focusReasonChanged FINAL) Q_PROPERTY(bool hovered READ isHovered NOTIFY hoveredChanged FINAL REVISION 1) Q_PROPERTY(bool hoverEnabled READ isHoverEnabled WRITE setHoverEnabled RESET resetHoverEnabled NOTIFY hoverEnabledChanged FINAL REVISION 1) + Q_PROPERTY(QPalette palette READ palette WRITE setPalette RESET resetPalette NOTIFY paletteChanged FINAL REVISION 3) public: explicit QQuickTextField(QQuickItem *parent = nullptr); @@ -91,6 +93,10 @@ public: void setHoverEnabled(bool enabled); void resetHoverEnabled(); + QPalette palette() const; + void setPalette(const QPalette &palette); + void resetPalette(); + Q_SIGNALS: void fontChanged(); void implicitWidthChanged3(); @@ -103,6 +109,7 @@ Q_SIGNALS: void pressAndHold(QQuickMouseEvent *event); Q_REVISION(1) void pressed(QQuickMouseEvent *event); Q_REVISION(1) void released(QQuickMouseEvent *event); + Q_REVISION(3) void paletteChanged(); protected: void classBegin() override; diff --git a/src/quicktemplates2/qquicktextfield_p_p.h b/src/quicktemplates2/qquicktextfield_p_p.h index 31ccb361..65767452 100644 --- a/src/quicktemplates2/qquicktextfield_p_p.h +++ b/src/quicktemplates2/qquicktextfield_p_p.h @@ -48,10 +48,11 @@ // We mean it. // +#include <QtQml/private/qlazilyallocated_p.h> #include <QtQuick/private/qquicktextinput_p_p.h> #include <QtQuickTemplates2/private/qquickpresshandler_p_p.h> -#include "qquicktextfield_p.h" +#include <QtQuickTemplates2/private/qquicktextfield_p.h> #if QT_CONFIG(accessibility) #include <QtGui/qaccessible.h> @@ -59,8 +60,6 @@ QT_BEGIN_NAMESPACE -class QQuickAccessibleAttached; - class QQuickTextFieldPrivate : public QQuickTextInputPrivate #if QT_CONFIG(accessibility) , public QAccessible::ActivationObserver @@ -76,8 +75,24 @@ public: return static_cast<QQuickTextFieldPrivate *>(QObjectPrivate::get(item)); } void resizeBackground(); + void resolveFont(); - void inheritFont(const QFont &f); + void inheritFont(const QFont &font); + void updateFont(const QFont &font); + inline void setFont_helper(const QFont &font) { + if (sourceFont.resolve() == font.resolve() && sourceFont == font) + return; + updateFont(font); + } + + void resolvePalette(); + void inheritPalette(const QPalette &palette); + void updatePalette(const QPalette &palette); + inline void setPalette_helper(const QPalette &palette) { + if (resolvedPalette.resolve() == palette.resolve() && resolvedPalette == palette) + return; + updatePalette(palette); + } #if QT_CONFIG(quicktemplates2_hover) void updateHoverEnabled(bool h, bool e); @@ -101,12 +116,18 @@ public: bool hovered; bool explicitHoverEnabled; #endif - QFont font; + + struct ExtraData { + QFont requestedFont; + QPalette requestedPalette; + }; + QLazilyAllocated<ExtraData> extra; + + QPalette resolvedPalette; QQuickItem *background; QString placeholder; Qt::FocusReason focusReason; QQuickPressHandler pressHandler; - QQuickAccessibleAttached *accessibleAttached; }; QT_END_NAMESPACE diff --git a/src/quicktemplates2/qquicktoolbar.cpp b/src/quicktemplates2/qquicktoolbar.cpp index 9f5f210e..99775c6a 100644 --- a/src/quicktemplates2/qquicktoolbar.cpp +++ b/src/quicktemplates2/qquicktoolbar.cpp @@ -141,6 +141,11 @@ void QQuickToolBar::setPosition(Position position) emit positionChanged(); } +QPalette QQuickToolBar::defaultPalette() const +{ + return QQuickControlPrivate::themePalette(QPlatformTheme::ToolButtonPalette); +} + #if QT_CONFIG(accessibility) QAccessible::Role QQuickToolBar::accessibleRole() const { diff --git a/src/quicktemplates2/qquicktoolbar_p.h b/src/quicktemplates2/qquicktoolbar_p.h index 58192ff9..b919c615 100644 --- a/src/quicktemplates2/qquicktoolbar_p.h +++ b/src/quicktemplates2/qquicktoolbar_p.h @@ -75,6 +75,8 @@ Q_SIGNALS: void positionChanged(); protected: + QPalette defaultPalette() const override; + #if QT_CONFIG(accessibility) QAccessible::Role accessibleRole() const override; #endif diff --git a/src/quicktemplates2/qquicktoolbutton.cpp b/src/quicktemplates2/qquicktoolbutton.cpp index 5ef25e3e..8c9e9bca 100644 --- a/src/quicktemplates2/qquicktoolbutton.cpp +++ b/src/quicktemplates2/qquicktoolbutton.cpp @@ -59,7 +59,8 @@ QT_BEGIN_NAMESPACE ToolButton inherits its API from AbstractButton. For instance, you can set \l {AbstractButton::text}{text}, and react to \l {AbstractButton::clicked}{clicks} - using the AbstractButton API. + using the AbstractButton API. In addition to displaying text, tool buttons + can also display an \l [QML]{Button Icons}{icon}. \sa ToolBar, {Customizing ToolButton}, {Button Controls} */ @@ -74,4 +75,9 @@ QFont QQuickToolButton::defaultFont() const return QQuickControlPrivate::themeFont(QPlatformTheme::ToolButtonFont); } +QPalette QQuickToolButton::defaultPalette() const +{ + return QQuickControlPrivate::themePalette(QPlatformTheme::ToolButtonPalette); +} + QT_END_NAMESPACE diff --git a/src/quicktemplates2/qquicktoolbutton_p.h b/src/quicktemplates2/qquicktoolbutton_p.h index 06745cd9..0e376f7b 100644 --- a/src/quicktemplates2/qquicktoolbutton_p.h +++ b/src/quicktemplates2/qquicktoolbutton_p.h @@ -61,6 +61,7 @@ public: protected: QFont defaultFont() const override; + QPalette defaultPalette() const override; }; QT_END_NAMESPACE diff --git a/src/quicktemplates2/qquicktoolseparator.cpp b/src/quicktemplates2/qquicktoolseparator.cpp index 4da63907..2ec7799f 100644 --- a/src/quicktemplates2/qquicktoolseparator.cpp +++ b/src/quicktemplates2/qquicktoolseparator.cpp @@ -133,6 +133,11 @@ bool QQuickToolSeparator::isVertical() const return d->orientation == Qt::Vertical; } +QPalette QQuickToolSeparator::defaultPalette() const +{ + return QQuickControlPrivate::themePalette(QPlatformTheme::ToolButtonPalette); +} + #if QT_CONFIG(accessibility) QAccessible::Role QQuickToolSeparator::accessibleRole() const { diff --git a/src/quicktemplates2/qquicktoolseparator_p.h b/src/quicktemplates2/qquicktoolseparator_p.h index 055f475c..2108cc5b 100644 --- a/src/quicktemplates2/qquicktoolseparator_p.h +++ b/src/quicktemplates2/qquicktoolseparator_p.h @@ -74,6 +74,8 @@ Q_SIGNALS: void orientationChanged(); protected: + QPalette defaultPalette() const override; + #if QT_CONFIG(accessibility) QAccessible::Role accessibleRole() const override; #endif diff --git a/src/quicktemplates2/qquicktooltip.cpp b/src/quicktemplates2/qquicktooltip.cpp index bf83a725..1aeb9914 100644 --- a/src/quicktemplates2/qquicktooltip.cpp +++ b/src/quicktemplates2/qquicktooltip.cpp @@ -279,6 +279,11 @@ QFont QQuickToolTip::defaultFont() const return QQuickControlPrivate::themeFont(QPlatformTheme::TipLabelFont); } +QPalette QQuickToolTip::defaultPalette() const +{ + return QQuickControlPrivate::themePalette(QPlatformTheme::ToolTipPalette); +} + void QQuickToolTip::itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &data) { Q_D(QQuickToolTip); @@ -353,7 +358,7 @@ QQuickToolTip *QQuickToolTipAttachedPrivate::instance(bool create) const if (!tip && create) { // TODO: a cleaner way to create the instance? QQml(Meta)Type? QQmlComponent component(engine); - component.setData("import QtQuick.Controls 2.2; ToolTip { }", QUrl()); + component.setData("import QtQuick.Controls 2.3; ToolTip { }", QUrl()); QObject *object = component.create(); if (object) diff --git a/src/quicktemplates2/qquicktooltip_p.h b/src/quicktemplates2/qquicktooltip_p.h index bdfbe362..60b02502 100644 --- a/src/quicktemplates2/qquicktooltip_p.h +++ b/src/quicktemplates2/qquicktooltip_p.h @@ -86,6 +86,7 @@ Q_SIGNALS: protected: QFont defaultFont() const override; + QPalette defaultPalette() const override; void itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &data) override; void timerEvent(QTimerEvent *event) override; diff --git a/src/quicktemplates2/qquicktumbler_p.h b/src/quicktemplates2/qquicktumbler_p.h index b71a7636..f536f58c 100644 --- a/src/quicktemplates2/qquicktumbler_p.h +++ b/src/quicktemplates2/qquicktumbler_p.h @@ -128,7 +128,7 @@ class QQuickTumblerAttachedPrivate; class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickTumblerAttached : public QObject { Q_OBJECT - Q_PROPERTY(QQuickTumbler *tumbler READ tumbler CONSTANT) + Q_PROPERTY(QQuickTumbler *tumbler READ tumbler CONSTANT FINAL) Q_PROPERTY(qreal displacement READ displacement NOTIFY displacementChanged FINAL) public: diff --git a/src/quicktemplates2/qtquicktemplates2global_p.h b/src/quicktemplates2/qtquicktemplates2global_p.h index b7f54bb6..e5ee3f2e 100644 --- a/src/quicktemplates2/qtquicktemplates2global_p.h +++ b/src/quicktemplates2/qtquicktemplates2global_p.h @@ -49,6 +49,7 @@ // #include <QtCore/qglobal.h> +#include <QtQml/private/qqmlglobal_p.h> #include <QtQuickTemplates2/private/qtquicktemplates2-config_p.h> QT_BEGIN_NAMESPACE diff --git a/src/quicktemplates2/quicktemplates2.pri b/src/quicktemplates2/quicktemplates2.pri index a7570ec5..47d8589d 100644 --- a/src/quicktemplates2/quicktemplates2.pri +++ b/src/quicktemplates2/quicktemplates2.pri @@ -3,6 +3,8 @@ INCLUDEPATH += $$PWD HEADERS += \ $$PWD/qquickabstractbutton_p.h \ $$PWD/qquickabstractbutton_p_p.h \ + $$PWD/qquickaction_p.h \ + $$PWD/qquickactiongroup_p.h \ $$PWD/qquickapplicationwindow_p.h \ $$PWD/qquickbusyindicator_p.h \ $$PWD/qquickbutton_p.h \ @@ -26,6 +28,7 @@ HEADERS += \ $$PWD/qquickframe_p.h \ $$PWD/qquickframe_p_p.h \ $$PWD/qquickgroupbox_p.h \ + $$PWD/qquickicon_p.h \ $$PWD/qquickitemdelegate_p.h \ $$PWD/qquickitemdelegate_p_p.h \ $$PWD/qquicklabel_p.h \ @@ -33,12 +36,14 @@ HEADERS += \ $$PWD/qquickmenu_p.h \ $$PWD/qquickmenu_p_p.h \ $$PWD/qquickmenuitem_p.h \ + $$PWD/qquickmenuitem_p_p.h \ $$PWD/qquickmenuseparator_p.h \ $$PWD/qquickoverlay_p.h \ $$PWD/qquickoverlay_p_p.h \ $$PWD/qquickpage_p.h \ $$PWD/qquickpageindicator_p.h \ $$PWD/qquickpagelayout_p_p.h \ + $$PWD/qquickpalette_p.h \ $$PWD/qquickpane_p.h \ $$PWD/qquickpane_p_p.h \ $$PWD/qquickpopup_p.h \ @@ -82,6 +87,8 @@ HEADERS += \ SOURCES += \ $$PWD/qquickabstractbutton.cpp \ + $$PWD/qquickaction.cpp \ + $$PWD/qquickactiongroup.cpp \ $$PWD/qquickapplicationwindow.cpp \ $$PWD/qquickbusyindicator.cpp \ $$PWD/qquickbutton.cpp \ @@ -98,6 +105,7 @@ SOURCES += \ $$PWD/qquickdrawer.cpp \ $$PWD/qquickframe.cpp \ $$PWD/qquickgroupbox.cpp \ + $$PWD/qquickicon.cpp \ $$PWD/qquickitemdelegate.cpp \ $$PWD/qquicklabel.cpp \ $$PWD/qquickmenu.cpp \ @@ -107,6 +115,7 @@ SOURCES += \ $$PWD/qquickpage.cpp \ $$PWD/qquickpageindicator.cpp \ $$PWD/qquickpagelayout.cpp \ + $$PWD/qquickpalette.cpp \ $$PWD/qquickpane.cpp \ $$PWD/qquickpopup.cpp \ $$PWD/qquickpopupitem.cpp \ diff --git a/tests/auto/accessibility/tst_accessibility.cpp b/tests/auto/accessibility/tst_accessibility.cpp index 4208a366..614566e6 100644 --- a/tests/auto/accessibility/tst_accessibility.cpp +++ b/tests/auto/accessibility/tst_accessibility.cpp @@ -113,16 +113,6 @@ void tst_accessibility::a11y_data() QTest::newRow("WeekNumberColumn") << "weeknumbercolumn" << 0x0 << "WeekNumberColumn"; //QAccessible::NoRole } -#if QT_CONFIG(accessibility) -static QQuickAccessibleAttached *accessibleAttached(QQuickItem *item) -{ - QQuickAccessibleAttached *acc = qobject_cast<QQuickAccessibleAttached *>(qmlAttachedPropertiesObject<QQuickAccessibleAttached>(item, false)); - if (!acc) - acc = item->findChild<QQuickAccessibleAttached *>(); - return acc; -} -#endif - void tst_accessibility::a11y() { QFETCH(QString, name); @@ -152,7 +142,7 @@ void tst_accessibility::a11y() QVERIFY(item); #if QT_CONFIG(accessibility) - QQuickAccessibleAttached *acc = accessibleAttached(item); + QQuickAccessibleAttached *acc = QQuickAccessibleAttached::attachedProperties(item); if (name != QLatin1Literal("dayofweekrow") && name != QLatin1Literal("monthgrid") && name != QLatin1Literal("weeknumbercolumn")) { @@ -161,7 +151,7 @@ void tst_accessibility::a11y() } else { QVERIFY(!acc); QAccessible::setActive(true); - acc = accessibleAttached(item); + acc = QQuickAccessibleAttached::attachedProperties(item); } } QVERIFY(acc); @@ -170,8 +160,6 @@ void tst_accessibility::a11y() #else Q_UNUSED(role) Q_UNUSED(text) - QObject *acc = qmlAttachedPropertiesObject<QObject>(item, false); - QVERIFY(!acc); #endif } diff --git a/tests/auto/applicationwindow/tst_applicationwindow.cpp b/tests/auto/applicationwindow/tst_applicationwindow.cpp index 61f84673..60160afe 100644 --- a/tests/auto/applicationwindow/tst_applicationwindow.cpp +++ b/tests/auto/applicationwindow/tst_applicationwindow.cpp @@ -504,7 +504,7 @@ void tst_applicationwindow::font() QCOMPARE(item6->font(), font); } -class TestTheme : public QQuickProxyTheme +class TestTheme : public QQuickProxyTheme { public: TestTheme(QPlatformTheme *theme) : QQuickProxyTheme(theme), m_font("Courier") diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro index ebc0b337..6de92b4f 100644 --- a/tests/auto/auto.pro +++ b/tests/auto/auto.pro @@ -8,9 +8,13 @@ SUBDIRS += \ drawer \ focus \ menu \ + palette \ platform \ popup \ pressandhold \ + qquickcolor \ + qquickiconimage \ + qquickiconlabel \ qquickmaterialstyle \ qquickmaterialstyleconf \ qquickstyle \ @@ -23,6 +27,7 @@ SUBDIRS += \ # QTBUG-60268 boot2qt: SUBDIRS -= applicationwindow calendar controls cursor \ - drawer focus menu platform popup qquickmaterialstyle \ - qquickmaterialstyleconf qquickuniversalstyle \ - qquickuniversalstyleconf snippets + drawer focus menu platform palette popup \ + qquickmaterialstyle qquickmaterialstyleconf \ + qquickuniversalstyle qquickuniversalstyleconf \ + snippets diff --git a/tests/auto/controls/controls.pro b/tests/auto/controls/controls.pro index 8f2f8e69..c61dff0e 100644 --- a/tests/auto/controls/controls.pro +++ b/tests/auto/controls/controls.pro @@ -1,5 +1,6 @@ TEMPLATE = subdirs SUBDIRS += \ default \ + fusion \ material \ universal diff --git a/tests/auto/controls/data/tst_abstractbutton.qml b/tests/auto/controls/data/tst_abstractbutton.qml index bddb952f..a7f4ab8a 100644 --- a/tests/auto/controls/data/tst_abstractbutton.qml +++ b/tests/auto/controls/data/tst_abstractbutton.qml @@ -50,7 +50,7 @@ import QtQuick 2.2 import QtTest 1.0 -import QtQuick.Controls 2.2 +import QtQuick.Controls 2.3 TestCase { id: testCase @@ -162,4 +162,131 @@ TestCase { keyRelease(data.key) compare(container.lastKeyRelease, data.result) } + + function test_icon() { + var control = createTemporaryObject(button, testCase) + verify(control) + compare(control.icon.name, "") + compare(control.icon.source, "") + compare(control.icon.width, 0) + compare(control.icon.height, 0) + compare(control.icon.color, "#00000000") + + var iconSpy = signalSpy.createObject(control, { target: control, signalName: "iconChanged"} ) + verify(iconSpy.valid) + + control.icon.name = "test-name" + compare(control.icon.name, "test-name") + compare(iconSpy.count, 1) + + control.icon.source = "qrc:/test-source" + compare(control.icon.source, "qrc:/test-source") + compare(iconSpy.count, 2) + + control.icon.width = 32 + compare(control.icon.width, 32) + compare(iconSpy.count, 3) + + control.icon.height = 32 + compare(control.icon.height, 32) + compare(iconSpy.count, 4) + + control.icon.color = "#ff0000" + compare(control.icon.color, "#ff0000") + compare(iconSpy.count, 5) + } + + Component { + id: actionButton + AbstractButton { + action: Action { + text: "Default" + icon.name: "default" + icon.source: "qrc:/icons/default.png" + checkable: true + checked: true + enabled: false + } + } + } + + function test_action() { + var control = createTemporaryObject(actionButton, testCase) + verify(control) + + // initial values + compare(control.text, "Default") + compare(control.icon.name, "default") + compare(control.icon.source, "qrc:/icons/default.png") + compare(control.checkable, true) + compare(control.checked, true) + compare(control.enabled, false) + + // changes via action + control.action.text = "Action" + control.action.icon.name = "action" + control.action.icon.source = "qrc:/icons/action.png" + control.action.checkable = false + control.action.checked = false + control.action.enabled = true + compare(control.text, "Action") // propagates + compare(control.icon.name, "action") // propagates + compare(control.icon.source, "qrc:/icons/action.png") // propagates + compare(control.checkable, false) // propagates + compare(control.checked, false) // propagates + compare(control.enabled, true) // propagates + + // changes via button + control.text = "Button" + control.icon.name = "button" + control.icon.source = "qrc:/icons/button.png" + control.checkable = true + control.checked = true + control.enabled = false + compare(control.text, "Button") + compare(control.icon.name, "button") + compare(control.icon.source, "qrc:/icons/button.png") + compare(control.checkable, true) + compare(control.checked, true) + compare(control.enabled, false) + compare(control.action.text, "Action") // does NOT propagate + compare(control.action.icon.name, "action") // does NOT propagate + compare(control.action.icon.source, "qrc:/icons/action.png") // does NOT propagate + compare(control.action.checkable, true) // propagates + compare(control.action.checked, true) // propagates + compare(control.action.enabled, true) // does NOT propagate + } + + function test_trigger_data() { + return [ + {tag: "click", click: true, button: true, action: true, clicked: true, triggered: true}, + {tag: "click disabled button", click: true, button: false, action: true, clicked: false, triggered: false}, + {tag: "click disabled action", click: true, button: true, action: false, clicked: true, triggered: false}, + {tag: "trigger", trigger: true, button: true, action: true, clicked: true, triggered: true}, + {tag: "trigger disabled button", trigger: true, button: false, action: true, clicked: false, triggered: true}, + {tag: "trigger disabled action", trigger: true, button: true, action: false, clicked: false, triggered: false} + ] + } + + function test_trigger(data) { + var control = createTemporaryObject(actionButton, testCase, {"enabled": data.button, "action.enabled": data.action}) + verify(control) + + compare(control.enabled, data.button) + compare(control.action.enabled, data.action) + + var buttonSpy = signalSpy.createObject(control, {target: control, signalName: "clicked"}) + verify(buttonSpy.valid) + + var actionSpy = signalSpy.createObject(control, {target: control.action, signalName: "triggered"}) + verify(actionSpy.valid) + + if (data.click) + mouseClick(control) + else if (data.trigger) + control.action.trigger() + + compare(buttonSpy.count, data.clicked ? 1 : 0) + compare(actionSpy.count, data.triggered ? 1 : 0) + } } diff --git a/tests/auto/controls/data/tst_action.qml b/tests/auto/controls/data/tst_action.qml new file mode 100644 index 00000000..7d057c26 --- /dev/null +++ b/tests/auto/controls/data/tst_action.qml @@ -0,0 +1,140 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.2 +import QtTest 1.0 +import QtQuick.Controls 2.3 +import QtQuick.Templates 2.3 as T + +TestCase { + id: testCase + width: 400 + height: 400 + visible: true + when: windowShown + name: "Action" + + Component { + id: component + Action { } + } + + Component { + id: signalSpy + SignalSpy { } + } + + function test_enabled() { + var action = createTemporaryObject(component, testCase) + verify(action) + + var spy = createTemporaryObject(signalSpy, testCase, {target: action, signalName: "triggered"}) + verify(spy.valid) + + action.trigger() + compare(spy.count, 1) + + action.enabled = false + action.trigger() + compare(spy.count, 1) + + action.enabled = undefined // reset + action.trigger() + compare(spy.count, 2) + } + + Component { + id: buttonAndMenu + Item { + property alias button: button + property alias menu: menu + property alias menuItem: menuItem + property alias action: sharedAction + property var lastSource + Action { + id: sharedAction + text: "Shared" + shortcut: "Ctrl+B" + onTriggered: lastSource = source + } + Button { + id: button + action: sharedAction + Menu { + id: menu + MenuItem { + id: menuItem + action: sharedAction + } + } + } + } + } + + function test_shared() { + var container = createTemporaryObject(buttonAndMenu, testCase) + verify(container) + + keyClick(Qt.Key_B, Qt.ControlModifier) + compare(container.lastSource, container.button) + + container.menu.open() + keyClick(Qt.Key_B, Qt.ControlModifier) + compare(container.lastSource, container.menuItem) + + tryVerify(function() { return !container.menu.visible }) + keyClick(Qt.Key_B, Qt.ControlModifier) + compare(container.lastSource, container.button) + + container.button.visible = false + keyClick(Qt.Key_B, Qt.ControlModifier) + compare(container.lastSource, container.action) + } +} diff --git a/tests/auto/controls/data/tst_actiongroup.qml b/tests/auto/controls/data/tst_actiongroup.qml new file mode 100644 index 00000000..6b31336d --- /dev/null +++ b/tests/auto/controls/data/tst_actiongroup.qml @@ -0,0 +1,381 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.2 +import QtTest 1.0 +import QtQuick.Controls 2.3 + +TestCase { + id: testCase + width: 200 + height: 200 + visible: true + when: windowShown + name: "ActionGroup" + + Component { + id: actionGroup + ActionGroup { } + } + + Component { + id: nonExclusiveGroup + ActionGroup { exclusive: false } + } + + Component { + id: signalSpy + SignalSpy { } + } + + function test_null() { + var group = createTemporaryObject(actionGroup, testCase) + verify(group) + + group.addAction(null) + group.removeAction(null) + } + + Component { + id: action + Action { } + } + + function test_defaults() { + var group = createTemporaryObject(actionGroup, testCase) + verify(group) + compare(group.actions.length, 0) + compare(group.checkedAction, null) + compare(group.exclusive, true) + } + + function test_current() { + var group = createTemporaryObject(actionGroup, testCase) + verify(group) + + var checkedActionSpy = createTemporaryObject(signalSpy, testCase, {target: group, signalName: "checkedActionChanged"}) + verify(checkedActionSpy.valid) + verify(!group.checkedAction) + + var action1 = createTemporaryObject(action, testCase, {checked: true}) + var action2 = createTemporaryObject(action, testCase, {checked: false}) + var action3 = createTemporaryObject(action, testCase, {checked: true, objectName: "3"}) + + // add checked + group.addAction(action1) + compare(group.checkedAction, action1) + compare(action1.checked, true) + compare(action2.checked, false) + compare(action3.checked, true) + compare(checkedActionSpy.count, 1) + + // add non-checked + group.addAction(action2) + compare(group.checkedAction, action1) + compare(action1.checked, true) + compare(action2.checked, false) + compare(action3.checked, true) + compare(checkedActionSpy.count, 1) + + // add checked + group.addAction(action3) + compare(group.checkedAction, action3) + compare(action1.checked, false) + compare(action2.checked, false) + compare(action3.checked, true) + compare(checkedActionSpy.count, 2) + + // change current + group.checkedAction = action2 + compare(group.checkedAction, action2) + compare(action1.checked, false) + compare(action2.checked, true) + compare(action3.checked, false) + compare(checkedActionSpy.count, 3) + + // check + action1.checked = true + compare(group.checkedAction, action1) + compare(action1.checked, true) + compare(action2.checked, false) + compare(action3.checked, false) + compare(checkedActionSpy.count, 4) + + // remove non-checked + group.removeAction(action2) + compare(group.checkedAction, action1) + compare(action1.checked, true) + compare(action2.checked, false) + compare(action3.checked, false) + compare(checkedActionSpy.count, 4) + + // remove checked + group.removeAction(action1) + verify(!group.checkedAction) + compare(action1.checked, false) + compare(action2.checked, false) + compare(action3.checked, false) + compare(checkedActionSpy.count, 5) + } + + function test_actions() { + var group = createTemporaryObject(actionGroup, testCase) + verify(group) + + var actionsSpy = createTemporaryObject(signalSpy, testCase, {target: group, signalName: "actionsChanged"}) + verify(actionsSpy.valid) + + compare(group.actions.length, 0) + compare(group.checkedAction, null) + + var action1 = createTemporaryObject(action, testCase, {checked: true}) + var action2 = createTemporaryObject(action, testCase, {checked: false}) + + group.actions = [action1, action2] + compare(group.actions.length, 2) + compare(group.actions[0], action1) + compare(group.actions[1], action2) + compare(group.checkedAction, action1) + compare(actionsSpy.count, 2) + + var action3 = createTemporaryObject(action, testCase, {checked: true}) + + group.addAction(action3) + compare(group.actions.length, 3) + compare(group.actions[0], action1) + compare(group.actions[1], action2) + compare(group.actions[2], action3) + compare(group.checkedAction, action3) + compare(actionsSpy.count, 3) + + group.removeAction(action1) + compare(group.actions.length, 2) + compare(group.actions[0], action2) + compare(group.actions[1], action3) + compare(group.checkedAction, action3) + compare(actionsSpy.count, 4) + + group.actions = [] + compare(group.actions.length, 0) + tryCompare(group, "checkedAction", null) + compare(actionsSpy.count, 5) + } + + function test_triggered_data() { + return [ + {tag: "exclusive", exclusive: true}, + {tag: "non-exclusive", exclusive: false} + ] + } + + function test_triggered(data) { + var group = createTemporaryObject(actionGroup, testCase, {exclusive: data.exclusive}) + verify(group) + + var triggeredSpy = createTemporaryObject(signalSpy, testCase, {target: group, signalName: "triggered"}) + verify(triggeredSpy.valid) + + var action1 = createTemporaryObject(action, testCase) + var action2 = createTemporaryObject(action, testCase) + + group.addAction(action1) + group.addAction(action2) + + action1.triggered() + compare(triggeredSpy.count, 1) + compare(triggeredSpy.signalArguments[0][0], action1) + + action2.triggered() + compare(triggeredSpy.count, 2) + compare(triggeredSpy.signalArguments[1][0], action2) + } + + Component { + id: attachedGroup + Item { + property ActionGroup group: ActionGroup { id: group } + property Action action1: Action { ActionGroup.group: group } + property Action action2: Action { ActionGroup.group: group } + property Action action3: Action { ActionGroup.group: group } + } + } + + function test_attached() { + var container = createTemporaryObject(attachedGroup, testCase) + verify(container) + + verify(!container.group.checkedAction) + + container.action1.checked = true + compare(container.group.checkedAction, container.action1) + compare(container.action1.checked, true) + compare(container.action2.checked, false) + compare(container.action3.checked, false) + + container.action2.checked = true + compare(container.group.checkedAction, container.action2) + compare(container.action1.checked, false) + compare(container.action2.checked, true) + compare(container.action3.checked, false) + + container.action3.checked = true + compare(container.group.checkedAction, container.action3) + compare(container.action1.checked, false) + compare(container.action2.checked, false) + compare(container.action3.checked, true) + } + + function test_actionDestroyed() { + var group = createTemporaryObject(actionGroup, testCase) + verify(group) + + var actionsSpy = createTemporaryObject(signalSpy, testCase, {target: group, signalName: "actionsChanged"}) + verify(actionsSpy.valid) + + var action1 = createTemporaryObject(action, testCase, {objectName: "action1", checked: true}) + + group.addAction(action1) + compare(group.actions.length, 1) + compare(group.actions[0], action1) + compare(group.checkedAction, action1) + compare(actionsSpy.count, 1) + + action1.destroy() + wait(0) + compare(group.actions.length, 0) + compare(group.checkedAction, null) + compare(actionsSpy.count, 2) + } + + function test_nonExclusive() { + var group = createTemporaryObject(nonExclusiveGroup, testCase) + verify(group) + + var action1 = createTemporaryObject(action, testCase, {checked: true}) + group.addAction(action1) + compare(action1.checked, true) + compare(group.checkedAction, null) + + var action2 = createTemporaryObject(action, testCase, {checked: true}) + group.addAction(action2) + compare(action1.checked, true) + compare(action2.checked, true) + compare(group.checkedAction, null) + + action1.checked = false + compare(action1.checked, false) + compare(action2.checked, true) + compare(group.checkedAction, null) + + action2.checked = false + compare(action1.checked, false) + compare(action2.checked, false) + compare(group.checkedAction, null) + + action1.checked = true + compare(action1.checked, true) + compare(action2.checked, false) + compare(group.checkedAction, null) + + action2.checked = true + compare(action1.checked, true) + compare(action2.checked, true) + compare(group.checkedAction, null) + } + + function test_enabled() { + var group = createTemporaryObject(actionGroup, testCase) + verify(group) + + compare(group.enabled, true) + + var action1 = createTemporaryObject(action, testCase) + var action2 = createTemporaryObject(action, testCase) + compare(action1.enabled, true) + compare(action2.enabled, true) + + var action1Spy = createTemporaryObject(signalSpy, testCase, {target: action1, signalName: "enabledChanged"}) + var action2Spy = createTemporaryObject(signalSpy, testCase, {target: action2, signalName: "enabledChanged"}) + verify(action1Spy.valid && action2Spy.valid) + + group.addAction(action1) + compare(action1.enabled, true) + compare(action2.enabled, true) + compare(action1Spy.count, 0) + compare(action2Spy.count, 0) + + group.enabled = false + compare(action1.enabled, false) + compare(action2.enabled, true) + compare(action1Spy.count, 1) + compare(action1Spy.signalArguments[0][0], false) + compare(action2Spy.count, 0) + + group.addAction(action2) + compare(action1.enabled, false) + compare(action2.enabled, false) + compare(action1Spy.count, 1) + compare(action2Spy.count, 1) + compare(action2Spy.signalArguments[0][0], false) + + action1.enabled = false + compare(action1.enabled, false) + compare(action1Spy.count, 2) + compare(action1Spy.signalArguments[1][0], false) + compare(action2Spy.count, 1) + + group.enabled = true + compare(action1.enabled, false) + compare(action2.enabled, true) + compare(action1Spy.count, 2) + compare(action2Spy.count, 2) + compare(action2Spy.signalArguments[1][0], true) + } +} diff --git a/tests/auto/controls/data/tst_button.qml b/tests/auto/controls/data/tst_button.qml index cf9cf64d..2cf399f4 100644 --- a/tests/auto/controls/data/tst_button.qml +++ b/tests/auto/controls/data/tst_button.qml @@ -50,7 +50,7 @@ import QtQuick 2.2 import QtTest 1.0 -import QtQuick.Controls 2.2 +import QtQuick.Controls 2.3 TestCase { id: testCase @@ -430,4 +430,83 @@ TestCase { control.highlighted = true verify(control.highlighted) } + + function test_spacing() { + var control = createTemporaryObject(button, testCase, { text: "Some long, long, long text" }) + verify(control) + verify(control.contentItem.implicitWidth + control.leftPadding + control.rightPadding > control.background.implicitWidth) + + var textLabel = findChild(control.contentItem, "label") + verify(textLabel) + + // The implicitWidth of the IconLabel that all buttons use as their contentItem + // should be equal to the implicitWidth of the Text while no icon is set. + compare(control.contentItem.implicitWidth, textLabel.implicitWidth) + + // That means that spacing shouldn't affect it. + control.spacing += 100 + compare(control.contentItem.implicitWidth, textLabel.implicitWidth) + + // The implicitWidth of the Button itself should, therefore, also never include spacing while no icon is set. + compare(control.implicitWidth, textLabel.implicitWidth + control.leftPadding + control.rightPadding) + } + + function test_display_data() { + return [ + { "tag": "IconOnly", display: Button.IconOnly }, + { "tag": "TextOnly", display: Button.TextOnly }, + { "tag": "TextUnderIcon", display: Button.TextUnderIcon }, + { "tag": "TextBesideIcon", display: Button.TextBesideIcon }, + { "tag": "IconOnly, mirrored", display: Button.IconOnly, mirrored: true }, + { "tag": "TextOnly, mirrored", display: Button.TextOnly, mirrored: true }, + { "tag": "TextUnderIcon, mirrored", display: Button.TextUnderIcon, mirrored: true }, + { "tag": "TextBesideIcon, mirrored", display: Button.TextBesideIcon, mirrored: true } + ] + } + + function test_display(data) { + var control = createTemporaryObject(button, testCase, { + text: "Button", + display: data.display, + "icon.source": "qrc:/qt-project.org/imports/QtQuick/Controls.2/images/check.png", + "LayoutMirroring.enabled": !!data.mirrored + }) + verify(control) + compare(control.icon.source, "qrc:/qt-project.org/imports/QtQuick/Controls.2/images/check.png") + + var iconImage = findChild(control.contentItem, "image") + var textLabel = findChild(control.contentItem, "label") + + switch (control.display) { + case Button.IconOnly: + verify(iconImage) + verify(!textLabel) + compare(iconImage.x, (control.availableWidth - iconImage.width) / 2) + compare(iconImage.y, (control.availableHeight - iconImage.height) / 2) + break; + case Button.TextOnly: + verify(!iconImage) + verify(textLabel) + compare(textLabel.x, (control.availableWidth - textLabel.width) / 2) + compare(textLabel.y, (control.availableHeight - textLabel.height) / 2) + break; + case Button.TextUnderIcon: + verify(iconImage) + verify(textLabel) + compare(iconImage.x, (control.availableWidth - iconImage.width) / 2) + compare(textLabel.x, (control.availableWidth - textLabel.width) / 2) + verify(iconImage.y < textLabel.y) + break; + case Button.TextBesideIcon: + verify(iconImage) + verify(textLabel) + if (control.mirrored) + verify(textLabel.x < iconImage.x) + else + verify(iconImage.x < textLabel.x) + compare(iconImage.y, (control.availableHeight - iconImage.height) / 2) + compare(textLabel.y, (control.availableHeight - textLabel.height) / 2) + break; + } + } } diff --git a/tests/auto/controls/data/tst_buttongroup.qml b/tests/auto/controls/data/tst_buttongroup.qml index bde655da..cbbaec5a 100644 --- a/tests/auto/controls/data/tst_buttongroup.qml +++ b/tests/auto/controls/data/tst_buttongroup.qml @@ -50,7 +50,7 @@ import QtQuick 2.2 import QtTest 1.0 -import QtQuick.Controls 2.2 +import QtQuick.Controls 2.3 TestCase { id: testCase @@ -66,6 +66,11 @@ TestCase { } Component { + id: nonExclusiveGroup + ButtonGroup { exclusive: false } + } + + Component { id: signalSpy SignalSpy { } } @@ -88,6 +93,14 @@ TestCase { QtObject { } } + function test_defaults() { + var group = createTemporaryObject(buttonGroup, testCase) + verify(group) + compare(group.buttons.length, 0) + compare(group.checkedButton, null) + compare(group.exclusive, true) + } + function test_current() { var group = createTemporaryObject(buttonGroup, testCase) verify(group) @@ -200,8 +213,15 @@ TestCase { compare(buttonsSpy.count, 5) } - function test_clicked() { - var group = createTemporaryObject(buttonGroup, testCase) + function test_clicked_data() { + return [ + {tag: "exclusive", exclusive: true}, + {tag: "non-exclusive", exclusive: false} + ] + } + + function test_clicked(data) { + var group = createTemporaryObject(buttonGroup, testCase, {exclusive: data.exclusive}) verify(group) var clickedSpy = createTemporaryObject(signalSpy, testCase, {target: group, signalName: "clicked"}) @@ -346,4 +366,40 @@ TestCase { verify(container.group.checkedButton) compare(container.group.checkedButton.objectName, "0") } + + function test_nonExclusive() { + var group = createTemporaryObject(nonExclusiveGroup, testCase) + verify(group) + + var button1 = createTemporaryObject(button, testCase, {checked: true}) + group.addButton(button1) + compare(button1.checked, true) + compare(group.checkedButton, null) + + var button2 = createTemporaryObject(button, testCase, {checked: true}) + group.addButton(button2) + compare(button1.checked, true) + compare(button2.checked, true) + compare(group.checkedButton, null) + + button1.checked = false + compare(button1.checked, false) + compare(button2.checked, true) + compare(group.checkedButton, null) + + button2.checked = false + compare(button1.checked, false) + compare(button2.checked, false) + compare(group.checkedButton, null) + + button1.checked = true + compare(button1.checked, true) + compare(button2.checked, false) + compare(group.checkedButton, null) + + button2.checked = true + compare(button1.checked, true) + compare(button2.checked, true) + compare(group.checkedButton, null) + } } diff --git a/tests/auto/controls/data/tst_checkdelegate.qml b/tests/auto/controls/data/tst_checkdelegate.qml index 8933a7dd..9f92b4dc 100644 --- a/tests/auto/controls/data/tst_checkdelegate.qml +++ b/tests/auto/controls/data/tst_checkdelegate.qml @@ -89,4 +89,85 @@ TestCase { verify(control); compare(control.baselineOffset, control.contentItem.y + control.contentItem.baselineOffset); } + + function test_spacing() { + var control = createTemporaryObject(checkDelegate, testCase, { text: "Some long, long, long text" }) + verify(control) + verify(control.contentItem.implicitWidth + control.leftPadding + control.rightPadding > control.background.implicitWidth) + + var textLabel = findChild(control.contentItem, "label") + verify(textLabel) + + // The implicitWidth of the IconLabel that all buttons use as their contentItem should be + // equal to the implicitWidth of the Text and the check indicator + spacing while no icon is set. + compare(control.contentItem.implicitWidth, textLabel.implicitWidth + control.indicator.width + control.spacing) + + control.spacing += 100 + compare(control.contentItem.implicitWidth, textLabel.implicitWidth + control.indicator.width + control.spacing) + + compare(control.implicitWidth, textLabel.implicitWidth + control.indicator.width + control.spacing + control.leftPadding + control.rightPadding) + } + + function test_display_data() { + return [ + { "tag": "IconOnly", display: CheckDelegate.IconOnly }, + { "tag": "TextOnly", display: CheckDelegate.TextOnly }, + { "tag": "TextUnderIcon", display: CheckDelegate.TextUnderIcon }, + { "tag": "TextBesideIcon", display: CheckDelegate.TextBesideIcon }, + { "tag": "IconOnly, mirrored", display: CheckDelegate.IconOnly, mirrored: true }, + { "tag": "TextOnly, mirrored", display: CheckDelegate.TextOnly, mirrored: true }, + { "tag": "TextUnderIcon, mirrored", display: CheckDelegate.TextUnderIcon, mirrored: true }, + { "tag": "TextBesideIcon, mirrored", display: CheckDelegate.TextBesideIcon, mirrored: true } + ] + } + + function test_display(data) { + var control = createTemporaryObject(checkDelegate, testCase, { + text: "CheckDelegate", + display: data.display, + width: 400, + "icon.source": "qrc:/qt-project.org/imports/QtQuick/Controls.2/images/check.png", + "LayoutMirroring.enabled": !!data.mirrored + }) + verify(control) + compare(control.icon.source, "qrc:/qt-project.org/imports/QtQuick/Controls.2/images/check.png") + + var iconImage = findChild(control.contentItem, "image") + var textLabel = findChild(control.contentItem, "label") + + var availableWidth = control.availableWidth - control.indicator.width - control.spacing + var indicatorOffset = control.mirrored ? control.indicator.width + control.spacing : 0 + + switch (control.display) { + case CheckDelegate.IconOnly: + verify(iconImage) + verify(!textLabel) + compare(iconImage.x, indicatorOffset + (availableWidth - iconImage.width) / 2) + compare(iconImage.y, (control.availableHeight - iconImage.height) / 2) + break; + case CheckDelegate.TextOnly: + verify(!iconImage) + verify(textLabel) + compare(textLabel.x, control.mirrored ? control.availableWidth - textLabel.width : 0) + compare(textLabel.y, (control.availableHeight - textLabel.height) / 2) + break; + case CheckDelegate.TextUnderIcon: + verify(iconImage) + verify(textLabel) + compare(iconImage.x, indicatorOffset + (availableWidth - iconImage.width) / 2) + compare(textLabel.x, indicatorOffset + (availableWidth - textLabel.width) / 2) + verify(iconImage.y < textLabel.y) + break; + case CheckDelegate.TextBesideIcon: + verify(iconImage) + verify(textLabel) + if (control.mirrored) + verify(textLabel.x < iconImage.x) + else + verify(iconImage.x < textLabel.x) + compare(iconImage.y, (control.availableHeight - iconImage.height) / 2) + compare(textLabel.y, (control.availableHeight - textLabel.height) / 2) + break; + } + } } diff --git a/tests/auto/controls/data/tst_combobox.qml b/tests/auto/controls/data/tst_combobox.qml index 07e49e70..4f969106 100644 --- a/tests/auto/controls/data/tst_combobox.qml +++ b/tests/auto/controls/data/tst_combobox.qml @@ -707,7 +707,7 @@ TestCase { compare(highlightedSpy.count, 0) mouseMove(content, content.width / 2 + 1, content.height / 2 + 1) compare(activatedSpy.count, 0) - compare(highlightedSpy.count, 0) + compare(highlightedSpy.count, 1) mouseRelease(content) compare(activatedSpy.count, 1) compare(highlightedSpy.count, 1) @@ -1151,6 +1151,55 @@ TestCase { closedSpy.target = null } + function test_mouseHighlight() { + var control = createTemporaryObject(comboBox, testCase, {model: 20}) + verify(control) + + compare(control.highlightedIndex, -1) + + var openedSpy = signalSpy.createObject(control, {target: control.popup, signalName: "opened"}) + verify(openedSpy.valid) + + control.popup.open() + compare(control.highlightedIndex, 0) + tryCompare(openedSpy, "count", 1) + + var listview = control.popup.contentItem + verify(listview) + waitForRendering(listview) + + // hover-highlight through all visible list items one by one + var hoverIndex = -1 + var prevHoverItem = null + for (var y = 0; y < listview.height; ++y) { + var hoverItem = listview.itemAt(0, listview.contentY + y) + if (!hoverItem || !hoverItem.visible || hoverItem === prevHoverItem) + continue + mouseMove(hoverItem, 0, 0) + tryCompare(control, "highlightedIndex", ++hoverIndex) + prevHoverItem = hoverItem + } + + mouseMove(listview, listview.width / 2, listview.height / 2) + + // wheel-highlight the rest of the items + var delta = 120 + var prevWheelItem = null + while (!listview.atYEnd) { + var prevContentY = listview.contentY + mouseWheel(listview, listview.width / 2, listview.height / 2, -delta, -delta) + tryCompare(listview, "moving", false) + verify(listview.contentY > prevContentY) + + var wheelItem = listview.itemAt(listview.width / 2, listview.contentY + listview.height / 2) + if (!wheelItem || !wheelItem.visible || wheelItem === prevWheelItem) + continue + + tryCompare(control, "highlightedIndex", parseInt(wheelItem.text)) + prevWheelItem = wheelItem + } + } + RegExpValidator { id: regExpValidator regExp: /(red|blue|green)?/ @@ -1441,7 +1490,7 @@ TestCase { var control = createTemporaryObject(comboBox, testCase, { model: 1 }) verify(control) compare(control.popup.implicitHeight, 0) - compare(control.popup.height, 0) + compare(control.popup.height, control.popup.topPadding + control.popup.bottomPadding) // Ensure that it's open so that the popup's implicitHeight changes when we increase the model count. control.popup.open() @@ -1457,6 +1506,6 @@ TestCase { control.model = 0 control.popup.open() tryCompare(control.popup, "visible", true) - compare(control.popup.height, 0) + compare(control.popup.height, control.popup.topPadding + control.popup.bottomPadding) } } diff --git a/tests/auto/controls/data/tst_container.qml b/tests/auto/controls/data/tst_container.qml index 049982fb..44d8e67a 100644 --- a/tests/auto/controls/data/tst_container.qml +++ b/tests/auto/controls/data/tst_container.qml @@ -126,4 +126,46 @@ TestCase { compare(control1.currentIndex, 1) compare(control2.currentIndex, 1) } + + function test_removeTakeItem() { + var control = createTemporaryObject(container, testCase) + verify(control) + + var item1 = rectangle.createObject(control) + var item2 = rectangle.createObject(control) + var item3 = rectangle.createObject(control) + + item1.Component.onDestruction.connect(function() { item1 = null }) + item2.Component.onDestruction.connect(function() { item2 = null }) + item3.Component.onDestruction.connect(function() { item3 = null }) + + control.addItem(item1) + control.addItem(item2) + control.addItem(item3) + compare(control.count, 3) + + // takeItem(int) does not destroy + compare(control.takeItem(1), item2) + compare(control.count, 2) + wait(1) + verify(item2) + + // removeItem(Item) destroys + control.removeItem(item1) + compare(control.count, 1) + wait(1) + verify(!item1) + + // removeItem(null) must not call removeItem(0) + control.removeItem(null) + compare(control.count, 1) + wait(1) + verify(item3) + + // deprecated removeItem(int) does not destroy + control.removeItem(0) + compare(control.count, 0) + wait(1) + verify(item3) + } } diff --git a/tests/auto/controls/data/tst_dialog.qml b/tests/auto/controls/data/tst_dialog.qml index 2f3d2a6b..5ad3e81a 100644 --- a/tests/auto/controls/data/tst_dialog.qml +++ b/tests/auto/controls/data/tst_dialog.qml @@ -99,6 +99,7 @@ TestCase { verify(acceptedSpy.valid) control.accept() compare(acceptedSpy.count, 1) + compare(control.result, Dialog.Accepted) tryCompare(control, "visible", false) } @@ -118,6 +119,7 @@ TestCase { verify(rejectedSpy.valid) control.reject() compare(rejectedSpy.count, 1) + compare(control.result, Dialog.Rejected) tryCompare(control, "visible", false) @@ -356,4 +358,42 @@ TestCase { - (data.header ? control.header.height + control.spacing : 0) - (data.footer ? control.footer.height + control.spacing : 0)) } + + function test_signals_data() { + return [ + { tag: "Ok", standardButton: Dialog.Ok, signalName: "accepted" }, + { tag: "Open", standardButton: Dialog.Open, signalName: "accepted" }, + { tag: "Save", standardButton: Dialog.Save, signalName: "accepted" }, + { tag: "Cancel", standardButton: Dialog.Cancel, signalName: "rejected" }, + { tag: "Close", standardButton: Dialog.Close, signalName: "rejected" }, + { tag: "Discard", standardButton: Dialog.Discard, signalName: "discarded" }, + { tag: "Apply", standardButton: Dialog.Apply, signalName: "applied" }, + { tag: "Reset", standardButton: Dialog.Reset, signalName: "reset" }, + { tag: "RestoreDefaults", standardButton: Dialog.RestoreDefaults, signalName: "reset" }, + { tag: "Help", standardButton: Dialog.Help, signalName: "helpRequested" }, + { tag: "SaveAll", standardButton: Dialog.SaveAll, signalName: "accepted" }, + { tag: "Yes", standardButton: Dialog.Yes, signalName: "accepted" }, + { tag: "YesToAll", standardButton: Dialog.YesToAll, signalName: "accepted" }, + { tag: "No", standardButton: Dialog.No, signalName: "rejected" }, + { tag: "NoToAll", standardButton: Dialog.NoToAll, signalName: "rejected" }, + { tag: "Abort", standardButton: Dialog.Abort, signalName: "rejected" }, + { tag: "Retry", standardButton: Dialog.Retry, signalName: "accepted" }, + { tag: "Ignore", standardButton: Dialog.Ignore, signalName: "accepted" } + ] + } + + function test_signals(data) { + var control = createTemporaryObject(dialog, testCase) + verify(control) + + control.standardButtons = data.standardButton + var button = control.standardButton(data.standardButton) + verify(button) + + var buttonSpy = signalSpy.createObject(control.contentItem, {target: control, signalName: data.signalName}) + verify(buttonSpy.valid) + + button.clicked() + compare(buttonSpy.count, 1) + } } diff --git a/tests/auto/controls/data/tst_dialogbuttonbox.qml b/tests/auto/controls/data/tst_dialogbuttonbox.qml index 9b3d969f..044c9593 100644 --- a/tests/auto/controls/data/tst_dialogbuttonbox.qml +++ b/tests/auto/controls/data/tst_dialogbuttonbox.qml @@ -159,10 +159,10 @@ TestCase { { tag: "Save", standardButton: DialogButtonBox.Save, buttonRole: DialogButtonBox.AcceptRole, signalName: "accepted" }, { tag: "Cancel", standardButton: DialogButtonBox.Cancel, buttonRole: DialogButtonBox.RejectRole, signalName: "rejected" }, { tag: "Close", standardButton: DialogButtonBox.Close, buttonRole: DialogButtonBox.RejectRole, signalName: "rejected" }, - { tag: "Discard", standardButton: DialogButtonBox.Discard, buttonRole: DialogButtonBox.DestructiveRole }, - { tag: "Apply", standardButton: DialogButtonBox.Apply, buttonRole: DialogButtonBox.ApplyRole }, - { tag: "Reset", standardButton: DialogButtonBox.Reset, buttonRole: DialogButtonBox.ResetRole }, - { tag: "RestoreDefaults", standardButton: DialogButtonBox.RestoreDefaults, buttonRole: DialogButtonBox.ResetRole }, + { tag: "Discard", standardButton: DialogButtonBox.Discard, buttonRole: DialogButtonBox.DestructiveRole, signalName: "discarded" }, + { tag: "Apply", standardButton: DialogButtonBox.Apply, buttonRole: DialogButtonBox.ApplyRole, signalName: "applied" }, + { tag: "Reset", standardButton: DialogButtonBox.Reset, buttonRole: DialogButtonBox.ResetRole, signalName: "reset" }, + { tag: "RestoreDefaults", standardButton: DialogButtonBox.RestoreDefaults, buttonRole: DialogButtonBox.ResetRole, signalName: "reset" }, { tag: "Help", standardButton: DialogButtonBox.Help, buttonRole: DialogButtonBox.HelpRole, signalName: "helpRequested" }, { tag: "SaveAll", standardButton: DialogButtonBox.SaveAll, buttonRole: DialogButtonBox.AcceptRole, signalName: "accepted" }, { tag: "Yes", standardButton: DialogButtonBox.Yes, buttonRole: DialogButtonBox.YesRole, signalName: "accepted" }, @@ -188,11 +188,11 @@ TestCase { var clickedSpy = signalSpy.createObject(control, {target: control, signalName: "clicked"}) verify(clickedSpy.valid) var roleSpy = signalSpy.createObject(control, {target: control, signalName: data.signalName}) - compare(roleSpy.valid, !!data.signalName) + verify(roleSpy.valid) button.clicked() compare(clickedSpy.count, 1) compare(clickedSpy.signalArguments[0][0], button) - compare(roleSpy.count, !!data.signalName ? 1 : 0) + compare(roleSpy.count, 1) } } diff --git a/tests/auto/controls/data/tst_itemdelegate.qml b/tests/auto/controls/data/tst_itemdelegate.qml index 6f4bb6cb..4e4ca0c4 100644 --- a/tests/auto/controls/data/tst_itemdelegate.qml +++ b/tests/auto/controls/data/tst_itemdelegate.qml @@ -79,4 +79,84 @@ TestCase { control.highlighted = true verify(control.highlighted) } + + function test_spacing() { + var control = createTemporaryObject(itemDelegate, testCase, { text: "Some long, long, long text" }) + verify(control) + verify(control.contentItem.implicitWidth + control.leftPadding + control.rightPadding > control.background.implicitWidth) + + var textLabel = findChild(control.contentItem, "label") + verify(textLabel) + + // The implicitWidth of the IconLabel that all buttons use as their contentItem + // should be equal to the implicitWidth of the Text while no icon is set. + compare(control.contentItem.implicitWidth, textLabel.implicitWidth) + + // That means that spacing shouldn't affect it. + control.spacing += 100 + compare(control.contentItem.implicitWidth, textLabel.implicitWidth) + + // The implicitWidth of the ItemDelegate itself should, therefore, also never include spacing while no icon is set. + compare(control.implicitWidth, textLabel.implicitWidth + control.leftPadding + control.rightPadding) + } + + function test_display_data() { + return [ + { "tag": "IconOnly", display: ItemDelegate.IconOnly }, + { "tag": "TextOnly", display: ItemDelegate.TextOnly }, + { "tag": "TextUnderIcon", display: ItemDelegate.TextUnderIcon }, + { "tag": "TextBesideIcon", display: ItemDelegate.TextBesideIcon }, + { "tag": "IconOnly, mirrored", display: ItemDelegate.IconOnly, mirrored: true }, + { "tag": "TextOnly, mirrored", display: ItemDelegate.TextOnly, mirrored: true }, + { "tag": "TextUnderIcon, mirrored", display: ItemDelegate.TextUnderIcon, mirrored: true }, + { "tag": "TextBesideIcon, mirrored", display: ItemDelegate.TextBesideIcon, mirrored: true } + ] + } + + function test_display(data) { + var control = createTemporaryObject(itemDelegate, testCase, { + text: "ItemDelegate", + display: data.display, + width: 400, + "icon.source": "qrc:/qt-project.org/imports/QtQuick/Controls.2/images/check.png", + "LayoutMirroring.enabled": !!data.mirrored + }) + verify(control) + compare(control.icon.source, "qrc:/qt-project.org/imports/QtQuick/Controls.2/images/check.png") + + var iconImage = findChild(control.contentItem, "image") + var textLabel = findChild(control.contentItem, "label") + + switch (control.display) { + case ItemDelegate.IconOnly: + verify(iconImage) + verify(!textLabel) + compare(iconImage.x, (control.availableWidth - iconImage.width) / 2) + compare(iconImage.y, (control.availableHeight - iconImage.height) / 2) + break; + case ItemDelegate.TextOnly: + verify(!iconImage) + verify(textLabel) + compare(textLabel.x, control.mirrored ? control.availableWidth - textLabel.width : 0) + compare(textLabel.y, (control.availableHeight - textLabel.height) / 2) + break; + case ItemDelegate.TextUnderIcon: + verify(iconImage) + verify(textLabel) + compare(iconImage.x, (control.availableWidth - iconImage.width) / 2) + compare(textLabel.x, (control.availableWidth - textLabel.width) / 2) + verify(iconImage.y < textLabel.y) + break; + case ItemDelegate.TextBesideIcon: + verify(iconImage) + verify(textLabel) + if (control.mirrored) + verify(textLabel.x < iconImage.x) + else + verify(iconImage.x < textLabel.x) + compare(iconImage.y, (control.availableHeight - iconImage.height) / 2) + compare(textLabel.y, (control.availableHeight - textLabel.height) / 2) + break; + } + } } diff --git a/tests/auto/controls/data/tst_menuitem.qml b/tests/auto/controls/data/tst_menuitem.qml index 068e2a5c..57286002 100644 --- a/tests/auto/controls/data/tst_menuitem.qml +++ b/tests/auto/controls/data/tst_menuitem.qml @@ -65,6 +65,11 @@ TestCase { MenuItem { } } + Component { + id: menu + Menu { } + } + function test_baseline() { var control = createTemporaryObject(menuItem, testCase) verify(control) @@ -96,4 +101,93 @@ TestCase { control.highlighted = true verify(control.highlighted) } + + function test_display_data() { + return [ + { "tag": "IconOnly", display: MenuItem.IconOnly }, + { "tag": "TextOnly", display: MenuItem.TextOnly }, + { "tag": "TextUnderIcon", display: MenuItem.TextUnderIcon }, + { "tag": "TextBesideIcon", display: MenuItem.TextBesideIcon }, + { "tag": "IconOnly, mirrored", display: MenuItem.IconOnly, mirrored: true }, + { "tag": "TextOnly, mirrored", display: MenuItem.TextOnly, mirrored: true }, + { "tag": "TextUnderIcon, mirrored", display: MenuItem.TextUnderIcon, mirrored: true }, + { "tag": "TextBesideIcon, mirrored", display: MenuItem.TextBesideIcon, mirrored: true } + ] + } + + function test_display(data) { + var control = createTemporaryObject(menuItem, testCase, { + text: "MenuItem", + display: data.display, + "icon.source": "qrc:/qt-project.org/imports/QtQuick/Controls.2/images/check.png", + "LayoutMirroring.enabled": !!data.mirrored + }) + verify(control) + compare(control.icon.source, "qrc:/qt-project.org/imports/QtQuick/Controls.2/images/check.png") + + var padding = data.mirrored ? control.contentItem.rightPadding : control.contentItem.leftPadding + var iconImage = findChild(control.contentItem, "image") + var textLabel = findChild(control.contentItem, "label") + + switch (control.display) { + case MenuItem.IconOnly: + verify(iconImage) + verify(!textLabel) + compare(iconImage.x, control.mirrored ? control.availableWidth - iconImage.width - padding : padding) + compare(iconImage.y, (control.availableHeight - iconImage.height) / 2) + break; + case MenuItem.TextOnly: + verify(!iconImage) + verify(textLabel) + compare(textLabel.x, control.mirrored ? control.availableWidth - textLabel.width - padding : padding) + compare(textLabel.y, (control.availableHeight - textLabel.height) / 2) + break; + case MenuItem.TextUnderIcon: + verify(iconImage) + verify(textLabel) + compare(iconImage.x, control.mirrored ? control.availableWidth - iconImage.width - (textLabel.width - iconImage.width) / 2 - padding : (textLabel.width - iconImage.width) / 2 + padding) + compare(textLabel.x, control.mirrored ? control.availableWidth - textLabel.width - padding : padding) + verify(iconImage.y < textLabel.y) + break; + case MenuItem.TextBesideIcon: + verify(iconImage) + verify(textLabel) + if (control.mirrored) + verify(textLabel.x < iconImage.x) + else + verify(iconImage.x < textLabel.x) + compare(iconImage.y, (control.availableHeight - iconImage.height) / 2) + compare(textLabel.y, (control.availableHeight - textLabel.height) / 2) + break; + } + } + + function test_menu() { + var control = createTemporaryObject(menu, testCase) + verify(control) + + var item1 = createTemporaryObject(menuItem, testCase) + verify(item1) + compare(item1.menu, null) + + var item2 = createTemporaryObject(menuItem, testCase) + verify(item2) + compare(item2.menu, null) + + control.addItem(item1) + compare(item1.menu, control) + compare(item2.menu, null) + + control.insertItem(1, item2) + compare(item1.menu, control) + compare(item2.menu, control) + + control.removeItem(1) + compare(item1.menu, control) + compare(item2.menu, null) + + control.removeItem(0) + compare(item1.menu, null) + compare(item2.menu, null) + } } diff --git a/tests/auto/controls/data/tst_popup.qml b/tests/auto/controls/data/tst_popup.qml index bec50ad0..c8b3985c 100644 --- a/tests/auto/controls/data/tst_popup.qml +++ b/tests/auto/controls/data/tst_popup.qml @@ -1178,16 +1178,6 @@ TestCase { compare(child.ApplicationWindow.window, null) } - SignalSpy { - id: openedSpy - signalName: "opened" - } - - SignalSpy { - id: closedSpy - signalName: "closed" - } - Component { id: pausePopup Popup { @@ -1200,19 +1190,32 @@ TestCase { var control = createTemporaryObject(pausePopup, testCase) verify(control) - openedSpy.target = control - closedSpy.target = control + var openedSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "opened"}) + verify(openedSpy.valid) + var closedSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "closed"}) + verify(closedSpy.valid) + var openedChangeSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "openedChanged"}) + verify(openedChangeSpy.valid) control.open() compare(control.visible, true) + compare(control.opened, false) + compare(openedChangeSpy.count, 0) compare(openedSpy.count, 0) tryCompare(openedSpy, "count", 1) + compare(control.opened, true) + compare(openedChangeSpy.count, 1) compare(closedSpy.count, 0) control.close() + compare(control.visible, true) + compare(control.opened, false) + compare(openedChangeSpy.count, 2) compare(openedSpy.count, 1) compare(closedSpy.count, 0) tryCompare(closedSpy, "count", 1) + compare(control.opened, false) + compare(openedChangeSpy.count, 2) compare(control.visible, false) } diff --git a/tests/auto/controls/data/tst_radiodelegate.qml b/tests/auto/controls/data/tst_radiodelegate.qml index 8fb6f933..b1ee00db 100644 --- a/tests/auto/controls/data/tst_radiodelegate.qml +++ b/tests/auto/controls/data/tst_radiodelegate.qml @@ -89,4 +89,85 @@ TestCase { verify(control); compare(control.baselineOffset, control.contentItem.y + control.contentItem.baselineOffset); } + + function test_spacing() { + var control = createTemporaryObject(radioDelegate, testCase, { text: "Some long, long, long text" }) + verify(control) + verify(control.contentItem.implicitWidth + control.leftPadding + control.rightPadding > control.background.implicitWidth) + + var textLabel = findChild(control.contentItem, "label") + verify(textLabel) + + // The implicitWidth of the IconLabel that all buttons use as their contentItem should be + // equal to the implicitWidth of the Text and the radio indicator + spacing while no icon is set. + compare(control.contentItem.implicitWidth, textLabel.implicitWidth + control.indicator.width + control.spacing) + + control.spacing += 100 + compare(control.contentItem.implicitWidth, textLabel.implicitWidth + control.indicator.width + control.spacing) + + compare(control.implicitWidth, textLabel.implicitWidth + control.indicator.width + control.spacing + control.leftPadding + control.rightPadding) + } + + function test_display_data() { + return [ + { "tag": "IconOnly", display: RadioDelegate.IconOnly }, + { "tag": "TextOnly", display: RadioDelegate.TextOnly }, + { "tag": "TextUnderIcon", display: RadioDelegate.TextUnderIcon }, + { "tag": "TextBesideIcon", display: RadioDelegate.TextBesideIcon }, + { "tag": "IconOnly, mirrored", display: RadioDelegate.IconOnly, mirrored: true }, + { "tag": "TextOnly, mirrored", display: RadioDelegate.TextOnly, mirrored: true }, + { "tag": "TextUnderIcon, mirrored", display: RadioDelegate.TextUnderIcon, mirrored: true }, + { "tag": "TextBesideIcon, mirrored", display: RadioDelegate.TextBesideIcon, mirrored: true } + ] + } + + function test_display(data) { + var control = createTemporaryObject(radioDelegate, testCase, { + text: "RadioDelegate", + display: data.display, + width: 400, + "icon.source": "qrc:/qt-project.org/imports/QtQuick/Controls.2/images/check.png", + "LayoutMirroring.enabled": !!data.mirrored + }) + verify(control) + compare(control.icon.source, "qrc:/qt-project.org/imports/QtQuick/Controls.2/images/check.png") + + var iconImage = findChild(control.contentItem, "image") + var textLabel = findChild(control.contentItem, "label") + + var availableWidth = control.availableWidth - control.indicator.width - control.spacing + var indicatorOffset = control.mirrored ? control.indicator.width + control.spacing : 0 + + switch (control.display) { + case RadioDelegate.IconOnly: + verify(iconImage) + verify(!textLabel) + compare(iconImage.x, indicatorOffset + (availableWidth - iconImage.width) / 2) + compare(iconImage.y, (control.availableHeight - iconImage.height) / 2) + break; + case RadioDelegate.TextOnly: + verify(!iconImage) + verify(textLabel) + compare(textLabel.x, control.mirrored ? control.availableWidth - textLabel.width : 0) + compare(textLabel.y, (control.availableHeight - textLabel.height) / 2) + break; + case RadioDelegate.TextUnderIcon: + verify(iconImage) + verify(textLabel) + compare(iconImage.x, indicatorOffset + (availableWidth - iconImage.width) / 2) + compare(textLabel.x, indicatorOffset + (availableWidth - textLabel.width) / 2) + verify(iconImage.y < textLabel.y) + break; + case RadioDelegate.TextBesideIcon: + verify(iconImage) + verify(textLabel) + if (control.mirrored) + verify(textLabel.x < iconImage.x) + else + verify(iconImage.x < textLabel.x) + compare(iconImage.y, (control.availableHeight - iconImage.height) / 2) + compare(textLabel.y, (control.availableHeight - textLabel.height) / 2) + break; + } + } } diff --git a/tests/auto/controls/data/tst_rangeslider.qml b/tests/auto/controls/data/tst_rangeslider.qml index 791f357f..39b0c4b0 100644 --- a/tests/auto/controls/data/tst_rangeslider.qml +++ b/tests/auto/controls/data/tst_rangeslider.qml @@ -96,6 +96,8 @@ TestCase { compare(control.stepSize, 0) compare(control.snapMode, RangeSlider.NoSnap) compare(control.orientation, Qt.Horizontal) + compare(control.horizontal, true) + compare(control.vertical, false) } function test_values() { @@ -262,9 +264,14 @@ TestCase { verify(control) compare(control.orientation, Qt.Horizontal) + compare(control.horizontal, true) + compare(control.vertical, false) verify(control.width > control.height) + control.orientation = Qt.Vertical compare(control.orientation, Qt.Vertical) + compare(control.horizontal, false) + compare(control.vertical, true) verify(control.width < control.height) } diff --git a/tests/auto/controls/data/tst_roundbutton.qml b/tests/auto/controls/data/tst_roundbutton.qml index 7a533348..c772c85f 100644 --- a/tests/auto/controls/data/tst_roundbutton.qml +++ b/tests/auto/controls/data/tst_roundbutton.qml @@ -84,4 +84,83 @@ TestCase { control.width = 10; compare(control.radius, 5); } + + function test_spacing() { + var control = createTemporaryObject(roundButton, testCase, { text: "Some long, long, long text" }) + verify(control) + verify(control.contentItem.implicitWidth + control.leftPadding + control.rightPadding > control.background.implicitWidth) + + var textLabel = findChild(control.contentItem, "label") + verify(textLabel) + + // The implicitWidth of the IconLabel that all buttons use as their contentItem + // should be equal to the implicitWidth of the Text while no icon is set. + compare(control.contentItem.implicitWidth, textLabel.implicitWidth) + + // That means that spacing shouldn't affect it. + control.spacing += 100 + compare(control.contentItem.implicitWidth, textLabel.implicitWidth) + + // The implicitWidth of the Button itself should, therefore, also never include spacing while no icon is set. + compare(control.implicitWidth, textLabel.implicitWidth + control.leftPadding + control.rightPadding) + } + + function test_display_data() { + return [ + { "tag": "IconOnly", display: RoundButton.IconOnly }, + { "tag": "TextOnly", display: RoundButton.TextOnly }, + { "tag": "TextUnderIcon", display: RoundButton.TextUnderIcon }, + { "tag": "TextBesideIcon", display: RoundButton.TextBesideIcon }, + { "tag": "IconOnly, mirrored", display: RoundButton.IconOnly, mirrored: true }, + { "tag": "TextOnly, mirrored", display: RoundButton.TextOnly, mirrored: true }, + { "tag": "TextUnderIcon, mirrored", display: RoundButton.TextUnderIcon, mirrored: true }, + { "tag": "TextBesideIcon, mirrored", display: RoundButton.TextBesideIcon, mirrored: true } + ] + } + + function test_display(data) { + var control = createTemporaryObject(roundButton, testCase, { + text: "RoundButton", + display: data.display, + "icon.source": "qrc:/qt-project.org/imports/QtQuick/Controls.2/images/check.png", + "LayoutMirroring.enabled": !!data.mirrored + }) + verify(control) + compare(control.icon.source, "qrc:/qt-project.org/imports/QtQuick/Controls.2/images/check.png") + + var iconImage = findChild(control.contentItem, "image") + var textLabel = findChild(control.contentItem, "label") + + switch (control.display) { + case RoundButton.IconOnly: + verify(iconImage) + verify(!textLabel) + compare(iconImage.x, (control.availableWidth - iconImage.width) / 2) + compare(iconImage.y, (control.availableHeight - iconImage.height) / 2) + break; + case RoundButton.TextOnly: + verify(!iconImage) + verify(textLabel) + compare(textLabel.x, (control.availableWidth - textLabel.width) / 2) + compare(textLabel.y, (control.availableHeight - textLabel.height) / 2) + break; + case RoundButton.TextUnderIcon: + verify(iconImage) + verify(textLabel) + compare(iconImage.x, (control.availableWidth - iconImage.width) / 2) + compare(textLabel.x, (control.availableWidth - textLabel.width) / 2) + verify(iconImage.y < textLabel.y) + break; + case RoundButton.TextBesideIcon: + verify(iconImage) + verify(textLabel) + if (control.mirrored) + verify(textLabel.x < iconImage.x) + else + verify(iconImage.x < textLabel.x) + compare(iconImage.y, (control.availableHeight - iconImage.height) / 2) + compare(textLabel.y, (control.availableHeight - textLabel.height) / 2) + break; + } + } } diff --git a/tests/auto/controls/data/tst_scrollbar.qml b/tests/auto/controls/data/tst_scrollbar.qml index 6697de88..ec0be3f8 100644 --- a/tests/auto/controls/data/tst_scrollbar.qml +++ b/tests/auto/controls/data/tst_scrollbar.qml @@ -736,4 +736,18 @@ TestCase { container.destroy() } + + function test_orientation() { + var control = createTemporaryObject(scrollBar, testCase) + verify(control) + + compare(control.orientation, Qt.Vertical) + compare(control.horizontal, false) + compare(control.vertical, true) + + control.orientation = Qt.Horizontal + compare(control.orientation, Qt.Horizontal) + compare(control.horizontal, true) + compare(control.vertical, false) + } } diff --git a/tests/auto/controls/data/tst_scrollindicator.qml b/tests/auto/controls/data/tst_scrollindicator.qml index 54cd7159..1e28c4f5 100644 --- a/tests/auto/controls/data/tst_scrollindicator.qml +++ b/tests/auto/controls/data/tst_scrollindicator.qml @@ -217,4 +217,18 @@ TestCase { compare(horizontal.contentItem.x, horizontal.leftPadding + 0.8 * horizontal.availableWidth) compare(horizontal.contentItem.width, 0.2 * horizontal.availableWidth) } + + function test_orientation() { + var control = createTemporaryObject(scrollIndicator, testCase) + verify(control) + + compare(control.orientation, Qt.Vertical) + compare(control.horizontal, false) + compare(control.vertical, true) + + control.orientation = Qt.Horizontal + compare(control.orientation, Qt.Horizontal) + compare(control.horizontal, true) + compare(control.vertical, false) + } } diff --git a/tests/auto/controls/data/tst_slider.qml b/tests/auto/controls/data/tst_slider.qml index 8d696297..b70aeaab 100644 --- a/tests/auto/controls/data/tst_slider.qml +++ b/tests/auto/controls/data/tst_slider.qml @@ -77,6 +77,8 @@ TestCase { compare(control.stepSize, 0) compare(control.snapMode, Slider.NoSnap) compare(control.orientation, Qt.Horizontal) + compare(control.horizontal, true) + compare(control.vertical, false) } function test_value() { @@ -201,9 +203,14 @@ TestCase { verify(control) compare(control.orientation, Qt.Horizontal) + compare(control.horizontal, true) + compare(control.vertical, false) verify(control.width > control.height) + control.orientation = Qt.Vertical compare(control.orientation, Qt.Vertical) + compare(control.horizontal, false) + compare(control.vertical, true) verify(control.width < control.height) } diff --git a/tests/auto/controls/data/tst_spinbox.qml b/tests/auto/controls/data/tst_spinbox.qml index 4b2e38b3..17e4b592 100644 --- a/tests/auto/controls/data/tst_spinbox.qml +++ b/tests/auto/controls/data/tst_spinbox.qml @@ -116,15 +116,23 @@ TestCase { compare(control.up.indicator.enabled, false) compare(control.down.indicator.enabled, true) + control.wrap = true + compare(control.up.indicator.enabled, true) + compare(control.down.indicator.enabled, true) + control.value = -1 compare(control.value, 0) compare(control.up.indicator.enabled, true) - compare(control.down.indicator.enabled, false) + compare(control.down.indicator.enabled, true) control.from = 25 compare(control.from, 25) compare(control.value, 25) compare(control.up.indicator.enabled, true) + compare(control.down.indicator.enabled, true) + + control.wrap = false + compare(control.up.indicator.enabled, true) compare(control.down.indicator.enabled, false) control.value = 30 @@ -276,8 +284,19 @@ TestCase { compare(valueModifiedSpy.count, 2) } - function test_keys() { - var control = createTemporaryObject(spinBox, testCase) + function test_keys_data() { + return [ + { tag: "1", from: 1, to: 10, value: 1, stepSize: 1, upSteps: [2,3,4], downSteps: [3,2,1,1] }, + { tag: "2", from: 1, to: 10, value: 10, stepSize: 2, upSteps: [10,10], downSteps: [8,6,4] }, + { tag: "25", from: 0, to: 100, value: 50, stepSize: 25, upSteps: [75,100,100], downSteps: [75,50,25,0,0] }, + { tag: "wrap1", wrap: true, from: 1, to: 10, value: 1, stepSize: 1, upSteps: [2,3], downSteps: [2,1,10,9] }, + { tag: "wrap2", wrap: true, from: 1, to: 10, value: 10, stepSize: 2, upSteps: [1,3,5], downSteps: [3,1,10,8,6] }, + { tag: "wrap25", wrap: true, from: 0, to: 100, value: 50, stepSize: 25, upSteps: [75,100,0,25], downSteps: [0,100,75] } + ] + } + + function test_keys(data) { + var control = createTemporaryObject(spinBox, testCase, {wrap: data.wrap, from: data.from, to: data.to, value: data.value, stepSize: data.stepSize}) verify(control) var upPressedCount = 0 @@ -296,48 +315,31 @@ TestCase { control.forceActiveFocus() verify(control.activeFocus) - control.value = 50 - compare(control.value, 50) - - for (var d1 = 1; d1 <= 10; ++d1) { - keyPress(Qt.Key_Down) - compare(control.down.pressed, true) - compare(control.up.pressed, false) - compare(downPressedSpy.count, ++downPressedCount) - compare(valueModifiedSpy.count, ++valueModifiedCount) - - compare(control.value, 50 - d1) - - keyRelease(Qt.Key_Down) - compare(control.down.pressed, false) - compare(control.up.pressed, false) - compare(downPressedSpy.count, ++downPressedCount) - compare(valueModifiedSpy.count, valueModifiedCount) - } - compare(control.value, 40) - - for (var i1 = 1; i1 <= 10; ++i1) { + for (var u = 0; u < data.upSteps.length; ++u) { + var wasUpEnabled = control.wrap || control.value < control.to keyPress(Qt.Key_Up) - compare(control.up.pressed, true) + compare(control.up.pressed, wasUpEnabled) compare(control.down.pressed, false) - compare(upPressedSpy.count, ++upPressedCount) - compare(valueModifiedSpy.count, ++valueModifiedCount) + if (wasUpEnabled) { + ++upPressedCount + ++valueModifiedCount + } + compare(upPressedSpy.count, upPressedCount) + compare(valueModifiedSpy.count, valueModifiedCount) - compare(control.value, 40 + i1) + compare(control.value, data.upSteps[u]) keyRelease(Qt.Key_Up) compare(control.down.pressed, false) compare(control.up.pressed, false) - compare(upPressedSpy.count, ++upPressedCount) + if (wasUpEnabled) + ++upPressedCount + compare(upPressedSpy.count, upPressedCount) compare(valueModifiedSpy.count, valueModifiedCount) } - compare(control.value, 50) - control.stepSize = 25 - compare(control.stepSize, 25) - - for (var d2 = 1; d2 <= 10; ++d2) { - var wasDownEnabled = control.value > control.from + for (var d = 0; d < data.downSteps.length; ++d) { + var wasDownEnabled = control.wrap || control.value > control.from keyPress(Qt.Key_Down) compare(control.down.pressed, wasDownEnabled) compare(control.up.pressed, false) @@ -348,7 +350,7 @@ TestCase { compare(downPressedSpy.count, downPressedCount) compare(valueModifiedSpy.count, valueModifiedCount) - compare(control.value, Math.max(0, 50 - d2 * 25)) + compare(control.value, data.downSteps[d]) keyRelease(Qt.Key_Down) compare(control.down.pressed, false) @@ -358,31 +360,6 @@ TestCase { compare(downPressedSpy.count, downPressedCount) compare(valueModifiedSpy.count, valueModifiedCount) } - compare(control.value, 0) - - for (var i2 = 1; i2 <= 10; ++i2) { - var wasUpEnabled = control.value < control.to - keyPress(Qt.Key_Up) - compare(control.up.pressed, wasUpEnabled) - compare(control.down.pressed, false) - if (wasUpEnabled) { - ++upPressedCount - ++valueModifiedCount - } - compare(upPressedSpy.count, upPressedCount) - compare(valueModifiedSpy.count, valueModifiedCount) - - compare(control.value, Math.min(99, i2 * 25)) - - keyRelease(Qt.Key_Up) - compare(control.down.pressed, false) - compare(control.up.pressed, false) - if (wasUpEnabled) - ++upPressedCount - compare(upPressedSpy.count, upPressedCount) - compare(valueModifiedSpy.count, valueModifiedCount) - } - compare(control.value, 99) } function test_locale() { @@ -454,46 +431,46 @@ TestCase { compare(control.value, 5) } + function test_wheel_data() { + return [ + { tag: "1", from: 1, to: 10, value: 1, stepSize: 1, upSteps: [2,3,4], downSteps: [3,2,1,1] }, + { tag: "2", from: 1, to: 10, value: 10, stepSize: 2, upSteps: [10,10], downSteps: [8,6,4] }, + { tag: "25", from: 0, to: 100, value: 50, stepSize: 25, upSteps: [75,100,100], downSteps: [75,50,25,0,0] }, + { tag: "wrap1", wrap: true, from: 1, to: 10, value: 1, stepSize: 1, upSteps: [2,3], downSteps: [2,1,10,9] }, + { tag: "wrap2", wrap: true, from: 1, to: 10, value: 10, stepSize: 2, upSteps: [1,3,5], downSteps: [3,1,10,8,6] }, + { tag: "wrap25", wrap: true, from: 0, to: 100, value: 50, stepSize: 25, upSteps: [75,100,0,25], downSteps: [0,100,75] } + ] + } + function test_wheel(data) { - var control = createTemporaryObject(spinBox, testCase, {wheelEnabled: true}) + var control = createTemporaryObject(spinBox, testCase, {wrap: data.wrap, from: data.from, to: data.to, value: data.value, stepSize: data.stepSize, wheelEnabled: true}) verify(control) + var valueModifiedCount = 0 var valueModifiedSpy = signalSpy.createObject(control, {target: control, signalName: "valueModified"}) verify(valueModifiedSpy.valid) var delta = 120 - compare(control.value, 0) - - mouseWheel(control, control.width / 2, control.height / 2, delta, delta) - compare(control.value, 1) - compare(valueModifiedSpy.count, 1) - - control.stepSize = 2 - - mouseWheel(control, control.width / 2, control.height / 2, delta, delta) - compare(control.value, 3) - compare(valueModifiedSpy.count, 2) - - control.stepSize = 10 - - mouseWheel(control, control.width / 2, control.height / 2, -delta, -delta) - compare(control.value, 0) - compare(valueModifiedSpy.count, 3) - - control.stepSize = 5 + for (var u = 0; u < data.upSteps.length; ++u) { + var wasUpEnabled = control.wrap || control.value < control.to + mouseWheel(control, control.width / 2, control.height / 2, delta, delta) + if (wasUpEnabled) + ++valueModifiedCount + compare(valueModifiedSpy.count, valueModifiedCount) - mouseWheel(control, control.width / 2, control.height / 2, delta, delta) - compare(control.value, 5) - compare(valueModifiedSpy.count, 4) + compare(control.value, data.upSteps[u]) + } - mouseWheel(control, control.width / 2, control.height / 2, 0.5 * delta, 0.5 * delta) - compare(control.value, 8) - compare(valueModifiedSpy.count, 5) + for (var d = 0; d < data.downSteps.length; ++d) { + var wasDownEnabled = control.wrap || control.value > control.from + mouseWheel(control, control.width / 2, control.height / 2, -delta, -delta) + if (wasDownEnabled) + ++valueModifiedCount + compare(valueModifiedSpy.count, valueModifiedCount) - mouseWheel(control, control.width / 2, control.height / 2, -delta, -delta) - compare(control.value, 3) - compare(valueModifiedSpy.count, 6) + compare(control.value, data.downSteps[d]) + } } function test_initiallyDisabledIndicators_data() { diff --git a/tests/auto/controls/data/tst_stackview.qml b/tests/auto/controls/data/tst_stackview.qml index 3328c84f..097180b8 100644 --- a/tests/auto/controls/data/tst_stackview.qml +++ b/tests/auto/controls/data/tst_stackview.qml @@ -221,33 +221,75 @@ TestCase { function test_depth() { var control = createTemporaryObject(stackView, testCase) verify(control) + + var depthChanges = 0 + var emptyChanges = 0 var depthSpy = signalSpy.createObject(control, {target: control, signalName: "depthChanged"}) + var emptySpy = signalSpy.createObject(control, {target: control, signalName: "emptyChanged"}) verify(depthSpy.valid) + verify(emptySpy.valid) compare(control.depth, 0) + compare(control.empty, true) + control.push(item, StackView.Immediate) compare(control.depth, 1) - compare(depthSpy.count, 1) + compare(depthSpy.count, ++depthChanges) + compare(control.empty, false) + compare(emptySpy.count, ++emptyChanges) + control.clear() compare(control.depth, 0) - compare(depthSpy.count, 2) + compare(depthSpy.count, ++depthChanges) + compare(control.empty, true) + compare(emptySpy.count, ++emptyChanges) + control.push(component, StackView.Immediate) compare(control.depth, 1) - compare(depthSpy.count, 3) + compare(depthSpy.count, ++depthChanges) + compare(control.empty, false) + compare(emptySpy.count, ++emptyChanges) + control.push(component, StackView.Immediate) compare(control.depth, 2) - compare(depthSpy.count, 4) - control.pop(StackView.Immediate) + compare(depthSpy.count, ++depthChanges) + compare(control.empty, false) + compare(emptySpy.count, emptyChanges) + + control.replace(component, StackView.Immediate) + compare(control.depth, 2) + compare(depthSpy.count, depthChanges) + compare(control.empty, false) + compare(emptySpy.count, emptyChanges) + + control.replace([component, component], StackView.Immediate) + compare(control.depth, 3) + compare(depthSpy.count, ++depthChanges) + compare(control.empty, false) + compare(emptySpy.count, emptyChanges) + + control.pop(null, StackView.Immediate) compare(control.depth, 1) - compare(depthSpy.count, 5) + compare(depthSpy.count, ++depthChanges) + compare(control.empty, false) + compare(emptySpy.count, emptyChanges) + control.pop(StackView.Immediate) // ignored compare(control.depth, 1) - compare(depthSpy.count, 5) + compare(depthSpy.count, depthChanges) + compare(control.empty, false) + compare(emptySpy.count, emptyChanges) + control.clear() compare(control.depth, 0) - compare(depthSpy.count, 6) + compare(depthSpy.count, ++depthChanges) + compare(control.empty, true) + compare(emptySpy.count, ++emptyChanges) + control.clear() compare(control.depth, 0) - compare(depthSpy.count, 6) + compare(depthSpy.count, depthChanges) + compare(control.empty, true) + compare(emptySpy.count, emptyChanges) } function test_size() { @@ -510,6 +552,24 @@ TestCase { compare(control.currentItem, item8) } + function test_clear() { + var control = createTemporaryObject(stackView, testCase) + verify(control) + + control.push(component, StackView.Immediate) + + control.clear() + compare(control.depth, 0) + compare(control.busy, false) + + control.push(component, StackView.Immediate) + + control.clear(StackView.PopTransition) + compare(control.depth, 0) + compare(control.busy, true) + tryCompare(control, "busy", false) + } + function test_visibility_data() { return [ {tag:"default transitions", properties: {}}, diff --git a/tests/auto/controls/data/tst_swipedelegate.qml b/tests/auto/controls/data/tst_swipedelegate.qml index c24f6962..d603bd7f 100644 --- a/tests/auto/controls/data/tst_swipedelegate.qml +++ b/tests/auto/controls/data/tst_swipedelegate.qml @@ -1569,4 +1569,84 @@ TestCase { verify(control.behavior.enabled); verify(control.animation.running); } + + function test_spacing() { + var control = createTemporaryObject(swipeDelegateComponent, testCase, { text: "Some long, long, long text" }) + verify(control) + verify(control.contentItem.implicitWidth + control.leftPadding + control.rightPadding > control.background.implicitWidth) + + var textLabel = findChild(control.contentItem, "label") + verify(textLabel) + + // The implicitWidth of the IconLabel that all buttons use as their contentItem + // should be equal to the implicitWidth of the Text while no icon is set. + compare(control.contentItem.implicitWidth, textLabel.implicitWidth) + + // That means that spacing shouldn't affect it. + control.spacing += 100 + compare(control.contentItem.implicitWidth, textLabel.implicitWidth) + + // The implicitWidth of the SwipeDelegate itself should, therefore, also never include spacing while no icon is set. + compare(control.implicitWidth, textLabel.implicitWidth + control.leftPadding + control.rightPadding) + } + + function test_display_data() { + return [ + { "tag": "IconOnly", display: SwipeDelegate.IconOnly }, + { "tag": "TextOnly", display: SwipeDelegate.TextOnly }, + { "tag": "TextUnderIcon", display: SwipeDelegate.TextUnderIcon }, + { "tag": "TextBesideIcon", display: SwipeDelegate.TextBesideIcon }, + { "tag": "IconOnly, mirrored", display: SwipeDelegate.IconOnly, mirrored: true }, + { "tag": "TextOnly, mirrored", display: SwipeDelegate.TextOnly, mirrored: true }, + { "tag": "TextUnderIcon, mirrored", display: SwipeDelegate.TextUnderIcon, mirrored: true }, + { "tag": "TextBesideIcon, mirrored", display: SwipeDelegate.TextBesideIcon, mirrored: true } + ] + } + + function test_display(data) { + var control = createTemporaryObject(swipeDelegateComponent, testCase, { + text: "SwipeDelegate", + display: data.display, + width: 400, + "icon.source": "qrc:/qt-project.org/imports/QtQuick/Controls.2/images/check.png", + "LayoutMirroring.enabled": !!data.mirrored + }) + verify(control) + compare(control.icon.source, "qrc:/qt-project.org/imports/QtQuick/Controls.2/images/check.png") + + var iconImage = findChild(control.contentItem, "image") + var textLabel = findChild(control.contentItem, "label") + + switch (control.display) { + case SwipeDelegate.IconOnly: + verify(iconImage) + verify(!textLabel) + compare(iconImage.x, (control.availableWidth - iconImage.width) / 2) + compare(iconImage.y, (control.availableHeight - iconImage.height) / 2) + break; + case SwipeDelegate.TextOnly: + verify(!iconImage) + verify(textLabel) + compare(textLabel.x, control.mirrored ? control.availableWidth - textLabel.width : 0) + compare(textLabel.y, (control.availableHeight - textLabel.height) / 2) + break; + case SwipeDelegate.TextUnderIcon: + verify(iconImage) + verify(textLabel) + compare(iconImage.x, (control.availableWidth - iconImage.width) / 2) + compare(textLabel.x, (control.availableWidth - textLabel.width) / 2) + verify(iconImage.y < textLabel.y) + break; + case SwipeDelegate.TextBesideIcon: + verify(iconImage) + verify(textLabel) + if (control.mirrored) + verify(textLabel.x < iconImage.x) + else + verify(iconImage.x < textLabel.x) + compare(iconImage.y, (control.availableHeight - iconImage.height) / 2) + compare(textLabel.y, (control.availableHeight - textLabel.height) / 2) + break; + } + } } diff --git a/tests/auto/controls/data/tst_swipeview.qml b/tests/auto/controls/data/tst_swipeview.qml index ff772b74..39311877 100644 --- a/tests/auto/controls/data/tst_swipeview.qml +++ b/tests/auto/controls/data/tst_swipeview.qml @@ -539,6 +539,8 @@ TestCase { control.addItem(page.createObject(control, {text: i})) compare(control.orientation, Qt.Horizontal) + compare(control.horizontal, true) + compare(control.vertical, false) for (i = 0; i < control.count; ++i) { control.currentIndex = i @@ -547,6 +549,8 @@ TestCase { control.orientation = Qt.Vertical compare(control.orientation, Qt.Vertical) + compare(control.horizontal, false) + compare(control.vertical, true) for (i = 0; i < control.count; ++i) { control.currentIndex = i diff --git a/tests/auto/controls/data/tst_switchdelegate.qml b/tests/auto/controls/data/tst_switchdelegate.qml index f0c3e68b..8f240409 100644 --- a/tests/auto/controls/data/tst_switchdelegate.qml +++ b/tests/auto/controls/data/tst_switchdelegate.qml @@ -523,4 +523,85 @@ TestCase { compare(control.pressed, false) verify(spy.success) } + + function test_spacing() { + var control = createTemporaryObject(switchDelegate, testCase, { text: "Some long, long, long text" }) + verify(control) + verify(control.contentItem.implicitWidth + control.leftPadding + control.rightPadding > control.background.implicitWidth) + + var textLabel = findChild(control.contentItem, "label") + verify(textLabel) + + // The implicitWidth of the IconLabel that all buttons use as their contentItem should be + // equal to the implicitWidth of the Text and the switch indicator + spacing while no icon is set. + compare(control.contentItem.implicitWidth, textLabel.implicitWidth + control.indicator.width + control.spacing) + + control.spacing += 100 + compare(control.contentItem.implicitWidth, textLabel.implicitWidth + control.indicator.width + control.spacing) + + compare(control.implicitWidth, textLabel.implicitWidth + control.indicator.width + control.spacing + control.leftPadding + control.rightPadding) + } + + function test_display_data() { + return [ + { "tag": "IconOnly", display: SwitchDelegate.IconOnly }, + { "tag": "TextOnly", display: SwitchDelegate.TextOnly }, + { "tag": "TextUnderIcon", display: SwitchDelegate.TextUnderIcon }, + { "tag": "TextBesideIcon", display: SwitchDelegate.TextBesideIcon }, + { "tag": "IconOnly, mirrored", display: SwitchDelegate.IconOnly, mirrored: true }, + { "tag": "TextOnly, mirrored", display: SwitchDelegate.TextOnly, mirrored: true }, + { "tag": "TextUnderIcon, mirrored", display: SwitchDelegate.TextUnderIcon, mirrored: true }, + { "tag": "TextBesideIcon, mirrored", display: SwitchDelegate.TextBesideIcon, mirrored: true } + ] + } + + function test_display(data) { + var control = createTemporaryObject(switchDelegate, testCase, { + text: "SwitchDelegate", + display: data.display, + width: 400, + "icon.source": "qrc:/qt-project.org/imports/QtQuick/Controls.2/images/check.png", + "LayoutMirroring.enabled": !!data.mirrored + }) + verify(control) + compare(control.icon.source, "qrc:/qt-project.org/imports/QtQuick/Controls.2/images/check.png") + + var iconImage = findChild(control.contentItem, "image") + var textLabel = findChild(control.contentItem, "label") + + var availableWidth = control.availableWidth - control.indicator.width - control.spacing + var indicatorOffset = control.mirrored ? control.indicator.width + control.spacing : 0 + + switch (control.display) { + case SwitchDelegate.IconOnly: + verify(iconImage) + verify(!textLabel) + compare(iconImage.x, indicatorOffset + (availableWidth - iconImage.width) / 2) + compare(iconImage.y, (control.availableHeight - iconImage.height) / 2) + break; + case SwitchDelegate.TextOnly: + verify(!iconImage) + verify(textLabel) + compare(textLabel.x, control.mirrored ? control.availableWidth - textLabel.width : 0) + compare(textLabel.y, (control.availableHeight - textLabel.height) / 2) + break; + case SwitchDelegate.TextUnderIcon: + verify(iconImage) + verify(textLabel) + compare(iconImage.x, indicatorOffset + (availableWidth - iconImage.width) / 2) + compare(textLabel.x, indicatorOffset + (availableWidth - textLabel.width) / 2) + verify(iconImage.y < textLabel.y) + break; + case SwitchDelegate.TextBesideIcon: + verify(iconImage) + verify(textLabel) + if (control.mirrored) + verify(textLabel.x < iconImage.x) + else + verify(iconImage.x < textLabel.x) + compare(iconImage.y, (control.availableHeight - iconImage.height) / 2) + compare(textLabel.y, (control.availableHeight - textLabel.height) / 2) + break; + } + } } diff --git a/tests/auto/controls/data/tst_tabbar.qml b/tests/auto/controls/data/tst_tabbar.qml index 5bcd476b..5c9905d5 100644 --- a/tests/auto/controls/data/tst_tabbar.qml +++ b/tests/auto/controls/data/tst_tabbar.qml @@ -514,39 +514,183 @@ TestCase { var tab1 = tabButton.createObject(control, {text: "First"}) control.addItem(tab1) tryCompare(tab1, "width", control.width) + compare(tab1.height, control.height) compare(control.contentWidth, tab1.implicitWidth) + compare(control.contentHeight, tab1.implicitHeight) compare(control.implicitWidth, control.contentWidth + control.leftPadding + control.rightPadding) + compare(control.implicitHeight, control.contentHeight + control.topPadding + control.bottomPadding) - var tab2 = tabButton.createObject(control, {text: "Second"}) + var tab2 = tabButton.createObject(control, {implicitHeight: tab1.implicitHeight + 10, text: "Second"}) control.addItem(tab2) tryCompare(tab1, "width", (control.width - data.spacing) / 2) + compare(tab1.height, control.height) compare(tab2.width, (control.width - data.spacing) / 2) + compare(tab2.height, control.height) compare(control.contentWidth, tab1.implicitWidth + tab2.implicitWidth + data.spacing) + compare(control.contentHeight, tab2.implicitHeight) compare(control.implicitWidth, control.contentWidth + control.leftPadding + control.rightPadding) + compare(control.implicitHeight, control.contentHeight + control.topPadding + control.bottomPadding) - var tab3 = tabButton.createObject(control, {width: 50, text: "Third"}) + var tab3 = tabButton.createObject(control, {width: 50, height: tab1.implicitHeight - 10, text: "Third"}) control.addItem(tab3) tryCompare(tab1, "width", (control.width - 2 * data.spacing - 50) / 2) + compare(tab1.y, 0) + compare(tab1.height, control.height) + compare(tab2.y, 0) compare(tab2.width, (control.width - 2 * data.spacing - 50) / 2) + compare(tab2.height, control.height) + verify(tab3.y > 0) + compare(tab3.y, (control.height - tab3.height) / 2) compare(tab3.width, 50) + compare(tab3.height, tab1.implicitHeight - 10) compare(control.contentWidth, tab1.implicitWidth + tab2.implicitWidth + tab3.width + 2 * data.spacing) + compare(control.contentHeight, tab2.implicitHeight) compare(control.implicitWidth, control.contentWidth + control.leftPadding + control.rightPadding) + compare(control.implicitHeight, control.contentHeight + control.topPadding + control.bottomPadding) var expectedWidth = tab3.contentItem.implicitWidth + tab3.leftPadding + tab3.rightPadding tab3.width = tab3.implicitWidth + tab3.height = tab3.implicitHeight tryCompare(tab1, "width", (control.width - 2 * data.spacing - expectedWidth) / 2) - tryCompare(tab2, "width", (control.width - 2 * data.spacing - expectedWidth) / 2) + compare(tab1.height, control.height) + compare(tab2.width, (control.width - 2 * data.spacing - expectedWidth) / 2) + compare(tab2.height, control.height) compare(tab3.width, expectedWidth) + compare(tab3.height, tab3.implicitHeight) compare(control.contentWidth, tab1.implicitWidth + tab2.implicitWidth + tab3.implicitWidth + 2 * data.spacing) + compare(control.contentHeight, tab2.implicitHeight) compare(control.implicitWidth, control.contentWidth + control.leftPadding + control.rightPadding) + compare(control.implicitHeight, control.contentHeight + control.topPadding + control.bottomPadding) tab3.width = undefined + tab3.height = undefined control.width = undefined control.contentWidth = 300 + control.contentHeight = 50 expectedWidth = (control.contentWidth - 2 * data.spacing) / 3 tryCompare(tab1, "width", expectedWidth) - tryCompare(tab2, "width", expectedWidth) - tryCompare(tab3, "width", expectedWidth) + compare(tab2.width, expectedWidth) + compare(tab3.width, expectedWidth) + compare(tab1.height, control.contentHeight) + compare(tab2.height, control.contentHeight) + compare(tab3.height, control.contentHeight) + } + + Component { + id: attachedButton + TabButton { + property int index: TabBar.index + property TabBar tabBar: TabBar.tabBar + property int position: TabBar.position + } + } + + function test_attached() { + var control = createTemporaryObject(tabBar, testCase, {position: TabBar.Footer}) + + // append + var tab1 = createTemporaryObject(attachedButton, testCase) + compare(tab1.index, -1) + compare(tab1.tabBar, null) + compare(tab1.position, TabBar.Header) + + control.addItem(tab1) + compare(tab1.index, 0) + compare(tab1.tabBar, control) + compare(tab1.position, TabBar.Footer) + + // insert in the beginning + var tab2 = createTemporaryObject(attachedButton, testCase) + compare(tab2.index, -1) + compare(tab2.tabBar, null) + compare(tab2.position, TabBar.Header) + + control.insertItem(0, tab2) + compare(tab2.index, 0) + compare(tab2.tabBar, control) + compare(tab2.position, TabBar.Footer) + + compare(tab1.index, 1) + + // insert in the middle + var tab3 = createTemporaryObject(attachedButton, testCase) + compare(tab3.index, -1) + compare(tab3.tabBar, null) + compare(tab3.position, TabBar.Header) + + control.insertItem(1, tab3) + compare(tab3.index, 1) + compare(tab3.tabBar, control) + compare(tab3.position, TabBar.Footer) + + compare(tab2.index, 0) + compare(tab1.index, 2) + + // insert in the end + var tab4 = createTemporaryObject(attachedButton, testCase) + compare(tab4.index, -1) + compare(tab4.tabBar, null) + compare(tab4.position, TabBar.Header) + + control.insertItem(-1, tab4) + compare(tab4.index, 3) + compare(tab4.tabBar, control) + compare(tab4.position, TabBar.Footer) + + compare(tab2.index, 0) + compare(tab3.index, 1) + compare(tab1.index, 2) + + // move forwards + control.moveItem(0, 1) + compare(tab3.index, 0) + compare(tab2.index, 1) + compare(tab1.index, 2) + compare(tab4.index, 3) + + control.moveItem(0, 2) + compare(tab2.index, 0) + compare(tab1.index, 1) + compare(tab3.index, 2) + compare(tab4.index, 3) + + control.moveItem(1, 3) + compare(tab2.index, 0) + compare(tab3.index, 1) + compare(tab4.index, 2) + compare(tab1.index, 3) + + // move backwards + control.moveItem(3, 2) + compare(tab2.index, 0) + compare(tab3.index, 1) + compare(tab1.index, 2) + compare(tab4.index, 3) + + control.moveItem(3, 1) + compare(tab2.index, 0) + compare(tab4.index, 1) + compare(tab3.index, 2) + compare(tab1.index, 3) + + // remove from the beginning + control.removeItem(0) + compare(tab2.index, -1) + compare(tab2.tabBar, null) + compare(tab2.position, TabBar.Header) + + compare(tab4.index, 0) + compare(tab3.index, 1) + compare(tab1.index, 2) + + // remove from the middle + control.removeItem(1) + compare(tab3.index, -1) + compare(tab3.tabBar, null) + compare(tab3.position, TabBar.Header) + + compare(tab4.index, 0) + compare(tab1.index, 1) } } diff --git a/tests/auto/controls/data/tst_tabbutton.qml b/tests/auto/controls/data/tst_tabbutton.qml index 60cae927..3cb22ecd 100644 --- a/tests/auto/controls/data/tst_tabbutton.qml +++ b/tests/auto/controls/data/tst_tabbutton.qml @@ -95,4 +95,84 @@ TestCase { verify(control) compare(control.baselineOffset, control.contentItem.y + control.contentItem.baselineOffset) } + + function test_spacing() { + var control = createTemporaryObject(tabButton, testCase, { text: "Some long, long, long text" }) + verify(control) + if (control.background) + verify(control.contentItem.implicitWidth + control.leftPadding + control.rightPadding > control.background.implicitWidth) + + var textLabel = findChild(control.contentItem, "label") + verify(textLabel) + + // The implicitWidth of the IconLabel that all buttons use as their contentItem + // should be equal to the implicitWidth of the Text while no icon is set. + compare(control.contentItem.implicitWidth, textLabel.implicitWidth) + + // That means that spacing shouldn't affect it. + control.spacing += 100 + compare(control.contentItem.implicitWidth, textLabel.implicitWidth) + + // The implicitWidth of the TabButton itself should, therefore, also never include spacing while no icon is set. + compare(control.implicitWidth, textLabel.implicitWidth + control.leftPadding + control.rightPadding) + } + + function test_display_data() { + return [ + { "tag": "IconOnly", display: TabButton.IconOnly }, + { "tag": "TextOnly", display: TabButton.TextOnly }, + { "tag": "TextUnderIcon", display: TabButton.TextUnderIcon }, + { "tag": "TextBesideIcon", display: TabButton.TextBesideIcon }, + { "tag": "IconOnly, mirrored", display: TabButton.IconOnly, mirrored: true }, + { "tag": "TextOnly, mirrored", display: TabButton.TextOnly, mirrored: true }, + { "tag": "TextUnderIcon, mirrored", display: TabButton.TextUnderIcon, mirrored: true }, + { "tag": "TextBesideIcon, mirrored", display: TabButton.TextBesideIcon, mirrored: true } + ] + } + + function test_display(data) { + var control = createTemporaryObject(tabButton, testCase, { + text: "TabButton", + display: data.display, + "icon.source": "qrc:/qt-project.org/imports/QtQuick/Controls.2/images/check.png", + "LayoutMirroring.enabled": !!data.mirrored + }) + verify(control) + compare(control.icon.source, "qrc:/qt-project.org/imports/QtQuick/Controls.2/images/check.png") + + var iconImage = findChild(control.contentItem, "image") + var textLabel = findChild(control.contentItem, "label") + + switch (control.display) { + case TabButton.IconOnly: + verify(iconImage) + verify(!textLabel) + compare(iconImage.x, (control.availableWidth - iconImage.width) / 2) + compare(iconImage.y, (control.availableHeight - iconImage.height) / 2) + break; + case TabButton.TextOnly: + verify(!iconImage) + verify(textLabel) + compare(textLabel.x, (control.availableWidth - textLabel.width) / 2) + compare(textLabel.y, (control.availableHeight - textLabel.height) / 2) + break; + case TabButton.TextUnderIcon: + verify(iconImage) + verify(textLabel) + compare(iconImage.x, (control.availableWidth - iconImage.width) / 2) + compare(textLabel.x, (control.availableWidth - textLabel.width) / 2) + verify(iconImage.y < textLabel.y) + break; + case TabButton.TextBesideIcon: + verify(iconImage) + verify(textLabel) + if (control.mirrored) + verify(textLabel.x < iconImage.x) + else + verify(iconImage.x < textLabel.x) + compare(iconImage.y, (control.availableHeight - iconImage.height) / 2) + compare(textLabel.y, (control.availableHeight - textLabel.height) / 2) + break; + } + } } diff --git a/tests/auto/controls/data/tst_toolbutton.qml b/tests/auto/controls/data/tst_toolbutton.qml index 5eefaf59..9e79cb8c 100644 --- a/tests/auto/controls/data/tst_toolbutton.qml +++ b/tests/auto/controls/data/tst_toolbutton.qml @@ -181,4 +181,63 @@ TestCase { verify(control) compare(control.baselineOffset, control.contentItem.y + control.contentItem.baselineOffset) } + + function test_display_data() { + return [ + { "tag": "IconOnly", display: ToolButton.IconOnly }, + { "tag": "TextOnly", display: ToolButton.TextOnly }, + { "tag": "TextUnderIcon", display: ToolButton.TextUnderIcon }, + { "tag": "TextBesideIcon", display: ToolButton.TextBesideIcon }, + { "tag": "IconOnly, mirrored", display: ToolButton.IconOnly, mirrored: true }, + { "tag": "TextOnly, mirrored", display: ToolButton.TextOnly, mirrored: true }, + { "tag": "TextUnderIcon, mirrored", display: ToolButton.TextUnderIcon, mirrored: true }, + { "tag": "TextBesideIcon, mirrored", display: ToolButton.TextBesideIcon, mirrored: true } + ] + } + + function test_display(data) { + var control = createTemporaryObject(toolButton, testCase, { + text: "ToolButton", + display: data.display, + "icon.source": "qrc:/qt-project.org/imports/QtQuick/Controls.2/images/check.png", + "LayoutMirroring.enabled": !!data.mirrored + }) + verify(control) + compare(control.icon.source, "qrc:/qt-project.org/imports/QtQuick/Controls.2/images/check.png") + + var iconImage = findChild(control.contentItem, "image") + var textLabel = findChild(control.contentItem, "label") + + switch (control.display) { + case ToolButton.IconOnly: + verify(iconImage) + verify(!textLabel) + compare(iconImage.x, (control.availableWidth - iconImage.width) / 2) + compare(iconImage.y, (control.availableHeight - iconImage.height) / 2) + break; + case ToolButton.TextOnly: + verify(!iconImage) + verify(textLabel) + compare(textLabel.x, (control.availableWidth - textLabel.width) / 2) + compare(textLabel.y, (control.availableHeight - textLabel.height) / 2) + break; + case ToolButton.TextUnderIcon: + verify(iconImage) + verify(textLabel) + compare(iconImage.x, (control.availableWidth - iconImage.width) / 2) + compare(textLabel.x, (control.availableWidth - textLabel.width) / 2) + verify(iconImage.y < textLabel.y) + break; + case ToolButton.TextBesideIcon: + verify(iconImage) + verify(textLabel) + if (control.mirrored) + verify(textLabel.x < iconImage.x) + else + verify(iconImage.x < textLabel.x) + compare(iconImage.y, (control.availableHeight - iconImage.height) / 2) + compare(textLabel.y, (control.availableHeight - textLabel.height) / 2) + break; + } + } } diff --git a/tests/auto/controls/fusion/dependencies.qml b/tests/auto/controls/fusion/dependencies.qml new file mode 100644 index 00000000..30c32fa5 --- /dev/null +++ b/tests/auto/controls/fusion/dependencies.qml @@ -0,0 +1,6 @@ +import QtTest 1.0 +import QtQuick 2.10 +import QtQuick.Controls 2.3 +import QtQuick.Controls.Fusion 2.3 + +TestCase { } diff --git a/tests/auto/controls/fusion/fusion.pro b/tests/auto/controls/fusion/fusion.pro new file mode 100644 index 00000000..f3374f34 --- /dev/null +++ b/tests/auto/controls/fusion/fusion.pro @@ -0,0 +1,15 @@ +TEMPLATE = app +TARGET = tst_fusion +CONFIG += qmltestcase +QT += quickcontrols2 + +DEFINES += TST_CONTROLS_DATA=\\\"$$QQC2_SOURCE_TREE/tests/auto/controls/data\\\" + +SOURCES += \ + $$PWD/tst_fusion.cpp + +OTHER_FILES += \ + $$PWD/../data/*.qml + +TESTDATA += \ + $$PWD/../data/tst_* diff --git a/tests/auto/controls/fusion/tst_fusion.cpp b/tests/auto/controls/fusion/tst_fusion.cpp new file mode 100644 index 00000000..84f9c231 --- /dev/null +++ b/tests/auto/controls/fusion/tst_fusion.cpp @@ -0,0 +1,47 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 <QtQuickTest/quicktest.h> +#include <QtQuickControls2/qquickstyle.h> + +int main(int argc, char *argv[]) +{ + QTEST_ADD_GPU_BLACKLIST_SUPPORT + QTEST_SET_MAIN_SOURCE_PATH + qputenv("QML_NO_TOUCH_COMPRESSION", "1"); + QQuickStyle::setStyle("Fusion"); + return quick_test_main(argc, argv, "tst_controls::Fusion", TST_CONTROLS_DATA); +} diff --git a/tests/auto/menu/data/actions.qml b/tests/auto/menu/data/actions.qml new file mode 100644 index 00000000..7cb1215c --- /dev/null +++ b/tests/auto/menu/data/actions.qml @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.9 +import QtQuick.Controls 2.3 + +ApplicationWindow { + width: 400 + height: 400 + + property alias menu: menu + + Menu { + id: menu + Action { text: "action1" } + MenuItem { text: "menuitem2" } + Action { text: "action3" } + MenuItem { text: "menuitem4" } + } +} diff --git a/tests/auto/menu/data/popup.qml b/tests/auto/menu/data/popup.qml new file mode 100644 index 00000000..4e21bf1f --- /dev/null +++ b/tests/auto/menu/data/popup.qml @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.9 +import QtQuick.Controls 2.3 + +ApplicationWindow { + width: 400 + height: 400 + + property alias menu: menu + property alias menuItem1: menuItem1 + property alias menuItem2: menuItem2 + property alias menuItem3: menuItem3 + + function popupAtCursor() { + menu.popup() + } + + function popupAtPos(pos) { + menu.popup(pos) + } + + function popupAtCoord(x, y) { + menu.popup(x, y) + } + + function popupItemAtCursor(item) { + menu.popup(item) + } + + function popupItemAtPos(pos, item) { + menu.popup(pos, item) + } + + function popupItemAtCoord(x, y, item) { + menu.popup(x, y, item) + } + + Menu { + id: menu + MenuItem { id: menuItem1; text: "Foo" } + MenuItem { id: menuItem2; text: "Bar" } + MenuItem { id: menuItem3; text: "Baz" } + } +} diff --git a/tests/auto/menu/data/removeTakeItem.qml b/tests/auto/menu/data/removeTakeItem.qml new file mode 100644 index 00000000..9a2914ed --- /dev/null +++ b/tests/auto/menu/data/removeTakeItem.qml @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.9 +import QtQuick.Controls 2.3 + +ApplicationWindow { + width: 200 + height: 200 + + property alias menu: menu + property alias menuItem1: menuItem1 + property alias menuItem2: menuItem2 + property alias menuItem3: menuItem3 + + function takeSecondItem() { + return menu.takeItem(1) + } + + function removeFirstItem() { + menu.removeItem(menuItem1) + } + + function removeNullItem() { + menu.removeItem(null) + } + + function removeFirstIndex() { + menu.removeItem(0) + } + + Menu { + id: menu + MenuItem { + id: menuItem1 + } + MenuItem { + id: menuItem2 + } + MenuItem { + id: menuItem3 + } + } +} diff --git a/tests/auto/menu/tst_menu.cpp b/tests/auto/menu/tst_menu.cpp index 1e6eaceb..8f4792ae 100644 --- a/tests/auto/menu/tst_menu.cpp +++ b/tests/auto/menu/tst_menu.cpp @@ -36,6 +36,7 @@ #include <qtest.h> #include <QtTest/QSignalSpy> +#include <QtGui/qcursor.h> #include <QtGui/qstylehints.h> #include <QtQml/qqmlengine.h> #include <QtQml/qqmlcomponent.h> @@ -69,6 +70,9 @@ private slots: void menuSeparator(); void repeater(); void order(); + void popup(); + void actions(); + void removeTakeItem(); }; void tst_menu::defaults() @@ -384,6 +388,149 @@ void tst_menu::order() } } +void tst_menu::popup() +{ + QQuickApplicationHelper helper(this, QLatin1String("popup.qml")); + QQuickWindow *window = helper.window; + window->show(); + QVERIFY(QTest::qWaitForWindowActive(window)); + + QQuickMenu *menu = window->property("menu").value<QQuickMenu *>(); + QVERIFY(menu); + + QQuickMenuItem *menuItem1 = window->property("menuItem1").value<QQuickMenuItem *>(); + QVERIFY(menuItem1); + + QQuickMenuItem *menuItem2 = window->property("menuItem2").value<QQuickMenuItem *>(); + QVERIFY(menuItem2); + + QQuickMenuItem *menuItem3 = window->property("menuItem3").value<QQuickMenuItem *>(); + QVERIFY(menuItem3); + +#if QT_CONFIG(cursor) + QPoint cursorPos = window->mapToGlobal(QPoint(11, 22)); + QCursor::setPos(cursorPos); + QTRY_COMPARE(QCursor::pos(), cursorPos); + + QVERIFY(QMetaObject::invokeMethod(window, "popupAtCursor")); + QTRY_COMPARE(menu->property("x").toInt(), 11); + QTRY_COMPARE(menu->property("y").toInt(), 22); + menu->close(); + + QVERIFY(QMetaObject::invokeMethod(window, "popupAtPos", Q_ARG(QVariant, QPointF(33, 44)))); + QTRY_COMPARE(menu->property("x").toInt(), 33); + QTRY_COMPARE(menu->property("y").toInt(), 44); + menu->close(); + + QVERIFY(QMetaObject::invokeMethod(window, "popupAtCoord", Q_ARG(QVariant, 55), Q_ARG(QVariant, 66))); + QTRY_COMPARE(menu->property("x").toInt(), 55); + QTRY_COMPARE(menu->property("y").toInt(), 66); + menu->close(); + + cursorPos = window->mapToGlobal(QPoint(12, window->height() / 2)); + QCursor::setPos(cursorPos); + QTRY_COMPARE(QCursor::pos(), cursorPos); + + const QList<QQuickMenuItem *> menuItems = QList<QQuickMenuItem *>() << menuItem1 << menuItem2 << menuItem3; + for (QQuickMenuItem *menuItem : menuItems) { + QVERIFY(QMetaObject::invokeMethod(window, "popupItemAtCursor", Q_ARG(QVariant, QVariant::fromValue(menuItem)))); + QTRY_COMPARE(menu->property("x").toInt(), 12); + QTRY_COMPARE(menu->property("y").toInt(), window->height() / 2 + menu->topPadding() - menuItem->y()); + menu->close(); + + QVERIFY(QMetaObject::invokeMethod(window, "popupItemAtPos", Q_ARG(QVariant, QPointF(33, window->height() / 3)), Q_ARG(QVariant, QVariant::fromValue(menuItem)))); + QTRY_COMPARE(menu->property("x").toInt(), 33); + QTRY_COMPARE(menu->property("y").toInt(), window->height() / 3 + menu->topPadding() - menuItem->y()); + menu->close(); + + QVERIFY(QMetaObject::invokeMethod(window, "popupItemAtCoord", Q_ARG(QVariant, 55), Q_ARG(QVariant, window->height() / 3 * 2), Q_ARG(QVariant, QVariant::fromValue(menuItem)))); + QTRY_COMPARE(menu->property("x").toInt(), 55); + QTRY_COMPARE(menu->property("y").toInt(), window->height() / 3 * 2 + menu->topPadding() - menuItem->y()); + menu->close(); + } +#endif +} + +void tst_menu::actions() +{ + QQuickApplicationHelper helper(this, QLatin1String("actions.qml")); + QQuickWindow *window = helper.window; + window->show(); + QVERIFY(QTest::qWaitForWindowActive(window)); + + QQuickMenu *menu = window->property("menu").value<QQuickMenu *>(); + QVERIFY(menu); + + QQuickMenuItem *menuItem1 = qobject_cast<QQuickMenuItem *>(menu->itemAt(0)); + QVERIFY(menuItem1); + QVERIFY(menuItem1->action()); + QCOMPARE(menuItem1->text(), "action1"); + + QQuickMenuItem *menuItem2 = qobject_cast<QQuickMenuItem *>(menu->itemAt(1)); + QVERIFY(menuItem2); + QVERIFY(!menuItem2->action()); + QCOMPARE(menuItem2->text(), "menuitem2"); + + QQuickMenuItem *menuItem3 = qobject_cast<QQuickMenuItem *>(menu->itemAt(2)); + QVERIFY(menuItem3); + QVERIFY(menuItem3->action()); + QCOMPARE(menuItem3->text(), "action3"); + + QQuickMenuItem *menuItem4 = qobject_cast<QQuickMenuItem *>(menu->itemAt(3)); + QVERIFY(menuItem4); + QVERIFY(!menuItem4->action()); + QCOMPARE(menuItem4->text(), "menuitem4"); +} + +void tst_menu::removeTakeItem() +{ + QQuickApplicationHelper helper(this, QLatin1String("removeTakeItem.qml")); + QQuickWindow *window = helper.window; + window->show(); + QVERIFY(QTest::qWaitForWindowActive(window)); + + QQuickMenu *menu = window->property("menu").value<QQuickMenu *>(); + QVERIFY(menu); + + QPointer<QQuickMenuItem> menuItem1 = window->property("menuItem1").value<QQuickMenuItem *>(); + QVERIFY(!menuItem1.isNull()); + QCOMPARE(menuItem1->menu(), menu); + + QPointer<QQuickMenuItem> menuItem2 = window->property("menuItem2").value<QQuickMenuItem *>(); + QVERIFY(!menuItem2.isNull()); + QCOMPARE(menuItem2->menu(), menu); + + QPointer<QQuickMenuItem> menuItem3 = window->property("menuItem3").value<QQuickMenuItem *>(); + QVERIFY(!menuItem3.isNull()); + QCOMPARE(menuItem3->menu(), menu); + + // takeItem(int) does not destroy + QVariant ret; + QVERIFY(QMetaObject::invokeMethod(window, "takeSecondItem", Q_RETURN_ARG(QVariant, ret))); + QCOMPARE(ret.value<QQuickMenuItem *>(), menuItem2); + QVERIFY(!menuItem2->menu()); + QCoreApplication::sendPostedEvents(menuItem2, QEvent::DeferredDelete); + QVERIFY(!menuItem2.isNull()); + + // removeItem(Item) destroys + QVERIFY(QMetaObject::invokeMethod(window, "removeFirstItem")); + QVERIFY(!menuItem1->menu()); + QCoreApplication::sendPostedEvents(menuItem1, QEvent::DeferredDelete); + QVERIFY(menuItem1.isNull()); + + // removeItem(null) must not call removeItem(0) + QVERIFY(QMetaObject::invokeMethod(window, "removeNullItem")); + QCOMPARE(menuItem3->menu(), menu); + QCoreApplication::sendPostedEvents(menuItem3, QEvent::DeferredDelete); + QVERIFY(!menuItem3.isNull()); + + // deprecated removeItem(int) does not destroy + QVERIFY(QMetaObject::invokeMethod(window, "removeFirstIndex")); + QVERIFY(!menuItem3->menu()); + QCoreApplication::sendPostedEvents(menuItem3, QEvent::DeferredDelete); + QVERIFY(!menuItem3.isNull()); +} + QTEST_MAIN(tst_menu) #include "tst_menu.moc" diff --git a/tests/auto/palette/data/inheritance-control.qml b/tests/auto/palette/data/inheritance-control.qml new file mode 100644 index 00000000..860d9b0c --- /dev/null +++ b/tests/auto/palette/data/inheritance-control.qml @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.9 +import QtQuick.Controls 2.3 + +ApplicationWindow { + id: window + + property alias control: control + property alias child: child + property alias grandChild: grandChild + + Control { + id: control + + Control { + id: child + + Item { + Control { + id: grandChild + } + } + } + } +} diff --git a/tests/auto/palette/data/inheritance-popup.qml b/tests/auto/palette/data/inheritance-popup.qml new file mode 100644 index 00000000..aceff6f2 --- /dev/null +++ b/tests/auto/palette/data/inheritance-popup.qml @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.9 +import QtQuick.Controls 2.3 + +ApplicationWindow { + id: window + + property alias control: control + property alias child: child + property alias grandChild: grandChild + + Popup { + id: control + + Control { + id: child + + Item { + Control { + id: grandChild + } + } + } + } +} diff --git a/tests/auto/palette/data/palette-appwindow-custom.qml b/tests/auto/palette/data/palette-appwindow-custom.qml new file mode 100644 index 00000000..90b07605 --- /dev/null +++ b/tests/auto/palette/data/palette-appwindow-custom.qml @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.9 +import QtQuick.Controls 2.3 + +ApplicationWindow { + palette.alternateBase: "aqua" + palette.base: "azure" + palette.brightText: "beige" + palette.button: "bisque" + palette.buttonText: "chocolate" + palette.dark: "coral" + palette.highlight: "crimson" + palette.highlightedText: "fuchsia" + palette.light: "gold" + palette.link: "indigo" + palette.linkVisited: "ivory" + palette.mid: "khaki" + palette.midlight: "lavender" + palette.shadow: "linen" + palette.text: "moccasin" + palette.toolTipBase: "navy" + palette.toolTipText: "orchid" + palette.window: "plum" + palette.windowText: "salmon" +} diff --git a/tests/auto/palette/data/palette-appwindow-default.qml b/tests/auto/palette/data/palette-appwindow-default.qml new file mode 100644 index 00000000..97376690 --- /dev/null +++ b/tests/auto/palette/data/palette-appwindow-default.qml @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.9 +import QtQuick.Controls 2.3 + +ApplicationWindow { +} diff --git a/tests/auto/palette/data/palette-control-custom.qml b/tests/auto/palette/data/palette-control-custom.qml new file mode 100644 index 00000000..eeefec3d --- /dev/null +++ b/tests/auto/palette/data/palette-control-custom.qml @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.9 +import QtQuick.Controls 2.3 + +Control { + palette.alternateBase: "aqua" + palette.base: "azure" + palette.brightText: "beige" + palette.button: "bisque" + palette.buttonText: "chocolate" + palette.dark: "coral" + palette.highlight: "crimson" + palette.highlightedText: "fuchsia" + palette.light: "gold" + palette.link: "indigo" + palette.linkVisited: "ivory" + palette.mid: "khaki" + palette.midlight: "lavender" + palette.shadow: "linen" + palette.text: "moccasin" + palette.toolTipBase: "navy" + palette.toolTipText: "orchid" + palette.window: "plum" + palette.windowText: "salmon" +} diff --git a/tests/auto/palette/data/palette-control-default.qml b/tests/auto/palette/data/palette-control-default.qml new file mode 100644 index 00000000..91f38843 --- /dev/null +++ b/tests/auto/palette/data/palette-control-default.qml @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.9 +import QtQuick.Controls 2.3 + +Control { +} diff --git a/tests/auto/palette/data/palette-popup-custom.qml b/tests/auto/palette/data/palette-popup-custom.qml new file mode 100644 index 00000000..55b24fc9 --- /dev/null +++ b/tests/auto/palette/data/palette-popup-custom.qml @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.9 +import QtQuick.Controls 2.3 + +Popup { + palette.alternateBase: "aqua" + palette.base: "azure" + palette.brightText: "beige" + palette.button: "bisque" + palette.buttonText: "chocolate" + palette.dark: "coral" + palette.highlight: "crimson" + palette.highlightedText: "fuchsia" + palette.light: "gold" + palette.link: "indigo" + palette.linkVisited: "ivory" + palette.mid: "khaki" + palette.midlight: "lavender" + palette.shadow: "linen" + palette.text: "moccasin" + palette.toolTipBase: "navy" + palette.toolTipText: "orchid" + palette.window: "plum" + palette.windowText: "salmon" +} diff --git a/tests/auto/palette/data/palette-popup-default.qml b/tests/auto/palette/data/palette-popup-default.qml new file mode 100644 index 00000000..6cff3efd --- /dev/null +++ b/tests/auto/palette/data/palette-popup-default.qml @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.9 +import QtQuick.Controls 2.3 + +Popup { +} diff --git a/tests/auto/palette/palette.pro b/tests/auto/palette/palette.pro new file mode 100644 index 00000000..c7d55d07 --- /dev/null +++ b/tests/auto/palette/palette.pro @@ -0,0 +1,16 @@ +CONFIG += testcase +TARGET = tst_palette +SOURCES += tst_palette.cpp + +macos:CONFIG -= app_bundle + +QT += core-private gui-private qml-private quick-private testlib quicktemplates2-private quickcontrols2-private + +include (../shared/util.pri) + +RESOURCES += qtquickcontrols2.conf + +TESTDATA = data/* + +OTHER_FILES += \ + data/*.qml diff --git a/tests/auto/palette/qtquickcontrols2.conf b/tests/auto/palette/qtquickcontrols2.conf new file mode 100644 index 00000000..2ffc7ecc --- /dev/null +++ b/tests/auto/palette/qtquickcontrols2.conf @@ -0,0 +1,5 @@ +[Default] +Palette\Base=#efefef + +[Default\Palette] +Text=#101010 diff --git a/tests/auto/palette/tst_palette.cpp b/tests/auto/palette/tst_palette.cpp new file mode 100644 index 00000000..2d125725 --- /dev/null +++ b/tests/auto/palette/tst_palette.cpp @@ -0,0 +1,340 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 "../shared/visualtestutil.h" + +#include <QtGui/qpalette.h> +#include <QtGui/qpa/qplatformtheme.h> +#include <QtGui/private/qguiapplication_p.h> +#include <QtQml/qqmlengine.h> +#include <QtQml/qqmlcomponent.h> +#include <QtQuickTemplates2/private/qquickapplicationwindow_p.h> +#include <QtQuickTemplates2/private/qquickcontrol_p.h> +#include <QtQuickTemplates2/private/qquickpopup_p.h> +#include <QtQuickControls2/private/qquickproxytheme_p.h> + +using namespace QQuickVisualTestUtil; + +class tst_palette : public QQmlDataTest +{ + Q_OBJECT + +private slots: + void palette_data(); + void palette(); + + void inheritance_data(); + void inheritance(); + + void defaultPalette_data(); + void defaultPalette(); +}; + +void tst_palette::palette_data() +{ + QTest::addColumn<QString>("testFile"); + QTest::addColumn<QPalette>("expectedPalette"); + + QPalette defaultPalette; + defaultPalette.setColor(QPalette::Base, QColor("#efefef")); + defaultPalette.setColor(QPalette::Text, QColor("#101010")); + + QTest::newRow("Control") << "palette-control-default.qml" << defaultPalette; + QTest::newRow("AppWindow") << "palette-appwindow-default.qml" << defaultPalette; + QTest::newRow("Popup") << "palette-popup-default.qml" << defaultPalette; + + QPalette customPalette; + customPalette.setColor(QPalette::AlternateBase, QColor("aqua")); + customPalette.setColor(QPalette::Base, QColor("azure")); + customPalette.setColor(QPalette::BrightText, QColor("beige")); + customPalette.setColor(QPalette::Button, QColor("bisque")); + customPalette.setColor(QPalette::ButtonText, QColor("chocolate")); + customPalette.setColor(QPalette::Dark, QColor("coral")); + customPalette.setColor(QPalette::Highlight, QColor("crimson")); + customPalette.setColor(QPalette::HighlightedText, QColor("fuchsia")); + customPalette.setColor(QPalette::Light, QColor("gold")); + customPalette.setColor(QPalette::Link, QColor("indigo")); + customPalette.setColor(QPalette::LinkVisited, QColor("ivory")); + customPalette.setColor(QPalette::Mid, QColor("khaki")); + customPalette.setColor(QPalette::Midlight, QColor("lavender")); + customPalette.setColor(QPalette::Shadow, QColor("linen")); + customPalette.setColor(QPalette::Text, QColor("moccasin")); + customPalette.setColor(QPalette::ToolTipBase, QColor("navy")); + customPalette.setColor(QPalette::ToolTipText, QColor("orchid")); + customPalette.setColor(QPalette::Window, QColor("plum")); + customPalette.setColor(QPalette::WindowText, QColor("salmon")); + + QTest::newRow("Control:custom") << "palette-control-custom.qml" << customPalette; + QTest::newRow("AppWindow:custom") << "palette-appwindow-custom.qml" << customPalette; + QTest::newRow("Popup:custom") << "palette-popup-custom.qml" << customPalette; +} + +void tst_palette::palette() +{ + QFETCH(QString, testFile); + QFETCH(QPalette, expectedPalette); + + QQmlEngine engine; + QQmlComponent component(&engine); + component.loadUrl(testFileUrl(testFile)); + + QScopedPointer<QObject> object(component.create()); + QVERIFY2(!object.isNull(), qPrintable(component.errorString())); + + QVariant var = object->property("palette"); + QVERIFY(var.isValid()); + + QPalette actualPalette = var.value<QPalette>(); + QCOMPARE(actualPalette, expectedPalette); +} + +void tst_palette::inheritance_data() +{ + QTest::addColumn<QString>("testFile"); + + QTest::newRow("Control") << "inheritance-control.qml"; + QTest::newRow("Popup") << "inheritance-popup.qml"; +} + +void tst_palette::inheritance() +{ + QFETCH(QString, testFile); + + QQmlEngine engine; + QQmlComponent component(&engine); + component.loadUrl(testFileUrl(testFile)); + + QScopedPointer<QQuickApplicationWindow> window(qobject_cast<QQuickApplicationWindow *>(component.create())); + QVERIFY2(!window.isNull(), qPrintable(component.errorString())); + + QObject *control = window->property("control").value<QObject *>(); + QObject *child = window->property("child").value<QObject *>(); + QObject *grandChild = window->property("grandChild").value<QObject *>(); + QVERIFY(control && child && grandChild); + + QPalette defaultPalette; + defaultPalette.setColor(QPalette::Base, QColor("#efefef")); + defaultPalette.setColor(QPalette::Text, QColor("#101010")); + + QCOMPARE(window->palette(), defaultPalette); + + QCOMPARE(control->property("palette").value<QPalette>(), defaultPalette); + QCOMPARE(child->property("palette").value<QPalette>(), defaultPalette); + QCOMPARE(grandChild->property("palette").value<QPalette>(), defaultPalette); + + QPalette childPalette(defaultPalette); + childPalette.setColor(QPalette::Base, Qt::red); + childPalette.setColor(QPalette::Text, Qt::green); + childPalette.setColor(QPalette::Button, Qt::blue); + child->setProperty("palette", childPalette); + QCOMPARE(child->property("palette").value<QPalette>(), childPalette); + QCOMPARE(grandChild->property("palette").value<QPalette>(), childPalette); + + QPalette grandChildPalette(childPalette); + grandChildPalette.setColor(QPalette::Base, Qt::cyan); + grandChildPalette.setColor(QPalette::Mid, Qt::magenta); + grandChild->setProperty("palette", grandChildPalette); + QCOMPARE(child->property("palette").value<QPalette>(), childPalette); + QCOMPARE(grandChild->property("palette").value<QPalette>(), grandChildPalette); + + QPalette windowPalette(defaultPalette); + windowPalette.setColor(QPalette::Window, Qt::gray); + window->setPalette(windowPalette); + QCOMPARE(window->palette(), windowPalette); + QCOMPARE(control->property("palette").value<QPalette>(), windowPalette); + + childPalette.setColor(QPalette::Window, Qt::gray); + QCOMPARE(child->property("palette").value<QPalette>(), childPalette); + + grandChildPalette.setColor(QPalette::Window, Qt::gray); + QCOMPARE(grandChild->property("palette").value<QPalette>(), grandChildPalette); + + child->setProperty("palette", QVariant()); + QCOMPARE(child->property("palette").value<QPalette>(), windowPalette); + QCOMPARE(grandChild->property("palette").value<QPalette>(), grandChildPalette); + + grandChild->setProperty("palette", QVariant()); + QCOMPARE(grandChild->property("palette").value<QPalette>(), windowPalette); +} + +class TestTheme : public QQuickProxyTheme +{ +public: + TestTheme(QPlatformTheme *theme) : QQuickProxyTheme(theme) + { + std::fill(palettes, palettes + QPlatformTheme::NPalettes, static_cast<QPalette *>(0)); + + QPalette palette = QPalette(); + palette.setColor(QPalette::Window, Qt::gray); + palettes[QPlatformTheme::SystemPalette] = new QPalette(palette); + + palette.setColor(QPalette::ToolTipBase, Qt::yellow); + palettes[QPlatformTheme::ToolTipPalette] = new QPalette(palette); + + palette.setColor(QPalette::ButtonText, Qt::blue); + palettes[QPlatformTheme::ToolButtonPalette] = new QPalette(palette); + + palette.setColor(QPalette::Button, Qt::red); + palettes[QPlatformTheme::ButtonPalette] = new QPalette(palette); + + palette.setColor(QPalette::Text, Qt::green); + palettes[QPlatformTheme::CheckBoxPalette] = new QPalette(palette); + + palette.setColor(QPalette::Text, Qt::blue); + palettes[QPlatformTheme::RadioButtonPalette] = new QPalette(palette); + + // HeaderPalette unused + + palette.setColor(QPalette::Base, Qt::darkGray); + palettes[QPlatformTheme::ComboBoxPalette] = new QPalette(palette); + + palette.setColor(QPalette::Base, Qt::lightGray); + palettes[QPlatformTheme::ItemViewPalette] = new QPalette(palette); + + // MessageBoxLabelPalette unused + + palette.setColor(QPalette::ButtonText, Qt::white); + palettes[QPlatformTheme::TabBarPalette] = new QPalette(palette); + + palette.setColor(QPalette::WindowText, Qt::darkGray); + palettes[QPlatformTheme::LabelPalette] = new QPalette(palette); + + palette.setColor(QPalette::Mid, Qt::gray); + palettes[QPlatformTheme::GroupBoxPalette] = new QPalette(palette); + + palette.setColor(QPalette::Shadow, Qt::darkYellow); + palettes[QPlatformTheme::MenuPalette] = new QPalette(palette); + + // MenuBarPalette unused + + palette.setColor(QPalette::Base, Qt::cyan); + palettes[QPlatformTheme::TextEditPalette] = new QPalette(palette); + + palette.setColor(QPalette::Base, Qt::magenta); + palettes[QPlatformTheme::TextLineEditPalette] = new QPalette(palette); + + QGuiApplicationPrivate::platform_theme = this; + } + + const QPalette *palette(Palette type = SystemPalette) const override + { + return palettes[type]; + } + +private: + QPalette *palettes[QPlatformTheme::NPalettes]; +}; + +Q_DECLARE_METATYPE(QPlatformTheme::Palette) + +void tst_palette::defaultPalette_data() +{ + QTest::addColumn<QString>("control"); + QTest::addColumn<QPlatformTheme::Palette>("paletteType"); + + QTest::newRow("AbstractButton") << "AbstractButton" << QPlatformTheme::SystemPalette; + QTest::newRow("ApplicationWindow") << "ApplicationWindow" << QPlatformTheme::SystemPalette; + QTest::newRow("Button") << "Button" << QPlatformTheme::ButtonPalette; + QTest::newRow("CheckBox") << "CheckBox" << QPlatformTheme::CheckBoxPalette; + QTest::newRow("CheckDelegate") << "CheckDelegate" << QPlatformTheme::ItemViewPalette; + QTest::newRow("ComboBox") << "ComboBox" << QPlatformTheme::ComboBoxPalette; + QTest::newRow("Container") << "Container" << QPlatformTheme::SystemPalette; + QTest::newRow("Control") << "Control" << QPlatformTheme::SystemPalette; + QTest::newRow("Dial") << "Dial" << QPlatformTheme::SystemPalette; + QTest::newRow("Dialog") << "Dialog" << QPlatformTheme::SystemPalette; + QTest::newRow("DialogButtonBox") << "DialogButtonBox" << QPlatformTheme::SystemPalette; + QTest::newRow("Drawer") << "Drawer" << QPlatformTheme::SystemPalette; + QTest::newRow("Frame") << "Frame" << QPlatformTheme::SystemPalette; + QTest::newRow("GroupBox") << "GroupBox" << QPlatformTheme::GroupBoxPalette; + QTest::newRow("ItemDelegate") << "ItemDelegate" << QPlatformTheme::ItemViewPalette; + QTest::newRow("Label") << "Label" << QPlatformTheme::LabelPalette; + QTest::newRow("Menu") << "Menu" << QPlatformTheme::MenuPalette; + QTest::newRow("MenuItem") << "MenuItem" << QPlatformTheme::MenuPalette; + QTest::newRow("MenuSeparator") << "MenuSeparator" << QPlatformTheme::MenuPalette; + QTest::newRow("Page") << "Page" << QPlatformTheme::SystemPalette; + QTest::newRow("Pane") << "Pane" << QPlatformTheme::SystemPalette; + QTest::newRow("Popup") << "Popup" << QPlatformTheme::SystemPalette; + QTest::newRow("ProgressBar") << "ProgressBar" << QPlatformTheme::SystemPalette; + QTest::newRow("RadioButton") << "RadioButton" << QPlatformTheme::RadioButtonPalette; + QTest::newRow("RadioDelegate") << "RadioDelegate" << QPlatformTheme::ItemViewPalette; + QTest::newRow("RangeSlider") << "RangeSlider" << QPlatformTheme::SystemPalette; + QTest::newRow("RoundButton") << "RoundButton" << QPlatformTheme::ButtonPalette; + QTest::newRow("ScrollBar") << "ScrollBar" << QPlatformTheme::SystemPalette; + QTest::newRow("ScrollIndicator") << "ScrollIndicator" << QPlatformTheme::SystemPalette; + QTest::newRow("Slider") << "Slider" << QPlatformTheme::SystemPalette; + QTest::newRow("SpinBox") << "SpinBox" << QPlatformTheme::TextLineEditPalette; + QTest::newRow("SwipeDelegate") << "SwipeDelegate" << QPlatformTheme::ItemViewPalette; + QTest::newRow("Switch") << "Switch" << QPlatformTheme::CheckBoxPalette; // ### TODO: add QPlatformTheme::SwitchPalette + QTest::newRow("SwitchDelegate") << "SwitchDelegate" << QPlatformTheme::ItemViewPalette; + QTest::newRow("TabBar") << "TabBar" << QPlatformTheme::TabBarPalette; + QTest::newRow("TabButton") << "TabButton" << QPlatformTheme::TabBarPalette; + QTest::newRow("TextArea") << "TextArea" << QPlatformTheme::TextEditPalette; + QTest::newRow("TextField") << "TextField" << QPlatformTheme::TextLineEditPalette; + QTest::newRow("ToolBar") << "ToolBar" << QPlatformTheme::ToolButtonPalette; + QTest::newRow("ToolButton") << "ToolButton" << QPlatformTheme::ToolButtonPalette; + QTest::newRow("ToolSeparator") << "ToolSeparator" << QPlatformTheme::ToolButtonPalette; + QTest::newRow("ToolTip") << "ToolTip" << QPlatformTheme::ToolTipPalette; + QTest::newRow("Tumbler") << "Tumbler" << QPlatformTheme::SystemPalette; +} + +void tst_palette::defaultPalette() +{ + QFETCH(QString, control); + QFETCH(QPlatformTheme::Palette, paletteType); + + TestTheme theme(QGuiApplicationPrivate::platform_theme); + + QQmlEngine engine; + QQmlComponent component(&engine); + component.setData(QString("import QtQuick.Controls 2.3; %1 { }").arg(control).toUtf8(), QUrl()); + + QScopedPointer<QObject> object(component.create()); + QVERIFY2(!object.isNull(), qPrintable(component.errorString())); + + QVariant var = object->property("palette"); + QVERIFY(var.isValid()); + + const QPalette *expectedPalette = theme.palette(paletteType); + QVERIFY(expectedPalette); + + QPalette actualPalette = var.value<QPalette>(); + QCOMPARE(actualPalette, *expectedPalette); +} + +QTEST_MAIN(tst_palette) + +#include "tst_palette.moc" diff --git a/tests/auto/qquickcolor/data/tst_color.qml b/tests/auto/qquickcolor/data/tst_color.qml new file mode 100644 index 00000000..ab398ea4 --- /dev/null +++ b/tests/auto/qquickcolor/data/tst_color.qml @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.9 +import QtTest 1.0 +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 + +TestCase { + id: testCase + name: "Color" + + function test_transparent() { + compare(Color.transparent("red", 0.2), Qt.rgba(1, 0, 0, 0.2)) + compare(Color.transparent(Qt.rgba(0, 1, 0, 1), 0.2), Qt.rgba(0, 1, 0, 0.2)) + compare(Color.transparent("#0000ff", 0.2), Qt.rgba(0, 0, 1, 0.2)) + } +} diff --git a/tests/auto/qquickcolor/qquickcolor.pro b/tests/auto/qquickcolor/qquickcolor.pro new file mode 100644 index 00000000..af562df1 --- /dev/null +++ b/tests/auto/qquickcolor/qquickcolor.pro @@ -0,0 +1,12 @@ +TEMPLATE = app +TARGET = tst_qquickcolor +CONFIG += qmltestcase + +SOURCES += \ + $$PWD/tst_qquickcolor.cpp + +OTHER_FILES += \ + $$PWD/data/*.qml + +TESTDATA += \ + $$PWD/data/tst_* diff --git a/tests/auto/qquickcolor/tst_qquickcolor.cpp b/tests/auto/qquickcolor/tst_qquickcolor.cpp new file mode 100644 index 00000000..94c60080 --- /dev/null +++ b/tests/auto/qquickcolor/tst_qquickcolor.cpp @@ -0,0 +1,38 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 <QtQuickTest/quicktest.h> +QUICK_TEST_MAIN(tst_qquickcolor) diff --git a/tests/auto/qquickiconimage/data/alignment.qml b/tests/auto/qquickiconimage/data/alignment.qml new file mode 100644 index 00000000..e3ed3857 --- /dev/null +++ b/tests/auto/qquickiconimage/data/alignment.qml @@ -0,0 +1,16 @@ +import QtQuick 2.9 +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 + +Row { + width: 200 + height: 200 + + IconImage { + name: "appointment-new" + sourceSize: Qt.size(22, 22) + } + Image { + source: "qrc:/icons/testtheme/22x22/actions/appointment-new.png" + } +} diff --git a/tests/auto/qquickiconimage/data/color.qml b/tests/auto/qquickiconimage/data/color.qml new file mode 100644 index 00000000..39d94259 --- /dev/null +++ b/tests/auto/qquickiconimage/data/color.qml @@ -0,0 +1,18 @@ +import QtQuick 2.9 +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 + +Row { + width: 200 + height: 200 + + IconImage { + source: "qrc:/icons/testtheme/22x22/actions/color-test-original.png" + sourceSize: Qt.size(22, 22) + color: "red" + } + Image { + source: "qrc:/icons/testtheme/22x22/actions/color-test-tinted.png" + fillMode: Image.Pad + } +} diff --git a/tests/auto/qquickiconimage/data/fileSelectors.qml b/tests/auto/qquickiconimage/data/fileSelectors.qml new file mode 100644 index 00000000..e3ed3857 --- /dev/null +++ b/tests/auto/qquickiconimage/data/fileSelectors.qml @@ -0,0 +1,16 @@ +import QtQuick 2.9 +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 + +Row { + width: 200 + height: 200 + + IconImage { + name: "appointment-new" + sourceSize: Qt.size(22, 22) + } + Image { + source: "qrc:/icons/testtheme/22x22/actions/appointment-new.png" + } +} diff --git a/tests/auto/qquickiconimage/data/nameBindingNoSizes.qml b/tests/auto/qquickiconimage/data/nameBindingNoSizes.qml new file mode 100644 index 00000000..440e8d1f --- /dev/null +++ b/tests/auto/qquickiconimage/data/nameBindingNoSizes.qml @@ -0,0 +1,7 @@ +import QtQuick 2.9 +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 + +IconImage { + name: "appointment-new" +} diff --git a/tests/auto/qquickiconimage/data/nameBindingSourceSize.qml b/tests/auto/qquickiconimage/data/nameBindingSourceSize.qml new file mode 100644 index 00000000..e3ed3857 --- /dev/null +++ b/tests/auto/qquickiconimage/data/nameBindingSourceSize.qml @@ -0,0 +1,16 @@ +import QtQuick 2.9 +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 + +Row { + width: 200 + height: 200 + + IconImage { + name: "appointment-new" + sourceSize: Qt.size(22, 22) + } + Image { + source: "qrc:/icons/testtheme/22x22/actions/appointment-new.png" + } +} diff --git a/tests/auto/qquickiconimage/data/nameBindingSourceSizeWidthHeight.qml b/tests/auto/qquickiconimage/data/nameBindingSourceSizeWidthHeight.qml new file mode 100644 index 00000000..fe24e94a --- /dev/null +++ b/tests/auto/qquickiconimage/data/nameBindingSourceSizeWidthHeight.qml @@ -0,0 +1,10 @@ +import QtQuick 2.9 +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 + +IconImage { + name: "appointment-new" + sourceSize: Qt.size(22, 22) + width: 16 + height: 16 +} diff --git a/tests/auto/qquickiconimage/data/root.qml b/tests/auto/qquickiconimage/data/root.qml new file mode 100644 index 00000000..ba65d9df --- /dev/null +++ b/tests/auto/qquickiconimage/data/root.qml @@ -0,0 +1,6 @@ +import QtQuick 2.9 + +Item { + width: 200 + height: 200 +} diff --git a/tests/auto/qquickiconimage/data/sourceBindingNoSizes.qml b/tests/auto/qquickiconimage/data/sourceBindingNoSizes.qml new file mode 100644 index 00000000..51cf6498 --- /dev/null +++ b/tests/auto/qquickiconimage/data/sourceBindingNoSizes.qml @@ -0,0 +1,15 @@ +import QtQuick 2.9 +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 + +Row { + width: 200 + height: 200 + + IconImage { + source: "qrc:/icons/testtheme/22x22/actions/appointment-new.png" + } + Image { + source: "qrc:/icons/testtheme/22x22/actions/appointment-new.png" + } +} diff --git a/tests/auto/qquickiconimage/data/sourceBindingSourceSize.qml b/tests/auto/qquickiconimage/data/sourceBindingSourceSize.qml new file mode 100644 index 00000000..f4fc424f --- /dev/null +++ b/tests/auto/qquickiconimage/data/sourceBindingSourceSize.qml @@ -0,0 +1,16 @@ +import QtQuick 2.9 +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 + +Row { + width: 200 + height: 200 + + IconImage { + source: "qrc:/icons/testtheme/22x22/actions/appointment-new.png" + sourceSize: Qt.size(22, 22) + } + Image { + source: "qrc:/icons/testtheme/22x22/actions/appointment-new.png" + } +} diff --git a/tests/auto/qquickiconimage/data/sourceBindingSourceSizeWidthHeight.qml b/tests/auto/qquickiconimage/data/sourceBindingSourceSizeWidthHeight.qml new file mode 100644 index 00000000..65e9b5f7 --- /dev/null +++ b/tests/auto/qquickiconimage/data/sourceBindingSourceSizeWidthHeight.qml @@ -0,0 +1,10 @@ +import QtQuick 2.9 +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 + +IconImage { + source: "qrc:/icons/testtheme/22x22/actions/appointment-new.png" + sourceSize: Qt.size(22, 22) + width: 16 + height: 16 +} diff --git a/tests/auto/qquickiconimage/data/sourceBindingSourceTooLarge.qml b/tests/auto/qquickiconimage/data/sourceBindingSourceTooLarge.qml new file mode 100644 index 00000000..a3ea3323 --- /dev/null +++ b/tests/auto/qquickiconimage/data/sourceBindingSourceTooLarge.qml @@ -0,0 +1,8 @@ +import QtQuick 2.9 +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 + +IconImage { + source: "qrc:/icons/testtheme/22x22/actions/appointment-new.png" + sourceSize: Qt.size(32, 32) +} diff --git a/tests/auto/qquickiconimage/data/svgNoSizes.qml b/tests/auto/qquickiconimage/data/svgNoSizes.qml new file mode 100644 index 00000000..40ae3247 --- /dev/null +++ b/tests/auto/qquickiconimage/data/svgNoSizes.qml @@ -0,0 +1,15 @@ +import QtQuick 2.9 +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 + +Row { + width: 200 + height: 200 + + IconImage { + source: "qrc:/icons/testtheme/appointment-new.svg" + } + Image { + source: "qrc:/icons/testtheme/appointment-new.svg" + } +} diff --git a/tests/auto/qquickiconimage/data/svgSourceBindingSourceSize.qml b/tests/auto/qquickiconimage/data/svgSourceBindingSourceSize.qml new file mode 100644 index 00000000..da52c561 --- /dev/null +++ b/tests/auto/qquickiconimage/data/svgSourceBindingSourceSize.qml @@ -0,0 +1,17 @@ +import QtQuick 2.9 +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 + +Row { + width: 200 + height: 200 + + IconImage { + source: "qrc:/data/icons/testtheme/appointment-new.svg" + sourceSize: Qt.size(22, 22) + } + Image { + source: "qrc:/data/icons/testtheme/appointment-new.svg" + sourceSize: Qt.size(22, 22) + } +} diff --git a/tests/auto/qquickiconimage/icons/testtheme/16x16/actions/appointment-new.png b/tests/auto/qquickiconimage/icons/testtheme/16x16/actions/appointment-new.png Binary files differnew file mode 100644 index 00000000..18b7c678 --- /dev/null +++ b/tests/auto/qquickiconimage/icons/testtheme/16x16/actions/appointment-new.png diff --git a/tests/auto/qquickiconimage/icons/testtheme/22x22/actions/+testselector/appointment-new.png b/tests/auto/qquickiconimage/icons/testtheme/22x22/actions/+testselector/appointment-new.png Binary files differnew file mode 100644 index 00000000..c6ceca43 --- /dev/null +++ b/tests/auto/qquickiconimage/icons/testtheme/22x22/actions/+testselector/appointment-new.png diff --git a/tests/auto/qquickiconimage/icons/testtheme/22x22/actions/+testselector/appointment-new@2x.png b/tests/auto/qquickiconimage/icons/testtheme/22x22/actions/+testselector/appointment-new@2x.png Binary files differnew file mode 100644 index 00000000..f380ebb6 --- /dev/null +++ b/tests/auto/qquickiconimage/icons/testtheme/22x22/actions/+testselector/appointment-new@2x.png diff --git a/tests/auto/qquickiconimage/icons/testtheme/22x22/actions/appointment-new.png b/tests/auto/qquickiconimage/icons/testtheme/22x22/actions/appointment-new.png Binary files differnew file mode 100644 index 00000000..d676ffd4 --- /dev/null +++ b/tests/auto/qquickiconimage/icons/testtheme/22x22/actions/appointment-new.png diff --git a/tests/auto/qquickiconimage/icons/testtheme/22x22/actions/appointment-new@2x.png b/tests/auto/qquickiconimage/icons/testtheme/22x22/actions/appointment-new@2x.png Binary files differnew file mode 100644 index 00000000..63ae9ce7 --- /dev/null +++ b/tests/auto/qquickiconimage/icons/testtheme/22x22/actions/appointment-new@2x.png diff --git a/tests/auto/qquickiconimage/icons/testtheme/22x22/actions/color-test-original.png b/tests/auto/qquickiconimage/icons/testtheme/22x22/actions/color-test-original.png Binary files differnew file mode 100644 index 00000000..2d876cc1 --- /dev/null +++ b/tests/auto/qquickiconimage/icons/testtheme/22x22/actions/color-test-original.png diff --git a/tests/auto/qquickiconimage/icons/testtheme/22x22/actions/color-test-original@2x.png b/tests/auto/qquickiconimage/icons/testtheme/22x22/actions/color-test-original@2x.png Binary files differnew file mode 100644 index 00000000..c65fbed0 --- /dev/null +++ b/tests/auto/qquickiconimage/icons/testtheme/22x22/actions/color-test-original@2x.png diff --git a/tests/auto/qquickiconimage/icons/testtheme/22x22/actions/color-test-tinted.png b/tests/auto/qquickiconimage/icons/testtheme/22x22/actions/color-test-tinted.png Binary files differnew file mode 100644 index 00000000..220a313d --- /dev/null +++ b/tests/auto/qquickiconimage/icons/testtheme/22x22/actions/color-test-tinted.png diff --git a/tests/auto/qquickiconimage/icons/testtheme/22x22/actions/color-test-tinted@2x.png b/tests/auto/qquickiconimage/icons/testtheme/22x22/actions/color-test-tinted@2x.png Binary files differnew file mode 100644 index 00000000..cd66ef69 --- /dev/null +++ b/tests/auto/qquickiconimage/icons/testtheme/22x22/actions/color-test-tinted@2x.png diff --git a/tests/auto/qquickiconimage/icons/testtheme/22x22@2/actions/+testselector/appointment-new.png b/tests/auto/qquickiconimage/icons/testtheme/22x22@2/actions/+testselector/appointment-new.png Binary files differnew file mode 100644 index 00000000..f380ebb6 --- /dev/null +++ b/tests/auto/qquickiconimage/icons/testtheme/22x22@2/actions/+testselector/appointment-new.png diff --git a/tests/auto/qquickiconimage/icons/testtheme/22x22@2/actions/appointment-new.png b/tests/auto/qquickiconimage/icons/testtheme/22x22@2/actions/appointment-new.png Binary files differnew file mode 100644 index 00000000..63ae9ce7 --- /dev/null +++ b/tests/auto/qquickiconimage/icons/testtheme/22x22@2/actions/appointment-new.png diff --git a/tests/auto/qquickiconimage/icons/testtheme/appointment-new.svg b/tests/auto/qquickiconimage/icons/testtheme/appointment-new.svg new file mode 100644 index 00000000..4cb14f82 --- /dev/null +++ b/tests/auto/qquickiconimage/icons/testtheme/appointment-new.svg @@ -0,0 +1,425 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + inkscape:export-ydpi="90.000000" + inkscape:export-xdpi="90.000000" + inkscape:export-filename="/home/jimmac/Desktop/wi-fi.png" + width="48px" + height="48px" + id="svg11300" + sodipodi:version="0.32" + inkscape:version="0.46" + sodipodi:docbase="/home/tigert/cvs/freedesktop.org/tango-icon-theme/scalable/actions" + sodipodi:docname="appointment-new.svg" + inkscape:output_extension="org.inkscape.output.svg.inkscape"> + <defs + id="defs3"> + <inkscape:perspective + sodipodi:type="inkscape:persp3d" + inkscape:vp_x="0 : 24 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_z="48 : 24 : 1" + inkscape:persp3d-origin="24 : 16 : 1" + id="perspective59" /> + <linearGradient + inkscape:collect="always" + id="linearGradient5204"> + <stop + style="stop-color:#c4a000;stop-opacity:1;" + offset="0" + id="stop5206" /> + <stop + style="stop-color:#c4a000;stop-opacity:0;" + offset="1" + id="stop5208" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + id="linearGradient5196"> + <stop + style="stop-color:#c4a000;stop-opacity:1;" + offset="0" + id="stop5198" /> + <stop + style="stop-color:#c4a000;stop-opacity:0;" + offset="1" + id="stop5200" /> + </linearGradient> + <linearGradient + id="linearGradient12512"> + <stop + style="stop-color:#ffffff;stop-opacity:1.0000000;" + offset="0.0000000" + id="stop12513" /> + <stop + style="stop-color:#fff520;stop-opacity:0.89108908;" + offset="0.50000000" + id="stop12517" /> + <stop + style="stop-color:#fff300;stop-opacity:0.0000000;" + offset="1.0000000" + id="stop12514" /> + </linearGradient> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient12512" + id="radialGradient278" + gradientUnits="userSpaceOnUse" + cx="55.000000" + cy="125.00000" + fx="55.000000" + fy="125.00000" + r="14.375000" /> + <linearGradient + id="linearGradient10653"> + <stop + style="stop-color:#f3f4ff;stop-opacity:1.0000000;" + offset="0.0000000" + id="stop10655" /> + <stop + style="stop-color:#9193af;stop-opacity:1.0000000;" + offset="1.0000000" + id="stop10657" /> + </linearGradient> + <linearGradient + id="linearGradient42174"> + <stop + style="stop-color:#a0a0a0;stop-opacity:1.0000000;" + offset="0.0000000" + id="stop42176" /> + <stop + style="stop-color:#ffffff;stop-opacity:1.0000000;" + offset="1.0000000" + id="stop42178" /> + </linearGradient> + <linearGradient + id="linearGradient2145"> + <stop + style="stop-color:#fffffd;stop-opacity:1.0000000;" + offset="0.0000000" + id="stop2147" /> + <stop + style="stop-color:#cbcbc9;stop-opacity:1.0000000;" + offset="1.0000000" + id="stop2149" /> + </linearGradient> + <linearGradient + id="linearGradient37935"> + <stop + id="stop37937" + offset="0.0000000" + style="stop-color:#9497b3;stop-opacity:1.0000000;" /> + <stop + id="stop37939" + offset="1.0000000" + style="stop-color:#4c4059;stop-opacity:1.0000000;" /> + </linearGradient> + <linearGradient + id="linearGradient2152"> + <stop + id="stop2154" + offset="0.0000000" + style="stop-color:#9aa29a;stop-opacity:1.0000000;" /> + <stop + id="stop2156" + offset="1.0000000" + style="stop-color:#b5beb5;stop-opacity:1.0000000;" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + id="linearGradient3816"> + <stop + style="stop-color:#000000;stop-opacity:1;" + offset="0" + id="stop3818" /> + <stop + style="stop-color:#000000;stop-opacity:0;" + offset="1" + id="stop3820" /> + </linearGradient> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3816" + id="radialGradient3822" + cx="31.112698" + cy="19.008621" + fx="31.112698" + fy="19.008621" + r="8.6620579" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2152" + id="linearGradient4307" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(3.123841,0.000000,0.000000,0.969691,-31.88758,-19.59492)" + x1="8.9156475" + y1="37.197018" + x2="9.8855033" + y2="52.090678" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient10653" + id="radialGradient4309" + gradientUnits="userSpaceOnUse" + cx="11.329200" + cy="10.583970" + fx="11.329200" + fy="10.583970" + r="15.532059" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2145" + id="radialGradient4311" + gradientUnits="userSpaceOnUse" + cx="11.901996" + cy="10.045444" + fx="11.901996" + fy="10.045444" + r="29.292715" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient42174" + id="linearGradient4313" + gradientUnits="userSpaceOnUse" + x1="6.3422160" + y1="7.7893324" + x2="22.218424" + y2="25.884274" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient5196" + id="radialGradient5202" + cx="23.375" + cy="10.972863" + fx="23.375" + fy="10.972863" + r="3.3478092" + gradientTransform="matrix(3.630420,1.654030e-15,-1.608743e-15,3.742066,-61.48607,-29.18618)" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient5204" + id="linearGradient5210" + x1="19.667364" + y1="4.2570662" + x2="20.329933" + y2="5.2845874" + gradientUnits="userSpaceOnUse" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient37935" + id="radialGradient5212" + gradientUnits="userSpaceOnUse" + cx="8.7468252" + cy="6.8283234" + fx="8.7468252" + fy="6.8283234" + r="29.889715" /> + </defs> + <sodipodi:namedview + stroke="#c4a000" + fill="#babdb6" + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="0.25490196" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="11.313708" + inkscape:cx="13.2248" + inkscape:cy="25.106052" + inkscape:current-layer="layer1" + showgrid="false" + inkscape:grid-bbox="true" + inkscape:document-units="px" + inkscape:showpageshadow="false" + inkscape:window-width="833" + inkscape:window-height="772" + inkscape:window-x="305" + inkscape:window-y="76" /> + <metadata + id="metadata4"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:creator> + <cc:Agent> + <dc:title>Jakub Steiner</dc:title> + </cc:Agent> + </dc:creator> + <dc:source>http://jimmac.musichall.cz</dc:source> + <cc:license + rdf:resource="http://creativecommons.org/licenses/publicdomain/" /> + <dc:title>New Appointment</dc:title> + <dc:subject> + <rdf:Bag> + <rdf:li>appointment</rdf:li> + <rdf:li>new</rdf:li> + <rdf:li>meeting</rdf:li> + <rdf:li>rvsp</rdf:li> + </rdf:Bag> + </dc:subject> + </cc:Work> + <cc:License + rdf:about="http://creativecommons.org/licenses/publicdomain/"> + <cc:permits + rdf:resource="http://creativecommons.org/ns#Reproduction" /> + <cc:permits + rdf:resource="http://creativecommons.org/ns#Distribution" /> + <cc:permits + rdf:resource="http://creativecommons.org/ns#DerivativeWorks" /> + </cc:License> + </rdf:RDF> + </metadata> + <g + id="layer1" + inkscape:label="Layer 1" + inkscape:groupmode="layer"> + <path + d="M 39.774755 19.008621 A 8.6620579 8.6620579 0 1 1 22.45064,19.008621 A 8.6620579 8.6620579 0 1 1 39.774755 19.008621 z" + sodipodi:ry="8.6620579" + sodipodi:rx="8.6620579" + sodipodi:cy="19.008621" + sodipodi:cx="31.112698" + id="path4318" + style="opacity:1;color:#000000;fill:url(#radialGradient3822);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" + sodipodi:type="arc" + transform="matrix(2.563158,0.000000,0.000000,1.219602,-55.98414,14.04144)" /> + <path + sodipodi:nodetypes="cccc" + id="path14341" + d="M 18.587591,1.403729 L 4.226755,18.096665 L 5.4854717,19.339844 L 18.587591,1.403729 z " + style="color:#000000;fill:url(#linearGradient4307);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" /> + <path + sodipodi:nodetypes="cccc" + id="path18921" + d="M 18.467176,1.3138035 L 5.6605716,19.072612 L 7.4900985,20.687913 L 18.467176,1.3138035 z " + style="fill:#fefefe;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1" /> + <path + transform="matrix(1.431529,0.000000,0.000000,1.431529,0.569459,-1.654618)" + d="M 31.160714 16.910715 A 14.910714 14.910714 0 1 1 1.3392859,16.910715 A 14.910714 14.910714 0 1 1 31.160714 16.910715 z" + sodipodi:ry="14.910714" + sodipodi:rx="14.910714" + sodipodi:cy="16.910715" + sodipodi:cx="16.25" + id="path27786" + style="fill:url(#radialGradient5212);fill-opacity:1;fill-rule:evenodd;stroke:#605773;stroke-width:0.69855404;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1" + sodipodi:type="arc" /> + <path + transform="matrix(1.163838,0.000000,0.000000,1.163838,4.824801,2.777556)" + d="M 31.160714 16.910715 A 14.910714 14.910714 0 1 1 1.3392859,16.910715 A 14.910714 14.910714 0 1 1 31.160714 16.910715 z" + sodipodi:ry="14.910714" + sodipodi:rx="14.910714" + sodipodi:cy="16.910715" + sodipodi:cx="16.25" + id="path35549" + style="fill:url(#radialGradient4311);fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient4313);stroke-width:0.71139598;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1" + sodipodi:type="arc" /> + <path + sodipodi:type="arc" + style="opacity:1;color:#000000;fill:url(#radialGradient5202);fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient5210);stroke-width:0.56498736;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" + id="path4120" + sodipodi:cx="23.375" + sodipodi:cy="11.875" + sodipodi:rx="8.5" + sodipodi:ry="8.5" + d="M 16.679382,6.6387137 A 8.5,8.5 0 0 1 23.332691,3.3751053 L 23.375,11.875 z" + transform="matrix(1.769951,0.000000,0.000000,1.769951,-17.02424,1.610741)" + sodipodi:start="3.8052902" + sodipodi:end="4.7074114" /> + <path + transform="matrix(2.073295,0.000000,0.000000,2.073295,-7.310224,-13.13682)" + d="M 16.40625 17.28125 A 1.21875 1.21875 0 1 1 13.96875,17.28125 A 1.21875 1.21875 0 1 1 16.40625 17.28125 z" + sodipodi:ry="1.21875" + sodipodi:rx="1.21875" + sodipodi:cy="17.28125" + sodipodi:cx="15.1875" + id="path34778" + style="fill:#f3f3f3;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.48232403;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;stroke-dasharray:none" + sodipodi:type="arc" /> + <path + id="path35559" + d="M 22.176614,20.718014 L 13.155702,13.140282" + style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + id="path35561" + d="M 19.408614,29.776506 L 22.368655,25.283228" + style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" + sodipodi:nodetypes="cc" /> + <path + transform="matrix(2.749493,0.000000,0.000000,2.749493,-22.30073,-12.40939)" + d="M 17.324117 7.6932044 A 0.61871845 0.61871845 0 1 1 16.08668,7.6932044 A 0.61871845 0.61871845 0 1 1 17.324117 7.6932044 z" + sodipodi:ry="0.61871845" + sodipodi:rx="0.61871845" + sodipodi:cy="7.6932044" + sodipodi:cx="16.705399" + id="path35563" + style="fill:#b6b9b1;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.36871839;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;opacity:1" + sodipodi:type="arc" /> + <path + transform="matrix(2.749493,0.000000,0.000000,2.749493,-22.30073,14.80922)" + d="M 17.324117 7.6932044 A 0.61871845 0.61871845 0 1 1 16.08668,7.6932044 A 0.61871845 0.61871845 0 1 1 17.324117 7.6932044 z" + sodipodi:ry="0.61871845" + sodipodi:rx="0.61871845" + sodipodi:cy="7.6932044" + sodipodi:cx="16.705399" + id="path35565" + style="fill:#b6b9b1;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.36871839;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;opacity:1" + sodipodi:type="arc" /> + <path + transform="matrix(2.749493,0.000000,0.000000,2.749493,-35.91004,1.199890)" + d="M 17.324117 7.6932044 A 0.61871845 0.61871845 0 1 1 16.08668,7.6932044 A 0.61871845 0.61871845 0 1 1 17.324117 7.6932044 z" + sodipodi:ry="0.61871845" + sodipodi:rx="0.61871845" + sodipodi:cy="7.6932044" + sodipodi:cx="16.705399" + id="path35567" + style="fill:#b6b9b1;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.36871839;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;opacity:1" + sodipodi:type="arc" /> + <path + transform="matrix(2.749493,0.000000,0.000000,2.749493,-8.691448,1.199890)" + d="M 17.324117 7.6932044 A 0.61871845 0.61871845 0 1 1 16.08668,7.6932044 A 0.61871845 0.61871845 0 1 1 17.324117 7.6932044 z" + sodipodi:ry="0.61871845" + sodipodi:rx="0.61871845" + sodipodi:cy="7.6932044" + sodipodi:cx="16.705399" + id="path35569" + style="fill:#b6b9b1;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.36871839;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;opacity:1" + sodipodi:type="arc" /> + <path + sodipodi:type="arc" + style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#radialGradient4309);stroke-width:0.73656511;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1" + id="path10651" + sodipodi:cx="16.25" + sodipodi:cy="16.910715" + sodipodi:rx="14.910714" + sodipodi:ry="14.910714" + d="M 31.160714 16.910715 A 14.910714 14.910714 0 1 1 1.3392859,16.910715 A 14.910714 14.910714 0 1 1 31.160714 16.910715 z" + transform="matrix(1.357654,0.000000,0.000000,1.357654,1.769896,-0.493735)" /> + <path + sodipodi:type="arc" + style="color:#000000;fill:url(#radialGradient278);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.25000024;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:block" + id="path12511" + sodipodi:cx="55" + sodipodi:cy="125" + sodipodi:rx="14.375" + sodipodi:ry="14.375" + d="M 69.375 125 A 14.375 14.375 0 1 1 40.625,125 A 14.375 14.375 0 1 1 69.375 125 z" + transform="matrix(0.611127,0.000000,0.000000,0.611127,5.544052,-66.92818)" + inkscape:export-filename="/home/jimmac/ximian_art/icons/nautilus/suse93/stock_new-16.png" + inkscape:export-xdpi="33.852203" + inkscape:export-ydpi="33.852203" /> + </g> +</svg> diff --git a/tests/auto/qquickiconimage/icons/testtheme/index.theme b/tests/auto/qquickiconimage/icons/testtheme/index.theme new file mode 100644 index 00000000..6ab6c15c --- /dev/null +++ b/tests/auto/qquickiconimage/icons/testtheme/index.theme @@ -0,0 +1,21 @@ +[Icon Theme] +Name=Test +Comment=Test Theme + +Directories=16x16/actions,22x22/actions,22x22@2/actions + +[16x16/actions] +Size=16 +Context=Actions +Type=Fixed + +[22x22/actions] +Size=22 +Context=Actions +Type=Fixed + +[22x22@2/actions] +Size=22 +Context=Actions +Scale=2 +Type=Fixed diff --git a/tests/auto/qquickiconimage/qquickiconimage.pro b/tests/auto/qquickiconimage/qquickiconimage.pro new file mode 100644 index 00000000..1a37d4ba --- /dev/null +++ b/tests/auto/qquickiconimage/qquickiconimage.pro @@ -0,0 +1,17 @@ +CONFIG += testcase +macos:CONFIG -= app_bundle +TARGET = tst_qquickiconimage + +QT += core gui qml quick testlib +QT_PRIVATE += quick-private quickcontrols2-private +qtHaveModule(svg): QT += svg + +include (../shared/util.pri) + +SOURCES += tst_qquickiconimage.cpp + +RESOURCES += resources.qrc + +TESTDATA += \ + $$PWD/data/*.qml \ + $$PWD/data/icons/* diff --git a/tests/auto/qquickiconimage/resources.qrc b/tests/auto/qquickiconimage/resources.qrc new file mode 100644 index 00000000..6558b039 --- /dev/null +++ b/tests/auto/qquickiconimage/resources.qrc @@ -0,0 +1,17 @@ +<RCC> + <qresource prefix="/"> + <file>icons/testtheme/16x16/actions/appointment-new.png</file> + <file>icons/testtheme/22x22/actions/appointment-new.png</file> + <file>icons/testtheme/22x22/actions/appointment-new@2x.png</file> + <file>icons/testtheme/22x22@2/actions/appointment-new.png</file> + <file>icons/testtheme/22x22/actions/+testselector/appointment-new.png</file> + <file>icons/testtheme/22x22/actions/+testselector/appointment-new@2x.png</file> + <file>icons/testtheme/22x22@2/actions/+testselector/appointment-new.png</file> + <file>icons/testtheme/index.theme</file> + <file>icons/testtheme/appointment-new.svg</file> + <file>icons/testtheme/22x22/actions/color-test-original.png</file> + <file>icons/testtheme/22x22/actions/color-test-tinted.png</file> + <file>icons/testtheme/22x22/actions/color-test-original@2x.png</file> + <file>icons/testtheme/22x22/actions/color-test-tinted@2x.png</file> + </qresource> +</RCC> diff --git a/tests/auto/qquickiconimage/tst_qquickiconimage.cpp b/tests/auto/qquickiconimage/tst_qquickiconimage.cpp new file mode 100644 index 00000000..4e4afb13 --- /dev/null +++ b/tests/auto/qquickiconimage/tst_qquickiconimage.cpp @@ -0,0 +1,493 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <qtest.h> +#include <QtTest/qsignalspy.h> + +#include <QtCore/qmath.h> +#include <QtQml/qqmlengine.h> +#include <QtQml/qqmlcomponent.h> +#include <QtQml/qqmlfileselector.h> +#include <QtQuick/qquickitem.h> +#include <QtQuick/qquickview.h> +#include <QtQuick/qquickitemgrabresult.h> +#include <QtQuick/private/qquickimage_p.h> +#include <QtQuickControls2/private/qquickiconimage_p.h> + +#include "../shared/util.h" +#include "../shared/visualtestutil.h" + +using namespace QQuickVisualTestUtil; + +class tst_qquickiconimage : public QQmlDataTest +{ + Q_OBJECT +public: + tst_qquickiconimage(); + +private slots: + void initTestCase(); + void defaults(); + void nameBindingSourceSize(); + void nameBindingSourceSizeWidthHeight(); + void nameBindingNoSizes(); + void sourceBindingNoSizes(); + void sourceBindingSourceSize(); + void sourceBindingSourceSizeWidthHeight(); + void sourceBindingSourceTooLarge(); + void changeSourceSize(); + void alignment_data(); + void alignment(); + void svgNoSizes(); + void svgSourceBindingSourceSize(); + void color(); + void fileSelectors(); + +private: + void setTheme(); + + qreal dpr; + int integerDpr; +}; + +static QImage grabItemToImage(QQuickItem *item) +{ + QSharedPointer<QQuickItemGrabResult> result = item->grabToImage(); + QSignalSpy spy(result.data(), SIGNAL(ready())); + spy.wait(); + return result->image(); +} + +#define SKIP_IF_DPR_TOO_HIGH() \ + if (dpr > 2) \ + QSKIP("Test does not support device pixel ratio greater than 2") + +tst_qquickiconimage::tst_qquickiconimage() : + dpr(qGuiApp->devicePixelRatio()), + integerDpr(qCeil(dpr)) +{ +} + +void tst_qquickiconimage::initTestCase() +{ + QQmlDataTest::initTestCase(); + QIcon::setThemeName(QStringLiteral("testtheme")); +} + +void tst_qquickiconimage::defaults() +{ + QQuickIconImage iconImage; + QCOMPARE(iconImage.fillMode(), QQuickImage::Pad); + QCOMPARE(iconImage.name(), QString()); + QCOMPARE(iconImage.source(), QUrl()); + QCOMPARE(iconImage.color(), QColor(Qt::transparent)); +} + +void tst_qquickiconimage::nameBindingSourceSize() +{ + // We can't have images for every DPR. + SKIP_IF_DPR_TOO_HIGH(); + + QQuickView view(testFileUrl("nameBindingSourceSize.qml")); + QCOMPARE(view.status(), QQuickView::Ready); + view.show(); + view.requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(&view)); + + QQuickIconImage *iconImage = qobject_cast<QQuickIconImage*>(view.rootObject()->childItems().at(0)); + QVERIFY(iconImage); + + QQuickItem *image = view.rootObject()->childItems().at(1); + QVERIFY(image); + + QCOMPARE(grabItemToImage(iconImage), grabItemToImage(image)); + QCOMPARE(iconImage->sourceSize().width(), 22); + QCOMPARE(iconImage->sourceSize().height(), 22); + QCOMPARE(iconImage->implicitWidth(), 22.0); + QCOMPARE(iconImage->implicitHeight(), 22.0); + QCOMPARE(iconImage->width(), 22.0); + QCOMPARE(iconImage->height(), 22.0); + + // The requested width of 16 is less than the pixmap's size on disk which + // is 22x22. Our default fillMode, Pad, would result in the image being clipped, + // so instead we change the fillMode to PreserveAspectFit. Doing so causes + // QQuickImage::updatePaintedGeometry() to set our implicit size to 22x16 to + // ensure that the aspect ratio is respected. Since we have no explicit height, + // the height (previously 22) becomes the implicit height (16). + iconImage->setWidth(16.0); + QCOMPARE(iconImage->fillMode(), QQuickImage::PreserveAspectFit); + QCOMPARE(iconImage->sourceSize().width(), 22); + QCOMPARE(iconImage->sourceSize().height(), 22); + QCOMPARE(iconImage->implicitWidth(), 22.0); + QCOMPARE(iconImage->implicitHeight(), 16.0); + QCOMPARE(iconImage->width(), 16.0); + QCOMPARE(iconImage->height(), 16.0); +} + +void tst_qquickiconimage::nameBindingSourceSizeWidthHeight() +{ + SKIP_IF_DPR_TOO_HIGH(); + + QQuickView view(testFileUrl("nameBindingSourceSizeWidthHeight.qml")); + QCOMPARE(view.status(), QQuickView::Ready); + view.show(); + + QQuickIconImage *iconImage = qobject_cast<QQuickIconImage*>(view.rootObject()); + QVERIFY(iconImage); + QCOMPARE(iconImage->sourceSize().width(), 22); + QCOMPARE(iconImage->sourceSize().height(), 22); + QCOMPARE(iconImage->implicitWidth(), 22.0); + QCOMPARE(iconImage->implicitHeight(), 22.0); + QCOMPARE(iconImage->width(), 16.0); + QCOMPARE(iconImage->height(), 16.0); +} + +void tst_qquickiconimage::nameBindingNoSizes() +{ + SKIP_IF_DPR_TOO_HIGH(); + + QQuickView view(testFileUrl("nameBindingNoSizes.qml")); + QCOMPARE(view.status(), QQuickView::Ready); + view.show(); + + QQuickIconImage *iconImage = qobject_cast<QQuickIconImage*>(view.rootObject()); + QVERIFY(iconImage); + // The smallest available size will be chosen. + QCOMPARE(iconImage->sourceSize().width(), 16); + QCOMPARE(iconImage->sourceSize().height(), 16); + QCOMPARE(iconImage->implicitWidth(), 16.0); + QCOMPARE(iconImage->implicitHeight(), 16.0); + QCOMPARE(iconImage->width(), 16.0); + QCOMPARE(iconImage->height(), 16.0); +} + +void tst_qquickiconimage::sourceBindingNoSizes() +{ + SKIP_IF_DPR_TOO_HIGH(); + + QQuickView view(testFileUrl("sourceBindingNoSizes.qml")); + QCOMPARE(view.status(), QQuickView::Ready); + view.show(); + view.requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(&view)); + + QQuickIconImage *iconImage = qobject_cast<QQuickIconImage*>(view.rootObject()->childItems().at(0)); + QVERIFY(iconImage); + + QQuickItem *image = view.rootObject()->childItems().at(1); + QVERIFY(image); + + QCOMPARE(iconImage->sourceSize().width(), 22 * integerDpr); + QCOMPARE(iconImage->sourceSize().height(), 22 * integerDpr); + QCOMPARE(iconImage->implicitWidth(), 22.0); + QCOMPARE(iconImage->implicitHeight(), 22.0); + QCOMPARE(iconImage->width(), 22.0); + QCOMPARE(iconImage->height(), 22.0); + QCOMPARE(grabItemToImage(iconImage), grabItemToImage(image)); +} + +void tst_qquickiconimage::sourceBindingSourceSize() +{ + SKIP_IF_DPR_TOO_HIGH(); + + QQuickView view(testFileUrl("sourceBindingSourceSize.qml")); + QCOMPARE(view.status(), QQuickView::Ready); + view.show(); + view.requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(&view)); + + QQuickIconImage *iconImage = qobject_cast<QQuickIconImage*>(view.rootObject()->childItems().at(0)); + QVERIFY(iconImage); + + QQuickItem *image = view.rootObject()->childItems().at(1); + QVERIFY(image); + + QCOMPARE(iconImage->sourceSize().width(), 22); + QCOMPARE(iconImage->sourceSize().height(), 22); + QCOMPARE(iconImage->implicitWidth(), 22.0); + QCOMPARE(iconImage->implicitHeight(), 22.0); + QCOMPARE(iconImage->width(), 22.0); + QCOMPARE(iconImage->height(), 22.0); + QCOMPARE(grabItemToImage(iconImage), grabItemToImage(image)); + + // Changing width and height should not affect sourceSize. + iconImage->setWidth(50); + QCOMPARE(iconImage->sourceSize().width(), 22); + QCOMPARE(iconImage->sourceSize().height(), 22); + iconImage->setHeight(50); + QCOMPARE(iconImage->sourceSize().width(), 22); + QCOMPARE(iconImage->sourceSize().height(), 22); +} + +void tst_qquickiconimage::sourceBindingSourceSizeWidthHeight() +{ + SKIP_IF_DPR_TOO_HIGH(); + + QQuickView view(testFileUrl("sourceBindingSourceSizeWidthHeight.qml")); + QCOMPARE(view.status(), QQuickView::Ready); + view.show(); + view.requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(&view)); + + QQuickIconImage *iconImage = qobject_cast<QQuickIconImage*>(view.rootObject()); + QVERIFY(iconImage); + QCOMPARE(iconImage->sourceSize().width(), 22); + QCOMPARE(iconImage->sourceSize().height(), 22); + QCOMPARE(iconImage->implicitWidth(), 22.0); + QCOMPARE(iconImage->implicitHeight(), 22.0); + QCOMPARE(iconImage->width(), 16.0); + QCOMPARE(iconImage->height(), 16.0); +} + +void tst_qquickiconimage::sourceBindingSourceTooLarge() +{ + SKIP_IF_DPR_TOO_HIGH(); + + QQuickView view(testFileUrl("sourceBindingSourceTooLarge.qml")); + QCOMPARE(view.status(), QQuickView::Ready); + view.show(); + view.requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(&view)); + + QQuickIconImage *iconImage = qobject_cast<QQuickIconImage*>(view.rootObject()); + QVERIFY(iconImage); + QCOMPARE(iconImage->sourceSize().width(), 32); + QCOMPARE(iconImage->sourceSize().height(), 32); + QCOMPARE(iconImage->implicitWidth(), 22.0); + QCOMPARE(iconImage->implicitHeight(), 22.0); + QCOMPARE(iconImage->width(), 22.0); + QCOMPARE(iconImage->height(), 22.0); +} + +void tst_qquickiconimage::alignment_data() +{ + QTest::addColumn<QQuickImage::HAlignment>("horizontalAlignment"); + QTest::addColumn<QQuickImage::VAlignment>("verticalAlignment"); + + QTest::newRow("AlignLeft,AlignTop") << QQuickImage::AlignLeft << QQuickImage::AlignTop; + QTest::newRow("AlignLeft,AlignVCenter") << QQuickImage::AlignLeft << QQuickImage::AlignVCenter; + QTest::newRow("AlignLeft,AlignBottom") << QQuickImage::AlignLeft << QQuickImage::AlignBottom; + QTest::newRow("AlignHCenter,AlignTop") << QQuickImage::AlignHCenter << QQuickImage::AlignTop; + QTest::newRow("AlignHCenter,AlignVCenter") << QQuickImage::AlignHCenter << QQuickImage::AlignVCenter; + QTest::newRow("AlignHCenter,AlignBottom") << QQuickImage::AlignHCenter << QQuickImage::AlignBottom; + QTest::newRow("AlignRight,AlignTop") << QQuickImage::AlignRight << QQuickImage::AlignTop; + QTest::newRow("AlignRight,AlignVCenter") << QQuickImage::AlignRight << QQuickImage::AlignVCenter; + QTest::newRow("AlignRight,AlignBottom") << QQuickImage::AlignRight << QQuickImage::AlignBottom; +} + +void tst_qquickiconimage::alignment() +{ + SKIP_IF_DPR_TOO_HIGH(); + + QFETCH(QQuickImage::HAlignment, horizontalAlignment); + QFETCH(QQuickImage::VAlignment, verticalAlignment); + + QQuickView view(testFileUrl("alignment.qml")); + QCOMPARE(view.status(), QQuickView::Ready); + view.show(); + view.requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(&view)); + + QQuickIconImage *iconImage = qobject_cast<QQuickIconImage*>(view.rootObject()->childItems().at(0)); + QVERIFY(iconImage); + + QQuickImage *image = qobject_cast<QQuickImage*>(view.rootObject()->childItems().at(1)); + QVERIFY(image); + + // The default fillMode for IconImage is Image::Pad, so these two grabs + // should only be equal when the device pixel ratio is 1 or 2, as there is no + // @3x version of the image, and hence the Image will be upscaled + // and therefore blurry when the ratio is higher than 2. + if (qGuiApp->devicePixelRatio() <= 2) + QCOMPARE(grabItemToImage(iconImage), grabItemToImage(image)); + else + QVERIFY(grabItemToImage(iconImage) != grabItemToImage(image)); + + // Check that the images are what we expect in different alignment configurations. + iconImage->setWidth(200); + iconImage->setHeight(100); + iconImage->setHorizontalAlignment(horizontalAlignment); + iconImage->setVerticalAlignment(verticalAlignment); + iconImage->setFillMode(QQuickImage::Pad); + image->setWidth(200); + image->setHeight(100); + image->setHorizontalAlignment(horizontalAlignment); + image->setVerticalAlignment(verticalAlignment); + image->setFillMode(QQuickImage::Pad); + + if (qGuiApp->devicePixelRatio() <= 2) + QCOMPARE(grabItemToImage(iconImage), grabItemToImage(image)); + else + QVERIFY(grabItemToImage(iconImage) != grabItemToImage(image)); +} + +void tst_qquickiconimage::svgNoSizes() +{ +#ifndef QT_SVG_LIB + QSKIP("This test requires qtsvg"); +#else + QQuickView view(testFileUrl("svgNoSizes.qml")); + QCOMPARE(view.status(), QQuickView::Ready); + view.show(); + view.requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(&view)); + + QQuickIconImage *iconImage = qobject_cast<QQuickIconImage*>(view.rootObject()->childItems().at(0)); + QVERIFY(iconImage); + + QQuickImage *image = qobject_cast<QQuickImage*>(view.rootObject()->childItems().at(1)); + QVERIFY(image); + + QCOMPARE(iconImage->sourceSize().width(), 48); + QCOMPARE(iconImage->sourceSize().height(), 48); + QCOMPARE(iconImage->implicitWidth(), 48.0); + QCOMPARE(iconImage->implicitHeight(), 48.0); + QCOMPARE(iconImage->width(), 48.0); + QCOMPARE(iconImage->height(), 48.0); + QCOMPARE(grabItemToImage(iconImage), grabItemToImage(image)); +#endif +} + +void tst_qquickiconimage::svgSourceBindingSourceSize() +{ +#ifndef QT_SVG_LIB + QSKIP("This test requires qtsvg"); +#else + QQuickView view(testFileUrl("alignment.qml")); + QCOMPARE(view.status(), QQuickView::Ready); + view.show(); + view.requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(&view)); + + QQuickIconImage *iconImage = qobject_cast<QQuickIconImage*>(view.rootObject()->childItems().at(0)); + QVERIFY(iconImage); + + QQuickImage *image = qobject_cast<QQuickImage*>(view.rootObject()->childItems().at(1)); + QVERIFY(image); + + QCOMPARE(iconImage->sourceSize().width(), 22); + QCOMPARE(iconImage->sourceSize().height(), 22); + QCOMPARE(iconImage->implicitWidth(), 22.0); + QCOMPARE(iconImage->implicitHeight(), 22.0); + QCOMPARE(iconImage->width(), 22.0); + QCOMPARE(iconImage->height(), 22.0); + QCOMPARE(grabItemToImage(iconImage), grabItemToImage(image)); +#endif +} + +void tst_qquickiconimage::color() +{ + SKIP_IF_DPR_TOO_HIGH(); + + QQuickView view(testFileUrl("color.qml")); + QCOMPARE(view.status(), QQuickView::Ready); + view.show(); + view.requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(&view)); + + QQuickIconImage *iconImage = qobject_cast<QQuickIconImage*>(view.rootObject()->childItems().at(0)); + QVERIFY(iconImage); + + QQuickImage *image = qobject_cast<QQuickImage*>(view.rootObject()->childItems().at(1)); + QVERIFY(image); + + QImage iconImageWindowGrab = grabItemToImage(iconImage); + QCOMPARE(iconImageWindowGrab, grabItemToImage(image)); + + // Transparent pixels should remain transparent. + QCOMPARE(iconImageWindowGrab.pixelColor(0, 0), QColor(0, 0, 0, 0)); + + // Set a color after component completion. + iconImage->setColor(QColor(Qt::green)); + iconImageWindowGrab = grabItemToImage(iconImage); + const QPoint centerPixelPos(11, 11); + QCOMPARE(iconImageWindowGrab.pixelColor(centerPixelPos), QColor(Qt::green)); + + // Set a semi-transparent color after component completion. + iconImage->setColor(QColor(0, 0, 255, 127)); + iconImageWindowGrab = grabItemToImage(iconImage); + QCOMPARE(iconImageWindowGrab.pixelColor(centerPixelPos).red(), 0); + QCOMPARE(iconImageWindowGrab.pixelColor(centerPixelPos).green(), 0); + QCOMPARE(iconImageWindowGrab.pixelColor(centerPixelPos).blue(), 255); + QCOMPARE(iconImageWindowGrab.pixelColor(centerPixelPos).alpha(), 127); +} + +void tst_qquickiconimage::changeSourceSize() +{ + QQuickView view(testFileUrl("sourceBindingSourceSize.qml")); + QCOMPARE(view.status(), QQuickView::Ready); + view.show(); + view.requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(&view)); + + QQuickIconImage *iconImage = qobject_cast<QQuickIconImage*>(view.rootObject()->childItems().at(0)); + QVERIFY(iconImage); + + // Ensure that there isn't any infinite recursion when trying to change the sourceSize. + QSize sourceSize = iconImage->sourceSize(); + sourceSize.setWidth(sourceSize.width() - 1); + iconImage->setSourceSize(sourceSize); +} + + +void tst_qquickiconimage::fileSelectors() +{ + SKIP_IF_DPR_TOO_HIGH(); + + QQuickView view; + QQmlFileSelector* fileSelector = new QQmlFileSelector(view.engine()); + fileSelector->setExtraSelectors(QStringList() << "testselector"); + view.setSource(testFileUrl("fileSelectors.qml")); + QCOMPARE(view.status(), QQuickView::Ready); + view.show(); + view.requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(&view)); + + QQuickIconImage *iconImage = qobject_cast<QQuickIconImage*>(view.rootObject()->childItems().at(0)); + QVERIFY(iconImage); + + QQuickItem *image = view.rootObject()->childItems().at(1); + QVERIFY(image); + + QImage iconImageWindowGrab = grabItemToImage(iconImage); + QCOMPARE(iconImageWindowGrab, grabItemToImage(image)); + + QCOMPARE(iconImageWindowGrab.pixelColor(iconImageWindowGrab.width() / 2, iconImageWindowGrab.height() / 2), QColor(Qt::blue)); +} + +int main(int argc, char *argv[]) +{ + QGuiApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); + QGuiApplication app(argc, argv); + Q_UNUSED(app); + tst_qquickiconimage test; + QTEST_SET_MAIN_SOURCE_PATH + return QTest::qExec(&test, argc, argv); +} + +#include "tst_qquickiconimage.moc" diff --git a/tests/auto/qquickiconlabel/data/colorChanges.qml b/tests/auto/qquickiconlabel/data/colorChanges.qml new file mode 100644 index 00000000..e60c32c8 --- /dev/null +++ b/tests/auto/qquickiconlabel/data/colorChanges.qml @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.9 +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 + +AbstractButton { + id: button + width: 200 + height: 200 + icon.source: "qrc:/qt-project.org/imports/QtQuick/Controls.2/images/check.png" + icon.color: enabled ? "transparent" : "red" + + IconLabel { + icon: button.icon + text: button.text + } +} diff --git a/tests/auto/qquickiconlabel/data/iconlabel.qml b/tests/auto/qquickiconlabel/data/iconlabel.qml new file mode 100644 index 00000000..7a1bafdf --- /dev/null +++ b/tests/auto/qquickiconlabel/data/iconlabel.qml @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.9 +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 + +AbstractButton { + id: button + width: 200 + height: 200 + text: "Some text" + icon.source: "qrc:/qt-project.org/imports/QtQuick/Controls.2/images/check.png" + + IconLabel { + icon: button.icon + text: button.text + } +} diff --git a/tests/auto/qquickiconlabel/data/spacingWithOnlyIcon.qml b/tests/auto/qquickiconlabel/data/spacingWithOnlyIcon.qml new file mode 100644 index 00000000..858f84b2 --- /dev/null +++ b/tests/auto/qquickiconlabel/data/spacingWithOnlyIcon.qml @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.9 +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 + +AbstractButton { + id: button + width: 200 + height: 200 + icon.source: "qrc:/qt-project.org/imports/QtQuick/Controls.2/images/check.png" + + IconLabel { + spacing: 10 + mirrored: true + icon: button.icon + } +} diff --git a/tests/auto/qquickiconlabel/data/spacingWithOnlyText.qml b/tests/auto/qquickiconlabel/data/spacingWithOnlyText.qml new file mode 100644 index 00000000..82eb5aee --- /dev/null +++ b/tests/auto/qquickiconlabel/data/spacingWithOnlyText.qml @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.9 +import QtQuick.Controls 2.3 +import QtQuick.Controls.impl 2.3 + +Item { + width: 200 + height: 200 + + IconLabel { + spacing: 10 + text: "Some text" + } +} diff --git a/tests/auto/qquickiconlabel/qquickiconlabel.pro b/tests/auto/qquickiconlabel/qquickiconlabel.pro new file mode 100644 index 00000000..6b0f73b3 --- /dev/null +++ b/tests/auto/qquickiconlabel/qquickiconlabel.pro @@ -0,0 +1,13 @@ +CONFIG += testcase +macos:CONFIG -= app_bundle +TARGET = tst_qquickiconlabel + +QT += core gui qml quick testlib +QT_PRIVATE += quick-private quickcontrols2-private + +include (../shared/util.pri) + +SOURCES += tst_qquickiconlabel.cpp + +TESTDATA += \ + $$PWD/data/*.qml diff --git a/tests/auto/qquickiconlabel/tst_qquickiconlabel.cpp b/tests/auto/qquickiconlabel/tst_qquickiconlabel.cpp new file mode 100644 index 00000000..a251b471 --- /dev/null +++ b/tests/auto/qquickiconlabel/tst_qquickiconlabel.cpp @@ -0,0 +1,326 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtCore/qvector.h> + +#include <qtest.h> + +#include <QtQuick/qquickitem.h> +#include <QtQuick/qquickview.h> +#include <QtQuick/qquickitemgrabresult.h> +#include <QtQuick/private/qquicktext_p.h> +#include <QtQuickTemplates2/private/qquickicon_p.h> +#include <QtQuickControls2/private/qquickiconimage_p.h> +#include <QtQuickControls2/private/qquickiconlabel_p.h> + +#include "../shared/util.h" +#include "../shared/visualtestutil.h" + +using namespace QQuickVisualTestUtil; + +class tst_qquickiconlabel : public QQmlDataTest +{ + Q_OBJECT +public: + tst_qquickiconlabel(); + +private slots: + void display_data(); + void display(); + void spacingWithOneDelegate_data(); + void spacingWithOneDelegate(); + void emptyIconSource(); + void colorChanges(); +}; + +tst_qquickiconlabel::tst_qquickiconlabel() +{ +} + +void tst_qquickiconlabel::display_data() +{ + QTest::addColumn<QVector<QQuickIconLabel::Display> >("displayTypes"); + QTest::addColumn<bool>("mirrored"); + QTest::addColumn<qreal>("labelWidth"); + QTest::addColumn<qreal>("labelHeight"); + QTest::addColumn<qreal>("spacing"); + + typedef QVector<QQuickIconLabel::Display> DisplayVector; + QQuickIconLabel::Display IconOnly = QQuickIconLabel::IconOnly; + QQuickIconLabel::Display TextOnly = QQuickIconLabel::TextOnly; + QQuickIconLabel::Display TextUnderIcon = QQuickIconLabel::TextUnderIcon; + QQuickIconLabel::Display TextBesideIcon = QQuickIconLabel::TextBesideIcon; + + QTest::addRow("IconOnly") << (DisplayVector() << IconOnly) << false << -1.0 << -1.0 << 0.0; + QTest::addRow("TextOnly") << (DisplayVector() << TextOnly) << false << -1.0 << -1.0 << 0.0; + QTest::addRow("TextUnderIcon") << (DisplayVector() << TextUnderIcon) << false << -1.0 << -1.0 << 10.0; + QTest::addRow("TextBesideIcon") << (DisplayVector() << TextBesideIcon) << false << -1.0 << -1.0 << 10.0; + QTest::addRow("IconOnly, spacing=10") << (DisplayVector() << IconOnly) << false << -1.0 << -1.0 << 10.0; + QTest::addRow("TextOnly, spacing=10") << (DisplayVector() << TextOnly) << false << -1.0 << -1.0 << 10.0; + QTest::addRow("TextUnderIcon, spacing=10") << (DisplayVector() << TextUnderIcon) << false << -1.0 << -1.0 << 0.0; + QTest::addRow("TextUnderIcon => IconOnly => TextUnderIcon") + << (DisplayVector() << TextUnderIcon << IconOnly << TextUnderIcon) << false << -1.0 << -1.0 << 0.0; + QTest::addRow("TextUnderIcon => IconOnly => TextUnderIcon, labelWidth=400") + << (DisplayVector() << TextUnderIcon << IconOnly << TextUnderIcon) << false << 400.0 << -1.0 << 0.0; + QTest::addRow("TextUnderIcon => TextOnly => TextUnderIcon") + << (DisplayVector() << TextUnderIcon << TextOnly << TextUnderIcon) << false << -1.0 << -1.0 << 0.0; + QTest::addRow("TextUnderIcon => TextOnly => TextUnderIcon, labelWidth=400") + << (DisplayVector() << TextUnderIcon << TextOnly << TextUnderIcon) << false << 400.0 << -1.0 << 0.0; + QTest::addRow("TextBesideIcon, spacing=10") << (DisplayVector() << TextBesideIcon) << false << -1.0 << -1.0 << 0.0; + QTest::addRow("TextBesideIcon => IconOnly => TextBesideIcon") + << (DisplayVector() << TextBesideIcon << IconOnly << TextBesideIcon) << false << -1.0 << -1.0 << 0.0; + QTest::addRow("TextBesideIcon => IconOnly => TextBesideIcon, labelWidth=400") + << (DisplayVector() << TextBesideIcon << IconOnly << TextBesideIcon) << false << 400.0 << -1.0 << 0.0; + QTest::addRow("TextBesideIcon => TextOnly => TextBesideIcon") + << (DisplayVector() << TextBesideIcon << TextOnly << TextBesideIcon) << false << -1.0 << -1.0 << 0.0; + QTest::addRow("TextBesideIcon => TextOnly => TextBesideIcon, labelWidth=400") + << (DisplayVector() << TextBesideIcon << TextOnly << TextBesideIcon) << false << 400.0 << -1.0 << 0.0; + QTest::addRow("IconOnly, mirrored") << (DisplayVector() << IconOnly) << true << -1.0 << -1.0 << 0.0; + QTest::addRow("TextOnly, mirrored") << (DisplayVector() << TextOnly) << true << -1.0 << -1.0 << 0.0; + QTest::addRow("TextUnderIcon, mirrored") << (DisplayVector() << TextUnderIcon) << true << -1.0 << -1.0 << 0.0; + QTest::addRow("TextBesideIcon, mirrored") << (DisplayVector() << TextBesideIcon) << true << -1.0 << -1.0 << 0.0; +} + +void tst_qquickiconlabel::display() +{ + QFETCH(QVector<QQuickIconLabel::Display>, displayTypes); + QFETCH(bool, mirrored); + QFETCH(qreal, labelWidth); + QFETCH(qreal, labelHeight); + QFETCH(qreal, spacing); + + QQuickView view(testFileUrl("iconlabel.qml")); + QCOMPARE(view.status(), QQuickView::Ready); + view.show(); + QVERIFY(QTest::qWaitForWindowExposed(&view)); + + QQuickItem *rootItem = view.rootObject(); + QVERIFY(rootItem); + + QQuickIconLabel *label = rootItem->findChild<QQuickIconLabel *>(); + QVERIFY(label); + QCOMPARE(label->spacing(), 0.0); + QCOMPARE(label->display(), QQuickIconLabel::TextBesideIcon); + QCOMPARE(label->isMirrored(), false); + + // Setting labelWidth allows us to test the issue where the icon's + // width was not updated after switching between different display types. + if (!qFuzzyCompare(labelWidth, -1)) { + label->setWidth(labelWidth); + QCOMPARE(label->width(), labelWidth); + } + if (!qFuzzyCompare(labelHeight, -1)) { + label->setHeight(labelHeight); + QCOMPARE(label->height(), labelHeight); + } + + label->setMirrored(mirrored); + QCOMPARE(label->isMirrored(), mirrored); + + label->setSpacing(spacing); + QCOMPARE(label->spacing(), spacing); + + const qreal horizontalPadding = label->leftPadding() + label->rightPadding(); + const qreal verticalPadding = label->topPadding() + label->bottomPadding(); + + // Test that the icon and text are correctly positioned and sized after + // setting several different display types in succession. + for (QQuickIconLabel::Display displayType : qAsConst(displayTypes)) { + label->setDisplay(displayType); + QCOMPARE(label->display(), displayType); + + QQuickIconImage *icon = label->findChild<QQuickIconImage *>(); + QQuickText *text = label->findChild<QQuickText *>(); + + const qreal horizontalCenter = label->width() / 2; + const qreal verticalCenter = label->height() / 2; + + switch (displayType) { + case QQuickIconLabel::IconOnly: + QVERIFY(icon); + QVERIFY(!text); + QCOMPARE(icon->x(), horizontalCenter - icon->width() / 2); + QCOMPARE(icon->y(), verticalCenter - icon->height() / 2); + QCOMPARE(icon->width(), icon->implicitWidth()); + QCOMPARE(icon->height(), icon->implicitHeight()); + QCOMPARE(label->implicitWidth(), icon->implicitWidth() + horizontalPadding); + QCOMPARE(label->implicitHeight(), icon->implicitHeight() + verticalPadding); + break; + case QQuickIconLabel::TextOnly: + QVERIFY(!icon); + QVERIFY(text); + QCOMPARE(text->x(), horizontalCenter - text->width() / 2); + QCOMPARE(text->y(), verticalCenter - text->height() / 2); + QCOMPARE(text->width(), text->implicitWidth()); + QCOMPARE(text->height(), text->implicitHeight()); + QCOMPARE(label->implicitWidth(), text->implicitWidth() + horizontalPadding); + QCOMPARE(label->implicitHeight(), text->implicitHeight() + verticalPadding); + break; + case QQuickIconLabel::TextUnderIcon: { + QVERIFY(icon); + QVERIFY(text); + const qreal combinedHeight = icon->height() + label->spacing() + text->height(); + const qreal contentY = verticalCenter - combinedHeight / 2; + QCOMPARE(icon->x(), horizontalCenter - icon->width() / 2); + QCOMPARE(icon->y(), contentY); + QCOMPARE(icon->width(), icon->implicitWidth()); + QCOMPARE(icon->height(), icon->implicitHeight()); + QCOMPARE(text->x(), horizontalCenter - text->width() / 2); + QCOMPARE(text->y(), contentY + icon->height() + label->spacing()); + QCOMPARE(text->width(), text->implicitWidth()); + QCOMPARE(text->height(), text->implicitHeight()); + QCOMPARE(label->implicitWidth(), qMax(icon->implicitWidth(), text->implicitWidth()) + horizontalPadding); + QCOMPARE(label->implicitHeight(), combinedHeight + verticalPadding); + break; + } + case QQuickIconLabel::TextBesideIcon: + default: + QVERIFY(icon); + QVERIFY(text); + const qreal combinedWidth = icon->width() + label->spacing() + text->width(); + const qreal contentX = horizontalCenter - combinedWidth / 2; + QCOMPARE(icon->x(), contentX + (label->isMirrored() ? text->width() + label->spacing() : 0)); + QCOMPARE(icon->y(), verticalCenter - icon->height() / 2); + QCOMPARE(icon->width(), icon->implicitWidth()); + QCOMPARE(icon->height(), icon->implicitHeight()); + QCOMPARE(text->x(), contentX + (label->isMirrored() ? 0 : icon->width() + label->spacing())); + QCOMPARE(text->y(), verticalCenter - text->height() / 2); + QCOMPARE(text->width(), text->implicitWidth()); + QCOMPARE(text->height(), text->implicitHeight()); + QCOMPARE(label->implicitWidth(), combinedWidth + horizontalPadding); + QCOMPARE(label->implicitHeight(), qMax(icon->implicitHeight(), text->implicitHeight()) + verticalPadding); + break; + } + } +} + +void tst_qquickiconlabel::spacingWithOneDelegate_data() +{ + QTest::addColumn<QString>("qmlFileName"); + + QTest::addRow("spacingWithOnlyIcon") << QStringLiteral("spacingWithOnlyIcon.qml"); + QTest::addRow("spacingWithOnlyText") << QStringLiteral("spacingWithOnlyText.qml"); +} + +void tst_qquickiconlabel::spacingWithOneDelegate() +{ + QFETCH(QString, qmlFileName); + + QQuickView view(testFileUrl(qmlFileName)); + QCOMPARE(view.status(), QQuickView::Ready); + view.show(); + QVERIFY(QTest::qWaitForWindowExposed(&view)); + + QQuickItem *rootItem = view.rootObject(); + QVERIFY(rootItem); + + QQuickIconLabel *label = rootItem->findChild<QQuickIconLabel *>(); + QVERIFY(label); + QQuickItem *delegate = nullptr; + if (!label->icon().isEmpty()) { + QVERIFY(!label->findChild<QQuickText *>()); + delegate = label->findChild<QQuickIconImage *>(); + } else { + QVERIFY(!label->findChild<QQuickIconImage *>()); + delegate = label->findChild<QQuickText *>(); + } + + QVERIFY(delegate); + QCOMPARE(delegate->x(), 0.0); + QCOMPARE(delegate->width(), label->width()); +} + +void tst_qquickiconlabel::emptyIconSource() +{ + QQuickView view(testFileUrl("iconlabel.qml")); + QCOMPARE(view.status(), QQuickView::Ready); + view.show(); + QVERIFY(QTest::qWaitForWindowExposed(&view)); + + QQuickItem *rootItem = view.rootObject(); + QVERIFY(rootItem); + + QQuickIconLabel *label = rootItem->findChild<QQuickIconLabel *>(); + QVERIFY(label); + QCOMPARE(label->spacing(), 0.0); + QCOMPARE(label->display(), QQuickIconLabel::TextBesideIcon); + QCOMPARE(label->isMirrored(), false); + + QQuickItem *icon = label->findChild<QQuickIconImage *>(); + QVERIFY(icon); + + QQuickItem *text = label->findChild<QQuickText *>(); + QVERIFY(text); + qreal horizontalCenter = label->width() / 2; + const qreal combinedWidth = icon->width() + text->width(); + const qreal contentX = horizontalCenter - combinedWidth / 2; + // The text should be positioned next to an item. + QCOMPARE(text->x(), contentX + icon->width() + label->spacing()); + + // Now give the label an explicit width large enough so that implicit size + // changes in its children don't affect its implicit size. + label->setWidth(label->implicitWidth() + 200); + label->setHeight(label->implicitWidth() + 100); + QVERIFY(icon->property("source").isValid()); + label->setIcon(QQuickIcon()); + QVERIFY(!label->findChild<QQuickIconImage *>()); + horizontalCenter = label->width() / 2; + QCOMPARE(text->x(), horizontalCenter - text->width() / 2); +} + +void tst_qquickiconlabel::colorChanges() +{ + QQuickView view(testFileUrl("colorChanges.qml")); + QCOMPARE(view.status(), QQuickView::Ready); + view.show(); + QVERIFY(QTest::qWaitForWindowExposed(&view)); + + QQuickItem *rootItem = view.rootObject(); + QVERIFY(rootItem); + + QQuickIconLabel *label = rootItem->findChild<QQuickIconLabel *>(); + QVERIFY(label); + QCOMPARE(label->spacing(), 0.0); + QCOMPARE(label->display(), QQuickIconLabel::TextBesideIcon); + QCOMPARE(label->isMirrored(), false); + + QSharedPointer<QQuickItemGrabResult> grabResult = label->grabToImage(); + QTRY_VERIFY(!grabResult->image().isNull()); + const QImage enabledImageGrab = grabResult->image(); + + // The color should change to "red" when the item is disabled. + rootItem->setEnabled(false); + + grabResult = label->grabToImage(); + QTRY_VERIFY(!grabResult->image().isNull()); + QVERIFY(grabResult->image() != enabledImageGrab); +} + +QTEST_MAIN(tst_qquickiconlabel) + +#include "tst_qquickiconlabel.moc" diff --git a/tests/auto/qquickmaterialstyleconf/qtquickcontrols2.conf b/tests/auto/qquickmaterialstyleconf/qtquickcontrols2.conf index 78634834..30cee878 100644 --- a/tests/auto/qquickmaterialstyleconf/qtquickcontrols2.conf +++ b/tests/auto/qquickmaterialstyleconf/qtquickcontrols2.conf @@ -4,3 +4,7 @@ Style=Material [Material] Background=#444444 Foreground=Red +Font\PixelSize=22 + +[Material\Font] +Family=Courier diff --git a/tests/auto/qquickmaterialstyleconf/tst_qquickmaterialstyleconf.cpp b/tests/auto/qquickmaterialstyleconf/tst_qquickmaterialstyleconf.cpp index cc81afea..17d1ea6d 100644 --- a/tests/auto/qquickmaterialstyleconf/tst_qquickmaterialstyleconf.cpp +++ b/tests/auto/qquickmaterialstyleconf/tst_qquickmaterialstyleconf.cpp @@ -55,16 +55,22 @@ void tst_qquickmaterialstyleconf::conf() { QQuickApplicationHelper helper(this, QLatin1String("applicationwindow.qml")); + QFont customFont; + customFont.setFamily("Courier"); + customFont.setPixelSize(22); + QQuickApplicationWindow *window = helper.appWindow; window->show(); QVERIFY(QTest::qWaitForWindowExposed(window)); - // We specified a custom background color, so the window should have it. + // We specified a custom background color and font, so the window should have them. QCOMPARE(window->property("color").value<QColor>(), QColor("#444444")); + QCOMPARE(window->property("font").value<QFont>(), customFont); - // We specified a custom foreground color, so the label should have it. + // We specified a custom foreground color and font, so the label should have them. QQuickItem *label = window->property("label").value<QQuickItem*>(); QVERIFY(label); QCOMPARE(label->property("color").value<QColor>(), QColor("#F44336")); + QCOMPARE(label->property("font").value<QFont>(), customFont); } QTEST_MAIN(tst_qquickmaterialstyleconf) diff --git a/tests/auto/qquickstyleselector/data/PlatformStyle/+linux/Button.qml b/tests/auto/qquickstyleselector/data/PlatformStyle/+linux/Button.qml new file mode 100644 index 00000000..ee17c230 --- /dev/null +++ b/tests/auto/qquickstyleselector/data/PlatformStyle/+linux/Button.qml @@ -0,0 +1,2 @@ +import QtQuick.Templates 2.1 as T +T.Button { } diff --git a/tests/auto/qquickstyleselector/data/PlatformStyle/+macos/Button.qml b/tests/auto/qquickstyleselector/data/PlatformStyle/+macos/Button.qml new file mode 100644 index 00000000..ee17c230 --- /dev/null +++ b/tests/auto/qquickstyleselector/data/PlatformStyle/+macos/Button.qml @@ -0,0 +1,2 @@ +import QtQuick.Templates 2.1 as T +T.Button { } diff --git a/tests/auto/qquickstyleselector/data/PlatformStyle/+windows/Button.qml b/tests/auto/qquickstyleselector/data/PlatformStyle/+windows/Button.qml new file mode 100644 index 00000000..ee17c230 --- /dev/null +++ b/tests/auto/qquickstyleselector/data/PlatformStyle/+windows/Button.qml @@ -0,0 +1,2 @@ +import QtQuick.Templates 2.1 as T +T.Button { } diff --git a/tests/auto/qquickstyleselector/data/PlatformStyle/Button.qml b/tests/auto/qquickstyleselector/data/PlatformStyle/Button.qml new file mode 100644 index 00000000..ee17c230 --- /dev/null +++ b/tests/auto/qquickstyleselector/data/PlatformStyle/Button.qml @@ -0,0 +1,2 @@ +import QtQuick.Templates 2.1 as T +T.Button { } diff --git a/tests/auto/qquickstyleselector/tst_qquickstyleselector.cpp b/tests/auto/qquickstyleselector/tst_qquickstyleselector.cpp index 598320d2..e90a8bd9 100644 --- a/tests/auto/qquickstyleselector/tst_qquickstyleselector.cpp +++ b/tests/auto/qquickstyleselector/tst_qquickstyleselector.cpp @@ -49,6 +49,8 @@ private slots: void select_data(); void select(); + + void platformSelectors(); }; void tst_QQuickStyleSelector::initTestCase() @@ -139,6 +141,24 @@ void tst_QQuickStyleSelector::select() QCOMPARE(selector.select(file), expected); } +void tst_QQuickStyleSelector::platformSelectors() +{ + QQuickStyle::setStyle(QDir(dataDirectory()).filePath("PlatformStyle")); + + QQuickStyleSelector selector; + selector.setBaseUrl(dataDirectoryUrl()); + +#if defined(Q_OS_LINUX) + QCOMPARE(selector.select("Button.qml"), testFileUrl("PlatformStyle/+linux/Button.qml").toString()); +#elif defined(Q_OS_MACOS) + QCOMPARE(selector.select("Button.qml"), testFileUrl("PlatformStyle/+macos/Button.qml").toString()); +#elif defined(Q_OS_WIN) + QCOMPARE(selector.select("Button.qml"), testFileUrl("PlatformStyle/+windows/Button.qml").toString()); +#else + QCOMPARE(selector.select("Button.qml"), testFileUrl("PlatformStyle/Button.qml").toString()); +#endif +} + QTEST_MAIN(tst_QQuickStyleSelector) #include "tst_qquickstyleselector.moc" diff --git a/tests/auto/qquickuniversalstyleconf/qtquickcontrols2.conf b/tests/auto/qquickuniversalstyleconf/qtquickcontrols2.conf index 836372c9..0ec13258 100644 --- a/tests/auto/qquickuniversalstyleconf/qtquickcontrols2.conf +++ b/tests/auto/qquickuniversalstyleconf/qtquickcontrols2.conf @@ -4,3 +4,7 @@ Style=Universal [Universal] Background=#444444 Foreground=Red +Font\PixelSize=22 + +[Universal\Font] +Family=Courier diff --git a/tests/auto/qquickuniversalstyleconf/tst_qquickuniversalstyleconf.cpp b/tests/auto/qquickuniversalstyleconf/tst_qquickuniversalstyleconf.cpp index c6b28be3..51cc5883 100644 --- a/tests/auto/qquickuniversalstyleconf/tst_qquickuniversalstyleconf.cpp +++ b/tests/auto/qquickuniversalstyleconf/tst_qquickuniversalstyleconf.cpp @@ -55,16 +55,22 @@ void tst_qquickuniversalstyleconf::conf() { QQuickApplicationHelper helper(this, QLatin1String("applicationwindow.qml")); + QFont customFont; + customFont.setFamily("Courier"); + customFont.setPixelSize(22); + QQuickApplicationWindow *window = helper.appWindow; window->show(); QVERIFY(QTest::qWaitForWindowExposed(window)); - // We specified a custom background color, so the window should have it. + // We specified a custom background color and font, so the window should have them. QCOMPARE(window->property("color").value<QColor>(), QColor("#444444")); + QCOMPARE(window->property("font").value<QFont>(), customFont); - // We specified a custom foreground color, so the label should have it. + // We specified a custom foreground color and font, so the label should have them. QQuickItem *label = window->property("label").value<QQuickItem*>(); QVERIFY(label); QCOMPARE(label->property("color").value<QColor>(), QColor("#E51400")); + QCOMPARE(label->property("font").value<QFont>(), customFont); } QTEST_MAIN(tst_qquickuniversalstyleconf) diff --git a/tests/auto/sanity/tst_sanity.cpp b/tests/auto/sanity/tst_sanity.cpp index 2988c96c..25e118e3 100644 --- a/tests/auto/sanity/tst_sanity.cpp +++ b/tests/auto/sanity/tst_sanity.cpp @@ -314,6 +314,7 @@ void tst_Sanity::attachedObjects_data() QTest::addColumn<QUrl>("url"); addTestRows(&engine, "calendar", "Qt/labs/calendar"); addTestRows(&engine, "controls", "QtQuick/Controls.2", QStringList() << "CheckIndicator" << "RadioIndicator" << "SwitchIndicator"); + addTestRows(&engine, "controls/fusion", "QtQuick/Controls.2", QStringList() << "CheckIndicator" << "RadioIndicator" << "SliderGroove" << "SliderHandle" << "SwitchIndicator"); addTestRows(&engine, "controls/material", "QtQuick/Controls.2/Material", QStringList() << "Ripple" << "SliderHandle" << "CheckIndicator" << "RadioIndicator" << "SwitchIndicator" << "BoxShadow" << "ElevationEffect" << "CursorDelegate"); addTestRows(&engine, "controls/universal", "QtQuick/Controls.2/Universal", QStringList() << "CheckIndicator" << "RadioIndicator" << "SwitchIndicator"); } diff --git a/tests/benchmarks/objectcount/tst_objectcount.cpp b/tests/benchmarks/objectcount/tst_objectcount.cpp index d12f3293..551d2009 100644 --- a/tests/benchmarks/objectcount/tst_objectcount.cpp +++ b/tests/benchmarks/objectcount/tst_objectcount.cpp @@ -124,6 +124,7 @@ static void addTestRows(QQmlEngine *engine, const QString &sourcePath, const QSt static void initTestRows(QQmlEngine *engine) { addTestRows(engine, "controls", "QtQuick/Controls.2", QStringList() << "CheckIndicator" << "RadioIndicator" << "SwitchIndicator"); + addTestRows(engine, "controls/fusion", "QtQuick/Controls.2/Fusion", QStringList() << "ButtonPanel" << "CheckIndicator" << "RadioIndicator" << "SliderGroove" << "SliderHandle" << "SwitchIndicator"); addTestRows(engine, "controls/material", "QtQuick/Controls.2/Material", QStringList() << "Ripple" << "SliderHandle" << "CheckIndicator" << "RadioIndicator" << "SwitchIndicator" << "BoxShadow" << "ElevationEffect" << "CursorDelegate"); addTestRows(engine, "controls/universal", "QtQuick/Controls.2/Universal", QStringList() << "CheckIndicator" << "RadioIndicator" << "SwitchIndicator"); } diff --git a/tests/manual/testbench/testbench.qml b/tests/manual/testbench/testbench.qml index 2ebb9923..3bb38fe8 100644 --- a/tests/manual/testbench/testbench.qml +++ b/tests/manual/testbench/testbench.qml @@ -66,8 +66,11 @@ ApplicationWindow { y = Screen.height / 2 - height / 2 } - Material.theme: themeSwitch.checked ? Material.Dark : Material.Light - Universal.theme: themeSwitch.checked ? Universal.Dark : Universal.Light + LayoutMirroring.childrenInherit: true + LayoutMirroring.enabled: mirroredMenuItem.checked + + Material.theme: darkMenuItem.checked ? Material.Dark : Material.Light + Universal.theme: darkMenuItem.checked ? Universal.Dark : Universal.Light property int controlSpacing: 10 @@ -82,95 +85,157 @@ ApplicationWindow { RowLayout { anchors.fill: parent + RowLayout { + enabled: enabledMenuItem.checked + + ToolButton { + text: "ToolButton" + hoverEnabled: true + ToolTip.text: text + ToolTip.delay: 1000 + ToolTip.visible: hovered + } + ToolButton { + text: "Pressed" + down: true + hoverEnabled: true + ToolTip.text: text + ToolTip.delay: 1000 + ToolTip.visible: hovered + } + ToolButton { + text: "Checked" + checkable: true + checked: true + hoverEnabled: true + ToolTip.text: text + ToolTip.delay: 1000 + ToolTip.visible: hovered + } + ToolButton { + text: "Highlighted" + highlighted: true + hoverEnabled: true + ToolTip.text: text + ToolTip.delay: 1000 + ToolTip.visible: hovered + } + ToolButton { + text: "Disabled" + enabled: false + } + + ToolSeparator {} + + ToolButton { + text: "1" + } + ToolButton { + text: "2" + } + + ToolSeparator {} + + ToolButton { + id: menuButton + text: "Menu" + hoverEnabled: true + ToolTip.text: text + ToolTip.delay: 1000 + ToolTip.visible: hovered + checked: menu.visible + checkable: true + + Menu { + id: menu + x: 1 + y: 1 + parent.height + visible: menuButton.checked + closePolicy: Popup.CloseOnPressOutsideParent + + MenuItem { + text: "MenuItem" + } + MenuItem { + text: "Pressed" + down: true + } + MenuItem { + text: "Disabled" + enabled: false + } + + MenuSeparator {} + + MenuItem { + text: "Checked" + checked: true + } + MenuItem { + text: "CH+PR" + checked: true + down: true + } + MenuItem { + text: "CH+DIS" + checked: true + enabled: false + } + } + } + } + + Item { + Layout.fillWidth: true + } + ToolButton { - text: "Normal" - hoverEnabled: true - ToolTip.text: text - ToolTip.delay: 1000 - ToolTip.visible: hovered - onClicked: menu.visible ? menu.close() : menu.open() + id: optionsMenuButton + text: "\u22EE" // VERTICAL ELLIPSIS + checked: optionsMenu.visible + checkable: true Menu { - id: menu + id: optionsMenu x: 1 y: 1 + parent.height + visible: optionsMenuButton.checked + closePolicy: Popup.CloseOnPressOutsideParent MenuItem { - text: "Option 1" + id: enabledMenuItem + text: "Enabled" checkable: true + checked: true } + MenuItem { - text: "Option 2" + id: mirroredMenuItem + text: "Mirrored" checkable: true } + MenuItem { - text: "Option 3" + id: darkMenuItem + text: "Dark" checkable: true } MenuSeparator {} MenuItem { - text: "Option A" + text: "Quit" + onTriggered: Qt.quit() } } } - ToolButton { - text: "Pressed" - down: true - hoverEnabled: true - ToolTip.text: text - ToolTip.delay: 1000 - ToolTip.visible: hovered - } - ToolButton { - text: "Checked" - checkable: true - checked: true - hoverEnabled: true - ToolTip.text: text - ToolTip.delay: 1000 - ToolTip.visible: hovered - } - ToolButton { - text: "Highlighted" - highlighted: true - hoverEnabled: true - ToolTip.text: text - ToolTip.delay: 1000 - ToolTip.visible: hovered - } - ToolButton { - text: "Disabled" - enabled: false - } - - ToolSeparator {} - - ToolButton { - text: "1" - } - ToolButton { - text: "2" - } - - ToolSeparator {} - - Item { - Layout.fillWidth: true - } - Label { - text: "Light/Dark" - } - Switch { - id: themeSwitch - } } } footer: TabBar { + enabled: enabledMenuItem.checked TabButton { - text: "Normal" + text: "TabButton" } TabButton { text: "Pressed" @@ -193,12 +258,13 @@ ApplicationWindow { id: flow width: parent.width spacing: 30 + enabled: enabledMenuItem.checked RowLayout { spacing: window.controlSpacing Button { - text: "Normal" + text: "Button" } Button { text: "Pressed" @@ -263,36 +329,6 @@ ApplicationWindow { RowLayout { spacing: window.controlSpacing * 2 - Button { - text: "Normal" - } - Button { - text: "Pressed" - down: true - } - Button { - text: "Checked" - checked: true - } - Button { - text: "CH + PR" - checked: true - down: true - } - Button { - text: "Disabled" - enabled: false - } - Button { - text: "CH + DIS" - enabled: false - checked: true - } - } - - RowLayout { - spacing: window.controlSpacing * 2 - ColumnLayout { RoundButton { highlighted: true @@ -364,7 +400,7 @@ ApplicationWindow { RowLayout { CheckBox { - text: "Normal" + text: "CheckBox" } CheckBox { text: "Pressed" @@ -391,8 +427,42 @@ ApplicationWindow { } RowLayout { + CheckBox { + text: "Tri-state\nCheckBox" + tristate: true + } + CheckBox { + text: "Pressed" + down: true + tristate: true + } + CheckBox { + text: "Partially\nChecked" + tristate: true + checkState: Qt.PartiallyChecked + } + CheckBox { + text: "CH + PR" + tristate: true + checkState: Qt.PartiallyChecked + down: true + } + CheckBox { + text: "Disabled" + tristate: true + enabled: false + } + CheckBox { + text: "CH + DIS" + tristate: true + checkState: Qt.PartiallyChecked + enabled: false + } + } + + RowLayout { RadioButton { - text: "Normal" + text: "RadioButton" } RadioButton { text: "Pressed" @@ -420,7 +490,7 @@ ApplicationWindow { RowLayout { Switch { - text: "Normal" + text: "Switch" } Switch { text: "Pressed" @@ -439,11 +509,16 @@ ApplicationWindow { text: "Disabled" enabled: false } + Switch { + text: "CH + DIS" + checked: true + enabled: false + } } RowLayout { ProgressBar { - value: 0.5 + value: slider.value } ProgressBar { value: 0.5 @@ -457,6 +532,7 @@ ApplicationWindow { RowLayout { Slider { + id: slider value: 0.5 } Slider { @@ -487,149 +563,110 @@ ApplicationWindow { } RowLayout { - Item { - implicitWidth: normalGroupBox.width - implicitHeight: normalTextArea.implicitHeight + spacing: window.controlSpacing * 2 - TextArea { - id: normalTextArea - text: "Normal" - } + TextArea { + text: "TextArea" + Layout.preferredWidth: normalGroupBox.implicitWidth } - Item { - implicitWidth: normalGroupBox.width - implicitHeight: normalTextArea.implicitHeight - TextArea { - placeholderText: "Placeholder" - } + TextArea { + placeholderText: "Placeholder" + Layout.preferredWidth: normalGroupBox.implicitWidth } - Item { - implicitWidth: normalGroupBox.width - implicitHeight: normalTextArea.implicitHeight - TextArea { - text: "Disabled" - enabled: false - } + TextArea { + text: "Disabled" + enabled: false + Layout.preferredWidth: normalGroupBox.implicitWidth } } RowLayout { - Item { - implicitWidth: normalGroupBox.implicitWidth - implicitHeight: normalTextField.implicitHeight + spacing: window.controlSpacing * 2 - TextField { - id: normalTextField - text: "Normal" - } + TextField { + text: "TextField" } - Item { - implicitWidth: normalGroupBox.implicitWidth - implicitHeight: normalTextField.implicitHeight - - TextField { - placeholderText: "Placeholder" - } + TextField { + placeholderText: "Placeholder" } - Item { - implicitWidth: normalGroupBox.implicitWidth - implicitHeight: normalTextField.implicitHeight - - TextField { - text: "Disabled" - enabled: false - } + TextField { + text: "Disabled" + enabled: false } } RowLayout { - Item { - implicitWidth: normalGroupBox.implicitWidth - implicitHeight: normalSpinBox.implicitHeight + spacing: window.controlSpacing * 2 - SpinBox { - id: normalSpinBox - } + SpinBox { + id: normalSpinBox } - Item { - implicitWidth: normalGroupBox.implicitWidth - implicitHeight: normalSpinBox.implicitHeight - - SpinBox { - up.pressed: true - } + SpinBox { + up.pressed: true } - Item { - implicitWidth: normalGroupBox.implicitWidth - implicitHeight: normalSpinBox.implicitHeight - - SpinBox { - enabled: false - } + SpinBox { + editable: true + } + SpinBox { + enabled: false } } RowLayout { - Item { - implicitWidth: normalGroupBox.implicitWidth - implicitHeight: normalComboBox.implicitHeight + spacing: window.controlSpacing * 2 - ComboBox { - id: normalComboBox - model: 5 - } + ComboBox { + model: 5 } - Item { - implicitWidth: normalGroupBox.implicitWidth - implicitHeight: normalComboBox.implicitHeight + ComboBox { + pressed: true + model: ["Pressed"] + } - ComboBox { - pressed: true - model: ListModel { - ListElement { text: "Pressed" } - } + ComboBox { + editable: true + model: ListModel { + id: fruitModel + ListElement { text: "Banana" } + ListElement { text: "Apple" } + ListElement { text: "Coconut" } + } + onAccepted: { + if (find(editText) === -1) + fruitModel.append({text: editText}) } } - Item { - implicitWidth: normalGroupBox.implicitWidth - implicitHeight: normalComboBox.implicitHeight - - ComboBox { - enabled: false - model: ["Disabled"] - } + ComboBox { + enabled: false + model: ["Disabled"] } } RowLayout { GroupBox { id: normalGroupBox - title: "Normal" + title: "GroupBox" - Item { - implicitWidth: 200 - implicitHeight: 100 + contentWidth: 200 + contentHeight: 100 - BusyIndicator { - anchors.centerIn: parent - } + BusyIndicator { + anchors.centerIn: parent } } GroupBox { enabled: false title: "Disabled" - Item { - implicitWidth: 200 - implicitHeight: 100 + contentWidth: 200 + contentHeight: 100 - BusyIndicator { - anchors.centerIn: parent - } + BusyIndicator { + anchors.centerIn: parent } } GroupBox { @@ -637,16 +674,14 @@ ApplicationWindow { title: "." label.visible: false - Item { - implicitWidth: 200 - implicitHeight: 100 + contentWidth: 200 + contentHeight: 100 - PageIndicator { - count: 5 - enabled: false - anchors.bottom: parent.bottom - anchors.horizontalCenter: parent.horizontalCenter - } + PageIndicator { + count: 5 + enabled: false + anchors.bottom: parent.bottom + anchors.horizontalCenter: parent.horizontalCenter } } } @@ -655,79 +690,77 @@ ApplicationWindow { Frame { id: scrollBarFrame - Item { - implicitWidth: 200 - implicitHeight: 100 + padding: 0 + contentWidth: 200 + contentHeight: 100 - Label { - text: "Normal" - anchors.centerIn: parent - } + Label { + text: "ScrollBar" + anchors.centerIn: parent + } - ScrollBar { - size: 0.3 - position: 0.2 - active: true - orientation: Qt.Vertical - height: parent.height - anchors.right: parent.right - } + ScrollBar { + size: 0.6 + position: 0.1 + policy: ScrollBar.AlwaysOn + orientation: Qt.Vertical + height: parent.height + anchors.right: parent.right } } Frame { - Item { - implicitWidth: 200 - implicitHeight: 100 + padding: 0 + contentWidth: 200 + contentHeight: 100 - Label { - text: "Pressed" - anchors.centerIn: parent - } + Label { + text: "Pressed" + anchors.centerIn: parent + } - ScrollBar { - size: 0.3 - position: 0.2 - active: true - orientation: Qt.Vertical - height: parent.height - anchors.right: parent.right - pressed: true - } + ScrollBar { + size: 0.6 + position: 0.1 + policy: ScrollBar.AlwaysOn + orientation: Qt.Vertical + height: parent.height + anchors.right: parent.right + pressed: true } } Frame { - Item { - implicitWidth: 200 - implicitHeight: 100 - enabled: false + padding: 0 + contentWidth: 200 + contentHeight: 100 + enabled: false - Label { - text: "Disabled" - anchors.centerIn: parent - } + Label { + text: "Disabled" + anchors.centerIn: parent + } - ScrollBar { - size: 0.3 - position: 0.2 - active: true - orientation: Qt.Vertical - height: parent.height - anchors.right: parent.right - } + ScrollBar { + size: 0.6 + position: 0.1 + policy: ScrollBar.AlwaysOn + orientation: Qt.Vertical + height: parent.height + anchors.right: parent.right } } } RowLayout { Frame { + padding: 0 Layout.preferredWidth: 100 Layout.preferredHeight: 100 ScrollIndicator { - size: 0.3 - position: 0.2 + size: 0.6 + position: 0.1 active: true orientation: Qt.Vertical height: parent.height @@ -736,12 +769,13 @@ ApplicationWindow { } Frame { + padding: 0 Layout.preferredWidth: 100 Layout.preferredHeight: 100 ScrollIndicator { - size: 0.3 - position: 0.2 + size: 0.6 + position: 0.1 active: true orientation: Qt.Vertical height: parent.height @@ -771,10 +805,12 @@ ApplicationWindow { RowLayout { Dial { + value: 0.5 implicitWidth: 100 implicitHeight: 100 } Dial { + value: 0.5 implicitWidth: 100 implicitHeight: 100 enabled: false @@ -783,11 +819,11 @@ ApplicationWindow { ListModel { id: checkableDelegateModel - ListElement { label: "Normal" } ListElement { label: "Pressed"; press: true } ListElement { label: "Checked"; check: true } ListElement { label: "CH + PR"; check: true; press: true } ListElement { label: "Disabled"; disabled: true } + ListElement { label: "CH + DIS"; check: true; disabled: true } } RowLayout { @@ -795,6 +831,12 @@ ApplicationWindow { Column { width: 200 + CheckDelegate { + text: "CheckDelegate" + width: parent.width + focusPolicy: Qt.StrongFocus + } + Repeater { model: checkableDelegateModel delegate: CheckDelegate { @@ -803,20 +845,22 @@ ApplicationWindow { down: press checked: check enabled: !disabled - ButtonGroup.group: radioButtonGroup + focusPolicy: Qt.StrongFocus } } } } - ButtonGroup { - id: radioButtonGroup - } - Frame { Column { width: 200 + RadioDelegate { + text: "RadioDelegate" + width: parent.width + focusPolicy: Qt.StrongFocus + } + Repeater { model: checkableDelegateModel delegate: RadioDelegate { @@ -825,7 +869,7 @@ ApplicationWindow { width: parent.width checked: check enabled: !disabled - ButtonGroup.group: radioButtonGroup + focusPolicy: Qt.StrongFocus } } } @@ -835,6 +879,12 @@ ApplicationWindow { Column { width: 200 + SwitchDelegate { + text: "SwitchDelegate" + width: parent.width + focusPolicy: Qt.StrongFocus + } + Repeater { model: checkableDelegateModel delegate: SwitchDelegate { @@ -843,6 +893,7 @@ ApplicationWindow { checked: check down: press enabled: !disabled + focusPolicy: Qt.StrongFocus } } } @@ -851,7 +902,6 @@ ApplicationWindow { ListModel { id: regularDelegateModel - ListElement { label: "Normal" } ListElement { label: "Pressed"; press: true } ListElement { label: "Disabled"; disabled: true } } @@ -861,6 +911,12 @@ ApplicationWindow { Column { width: 200 + ItemDelegate { + text: "ItemDelegate" + width: parent.width + focusPolicy: Qt.StrongFocus + } + Repeater { model: regularDelegateModel delegate: ItemDelegate { @@ -868,6 +924,7 @@ ApplicationWindow { width: parent.width down: press enabled: !disabled + focusPolicy: Qt.StrongFocus } } } @@ -878,41 +935,55 @@ ApplicationWindow { width: 200 clip: true + SwipeDelegate { + text: "SwipeDelegate" + width: parent.width + swipe.left: removeComponent + swipe.right: removeComponent + focusPolicy: Qt.StrongFocus + } + Repeater { model: regularDelegateModel delegate: SwipeDelegate { - id: swipeDelegate text: label width: parent.width down: press enabled: !disabled - - Component { - id: removeComponent - - Rectangle { - color: swipeDelegate.swipe.complete && swipeDelegate.pressed ? "#333" : "#444" - width: parent.width - height: parent.height - clip: true - - Label { - font.pixelSize: swipeDelegate.font.pixelSize - text: "Boop" - color: "white" - anchors.centerIn: parent - } - } - } + focusPolicy: Qt.StrongFocus swipe.left: removeComponent swipe.right: removeComponent } } + + Component { + id: removeComponent + + Rectangle { + color: parent.swipe.complete && parent.pressed ? "#333" : "#444" + width: parent.width + height: parent.height + clip: true + + Label { + font.pixelSize: parent.parent.font.pixelSize + text: "Boop" + color: "white" + anchors.centerIn: parent + } + } + } } } } } + + ScrollBar.vertical: ScrollBar { + parent: window.contentItem + x: parent.width - width + height: parent.height + } } } } |