diff options
Diffstat (limited to 'raveos-hyprland-theme/theme-data/dms/Modules/Settings/Widgets')
12 files changed, 1613 insertions, 0 deletions
diff --git a/raveos-hyprland-theme/theme-data/dms/Modules/Settings/Widgets/DeviceAliasRow.qml b/raveos-hyprland-theme/theme-data/dms/Modules/Settings/Widgets/DeviceAliasRow.qml new file mode 100644 index 0000000..bec5ff1 --- /dev/null +++ b/raveos-hyprland-theme/theme-data/dms/Modules/Settings/Widgets/DeviceAliasRow.qml @@ -0,0 +1,180 @@ +pragma ComponentBehavior: Bound + +import QtQuick +import qs.Common +import qs.Services +import qs.Widgets + +Rectangle { + id: root + + LayoutMirroring.enabled: I18n.isRtl + LayoutMirroring.childrenInherit: true + + required property var deviceNode + property string deviceType: "output" + + property bool showHideButton: false + property bool isHidden: false + + signal editRequested(var deviceNode) + signal resetRequested(var deviceNode) + signal hideRequested(var deviceNode) + + width: parent?.width ?? 0 + height: deviceRowContent.height + Theme.spacingM * 2 + radius: Theme.cornerRadius + color: deviceMouseArea.containsMouse ? Theme.surfaceHover : "transparent" + + readonly property bool hasCustomAlias: AudioService.hasDeviceAlias(deviceNode?.name ?? "") + readonly property string displayedName: AudioService.displayName(deviceNode) + + Row { + id: deviceRowContent + anchors.left: parent.left + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + anchors.leftMargin: Theme.spacingM + anchors.rightMargin: Theme.spacingM + spacing: Theme.spacingM + + DankIcon { + name: root.deviceType === "input" ? "mic" : "speaker" + size: Theme.iconSize + color: Theme.surfaceText + anchors.verticalCenter: parent.verticalCenter + } + + Column { + anchors.verticalCenter: parent.verticalCenter + width: parent.width - Theme.iconSize - Theme.spacingM * 3 - buttonsRow.width + spacing: 2 + + StyledText { + text: root.displayedName + font.pixelSize: Theme.fontSizeMedium + font.weight: Font.Medium + color: Theme.surfaceText + width: parent.width + elide: Text.ElideRight + horizontalAlignment: Text.AlignLeft + } + + Column { + width: parent.width + spacing: 2 + + Row { + width: parent.width + spacing: Theme.spacingS + + StyledText { + text: root.deviceNode?.name ?? "" + font.pixelSize: Theme.fontSizeSmall + color: Theme.surfaceVariantText + width: parent.width - (customAliasLabel.visible ? customAliasLabel.width + Theme.spacingS : 0) + elide: Text.ElideRight + anchors.verticalCenter: parent.verticalCenter + horizontalAlignment: Text.AlignLeft + } + + Rectangle { + id: customAliasLabel + visible: root.hasCustomAlias + height: customAliasText.implicitHeight + 4 + width: customAliasText.implicitWidth + Theme.spacingS * 2 + radius: 3 + color: Theme.withAlpha(Theme.primary, 0.15) + anchors.verticalCenter: parent.verticalCenter + + StyledText { + id: customAliasText + text: I18n.tr("Custom") + font.pixelSize: Theme.fontSizeSmall - 1 + color: Theme.primary + font.weight: Font.Medium + anchors.centerIn: parent + } + } + } + + StyledText { + visible: root.hasCustomAlias + text: I18n.tr("Original: %1").arg(AudioService.originalName(root.deviceNode)) + font.pixelSize: Theme.fontSizeSmall - 1 + color: Theme.surfaceVariantText + width: parent.width + elide: Text.ElideRight + opacity: 0.6 + horizontalAlignment: Text.AlignLeft + } + } + } + + Row { + id: buttonsRow + anchors.verticalCenter: parent.verticalCenter + spacing: Theme.spacingS + + DankActionButton { + id: resetButton + visible: root.hasCustomAlias + buttonSize: 36 + iconName: "restart_alt" + iconSize: 20 + backgroundColor: Theme.surfaceContainerHigh + iconColor: Theme.surfaceVariantText + tooltipText: I18n.tr("Reset to default name") + anchors.verticalCenter: parent.verticalCenter + onClicked: { + root.resetRequested(root.deviceNode); + } + } + + DankActionButton { + id: hideButton + visible: root.showHideButton + buttonSize: 36 + iconName: root.isHidden ? "visibility" : "visibility_off" + iconSize: 20 + backgroundColor: Theme.surfaceContainerHigh + iconColor: root.isHidden ? Theme.primary : Theme.surfaceVariantText + tooltipText: root.isHidden ? I18n.tr("Show device") : I18n.tr("Hide device") + anchors.verticalCenter: parent.verticalCenter + onClicked: { + root.hideRequested(root.deviceNode); + } + } + + DankActionButton { + id: editButton + buttonSize: 36 + iconName: "edit" + iconSize: 20 + backgroundColor: Theme.buttonBg + iconColor: Theme.buttonText + tooltipText: I18n.tr("Set custom name") + anchors.verticalCenter: parent.verticalCenter + visible: !root.isHidden + onClicked: { + root.editRequested(root.deviceNode); + } + } + } + } + + MouseArea { + id: deviceMouseArea + anchors.fill: parent + hoverEnabled: true + propagateComposedEvents: true + z: -1 + } + + Behavior on color { + ColorAnimation { + duration: Theme.shortDuration + easing.type: Theme.standardEasing + } + } +} diff --git a/raveos-hyprland-theme/theme-data/dms/Modules/Settings/Widgets/SettingsButtonGroupRow.qml b/raveos-hyprland-theme/theme-data/dms/Modules/Settings/Widgets/SettingsButtonGroupRow.qml new file mode 100644 index 0000000..5e49936 --- /dev/null +++ b/raveos-hyprland-theme/theme-data/dms/Modules/Settings/Widgets/SettingsButtonGroupRow.qml @@ -0,0 +1,117 @@ +pragma ComponentBehavior: Bound + +import QtQuick +import qs.Common +import qs.Services +import qs.Widgets + +Item { + id: root + + LayoutMirroring.enabled: I18n.isRtl + LayoutMirroring.childrenInherit: true + + property string tab: "" + property var tags: [] + property string settingKey: "" + + property string text: "" + property string description: "" + + readonly property bool isHighlighted: settingKey !== "" && SettingsSearchService.highlightSection === settingKey + + function findParentFlickable() { + let p = root.parent; + while (p) { + if (p.hasOwnProperty("contentY") && p.hasOwnProperty("contentItem")) + return p; + p = p.parent; + } + return null; + } + + Component.onCompleted: { + if (!settingKey) + return; + let flickable = findParentFlickable(); + if (flickable) + SettingsSearchService.registerCard(settingKey, root, flickable); + } + + Component.onDestruction: { + if (settingKey) + SettingsSearchService.unregisterCard(settingKey); + } + + Rectangle { + anchors.fill: parent + radius: Theme.cornerRadius + color: Theme.withAlpha(Theme.primary, root.isHighlighted ? 0.2 : 0) + visible: root.isHighlighted + + Behavior on color { + ColorAnimation { + duration: Theme.shortDuration + easing.type: Theme.standardEasing + } + } + } + + property alias model: buttonGroup.model + property alias currentIndex: buttonGroup.currentIndex + property alias selectionMode: buttonGroup.selectionMode + property alias buttonHeight: buttonGroup.buttonHeight + property alias minButtonWidth: buttonGroup.minButtonWidth + property alias buttonPadding: buttonGroup.buttonPadding + property alias checkIconSize: buttonGroup.checkIconSize + property alias textSize: buttonGroup.textSize + property alias spacing: buttonGroup.spacing + property alias checkEnabled: buttonGroup.checkEnabled + + signal selectionChanged(int index, bool selected) + + width: parent?.width ?? 0 + height: 60 + + Row { + id: contentRow + width: parent.width - Theme.spacingM * 2 + x: Theme.spacingM + anchors.verticalCenter: parent.verticalCenter + spacing: Theme.spacingM + + Column { + width: parent.width - buttonGroup.width - Theme.spacingM + anchors.verticalCenter: parent.verticalCenter + spacing: Theme.spacingXS + + StyledText { + text: root.text + font.pixelSize: Theme.fontSizeMedium + font.weight: Font.Medium + color: Theme.surfaceText + elide: Text.ElideRight + width: parent.width + visible: root.text !== "" + horizontalAlignment: Text.AlignLeft + } + + StyledText { + text: root.description + font.pixelSize: Theme.fontSizeSmall + color: Theme.surfaceVariantText + wrapMode: Text.WordWrap + width: parent.width + visible: root.description !== "" + horizontalAlignment: Text.AlignLeft + } + } + + DankButtonGroup { + id: buttonGroup + anchors.verticalCenter: parent.verticalCenter + selectionMode: "single" + onSelectionChanged: (index, selected) => root.selectionChanged(index, selected) + } + } +} diff --git a/raveos-hyprland-theme/theme-data/dms/Modules/Settings/Widgets/SettingsCard.qml b/raveos-hyprland-theme/theme-data/dms/Modules/Settings/Widgets/SettingsCard.qml new file mode 100644 index 0000000..65642a0 --- /dev/null +++ b/raveos-hyprland-theme/theme-data/dms/Modules/Settings/Widgets/SettingsCard.qml @@ -0,0 +1,199 @@ +pragma ComponentBehavior: Bound + +import QtQuick +import qs.Common +import qs.Services +import qs.Widgets + +StyledRect { + id: root + + LayoutMirroring.enabled: I18n.isRtl + LayoutMirroring.childrenInherit: true + + property string tab: "" + property var tags: [] + property string settingKey: "" + + property string title: "" + property string iconName: "" + property bool collapsible: false + property bool expanded: true + property real headerLeftPadding: 0 + + default property alias content: contentColumn.children + property alias headerActions: headerActionsRow.children + + readonly property bool isHighlighted: settingKey !== "" && SettingsSearchService.highlightSection === settingKey + + width: parent?.width ?? 0 + height: { + var hasHeader = root.title !== "" || root.iconName !== ""; + if (collapsed) + return headerRow.height + Theme.spacingL * 2; + var h = Theme.spacingL * 2 + contentColumn.height; + if (hasHeader) + h += headerRow.height + Theme.spacingM; + return h; + } + radius: Theme.cornerRadius + color: Theme.surfaceContainerHigh + + readonly property bool collapsed: collapsible && !expanded + readonly property bool hasHeader: root.title !== "" || root.iconName !== "" + property bool userToggledCollapse: false + + function findParentFlickable() { + let p = root.parent; + while (p) { + if (p.hasOwnProperty("contentY") && p.hasOwnProperty("contentItem")) { + return p; + } + p = p.parent; + } + return null; + } + + Component.onCompleted: { + if (settingKey) { + let flickable = findParentFlickable(); + if (flickable) { + SettingsSearchService.registerCard(settingKey, root, flickable); + } + } + } + + Component.onDestruction: { + if (settingKey) { + SettingsSearchService.unregisterCard(settingKey); + } + } + + Behavior on height { + enabled: root.userToggledCollapse + NumberAnimation { + duration: Theme.shortDuration + easing.type: Theme.standardEasing + onRunningChanged: { + if (!running) + root.userToggledCollapse = false; + } + } + } + + Rectangle { + id: highlightBorder + anchors.fill: parent + anchors.margins: -2 + radius: root.radius + 2 + color: "transparent" + border.width: 2 + border.color: Theme.primary + opacity: root.isHighlighted ? 1 : 0 + visible: opacity > 0 + z: 100 + + Behavior on opacity { + NumberAnimation { + duration: Theme.shortDuration + easing.type: Theme.standardEasing + } + } + } + + Column { + id: mainColumn + anchors.fill: parent + anchors.margins: Theme.spacingL + spacing: root.hasHeader ? Theme.spacingM : 0 + clip: true + + Item { + id: headerRow + width: parent.width + height: root.hasHeader ? Math.max(headerIcon.height, headerText.height, headerActionsRow.height) : 0 + visible: root.hasHeader + + Row { + anchors.left: parent.left + anchors.leftMargin: root.headerLeftPadding + anchors.verticalCenter: parent.verticalCenter + spacing: Theme.spacingM + + DankIcon { + id: headerIcon + name: root.iconName + size: Theme.iconSize + color: Theme.primary + anchors.verticalCenter: parent.verticalCenter + visible: root.iconName !== "" + } + + StyledText { + id: headerText + text: root.title + font.pixelSize: Theme.fontSizeLarge + font.weight: Font.Medium + color: Theme.surfaceText + anchors.verticalCenter: parent.verticalCenter + visible: root.title !== "" + width: implicitWidth + horizontalAlignment: Text.AlignLeft + } + } + + Row { + id: headerActionsRow + anchors.right: root.collapsible ? caretIcon.left : parent.right + anchors.rightMargin: root.collapsible ? Theme.spacingS : 0 + anchors.verticalCenter: parent.verticalCenter + spacing: Theme.spacingXS + } + + DankIcon { + id: caretIcon + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + name: root.expanded ? "expand_less" : "expand_more" + size: Theme.iconSize - 2 + color: Theme.surfaceVariantText + visible: root.collapsible + } + + MouseArea { + 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 { + visible: root.collapsible + anchors.left: caretIcon.left + anchors.right: parent.right + anchors.top: parent.top + anchors.bottom: parent.bottom + anchors.leftMargin: -Theme.spacingS + enabled: root.collapsible + cursorShape: root.collapsible ? Qt.PointingHandCursor : Qt.ArrowCursor + onClicked: { + root.userToggledCollapse = true; + root.expanded = !root.expanded; + } + } + } + + Column { + id: contentColumn + width: parent.width + spacing: Theme.spacingM + visible: !root.collapsed + } + } +} diff --git a/raveos-hyprland-theme/theme-data/dms/Modules/Settings/Widgets/SettingsColorPicker.qml b/raveos-hyprland-theme/theme-data/dms/Modules/Settings/Widgets/SettingsColorPicker.qml new file mode 100644 index 0000000..68011fa --- /dev/null +++ b/raveos-hyprland-theme/theme-data/dms/Modules/Settings/Widgets/SettingsColorPicker.qml @@ -0,0 +1,119 @@ +pragma ComponentBehavior: Bound + +import QtQuick +import qs.Common +import qs.Services +import qs.Widgets + +Item { + id: root + + property string colorMode: "primary" + property color customColor: "#ffffff" + property string pickerTitle: I18n.tr("Choose Color") + + signal colorModeSelected(string mode) + signal customColorSelected(color selectedColor) + + width: parent?.width ?? 0 + height: colorColumn.height + Theme.spacingM * 2 + + Column { + id: colorColumn + width: parent.width - Theme.spacingM * 2 + x: Theme.spacingM + anchors.verticalCenter: parent.verticalCenter + spacing: Theme.spacingM + + StyledText { + text: I18n.tr("Color") + font.pixelSize: Theme.fontSizeMedium + color: Theme.surfaceText + } + + Row { + width: parent.width + spacing: Theme.spacingS + + Repeater { + model: [ + { + id: "primary", + label: I18n.tr("Primary"), + color: Theme.primary + }, + { + id: "secondary", + label: I18n.tr("Secondary"), + color: Theme.secondary + }, + { + id: "custom", + label: I18n.tr("Custom"), + color: root.customColor + } + ] + + Rectangle { + required property var modelData + required property int index + + width: (parent.width - Theme.spacingS * 2) / 3 + height: 60 + radius: Theme.cornerRadius + color: root.colorMode === modelData.id ? Theme.primarySelected : Theme.surfaceHover + border.color: root.colorMode === modelData.id ? Theme.primary : "transparent" + border.width: 2 + + Column { + anchors.centerIn: parent + spacing: Theme.spacingXS + + Rectangle { + width: 24 + height: 24 + radius: 12 + color: modelData.color + border.color: Theme.outline + border.width: 1 + anchors.horizontalCenter: parent.horizontalCenter + + DankIcon { + visible: modelData.id === "custom" + anchors.centerIn: parent + name: "colorize" + size: 14 + color: Theme.background + } + } + + StyledText { + text: modelData.label + font.pixelSize: Theme.fontSizeSmall + color: Theme.surfaceText + anchors.horizontalCenter: parent.horizontalCenter + } + } + + MouseArea { + anchors.fill: parent + cursorShape: Qt.PointingHandCursor + onClicked: { + if (modelData.id !== "custom") { + root.colorModeSelected(modelData.id); + return; + } + PopoutService.colorPickerModal.selectedColor = root.customColor; + PopoutService.colorPickerModal.pickerTitle = root.pickerTitle; + PopoutService.colorPickerModal.onColorSelectedCallback = function (selectedColor) { + root.customColorSelected(selectedColor); + root.colorModeSelected("custom"); + }; + PopoutService.colorPickerModal.show(); + } + } + } + } + } + } +} diff --git a/raveos-hyprland-theme/theme-data/dms/Modules/Settings/Widgets/SettingsDisplayPicker.qml b/raveos-hyprland-theme/theme-data/dms/Modules/Settings/Widgets/SettingsDisplayPicker.qml new file mode 100644 index 0000000..ba453fd --- /dev/null +++ b/raveos-hyprland-theme/theme-data/dms/Modules/Settings/Widgets/SettingsDisplayPicker.qml @@ -0,0 +1,103 @@ +pragma ComponentBehavior: Bound + +import QtQuick +import Quickshell +import qs.Common +import qs.Widgets + +Item { + id: root + + property var displayPreferences: [] + + signal preferencesChanged(var preferences) + + property bool localAllDisplays: true + + onDisplayPreferencesChanged: { + if (!Array.isArray(displayPreferences) || displayPreferences.length === 0) { + localAllDisplays = true; + return; + } + localAllDisplays = displayPreferences.includes("all"); + } + + width: parent?.width ?? 0 + height: displayColumn.height + Theme.spacingM * 2 + + Column { + id: displayColumn + width: parent.width - Theme.spacingM * 2 + x: Theme.spacingM + anchors.verticalCenter: parent.verticalCenter + spacing: Theme.spacingM + + StyledText { + text: I18n.tr("Displays") + font.pixelSize: Theme.fontSizeMedium + color: Theme.surfaceText + } + + DankToggle { + width: parent.width + text: I18n.tr("All displays") + checked: root.localAllDisplays + onToggled: isChecked => { + root.localAllDisplays = isChecked; + if (isChecked) { + root.preferencesChanged(["all"]); + return; + } + var screens = []; + for (var i = 0; i < Quickshell.screens.length; i++) { + var s = Quickshell.screens[i]; + screens.push({ + name: s.name, + model: s.model || "" + }); + } + root.preferencesChanged(screens); + } + } + + Column { + width: parent.width + spacing: Theme.spacingXS + visible: !root.localAllDisplays + + Repeater { + model: Quickshell.screens + + DankToggle { + required property var modelData + + property bool localChecked: { + const prefs = root.displayPreferences; + if (!Array.isArray(prefs) || prefs.includes("all")) + return true; + return prefs.some(p => p.name === modelData.name); + } + + width: parent.width + text: SettingsData.getScreenDisplayName(modelData) + description: modelData.width + "×" + modelData.height + checked: localChecked + onToggled: isChecked => { + localChecked = isChecked; + var prefs = JSON.parse(JSON.stringify(root.displayPreferences)); + if (!Array.isArray(prefs) || prefs.includes("all")) + prefs = []; + prefs = prefs.filter(p => p.name !== modelData.name); + if (isChecked) { + prefs.push({ + name: modelData.name, + model: modelData.model || "" + }); + } + root.preferencesChanged(prefs); + } + } + } + } + } +} diff --git a/raveos-hyprland-theme/theme-data/dms/Modules/Settings/Widgets/SettingsDivider.qml b/raveos-hyprland-theme/theme-data/dms/Modules/Settings/Widgets/SettingsDivider.qml new file mode 100644 index 0000000..86d9fe7 --- /dev/null +++ b/raveos-hyprland-theme/theme-data/dms/Modules/Settings/Widgets/SettingsDivider.qml @@ -0,0 +1,11 @@ +pragma ComponentBehavior: Bound + +import QtQuick +import qs.Common + +Rectangle { + width: parent?.width ?? 0 + height: 1 + color: Theme.outline + opacity: 0.15 +} diff --git a/raveos-hyprland-theme/theme-data/dms/Modules/Settings/Widgets/SettingsDropdownRow.qml b/raveos-hyprland-theme/theme-data/dms/Modules/Settings/Widgets/SettingsDropdownRow.qml new file mode 100644 index 0000000..c5ec3a6 --- /dev/null +++ b/raveos-hyprland-theme/theme-data/dms/Modules/Settings/Widgets/SettingsDropdownRow.qml @@ -0,0 +1,60 @@ +pragma ComponentBehavior: Bound + +import QtQuick +import qs.Common +import qs.Services +import qs.Widgets + +DankDropdown { + id: root + + LayoutMirroring.enabled: I18n.isRtl + LayoutMirroring.childrenInherit: true + + property string tab: "" + property var tags: [] + property string settingKey: "" + + readonly property bool isHighlighted: settingKey !== "" && SettingsSearchService.highlightSection === settingKey + + width: parent?.width ?? 0 + addHorizontalPadding: true + usePopupTransparency: false + + Rectangle { + anchors.fill: parent + radius: Theme.cornerRadius + color: Theme.withAlpha(Theme.primary, root.isHighlighted ? 0.2 : 0) + visible: root.isHighlighted + + Behavior on color { + ColorAnimation { + duration: Theme.shortDuration + easing.type: Theme.standardEasing + } + } + } + + function findParentFlickable() { + let p = root.parent; + while (p) { + if (p.hasOwnProperty("contentY") && p.hasOwnProperty("contentItem")) + return p; + p = p.parent; + } + return null; + } + + Component.onCompleted: { + if (!settingKey) + return; + let flickable = findParentFlickable(); + if (flickable) + SettingsSearchService.registerCard(settingKey, root, flickable); + } + + Component.onDestruction: { + if (settingKey) + SettingsSearchService.unregisterCard(settingKey); + } +} diff --git a/raveos-hyprland-theme/theme-data/dms/Modules/Settings/Widgets/SettingsSliderCard.qml b/raveos-hyprland-theme/theme-data/dms/Modules/Settings/Widgets/SettingsSliderCard.qml new file mode 100644 index 0000000..5bdd91a --- /dev/null +++ b/raveos-hyprland-theme/theme-data/dms/Modules/Settings/Widgets/SettingsSliderCard.qml @@ -0,0 +1,108 @@ +pragma ComponentBehavior: Bound + +import QtQuick +import qs.Common +import qs.Widgets + +StyledRect { + id: root + + LayoutMirroring.enabled: I18n.isRtl + LayoutMirroring.childrenInherit: true + + property string tab: "" + property var tags: [] + + property string title: "" + property string description: "" + property string iconName: "" + property alias value: slider.value + property alias minimum: slider.minimum + property alias maximum: slider.maximum + property alias unit: slider.unit + property int defaultValue: -1 + + signal sliderValueChanged(int newValue) + signal sliderDragFinished(int finalValue) + width: parent?.width ?? 0 + height: Theme.spacingL * 2 + contentColumn.height + radius: Theme.cornerRadius + color: Theme.surfaceContainerHigh + + Column { + id: contentColumn + anchors.left: parent.left + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + anchors.leftMargin: Theme.spacingL + anchors.rightMargin: Theme.spacingL + spacing: Theme.spacingS + + Row { + width: parent.width + spacing: Theme.spacingM + + DankIcon { + id: headerIcon + name: root.iconName + size: Theme.iconSize + color: Theme.primary + anchors.verticalCenter: parent.verticalCenter + visible: root.iconName !== "" + } + + Column { + anchors.verticalCenter: parent.verticalCenter + spacing: Theme.spacingXS + width: parent.width - headerIcon.width - (root.defaultValue >= 0 ? resetButton.width + Theme.spacingS : 0) - Theme.spacingM + + StyledText { + text: root.title + font.pixelSize: Theme.fontSizeLarge + font.weight: Font.Medium + color: Theme.surfaceText + width: parent.width + horizontalAlignment: Text.AlignLeft + visible: root.title !== "" + } + + StyledText { + text: root.description + font.pixelSize: Theme.fontSizeSmall + color: Theme.surfaceVariantText + wrapMode: Text.WordWrap + width: parent.width + horizontalAlignment: Text.AlignLeft + visible: root.description !== "" + } + } + + DankActionButton { + id: resetButton + anchors.verticalCenter: parent.verticalCenter + buttonSize: 36 + iconName: "restart_alt" + iconSize: 20 + visible: root.defaultValue >= 0 && slider.value !== root.defaultValue + backgroundColor: Theme.surfaceContainerHigh + iconColor: Theme.surfaceVariantText + onClicked: { + slider.value = root.defaultValue; + root.sliderValueChanged(root.defaultValue); + root.sliderDragFinished(root.defaultValue); + } + } + } + + DankSlider { + id: slider + width: parent.width + height: 32 + showValue: true + wheelEnabled: false + thumbOutlineColor: Theme.surfaceContainerHigh + onSliderValueChanged: newValue => root.sliderValueChanged(newValue) + onSliderDragFinished: finalValue => root.sliderDragFinished(finalValue) + } + } +} diff --git a/raveos-hyprland-theme/theme-data/dms/Modules/Settings/Widgets/SettingsSliderRow.qml b/raveos-hyprland-theme/theme-data/dms/Modules/Settings/Widgets/SettingsSliderRow.qml new file mode 100644 index 0000000..b1ada84 --- /dev/null +++ b/raveos-hyprland-theme/theme-data/dms/Modules/Settings/Widgets/SettingsSliderRow.qml @@ -0,0 +1,148 @@ +pragma ComponentBehavior: Bound + +import QtQuick +import qs.Common +import qs.Services +import qs.Widgets + +Item { + id: root + + LayoutMirroring.enabled: I18n.isRtl + LayoutMirroring.childrenInherit: true + + property string tab: "" + property var tags: [] + property string settingKey: "" + + property string text: "" + property string description: "" + + readonly property bool isHighlighted: settingKey !== "" && SettingsSearchService.highlightSection === settingKey + + function findParentFlickable() { + let p = root.parent; + while (p) { + if (p.hasOwnProperty("contentY") && p.hasOwnProperty("contentItem")) + return p; + p = p.parent; + } + return null; + } + + Component.onCompleted: { + if (!settingKey) + return; + let flickable = findParentFlickable(); + if (flickable) + SettingsSearchService.registerCard(settingKey, root, flickable); + } + + Component.onDestruction: { + if (settingKey) + SettingsSearchService.unregisterCard(settingKey); + } + + Rectangle { + anchors.fill: parent + radius: Theme.cornerRadius + color: Theme.withAlpha(Theme.primary, root.isHighlighted ? 0.2 : 0) + visible: root.isHighlighted + + Behavior on color { + ColorAnimation { + duration: Theme.shortDuration + easing.type: Theme.standardEasing + } + } + } + property alias value: slider.value + property alias minimum: slider.minimum + property alias maximum: slider.maximum + property alias step: slider.step + property alias unit: slider.unit + property alias wheelEnabled: slider.wheelEnabled + property alias thumbOutlineColor: slider.thumbOutlineColor + property int defaultValue: -1 + + signal sliderValueChanged(int newValue) + signal sliderDragFinished(int finalValue) + width: parent?.width ?? 0 + height: headerRow.height + Theme.spacingXS + slider.height + + Column { + id: contentColumn + width: parent.width - Theme.spacingM * 2 + x: Theme.spacingM + anchors.verticalCenter: parent.verticalCenter + spacing: Theme.spacingXS + + Row { + id: headerRow + width: parent.width + height: labelColumn.height + spacing: Theme.spacingS + + Column { + id: labelColumn + anchors.verticalCenter: parent.verticalCenter + spacing: Theme.spacingXS + width: parent.width - resetButtonContainer.width - Theme.spacingS + + StyledText { + text: root.text + font.pixelSize: Theme.fontSizeMedium + font.weight: Font.Medium + color: Theme.surfaceText + visible: root.text !== "" + width: parent.width + horizontalAlignment: Text.AlignLeft + } + + StyledText { + text: root.description + font.pixelSize: Theme.fontSizeSmall + color: Theme.surfaceVariantText + wrapMode: Text.WordWrap + width: parent.width + visible: root.description !== "" + horizontalAlignment: Text.AlignLeft + } + } + + Item { + id: resetButtonContainer + width: root.defaultValue >= 0 ? 36 : 0 + height: 36 + anchors.verticalCenter: parent.verticalCenter + + DankActionButton { + id: resetButton + anchors.centerIn: parent + buttonSize: 36 + iconName: "restart_alt" + iconSize: 20 + visible: root.defaultValue >= 0 && slider.value !== root.defaultValue + backgroundColor: Theme.surfaceContainerHigh + iconColor: Theme.surfaceVariantText + onClicked: { + slider.value = root.defaultValue; + root.sliderValueChanged(root.defaultValue); + root.sliderDragFinished(root.defaultValue); + } + } + } + } + + DankSlider { + id: slider + width: parent.width + height: 32 + showValue: true + wheelEnabled: false + thumbOutlineColor: Theme.surfaceContainerHigh + onSliderValueChanged: newValue => root.sliderValueChanged(newValue) + onSliderDragFinished: finalValue => root.sliderDragFinished(finalValue) + } + } +} diff --git a/raveos-hyprland-theme/theme-data/dms/Modules/Settings/Widgets/SettingsToggleCard.qml b/raveos-hyprland-theme/theme-data/dms/Modules/Settings/Widgets/SettingsToggleCard.qml new file mode 100644 index 0000000..c36fb7c --- /dev/null +++ b/raveos-hyprland-theme/theme-data/dms/Modules/Settings/Widgets/SettingsToggleCard.qml @@ -0,0 +1,120 @@ +pragma ComponentBehavior: Bound + +import QtQuick +import qs.Common +import qs.Widgets + +StyledRect { + id: root + + LayoutMirroring.enabled: I18n.isRtl + LayoutMirroring.childrenInherit: true + + property string tab: "" + property var tags: [] + + property string title: "" + property string description: "" + property string iconName: "" + property bool checked: false + property bool enabled: true + + default property alias content: expandedContent.children + readonly property bool hasContent: expandedContent.children.length > 0 + + signal toggled(bool checked) + + width: parent?.width ?? 0 + height: Theme.spacingL * 2 + mainColumn.height + radius: Theme.cornerRadius + color: Theme.surfaceContainerHigh + + Column { + id: mainColumn + anchors.left: parent.left + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + anchors.leftMargin: Theme.spacingL + anchors.rightMargin: Theme.spacingL + spacing: Theme.spacingM + + Item { + width: parent.width + height: headerColumn.height + + Column { + id: headerColumn + anchors.left: parent.left + anchors.right: toggleSwitch.left + anchors.rightMargin: Theme.spacingM + spacing: Theme.spacingXS + + Row { + spacing: Theme.spacingM + width: parent.width + + DankIcon { + id: headerIcon + name: root.iconName + size: Theme.iconSize + color: Theme.primary + anchors.verticalCenter: parent.verticalCenter + visible: root.iconName !== "" + } + + StyledText { + id: headerText + text: root.title + font.pixelSize: Theme.fontSizeLarge + font.weight: Font.Medium + color: Theme.surfaceText + anchors.verticalCenter: parent.verticalCenter + visible: root.title !== "" + width: parent.width - (headerIcon.visible ? headerIcon.width + parent.spacing : 0) + horizontalAlignment: Text.AlignLeft + } + } + + StyledText { + id: descriptionText + text: root.description + font.pixelSize: Theme.fontSizeSmall + color: Theme.surfaceVariantText + wrapMode: Text.WordWrap + width: parent.width + horizontalAlignment: Text.AlignLeft + visible: root.description !== "" + } + } + + DankToggle { + id: toggleSwitch + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + hideText: true + checked: root.checked + enabled: root.enabled + onToggled: checked => root.toggled(checked) + } + + StateLayer { + anchors.fill: parent + disabled: !root.enabled + stateColor: Theme.primary + cornerRadius: root.radius + onClicked: { + if (!root.enabled) + return; + root.toggled(!root.checked); + } + } + } + + Column { + id: expandedContent + width: parent.width + spacing: Theme.spacingM + visible: root.checked && root.hasContent + } + } +} diff --git a/raveos-hyprland-theme/theme-data/dms/Modules/Settings/Widgets/SettingsToggleRow.qml b/raveos-hyprland-theme/theme-data/dms/Modules/Settings/Widgets/SettingsToggleRow.qml new file mode 100644 index 0000000..684b639 --- /dev/null +++ b/raveos-hyprland-theme/theme-data/dms/Modules/Settings/Widgets/SettingsToggleRow.qml @@ -0,0 +1,58 @@ +pragma ComponentBehavior: Bound + +import QtQuick +import qs.Common +import qs.Services +import qs.Widgets + +DankToggle { + id: root + + LayoutMirroring.enabled: I18n.isRtl + LayoutMirroring.childrenInherit: true + + property string tab: "" + property var tags: [] + property string settingKey: "" + + readonly property bool isHighlighted: settingKey !== "" && SettingsSearchService.highlightSection === settingKey + + width: parent?.width ?? 0 + + function findParentFlickable() { + let p = root.parent; + while (p) { + if (p.hasOwnProperty("contentY") && p.hasOwnProperty("contentItem")) + return p; + p = p.parent; + } + return null; + } + + Component.onCompleted: { + if (!settingKey) + return; + let flickable = findParentFlickable(); + if (flickable) + SettingsSearchService.registerCard(settingKey, root, flickable); + } + + Component.onDestruction: { + if (settingKey) + SettingsSearchService.unregisterCard(settingKey); + } + + Rectangle { + anchors.fill: parent + radius: Theme.cornerRadius + color: Theme.withAlpha(Theme.primary, root.isHighlighted ? 0.2 : 0) + visible: root.isHighlighted + + Behavior on color { + ColorAnimation { + duration: Theme.shortDuration + easing.type: Theme.standardEasing + } + } + } +} diff --git a/raveos-hyprland-theme/theme-data/dms/Modules/Settings/Widgets/SystemMonitorVariantCard.qml b/raveos-hyprland-theme/theme-data/dms/Modules/Settings/Widgets/SystemMonitorVariantCard.qml new file mode 100644 index 0000000..1ecd451 --- /dev/null +++ b/raveos-hyprland-theme/theme-data/dms/Modules/Settings/Widgets/SystemMonitorVariantCard.qml @@ -0,0 +1,390 @@ +pragma ComponentBehavior: Bound + +import QtQuick +import qs.Common +import qs.Services +import qs.Widgets + +Rectangle { + id: root + + property var variant: ({}) + property bool expanded: false + + signal expandToggled(bool isExpanded) + signal deleteRequested + signal nameChanged(string newName) + signal configChanged(string key, var value) + + readonly property var cfg: variant.config || {} + + function updateConfig(key, value) { + var newConfig = JSON.parse(JSON.stringify(cfg)); + newConfig[key] = value; + root.configChanged("config", newConfig); + } + + width: parent?.width ?? 0 + height: variantColumn.height + radius: Theme.cornerRadius + color: Theme.surfaceContainerHigh + clip: true + + Column { + id: variantColumn + width: parent.width + spacing: 0 + + Item { + width: parent.width + height: headerContent.height + Theme.spacingM * 2 + + Row { + id: headerContent + x: Theme.spacingM + y: Theme.spacingM + width: parent.width - Theme.spacingM * 2 + spacing: Theme.spacingM + + DankIcon { + name: root.expanded ? "expand_less" : "expand_more" + size: Theme.iconSize + color: Theme.surfaceVariantText + anchors.verticalCenter: parent.verticalCenter + } + + Column { + width: parent.width - Theme.iconSize - deleteBtn.width - Theme.spacingM * 2 + anchors.verticalCenter: parent.verticalCenter + spacing: 0 + + StyledText { + text: root.variant.name || "Unnamed" + font.pixelSize: Theme.fontSizeMedium + color: Theme.surfaceText + width: parent.width + elide: Text.ElideRight + } + + StyledText { + property var features: { + var f = []; + if (root.cfg.showCpu) + f.push("CPU"); + if (root.cfg.showMemory) + f.push("RAM"); + if (root.cfg.showNetwork) + f.push("Net"); + if (root.cfg.showDisk) + f.push("Disk"); + if (root.cfg.showGpuTemp) + f.push("GPU"); + return f; + } + text: features.length > 0 ? features.join(", ") : I18n.tr("No features enabled") + font.pixelSize: Theme.fontSizeSmall + color: Theme.surfaceVariantText + width: parent.width + elide: Text.ElideRight + } + } + + Rectangle { + id: deleteBtn + width: 32 + height: 32 + radius: 16 + color: deleteMouse.containsMouse ? Theme.error : "transparent" + anchors.verticalCenter: parent.verticalCenter + + DankIcon { + anchors.centerIn: parent + name: "delete" + size: 16 + color: deleteMouse.containsMouse ? Theme.background : Theme.surfaceVariantText + } + + MouseArea { + id: deleteMouse + anchors.fill: parent + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + onClicked: root.deleteRequested() + } + } + } + + MouseArea { + anchors.fill: parent + anchors.rightMargin: deleteBtn.width + Theme.spacingM + cursorShape: Qt.PointingHandCursor + onClicked: root.expandToggled(!root.expanded) + } + } + + Column { + width: parent.width + spacing: 0 + visible: root.expanded + + SettingsDivider {} + + Item { + width: parent.width + height: nameRow.height + Theme.spacingM * 2 + + Row { + id: nameRow + x: Theme.spacingM + y: Theme.spacingM + width: parent.width - Theme.spacingM * 2 + spacing: Theme.spacingM + + StyledText { + text: I18n.tr("Name") + font.pixelSize: Theme.fontSizeSmall + color: Theme.surfaceVariantText + width: 80 + anchors.verticalCenter: parent.verticalCenter + } + + DankTextField { + width: parent.width - 80 - Theme.spacingM + text: root.variant.name || "" + onEditingFinished: { + if (text !== root.variant.name) + root.nameChanged(text); + } + } + } + } + + SettingsDivider {} + + DankToggle { + width: parent.width - Theme.spacingM * 2 + x: Theme.spacingM + text: I18n.tr("Show Header") + checked: root.cfg.showHeader ?? true + onToggled: checked => root.updateConfig("showHeader", checked) + } + + SettingsDivider {} + + DankToggle { + width: parent.width - Theme.spacingM * 2 + x: Theme.spacingM + text: I18n.tr("Show CPU") + checked: root.cfg.showCpu ?? true + onToggled: checked => root.updateConfig("showCpu", checked) + } + + DankToggle { + width: parent.width - Theme.spacingM * 2 + x: Theme.spacingM + text: I18n.tr("Show CPU Graph") + visible: root.cfg.showCpu + checked: root.cfg.showCpuGraph ?? true + onToggled: checked => root.updateConfig("showCpuGraph", checked) + } + + DankToggle { + width: parent.width - Theme.spacingM * 2 + x: Theme.spacingM + text: I18n.tr("Show CPU Temp") + visible: root.cfg.showCpu + checked: root.cfg.showCpuTemp ?? true + onToggled: checked => root.updateConfig("showCpuTemp", checked) + } + + SettingsDivider {} + + DankToggle { + width: parent.width - Theme.spacingM * 2 + x: Theme.spacingM + text: I18n.tr("Show Memory") + checked: root.cfg.showMemory ?? true + onToggled: checked => root.updateConfig("showMemory", checked) + } + + DankToggle { + width: parent.width - Theme.spacingM * 2 + x: Theme.spacingM + text: I18n.tr("Show Memory Graph") + visible: root.cfg.showMemory + checked: root.cfg.showMemoryGraph ?? true + onToggled: checked => root.updateConfig("showMemoryGraph", checked) + } + + DankToggle { + width: parent.width - Theme.spacingM * 2 + x: Theme.spacingM + text: I18n.tr("Show Memory in GB") + visible: root.cfg.showMemory + checked: root.cfg.showInGb ?? false + onToggled: checked => root.updateConfig("showInGb", checked) + } + + SettingsDivider {} + + DankToggle { + width: parent.width - Theme.spacingM * 2 + x: Theme.spacingM + text: I18n.tr("Show Network") + checked: root.cfg.showNetwork ?? true + onToggled: checked => root.updateConfig("showNetwork", checked) + } + + DankToggle { + width: parent.width - Theme.spacingM * 2 + x: Theme.spacingM + text: I18n.tr("Show Network Graph") + visible: root.cfg.showNetwork + checked: root.cfg.showNetworkGraph ?? true + onToggled: checked => root.updateConfig("showNetworkGraph", checked) + } + + SettingsDivider {} + + DankToggle { + width: parent.width - Theme.spacingM * 2 + x: Theme.spacingM + text: I18n.tr("Show Disk") + checked: root.cfg.showDisk ?? true + onToggled: checked => root.updateConfig("showDisk", checked) + } + + SettingsDivider {} + + DankToggle { + width: parent.width - Theme.spacingM * 2 + x: Theme.spacingM + text: I18n.tr("Show GPU Temperature") + checked: root.cfg.showGpuTemp ?? false + onToggled: checked => root.updateConfig("showGpuTemp", checked) + } + + Column { + width: parent.width + spacing: Theme.spacingXS + visible: root.cfg.showGpuTemp && DgopService.availableGpus.length > 0 + + Item { + width: 1 + height: Theme.spacingS + } + + Repeater { + model: DgopService.availableGpus + + Rectangle { + required property var modelData + + width: (parent?.width ?? 0) - Theme.spacingM * 2 + x: Theme.spacingM + height: 40 + radius: Theme.cornerRadius + color: root.cfg.gpuPciId === modelData.pciId ? Theme.primarySelected : Theme.surfaceContainer + border.color: root.cfg.gpuPciId === modelData.pciId ? Theme.primary : "transparent" + border.width: 2 + + Row { + anchors.fill: parent + anchors.margins: Theme.spacingS + spacing: Theme.spacingS + + DankIcon { + name: "videocam" + size: Theme.iconSizeSmall + color: root.cfg.gpuPciId === modelData.pciId ? Theme.primary : Theme.surfaceVariantText + anchors.verticalCenter: parent.verticalCenter + } + + StyledText { + text: modelData.displayName || "Unknown GPU" + font.pixelSize: Theme.fontSizeSmall + color: Theme.surfaceText + width: parent.width - Theme.iconSizeSmall - Theme.spacingS + anchors.verticalCenter: parent.verticalCenter + elide: Text.ElideRight + } + } + + MouseArea { + anchors.fill: parent + cursorShape: Qt.PointingHandCursor + onClicked: root.updateConfig("gpuPciId", modelData.pciId) + } + } + } + + Item { + width: 1 + height: Theme.spacingS + } + } + + SettingsDivider {} + + DankToggle { + width: parent.width - Theme.spacingM * 2 + x: Theme.spacingM + text: I18n.tr("Show Top Processes") + checked: root.cfg.showTopProcesses ?? false + onToggled: checked => root.updateConfig("showTopProcesses", checked) + } + + SettingsDivider {} + + Column { + width: parent.width - Theme.spacingM * 2 + x: Theme.spacingM + topPadding: Theme.spacingM + bottomPadding: Theme.spacingM + spacing: Theme.spacingS + + Row { + width: parent.width + + StyledText { + id: transparencyLabel + text: I18n.tr("Transparency") + font.pixelSize: Theme.fontSizeSmall + color: Theme.surfaceVariantText + anchors.verticalCenter: parent.verticalCenter + } + + Item { + width: parent.width - transparencyLabel.width - transparencyValue.width + height: 1 + } + + StyledText { + id: transparencyValue + text: transparencySlider.value + "%" + font.pixelSize: Theme.fontSizeSmall + font.weight: Font.Medium + color: Theme.primary + anchors.verticalCenter: parent.verticalCenter + } + } + + DankSlider { + id: transparencySlider + width: parent.width + minimum: 0 + maximum: 100 + value: Math.round((root.cfg.transparency ?? 0.8) * 100) + showValue: false + wheelEnabled: false + onSliderDragFinished: finalValue => root.updateConfig("transparency", finalValue / 100) + } + } + + Item { + width: 1 + height: Theme.spacingM + } + } + } +} |