summaryrefslogtreecommitdiff
path: root/raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modules/Settings/DesktopWidgetsTab.qml
diff options
context:
space:
mode:
authornippy <you@example.com>2026-04-18 13:49:56 +0200
committernippy <you@example.com>2026-04-18 13:49:56 +0200
commit5d94c0a7d44a2255b81815a52a7056a94a39842d (patch)
tree759bdea9645c6a62f9e1e4c001f7d81cccd120d2 /raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modules/Settings/DesktopWidgetsTab.qml
parente79cdf210b267f21a186255ce1a4d50029439d54 (diff)
downloadRaveOS-PKGBUILD-5d94c0a7d44a2255b81815a52a7056a94a39842d.tar.gz
RaveOS-PKGBUILD-5d94c0a7d44a2255b81815a52a7056a94a39842d.zip
update Raveos themes
Diffstat (limited to 'raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modules/Settings/DesktopWidgetsTab.qml')
-rw-r--r--raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modules/Settings/DesktopWidgetsTab.qml708
1 files changed, 708 insertions, 0 deletions
diff --git a/raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modules/Settings/DesktopWidgetsTab.qml b/raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modules/Settings/DesktopWidgetsTab.qml
new file mode 100644
index 0000000..5fb2794
--- /dev/null
+++ b/raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modules/Settings/DesktopWidgetsTab.qml
@@ -0,0 +1,708 @@
+pragma ComponentBehavior: Bound
+
+import QtQuick
+import Quickshell
+import qs.Common
+import qs.Services
+import qs.Widgets
+import qs.Modules.Settings.Widgets
+
+Item {
+ id: root
+
+ LayoutMirroring.enabled: I18n.isRtl
+ LayoutMirroring.childrenInherit: true
+
+ property var expandedStates: ({})
+ property var groupCollapsedStates: ({})
+ property var parentModal: null
+ property string editingGroupId: ""
+ property string newGroupName: ""
+
+ readonly property var allInstances: SettingsData.desktopWidgetInstances || []
+ readonly property var allGroups: SettingsData.desktopWidgetGroups || []
+
+ function showWidgetBrowser() {
+ widgetBrowserLoader.active = true;
+ if (widgetBrowserLoader.item)
+ widgetBrowserLoader.item.show();
+ }
+
+ function showDesktopPluginBrowser() {
+ desktopPluginBrowserLoader.active = true;
+ if (desktopPluginBrowserLoader.item)
+ desktopPluginBrowserLoader.item.show();
+ }
+
+ LazyLoader {
+ id: widgetBrowserLoader
+ active: false
+
+ DesktopWidgetBrowser {
+ parentModal: root.parentModal
+ onWidgetAdded: widgetType => {
+ ToastService.showInfo(I18n.tr("Widget added"));
+ }
+ }
+ }
+
+ LazyLoader {
+ id: desktopPluginBrowserLoader
+ active: false
+
+ PluginBrowser {
+ parentModal: root.parentModal
+ typeFilter: "desktop-widget"
+ }
+ }
+
+ DankFlickable {
+ anchors.fill: parent
+ clip: true
+ contentHeight: mainColumn.height + Theme.spacingXL
+ contentWidth: width
+
+ Column {
+ id: mainColumn
+ topPadding: 4
+ width: Math.min(550, parent.width - Theme.spacingL * 2)
+ anchors.horizontalCenter: parent.horizontalCenter
+ spacing: Theme.spacingXL
+
+ SettingsCard {
+ width: parent.width
+ iconName: "widgets"
+ title: I18n.tr("Desktop Widgets")
+
+ Column {
+ width: parent.width - Theme.spacingM * 2
+ x: Theme.spacingM
+ spacing: Theme.spacingM
+
+ StyledText {
+ width: parent.width
+ text: I18n.tr("Add and configure widgets that appear on your desktop")
+ font.pixelSize: Theme.fontSizeSmall
+ color: Theme.surfaceVariantText
+ wrapMode: Text.WordWrap
+ horizontalAlignment: Text.AlignLeft
+ }
+
+ Row {
+ spacing: Theme.spacingM
+
+ DankButton {
+ text: I18n.tr("Add Widget")
+ iconName: "add"
+ onClicked: root.showWidgetBrowser()
+ }
+
+ DankButton {
+ text: I18n.tr("Browse Plugins")
+ iconName: "store"
+ onClicked: root.showDesktopPluginBrowser()
+ }
+ }
+ }
+ }
+
+ SettingsCard {
+ width: parent.width
+ iconName: "folder"
+ title: I18n.tr("Groups")
+ collapsible: true
+ expanded: root.allGroups.length > 0
+
+ Column {
+ width: parent.width - Theme.spacingM * 2
+ x: Theme.spacingM
+ spacing: Theme.spacingM
+
+ StyledText {
+ width: parent.width
+ text: I18n.tr("Organize widgets into collapsible groups")
+ font.pixelSize: Theme.fontSizeSmall
+ color: Theme.surfaceVariantText
+ wrapMode: Text.WordWrap
+ horizontalAlignment: Text.AlignLeft
+ }
+
+ Row {
+ spacing: Theme.spacingS
+ width: parent.width
+
+ DankTextField {
+ id: newGroupField
+ width: parent.width - addGroupBtn.width - Theme.spacingS
+ placeholderText: I18n.tr("New group name...")
+ text: root.newGroupName
+ onTextChanged: root.newGroupName = text
+ onAccepted: {
+ if (!text.trim())
+ return;
+ SettingsData.createDesktopWidgetGroup(text.trim());
+ root.newGroupName = "";
+ text = "";
+ }
+ }
+
+ DankButton {
+ id: addGroupBtn
+ iconName: "add"
+ text: I18n.tr("Add")
+ enabled: root.newGroupName.trim().length > 0
+ onClicked: {
+ SettingsData.createDesktopWidgetGroup(root.newGroupName.trim());
+ root.newGroupName = "";
+ newGroupField.text = "";
+ }
+ }
+ }
+
+ Column {
+ width: parent.width
+ spacing: Theme.spacingXS
+ visible: root.allGroups.length > 0
+
+ Repeater {
+ model: root.allGroups
+
+ Rectangle {
+ id: groupItem
+ required property var modelData
+ required property int index
+
+ width: parent.width
+ height: 40
+ radius: Theme.cornerRadius
+ color: groupMouseArea.containsMouse ? Theme.surfaceHover : Theme.surfaceContainer
+
+ Row {
+ anchors.fill: parent
+ anchors.leftMargin: Theme.spacingS
+ anchors.rightMargin: Theme.spacingS
+ spacing: Theme.spacingS
+
+ DankIcon {
+ name: "folder"
+ size: Theme.iconSizeSmall
+ color: Theme.surfaceText
+ anchors.verticalCenter: parent.verticalCenter
+ }
+
+ Loader {
+ active: root.editingGroupId === groupItem.modelData.id
+ width: active ? parent.width - Theme.iconSizeSmall - deleteGroupBtn.width - Theme.spacingS * 3 : 0
+ height: active ? 32 : 0
+ anchors.verticalCenter: parent.verticalCenter
+
+ sourceComponent: DankTextField {
+ text: groupItem.modelData.name
+ onAccepted: {
+ if (!text.trim())
+ return;
+ SettingsData.updateDesktopWidgetGroup(groupItem.modelData.id, {
+ name: text.trim()
+ });
+ root.editingGroupId = "";
+ }
+ onEditingFinished: {
+ if (!text.trim())
+ return;
+ SettingsData.updateDesktopWidgetGroup(groupItem.modelData.id, {
+ name: text.trim()
+ });
+ root.editingGroupId = "";
+ }
+ Component.onCompleted: forceActiveFocus()
+ }
+ }
+
+ StyledText {
+ visible: root.editingGroupId !== groupItem.modelData.id
+ text: groupItem.modelData.name
+ font.pixelSize: Theme.fontSizeMedium
+ color: Theme.surfaceText
+ anchors.verticalCenter: parent.verticalCenter
+ elide: Text.ElideRight
+ width: parent.width - Theme.iconSizeSmall - deleteGroupBtn.width - Theme.spacingS * 3
+ }
+
+ DankActionButton {
+ id: deleteGroupBtn
+ iconName: "delete"
+ anchors.verticalCenter: parent.verticalCenter
+ onClicked: {
+ SettingsData.removeDesktopWidgetGroup(groupItem.modelData.id);
+ ToastService.showInfo(I18n.tr("Group removed"));
+ }
+ }
+ }
+
+ MouseArea {
+ id: groupMouseArea
+ anchors.fill: parent
+ hoverEnabled: true
+ onDoubleClicked: root.editingGroupId = groupItem.modelData.id
+ }
+ }
+ }
+ }
+ }
+ }
+
+ Repeater {
+ model: root.allGroups
+
+ Column {
+ id: groupSection
+ required property var modelData
+ required property int index
+
+ readonly property string groupId: modelData.id
+ readonly property var groupInstances: root.allInstances.filter(inst => inst.group === groupId)
+
+ width: mainColumn.width
+ spacing: Theme.spacingM
+ visible: groupInstances.length > 0
+
+ Rectangle {
+ width: parent.width
+ height: 44
+ radius: Theme.cornerRadius
+ color: Theme.surfaceContainer
+
+ Row {
+ anchors.fill: parent
+ anchors.leftMargin: Theme.spacingM
+ anchors.rightMargin: Theme.spacingM
+ spacing: Theme.spacingS
+
+ DankIcon {
+ name: (root.groupCollapsedStates[groupSection.groupId] ?? false) ? "expand_more" : "expand_less"
+ size: Theme.iconSize
+ color: Theme.surfaceText
+ anchors.verticalCenter: parent.verticalCenter
+ }
+
+ DankIcon {
+ name: "folder"
+ size: Theme.iconSize
+ color: Theme.primary
+ anchors.verticalCenter: parent.verticalCenter
+ }
+
+ StyledText {
+ text: groupSection.modelData.name
+ font.pixelSize: Theme.fontSizeMedium
+ font.weight: Font.Medium
+ color: Theme.surfaceText
+ anchors.verticalCenter: parent.verticalCenter
+ }
+
+ StyledText {
+ text: "(" + groupSection.groupInstances.length + ")"
+ font.pixelSize: Theme.fontSizeSmall
+ color: Theme.surfaceVariantText
+ anchors.verticalCenter: parent.verticalCenter
+ }
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ cursorShape: Qt.PointingHandCursor
+ onClicked: {
+ var states = Object.assign({}, root.groupCollapsedStates);
+ states[groupSection.groupId] = !(states[groupSection.groupId] ?? false);
+ root.groupCollapsedStates = states;
+ }
+ }
+ }
+
+ Column {
+ width: parent.width
+ spacing: Theme.spacingM
+ visible: !(root.groupCollapsedStates[groupSection.groupId] ?? false)
+ leftPadding: Theme.spacingM
+
+ Repeater {
+ model: ScriptModel {
+ objectProp: "id"
+ values: groupSection.groupInstances
+ }
+
+ Item {
+ id: groupDelegateItem
+ required property var modelData
+ required property int index
+
+ property bool held: groupDragArea.pressed
+ property real originalY: y
+
+ readonly property string instanceIdRef: modelData.id
+ readonly property var liveInstanceData: {
+ const instances = root.allInstances;
+ return instances.find(inst => inst.id === instanceIdRef) ?? modelData;
+ }
+
+ width: groupSection.width - Theme.spacingM
+ height: groupCard.height
+ z: held ? 2 : 1
+
+ DesktopWidgetInstanceCard {
+ id: groupCard
+ width: parent.width
+ headerLeftPadding: 20
+ instanceData: groupDelegateItem.liveInstanceData
+ isExpanded: root.expandedStates[groupDelegateItem.instanceIdRef] ?? false
+
+ onExpandedChanged: {
+ if (expanded === (root.expandedStates[groupDelegateItem.instanceIdRef] ?? false))
+ return;
+ var states = Object.assign({}, root.expandedStates);
+ states[groupDelegateItem.instanceIdRef] = expanded;
+ root.expandedStates = states;
+ }
+
+ onDuplicateRequested: SettingsData.duplicateDesktopWidgetInstance(groupDelegateItem.instanceIdRef)
+
+ onDeleteRequested: {
+ SettingsData.removeDesktopWidgetInstance(groupDelegateItem.instanceIdRef);
+ ToastService.showInfo(I18n.tr("Widget removed"));
+ }
+ }
+
+ MouseArea {
+ id: groupDragArea
+ anchors.left: parent.left
+ anchors.top: parent.top
+ width: 40
+ height: 50
+ hoverEnabled: true
+ cursorShape: Qt.SizeVerCursor
+ drag.target: groupDelegateItem.held ? groupDelegateItem : undefined
+ drag.axis: Drag.YAxis
+ preventStealing: true
+
+ onPressed: {
+ groupDelegateItem.z = 2;
+ groupDelegateItem.originalY = groupDelegateItem.y;
+ }
+ onReleased: {
+ groupDelegateItem.z = 1;
+ if (!drag.active) {
+ groupDelegateItem.y = groupDelegateItem.originalY;
+ return;
+ }
+ const spacing = Theme.spacingM;
+ const itemH = groupDelegateItem.height + spacing;
+ var newIndex = Math.round(groupDelegateItem.y / itemH);
+ newIndex = Math.max(0, Math.min(newIndex, groupSection.groupInstances.length - 1));
+ if (newIndex !== groupDelegateItem.index)
+ SettingsData.reorderDesktopWidgetInstanceInGroup(groupDelegateItem.instanceIdRef, groupSection.groupId, newIndex);
+ groupDelegateItem.y = groupDelegateItem.originalY;
+ }
+ }
+
+ DankIcon {
+ x: Theme.spacingL - 2
+ y: Theme.spacingL + (Theme.iconSize / 2) - (size / 2)
+ name: "drag_indicator"
+ size: 18
+ color: Theme.outline
+ opacity: groupDragArea.containsMouse || groupDragArea.pressed ? 1 : 0.5
+ }
+
+ Behavior on y {
+ enabled: !groupDragArea.pressed && !groupDragArea.drag.active
+ NumberAnimation {
+ duration: Theme.shortDuration
+ easing.type: Theme.standardEasing
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ Column {
+ id: ungroupedSection
+ width: parent.width
+ spacing: Theme.spacingM
+ visible: ungroupedInstances.length > 0
+
+ readonly property var ungroupedInstances: root.allInstances.filter(inst => {
+ if (!inst.group)
+ return true;
+ return !root.allGroups.some(g => g.id === inst.group);
+ })
+
+ Rectangle {
+ width: parent.width
+ height: 44
+ radius: Theme.cornerRadius
+ color: Theme.surfaceContainer
+ visible: root.allGroups.length > 0
+
+ Row {
+ anchors.fill: parent
+ anchors.leftMargin: Theme.spacingM
+ anchors.rightMargin: Theme.spacingM
+ spacing: Theme.spacingS
+
+ DankIcon {
+ name: (root.groupCollapsedStates["_ungrouped"] ?? false) ? "expand_more" : "expand_less"
+ size: Theme.iconSize
+ color: Theme.surfaceText
+ anchors.verticalCenter: parent.verticalCenter
+ }
+
+ DankIcon {
+ name: "widgets"
+ size: Theme.iconSize
+ color: Theme.primary
+ anchors.verticalCenter: parent.verticalCenter
+ }
+
+ StyledText {
+ text: I18n.tr("Ungrouped")
+ font.pixelSize: Theme.fontSizeMedium
+ font.weight: Font.Medium
+ color: Theme.surfaceText
+ anchors.verticalCenter: parent.verticalCenter
+ }
+
+ StyledText {
+ text: "(" + ungroupedSection.ungroupedInstances.length + ")"
+ font.pixelSize: Theme.fontSizeSmall
+ color: Theme.surfaceVariantText
+ anchors.verticalCenter: parent.verticalCenter
+ }
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ cursorShape: Qt.PointingHandCursor
+ onClicked: {
+ var states = Object.assign({}, root.groupCollapsedStates);
+ states["_ungrouped"] = !(states["_ungrouped"] ?? false);
+ root.groupCollapsedStates = states;
+ }
+ }
+ }
+
+ Column {
+ width: parent.width
+ spacing: Theme.spacingM
+ visible: !(root.groupCollapsedStates["_ungrouped"] ?? false)
+ leftPadding: root.allGroups.length > 0 ? Theme.spacingM : 0
+
+ Repeater {
+ model: ScriptModel {
+ objectProp: "id"
+ values: ungroupedSection.ungroupedInstances
+ }
+
+ Item {
+ id: ungroupedDelegateItem
+ required property var modelData
+ required property int index
+
+ property bool held: ungroupedDragArea.pressed
+ property real originalY: y
+
+ readonly property string instanceIdRef: modelData.id
+ readonly property var liveInstanceData: {
+ const instances = root.allInstances;
+ return instances.find(inst => inst.id === instanceIdRef) ?? modelData;
+ }
+
+ width: ungroupedSection.width - (root.allGroups.length > 0 ? Theme.spacingM : 0)
+ height: ungroupedCard.height
+ z: held ? 2 : 1
+
+ DesktopWidgetInstanceCard {
+ id: ungroupedCard
+ width: parent.width
+ headerLeftPadding: 20
+ instanceData: ungroupedDelegateItem.liveInstanceData
+ isExpanded: root.expandedStates[ungroupedDelegateItem.instanceIdRef] ?? false
+
+ onExpandedChanged: {
+ if (expanded === (root.expandedStates[ungroupedDelegateItem.instanceIdRef] ?? false))
+ return;
+ var states = Object.assign({}, root.expandedStates);
+ states[ungroupedDelegateItem.instanceIdRef] = expanded;
+ root.expandedStates = states;
+ }
+
+ onDuplicateRequested: SettingsData.duplicateDesktopWidgetInstance(ungroupedDelegateItem.instanceIdRef)
+
+ onDeleteRequested: {
+ SettingsData.removeDesktopWidgetInstance(ungroupedDelegateItem.instanceIdRef);
+ ToastService.showInfo(I18n.tr("Widget removed"));
+ }
+ }
+
+ MouseArea {
+ id: ungroupedDragArea
+ anchors.left: parent.left
+ anchors.top: parent.top
+ width: 40
+ height: 50
+ hoverEnabled: true
+ cursorShape: Qt.SizeVerCursor
+ drag.target: ungroupedDelegateItem.held ? ungroupedDelegateItem : undefined
+ drag.axis: Drag.YAxis
+ preventStealing: true
+
+ onPressed: {
+ ungroupedDelegateItem.z = 2;
+ ungroupedDelegateItem.originalY = ungroupedDelegateItem.y;
+ }
+ onReleased: {
+ ungroupedDelegateItem.z = 1;
+ if (!drag.active) {
+ ungroupedDelegateItem.y = ungroupedDelegateItem.originalY;
+ return;
+ }
+ const spacing = Theme.spacingM;
+ const itemH = ungroupedDelegateItem.height + spacing;
+ var newIndex = Math.round(ungroupedDelegateItem.y / itemH);
+ newIndex = Math.max(0, Math.min(newIndex, ungroupedSection.ungroupedInstances.length - 1));
+ if (newIndex !== ungroupedDelegateItem.index)
+ SettingsData.reorderDesktopWidgetInstanceInGroup(ungroupedDelegateItem.instanceIdRef, null, newIndex);
+ ungroupedDelegateItem.y = ungroupedDelegateItem.originalY;
+ }
+ }
+
+ DankIcon {
+ x: Theme.spacingL - 2
+ y: Theme.spacingL + (Theme.iconSize / 2) - (size / 2)
+ name: "drag_indicator"
+ size: 18
+ color: Theme.outline
+ opacity: ungroupedDragArea.containsMouse || ungroupedDragArea.pressed ? 1 : 0.5
+ }
+
+ Behavior on y {
+ enabled: !ungroupedDragArea.pressed && !ungroupedDragArea.drag.active
+ NumberAnimation {
+ duration: Theme.shortDuration
+ easing.type: Theme.standardEasing
+ }
+ }
+ }
+ }
+ }
+ }
+
+ StyledText {
+ visible: root.allInstances.length === 0
+ text: I18n.tr("No widgets added. Click \"Add Widget\" to get started.")
+ font.pixelSize: Theme.fontSizeMedium
+ color: Theme.surfaceVariantText
+ width: parent.width
+ wrapMode: Text.WordWrap
+ horizontalAlignment: Text.AlignLeft
+ }
+
+ SettingsCard {
+ width: parent.width
+ iconName: "info"
+ title: I18n.tr("Help")
+
+ Column {
+ width: parent.width - Theme.spacingM * 2
+ x: Theme.spacingM
+ spacing: Theme.spacingM
+
+ Row {
+ width: parent.width
+ spacing: Theme.spacingM
+
+ Rectangle {
+ width: 40
+ height: 40
+ radius: 20
+ color: Theme.primarySelected
+
+ DankIcon {
+ anchors.centerIn: parent
+ name: "drag_pan"
+ size: Theme.iconSize
+ color: Theme.primary
+ }
+ }
+
+ Column {
+ spacing: 2
+ anchors.verticalCenter: parent.verticalCenter
+ width: parent.width - 40 - Theme.spacingM
+
+ StyledText {
+ text: I18n.tr("Move Widget")
+ font.pixelSize: Theme.fontSizeMedium
+ font.weight: Font.Medium
+ color: Theme.surfaceText
+ width: parent.width
+ horizontalAlignment: Text.AlignLeft
+ }
+
+ StyledText {
+ text: I18n.tr("Right-click and drag anywhere on the widget")
+ font.pixelSize: Theme.fontSizeSmall
+ color: Theme.surfaceVariantText
+ width: parent.width
+ horizontalAlignment: Text.AlignLeft
+ }
+ }
+ }
+
+ Row {
+ width: parent.width
+ spacing: Theme.spacingM
+
+ Rectangle {
+ width: 40
+ height: 40
+ radius: 20
+ color: Theme.primarySelected
+
+ DankIcon {
+ anchors.centerIn: parent
+ name: "open_in_full"
+ size: Theme.iconSize
+ color: Theme.primary
+ }
+ }
+
+ Column {
+ spacing: 2
+ anchors.verticalCenter: parent.verticalCenter
+ width: parent.width - 40 - Theme.spacingM
+
+ StyledText {
+ text: I18n.tr("Resize Widget")
+ font.pixelSize: Theme.fontSizeMedium
+ font.weight: Font.Medium
+ color: Theme.surfaceText
+ width: parent.width
+ horizontalAlignment: Text.AlignLeft
+ }
+
+ StyledText {
+ text: I18n.tr("Right-click and drag the bottom-right corner")
+ font.pixelSize: Theme.fontSizeSmall
+ color: Theme.surfaceVariantText
+ width: parent.width
+ horizontalAlignment: Text.AlignLeft
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}