1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-01-24 21:42:51 -05:00

desktop widgets: easier copy/delete

This commit is contained in:
bbedward
2025-12-27 14:13:06 -05:00
parent fbe362cd20
commit 7aff1182c8
4 changed files with 167 additions and 42 deletions

View File

@@ -614,6 +614,26 @@ Singleton {
saveSettings(); saveSettings();
} }
function duplicateDesktopWidgetInstance(instanceId) {
const source = getDesktopWidgetInstance(instanceId);
if (!source)
return null;
const newId = "dw_" + Date.now() + "_" + Math.random().toString(36).substr(2, 9);
const instance = {
id: newId,
widgetType: source.widgetType,
name: source.name + " (Copy)",
enabled: source.enabled,
config: JSON.parse(JSON.stringify(source.config || {})),
positions: {}
};
const instances = JSON.parse(JSON.stringify(desktopWidgetInstances || []));
instances.push(instance);
desktopWidgetInstances = instances;
saveSettings();
return instance;
}
function getDesktopWidgetInstance(instanceId) { function getDesktopWidgetInstance(instanceId) {
return (desktopWidgetInstances || []).find(inst => inst.id === instanceId) || null; return (desktopWidgetInstances || []).find(inst => inst.id === instanceId) || null;
} }

View File

@@ -1,6 +1,7 @@
pragma ComponentBehavior: Bound pragma ComponentBehavior: Bound
import QtQuick import QtQuick
import QtQuick.Controls
import Quickshell import Quickshell
import qs.Common import qs.Common
import qs.Services import qs.Services
@@ -13,6 +14,7 @@ SettingsCard {
required property var instanceData required property var instanceData
property bool isExpanded: false property bool isExpanded: false
property bool confirmingDelete: false
readonly property string instanceId: instanceData?.id ?? "" readonly property string instanceId: instanceData?.id ?? ""
readonly property string widgetType: instanceData?.widgetType ?? "" readonly property string widgetType: instanceData?.widgetType ?? ""
@@ -20,6 +22,7 @@ SettingsCard {
readonly property string widgetName: instanceData?.name ?? widgetDef?.name ?? widgetType readonly property string widgetName: instanceData?.name ?? widgetDef?.name ?? widgetType
signal deleteRequested signal deleteRequested
signal duplicateRequested
property Component clockSettingsComponent: Component { property Component clockSettingsComponent: Component {
DWS.ClockSettings {} DWS.ClockSettings {}
@@ -46,48 +49,125 @@ SettingsCard {
onExpandedChanged: isExpanded = expanded onExpandedChanged: isExpanded = expanded
Row { headerActions: [
width: parent.width DankToggle {
spacing: Theme.spacingS checked: instanceData?.enabled ?? true
onToggled: isChecked => {
Item { if (!root.instanceId)
width: parent.width - toggleRow.width - deleteBtn.width - Theme.spacingS * 2 return;
height: 1 SettingsData.updateDesktopWidgetInstance(root.instanceId, {
} enabled: isChecked
});
Row {
id: toggleRow
spacing: Theme.spacingS
StyledText {
text: (instanceData?.enabled ?? true) ? I18n.tr("Enabled") : I18n.tr("Disabled")
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
anchors.verticalCenter: parent.verticalCenter
} }
},
DankActionButton {
id: menuButton
iconName: "more_vert"
onClicked: actionsMenu.open()
DankToggle { Popup {
checked: instanceData?.enabled ?? true id: actionsMenu
onToggled: isChecked => { x: -width + parent.width
if (!root.instanceId) y: parent.height + Theme.spacingXS
return; width: 160
SettingsData.updateDesktopWidgetInstance(root.instanceId, { padding: Theme.spacingXS
enabled: isChecked modal: true
}); focus: true
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
onClosed: root.confirmingDelete = false
background: Rectangle {
color: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
radius: Theme.cornerRadius
border.color: Theme.outlineLight
border.width: 1
}
contentItem: Column {
spacing: 2
Rectangle {
width: parent.width
height: Theme.iconSizeLarge
radius: Theme.cornerRadius
color: duplicateArea.containsMouse ? Theme.primaryHover : "transparent"
Row {
anchors.left: parent.left
anchors.leftMargin: Theme.spacingS
anchors.verticalCenter: parent.verticalCenter
spacing: Theme.spacingS
DankIcon {
name: "content_copy"
size: Theme.iconSizeSmall
color: Theme.surfaceText
}
StyledText {
text: I18n.tr("Duplicate")
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
}
}
MouseArea {
id: duplicateArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
actionsMenu.close();
root.duplicateRequested();
}
}
}
Rectangle {
width: parent.width
height: Theme.iconSizeLarge
radius: Theme.cornerRadius
color: deleteArea.containsMouse ? Theme.errorHover : "transparent"
Row {
anchors.left: parent.left
anchors.leftMargin: Theme.spacingS
anchors.verticalCenter: parent.verticalCenter
spacing: Theme.spacingS
DankIcon {
name: root.confirmingDelete ? "warning" : "delete"
size: Theme.iconSizeSmall
color: Theme.error
}
StyledText {
text: root.confirmingDelete ? I18n.tr("Confirm Delete") : I18n.tr("Delete")
font.pixelSize: Theme.fontSizeSmall
color: Theme.error
}
}
MouseArea {
id: deleteArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
if (root.confirmingDelete) {
actionsMenu.close();
root.deleteRequested();
return;
}
root.confirmingDelete = true;
}
}
}
} }
} }
} }
]
DankButton {
id: deleteBtn
iconName: "delete"
backgroundColor: "transparent"
textColor: Theme.error
buttonHeight: 32
horizontalPadding: 4
onClicked: root.deleteRequested()
}
}
Column { Column {
width: parent.width width: parent.width
@@ -102,8 +182,6 @@ SettingsCard {
} }
} }
SettingsDivider {}
Item { Item {
width: parent.width width: parent.width
height: nameRow.height + Theme.spacingM * 2 height: nameRow.height + Theme.spacingM * 2

View File

@@ -112,6 +112,8 @@ Item {
root.expandedStates = states; root.expandedStates = states;
} }
onDuplicateRequested: SettingsData.duplicateDesktopWidgetInstance(instanceIdRef)
onDeleteRequested: { onDeleteRequested: {
SettingsData.removeDesktopWidgetInstance(instanceIdRef); SettingsData.removeDesktopWidgetInstance(instanceIdRef);
ToastService.showInfo(I18n.tr("Widget removed")); ToastService.showInfo(I18n.tr("Widget removed"));

View File

@@ -21,6 +21,7 @@ StyledRect {
property bool expanded: true property bool expanded: true
default property alias content: contentColumn.children default property alias content: contentColumn.children
property alias headerActions: headerActionsRow.children
readonly property bool isHighlighted: settingKey !== "" && SettingsSearchService.highlightSection === settingKey readonly property bool isHighlighted: settingKey !== "" && SettingsSearchService.highlightSection === settingKey
@@ -137,7 +138,16 @@ StyledRect {
} }
} }
Row {
id: headerActionsRow
anchors.right: caretIcon.left
anchors.rightMargin: root.collapsible ? Theme.spacingS : 0
anchors.verticalCenter: parent.verticalCenter
spacing: Theme.spacingXS
}
DankIcon { DankIcon {
id: caretIcon
anchors.right: parent.right anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
name: root.expanded ? "expand_less" : "expand_more" name: root.expanded ? "expand_less" : "expand_more"
@@ -147,12 +157,27 @@ StyledRect {
} }
MouseArea { MouseArea {
anchors.fill: parent anchors.left: parent.left
anchors.right: headerActionsRow.left
anchors.top: parent.top
anchors.bottom: parent.bottom
enabled: root.collapsible
cursorShape: root.collapsible ? Qt.PointingHandCursor : Qt.ArrowCursor
onClicked: {
root.userToggledCollapse = true;
root.expanded = !root.expanded;
}
}
MouseArea {
anchors.left: caretIcon.left
anchors.right: parent.right
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.leftMargin: -Theme.spacingS
enabled: root.collapsible enabled: root.collapsible
cursorShape: root.collapsible ? Qt.PointingHandCursor : Qt.ArrowCursor cursorShape: root.collapsible ? Qt.PointingHandCursor : Qt.ArrowCursor
onClicked: { onClicked: {
if (!root.collapsible)
return;
root.userToggledCollapse = true; root.userToggledCollapse = true;
root.expanded = !root.expanded; root.expanded = !root.expanded;
} }