diff options
Diffstat (limited to 'raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Widgets')
14 files changed, 1356 insertions, 0 deletions
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Widgets/AudioSliderRow.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Widgets/AudioSliderRow.qml new file mode 100644 index 0000000..81d346d --- /dev/null +++ b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Widgets/AudioSliderRow.qml @@ -0,0 +1,103 @@ +import QtQuick +import qs.Common +import qs.Services +import qs.Widgets + +Row { + id: root + + LayoutMirroring.enabled: I18n.isRtl + LayoutMirroring.childrenInherit: true + + property var defaultSink: AudioService.sink + property color sliderTrackColor: "transparent" + + height: 40 + spacing: 0 + + Rectangle { + width: Theme.iconSize + Theme.spacingS * 2 + height: Theme.iconSize + Theme.spacingS * 2 + anchors.verticalCenter: parent.verticalCenter + radius: (Theme.iconSize + Theme.spacingS * 2) / 2 + color: iconArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Theme.withAlpha(Theme.primary, 0) + + DankRipple { + id: iconRipple + cornerRadius: parent.radius + } + + MouseArea { + id: iconArea + anchors.fill: parent + visible: defaultSink !== null + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + onPressed: mouse => iconRipple.trigger(mouse.x, mouse.y) + onClicked: { + if (defaultSink) { + SessionData.suppressOSDTemporarily(); + defaultSink.audio.muted = !defaultSink.audio.muted; + } + } + } + + DankIcon { + anchors.centerIn: parent + name: { + if (!defaultSink) + return "volume_off"; + + let volume = defaultSink.audio.volume; + let muted = defaultSink.audio.muted; + + if (muted) + return "volume_off"; + if (volume === 0.0) + return "volume_mute"; + if (volume <= 0.33) + return "volume_down"; + if (volume <= 0.66) + return "volume_up"; + return "volume_up"; + } + size: Theme.iconSize + color: defaultSink && !defaultSink.audio.muted && defaultSink.audio.volume > 0 ? Theme.primary : Theme.surfaceText + } + } + + DankSlider { + id: volumeSlider + + readonly property real actualVolumePercent: defaultSink ? Math.round(defaultSink.audio.volume * 100) : 0 + + anchors.verticalCenter: parent.verticalCenter + width: parent.width - (Theme.iconSize + Theme.spacingS * 2) + enabled: defaultSink !== null + minimum: 0 + maximum: AudioService.sinkMaxVolume + showValue: true + unit: "%" + valueOverride: actualVolumePercent + thumbOutlineColor: Theme.surfaceContainer + trackColor: root.sliderTrackColor.a > 0 ? root.sliderTrackColor : Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency) + + onSliderValueChanged: function (newValue) { + if (defaultSink) { + SessionData.suppressOSDTemporarily(); + defaultSink.audio.volume = newValue / 100.0; + if (newValue > 0 && defaultSink.audio.muted) { + defaultSink.audio.muted = false; + } + AudioService.playVolumeChangeSoundIfEnabled(); + } + } + } + + Binding { + target: volumeSlider + property: "value" + value: defaultSink ? Math.min(AudioService.sinkMaxVolume, Math.round(defaultSink.audio.volume * 100)) : 0 + when: !volumeSlider.isDragging + } +} diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Widgets/BatteryPill.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Widgets/BatteryPill.qml new file mode 100644 index 0000000..c14c308 --- /dev/null +++ b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Widgets/BatteryPill.qml @@ -0,0 +1,46 @@ +import QtQuick +import qs.Common +import qs.Services +import qs.Modules.ControlCenter.Widgets + +CompoundPill { + id: root + + iconName: BatteryService.getBatteryIcon() + + isActive: BatteryService.batteryAvailable && (BatteryService.isCharging || BatteryService.isPluggedIn) + + primaryText: { + if (!BatteryService.batteryAvailable) { + return I18n.tr("No battery"); + } + return I18n.tr("Battery"); + } + + secondaryText: { + if (!BatteryService.batteryAvailable) { + return I18n.tr("Not available"); + } + if (BatteryService.isCharging) { + return `${BatteryService.batteryLevel}% • ` + I18n.tr("Charging"); + } + if (BatteryService.isPluggedIn) { + return `${BatteryService.batteryLevel}% • ` + I18n.tr("Plugged in"); + } + return `${BatteryService.batteryLevel}%`; + } + + iconColor: { + if (BatteryService.isLowBattery && !BatteryService.isCharging) { + return Theme.error; + } + if (BatteryService.isCharging || BatteryService.isPluggedIn) { + return Theme.primary; + } + return Theme.surfaceText; + } + + onToggled: { + expandClicked(); + } +} diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Widgets/BrightnessSliderRow.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Widgets/BrightnessSliderRow.qml new file mode 100644 index 0000000..037c08f --- /dev/null +++ b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Widgets/BrightnessSliderRow.qml @@ -0,0 +1,194 @@ +import QtQuick +import qs.Common +import qs.Services +import qs.Widgets + +Row { + id: root + + LayoutMirroring.enabled: I18n.isRtl + LayoutMirroring.childrenInherit: true + + property string deviceName: "" + property string instanceId: "" + property string screenName: "" + property var parentScreen: null + + signal iconClicked + + height: 40 + spacing: 0 + + DankTooltipV2 { + id: sharedTooltip + } + + property string targetDeviceName: { + if (!DisplayService.brightnessAvailable || !DisplayService.devices || DisplayService.devices.length === 0) { + return ""; + } + + if (screenName && screenName.length > 0) { + const pins = SettingsData.brightnessDevicePins || {}; + const pinnedDevice = pins[screenName]; + if (pinnedDevice && pinnedDevice.length > 0) { + const found = DisplayService.devices.find(dev => dev.name === pinnedDevice); + if (found) { + return found.name; + } + } + } + + if (deviceName && deviceName.length > 0) { + const found = DisplayService.devices.find(dev => dev.name === deviceName); + if (found) { + return found.name; + } + } + + const currentDeviceName = DisplayService.currentDevice; + if (currentDeviceName) { + const found = DisplayService.devices.find(dev => dev.name === currentDeviceName); + if (found) { + return found.name; + } + } + + const backlight = DisplayService.devices.find(d => d.class === "backlight"); + if (backlight) { + return backlight.name; + } + + const ddc = DisplayService.devices.find(d => d.class === "ddc"); + if (ddc) { + return ddc.name; + } + + return DisplayService.devices.length > 0 ? DisplayService.devices[0].name : ""; + } + + property var targetDevice: { + if (!targetDeviceName || !DisplayService.devices) { + return null; + } + + return DisplayService.devices.find(dev => dev.name === targetDeviceName) || null; + } + + property real targetBrightness: { + DisplayService.brightnessVersion; + if (!targetDeviceName) { + return 0; + } + + return DisplayService.getDeviceBrightness(targetDeviceName); + } + + Rectangle { + width: Theme.iconSize + Theme.spacingS * 2 + height: Theme.iconSize + Theme.spacingS * 2 + anchors.verticalCenter: parent.verticalCenter + radius: (Theme.iconSize + Theme.spacingS * 2) / 2 + color: iconArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Theme.withAlpha(Theme.primary, 0) + + DankRipple { + id: iconRipple + cornerRadius: parent.radius + } + + MouseArea { + id: iconArea + anchors.fill: parent + hoverEnabled: true + cursorShape: DisplayService.devices && DisplayService.devices.length > 1 ? Qt.PointingHandCursor : Qt.ArrowCursor + + onPressed: mouse => iconRipple.trigger(mouse.x, mouse.y) + onClicked: { + if (DisplayService.devices && DisplayService.devices.length > 1) { + root.iconClicked(); + } + } + + onEntered: { + const tooltipText = targetDevice ? "bl device: " + targetDevice.name : "Backlight Control"; + sharedTooltip.show(tooltipText, iconArea, 0, 0, "bottom"); + } + + onExited: { + sharedTooltip.hide(); + } + + DankIcon { + anchors.centerIn: parent + name: { + if (!DisplayService.brightnessAvailable || !targetDevice) { + return "brightness_low"; + } + + if (targetDevice.class === "backlight" || targetDevice.class === "ddc") { + const brightness = targetBrightness; + if (brightness <= 33) + return "brightness_low"; + if (brightness <= 66) + return "brightness_medium"; + return "brightness_high"; + } else if (targetDevice.name.includes("kbd")) { + return "keyboard"; + } else { + return "lightbulb"; + } + } + size: Theme.iconSize + color: DisplayService.brightnessAvailable && targetDevice && targetBrightness > 0 ? Theme.primary : Theme.surfaceText + } + } + } + + DankSlider { + id: brightnessSlider + + anchors.verticalCenter: parent.verticalCenter + width: parent.width - (Theme.iconSize + Theme.spacingS * 2) + enabled: DisplayService.brightnessAvailable && targetDeviceName.length > 0 + minimum: { + if (!targetDevice) + return 1; + const isExponential = SessionData.getBrightnessExponential(targetDevice.id); + if (isExponential) { + return 1; + } + return (targetDevice.class === "backlight" || targetDevice.class === "ddc") ? 1 : 0; + } + maximum: { + if (!targetDevice) + return 100; + const isExponential = SessionData.getBrightnessExponential(targetDevice.id); + if (isExponential) { + return 100; + } + return targetDevice.displayMax || 100; + } + showValue: true + unit: { + if (!targetDevice) + return "%"; + const isExponential = SessionData.getBrightnessExponential(targetDevice.id); + if (isExponential) { + return "%"; + } + return targetDevice.class === "ddc" ? "" : "%"; + } + onSliderValueChanged: function (newValue) { + if (DisplayService.brightnessAvailable && targetDeviceName) { + DisplayService.setBrightness(newValue, targetDeviceName, true); + } + } + thumbOutlineColor: Theme.surfaceContainer + trackColor: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency) + + Binding on value { + value: root.targetBrightness + when: !brightnessSlider.isDragging + } + } +} diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Widgets/ColorPickerPill.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Widgets/ColorPickerPill.qml new file mode 100644 index 0000000..a95410b --- /dev/null +++ b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Widgets/ColorPickerPill.qml @@ -0,0 +1,29 @@ +import QtQuick +import qs.Common +import qs.Modules.ControlCenter.Widgets + +CompoundPill { + id: root + + property var colorPickerModal: null + + isActive: true + iconName: "palette" + iconColor: Theme.primary + primaryText: I18n.tr("Color Picker") + secondaryText: I18n.tr("Choose a color") + + onToggled: { + console.log("ColorPickerPill toggled, modal:", colorPickerModal); + if (colorPickerModal) { + colorPickerModal.show(); + } + } + + onExpandClicked: { + console.log("ColorPickerPill expandClicked, modal:", colorPickerModal); + if (colorPickerModal) { + colorPickerModal.show(); + } + } +} diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Widgets/CompactSlider.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Widgets/CompactSlider.qml new file mode 100644 index 0000000..eeed4c4 --- /dev/null +++ b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Widgets/CompactSlider.qml @@ -0,0 +1,71 @@ +import QtQuick +import qs.Common +import qs.Widgets + +Rectangle { + id: root + + LayoutMirroring.enabled: I18n.isRtl + LayoutMirroring.childrenInherit: true + + property string iconName: "" + property color iconColor: Theme.surfaceText + property string labelText: "" + property real value: 0.0 + property real maximumValue: 1.0 + property real minimumValue: 0.0 + property bool enabled: true + + signal sliderValueChanged(real value) + + width: parent ? parent.width : 200 + height: 60 + radius: Theme.cornerRadius + color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency) + border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08) + border.width: 0 + opacity: enabled ? 1.0 : 0.6 + + Row { + anchors.left: parent.left + anchors.verticalCenter: parent.verticalCenter + anchors.leftMargin: Theme.spacingM + anchors.right: sliderContainer.left + anchors.rightMargin: Theme.spacingS + spacing: Theme.spacingS + + DankIcon { + name: root.iconName + size: Theme.iconSize + color: root.iconColor + anchors.verticalCenter: parent.verticalCenter + } + + StyledText { + text: root.labelText + font.pixelSize: Theme.fontSizeMedium + color: Theme.surfaceText + font.weight: Font.Medium + anchors.verticalCenter: parent.verticalCenter + } + } + + Rectangle { + id: sliderContainer + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + anchors.rightMargin: Theme.spacingM + width: 120 + height: parent.height - Theme.spacingS * 2 + + DankSlider { + anchors.centerIn: parent + width: parent.width + enabled: root.enabled + minimum: Math.round(root.minimumValue * 100) + maximum: Math.round(root.maximumValue * 100) + value: Math.round(root.value * 100) + onSliderValueChanged: root.sliderValueChanged(newValue / 100.0) + } + } +} diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Widgets/CompoundPill.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Widgets/CompoundPill.qml new file mode 100644 index 0000000..9165ec4 --- /dev/null +++ b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Widgets/CompoundPill.qml @@ -0,0 +1,205 @@ +import QtQuick +import qs.Common +import qs.Widgets + +Rectangle { + id: root + + LayoutMirroring.enabled: I18n.isRtl + LayoutMirroring.childrenInherit: true + + property string iconName: "" + property color iconColor: Theme.surfaceText + property string primaryText: "" + property string secondaryText: "" + property bool expanded: false + property bool isActive: false + property bool showExpandArea: true + + signal toggled + signal expandClicked + signal wheelEvent(var wheelEvent) + + width: parent ? parent.width : 220 + height: 60 + radius: Theme.cornerRadius + + function hoverTint(base) { + const factor = 1.2; + return Theme.isLightMode ? Qt.darker(base, factor) : Qt.lighter(base, factor); + } + + readonly property color _containerBg: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency) + + color: { + const baseColor = bodyMouse.containsMouse ? Theme.primaryPressed : _containerBg; + return baseColor; + } + border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.10) + border.width: 0 + antialiasing: true + + readonly property color _labelPrimary: Theme.surfaceText + readonly property color _labelSecondary: Theme.surfaceVariantText + readonly property color _tileBgActive: Theme.ccTileActiveBg + readonly property color _tileBgInactive: { + const transparency = Theme.popupTransparency; + const surface = Theme.surfaceContainer || Qt.rgba(0.1, 0.1, 0.1, 1); + return Qt.rgba(surface.r, surface.g, surface.b, transparency); + } + readonly property color _tileRingActive: Theme.ccTileRing + readonly property color _tileRingInactive: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.18) + readonly property color _tileIconActive: Theme.ccTileActiveText + readonly property color _tileIconInactive: Theme.ccTileInactiveIcon + + property int _padH: Theme.spacingS + property int _tileSize: 48 + property int _tileRadius: Theme.cornerRadius + + Rectangle { + id: rightHoverOverlay + anchors.fill: parent + radius: root.radius + z: 0 + visible: false + color: hoverTint(_containerBg) + opacity: 0.08 + antialiasing: true + Behavior on opacity { + NumberAnimation { + duration: Theme.shortDuration + } + } + } + + DankRipple { + id: bodyRipple + cornerRadius: root.radius + } + + Row { + id: row + anchors.fill: parent + anchors.leftMargin: _padH + anchors.rightMargin: Theme.spacingM + spacing: Theme.spacingM + + Rectangle { + id: iconTile + z: 1 + width: _tileSize + height: _tileSize + anchors.verticalCenter: parent.verticalCenter + radius: _tileRadius + color: isActive ? _tileBgActive : _tileBgInactive + border.color: isActive ? _tileRingActive : "transparent" + border.width: isActive ? 1 : 0 + antialiasing: true + + Rectangle { + anchors.fill: parent + radius: _tileRadius + color: hoverTint(iconTile.color) + opacity: tileMouse.pressed ? 0.3 : (tileMouse.containsMouse ? 0.2 : 0.0) + visible: opacity > 0 + antialiasing: true + Behavior on opacity { + NumberAnimation { + duration: Theme.shortDuration + } + } + } + + DankIcon { + anchors.centerIn: parent + name: iconName + size: Theme.iconSize + color: isActive ? _tileIconActive : _tileIconInactive + } + + DankRipple { + id: tileRipple + cornerRadius: _tileRadius + } + + MouseArea { + id: tileMouse + anchors.fill: parent + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + onPressed: mouse => tileRipple.trigger(mouse.x, mouse.y) + onClicked: root.toggled() + } + } + + Item { + id: body + width: row.width - iconTile.width - row.spacing + height: row.height + + Column { + anchors.left: parent.left + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + spacing: 2 + + StyledText { + width: parent.width + text: root.primaryText + color: _labelPrimary + font.pixelSize: Theme.fontSizeMedium + font.weight: Font.Medium + elide: Text.ElideRight + wrapMode: Text.NoWrap + horizontalAlignment: Text.AlignLeft + } + StyledText { + width: parent.width + text: root.secondaryText + color: _labelSecondary + font.pixelSize: Theme.fontSizeSmall + visible: text.length > 0 + elide: Text.ElideRight + wrapMode: Text.NoWrap + horizontalAlignment: Text.AlignLeft + } + } + + MouseArea { + id: bodyMouse + anchors.fill: parent + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + onEntered: { + rightHoverOverlay.visible = true; + rightHoverOverlay.opacity = 0.08; + } + onExited: { + rightHoverOverlay.opacity = 0.0; + rightHoverOverlay.visible = false; + } + onPressed: mouse => { + const pos = mapToItem(root, mouse.x, mouse.y); + bodyRipple.trigger(pos.x, pos.y); + rightHoverOverlay.opacity = 0.16; + } + onReleased: rightHoverOverlay.opacity = containsMouse ? 0.08 : 0.0 + onClicked: root.expandClicked() + onWheel: function (ev) { + root.wheelEvent(ev); + } + } + } + } + + focus: true + Keys.onPressed: function (ev) { + if (ev.key === Qt.Key_Space || ev.key === Qt.Key_Return) { + root.toggled(); + ev.accepted = true; + } else if (ev.key === Qt.Key_Right) { + root.expandClicked(); + ev.accepted = true; + } + } +} diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Widgets/DetailView.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Widgets/DetailView.qml new file mode 100644 index 0000000..2d946f3 --- /dev/null +++ b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Widgets/DetailView.qml @@ -0,0 +1,23 @@ +import QtQuick + +Rectangle { + id: root + + property string title: "" + property Component content: null + property bool isVisible: true + property int contentHeight: 300 + + width: parent ? parent.width : 400 + implicitHeight: isVisible ? contentHeight : 0 + height: implicitHeight + color: "transparent" + clip: true + + Loader { + id: contentLoader + anchors.fill: parent + sourceComponent: root.content + asynchronous: true + } +} diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Widgets/DiskUsagePill.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Widgets/DiskUsagePill.qml new file mode 100644 index 0000000..827df4e --- /dev/null +++ b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Widgets/DiskUsagePill.qml @@ -0,0 +1,76 @@ +import QtQuick +import qs.Common +import qs.Services +import qs.Modules.ControlCenter.Widgets + +CompoundPill { + id: root + + property string mountPath: "/" + property string instanceId: "" + + iconName: "storage" + + property var selectedMount: { + if (!DgopService.diskMounts || DgopService.diskMounts.length === 0) { + return null; + } + + const targetMount = DgopService.diskMounts.find(mount => mount.mount === mountPath); + return targetMount || DgopService.diskMounts.find(mount => mount.mount === "/") || DgopService.diskMounts[0]; + } + + property real usagePercent: { + if (!selectedMount || !selectedMount.percent) { + return 0; + } + const percentStr = selectedMount.percent.replace("%", ""); + return parseFloat(percentStr) || 0; + } + + isActive: DgopService.dgopAvailable && selectedMount !== null + + primaryText: { + if (!DgopService.dgopAvailable) { + return I18n.tr("Disk Usage"); + } + if (!selectedMount) { + return I18n.tr("No disk data"); + } + return selectedMount.mount; + } + + secondaryText: { + if (!DgopService.dgopAvailable) { + return I18n.tr("dgop not available"); + } + if (!selectedMount) { + return I18n.tr("No disk data available"); + } + return `${selectedMount.used} / ${selectedMount.size} (${usagePercent.toFixed(0)}%)`; + } + + iconColor: { + if (!DgopService.dgopAvailable || !selectedMount) { + return Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.5); + } + if (usagePercent > 90) { + return Theme.error; + } + if (usagePercent > 75) { + return Theme.warning; + } + return Theme.surfaceText; + } + + Component.onCompleted: { + DgopService.addRef(["diskmounts"]); + } + Component.onDestruction: { + DgopService.removeRef(["diskmounts"]); + } + + onToggled: { + expandClicked(); + } +} diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Widgets/ErrorPill.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Widgets/ErrorPill.qml new file mode 100644 index 0000000..cece467 --- /dev/null +++ b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Widgets/ErrorPill.qml @@ -0,0 +1,56 @@ +import QtQuick +import qs.Common +import qs.Widgets + +StyledRect { + id: root + + LayoutMirroring.enabled: I18n.isRtl + LayoutMirroring.childrenInherit: true + + property string primaryMessage: "" + property string secondaryMessage: "" + + radius: Theme.cornerRadius + color: Qt.rgba(Theme.warning.r, Theme.warning.g, Theme.warning.b, 0.1) + border.color: Theme.warning + border.width: 1 + + Row { + anchors.fill: parent + anchors.margins: Theme.spacingM + spacing: Theme.spacingXS + + DankIcon { + name: "warning" + size: 16 + color: Theme.warning + anchors.top: parent.top + anchors.topMargin: 2 + } + + Column { + width: parent.width - 16 - parent.spacing + spacing: Theme.spacingXS + + StyledText { + width: parent.width + text: root.primaryMessage + font.pixelSize: Theme.fontSizeSmall + color: Theme.warning + font.weight: Font.Medium + wrapMode: Text.WordWrap + horizontalAlignment: Text.AlignLeft + } + + StyledText { + width: parent.width + text: root.secondaryMessage + font.pixelSize: Theme.fontSizeSmall + color: Theme.warning + visible: text.length > 0 + horizontalAlignment: Text.AlignLeft + } + } + } +} diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Widgets/InputAudioSliderRow.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Widgets/InputAudioSliderRow.qml new file mode 100644 index 0000000..49ea30e --- /dev/null +++ b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Widgets/InputAudioSliderRow.qml @@ -0,0 +1,87 @@ +import QtQuick +import qs.Common +import qs.Services +import qs.Widgets + +Row { + id: root + + LayoutMirroring.enabled: I18n.isRtl + LayoutMirroring.childrenInherit: true + + property var defaultSource: AudioService.source + property color sliderTrackColor: "transparent" + + height: 40 + spacing: 0 + + Rectangle { + width: Theme.iconSize + Theme.spacingS * 2 + height: Theme.iconSize + Theme.spacingS * 2 + anchors.verticalCenter: parent.verticalCenter + radius: (Theme.iconSize + Theme.spacingS * 2) / 2 + color: iconArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Theme.withAlpha(Theme.primary, 0) + + DankRipple { + id: iconRipple + cornerRadius: parent.radius + } + + MouseArea { + id: iconArea + anchors.fill: parent + visible: defaultSource !== null + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + onPressed: mouse => iconRipple.trigger(mouse.x, mouse.y) + onClicked: { + if (defaultSource) { + SessionData.suppressOSDTemporarily(); + defaultSource.audio.muted = !defaultSource.audio.muted; + } + } + } + + DankIcon { + anchors.centerIn: parent + name: { + if (!defaultSource) + return "mic_off"; + + let volume = defaultSource.audio.volume; + let muted = defaultSource.audio.muted; + + if (muted || volume === 0.0) + return "mic_off"; + return "mic"; + } + size: Theme.iconSize + color: defaultSource && !defaultSource.audio.muted && defaultSource.audio.volume > 0 ? Theme.primary : Theme.surfaceText + } + } + + DankSlider { + readonly property real actualVolumePercent: defaultSource ? Math.round(defaultSource.audio.volume * 100) : 0 + + anchors.verticalCenter: parent.verticalCenter + width: parent.width - (Theme.iconSize + Theme.spacingS * 2) + enabled: defaultSource !== null + minimum: 0 + maximum: 100 + value: defaultSource ? Math.min(100, Math.round(defaultSource.audio.volume * 100)) : 0 + showValue: true + unit: "%" + valueOverride: actualVolumePercent + thumbOutlineColor: Theme.surfaceContainer + trackColor: root.sliderTrackColor.a > 0 ? root.sliderTrackColor : Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency) + onSliderValueChanged: function (newValue) { + if (defaultSource) { + SessionData.suppressOSDTemporarily(); + defaultSource.audio.volume = newValue / 100.0; + if (newValue > 0 && defaultSource.audio.muted) { + defaultSource.audio.muted = false; + } + } + } + } +} diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Widgets/SmallBatteryButton.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Widgets/SmallBatteryButton.qml new file mode 100644 index 0000000..02da286 --- /dev/null +++ b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Widgets/SmallBatteryButton.qml @@ -0,0 +1,113 @@ +import QtQuick +import qs.Common +import qs.Services +import qs.Widgets + +Rectangle { + id: root + + LayoutMirroring.enabled: I18n.isRtl + LayoutMirroring.childrenInherit: true + + property bool isActive: BatteryService.batteryAvailable && (BatteryService.isCharging || BatteryService.isPluggedIn) + property bool enabled: BatteryService.batteryAvailable + + signal clicked + + width: parent ? ((parent.width - parent.spacing * 3) / 4) : 48 + height: 48 + radius: { + if (Theme.cornerRadius === 0) + return 0; + return isActive ? Theme.cornerRadius : Theme.cornerRadius + 4; + } + + function hoverTint(base) { + const factor = 1.2; + return Theme.isLightMode ? Qt.darker(base, factor) : Qt.lighter(base, factor); + } + + readonly property color _tileBgActive: Theme.ccTileActiveBg + readonly property color _tileBgInactive: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency) + readonly property color _tileRingActive: Theme.ccTileRing + readonly property color _tileIconActive: Theme.ccTileActiveText + readonly property color _tileIconInactive: Theme.ccTileInactiveIcon + + color: { + if (isActive) + return _tileBgActive; + const baseColor = mouseArea.containsMouse ? Theme.primaryPressed : _tileBgInactive; + return baseColor; + } + border.color: isActive ? _tileRingActive : "transparent" + border.width: isActive ? 1 : 0 + antialiasing: true + opacity: enabled ? 1.0 : 0.6 + + Rectangle { + anchors.fill: parent + radius: parent.radius + color: hoverTint(root.color) + opacity: mouseArea.pressed ? 0.3 : (mouseArea.containsMouse ? 0.2 : 0.0) + visible: opacity > 0 + antialiasing: true + Behavior on opacity { + NumberAnimation { + duration: Theme.shortDuration + } + } + } + + Row { + anchors.centerIn: parent + spacing: 4 + + DankIcon { + name: BatteryService.getBatteryIcon() + size: parent.parent.width * 0.25 + color: { + if (BatteryService.isLowBattery && !BatteryService.isCharging) { + return Theme.error; + } + return isActive ? _tileIconActive : _tileIconInactive; + } + anchors.verticalCenter: parent.verticalCenter + } + + StyledText { + text: BatteryService.batteryAvailable ? `${BatteryService.batteryLevel}%` : "" + font.pixelSize: parent.parent.width * 0.15 + font.weight: Font.Medium + color: { + if (BatteryService.isLowBattery && !BatteryService.isCharging) { + return Theme.error; + } + return isActive ? _tileIconActive : _tileIconInactive; + } + anchors.verticalCenter: parent.verticalCenter + visible: BatteryService.batteryAvailable + } + } + + DankRipple { + id: ripple + cornerRadius: root.radius + } + + MouseArea { + id: mouseArea + anchors.fill: parent + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + enabled: root.enabled + onPressed: mouse => ripple.trigger(mouse.x, mouse.y) + onClicked: root.clicked() + } + + Behavior on radius { + NumberAnimation { + duration: Theme.shortDuration + easing.type: Theme.standardEasing + } + } +} diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Widgets/SmallDiskUsageButton.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Widgets/SmallDiskUsageButton.qml new file mode 100644 index 0000000..30c4e36 --- /dev/null +++ b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Widgets/SmallDiskUsageButton.qml @@ -0,0 +1,129 @@ +import QtQuick +import qs.Common +import qs.Services +import qs.Widgets + +Rectangle { + id: root + + LayoutMirroring.enabled: I18n.isRtl + LayoutMirroring.childrenInherit: true + + property string mountPath: "/" + property string instanceId: "" + + property var selectedMount: { + if (!DgopService.diskMounts || DgopService.diskMounts.length === 0) + return null; + const targetMount = DgopService.diskMounts.find(mount => mount.mount === mountPath); + return targetMount || DgopService.diskMounts.find(mount => mount.mount === "/") || DgopService.diskMounts[0]; + } + + property real usagePercent: { + if (!selectedMount?.percent) + return 0; + return parseFloat(selectedMount.percent.replace("%", "")) || 0; + } + + property bool enabled: DgopService.dgopAvailable + + signal clicked + + width: parent ? ((parent.width - parent.spacing * 3) / 4) : 48 + height: 48 + radius: Theme.cornerRadius + 4 + + function hoverTint(base) { + const factor = 1.2; + return Theme.isLightMode ? Qt.darker(base, factor) : Qt.lighter(base, factor); + } + + readonly property color _tileBg: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency) + + color: mouseArea.containsMouse ? Theme.primaryPressed : _tileBg + border.color: "transparent" + border.width: 0 + antialiasing: true + opacity: enabled ? 1.0 : 0.6 + + Rectangle { + anchors.fill: parent + radius: parent.radius + color: hoverTint(root.color) + opacity: mouseArea.pressed ? 0.3 : (mouseArea.containsMouse ? 0.2 : 0.0) + visible: opacity > 0 + antialiasing: true + Behavior on opacity { + NumberAnimation { + duration: Theme.shortDuration + } + } + } + + Row { + anchors.centerIn: parent + spacing: Theme.spacingXS + + DankIcon { + anchors.verticalCenter: parent.verticalCenter + name: "storage" + size: Theme.iconSizeSmall + color: { + if (root.usagePercent > 90) + return Theme.error; + if (root.usagePercent > 75) + return Theme.warning; + return Theme.ccTileInactiveIcon; + } + } + + Column { + anchors.verticalCenter: parent.verticalCenter + spacing: 0 + + StyledText { + text: root.selectedMount?.mount || root.mountPath + font.pixelSize: Theme.fontSizeSmall + color: Theme.surfaceVariantText + elide: Text.ElideMiddle + width: Math.min(implicitWidth, root.width - Theme.iconSizeSmall - Theme.spacingM) + horizontalAlignment: Text.AlignLeft + } + + StyledText { + text: `${root.usagePercent.toFixed(0)}%` + font.pixelSize: Theme.fontSizeSmall + font.weight: Font.Bold + color: { + if (root.usagePercent > 90) + return Theme.error; + if (root.usagePercent > 75) + return Theme.warning; + return Theme.ccTileInactiveIcon; + } + } + } + } + + DankRipple { + id: ripple + cornerRadius: root.radius + } + + MouseArea { + id: mouseArea + anchors.fill: parent + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + enabled: root.enabled + onPressed: mouse => ripple.trigger(mouse.x, mouse.y) + onClicked: root.clicked() + } + + Component.onCompleted: { + DgopService.addRef(["diskmounts"]); + } + Component.onDestruction: { + DgopService.removeRef(["diskmounts"]); + } +} diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Widgets/SmallToggleButton.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Widgets/SmallToggleButton.qml new file mode 100644 index 0000000..7d86947 --- /dev/null +++ b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Widgets/SmallToggleButton.qml @@ -0,0 +1,90 @@ +import QtQuick +import qs.Common +import qs.Widgets + +Rectangle { + id: root + + property string iconName: "" + property bool isActive: false + property bool enabled: true + property real iconRotation: 0 + + signal clicked + signal iconRotationCompleted + + width: parent ? ((parent.width - parent.spacing * 3) / 4) : 48 + height: 48 + radius: { + if (Theme.cornerRadius === 0) + return 0; + return isActive ? Theme.cornerRadius : Theme.cornerRadius + 4; + } + + function hoverTint(base) { + const factor = 1.2; + return Theme.isLightMode ? Qt.darker(base, factor) : Qt.lighter(base, factor); + } + + readonly property color _tileBgActive: Theme.ccTileActiveBg + readonly property color _tileBgInactive: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency) + readonly property color _tileRingActive: Theme.ccTileRing + readonly property color _tileIconActive: Theme.ccTileActiveText + readonly property color _tileIconInactive: Theme.ccTileInactiveIcon + + color: { + if (isActive) + return _tileBgActive; + const baseColor = mouseArea.containsMouse ? Theme.primaryPressed : _tileBgInactive; + return baseColor; + } + border.color: isActive ? _tileRingActive : "transparent" + border.width: isActive ? 1 : 0 + antialiasing: true + opacity: enabled ? 1.0 : 0.6 + + Rectangle { + anchors.fill: parent + radius: parent.radius + color: hoverTint(root.color) + opacity: mouseArea.pressed ? 0.3 : (mouseArea.containsMouse ? 0.2 : 0.0) + visible: opacity > 0 + antialiasing: true + Behavior on opacity { + NumberAnimation { + duration: Theme.shortDuration + } + } + } + + DankIcon { + anchors.centerIn: parent + name: iconName + size: Theme.iconSize + color: isActive ? _tileIconActive : _tileIconInactive + rotation: iconRotation + onRotationCompleted: root.iconRotationCompleted() + } + + DankRipple { + id: ripple + cornerRadius: root.radius + } + + MouseArea { + id: mouseArea + anchors.fill: parent + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + enabled: root.enabled + onPressed: mouse => ripple.trigger(mouse.x, mouse.y) + onClicked: root.clicked() + } + + Behavior on radius { + NumberAnimation { + duration: Theme.shortDuration + easing.type: Theme.standardEasing + } + } +} diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Widgets/ToggleButton.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Widgets/ToggleButton.qml new file mode 100644 index 0000000..b8adda8 --- /dev/null +++ b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Widgets/ToggleButton.qml @@ -0,0 +1,134 @@ +import QtQuick +import qs.Common +import qs.Widgets + +Rectangle { + id: root + + LayoutMirroring.enabled: I18n.isRtl + LayoutMirroring.childrenInherit: true + + property string iconName: "" + property string text: "" + property bool isActive: false + property bool enabled: true + property string secondaryText: "" + property real iconRotation: 0 + + signal clicked + signal iconRotationCompleted + + width: parent ? parent.width : 200 + height: 60 + radius: { + if (Theme.cornerRadius === 0) + return 0; + return isActive ? Theme.cornerRadius : Theme.cornerRadius + 4; + } + + readonly property color _tileBgActive: Theme.ccTileActiveBg + readonly property color _tileBgInactive: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency) + readonly property color _tileRingActive: Theme.ccTileRing + + color: { + if (isActive) + return _tileBgActive; + const baseColor = mouseArea.containsMouse ? Theme.primaryPressed : _tileBgInactive; + return baseColor; + } + border.color: isActive ? _tileRingActive : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08) + border.width: 0 + opacity: enabled ? 1.0 : 0.6 + + function hoverTint(base) { + const factor = 1.2; + return Theme.isLightMode ? Qt.darker(base, factor) : Qt.lighter(base, factor); + } + + readonly property color _containerBg: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency) + + Rectangle { + anchors.fill: parent + radius: Theme.cornerRadius + color: mouseArea.containsMouse ? hoverTint(_containerBg) : Theme.withAlpha(_containerBg, 0) + opacity: mouseArea.containsMouse ? 0.08 : 0.0 + + Behavior on opacity { + NumberAnimation { + duration: Theme.shortDuration + } + } + } + + Row { + anchors.fill: parent + anchors.leftMargin: Theme.spacingL + 2 + anchors.rightMargin: Theme.spacingM + spacing: Theme.spacingM + + DankIcon { + name: root.iconName + size: Theme.iconSize + color: isActive ? Theme.ccTileActiveText : Theme.ccTileInactiveIcon + anchors.verticalCenter: parent.verticalCenter + rotation: root.iconRotation + onRotationCompleted: root.iconRotationCompleted() + } + + Item { + width: parent.width - Theme.iconSize - parent.spacing + height: parent.height + + Column { + anchors.left: parent.left + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + spacing: 2 + + StyledText { + width: parent.width + text: root.text + font.pixelSize: Theme.fontSizeMedium + color: isActive ? Theme.ccTileActiveText : Theme.surfaceText + font.weight: Font.Medium + elide: Text.ElideRight + wrapMode: Text.NoWrap + horizontalAlignment: Text.AlignLeft + } + + StyledText { + width: parent.width + text: root.secondaryText + font.pixelSize: Theme.fontSizeSmall + color: isActive ? Theme.ccTileActiveText : Theme.surfaceVariantText + visible: text.length > 0 + elide: Text.ElideRight + wrapMode: Text.NoWrap + horizontalAlignment: Text.AlignLeft + } + } + } + } + + DankRipple { + id: ripple + cornerRadius: root.radius + } + + MouseArea { + id: mouseArea + anchors.fill: parent + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + enabled: root.enabled + onPressed: mouse => ripple.trigger(mouse.x, mouse.y) + onClicked: root.clicked() + } + + Behavior on radius { + NumberAnimation { + duration: Theme.shortDuration + easing.type: Theme.standardEasing + } + } +} |