diff --git a/chameleon/CMakeLists.txt b/chameleon/CMakeLists.txt
index e7b6ca9f..fd2ad28e 100644
--- a/chameleon/CMakeLists.txt
+++ b/chameleon/CMakeLists.txt
@@ -24,6 +24,7 @@ set(QML_FILES
Frame.qml
GroupBox.qml
ItemDelegate.qml
+ ListView.qml
MenuItem.qml
Menu.qml
MenuSeparator.qml
diff --git a/chameleon/ListView.qml b/chameleon/ListView.qml
new file mode 100644
index 00000000..43fe1d9c
--- /dev/null
+++ b/chameleon/ListView.qml
@@ -0,0 +1,9 @@
+// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+
+import org.deepin.dtk 1.0 as D
+
+D.ListView {
+
+}
diff --git a/examples/exhibition/ControlGroup.qml b/examples/exhibition/ControlGroup.qml
new file mode 100644
index 00000000..a0b83da3
--- /dev/null
+++ b/examples/exhibition/ControlGroup.qml
@@ -0,0 +1,52 @@
+// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+
+import QtQuick 2.0
+import QtQuick.Window 2.11
+import QtQuick.Layouts 1.11
+import org.deepin.dtk 1.0
+import ".."
+
+ ControlGroup {
+ title: "磁盘"
+ ControlGroupItem {
+ Label {
+ visible: true
+ text: "test0111111111111"
+ }
+ Label {
+ visible: true
+ text: "test13333333333"
+ }
+ }
+ ControlGroupItem {
+ Rectangle {
+ width: 100
+ height: 100
+ color: "red"
+ border.color: "black"
+ border.width: 5
+ radius: 10
+ }
+ Switch {
+ checked: true
+ Layout.alignment: Qt.AlignHCenter
+ }
+ }
+ ControlGroupItem {
+ Rectangle {
+ width: 100
+ height: 100
+ color: "green"
+ border.color: "black"
+ border.width: 5
+ radius: 10
+ }
+ Button {
+ width: 100
+ height: 100
+ Layout.alignment: Qt.AlignHCenter
+ }
+ }
+ }
diff --git a/examples/exhibition/qml-qt6.qrc b/examples/exhibition/qml-qt6.qrc
index 8d9a8f2d..750b0636 100644
--- a/examples/exhibition/qml-qt6.qrc
+++ b/examples/exhibition/qml-qt6.qrc
@@ -25,5 +25,6 @@
ToolBar.qml
Dialog.qml
ProgressBar.qml
+ ControlGroup.qml
diff --git a/qmlplugin/qmlplugin_plugin.cpp b/qmlplugin/qmlplugin_plugin.cpp
index 43b84638..0178de15 100644
--- a/qmlplugin/qmlplugin_plugin.cpp
+++ b/qmlplugin/qmlplugin_plugin.cpp
@@ -34,6 +34,7 @@
#include "private/dquickcontrolpalette_p.h"
#include
+#include
#include
#include
@@ -206,6 +207,7 @@ void QmlpluginPlugin::registerTypes(const char *uri)
dtkRegisterUncreatableType(uri, implUri, 1, 0, "Color",
QStringLiteral("Color is only available as enums."));
dtkRegisterUncreatableType(uri, implUri, 1, 0, "PopupHandle", "PopupWindow Attached");
+ dtkRegisterUncreatableType(uri, implUri, 1, 0, "PlatformHandle", "PlatformHandle");
qRegisterMetaType();
qRegisterMetaType("ControlColor");
diff --git a/qt6/src/dquickextendregister_p.h b/qt6/src/dquickextendregister_p.h
index 69785a40..605d9b42 100644
--- a/qt6/src/dquickextendregister_p.h
+++ b/qt6/src/dquickextendregister_p.h
@@ -9,6 +9,7 @@
#include
#include
#include
+#include
#include
DQUICK_BEGIN_NAMESPACE
@@ -51,4 +52,11 @@ struct DFontManagerForeign
QML_NAMED_ELEMENT(FontManager)
};
+struct DPlatformHandleForeign
+{
+ Q_GADGET
+ QML_FOREIGN(DPlatformHandle)
+ QML_NAMED_ELEMENT(PlatformHandle)
+};
+
DQUICK_END_NAMESPACE
diff --git a/qt6/src/dtkdeclarative_qml.qrc b/qt6/src/dtkdeclarative_qml.qrc
index 2b88b5b3..899a09ac 100644
--- a/qt6/src/dtkdeclarative_qml.qrc
+++ b/qt6/src/dtkdeclarative_qml.qrc
@@ -63,6 +63,7 @@
qml/private/ButtonPanel.qml
qml/ActionButton.qml
qml/ItemDelegate.qml
+ qml/ListView.qml
qml/CheckDelegate.qml
qml/TipsSlider.qml
qml/SliderTipItem.qml
@@ -109,6 +110,8 @@
qml/ButtonIndicator.qml
qml/EmbeddedProgressBar.qml
qml/WaterProgressBar.qml
+ qml/ControlGroup.qml
+ qml/ControlGroupItem.qml
qml/private/ProgressBarImpl.qml
qml/private/ProgressBarPanel.qml
qml/PlaceholderText.qml
diff --git a/qt6/src/qml.cmake b/qt6/src/qml.cmake
index 965e28db..0a40268a 100644
--- a/qt6/src/qml.cmake
+++ b/qt6/src/qml.cmake
@@ -52,6 +52,7 @@ set(QML_DTK_CONTROLS
"qml/ComboBox.qml"
"qml/ActionButton.qml"
"qml/ItemDelegate.qml"
+ "qml/ListView.qml"
"qml/CheckDelegate.qml"
"qml/TipsSlider.qml"
"qml/SliderTipItem.qml"
@@ -96,6 +97,9 @@ set(QML_DTK_CONTROLS
"qml/EmbeddedProgressBar.qml"
"qml/WaterProgressBar.qml"
"qml/PlaceholderText.qml"
+ "qml/ControlGroup.qml"
+ "qml/ControlGroupItem.qml"
+ "qml/DragItemsImage.qml"
)
foreach(QML_FILE ${QML_DTK_CONTROLS})
diff --git a/qt6/src/qml/ArrowListView.qml b/qt6/src/qml/ArrowListView.qml
index a7e53fb6..94bc24f9 100644
--- a/qt6/src/qml/ArrowListView.qml
+++ b/qt6/src/qml/ArrowListView.qml
@@ -5,6 +5,7 @@
import QtQuick 2.11
import QtQuick.Window 2.11
import QtQuick.Layouts 1.11
+import org.deepin.dtk 1.0 as D
import org.deepin.dtk.style 1.0 as DS
import org.deepin.dtk.private 1.0 as P
diff --git a/qt6/src/qml/ButtonBox.qml b/qt6/src/qml/ButtonBox.qml
index 7502dba9..fb5688cc 100644
--- a/qt6/src/qml/ButtonBox.qml
+++ b/qt6/src/qml/ButtonBox.qml
@@ -6,6 +6,7 @@ import QtQuick 2.11
import QtQuick.Layouts 1.11
import org.deepin.dtk 1.0 as D
import org.deepin.dtk.style 1.0 as DS
+import org.deepin.dtk.private 1.0 as P
Control {
id: control
@@ -31,4 +32,27 @@ Control {
outsideBorderColor: null
color2: color1
}
+
+ ParallelAnimation {
+ running: btnGroup.checkedButton && (btnGroup.checkedButton.x !== backgroundPanel.x || btnGroup.checkedButton.y !== backgroundPanel.y)
+ NumberAnimation { target: backgroundPanel; property: "x"; to: btnGroup.checkedButton ? btnGroup.checkedButton.x : backgroundPanel.x; duration: 200 }
+ NumberAnimation { target: backgroundPanel; property: "y"; to: btnGroup.checkedButton ? btnGroup.checkedButton.y : backgroundPanel.y; duration: 200 }
+ NumberAnimation { target: backgroundPanel; property: "width"; to: btnGroup.checkedButton ? btnGroup.checkedButton.width : backgroundPanel.width; duration: 200 }
+ NumberAnimation { target: backgroundPanel; property: "height"; to: btnGroup.checkedButton ? btnGroup.checkedButton.height : backgroundPanel.height; duration: 200 }
+ }
+
+ P.ButtonPanel {
+ id: backgroundPanel
+ visible: btnGroup.checkedButton
+ implicitWidth: visible ? btnGroup.checkedButton.width : 0
+ implicitHeight: visible ? btnGroup.checkedButton.height : 0
+ button: control
+ outsideBorderColor: null
+ color1: D.Palette {
+ normal {
+ common: Qt.rgba(0, 0, 0, 0.2)
+ }
+ }
+ color2: color1
+ }
}
diff --git a/qt6/src/qml/CheckDelegate.qml b/qt6/src/qml/CheckDelegate.qml
index 8db95ae2..ec1cb380 100644
--- a/qt6/src/qml/CheckDelegate.qml
+++ b/qt6/src/qml/CheckDelegate.qml
@@ -12,6 +12,8 @@ T.CheckDelegate {
id: control
property Component content
property D.Palette backgroundColor: DS.Style.itemDelegate.checkBackgroundColor
+ property string indicatorIcon: control.checkState === Qt.Unchecked ? "item_unchecked" : "item_checked"
+ property bool indicatorVisible: control.checked
implicitWidth: DS.Style.control.implicitWidth(control)
implicitHeight: DS.Style.control.implicitHeight(control)
@@ -26,15 +28,22 @@ T.CheckDelegate {
indicator: Loader {
x: control.mirrored ? control.leftPadding : control.width - width - control.rightPadding
y: control.topPadding + (control.availableHeight - height) / 2
- active: control.checked
+ active: indicatorVisible
sourceComponent: D.DciIcon {
palette: control.D.DTK.makeIconPalette(control.palette)
mode: control.D.ColorSelector.controlState
theme: control.D.ColorSelector.controlTheme
- name: "menu_select"
+ name: indicatorIcon
sourceSize: Qt.size(DS.Style.itemDelegate.checkIndicatorIconSize, DS.Style.itemDelegate.checkIndicatorIconSize)
fallbackToQIcon: false
+ onNameChanged: {
+ play(D.DTK.NormalState);
+ }
+ Component.onCompleted: {
+ if (indicatorVisible)
+ play(D.DTK.NormalState);
+ }
}
}
@@ -58,12 +67,12 @@ T.CheckDelegate {
}
}
- background: Item {
+ background: Control {
implicitWidth: DS.Style.itemDelegate.width
implicitHeight: DS.Style.itemDelegate.height
Rectangle {
anchors.fill: parent
- visible: !checked
+ visible: !checked && !control.ListView.view
color: control.D.ColorSelector.backgroundColor
radius: DS.Style.control.radius
}
@@ -74,4 +83,12 @@ T.CheckDelegate {
radius: DS.Style.control.radius
}
}
+
+ onHoveredChanged: {
+ if (checked || !ListView.view)
+ return
+
+ if (ListView.view)
+ ListView.view.setHoverItem(control.hovered ? control : null)
+ }
}
diff --git a/qt6/src/qml/ControlGroup.qml b/qt6/src/qml/ControlGroup.qml
new file mode 100644
index 00000000..6f7ddc9c
--- /dev/null
+++ b/qt6/src/qml/ControlGroup.qml
@@ -0,0 +1,173 @@
+// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+
+import QtQuick 2.0
+import QtQuick.Layouts 1.11
+import org.deepin.dtk 1.0 as D
+import org.deepin.dtk.style 1.0 as DS
+
+ColumnLayout {
+ id: root
+ spacing: 10
+
+ property string title
+ property bool isExpanded: true
+ property int interval: 400 / (itemLayout.children.length)
+ property int index: 0
+ property int titleHeight: 36
+ default property alias childItem: itemLayout.children
+
+ Control {
+ id: title
+ Layout.fillWidth: true
+ Layout.preferredHeight: 36
+ property int inset: 4
+ leftInset: inset
+ rightInset: inset
+ topInset: inset
+ bottomInset: inset
+ state: "normal"
+ states: [
+ State {
+ name: "normal"
+ PropertyChanges {
+ target: title
+ inset:4
+ }
+ },
+ State {
+ name: "hovered"
+ PropertyChanges {
+ target: title
+ inset:0
+ }
+ },
+ State {
+ name: "pressed"
+ PropertyChanges {
+ target: title
+ inset: 4
+ }
+ }
+ ]
+ transitions: [
+ Transition {
+ from: "normal"
+ to: "hovered"
+ NumberAnimation {
+ properties: "inset"
+ easing.type: Easing.Linear
+ duration: 500
+ }
+ },
+ Transition {
+ from: "hovered"
+ to: "normal"
+ NumberAnimation {
+ properties: "inset"
+ easing.type: Easing.Linear
+ duration: 500
+ }
+ },
+ Transition {
+ from: "hovered"
+ to: "pressed"
+ NumberAnimation {
+ properties: "inset"
+ easing.type: Easing.Linear
+ duration: 500
+ }
+ },
+ Transition {
+ from: "pressed"
+ to: "hovered"
+ NumberAnimation {
+ properties: "inset"
+ easing.type: Easing.Linear
+ duration: 500
+ }
+ }
+ ]
+ RowLayout {
+ anchors.fill: parent
+ spacing: 0
+ Label {
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ text: root.title
+ font: DTK.fontManager.t5
+ verticalAlignment: Qt.AlignVCenter
+ }
+ D.DciIcon {
+ rotation: root.isExpanded ? 0 : - 90
+ name: "arrow_ordinary_down"
+ mode: title.D.ColorSelector.controlState
+ theme: title.D.ColorSelector.controlTheme
+ palette: D.DTK.makeIconPalette(title.palette)
+ sourceSize: Qt.size(36, 36)
+
+ Behavior on rotation {
+ NumberAnimation {
+ duration: root.interval
+ easing.type: Easing.Linear
+ }
+ }
+ }
+ }
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ hoverEnabled: true
+ onClicked: root.isExpanded = !root.isExpanded
+ onPressed: title.state = "pressed"
+ onReleased: title.state = "hovered"
+ onEntered: title.state = "hovered"
+ onExited: title.state = "normal"
+ }
+ background: Item {
+ Loader {
+ anchors.fill: parent
+ active: title.hovered
+ sourceComponent: D.RoundRectangle {
+ color: DS.Style.itemDelegate.normalColor
+ radius: DS.Style.control.radius
+ corners: D.RoundRectangle.TopLeftCorner | D.RoundRectangle.TopRightCorner | D.RoundRectangle.BottomLeftCorner | D.RoundRectangle.BottomRightCorner
+ }
+ }
+ }
+ }
+
+ Timer {
+ id: timer
+ }
+
+ ColumnLayout {
+ id: itemLayout
+ Layout.fillHeight: false
+ }
+
+ onIsExpandedChanged: (isExpanded) => {
+ for(let i = 0; i < itemLayout.children.length; ++i) {
+ itemLayout.children[i].isExpanded = !itemLayout.children[i].isExpanded
+ }
+ // delay(0, timeout)
+ }
+
+ function timeout() {
+ itemLayout.children[index].isExpanded = !itemLayout.children[index].isExpanded
+ ++index
+ if (index === itemLayout.children.length) {
+ timer.stop()
+ timer.triggered.disconnect(timeout)
+ index = 0
+ }
+ }
+
+ function delay(delayTime, cb) {
+ timer.interval = delayTime
+ timer.repeat = true
+ timer.triggered.connect(cb)
+ timer.restart()
+ }
+}
diff --git a/qt6/src/qml/ControlGroupItem.qml b/qt6/src/qml/ControlGroupItem.qml
new file mode 100644
index 00000000..2a98212a
--- /dev/null
+++ b/qt6/src/qml/ControlGroupItem.qml
@@ -0,0 +1,39 @@
+// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+
+import QtQuick 2.0
+import QtQuick.Layouts 1.11
+import QtQml.Models 2.11
+import org.deepin.dtk 1.0
+
+RowLayout {
+ id: root
+
+ property int initY
+ property bool isExpanded: true
+
+ y: isExpanded ? initY : - parent.parent.titleHeight
+ opacity: isExpanded ? 1.0 : 0.0
+ visible: opacity === 0.0 ? false : true
+
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+
+ Behavior on y {
+ NumberAnimation {
+ duration: parent.parent.interval
+ easing.type: Easing.Linear
+ }
+ }
+ Behavior on opacity {
+ NumberAnimation {
+ duration: parent.parent.interval
+ easing.type: Easing.Linear
+ }
+ }
+
+ Component.onCompleted: {
+ root.initY = root.y
+ }
+}
diff --git a/qt6/src/qml/DialogTitleBar.qml b/qt6/src/qml/DialogTitleBar.qml
index 11fa1a82..e8feb26d 100644
--- a/qt6/src/qml/DialogTitleBar.qml
+++ b/qt6/src/qml/DialogTitleBar.qml
@@ -2,13 +2,13 @@
//
// SPDX-License-Identifier: LGPL-3.0-or-later
-import QtQuick 2.11
-import QtQuick.Window 2.11
-import QtQuick.Layouts 1.11
+import QtQuick
+import QtQuick.Window
+import QtQuick.Layouts
import org.deepin.dtk 1.0 as D
import org.deepin.dtk.style 1.0 as DS
-Control {
+Item {
id: control
z: D.DTK.TopOrder
width: Window.window.width
@@ -39,15 +39,17 @@ Control {
}
}
- background: D.InWindowBlur {
+ D.InWindowBlur {
id: background
visible: false
+ anchors.fill: parent
}
- contentItem: ColumnLayout {
+ ColumnLayout {
id: content
spacing: 0
+ anchors.fill: parent
Rectangle {
id: separatorTop
Layout.preferredWidth: parent.width
@@ -63,15 +65,18 @@ Control {
Layout.preferredWidth: parent.width
Layout.leftMargin: DS.Style.titleBar.leftMargin
- D.DciIcon {
- id: iconLabel
- visible: name !== ""
- mode: control.D.ColorSelector.controlState
- theme: control.D.ColorSelector.controlTheme
- palette: D.DTK.makeIconPalette(control.palette)
- sourceSize {
- width: DS.Style.dialogWindow.iconSize
- height: DS.Style.dialogWindow.iconSize
+ Control {
+ id: iconControl
+ visible: iconLabel.name !== ""
+ contentItem: D.DciIcon {
+ id: iconLabel
+ mode: iconControl.D.ColorSelector.controlState
+ theme: iconControl.D.ColorSelector.controlTheme
+ palette: D.DTK.makeIconPalette(iconControl.palette)
+ sourceSize {
+ width: DS.Style.dialogWindow.iconSize
+ height: DS.Style.dialogWindow.iconSize
+ }
}
}
diff --git a/qt6/src/qml/DialogWindow.qml b/qt6/src/qml/DialogWindow.qml
index b208f881..7bd44968 100644
--- a/qt6/src/qml/DialogWindow.qml
+++ b/qt6/src/qml/DialogWindow.qml
@@ -2,9 +2,9 @@
//
// SPDX-License-Identifier: LGPL-3.0-or-later
-import QtQuick 2.11
-import QtQuick.Layouts 1.11
-import QtQuick.Window 2.11
+import QtQuick
+import QtQuick.Layouts
+import QtQuick.Window
import org.deepin.dtk 1.0 as D
import org.deepin.dtk.style 1.0 as DS
@@ -31,10 +31,11 @@ Window {
default property alias content: contentLoader.children
property alias palette : content.palette
- Control {
+ Item {
id: content
palette: control.active ? D.DTK.palette : D.DTK.inactivePalette
- contentItem: ColumnLayout {
+ implicitHeight: childrenRect.height
+ ColumnLayout {
id: layout
spacing: 0
diff --git a/qt6/src/qml/DragItemsImage.qml b/qt6/src/qml/DragItemsImage.qml
new file mode 100644
index 00000000..e978a683
--- /dev/null
+++ b/qt6/src/qml/DragItemsImage.qml
@@ -0,0 +1,81 @@
+// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+
+import QtQuick 2.15
+
+Item {
+ id: control
+ property list- items
+
+ signal aboutToGrabToImage(Item item)
+ signal grabToImageFinished(Item item)
+
+ onItemsChanged: function updateGeomotry() {
+ var w = 0
+ var h = 0
+ for (var i = 0; i < control.items.length; ++i) {
+ let item = control.items[i]
+ w = Math.max(w, item.width)
+ h = Math.max(h, item.height)
+ }
+ control.width = w + 30
+ control.height = h * 2 + 30
+ }
+
+ function addItem(item) {
+ if (control.items.include(item))
+ return
+
+ items.push(item)
+ }
+
+ function removeItem(item) {
+ if (!control.items.include(item))
+ return
+
+ var index = control.items.indexOf(item);
+ if (index !== -1) {
+ control.items.splice(index, 1);
+ }
+ }
+
+ Repeater {
+ model: control.items.length
+ delegate: Image {
+ id: img
+ anchors.centerIn: parent
+ antialiasing: true
+ rotation: index ? (index % 2 === 0 ? 10 : -10) : 0
+ opacity: (1 - index * 0.2)
+ z: -index
+
+ Component.onCompleted: {
+ let item = control.items[index]
+ if (!item)
+ return
+
+ img.width = item.width
+ img.height = item.height
+
+ aboutToGrabToImage(item)
+ item.grabToImage(function(result) {
+ img.source = result.url
+ grabToImageFinished(item)
+ })
+ }
+ }
+ }
+
+ RoundButton {
+ id: number
+ checked: true
+ anchors.right: dragItem.right
+ anchors.top: dragItem.top
+ anchors.margins: 8
+ implicitWidth: 24
+ implicitHeight: 24
+ text: control.items.length > 1 ? control.items.length : ""
+ opacity: control.items.length > 1 ? 1 : 0
+ }
+}
diff --git a/qt6/src/qml/FloatingMessage.qml b/qt6/src/qml/FloatingMessage.qml
index 5b1d9cb9..c80a09bd 100644
--- a/qt6/src/qml/FloatingMessage.qml
+++ b/qt6/src/qml/FloatingMessage.qml
@@ -23,23 +23,39 @@ D.FloatingMessageContainer {
width: DS.Style.floatingMessage.closeButtonSize
height: DS.Style.floatingMessage.closeButtonSize
}
- onClicked: D.DTK.closeMessage(control)
+ onClicked: floatingPanel.state = "small"
}
+ onDelayClose: floatingPanel.state = "small"
duration: 4000
panel: FloatingPanel {
id: floatingPanel
+ property bool animationFinished: false
implicitWidth: DS.Style.control.contentImplicitWidth(floatingPanel)
leftPadding: 10
rightPadding: 10
topPadding: 0
bottomPadding: 0
+ opacity: 0.0
+ state: "small"
+ onAnimationFinishedChanged: (finished) => {
+ if (floatingPanel.animationFinished === true) {
+ D.DTK.closeMessage(control)
+ }
+ }
+ Timer {
+ id: timer
+ interval: 100; running: false; repeat: false
+ onTriggered: floatingPanel.state = "normal"
+ }
+ Component.onCompleted: {
+ timer.running = true
+ }
contentItem: RowLayout {
height: DS.Style.floatingMessage.minimumHeight
width: Math.min(DS.Style.floatingMessage.maximumWidth, children.width + floatingPanel.leftPadding - floatingPanel.rightPadding)
spacing: 10
-
Loader {
id: iconLoader
Layout.alignment: Qt.AlignVCenter
@@ -77,6 +93,69 @@ D.FloatingMessageContainer {
visible: active
sourceComponent: button
}
+
+ ParallelAnimation {
+ running: closeButton.item ? closeButton.item.hovered : false
+ NumberAnimation { target: closeButton; property: "scale"; to: 1.25; duration: 500 }
+ NumberAnimation { target: closeButton; property: "rotation"; to: 90; duration: 500 }
+ }
+ ParallelAnimation {
+ running: closeButton.item ? !closeButton.item.hovered : false
+ NumberAnimation { target: closeButton; property: "scale"; to: 1; duration: 500 }
+ NumberAnimation { target: closeButton; property: "rotation"; to: 0; duration: 500 }
+ }
}
+
+ states: [
+ State {
+ name: "normal"
+ PropertyChanges {
+ target: floatingPanel
+ y: 0
+ opacity: 1.0
+ scale: 1.0
+ }
+ },
+ State {
+ name: "small"
+ PropertyChanges {
+ target: floatingPanel
+ y: floatingPanel.parent ? floatingPanel.parent.height : 0
+ opacity: 0.0
+ scale: 0.2
+ }
+ }
+ ]
+
+ transitions: [
+ Transition {
+ from: "normal"
+ to: "small"
+ SequentialAnimation {
+ NumberAnimation {
+ properties: "y, opacity, scale"
+ easing.type: Easing.Linear
+ duration: 300
+ }
+ PropertyAction { target: floatingPanel; property: "animationFinished"; value: true; }
+ }
+ },
+ Transition {
+ from: "small"
+ to: "normal"
+ SequentialAnimation {
+ PropertyAction {
+ target: floatingPanel
+ property: "y"
+ value: floatingPanel.parent ? floatingPanel.parent.height : 0
+ }
+ NumberAnimation {
+ properties: "y, opacity, scale"
+ easing.type: Easing.Linear
+ duration: 300
+ }
+ }
+ }
+ ]
}
}
diff --git a/qt6/src/qml/FlowStyle.qml b/qt6/src/qml/FlowStyle.qml
index fc8dc607..37641dbf 100644
--- a/qt6/src/qml/FlowStyle.qml
+++ b/qt6/src/qml/FlowStyle.qml
@@ -814,7 +814,7 @@ QtObject {
}
property D.Palette handleGradientColor: D.Palette {
- normal: D.DTK.makeColor(D.Color.Highlight).hue(-10).saturation(+40).lightness(+20)
+ normal: D.DTK.makeColor(D.Color.Highlight).hue(-0).saturation(+30).lightness(+30)
}
}
diff --git a/qt6/src/qml/ItemDelegate.qml b/qt6/src/qml/ItemDelegate.qml
index 0a2acca4..f8c5a205 100644
--- a/qt6/src/qml/ItemDelegate.qml
+++ b/qt6/src/qml/ItemDelegate.qml
@@ -1,12 +1,13 @@
-// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd.
+// SPDX-FileCopyrightText: 2022-2024 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: LGPL-3.0-or-later
-import QtQuick 2.11
+import QtQuick
import QtQuick.Templates as T
import QtQuick.Layouts 1.11
import org.deepin.dtk 1.0 as D
import org.deepin.dtk.style 1.0 as DS
+import org.deepin.dtk.private 1.0 as P
T.ItemDelegate {
id: control
@@ -17,6 +18,12 @@ T.ItemDelegate {
property Component content
property D.Palette checkedTextColor: DS.Style.checkedButton.text
property int corners: D.RoundRectangle.TopLeftCorner | D.RoundRectangle.TopRightCorner | D.RoundRectangle.BottomLeftCorner | D.RoundRectangle.BottomRightCorner
+ property bool dragActive: false
+ // drag
+ property bool enableDrag: false
+ Drag.mimeData: { "text/plain": control.text }
+ Drag.dragType: Drag.Automatic
+
function getCornersForBackground(index, count) {
if (count <= 1)
return D.RoundRectangle.TopLeftCorner | D.RoundRectangle.TopRightCorner | D.RoundRectangle.BottomLeftCorner | D.RoundRectangle.BottomRightCorner
@@ -35,7 +42,7 @@ T.ItemDelegate {
spacing: DS.Style.control.spacing
checkable: true
autoExclusive: true
- palette.windowText: checked && !control.cascadeSelected ? D.ColorSelector.checkedTextColor : undefined
+ palette.windowText: checked && !control.cascadeSelected && control.backgroundVisible && !dragActive? D.ColorSelector.checkedTextColor : undefined
D.DciIcon.mode: D.ColorSelector.controlState
D.DciIcon.theme: D.ColorSelector.controlTheme
@@ -83,12 +90,13 @@ T.ItemDelegate {
}
background: Item {
+ visible: backgroundVisible
implicitWidth: DS.Style.itemDelegate.width
implicitHeight: DS.Style.itemDelegate.height
Loader {
anchors.fill: parent
- active: checked && !control.cascadeSelected
+ active: checked && !control.cascadeSelected && !dragActive
sourceComponent: HighlightPanel {}
}
@@ -104,12 +112,57 @@ T.ItemDelegate {
Loader {
anchors.fill: parent
- active: !checked && control.backgroundVisible
+ active: !control.ListView.view && !checked && control.backgroundVisible
sourceComponent: D.RoundRectangle {
color: DS.Style.itemDelegate.normalColor
radius: DS.Style.control.radius
corners: control.corners
}
}
+
+ Loader {
+ anchors.fill: parent
+ active: dragActive
+ sourceComponent: Rectangle {
+ border.color: Qt.rgba(0, 0, 0, 0.09)
+ radius: DS.Style.control.radius
+ }
+ }
+ }
+
+ DragHandler {
+ id: dragHandler
+ enabled: enableDrag
+ onActiveChanged: {
+ if (active) {
+ let dragItem = control.ListView.view.dragItem
+ if (!dragItem)
+ return
+
+ let md = JSON.stringify(dragItem.Drag.mimeData)
+
+ if (md.length > 2) // '{}'
+ control.Drag.mimeData = dragItem.Drag.mimeData
+
+ dragItem.grabToImage(function(result) {
+ control.Drag.imageSource = result.url;
+ control.Drag.hotSpot = Qt.point(dragItem.width / 2, dragItem.height / 2)
+ control.Drag.active = true
+ })
+ }
+ }
+ }
+
+ onHoveredChanged: {
+ if (checked || control.cascadeSelected || !backgroundVisible || dragActive)
+ return
+
+ if (ListView.view)
+ ListView.view.setHoverItem(control.hovered ? control : null)
+ }
+
+ onCheckedChanged: {
+ if (ListView.view)
+ ListView.view.updateCheckedItems()
}
}
diff --git a/qt6/src/qml/ListView.qml b/qt6/src/qml/ListView.qml
new file mode 100644
index 00000000..ba2da84d
--- /dev/null
+++ b/qt6/src/qml/ListView.qml
@@ -0,0 +1,205 @@
+// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+
+import QtQuick 2.15
+import QtQuick.Templates as T
+import org.deepin.dtk 1.0 as D
+import org.deepin.dtk.style 1.0 as DS
+import org.deepin.dtk.private 1.0 as P
+
+ListView {
+ id: control
+ property int duration: 100
+ property bool bgVisible: false
+ property Item hoveredItem
+ property list
- checkedItems
+ property alias dragItem: dragItem
+
+ function setHoverItem(item) {
+ if (item) {
+ hoveredItem = item
+ // if hover from null to item do not show animation
+ bgVisible = (background.x <= 0 && background.y <= 0) ? false : hoveredItem.hovered
+ background.x = hoveredItem.x - contentX
+ background.y = hoveredItem.y - contentY
+ background.width = hoveredItem.implicitWidth
+ background.height = hoveredItem.implicitHeight
+ bgVisible = hoveredItem.hovered
+ control.state = bgVisible ? "Visible" : "Invisible"
+ } else {
+ hideTimer.start()
+ }
+ }
+
+ function updateCheckedItems() {
+ var items = []
+ for (var i = 0; i < count; ++i) {
+ let item = itemAtIndex(i)
+ if (item && item.checked) {
+ items.push(item)
+ }
+ }
+
+ checkedItems = items
+ }
+
+ DragItemsImage {
+ id: dragItem
+ items: checkedItems
+ visible: Drag.active
+ // Drag.mimeData: {"text/plain": ""}
+
+ onAboutToGrabToImage: function(item) {
+ item.dragActive = true
+ }
+ onGrabToImageFinished: function(item) {
+ item.dragActive = false
+ }
+ }
+
+ onContentXChanged: {
+ if (hoveredItem && hoveredItem.hovered && background)
+ background.x = hoveredItem.x - contentX
+ }
+
+ onContentYChanged: {
+ if (hoveredItem && hoveredItem.hovered && background)
+ background.y = hoveredItem.y - contentY
+ }
+
+ // ItemDelegate hover item0 ==> item1, add timer ignore [item0.unhovered]
+ // item0.hovered, item0.unhovered, item1.hovered
+ Timer {
+ id: hideTimer
+ interval: control.duration
+ onTriggered: {
+ bgVisible = hoveredItem ? hoveredItem.hovered : false
+ control.state = bgVisible ? "Visible" : "Invisible"
+ }
+ }
+
+ // visible animation
+ states: [
+ State{
+ name: "Visible"
+ PropertyChanges { target: background; opacity: 1.0 }
+ PropertyChanges { target: background; scale: 1.0 }
+ PropertyChanges { target: background; visible: true }
+ },
+ State{
+ name:"Invisible"
+ PropertyChanges { target: background; opacity: 0.0 }
+ PropertyChanges { target: background; scale: 0.5 }
+ PropertyChanges { target: background; visible: false }
+ }
+ ]
+
+ transitions: [
+ Transition {
+ from: "Visible"
+ to: "Invisible"
+
+ SequentialAnimation {
+ ParallelAnimation {
+ NumberAnimation {
+ target: background
+ property: "opacity"
+ duration: control.duration
+ easing.type: Easing.InOutQuad
+ }
+ NumberAnimation {
+ target: background
+ property: "scale"
+ duration: control.duration
+ easing.type: Easing.InOutQuad
+ }
+ }
+ NumberAnimation {
+ target: background
+ property: "visible"
+ duration: 0
+ }
+ }
+ },
+ Transition {
+ from: "Invisible"
+ to: "Visible"
+ SequentialAnimation {
+ NumberAnimation {
+ target: background
+ property: "visible"
+ duration: 0
+ }
+ ParallelAnimation {
+ NumberAnimation {
+ target: background
+ property: "opacity"
+ duration: control.duration
+ easing.type: Easing.InOutQuad
+ }
+ NumberAnimation {
+ target: background
+ property: "scale"
+ duration: control.duration
+ easing.type: Easing.InOutQuad
+ }
+ }
+ }
+ }
+ ]
+
+ Item {
+ id: background
+ implicitWidth: DS.Style.itemDelegate.width
+ implicitHeight: DS.Style.itemDelegate.height
+ z: -1
+
+ Loader {
+ anchors.fill: parent
+ active: hoveredItem
+ sourceComponent: P.ButtonPanel {
+ button: hoveredItem
+ enableAnimation: false // avoid hover animation
+ outsideBorderColor: null
+ insideBorderColor: null
+ visible: hoveredItem && !hoveredItem.checked && hoveredItem.enabled
+ color1: D.Palette {
+ normal {
+ common: Qt.rgba(0, 0, 0, 0.1)
+ }
+ normalDark {
+ common: Qt.rgba(1, 1, 1, 0.1)
+ }
+ }
+ color2: color1
+ }
+ }
+
+ onVisibleChanged: {
+ if (!visible) {
+ // ensure do not show animation when hoveredItem from null to item
+ background.x = -1
+ background.y = -1
+ }
+ }
+
+ // move and resize animation
+ Behavior on x {
+ enabled: bgVisible
+ NumberAnimation { duration: control.duration }
+ }
+ Behavior on y {
+ enabled: bgVisible
+ NumberAnimation { duration: control.duration }
+ }
+ Behavior on width {
+ enabled: bgVisible
+ NumberAnimation { duration: control.duration }
+ }
+ Behavior on height {
+ enabled: bgVisible
+ NumberAnimation { duration: control.duration }
+ }
+ }
+}
diff --git a/qt6/src/qml/Menu.qml b/qt6/src/qml/Menu.qml
index 5c43d4d6..110c070d 100644
--- a/qt6/src/qml/Menu.qml
+++ b/qt6/src/qml/Menu.qml
@@ -42,13 +42,14 @@ T.Menu {
}
contentItem: Control {
- topPadding: 10 // TODO how to clip radius
+ topPadding: 6 // TODO how to clip radius
bottomPadding: topPadding
leftPadding: 0
rightPadding: leftPadding
contentItem: ColumnLayout {
id: viewLayout
+ spacing: 0
Loader {
Layout.fillWidth: true
@@ -78,6 +79,27 @@ T.Menu {
onCountChanged: refreshContentItemWidth()
onWidthChanged: refreshContentItemWidth()
+ view.highlightFollowsCurrentItem: true
+ view.highlightMoveDuration: 50
+ view.highlightMoveVelocity: -1
+
+ view.highlight: Rectangle {
+ anchors.left: parent ? parent.left : undefined
+ anchors.right: parent ? parent.right : undefined
+ anchors.leftMargin: 6
+ anchors.rightMargin: 6
+ scale: 0.9
+ property D.Palette backgroundColor: DS.Style.highlightPanel.background
+ color: D.ColorSelector.backgroundColor
+ radius: 6
+ Component.onCompleted: {
+ scale = 1.0
+ }
+ Behavior on scale {
+ NumberAnimation { duration: 100 }
+ }
+
+ }
}
Loader {
Layout.fillWidth: true
diff --git a/qt6/src/qml/MenuItem.qml b/qt6/src/qml/MenuItem.qml
index 0107be5a..61fffa75 100644
--- a/qt6/src/qml/MenuItem.qml
+++ b/qt6/src/qml/MenuItem.qml
@@ -43,6 +43,9 @@ T.MenuItem {
text: control.text
font: control.font
color: control.palette.windowText
+ Behavior on color {
+ ColorAnimation { duration: control.hovered ? 100 : 0; }
+ }
icon: D.DTK.makeIcon(control.icon, control.D.DciIcon)
}
@@ -102,15 +105,5 @@ T.MenuItem {
radius: DS.Style.control.radius
}
}
-
- Loader {
- anchors.fill: parent
- active: control.down || control.highlighted
- sourceComponent: Rectangle {
- property D.Palette backgroundColor: DS.Style.highlightPanel.background
- color: D.ColorSelector.backgroundColor
- radius: 1 // TODO can't display background when using dtk's InWindowBlur.
- }
- }
}
}
diff --git a/qt6/src/qml/Switch.qml b/qt6/src/qml/Switch.qml
index 4f148062..4844b967 100644
--- a/qt6/src/qml/Switch.qml
+++ b/qt6/src/qml/Switch.qml
@@ -20,43 +20,50 @@ T.Switch {
topPadding: DS.Style.control.vPadding
bottomPadding: DS.Style.control.vPadding
spacing: DS.Style.control.spacing
+ D.ColorSelector.hovered: false // disable hover ==> normal animation
- indicator: Rectangle {
+ indicator: D.DciIcon {
+ id: handle
implicitWidth: DS.Style.switchButton.indicatorWidth
implicitHeight: DS.Style.switchButton.indicatorHeight
x: text ? (control.mirrored ? control.width - width - control.rightPadding : control.leftPadding) : control.leftPadding + (control.availableWidth - width) / 2
y: control.topPadding + (control.availableHeight - height) / 2
- radius: DS.Style.control.radius
- color: control.D.ColorSelector.backgroundColor
- opacity: control.D.ColorSelector.controlState === D.DTK.DisabledState ? 0.4 : 1
- D.DciIcon {
- id: handle
- x: Math.max(0, Math.min(parent.width - width, control.visualPosition * parent.width - (width / 2)))
- y: (parent.height - height) / 2
- width: DS.Style.switchButton.handleWidth
- height: DS.Style.switchButton.handleHeight
- sourceSize: Qt.size(DS.Style.switchButton.handleWidth, DS.Style.switchButton.handleHeight)
- name: DS.Style.switchButton.iconName
- opacity: control.D.ColorSelector.controlState === D.DTK.DisabledState && control.checked ? 0.4 : 1
- palette {
- highlight: control.checked ? control.palette.highlight : control.D.ColorSelector.handleColor
- highlightForeground: control.palette.highlightedText
- foreground: control.palette.windowText
- background: control.palette.window
- }
- mode: control.D.ColorSelector.controlState
- theme: control.D.ColorSelector.controlTheme
- fallbackToQIcon: false
+ width: DS.Style.switchButton.handleWidth
+ height: DS.Style.switchButton.handleHeight
+ sourceSize: Qt.size(DS.Style.switchButton.indicatorWidth, DS.Style.switchButton.indicatorWidth)
+ name: !control.checked ? "switch_on" : "switch_off"
+ opacity: control.D.ColorSelector.controlState === D.DTK.DisabledState && control.checked ? 0.4 : 1
+ palette: DTK.makeIconPalette(control.palette)
+ mode: control.D.ColorSelector.controlState
+ theme: control.D.ColorSelector.controlTheme
+ fallbackToQIcon: false
+ }
- Behavior on x {
- enabled: !control.down
- SmoothedAnimation { velocity: 200 }
- }
+ Timer {
+ id: toggletimer
+ interval: 300
+ onTriggered: {
+ control.toggle()
}
}
+ function palyAndSetImage() {
+ handle.play(D.DTK.NormalState)
+ toggletimer.start();
+ }
+
+ Keys.onSpacePressed: palyAndSetImage()
+ Keys.onEnterPressed: palyAndSetImage()
+ Keys.onReturnPressed: palyAndSetImage()
+
+ MouseArea {
+ anchors.fill: parent
+ acceptedButtons: Qt.LeftButton
+ onClicked: palyAndSetImage()
+ }
+
contentItem: Label {
leftPadding: control.indicator && !control.mirrored ? control.indicator.width + control.spacing : 0
rightPadding: control.indicator && control.mirrored ? control.indicator.width + control.spacing : 0
diff --git a/qt6/src/qml/ToolButton.qml b/qt6/src/qml/ToolButton.qml
index 5fc097c3..1e07efd5 100644
--- a/qt6/src/qml/ToolButton.qml
+++ b/qt6/src/qml/ToolButton.qml
@@ -10,7 +10,7 @@ import org.deepin.dtk.private 1.0 as P
T.ToolButton {
id: control
- property D.Palette textColor: checked ? DS.Style.checkedButton.text : (highlighted ? DS.Style.highlightedButton.text : DS.Style.button.text)
+ property D.Palette textColor: checked ? DS.Style.highlightedButton.text : (highlighted ? DS.Style.highlightedButton.text : DS.Style.button.text)
implicitWidth: DS.Style.control.implicitWidth(control)
implicitHeight: DS.Style.control.implicitHeight(control)
@@ -66,10 +66,46 @@ T.ToolButton {
}
}
+ states: [
+ State {
+ name: "hovered"
+ when: control.hovered && !control.checked
+ PropertyChanges {
+ target: contentItem
+ scale : 1.2
+ }
+ PropertyChanges {
+ target: background
+ scale : 1.0
+ }
+
+ },
+ State {
+ name: "checked"
+ when: control.checked
+ PropertyChanges {
+ target: contentItem
+ scale : 1.0
+ }
+ }
+ ]
+
+ transitions: Transition {
+ NumberAnimation { properties: "scale"; easing.type: Easing.InOutQuad }
+ }
+
background: P.ButtonPanel {
+ visible: control.state === "hovered"
+ scale : 0.9
implicitWidth: DS.Style.toolButton.width
implicitHeight: DS.Style.toolButton.height
button: control
outsideBorderColor: null
+ color1: D.Palette {
+ normal {
+ common: Qt.rgba(0, 0, 0, 0.1)
+ }
+ }
+ color2 : color1
}
}
diff --git a/qt6/src/qml/private/ButtonPanel.qml b/qt6/src/qml/private/ButtonPanel.qml
index f8c62798..a77aa8bb 100644
--- a/qt6/src/qml/private/ButtonPanel.qml
+++ b/qt6/src/qml/private/ButtonPanel.qml
@@ -11,6 +11,7 @@ BoxPanel {
id: control
property Item button
+ property bool enableAnimation: control.D.ColorSelector.controlState === D.DTK.HoveredState && control.D.ColorSelector.family === D.Palette.CommonColor
color1: selectValue(DS.Style.button.background1, DS.Style.checkedButton.background, DS.Style.highlightedButton.background1)
color2: selectValue(DS.Style.button.background2, DS.Style.checkedButton.background, DS.Style.highlightedButton.background2)
insideBorderColor: selectValue(DS.Style.button.insideBorder, null, DS.Style.highlightedButton.border)
@@ -52,8 +53,7 @@ BoxPanel {
CicleSpreadAnimation {
id: hoverAnimation
anchors.fill: parent
- visible: control.D.ColorSelector.controlState === D.DTK.HoveredState
- && control.D.ColorSelector.family === D.Palette.CommonColor
+ visible: enableAnimation
Rectangle {
anchors.fill: parent
diff --git a/qt6/src/qml/private/ProgressBarImpl.qml b/qt6/src/qml/private/ProgressBarImpl.qml
index d9270975..dd29b673 100644
--- a/qt6/src/qml/private/ProgressBarImpl.qml
+++ b/qt6/src/qml/private/ProgressBarImpl.qml
@@ -39,12 +39,32 @@ Item {
visible: progressBar.visualPosition > 0
Rectangle {
+ id: rect
anchors.fill: parent
radius: parent.cornerRadius
+ property int count
+ property real lightPosition
gradient: Gradient {
- GradientStop { position: 1 - 1 / progressBar.visualPosition; color: progressBar.palette.highlight }
- GradientStop {position: 1 - 0.28 / progressBar.visualPosition; color: progressBar.palette.highlight }
- GradientStop { position: 1; color: control.D.ColorSelector.handleGradientColor }
+ GradientStop { position: 0; color: progressBar.palette.highlight }
+ GradientStop { position: rect.lightPosition; color: control.D.ColorSelector.handleGradientColor }
+ GradientStop { position: 1; color: progressBar.palette.highlight }
+ }
+ Timer {
+ id: moveTimer
+ interval: 10
+ repeat: true
+ running: rect.visible
+ onTriggered: {
+ moveTimer.interval = 10
+ if (rect.count === 100) {
+ rect.count = 0
+ rect.lightPosition = 0.0
+ moveTimer.interval = 2000
+ return;
+ }
+ rect.count += 1
+ rect.lightPosition = rect.count * 0.01
+ }
}
}
}
@@ -98,13 +118,32 @@ Item {
rotation: -90
Rectangle {
+ id: indeterminateRect
anchors.fill: parent
radius: indeterminateProgressContent.cornerRadius
+ property int count
+ property real lightPosition
gradient: Gradient {
GradientStop { position: 0.0; color: progressBar.palette.highlight }
- GradientStop { position: 0.39; color: control.D.ColorSelector.handleGradientColor }
+ GradientStop { position: indeterminateRect.lightPosition; color: control.D.ColorSelector.handleGradientColor }
GradientStop { position: 1.0; color: progressBar.palette.highlight }
}
+ Timer {
+ id: indeterminateMoveTimer
+ interval: 50
+ repeat: true
+ running: indeterminateRect.visible
+ onTriggered: {
+ indeterminateMoveTimer.interval = 50
+ if (indeterminateRect.count === 100) {
+ indeterminateRect.count = 0
+ indeterminateMoveTimer.interval = 2000
+ return;
+ }
+ indeterminateRect.count += 5
+ indeterminateRect.lightPosition = indeterminateRect.count * 0.01
+ }
+ }
}
SequentialAnimation {
diff --git a/src/dquickwindow.cpp b/src/dquickwindow.cpp
index 42a4eeaa..101791e6 100644
--- a/src/dquickwindow.cpp
+++ b/src/dquickwindow.cpp
@@ -108,6 +108,24 @@ inline static void updateValue(QPoint &value, Func call)
}
}
+template
+inline static void updateValue(DTK_GUI_NAMESPACE::DPlatformHandle::EffectScenes &value, Func call)
+{
+ if (value != DTK_GUI_NAMESPACE::DPlatformHandle::EffectScene(0)) {
+ call(value);
+ value = DTK_GUI_NAMESPACE::DPlatformHandle::EffectScene(0);
+ }
+}
+
+template
+inline static void updateValue(DTK_GUI_NAMESPACE::DPlatformHandle::EffectTypes &value, Func call)
+{
+ if (value != DTK_GUI_NAMESPACE::DPlatformHandle::EffectType(0)) {
+ call(value);
+ value = DTK_GUI_NAMESPACE::DPlatformHandle::EffectType(0);
+ }
+}
+
bool DQuickWindowAttachedPrivate::ensurePlatformHandle()
{
if (handle)
@@ -133,6 +151,8 @@ bool DQuickWindowAttachedPrivate::ensurePlatformHandle()
updateValue(explicitEnableSystemResize, std::bind(&DPlatformHandle::setEnableSystemResize, handle, std::placeholders::_1));
updateValue(explicitEnableSystemMove, std::bind(&DPlatformHandle::setEnableSystemMove, handle, std::placeholders::_1));
updateValue(explicitEnableBlurWindow, std::bind(&DPlatformHandle::setEnableBlurWindow, handle, std::placeholders::_1));
+ updateValue(explicitEffectScene, std::bind(&DPlatformHandle::setWindowEffect, handle, std::placeholders::_1));
+ updateValue(explicitEffectType, std::bind(&DPlatformHandle::setWindowStartUpEffect, handle, std::placeholders::_1));
QObject::connect(handle, &DPlatformHandle::borderColorChanged, q, &DQuickWindowAttached::borderColorChanged);
QObject::connect(handle, &DPlatformHandle::borderWidthChanged, q, &DQuickWindowAttached::borderWidthChanged);
@@ -145,6 +165,8 @@ bool DQuickWindowAttachedPrivate::ensurePlatformHandle()
QObject::connect(handle, &DPlatformHandle::enableSystemResizeChanged, q, &DQuickWindowAttached::enableSystemResizeChanged);
QObject::connect(handle, &DPlatformHandle::enableBlurWindowChanged, q, &DQuickWindowAttached::enableBlurWindowChanged);
QObject::connect(handle, SIGNAL(enableBlurWindowChanged()), q, SLOT(_q_updateBlurAreaForWindow()));
+ QObject::connect(handle, &DPlatformHandle::windowEffectChanged, q, &DQuickWindowAttached::windowEffectChanged);
+ QObject::connect(handle, &DPlatformHandle::windowStartUpEffectChanged, q, &DQuickWindowAttached::windowStartUpEffectChanged);
Q_EMIT q->enabledChanged();
return true;
}
@@ -486,6 +508,28 @@ void DQuickWindowAttached::setLoadingOverlay(QQmlComponent *component)
Q_EMIT loadingOverlayChanged();
}
+void DQuickWindowAttached::setWindowEffect(DTK_GUI_NAMESPACE::DPlatformHandle::EffectScenes effect)
+{
+ D_D(DQuickWindowAttached);
+
+ d->ensurePlatformHandle();
+ if (d->handle)
+ d->handle->setWindowEffect(effect);
+ else
+ d->explicitEffectScene = effect;
+}
+
+void DQuickWindowAttached::setWindowStartUpEffect(DTK_GUI_NAMESPACE::DPlatformHandle::EffectTypes type)
+{
+ D_D(DQuickWindowAttached);
+
+ d->ensurePlatformHandle();
+ if (d->handle)
+ d->handle->setWindowStartUpEffect(type);
+ else
+ d->explicitEffectType = type;
+}
+
/*!
* \~chinese \property DQuickWindowAttached::translucentBackground
* \~chinese \brief 如果此属性值为 true,则在更新窗口绘制内容之前会先清空要更新区域内的图像,否则不清空。
@@ -620,6 +664,29 @@ void DQuickWindowAttached::resetThemeType()
}
#endif
+
+DTK_GUI_NAMESPACE::DPlatformHandle::EffectScene DQuickWindowAttached::windowEffect() const
+{
+ D_DC(DQuickWindowAttached);
+
+ if (!d->handle) {
+ return DTK_GUI_NAMESPACE::DPlatformHandle::EffectScene(0);
+ }
+
+ return d->handle->windowEffect();
+}
+
+DTK_GUI_NAMESPACE::DPlatformHandle::EffectType DQuickWindowAttached::windowStartUpEffect() const
+{
+ D_DC(DQuickWindowAttached);
+
+ if (!d->handle) {
+ return DTK_GUI_NAMESPACE::DPlatformHandle::EffectType(0);
+ }
+
+ return d->handle->windowStartUpEffect();
+}
+
/*!
* \~chinese \brief DQuickWindowAttached::setEnabled 设置当前的窗口为 DTK 风格。
* \~chinese \note 只能把默认风格设置为 DTK 风格,不能把 DTK 设置为默认风格。
diff --git a/src/dquickwindow.h b/src/dquickwindow.h
index 1d8cc918..f2b68abc 100644
--- a/src/dquickwindow.h
+++ b/src/dquickwindow.h
@@ -72,6 +72,8 @@ class DQuickWindowAttached : public QObject, public DTK_CORE_NAMESPACE::DObject
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
Q_PROPERTY(DTK_GUI_NAMESPACE::DGuiApplicationHelper::ColorType themeType READ themeType WRITE setThemeType RESET resetThemeType NOTIFY themeTypeChanged)
#endif
+ Q_PROPERTY(DTK_GUI_NAMESPACE::DPlatformHandle::EffectScene windowEffect READ windowEffect WRITE setWindowEffect NOTIFY windowEffectChanged)
+ Q_PROPERTY(DTK_GUI_NAMESPACE::DPlatformHandle::EffectType windowStartUpEffect READ windowStartUpEffect WRITE setWindowStartUpEffect NOTIFY windowStartUpEffectChanged)
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
QML_ANONYMOUS
#endif
@@ -117,6 +119,9 @@ class DQuickWindowAttached : public QObject, public DTK_CORE_NAMESPACE::DObject
void resetThemeType();
#endif
+ DTK_GUI_NAMESPACE::DPlatformHandle::EffectScene windowEffect() const;
+ DTK_GUI_NAMESPACE::DPlatformHandle::EffectType windowStartUpEffect() const;
+
public Q_SLOTS:
void setEnabled(bool e);
@@ -149,6 +154,9 @@ public Q_SLOTS:
void setOverlayExited(QQuickTransition *exit);
void setLoadingOverlay(QQmlComponent *component);
+ void setWindowEffect(DTK_GUI_NAMESPACE::DPlatformHandle::EffectScenes effect);
+ void setWindowStartUpEffect(DTK_GUI_NAMESPACE::DPlatformHandle::EffectTypes type);
+
protected:
bool eventFilter(QObject *watched, QEvent *event) override;
@@ -175,6 +183,8 @@ public Q_SLOTS:
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
void themeTypeChanged();
#endif
+ void windowEffectChanged();
+ void windowStartUpEffectChanged();
private:
D_DECLARE_PRIVATE(DQuickWindowAttached)
diff --git a/src/dtkdeclarative_assets.qrc b/src/dtkdeclarative_assets.qrc
index c4126298..a10294a3 100644
--- a/src/dtkdeclarative_assets.qrc
+++ b/src/dtkdeclarative_assets.qrc
@@ -46,7 +46,8 @@
icons/bloom/slider_point_left.dci
icons/bloom/slider_round_hor.dci
icons/bloom/slider_round_ver.dci
- icons/bloom/switch_button.dci
+ icons/bloom/switch_on.dci
+ icons/bloom/switch_off.dci
icons/bloom/slider_point_up.dci
icons/bloom/checkbox_mix.dci
icons/bloom/checkbox_checked.dci
@@ -86,6 +87,8 @@
icons/bloom/list_delete.dci
icons/bloom/menu_arrow.dci
icons/bloom/menu_select.dci
+ icons/bloom/item_checked.dci
+ icons/bloom/item_unchecked.dci
icons/bloom/window_sidebar.dci
icons/bloom/action_add.dci
icons/bloom/radio_checked.dci
diff --git a/src/icons/bloom/checkbox_checked.dci b/src/icons/bloom/checkbox_checked.dci
index bae6718e..de394945 100644
Binary files a/src/icons/bloom/checkbox_checked.dci and b/src/icons/bloom/checkbox_checked.dci differ
diff --git a/src/icons/bloom/checkbox_unchecked.dci b/src/icons/bloom/checkbox_unchecked.dci
index e68eed24..413e4145 100644
Binary files a/src/icons/bloom/checkbox_unchecked.dci and b/src/icons/bloom/checkbox_unchecked.dci differ
diff --git a/src/icons/bloom/item_checked.dci b/src/icons/bloom/item_checked.dci
new file mode 100644
index 00000000..e38bb103
Binary files /dev/null and b/src/icons/bloom/item_checked.dci differ
diff --git a/src/icons/bloom/item_unchecked.dci b/src/icons/bloom/item_unchecked.dci
new file mode 100644
index 00000000..4da8717c
Binary files /dev/null and b/src/icons/bloom/item_unchecked.dci differ
diff --git a/src/icons/bloom/radio_checked.dci b/src/icons/bloom/radio_checked.dci
index 1075ebd3..69df89f3 100644
Binary files a/src/icons/bloom/radio_checked.dci and b/src/icons/bloom/radio_checked.dci differ
diff --git a/src/icons/bloom/radio_unchecked.dci b/src/icons/bloom/radio_unchecked.dci
index 641029d6..792ce8ec 100644
Binary files a/src/icons/bloom/radio_unchecked.dci and b/src/icons/bloom/radio_unchecked.dci differ
diff --git a/src/icons/bloom/switch_off.dci b/src/icons/bloom/switch_off.dci
new file mode 100644
index 00000000..957f499a
Binary files /dev/null and b/src/icons/bloom/switch_off.dci differ
diff --git a/src/icons/bloom/switch_on.dci b/src/icons/bloom/switch_on.dci
new file mode 100644
index 00000000..20ec32c8
Binary files /dev/null and b/src/icons/bloom/switch_on.dci differ
diff --git a/src/private/dmessagemanager.cpp b/src/private/dmessagemanager.cpp
index 4d1bd33d..e80259f4 100644
--- a/src/private/dmessagemanager.cpp
+++ b/src/private/dmessagemanager.cpp
@@ -54,6 +54,19 @@ void FloatingMessageContainer::setDuration(int duration)
Q_EMIT durationChanged();
}
+bool FloatingMessageContainer::immediateClose() const
+{
+ return m_immediateClose;
+}
+
+void FloatingMessageContainer::setImmediateClose(bool immediateClose)
+{
+ if (m_immediateClose == immediateClose)
+ return;
+
+ m_immediateClose = immediateClose;
+}
+
void FloatingMessageContainer::close()
{
if (auto manager = qobject_cast(parent())) {
@@ -188,9 +201,10 @@ void MessageManager::ensureLayout()
QQmlComponent columnCom(qmlEngine(parent()));
columnCom.setData("import QtQuick 2.11\n"
"Column {\n"
+ " spacing: 0\n"
" anchors {\n"
" bottom: parent.bottom\n"
- " bottomMargin: 10;\n"
+ " bottomMargin: 20;\n"
" horizontalCenter: parent.horizontalCenter\n"
" }\n"
"}\n", QUrl());
@@ -307,7 +321,11 @@ void MessageManager::timerEvent(QTimerEvent *e)
killTimer(e->timerId());
e->accept();
if (auto container = item.second) {
- close(container);
+ if (container->immediateClose()) {
+ close(container);
+ } else {
+ Q_EMIT container->delayClose();
+ }
}
break;
}
diff --git a/src/private/dmessagemanager_p.h b/src/private/dmessagemanager_p.h
index 3e613015..002fe0ba 100644
--- a/src/private/dmessagemanager_p.h
+++ b/src/private/dmessagemanager_p.h
@@ -18,6 +18,7 @@ class FloatingMessageContainer : public QObject
Q_PROPERTY(QQuickItem *panel READ panel WRITE setPanel)
Q_PROPERTY(QVariant message READ message WRITE setMessage NOTIFY messageChanged)
Q_PROPERTY(int duration READ duration WRITE setDuration NOTIFY durationChanged)
+ Q_PROPERTY(bool immediateClose READ immediateClose WRITE setImmediateClose)
Q_CLASSINFO("DefaultProperty", "panel")
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
QML_NAMED_ELEMENT(FloatingMessageContainer)
@@ -33,6 +34,8 @@ class FloatingMessageContainer : public QObject
void setMessageId(const QString &msgId);
int duration() const;
void setDuration(int duration);
+ bool immediateClose() const;
+ void setImmediateClose(bool immediateClose);
public Q_SLOT:
void close();
@@ -40,6 +43,7 @@ public Q_SLOT:
Q_SIGNALS:
void messageChanged();
void durationChanged();
+ void delayClose();
private:
friend MessageManager;
@@ -48,6 +52,7 @@ public Q_SLOT:
QVariant m_message;
QString m_msgId;
int m_duration = 4000;
+ bool m_immediateClose = false;
};
class MessageManager : public QObject
diff --git a/src/private/dquickdciiconimage.cpp b/src/private/dquickdciiconimage.cpp
index cffac58a..3bf4d794 100644
--- a/src/private/dquickdciiconimage.cpp
+++ b/src/private/dquickdciiconimage.cpp
@@ -18,6 +18,47 @@ static QString appIconThemeName()
return DGuiApplicationHelper::instance()->applicationTheme()->iconThemeName();
}
+static QString findDciIconPath(const QString &iconName, const QString &themeName)
+{
+ QString iconPath;
+ auto cached = DIconTheme::cached();
+
+ if (cached) {
+ iconPath = cached->findDciIconFile(iconName, themeName);
+ } else {
+ iconPath = DIconTheme::findDciIconFile(iconName, themeName);
+ }
+ return iconPath;
+}
+
+static DDciIcon::Mode controlState2DciMode(int state)
+{
+ DDciIcon::Mode dcimode = DDciIcon::Normal;
+ switch (state) {
+ case DQMLGlobalObject::NormalState:
+ dcimode = DDciIcon::Normal;
+ break;
+ case DQMLGlobalObject::DisabledState:
+ dcimode = DDciIcon::Disabled;
+ break;
+ case DQMLGlobalObject::HoveredState:
+ dcimode = DDciIcon::Hover;
+ break;
+ case DQMLGlobalObject::PressedState:
+ dcimode = DDciIcon::Pressed;
+ break;
+ default:
+ break;
+ }
+
+ return dcimode;
+}
+
+static inline DDciIcon::Theme dciTheme(DGuiApplicationHelper::ColorType type)
+{
+ return type == DGuiApplicationHelper::DarkType ? DDciIcon::Dark : DDciIcon::Light;
+}
+
DQuickDciIconImageItemPrivate::DQuickDciIconImageItemPrivate(DQuickDciIconImagePrivate *pqq)
: parentPriv(pqq)
{
@@ -31,11 +72,27 @@ void DQuickDciIconImageItemPrivate::maybeUpdateUrl()
return DQuickIconImagePrivate::maybeUpdateUrl();
}
- QUrl url;
- url.setScheme(QLatin1String("image"));
- url.setHost(QLatin1String("dtk.dci.icon"));
- url.setQuery(getUrlQuery());
- q->setSource(url);
+ QString iconPath = findDciIconPath(parentPriv->imageItem->name(), appIconThemeName());
+ if (iconPath.isEmpty())
+ return DQuickIconImagePrivate::maybeUpdateUrl();
+
+ updatePlayer();
+
+ if (player)
+ player->setMode(controlState2DciMode(parentPriv->mode));
+}
+
+void DQuickDciIconImageItemPrivate::play(int mode)
+{
+ Q_Q(DQuickIconImage);
+ if (parentPriv->imageItem->name().isEmpty() || iconType != ThemeIconName) {
+ return;
+ }
+
+ updatePlayer();
+
+ if (player)
+ player->play(controlState2DciMode(mode));
}
QUrlQuery DQuickDciIconImageItemPrivate::getUrlQuery()
@@ -56,6 +113,53 @@ QUrlQuery DQuickDciIconImageItemPrivate::getUrlQuery()
return query;
}
+void DQuickDciIconImageItemPrivate::updatePlayerIconSize()
+{
+ if (!player)
+ return;
+
+ int boundingSize = qMax(q_func()->sourceSize().width(), q_func()->sourceSize().height());
+
+ player->setIconSize(boundingSize);
+}
+
+void DQuickDciIconImageItemPrivate::updatePlayer()
+{
+ if (!player) {
+ Q_Q(DQuickIconImage);
+ player = new DDciIconPlayer(parentPriv->imageItem);
+ QObject::connect(player, &DDciIconPlayer::updated, parentPriv->imageItem, [this](){
+ parentPriv->imageItem->setImage(player->currentImage());
+ });
+ QObject::connect(parentPriv->imageItem, &DQuickIconImage::sourceSizeChanged, player, [this](){
+ updatePlayerIconSize();
+ });
+ }
+
+ QString iconPath = findDciIconPath(parentPriv->imageItem->name(), appIconThemeName());
+
+ // 防止频繁构造 dciicon
+ if (iconPathCache != iconPath) {
+ DDciIcon dciIcon(iconPath);
+ if (!dciIcon.isNull()) {
+ player->setIcon(dciIcon);
+ iconPathCache = iconPath;
+ }
+ }
+
+ player->setTheme(dciTheme(parentPriv->theme));
+
+ DDciIconPalette palette = parentPriv->palette;
+ if (!parentPriv->palette.foreground().isValid() && q_func()->color().isValid())
+ palette.setForeground(q_func()->color());
+
+ player->setPalette(palette);
+
+ updatePlayerIconSize();
+
+ player->setDevicePixelRatio(devicePixelRatio);
+}
+
DQuickDciIconImagePrivate::DQuickDciIconImagePrivate(DQuickDciIconImage *qq)
: DObjectPrivate(qq)
, imageItem(new DQuickIconImage(*new DQuickDciIconImageItemPrivate(this), qq))
@@ -76,6 +180,11 @@ void DQuickDciIconImagePrivate::updateImageSourceUrl()
imageItem->d_func()->maybeUpdateUrl();
}
+void DQuickDciIconImagePrivate::play(DQMLGlobalObject::ControlState mode)
+{
+ imageItem->d_func()->play(mode);
+}
+
DQuickDciIconImage::DQuickDciIconImage(QQuickItem *parent)
: QQuickItem(parent)
, DObject(*new DQuickDciIconImagePrivate(this))
@@ -119,6 +228,13 @@ void DQuickDciIconImage::setMode(DQMLGlobalObject::ControlState mode)
Q_EMIT modeChanged();
}
+void DQuickDciIconImage::play(DQMLGlobalObject::ControlState mode)
+{
+ D_D(DQuickDciIconImage);
+ if (d->imageItem)
+ d->play(mode);
+}
+
DGuiApplicationHelper::ColorType DQuickDciIconImage::theme() const
{
D_DC(DQuickDciIconImage);
@@ -226,15 +342,7 @@ Dtk::Quick::DQuickIconImage *DQuickDciIconImage::imageItem() const
bool DQuickDciIconImage::isNull(const QString &iconName)
{
- QString iconPath;
- auto cached = DIconTheme::cached();
-
- if (cached) {
- iconPath = cached->findDciIconFile(iconName, appIconThemeName());
- } else {
- iconPath = DIconTheme::findDciIconFile(iconName, appIconThemeName());
- }
- return iconPath.isEmpty();
+ return findDciIconPath(iconName, appIconThemeName()).isEmpty();
}
DQuickIconAttached *DQuickDciIconImage::qmlAttachedProperties(QObject *object)
diff --git a/src/private/dquickdciiconimage_p.h b/src/private/dquickdciiconimage_p.h
index 8b7fb3d5..1d61f0f2 100644
--- a/src/private/dquickdciiconimage_p.h
+++ b/src/private/dquickdciiconimage_p.h
@@ -46,6 +46,7 @@ class DQuickDciIconImage : public QQuickItem, DCORE_NAMESPACE::DObject
DQMLGlobalObject::ControlState mode() const;
void setMode(DQMLGlobalObject::ControlState mode);
+ Q_INVOKABLE void play(DQMLGlobalObject::ControlState mode);
DGuiApplicationHelper::ColorType theme() const;
void setTheme(DGuiApplicationHelper::ColorType theme);
diff --git a/src/private/dquickdciiconimage_p_p.h b/src/private/dquickdciiconimage_p_p.h
index 81fd039b..5d2ea787 100644
--- a/src/private/dquickdciiconimage_p_p.h
+++ b/src/private/dquickdciiconimage_p_p.h
@@ -12,6 +12,7 @@
#include
#include
+#include
DQUICK_BEGIN_NAMESPACE
class DQuickDciIconImageItemPrivate;
@@ -22,10 +23,15 @@ class DQuickDciIconImageItemPrivate : public DQuickIconImagePrivate
public:
DQuickDciIconImageItemPrivate(DQuickDciIconImagePrivate *pqq);
void maybeUpdateUrl();
+ void play(int mode);
QUrlQuery getUrlQuery();
+ void updatePlayer();
+ void updatePlayerIconSize();
private:
DQuickDciIconImagePrivate *parentPriv;
+ DDciIconPlayer *player = nullptr;
+ QString iconPathCache;
};
class DQuickDciIconImagePrivate : public DCORE_NAMESPACE::DObjectPrivate
@@ -36,6 +42,7 @@ class DQuickDciIconImagePrivate : public DCORE_NAMESPACE::DObjectPrivate
DQuickDciIconImagePrivate(DQuickDciIconImage *qq);
void layout();
void updateImageSourceUrl();
+ void play(DQMLGlobalObject::ControlState mode);
DDciIconPalette palette;
DQuickIconImage *imageItem;
diff --git a/src/private/dquickiconimage.cpp b/src/private/dquickiconimage.cpp
index 1772751a..a2f19c11 100644
--- a/src/private/dquickiconimage.cpp
+++ b/src/private/dquickiconimage.cpp
@@ -108,6 +108,11 @@ void DQuickIconImagePrivate::maybeUpdateUrl()
q->setSource(url);
}
+void DQuickIconImagePrivate::play(int mode)
+{
+ Q_UNUSED(mode)
+}
+
QUrlQuery DQuickIconImagePrivate::getUrlQuery()
{
QUrlQuery query;
@@ -316,6 +321,12 @@ void DQuickIconImage::setFallbackSource(const QUrl &newSource)
d->maybeUpdateUrl();
}
+void DQuickIconImage::setImage(const QImage &img)
+{
+ D_D(DQuickIconImage);
+ d->setImage(img);
+}
+
DQuickIconImage::DQuickIconImage(DQuickIconImagePrivate &dd, QQuickItem *parent)
: QQuickImage(dd, parent)
{
diff --git a/src/private/dquickiconimage_p.h b/src/private/dquickiconimage_p.h
index 3afe3260..58fdb98b 100644
--- a/src/private/dquickiconimage_p.h
+++ b/src/private/dquickiconimage_p.h
@@ -65,6 +65,7 @@ public Q_SLOTS:
void setMode(Mode mode);
void setColor(const QColor &color);
void setFallbackSource(const QUrl &newSource);
+ void setImage(const QImage &img);
Q_SIGNALS:
void nameChanged();
diff --git a/src/private/dquickiconimage_p_p.h b/src/private/dquickiconimage_p_p.h
index e6973c53..847775af 100644
--- a/src/private/dquickiconimage_p_p.h
+++ b/src/private/dquickiconimage_p_p.h
@@ -23,6 +23,7 @@ class DQuickIconImagePrivate : public QQuickImagePrivate
public:
void init();
virtual void maybeUpdateUrl();
+ virtual void play(int mode);
QUrlQuery getUrlQuery();
DQuickIconImage::Mode getIconMode() const;
diff --git a/src/private/dquickiconlabel.cpp b/src/private/dquickiconlabel.cpp
index cc7c7f99..94dda0ea 100644
--- a/src/private/dquickiconlabel.cpp
+++ b/src/private/dquickiconlabel.cpp
@@ -473,6 +473,7 @@ void DQuickIconLabel::setColor(const QColor &color)
d->color = color;
if (d->label)
d->label->setColor(color);
+ Q_EMIT colorChanged(color);
}
DQuickIconLabel::Display DQuickIconLabel::display() const
diff --git a/src/private/dquickiconlabel_p.h b/src/private/dquickiconlabel_p.h
index ac675040..19db472f 100644
--- a/src/private/dquickiconlabel_p.h
+++ b/src/private/dquickiconlabel_p.h
@@ -21,7 +21,7 @@ class DQuickIconLabel : public QQuickItem
Q_PROPERTY(DTK_QUICK_NAMESPACE::DQuickDciIcon 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(QColor color READ color WRITE setColor NOTIFY colorChanged 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)
@@ -87,6 +87,9 @@ class DQuickIconLabel : public QQuickItem
void setBottomPadding(qreal padding);
void resetBottomPadding();
+Q_SIGNALS:
+ void colorChanged(const QColor &color);
+
protected:
void componentComplete() override;
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
diff --git a/src/private/dquickwindow_p.h b/src/private/dquickwindow_p.h
index dd442aee..17d50221 100644
--- a/src/private/dquickwindow_p.h
+++ b/src/private/dquickwindow_p.h
@@ -65,6 +65,8 @@ class DQuickWindowAttachedPrivate : public DTK_CORE_NAMESPACE::DObjectPrivate
QPoint explicitShadowOffset;
QColor explicitBorderColor;
QColor explicitShadowColor;
+ DPlatformHandle::EffectScenes explicitEffectScene = DPlatformHandle::EffectScenes(0);
+ DPlatformHandle::EffectTypes explicitEffectType = DPlatformHandle::EffectTypes(0);
DWindowManagerHelper::WmWindowTypes wmWindowTypes;
DWindowManagerHelper::MotifFunctions motifFunctions;