diff options
332 files changed, 9080 insertions, 1536 deletions
@@ -39,6 +39,9 @@ /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 8114dfd7..00c9f8dd 100644 --- a/.qmake.conf +++ b/.qmake.conf @@ -4,4 +4,4 @@ DEFINES += QT_NO_FOREACH QQC2_SOURCE_TREE = $$PWD -MODULE_VERSION = 5.9.0 +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/+material/back.png b/examples/quickcontrols2/gallery/icons/gallery/20x20/+material/back.png Binary files differindex ebc1000f..ebc1000f 100644 --- a/examples/quickcontrols2/gallery/images/+material/back.png +++ b/examples/quickcontrols2/gallery/icons/gallery/20x20/+material/back.png diff --git a/examples/quickcontrols2/gallery/images/+material/drawer.png b/examples/quickcontrols2/gallery/icons/gallery/20x20/+material/drawer.png Binary files differindex 615cc817..615cc817 100644 --- a/examples/quickcontrols2/gallery/images/+material/drawer.png +++ b/examples/quickcontrols2/gallery/icons/gallery/20x20/+material/drawer.png diff --git a/examples/quickcontrols2/gallery/images/+material/menu.png b/examples/quickcontrols2/gallery/icons/gallery/20x20/+material/menu.png Binary files differindex f02429e9..f02429e9 100644 --- a/examples/quickcontrols2/gallery/images/+material/menu.png +++ b/examples/quickcontrols2/gallery/icons/gallery/20x20/+material/menu.png 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/+material/back@2x.png b/examples/quickcontrols2/gallery/icons/gallery/20x20@2/+material/back.png Binary files differindex cf6163c8..cf6163c8 100644 --- a/examples/quickcontrols2/gallery/images/+material/back@2x.png +++ b/examples/quickcontrols2/gallery/icons/gallery/20x20@2/+material/back.png diff --git a/examples/quickcontrols2/gallery/images/+material/drawer@2x.png b/examples/quickcontrols2/gallery/icons/gallery/20x20@2/+material/drawer.png Binary files differindex b1dd106d..b1dd106d 100644 --- a/examples/quickcontrols2/gallery/images/+material/drawer@2x.png +++ b/examples/quickcontrols2/gallery/icons/gallery/20x20@2/+material/drawer.png diff --git a/examples/quickcontrols2/gallery/images/+material/menu@2x.png b/examples/quickcontrols2/gallery/icons/gallery/20x20@2/+material/menu.png Binary files differindex 9309ad9a..9309ad9a 100644 --- a/examples/quickcontrols2/gallery/images/+material/menu@2x.png +++ b/examples/quickcontrols2/gallery/icons/gallery/20x20@2/+material/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/+material/back@3x.png b/examples/quickcontrols2/gallery/icons/gallery/20x20@3/+material/back.png Binary files differindex 96376a5a..96376a5a 100644 --- a/examples/quickcontrols2/gallery/images/+material/back@3x.png +++ b/examples/quickcontrols2/gallery/icons/gallery/20x20@3/+material/back.png diff --git a/examples/quickcontrols2/gallery/images/+material/drawer@3x.png b/examples/quickcontrols2/gallery/icons/gallery/20x20@3/+material/drawer.png Binary files differindex 289889bf..289889bf 100644 --- a/examples/quickcontrols2/gallery/images/+material/drawer@3x.png +++ b/examples/quickcontrols2/gallery/icons/gallery/20x20@3/+material/drawer.png diff --git a/examples/quickcontrols2/gallery/images/+material/menu@3x.png b/examples/quickcontrols2/gallery/icons/gallery/20x20@3/+material/menu.png Binary files differindex 7bddf71f..7bddf71f 100644 --- a/examples/quickcontrols2/gallery/images/+material/menu@3x.png +++ b/examples/quickcontrols2/gallery/icons/gallery/20x20@3/+material/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/+material/back@4x.png b/examples/quickcontrols2/gallery/icons/gallery/20x20@4/+material/back.png Binary files differindex 578ac14f..578ac14f 100644 --- a/examples/quickcontrols2/gallery/images/+material/back@4x.png +++ b/examples/quickcontrols2/gallery/icons/gallery/20x20@4/+material/back.png diff --git a/examples/quickcontrols2/gallery/images/+material/drawer@4x.png b/examples/quickcontrols2/gallery/icons/gallery/20x20@4/+material/drawer.png Binary files differindex 215e6a82..215e6a82 100644 --- a/examples/quickcontrols2/gallery/images/+material/drawer@4x.png +++ b/examples/quickcontrols2/gallery/icons/gallery/20x20@4/+material/drawer.png diff --git a/examples/quickcontrols2/gallery/images/+material/menu@4x.png b/examples/quickcontrols2/gallery/icons/gallery/20x20@4/+material/menu.png Binary files differindex e5c23a3b..e5c23a3b 100644 --- a/examples/quickcontrols2/gallery/images/+material/menu@4x.png +++ b/examples/quickcontrols2/gallery/icons/gallery/20x20@4/+material/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/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/ApplicationWindow.qml b/src/imports/controls/ApplicationWindow.qml index 1dd39279..9a81812f 100644 --- a/src/imports/controls/ApplicationWindow.qml +++ b/src/imports/controls/ApplicationWindow.qml @@ -35,10 +35,10 @@ ****************************************************************************/ 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 import QtQuick.Window 2.2 -import QtQuick.Templates 2.2 as T +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..a645e45e 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 diff --git a/src/imports/controls/Button.qml b/src/imports/controls/Button.qml index 6c150d5d..438265d1 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,23 @@ T.Button { padding: 6 leftPadding: padding + 2 rightPadding: padding + 2 + spacing: 6 - contentItem: Text { + icon.width: 24 + icon.height: 24 + icon.color: enabled ? undefined : Default.textDisabledLightColor + + 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/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..095e1949 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 ? undefined : Default.textDisabledLightColor + + 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 48feaec6..e6a1e8a8 100644 --- a/src/imports/controls/ComboBox.qml +++ b/src/imports/controls/ComboBox.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.ComboBox { id: control @@ -60,12 +60,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 } 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..db8203fe 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 @@ -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..507dfd2d 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 ? undefined : Default.textDisabledLightColor + 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..9e4ce902 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 diff --git a/src/imports/controls/MenuItem.qml b/src/imports/controls/MenuItem.qml index d2420d86..73d921c2 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 ? undefined : Default.textDisabledLightColor + + 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..3edc24fa 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 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..89d4b12a 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 ? undefined : Default.textDisabledLightColor + + 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 85ee00a0..1d8a561d 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,22 +79,18 @@ 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 diff --git a/src/imports/controls/RoundButton.qml b/src/imports/controls/RoundButton.qml index 6b4000b1..747988d8 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,24 @@ T.RoundButton { baselineOffset: contentItem.y + contentItem.baselineOffset padding: 6 + spacing: 6 - contentItem: Text { + icon.width: 24 + icon.height: 24 + icon.color: enabled ? undefined : Default.textDisabledLightColor + + 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..5ee85607 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,17 @@ 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 - - readonly property bool horizontal: control.orientation === Qt.Horizontal + scale: control.horizontal && control.mirrored ? -1 : 1 } } 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..acbabe2c 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,19 +52,22 @@ T.SwipeDelegate { padding: 12 spacing: 12 + icon.width: 24 + icon.height: 24 + icon.color: enabled ? undefined : Default.textDisabledLightColor + 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 { 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..287e174c 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 ? undefined : Default.textDisabledLightColor + 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..039f9769 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: !enabled ? Default.textDisabledLightColor : !checked ? Default.textLightColor : Default.textColor + + 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..184bbfad 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 ? undefined : 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.pro b/src/imports/controls/controls.pro index 1d57973f..145b468c 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/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/screenshots/qtquickcontrols2-button-icononly.qml b/src/imports/controls/doc/snippets/screenshots/qtquickcontrols2-button-icononly.qml new file mode 100644 index 00000000..0a58d4ad --- /dev/null +++ b/src/imports/controls/doc/snippets/screenshots/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/screenshots/qtquickcontrols2-button-textbesideicon.qml b/src/imports/controls/doc/snippets/screenshots/qtquickcontrols2-button-textbesideicon.qml new file mode 100644 index 00000000..308837f7 --- /dev/null +++ b/src/imports/controls/doc/snippets/screenshots/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/screenshots/qtquickcontrols2-button-textonly.qml b/src/imports/controls/doc/snippets/screenshots/qtquickcontrols2-button-textonly.qml new file mode 100644 index 00000000..89d335e4 --- /dev/null +++ b/src/imports/controls/doc/snippets/screenshots/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..1bfa0119 --- /dev/null +++ b/src/imports/controls/doc/src/includes/qquickicon.qdocinc @@ -0,0 +1,36 @@ +//! [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. +\endtable +//! [grouped-properties] 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-index.qdoc b/src/imports/controls/doc/src/qtquickcontrols2-index.qdoc index 056c4ec3..4f0771a6 100644 --- a/src/imports/controls/doc/src/qtquickcontrols2-index.qdoc +++ b/src/imports/controls/doc/src/qtquickcontrols2-index.qdoc @@ -71,7 +71,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 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-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/material/ApplicationWindow.qml b/src/imports/controls/material/ApplicationWindow.qml index 82a0d135..14dd4637 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.2 -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..9e21c8a0 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,27 @@ T.Button { padding: 12 leftPadding: padding - 4 rightPadding: padding - 4 + spacing: 6 + + icon.width: 24 + icon.height: 24 + icon.color: enabled ? undefined : Material.hintTextColor 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..431fcb16 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 ? undefined : 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 d3e6d588..c2bdff65 100644 --- a/src/imports/controls/material/ComboBox.qml +++ b/src/imports/controls/material/ComboBox.qml @@ -35,10 +35,11 @@ ****************************************************************************/ 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.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 @@ -66,12 +67,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 { diff --git a/src/imports/controls/material/CursorDelegate.qml b/src/imports/controls/material/CursorDelegate.qml index 0880bc0a..cecca0b4 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..5a9f844e 100644 --- a/src/imports/controls/material/DelayButton.qml +++ b/src/imports/controls/material/DelayButton.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.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..5d46109b 100644 --- a/src/imports/controls/material/Dialog.qml +++ b/src/imports/controls/material/Dialog.qml @@ -35,10 +35,10 @@ ****************************************************************************/ 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.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..f66ecda3 100644 --- a/src/imports/controls/material/DialogButtonBox.qml +++ b/src/imports/controls/material/DialogButtonBox.qml @@ -35,10 +35,10 @@ ****************************************************************************/ 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.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..e9a75186 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 ? undefined : 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..9767eed0 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 diff --git a/src/imports/controls/material/MenuItem.qml b/src/imports/controls/material/MenuItem.qml index 5a136231..7c4e93fe 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 ? undefined : 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..18a2de35 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 ? undefined : 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..ac5949d9 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,27 @@ T.RoundButton { // external vertical padding is 6 (to increase touch area) padding: 12 + spacing: 6 + + icon.width: 24 + icon.height: 24 + icon.color: enabled ? undefined : Material.hintTextColor 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..c84ee702 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 ? undefined : 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..c1591178 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 ? undefined : 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..c794a468 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 ? undefined : Material.hintTextColor + + 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 72e937f3..08d5e3ab 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..f75fa8a5 100644 --- a/src/imports/controls/material/qquickmaterialtheme.cpp +++ b/src/imports/controls/material/qquickmaterialtheme.cpp @@ -110,14 +110,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/qtquickcontrols2materialstyleplugin.cpp b/src/imports/controls/material/qtquickcontrols2materialstyleplugin.cpp index 3f3a66b0..0c162d2c 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,8 +85,6 @@ 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... diff --git a/src/imports/controls/plugins.qmltypes b/src/imports/controls/plugins.qmltypes index 1e1b9d0f..7f779637 100644 --- a/src/imports/controls/plugins.qmltypes +++ b/src/imports/controls/plugins.qmltypes @@ -4,15 +4,37 @@ 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" @@ -85,6 +107,43 @@ Module { Property { name: "color"; type: "QColor" } } Component { + name: "QQuickIconImage" + defaultProperty: "data" + prototype: "QQuickImage" + exports: ["QtQuick.Controls.impl/IconImage 2.3"] + exportMetaObjectRevisions: [0] + 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"; isPointer: true } + 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: "QQuickPlaceholderText" defaultProperty: "data" prototype: "QQuickText" @@ -537,6 +596,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"; isReadonly: true; isPointer: true } + 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,9 +606,91 @@ Module { Signal { name: "toggled"; revision: 2 } Signal { name: "pressAndHold" } Signal { name: "doubleClicked" } + 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"; isReadonly: true; isPointer: true } + 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: "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" @@ -902,6 +1046,35 @@ Module { Property { name: "label"; type: "QQuickItem"; isPointer: true } } Component { + name: "QQuickIcon" + prototype: "QObject" + Property { name: "name"; type: "string" } + Property { name: "source"; type: "string" } + Property { name: "width"; type: "int" } + Property { name: "height"; type: "int" } + Property { name: "color"; type: "QColor" } + Signal { + name: "nameChanged" + Parameter { name: "name"; type: "string" } + } + Signal { + name: "sourceChanged" + Parameter { name: "source"; type: "string" } + } + Signal { + name: "widthChanged" + Parameter { name: "width"; type: "int" } + } + Signal { + name: "heightChanged" + Parameter { name: "height"; type: "int" } + } + Signal { + name: "colorChanged" + Parameter { name: "color"; type: "QColor" } + } + } + Component { name: "QQuickItemDelegate" defaultProperty: "data" prototype: "QQuickAbstractButton" @@ -1140,9 +1313,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 +1332,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 +1369,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 +1399,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 +1425,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 +1470,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 +1491,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 } @@ -1512,6 +1699,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 } } 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/qtquickcontrols2plugin.cpp b/src/imports/controls/qtquickcontrols2plugin.cpp index 848f55b5..aa4eb295 100644 --- a/src/imports/controls/qtquickcontrols2plugin.cpp +++ b/src/imports/controls/qtquickcontrols2plugin.cpp @@ -36,15 +36,21 @@ #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/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/qquickaction_p.h> +#include <QtQuickTemplates2/private/qquickactiongroup_p.h> #include <QtQuickTemplates2/private/qquickbuttongroup_p.h> +#include <QtQuickTemplates2/private/qquickicon_p.h> #include "qquickdefaultbusyindicator_p.h" #include "qquickdefaultprogressbar_p.h" @@ -148,6 +154,11 @@ 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<QQuickAction>(uri, 2, 3, "Action"); + qmlRegisterType<QQuickActionGroup>(uri, 2, 3, "ActionGroup"); + qmlRegisterType<QQuickIcon>(); } static QObject *styleSingleton(QQmlEngine *engine, QJSEngine *scriptEngine) @@ -157,11 +168,16 @@ 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) +{ + Q_UNUSED(engine); 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... @@ -177,6 +193,11 @@ 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"); } QT_END_NAMESPACE diff --git a/src/imports/controls/universal/ApplicationWindow.qml b/src/imports/controls/universal/ApplicationWindow.qml index a9d03c8c..e359b1bf 100644 --- a/src/imports/controls/universal/ApplicationWindow.qml +++ b/src/imports/controls/universal/ApplicationWindow.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.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..44f86a38 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: enabled ? undefined : Color.transparent(Universal.foreground, 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 95ed29e0..5d866d06 100644 --- a/src/imports/controls/universal/CheckDelegate.qml +++ b/src/imports/controls/universal/CheckDelegate.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.CheckDelegate { id: control @@ -54,25 +56,29 @@ T.CheckDelegate { topPadding: padding - 1 bottomPadding: padding + 1 + icon.width: 20 + icon.height: 20 + icon.color: enabled ? undefined : Color.transparent(Universal.foreground, 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 5a6ced60..5ec5bbee 100644 --- a/src/imports/controls/universal/ComboBox.qml +++ b/src/imports/controls/universal/ComboBox.qml @@ -35,9 +35,10 @@ ****************************************************************************/ 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.Controls.impl 2.3 +import QtQuick.Templates 2.3 as T +import QtQuick.Controls.Universal 2.3 T.ComboBox { id: control @@ -61,12 +62,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 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..0ccac5b9 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: enabled ? undefined : Color.transparent(Universal.foreground, 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..60dc8904 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 diff --git a/src/imports/controls/universal/MenuItem.qml b/src/imports/controls/universal/MenuItem.qml index 35e2f2ba..35def542 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 ? undefined : Color.transparent(Universal.foreground, 0.2) + 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 62b74e0c..bc15f990 100644 --- a/src/imports/controls/universal/RadioDelegate.qml +++ b/src/imports/controls/universal/RadioDelegate.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.RadioDelegate { id: control @@ -54,25 +56,29 @@ T.RadioDelegate { topPadding: padding - 1 bottomPadding: padding + 1 + icon.width: 20 + icon.height: 20 + icon.color: enabled ? undefined : Color.transparent(Universal.foreground, 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..759f5113 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: enabled ? undefined : Color.transparent(Universal.foreground, 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..23f327d1 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: enabled ? undefined : Color.transparent(Universal.foreground, 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 e3dde0dc..a507a953 100644 --- a/src/imports/controls/universal/Switch.qml +++ b/src/imports/controls/universal/Switch.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.Switch { id: control diff --git a/src/imports/controls/universal/SwitchDelegate.qml b/src/imports/controls/universal/SwitchDelegate.qml index 59b71817..af7f403e 100644 --- a/src/imports/controls/universal/SwitchDelegate.qml +++ b/src/imports/controls/universal/SwitchDelegate.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.SwitchDelegate { id: control @@ -54,25 +56,29 @@ T.SwitchDelegate { topPadding: padding - 1 bottomPadding: padding + 1 + icon.width: 20 + icon.height: 20 + icon.color: enabled ? undefined : Color.transparent(Universal.foreground, 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..a13181a2 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: enabled ? undefined : Color.transparent(Universal.foreground, 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/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 f2515205..d9bae111 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/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..13d9e205 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"] @@ -24,6 +24,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"; isReadonly: true; isPointer: true } + 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,9 +34,91 @@ Module { Signal { name: "toggled"; revision: 2 } Signal { name: "pressAndHold" } Signal { name: "doubleClicked" } + 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"; isReadonly: true; isPointer: true } + 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: "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" @@ -389,6 +474,35 @@ Module { Property { name: "label"; type: "QQuickItem"; isPointer: true } } Component { + name: "QQuickIcon" + prototype: "QObject" + Property { name: "name"; type: "string" } + Property { name: "source"; type: "string" } + Property { name: "width"; type: "int" } + Property { name: "height"; type: "int" } + Property { name: "color"; type: "QColor" } + Signal { + name: "nameChanged" + Parameter { name: "name"; type: "string" } + } + Signal { + name: "sourceChanged" + Parameter { name: "source"; type: "string" } + } + Signal { + name: "widthChanged" + Parameter { name: "width"; type: "int" } + } + Signal { + name: "heightChanged" + Parameter { name: "height"; type: "int" } + } + Signal { + name: "colorChanged" + Parameter { name: "color"; type: "QColor" } + } + } + Component { name: "QQuickItemDelegate" defaultProperty: "data" prototype: "QQuickAbstractButton" @@ -627,9 +741,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 +760,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 +797,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 +827,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 +853,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 +898,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 +919,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 } @@ -999,6 +1127,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 } } diff --git a/src/imports/templates/qtquicktemplates2plugin.cpp b/src/imports/templates/qtquicktemplates2plugin.cpp index dd79ac5b..e16a0e45 100644 --- a/src/imports/templates/qtquicktemplates2plugin.cpp +++ b/src/imports/templates/qtquicktemplates2plugin.cpp @@ -37,6 +37,8 @@ #include <QtQml/qqmlextensionplugin.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 +55,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> @@ -178,21 +181,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"); @@ -201,10 +204,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); // QtQuick.Templates 2.1 (new types and revisions in Qt 5.8) qmlRegisterType<QQuickButtonGroup, 1>(uri, 2, 1, "ButtonGroup"); @@ -252,6 +255,17 @@ void QtQuickTemplates2Plugin::registerTypes(const char *uri) // make revisioned properties available to their subclasses (synced with Qt 5.9) qmlRegisterRevision<QQuickText, 9>(uri, 2, 2); qmlRegisterRevision<QQuickTextInput, 9>(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<QQuickIcon>(); + 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..9a95812b 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 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..629fc0cb --- /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 = pix.implicitSize() / 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..61151f28 --- /dev/null +++ b/src/quickcontrols2/qquickiconlabel.cpp @@ -0,0 +1,659 @@ +/**************************************************************************** +** +** 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> +#include <QtQuickTemplates2/private/qquickicon_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), + icon(nullptr), + image(nullptr), + label(nullptr) +{ +} + +bool QQuickIconLabelPrivate::hasIcon() const +{ + return display != QQuickIconLabel::TextOnly && icon && (!icon->name().isEmpty() || !icon->source().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) + return; + + image->setName(icon->name()); + image->setSource(icon->source()); +} + +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::updateIcon() +{ + if (!image || !icon) + return; + + image->setColor(icon->color()); + image->setSourceSize(QSize(icon->width(), icon->height())); +} + +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(QQuickIcon *icon) +{ + Q_D(QQuickIconLabel); + if (d->icon == icon) + return; + + if (QQuickIcon *oldIcon = d->icon) { + QObjectPrivate::disconnect(oldIcon, &QQuickIcon::nameChanged, d, &QQuickIconLabelPrivate::updateOrSyncImage); + QObjectPrivate::disconnect(oldIcon, &QQuickIcon::sourceChanged, d, &QQuickIconLabelPrivate::updateOrSyncImage); + QObjectPrivate::disconnect(oldIcon, &QQuickIcon::colorChanged, d, &QQuickIconLabelPrivate::updateIcon); + QObjectPrivate::disconnect(oldIcon, &QQuickIcon::widthChanged, d, &QQuickIconLabelPrivate::updateIcon); + QObjectPrivate::disconnect(oldIcon, &QQuickIcon::heightChanged, d, &QQuickIconLabelPrivate::updateIcon); + } + + d->icon = icon; + if (icon) { + QObjectPrivate::connect(icon, &QQuickIcon::nameChanged, d, &QQuickIconLabelPrivate::updateOrSyncImage); + QObjectPrivate::connect(icon, &QQuickIcon::sourceChanged, d, &QQuickIconLabelPrivate::updateOrSyncImage); + QObjectPrivate::connect(icon, &QQuickIcon::colorChanged, d, &QQuickIconLabelPrivate::updateIcon); + QObjectPrivate::connect(icon, &QQuickIcon::widthChanged, d, &QQuickIconLabelPrivate::updateIcon); + QObjectPrivate::connect(icon, &QQuickIcon::heightChanged, d, &QQuickIconLabelPrivate::updateIcon); + } + + 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..63b7fbd2 --- /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> + +QT_BEGIN_NAMESPACE + +class QQuickIcon; +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(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..00c2d404 --- /dev/null +++ b/src/quickcontrols2/qquickiconlabel_p_p.h @@ -0,0 +1,115 @@ +/**************************************************************************** +** +** 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 QQuickIcon; +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 updateIcon(); + 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/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/quickcontrols2.pri b/src/quickcontrols2/quickcontrols2.pri index a618989e..7124027b 100644 --- a/src/quickcontrols2/quickcontrols2.pri +++ b/src/quickcontrols2/quickcontrols2.pri @@ -1,11 +1,16 @@ 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/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 \ @@ -13,11 +18,14 @@ HEADERS += \ SOURCES += \ $$PWD/qquickanimatednode.cpp \ - $$PWD/qquickcolorimageprovider.cpp \ + $$PWD/qquickattachedobject.cpp \ + $$PWD/qquickcolor.cpp \ + $$PWD/qquickcolorimage.cpp \ + $$PWD/qquickiconimage.cpp \ + $$PWD/qquickiconlabel.cpp \ $$PWD/qquickplaceholdertext.cpp \ $$PWD/qquickproxytheme.cpp \ $$PWD/qquickstyle.cpp \ - $$PWD/qquickstyleattached.cpp \ $$PWD/qquickstyleplugin.cpp \ $$PWD/qquickstyleselector.cpp \ $$PWD/qquickpaddedrectangle.cpp diff --git a/src/quicktemplates2/qquickabstractbutton.cpp b/src/quicktemplates2/qquickabstractbutton.cpp index 0207d2f9..96faf2d5 100644 --- a/src/quicktemplates2/qquickabstractbutton.cpp +++ b/src/quicktemplates2/qquickabstractbutton.cpp @@ -37,6 +37,9 @@ #include "qquickabstractbutton_p.h" #include "qquickabstractbutton_p_p.h" #include "qquickbuttongroup_p.h" +#include "qquickicon_p.h" +#include "qquickaction_p.h" +#include "qquickaction_p_p.h" #include <QtGui/qstylehints.h> #include <QtGui/qguiapplication.h> @@ -63,6 +66,37 @@ 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. + \section1 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. + + Each \l {Styling Qt Quick Controls 2}{style} sets a default size for + icons, but it is possible to override this by setting the \l icon.width and + \l icon.height 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 \l display property can be used to control how the icon and text are + displayed within the button. + \sa ButtonGroup, {Button Controls} */ @@ -126,7 +160,10 @@ QQuickAbstractButtonPrivate::QQuickAbstractButtonPrivate() repeatTimer(0), pressButtons(Qt::NoButton), indicator(nullptr), - group(nullptr) + group(nullptr), + icon(nullptr), + display(QQuickAbstractButton::TextBesideIcon), + action(nullptr) { } @@ -173,7 +210,7 @@ void QQuickAbstractButtonPrivate::handleRelease(const QPointF &point) if (wasPressed) { emit q->released(); if (!wasHeld) - emit q->clicked(); + trigger(); } else { emit q->canceled(); } @@ -249,6 +286,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 +506,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 +541,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 +623,151 @@ 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 {Control::}{contentItem} +*/ + +QQuickIcon *QQuickAbstractButton::icon() const +{ + QQuickAbstractButtonPrivate *d = const_cast<QQuickAbstractButtonPrivate*>(d_func()); + if (!d->icon) { + d->icon = new QQuickIcon; + QQml_setParent_noEvent(d->icon, const_cast<QQuickAbstractButton*>(this)); + } + return d->icon; +} + +/*! + \since QtQuick.Controls 2.3 + \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 + \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::checkedChanged, this, &QQuickAbstractButton::setChecked); + disconnect(oldAction, &QQuickAction::checkableChanged, this, &QQuickAbstractButton::setCheckable); + disconnect(oldAction, &QQuickAction::enabledChanged, this, &QQuickItem::setEnabled); + + QQuickIcon *actionIcon = QQuickActionPrivate::get(oldAction)->icon; + if (actionIcon && d->icon) { + disconnect(actionIcon, &QQuickIcon::nameChanged, d->icon, &QQuickIcon::setName); + disconnect(actionIcon, &QQuickIcon::sourceChanged, d->icon, &QQuickIcon::setSource); + disconnect(actionIcon, &QQuickIcon::widthChanged, d->icon, &QQuickIcon::setWidth); + disconnect(actionIcon, &QQuickIcon::heightChanged, d->icon, &QQuickIcon::setHeight); + disconnect(actionIcon, &QQuickIcon::colorChanged, d->icon, &QQuickIcon::setColor); + } + } + + 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::checkedChanged, this, &QQuickAbstractButton::setChecked); + connect(action, &QQuickAction::checkableChanged, this, &QQuickAbstractButton::setCheckable); + connect(action, &QQuickAction::enabledChanged, this, &QQuickItem::setEnabled); + + QQuickIcon *actionIcon = QQuickActionPrivate::get(action)->icon; + if (actionIcon) { + QQuickIcon *buttonIcon = icon(); + connect(actionIcon, &QQuickIcon::nameChanged, buttonIcon, &QQuickIcon::setName); + connect(actionIcon, &QQuickIcon::sourceChanged, buttonIcon, &QQuickIcon::setSource); + connect(actionIcon, &QQuickIcon::widthChanged, buttonIcon, &QQuickIcon::setWidth); + connect(actionIcon, &QQuickIcon::heightChanged, buttonIcon, &QQuickIcon::setHeight); + connect(actionIcon, &QQuickIcon::colorChanged, buttonIcon, &QQuickIcon::setColor); + + QString name = actionIcon->name(); + if (!name.isEmpty()) + buttonIcon->setName(name); + + QUrl source = actionIcon->source(); + if (!source.isEmpty()) + buttonIcon->setSource(source); + + int width = actionIcon->width(); + if (width > 0) + buttonIcon->setWidth(width); + + int height = actionIcon->height(); + if (height) + buttonIcon->setHeight(height); + + QColor color = actionIcon->color(); + if (color != Qt::transparent) + buttonIcon->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 +811,7 @@ void QQuickAbstractButton::keyReleaseEvent(QKeyEvent *event) nextCheckState(); emit released(); - emit clicked(); + d->trigger(); if (d->autoRepeat) d->stopPressRepeat(); @@ -642,7 +844,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..c6a50665 100644 --- a/src/quicktemplates2/qquickabstractbutton_p.h +++ b/src/quicktemplates2/qquickabstractbutton_p.h @@ -52,6 +52,8 @@ QT_BEGIN_NAMESPACE +class QQuickIcon; +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 CONSTANT FINAL REVISION 3) + Q_PROPERTY(Display display READ display WRITE setDisplay NOTIFY displayChanged REVISION 3) + Q_PROPERTY(QQuickAction *action READ action WRITE setAction NOTIFY actionChanged FINAL REVISION 3) public: explicit QQuickAbstractButton(QQuickItem *parent = nullptr); @@ -94,6 +99,22 @@ public: QQuickItem *indicator() const; void setIndicator(QQuickItem *indicator); + QQuickIcon *icon() const; + + 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 +133,8 @@ Q_SIGNALS: void checkableChanged(); void autoExclusiveChanged(); void indicatorChanged(); + 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..61a546d1 100644 --- a/src/quicktemplates2/qquickabstractbutton_p_p.h +++ b/src/quicktemplates2/qquickabstractbutton_p_p.h @@ -53,7 +53,9 @@ QT_BEGIN_NAMESPACE +class QQuickAction; class QQuickButtonGroup; +class QQuickIcon; class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickAbstractButtonPrivate : public QQuickControlPrivate { @@ -83,6 +85,8 @@ public: QQuickAbstractButton *findCheckedButton() const; QList<QQuickAbstractButton *> findExclusiveButtons() const; + void click(); + void trigger(); void toggle(bool value); QString text; @@ -102,6 +106,9 @@ public: Qt::MouseButtons pressButtons; QQuickItem *indicator; QQuickButtonGroup *group; + QQuickIcon *icon; + 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..e6b1cedb --- /dev/null +++ b/src/quicktemplates2/qquickaction.cpp @@ -0,0 +1,549 @@ +/**************************************************************************** +** +** 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 "qquickicon_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), + icon(nullptr), + 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 +{ + QQuickActionPrivate *d = const_cast<QQuickActionPrivate *>(d_func()); + if (!d->icon) { + d->icon = new QQuickIcon; + QQml_setParent_noEvent(d->icon, const_cast<QQuickAction *>(this)); + } + return d->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..d47b847e --- /dev/null +++ b/src/quicktemplates2/qquickaction_p.h @@ -0,0 +1,120 @@ +/**************************************************************************** +** +** 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 <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 CONSTANT 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; + + 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 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..85da6b03 --- /dev/null +++ b/src/quicktemplates2/qquickaction_p_p.h @@ -0,0 +1,128 @@ +/**************************************************************************** +** +** 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 QQuickIcon; +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..4a445d9b 100644 --- a/src/quicktemplates2/qquickapplicationwindow.cpp +++ b/src/quicktemplates2/qquickapplicationwindow.cpp @@ -251,6 +251,29 @@ 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::_q_updateActiveFocus() { Q_Q(QQuickApplicationWindow); @@ -614,28 +637,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 diff --git a/src/quicktemplates2/qquickbutton.cpp b/src/quicktemplates2/qquickbutton.cpp index 1a614754..d324feb2 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} */ diff --git a/src/quicktemplates2/qquickcontrol.cpp b/src/quicktemplates2/qquickcontrol.cpp index c039253d..d57c3260 100644 --- a/src/quicktemplates2/qquickcontrol.cpp +++ b/src/quicktemplates2/qquickcontrol.cpp @@ -293,29 +293,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 /*! @@ -423,6 +400,58 @@ void QQuickControlPrivate::updateFontRecur(QQuickItem *item, const QFont &f) } } +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); + } +} + #if QT_CONFIG(quicktemplates2_hover) void QQuickControlPrivate::updateHoverEnabled(bool enabled, bool xplicit) { @@ -481,48 +510,26 @@ 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) @@ -887,80 +894,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 @@ -1476,4 +1409,73 @@ void QQuickControl::localeChange(const QLocale &newLocale, const QLocale &oldLoc Q_UNUSED(oldLocale); } +#if QT_CONFIG(accessibility) +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 + +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) +{ +#if QT_CONFIG(accessibility) + Q_D(QQuickControl); + if (d->accessibleAttached) + d->accessibleAttached->setName(name); +#else + Q_UNUSED(name) +#endif +} + +QVariant QQuickControl::accessibleProperty(const char *propertyName) +{ +#if QT_CONFIG(accessibility) + Q_D(QQuickControl); + if (d->accessibleAttached) + return QQuickAccessibleAttached::property(this, propertyName); +#endif + Q_UNUSED(propertyName) + return QVariant(); +} + +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; +} + QT_END_NAMESPACE diff --git a/src/quicktemplates2/qquickcontrol_p.h b/src/quicktemplates2/qquickcontrol_p.h index 6ad89376..feb6646e 100644 --- a/src/quicktemplates2/qquickcontrol_p.h +++ b/src/quicktemplates2/qquickcontrol_p.h @@ -204,8 +204,8 @@ protected: virtual void localeChange(const QLocale &newLocale, const QLocale &oldLocale); #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 4dd6f32a..a6825640 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> diff --git a/src/quicktemplates2/qquickdrawer_p_p.h b/src/quicktemplates2/qquickdrawer_p_p.h index 8956acef..dba3032e 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/qquickicon.cpp b/src/quicktemplates2/qquickicon.cpp new file mode 100644 index 00000000..38d0b2af --- /dev/null +++ b/src/quicktemplates2/qquickicon.cpp @@ -0,0 +1,151 @@ +/**************************************************************************** +** +** 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 <QtCore/private/qobject_p.h> +#include "qquickicon_p.h" + +QT_BEGIN_NAMESPACE + +class QQuickIconPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QQuickIcon) + +public: + QQuickIconPrivate() + : width(0), + height(0), + color(Qt::transparent) + { + } + + QString name; + QUrl source; + int width; + int height; + QColor color; +}; + +QQuickIcon::QQuickIcon(QObject *parent) + : QObject(*(new QQuickIconPrivate), parent) +{ +} + +QString QQuickIcon::name() const +{ + Q_D(const QQuickIcon); + return d->name; +} + +void QQuickIcon::setName(const QString &name) +{ + Q_D(QQuickIcon); + if (name == d->name) + return; + + d->name = name; + emit nameChanged(name); +} + +QUrl QQuickIcon::source() const +{ + Q_D(const QQuickIcon); + return d->source; +} + +void QQuickIcon::setSource(const QUrl &source) +{ + Q_D(QQuickIcon); + if (source == d->source) + return; + + d->source = source; + emit sourceChanged(source); +} + +int QQuickIcon::width() const +{ + Q_D(const QQuickIcon); + return d->width; +} + +void QQuickIcon::setWidth(int width) +{ + Q_D(QQuickIcon); + if (width == d->width) + return; + + d->width = width; + emit widthChanged(width); +} + +int QQuickIcon::height() const +{ + Q_D(const QQuickIcon); + return d->height; +} + +void QQuickIcon::setHeight(int height) +{ + Q_D(QQuickIcon); + if (height == d->height) + return; + + d->height = height; + emit heightChanged(height); +} + +QColor QQuickIcon::color() const +{ + Q_D(const QQuickIcon); + return d->color; +} + +void QQuickIcon::setColor(const QColor &color) +{ + Q_D(QQuickIcon); + if (color == d->color) + return; + + d->color = color; + emit colorChanged(color); +} + +void QQuickIcon::resetColor() +{ + setColor(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..4b1557a0 --- /dev/null +++ b/src/quicktemplates2/qquickicon_p.h @@ -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 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/qobject.h> +#include <QtQuickTemplates2/private/qtquicktemplates2global_p.h> +#include <QtGui/qcolor.h> + +QT_BEGIN_NAMESPACE + +class QQuickIconPrivate; + +class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickIcon : public QObject +{ + Q_OBJECT + Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged FINAL) + Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged FINAL) + Q_PROPERTY(int width READ width WRITE setWidth NOTIFY widthChanged FINAL) + Q_PROPERTY(int height READ height WRITE setHeight NOTIFY heightChanged FINAL) + Q_PROPERTY(QColor color READ color WRITE setColor RESET resetColor NOTIFY colorChanged FINAL) + +public: + explicit QQuickIcon(QObject *parent = nullptr); + + 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(); + +Q_SIGNALS: + void nameChanged(const QString &name); + void sourceChanged(const QUrl &source); + void widthChanged(int width); + void heightChanged(int height); + void colorChanged(const QColor &color); + +private: + Q_DISABLE_COPY(QQuickIcon) + Q_DECLARE_PRIVATE(QQuickIcon) +}; + +QT_END_NAMESPACE + +#endif // QQUICKICON_P_H diff --git a/src/quicktemplates2/qquickitemdelegate.cpp b/src/quicktemplates2/qquickitemdelegate.cpp index 1b93c145..fb540a49 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 diff --git a/src/quicktemplates2/qquickmenuitem.cpp b/src/quicktemplates2/qquickmenuitem.cpp index e15640fb..0c6c80a3 100644 --- a/src/quicktemplates2/qquickmenuitem.cpp +++ b/src/quicktemplates2/qquickmenuitem.cpp @@ -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 @@ -110,11 +114,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 +140,11 @@ void QQuickMenuItem::setHighlighted(bool highlighted) emit highlightedChanged(); } +QFont QQuickMenuItem::defaultFont() const +{ + return QQuickControlPrivate::themeFont(QPlatformTheme::MenuItemFont); +} + #if QT_CONFIG(accessibility) QAccessible::Role QQuickMenuItem::accessibleRole() const { diff --git a/src/quicktemplates2/qquickoverlay_p_p.h b/src/quicktemplates2/qquickoverlay_p_p.h index fa53d52b..de8539c9 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/qquickpopup.cpp b/src/quicktemplates2/qquickpopup.cpp index 68a82204..775d4e6a 100644 --- a/src/quicktemplates2/qquickpopup.cpp +++ b/src/quicktemplates2/qquickpopup.cpp @@ -649,6 +649,7 @@ QQuickPopup::~QQuickPopup() setParentItem(nullptr); d->popupItem->ungrabShortcut(); delete d->popupItem; + d->popupItem = nullptr; } /*! diff --git a/src/quicktemplates2/qquickpopup_p_p.h b/src/quicktemplates2/qquickpopup_p_p.h index 5c2fe4f7..476e691d 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_p_p.h b/src/quicktemplates2/qquickpopupitem_p_p.h index 16321feb..9b3c76df 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 diff --git a/src/quicktemplates2/qquickrangeslider.cpp b/src/quicktemplates2/qquickrangeslider.cpp index 5b03de88..f1e8a01e 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 + \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 + \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 \qmlproperty bool QtQuick.Controls::RangeSlider::live diff --git a/src/quicktemplates2/qquickrangeslider_p.h b/src/quicktemplates2/qquickrangeslider_p.h index c4bc52ff..b4553501 100644 --- a/src/quicktemplates2/qquickrangeslider_p.h +++ b/src/quicktemplates2/qquickrangeslider_p.h @@ -65,6 +65,8 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickRangeSlider : public QQuickControl 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 c04a2d0d..128bca6f 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 + \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 + \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..5e39134c 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 + \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 + \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 15c7be97..2e337c3a 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 + \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 + \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 a41383aa..07bf4121 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); } /*! @@ -694,6 +713,34 @@ bool QQuickSpinBox::isInputMethodComposing() const } /*! + \since QtQuick.Controls 2.3 + \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. @@ -703,7 +750,7 @@ bool QQuickSpinBox::isInputMethodComposing() const void QQuickSpinBox::increase() { Q_D(QQuickSpinBox); - setValue(d->value + d->effectiveStepSize()); + d->stepBy(d->effectiveStepSize()); } /*! @@ -716,7 +763,7 @@ void QQuickSpinBox::increase() void QQuickSpinBox::decrease() { Q_D(QQuickSpinBox); - setValue(d->value - d->effectiveStepSize()); + d->stepBy(-d->effectiveStepSize()); } void QQuickSpinBox::focusInEvent(QFocusEvent *event) @@ -819,7 +866,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); diff --git a/src/quicktemplates2/qquickspinbox_p.h b/src/quicktemplates2/qquickspinbox_p.h index 73cb3389..27956d7c 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; diff --git a/src/quicktemplates2/qquickswipeview.cpp b/src/quicktemplates2/qquickswipeview.cpp index cfea81bc..d278beb7 100644 --- a/src/quicktemplates2/qquickswipeview.cpp +++ b/src/quicktemplates2/qquickswipeview.cpp @@ -190,6 +190,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 +211,36 @@ void QQuickSwipeView::setOrientation(Qt::Orientation orientation) emit orientationChanged(); } +/*! + \since QtQuick.Controls 2.3 + \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 + \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); diff --git a/src/quicktemplates2/qquickswipeview_p.h b/src/quicktemplates2/qquickswipeview_p.h index e07ed7f0..0c0d3557 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: diff --git a/src/quicktemplates2/qquicktabbar.cpp b/src/quicktemplates2/qquicktabbar.cpp index 7ce8a21e..98bf94c7 100644 --- a/src/quicktemplates2/qquicktabbar.cpp +++ b/src/quicktemplates2/qquicktabbar.cpp @@ -152,38 +152,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) / 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)) { diff --git a/src/quicktemplates2/qquicktextarea_p_p.h b/src/quicktemplates2/qquicktextarea_p_p.h index ef2c7237..1115b3e9 100644 --- a/src/quicktemplates2/qquicktextarea_p_p.h +++ b/src/quicktemplates2/qquicktextarea_p_p.h @@ -52,7 +52,7 @@ #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> diff --git a/src/quicktemplates2/qquicktextfield_p_p.h b/src/quicktemplates2/qquicktextfield_p_p.h index 31ccb361..e8dc625b 100644 --- a/src/quicktemplates2/qquicktextfield_p_p.h +++ b/src/quicktemplates2/qquicktextfield_p_p.h @@ -51,7 +51,7 @@ #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> diff --git a/src/quicktemplates2/qquicktoolbutton.cpp b/src/quicktemplates2/qquicktoolbutton.cpp index 5ef25e3e..3db22022 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} */ diff --git a/src/quicktemplates2/qquicktooltip.cpp b/src/quicktemplates2/qquicktooltip.cpp index bf83a725..47aacea1 100644 --- a/src/quicktemplates2/qquicktooltip.cpp +++ b/src/quicktemplates2/qquicktooltip.cpp @@ -353,7 +353,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/quicktemplates2.pri b/src/quicktemplates2/quicktemplates2.pri index a7570ec5..e1a1a917 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 \ @@ -82,6 +85,8 @@ HEADERS += \ SOURCES += \ $$PWD/qquickabstractbutton.cpp \ + $$PWD/qquickaction.cpp \ + $$PWD/qquickactiongroup.cpp \ $$PWD/qquickapplicationwindow.cpp \ $$PWD/qquickbusyindicator.cpp \ $$PWD/qquickbutton.cpp \ @@ -98,6 +103,7 @@ SOURCES += \ $$PWD/qquickdrawer.cpp \ $$PWD/qquickframe.cpp \ $$PWD/qquickgroupbox.cpp \ + $$PWD/qquickicon.cpp \ $$PWD/qquickitemdelegate.cpp \ $$PWD/qquicklabel.cpp \ $$PWD/qquickmenu.cpp \ diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro index 1947b177..7c6f7a16 100644 --- a/tests/auto/auto.pro +++ b/tests/auto/auto.pro @@ -11,6 +11,9 @@ SUBDIRS += \ platform \ popup \ pressandhold \ + qquickcolor \ + qquickiconimage \ + qquickiconlabel \ qquickmaterialstyle \ qquickmaterialstyleconf \ qquickstyle \ diff --git a/tests/auto/controls/data/tst_abstractbutton.qml b/tests/auto/controls/data/tst_abstractbutton.qml index 422d13b4..8ab91e3a 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 @@ -164,4 +164,143 @@ TestCase { container.destroy() } + + 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 iconNameSpy = signalSpy.createObject(control, { target: control.icon, signalName: "nameChanged"} ) + verify(iconNameSpy.valid) + + control.icon.name = "test-name" + compare(control.icon.name, "test-name") + compare(iconNameSpy.count, 1) + + var iconSourceSpy = signalSpy.createObject(control, { target: control.icon, signalName: "sourceChanged"} ) + verify(iconSourceSpy.valid) + + control.icon.source = "qrc:/test-source" + compare(control.icon.source, "qrc:/test-source") + compare(iconSourceSpy.count, 1) + + var iconWidthSpy = signalSpy.createObject(control, { target: control.icon, signalName: "widthChanged"} ) + verify(iconWidthSpy.valid) + + control.icon.width = 32 + compare(control.icon.width, 32) + compare(iconWidthSpy.count, 1) + + var iconHeightSpy = signalSpy.createObject(control, { target: control.icon, signalName: "heightChanged"} ) + verify(iconHeightSpy.valid) + + control.icon.height = 32 + compare(control.icon.height, 32) + compare(iconHeightSpy.count, 1) + + var iconColorSpy = signalSpy.createObject(control, { target: control.icon, signalName: "colorChanged"} ) + verify(iconColorSpy.valid) + + control.icon.color = "#ff0000" + compare(control.icon.color, "#ff0000") + compare(iconColorSpy.count, 1) + } + + 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_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_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..d5de9e89 100644 --- a/tests/auto/controls/data/tst_menuitem.qml +++ b/tests/auto/controls/data/tst_menuitem.qml @@ -96,4 +96,63 @@ 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 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 : 0) + 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 : 0) + 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 : (textLabel.width - iconImage.width) / 2) + compare(textLabel.x, control.mirrored ? control.availableWidth - textLabel.width : 0) + 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; + } + } } 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 da6e24a1..01ac1b8f 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_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..4c67ec82 100644 --- a/tests/auto/controls/data/tst_tabbar.qml +++ b/tests/auto/controls/data/tst_tabbar.qml @@ -514,39 +514,66 @@ 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) } } 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/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/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..9e7c6794 --- /dev/null +++ b/tests/auto/qquickiconlabel/tst_qquickiconlabel.cpp @@ -0,0 +1,296 @@ +/**************************************************************************** +** +** 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/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(); +}; + +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()) { + 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->icon()->setSource(QString()); + QVERIFY(!label->findChild<QQuickIconImage *>()); + horizontalCenter = label->width() / 2; + QCOMPARE(text->x(), horizontalCenter - text->width() / 2); +} + +QTEST_MAIN(tst_qquickiconlabel) + +#include "tst_qquickiconlabel.moc" |