summaryrefslogtreecommitdiff
path: root/raveos-hyprland-theme/theme-data/dms/Modules/DankBar/Widgets/ControlCenterButton.qml
diff options
context:
space:
mode:
Diffstat (limited to 'raveos-hyprland-theme/theme-data/dms/Modules/DankBar/Widgets/ControlCenterButton.qml')
-rw-r--r--raveos-hyprland-theme/theme-data/dms/Modules/DankBar/Widgets/ControlCenterButton.qml830
1 files changed, 830 insertions, 0 deletions
diff --git a/raveos-hyprland-theme/theme-data/dms/Modules/DankBar/Widgets/ControlCenterButton.qml b/raveos-hyprland-theme/theme-data/dms/Modules/DankBar/Widgets/ControlCenterButton.qml
new file mode 100644
index 0000000..5413d20
--- /dev/null
+++ b/raveos-hyprland-theme/theme-data/dms/Modules/DankBar/Widgets/ControlCenterButton.qml
@@ -0,0 +1,830 @@
+pragma ComponentBehavior: Bound
+import QtQuick
+import Quickshell
+import qs.Common
+import qs.Modules.Plugins
+import qs.Services
+import qs.Widgets
+
+BasePill {
+ id: root
+
+ property bool isActive: false
+ property var popoutTarget: null
+ property var widgetData: null
+ property string screenName: ""
+ property string screenModel: ""
+ property bool showNetworkIcon: widgetData?.showNetworkIcon !== undefined ? widgetData.showNetworkIcon : SettingsData.controlCenterShowNetworkIcon
+ property bool showBluetoothIcon: widgetData?.showBluetoothIcon !== undefined ? widgetData.showBluetoothIcon : SettingsData.controlCenterShowBluetoothIcon
+ property bool showAudioIcon: widgetData?.showAudioIcon !== undefined ? widgetData.showAudioIcon : SettingsData.controlCenterShowAudioIcon
+ property bool showAudioPercent: widgetData?.showAudioPercent !== undefined ? widgetData.showAudioPercent : SettingsData.controlCenterShowAudioPercent
+ property bool showVpnIcon: widgetData?.showVpnIcon !== undefined ? widgetData.showVpnIcon : SettingsData.controlCenterShowVpnIcon
+ property bool showBrightnessIcon: widgetData?.showBrightnessIcon !== undefined ? widgetData.showBrightnessIcon : SettingsData.controlCenterShowBrightnessIcon
+ property bool showBrightnessPercent: widgetData?.showBrightnessPercent !== undefined ? widgetData.showBrightnessPercent : SettingsData.controlCenterShowBrightnessPercent
+ property bool showMicIcon: widgetData?.showMicIcon !== undefined ? widgetData.showMicIcon : SettingsData.controlCenterShowMicIcon
+ property bool showMicPercent: widgetData?.showMicPercent !== undefined ? widgetData.showMicPercent : SettingsData.controlCenterShowMicPercent
+ property bool showBatteryIcon: widgetData?.showBatteryIcon !== undefined ? widgetData.showBatteryIcon : SettingsData.controlCenterShowBatteryIcon
+ property bool showPrinterIcon: widgetData?.showPrinterIcon !== undefined ? widgetData.showPrinterIcon : SettingsData.controlCenterShowPrinterIcon
+ property bool showScreenSharingIcon: widgetData?.showScreenSharingIcon !== undefined ? widgetData.showScreenSharingIcon : SettingsData.controlCenterShowScreenSharingIcon
+ property real touchpadThreshold: 100
+ property real micAccumulator: 0
+ property real volumeAccumulator: 0
+ property real brightnessAccumulator: 0
+ readonly property real vIconSize: Theme.barIconSize(root.barThickness, -4, root.barConfig?.maximizeWidgetIcons, root.barConfig?.iconScale)
+ property var _hRow: null
+ property var _vCol: null
+ property var _hAudio: null
+ property var _hBrightness: null
+ property var _hMic: null
+ property var _vAudio: null
+ property var _vBrightness: null
+ property var _vMic: null
+ property var _interactionDelegates: []
+ readonly property var defaultControlCenterGroupOrder: ["network", "vpn", "bluetooth", "audio", "microphone", "brightness", "battery", "printer", "screenSharing"]
+ readonly property var effectiveControlCenterGroupOrder: getEffectiveControlCenterGroupOrder()
+ readonly property var controlCenterRenderModel: getControlCenterRenderModel()
+
+ onIsVerticalOrientationChanged: root.clearInteractionRefs()
+
+ onWheel: function (wheelEvent) {
+ const delta = wheelEvent.angleDelta.y;
+ if (delta === 0)
+ return;
+
+ root.refreshInteractionRefs();
+
+ const rootX = wheelEvent.x - root.leftMargin;
+ const rootY = wheelEvent.y - root.topMargin;
+
+ if (root.isVerticalOrientation && _vCol) {
+ const pos = root.mapToItem(_vCol, rootX, rootY);
+ if (_vBrightness?.visible && pos.y >= _vBrightness.y && pos.y < _vBrightness.y + _vBrightness.height) {
+ root.handleBrightnessWheel(delta);
+ } else if (_vMic?.visible && pos.y >= _vMic.y && pos.y < _vMic.y + _vMic.height) {
+ root.handleMicWheel(delta);
+ } else {
+ root.handleVolumeWheel(delta);
+ }
+ } else if (_hRow) {
+ const pos = root.mapToItem(_hRow, rootX, rootY);
+ if (_hBrightness?.visible && pos.x >= _hBrightness.x && pos.x < _hBrightness.x + _hBrightness.width) {
+ root.handleBrightnessWheel(delta);
+ } else if (_hMic?.visible && pos.x >= _hMic.x && pos.x < _hMic.x + _hMic.width) {
+ root.handleMicWheel(delta);
+ } else {
+ root.handleVolumeWheel(delta);
+ }
+ } else {
+ root.handleVolumeWheel(delta);
+ }
+ wheelEvent.accepted = true;
+ }
+
+ onRightClicked: function (rootX, rootY) {
+ root.refreshInteractionRefs();
+
+ if (root.isVerticalOrientation && _vCol) {
+ const pos = root.mapToItem(_vCol, rootX, rootY);
+ if (_vAudio?.visible && pos.y >= _vAudio.y && pos.y < _vAudio.y + _vAudio.height) {
+ AudioService.toggleMute();
+ return;
+ }
+ if (_vMic?.visible && pos.y >= _vMic.y && pos.y < _vMic.y + _vMic.height) {
+ AudioService.toggleMicMute();
+ return;
+ }
+ } else if (_hRow) {
+ const pos = root.mapToItem(_hRow, rootX, rootY);
+ if (_hAudio?.visible && pos.x >= _hAudio.x && pos.x < _hAudio.x + _hAudio.width) {
+ AudioService.toggleMute();
+ return;
+ }
+ if (_hMic?.visible && pos.x >= _hMic.x && pos.x < _hMic.x + _hMic.width) {
+ AudioService.toggleMicMute();
+ return;
+ }
+ }
+ }
+
+ Loader {
+ active: root.showPrinterIcon
+ sourceComponent: Component {
+ Ref {
+ service: CupsService
+ }
+ }
+ }
+
+ function getNetworkIconName() {
+ if (NetworkService.wifiToggling)
+ return "sync";
+ switch (NetworkService.networkStatus) {
+ case "ethernet":
+ return "lan";
+ case "vpn":
+ return NetworkService.ethernetConnected ? "lan" : NetworkService.wifiSignalIcon;
+ default:
+ return NetworkService.wifiSignalIcon;
+ }
+ }
+
+ function getNetworkIconColor() {
+ if (NetworkService.wifiToggling)
+ return Theme.primary;
+ return NetworkService.networkStatus !== "disconnected" ? Theme.primary : Theme.surfaceText;
+ }
+
+ function getVolumeIconName() {
+ if (!AudioService.sink?.audio)
+ return "volume_up";
+ if (AudioService.sink.audio.muted)
+ return "volume_off";
+ if (AudioService.sink.audio.volume === 0)
+ return "volume_mute";
+ if (AudioService.sink.audio.volume * 100 < 33)
+ return "volume_down";
+ return "volume_up";
+ }
+
+ function getMicIconName() {
+ if (!AudioService.source?.audio)
+ return "mic";
+ if (AudioService.source.audio.muted || AudioService.source.audio.volume === 0)
+ return "mic_off";
+ return "mic";
+ }
+
+ function getMicIconColor() {
+ if (!AudioService.source?.audio)
+ return Theme.surfaceText;
+ if (AudioService.source.audio.muted || AudioService.source.audio.volume === 0)
+ return Theme.surfaceText;
+ return Theme.widgetIconColor;
+ }
+
+ function getBrightnessIconName() {
+ const deviceName = getPinnedBrightnessDevice();
+ if (!deviceName)
+ return "brightness_medium";
+ const level = DisplayService.getDeviceBrightness(deviceName);
+ if (level <= 33)
+ return "brightness_low";
+ if (level <= 66)
+ return "brightness_medium";
+ return "brightness_high";
+ }
+
+ function getScreenPinKey() {
+ if (!root.screenName)
+ return "";
+ const screen = Quickshell.screens.find(s => s.name === root.screenName);
+ if (screen) {
+ return SettingsData.getScreenDisplayName(screen);
+ }
+ if (SettingsData.displayNameMode === "model" && root.screenModel && root.screenModel.length > 0) {
+ return root.screenModel;
+ }
+ return root.screenName;
+ }
+
+ function getPinnedBrightnessDevice() {
+ const pinKey = getScreenPinKey();
+ if (!pinKey)
+ return "";
+ const pins = SettingsData.brightnessDevicePins || {};
+ return pins[pinKey] || "";
+ }
+
+ function hasPinnedBrightnessDevice() {
+ return getPinnedBrightnessDevice().length > 0;
+ }
+
+ function handleVolumeWheel(delta) {
+ if (!AudioService.sink?.audio)
+ return;
+
+ var step = 5;
+ const isMouseWheel = Math.abs(delta) >= 120 && (Math.abs(delta) % 120) === 0;
+ if (!isMouseWheel) {
+ step = 1;
+ volumeAccumulator += delta;
+ if (Math.abs(volumeAccumulator) < touchpadThreshold)
+ return;
+
+ delta = volumeAccumulator;
+ volumeAccumulator = 0;
+ }
+
+ const maxVol = AudioService.sinkMaxVolume;
+ const currentVolume = AudioService.sink.audio.volume * 100;
+ const newVolume = delta > 0 ? Math.min(maxVol, currentVolume + step) : Math.max(0, currentVolume - step);
+ AudioService.sink.audio.muted = false;
+ AudioService.sink.audio.volume = newVolume / 100;
+ AudioService.playVolumeChangeSoundIfEnabled();
+ }
+
+ function handleMicWheel(delta) {
+ if (!AudioService.source?.audio)
+ return;
+
+ var step = 5;
+ const isMouseWheel = Math.abs(delta) >= 120 && (Math.abs(delta) % 120) === 0;
+ if (!isMouseWheel) {
+ step = 1;
+ micAccumulator += delta;
+ if (Math.abs(micAccumulator) < touchpadThreshold)
+ return;
+
+ delta = micAccumulator;
+ micAccumulator = 0;
+ }
+
+ const currentVolume = AudioService.source.audio.volume * 100;
+ const newVolume = delta > 0 ? Math.min(100, currentVolume + step) : Math.max(0, currentVolume - step);
+ AudioService.source.audio.muted = false;
+ AudioService.source.audio.volume = newVolume / 100;
+ }
+
+ function handleBrightnessWheel(delta) {
+ const deviceName = getPinnedBrightnessDevice();
+ if (!deviceName) {
+ return;
+ }
+
+ var step = 5;
+ const isMouseWheel = Math.abs(delta) >= 120 && (Math.abs(delta) % 120) === 0;
+ if (!isMouseWheel) {
+ step = 1;
+ brightnessAccumulator += delta;
+ if (Math.abs(brightnessAccumulator) < touchpadThreshold)
+ return;
+
+ delta = brightnessAccumulator;
+ brightnessAccumulator = 0;
+ }
+
+ const currentBrightness = DisplayService.getDeviceBrightness(deviceName);
+ const newBrightness = delta > 0 ? Math.min(100, currentBrightness + step) : Math.max(1, currentBrightness - step);
+ DisplayService.setBrightness(newBrightness, deviceName);
+ }
+
+ function getBrightness() {
+ const deviceName = getPinnedBrightnessDevice();
+ if (!deviceName) {
+ return;
+ }
+ return DisplayService.getDeviceBrightness(deviceName) / 100;
+ }
+
+ function getBatteryIconColor() {
+ if (!BatteryService.batteryAvailable)
+ return Theme.widgetIconColor;
+ if (BatteryService.isLowBattery && !BatteryService.isCharging)
+ return Theme.error;
+ if (BatteryService.isCharging || BatteryService.isPluggedIn)
+ return Theme.primary;
+ return Theme.widgetIconColor;
+ }
+
+ function hasPrintJobs() {
+ return CupsService.getTotalJobsNum() > 0;
+ }
+
+ function getControlCenterIconSize() {
+ return Theme.barIconSize(root.barThickness, -4, root.barConfig?.maximizeWidgetIcons, root.barConfig?.iconScale);
+ }
+
+ function getEffectiveControlCenterGroupOrder() {
+ const knownIds = root.defaultControlCenterGroupOrder;
+ const savedOrder = root.widgetData?.controlCenterGroupOrder;
+ const result = [];
+ const seen = {};
+
+ if (savedOrder && typeof savedOrder.length === "number") {
+ for (let i = 0; i < savedOrder.length; ++i) {
+ const groupId = savedOrder[i];
+ if (knownIds.indexOf(groupId) === -1 || seen[groupId])
+ continue;
+
+ seen[groupId] = true;
+ result.push(groupId);
+ }
+ }
+
+ for (let i = 0; i < knownIds.length; ++i) {
+ const groupId = knownIds[i];
+ if (seen[groupId])
+ continue;
+
+ seen[groupId] = true;
+ result.push(groupId);
+ }
+
+ return result;
+ }
+
+ function isGroupVisible(groupId) {
+ switch (groupId) {
+ case "screenSharing":
+ return root.showScreenSharingIcon && NiriService.hasCasts;
+ case "network":
+ return root.showNetworkIcon && NetworkService.networkAvailable;
+ case "vpn":
+ return root.showVpnIcon && NetworkService.vpnAvailable && NetworkService.vpnConnected;
+ case "bluetooth":
+ return root.showBluetoothIcon && BluetoothService.available && BluetoothService.enabled;
+ case "audio":
+ return root.showAudioIcon;
+ case "microphone":
+ return root.showMicIcon;
+ case "brightness":
+ return root.showBrightnessIcon && DisplayService.brightnessAvailable && root.hasPinnedBrightnessDevice();
+ case "battery":
+ return root.showBatteryIcon && BatteryService.batteryAvailable;
+ case "printer":
+ return root.showPrinterIcon && CupsService.cupsAvailable && root.hasPrintJobs();
+ default:
+ return false;
+ }
+ }
+
+ function isCompositeGroup(groupId) {
+ return groupId === "audio" || groupId === "microphone" || groupId === "brightness";
+ }
+
+ function getControlCenterRenderModel() {
+ return root.effectiveControlCenterGroupOrder.map(groupId => ({
+ "id": groupId,
+ "visible": root.isGroupVisible(groupId),
+ "composite": root.isCompositeGroup(groupId)
+ }));
+ }
+
+ function clearInteractionRefs() {
+ root._hAudio = null;
+ root._hBrightness = null;
+ root._hMic = null;
+ root._vAudio = null;
+ root._vBrightness = null;
+ root._vMic = null;
+ }
+
+ function registerInteractionDelegate(isVertical, item) {
+ if (!item)
+ return;
+
+ for (let i = 0; i < root._interactionDelegates.length; ++i) {
+ const entry = root._interactionDelegates[i];
+ if (entry && entry.item === item) {
+ entry.isVertical = isVertical;
+ return;
+ }
+ }
+
+ root._interactionDelegates = root._interactionDelegates.concat([
+ {
+ "isVertical": isVertical,
+ "item": item
+ }
+ ]);
+ }
+
+ function unregisterInteractionDelegate(item) {
+ if (!item)
+ return;
+
+ root._interactionDelegates = root._interactionDelegates.filter(entry => entry && entry.item !== item);
+ }
+
+ function refreshInteractionRefs() {
+ root.clearInteractionRefs();
+
+ for (let i = 0; i < root._interactionDelegates.length; ++i) {
+ const entry = root._interactionDelegates[i];
+ const item = entry?.item;
+ if (!item || !item.visible)
+ continue;
+
+ const groupId = item.interactionGroupId;
+ if (entry.isVertical) {
+ if (groupId === "audio")
+ root._vAudio = item;
+ else if (groupId === "microphone")
+ root._vMic = item;
+ else if (groupId === "brightness")
+ root._vBrightness = item;
+ } else {
+ if (groupId === "audio")
+ root._hAudio = item;
+ else if (groupId === "microphone")
+ root._hMic = item;
+ else if (groupId === "brightness")
+ root._hBrightness = item;
+ }
+ }
+ }
+
+ function hasNoVisibleIcons() {
+ return !root.controlCenterRenderModel.some(entry => entry.visible);
+ }
+
+ content: Component {
+ Item {
+ implicitWidth: root.isVerticalOrientation ? (root.widgetThickness - root.horizontalPadding * 2) : controlIndicators.implicitWidth
+ implicitHeight: root.isVerticalOrientation ? controlColumn.implicitHeight : (root.widgetThickness - root.horizontalPadding * 2)
+
+ Component.onCompleted: {
+ root._hRow = controlIndicators;
+ root._vCol = controlColumn;
+ root.clearInteractionRefs();
+ }
+
+ Column {
+ id: controlColumn
+ visible: root.isVerticalOrientation
+ width: parent.width
+ anchors.horizontalCenter: parent.horizontalCenter
+ spacing: Theme.spacingXS
+
+ Repeater {
+ model: root.controlCenterRenderModel
+ Item {
+ id: verticalGroupItem
+ required property var modelData
+ required property int index
+ property string interactionGroupId: modelData.id
+
+ width: parent.width
+ height: {
+ switch (modelData.id) {
+ case "audio":
+ return root.vIconSize + (audioPercentV.visible ? audioPercentV.implicitHeight + 2 : 0);
+ case "microphone":
+ return root.vIconSize + (micPercentV.visible ? micPercentV.implicitHeight + 2 : 0);
+ case "brightness":
+ return root.vIconSize + (brightnessPercentV.visible ? brightnessPercentV.implicitHeight + 2 : 0);
+ default:
+ return root.vIconSize;
+ }
+ }
+ visible: modelData.visible
+
+ Component.onCompleted: {
+ root.registerInteractionDelegate(true, verticalGroupItem);
+ root.refreshInteractionRefs();
+ }
+ Component.onDestruction: {
+ if (root) {
+ root.unregisterInteractionDelegate(verticalGroupItem);
+ root.refreshInteractionRefs();
+ }
+ }
+ onVisibleChanged: root.refreshInteractionRefs()
+ onInteractionGroupIdChanged: {
+ root.refreshInteractionRefs();
+ }
+
+ DankIcon {
+ anchors.centerIn: parent
+ visible: !verticalGroupItem.modelData.composite
+ name: {
+ switch (verticalGroupItem.modelData.id) {
+ case "screenSharing":
+ return "screen_record";
+ case "network":
+ return root.getNetworkIconName();
+ case "vpn":
+ return "vpn_lock";
+ case "bluetooth":
+ return "bluetooth";
+ case "battery":
+ return Theme.getBatteryIcon(BatteryService.batteryLevel, BatteryService.isCharging, BatteryService.batteryAvailable);
+ case "printer":
+ return "print";
+ default:
+ return "settings";
+ }
+ }
+ size: root.vIconSize
+ color: {
+ switch (verticalGroupItem.modelData.id) {
+ case "screenSharing":
+ return NiriService.hasActiveCast ? Theme.primary : Theme.surfaceText;
+ case "network":
+ return root.getNetworkIconColor();
+ case "vpn":
+ return NetworkService.vpnConnected ? Theme.primary : Theme.surfaceText;
+ case "bluetooth":
+ return BluetoothService.connected ? Theme.primary : Theme.surfaceText;
+ case "battery":
+ return root.getBatteryIconColor();
+ case "printer":
+ return Theme.primary;
+ default:
+ return Theme.widgetIconColor;
+ }
+ }
+ }
+
+ DankIcon {
+ id: audioIconV
+ visible: verticalGroupItem.modelData.id === "audio"
+ name: root.getVolumeIconName()
+ size: root.vIconSize
+ color: Theme.widgetIconColor
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.top: parent.top
+ }
+
+ NumericText {
+ id: audioPercentV
+ visible: verticalGroupItem.modelData.id === "audio" && root.showAudioPercent && isFinite(AudioService.sink?.audio?.volume)
+ text: Math.round((AudioService.sink?.audio?.volume ?? 0) * 100) + "%"
+ reserveText: "100%"
+ font.pixelSize: Theme.barTextSize(root.barThickness, root.barConfig?.fontScale, root.barConfig?.maximizeWidgetText)
+ color: Theme.widgetTextColor
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.top: audioIconV.bottom
+ anchors.topMargin: 2
+ }
+
+ DankIcon {
+ id: micIconV
+ visible: verticalGroupItem.modelData.id === "microphone"
+ name: root.getMicIconName()
+ size: root.vIconSize
+ color: root.getMicIconColor()
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.top: parent.top
+ }
+
+ NumericText {
+ id: micPercentV
+ visible: verticalGroupItem.modelData.id === "microphone" && root.showMicPercent && isFinite(AudioService.source?.audio?.volume)
+ text: Math.round((AudioService.source?.audio?.volume ?? 0) * 100) + "%"
+ reserveText: "100%"
+ font.pixelSize: Theme.barTextSize(root.barThickness, root.barConfig?.fontScale, root.barConfig?.maximizeWidgetText)
+ color: Theme.widgetTextColor
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.top: micIconV.bottom
+ anchors.topMargin: 2
+ }
+
+ DankIcon {
+ id: brightnessIconV
+ visible: verticalGroupItem.modelData.id === "brightness"
+ name: root.getBrightnessIconName()
+ size: root.vIconSize
+ color: Theme.widgetIconColor
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.top: parent.top
+ }
+
+ NumericText {
+ id: brightnessPercentV
+ visible: verticalGroupItem.modelData.id === "brightness" && root.showBrightnessPercent && isFinite(getBrightness())
+ text: Math.round(getBrightness() * 100) + "%"
+ reserveText: "100%"
+ font.pixelSize: Theme.barTextSize(root.barThickness, root.barConfig?.fontScale, root.barConfig?.maximizeWidgetText)
+ color: Theme.widgetTextColor
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.top: brightnessIconV.bottom
+ anchors.topMargin: 2
+ }
+ }
+ }
+
+ Item {
+ width: parent.width
+ height: root.vIconSize
+ visible: root.hasNoVisibleIcons()
+
+ DankIcon {
+ name: "settings"
+ size: root.vIconSize
+ color: root.isActive ? Theme.primary : Theme.widgetIconColor
+ anchors.centerIn: parent
+ }
+ }
+ }
+
+ Row {
+ id: controlIndicators
+ visible: !root.isVerticalOrientation
+ anchors.centerIn: parent
+ spacing: Theme.spacingXS
+
+ Repeater {
+ model: root.controlCenterRenderModel
+
+ Item {
+ id: horizontalGroupItem
+ required property var modelData
+ required property int index
+ property string interactionGroupId: modelData.id
+
+ width: {
+ switch (modelData.id) {
+ case "audio":
+ return audioGroup.width;
+ case "microphone":
+ return micGroup.width;
+ case "brightness":
+ return brightnessGroup.width;
+ default:
+ return root.getControlCenterIconSize();
+ }
+ }
+ implicitWidth: width
+ height: root.widgetThickness - root.horizontalPadding * 2
+ visible: modelData.visible
+
+ Component.onCompleted: {
+ root.registerInteractionDelegate(false, horizontalGroupItem);
+ root.refreshInteractionRefs();
+ }
+ Component.onDestruction: {
+ if (root) {
+ root.unregisterInteractionDelegate(horizontalGroupItem);
+ root.refreshInteractionRefs();
+ }
+ }
+ onVisibleChanged: root.refreshInteractionRefs()
+ onInteractionGroupIdChanged: {
+ root.refreshInteractionRefs();
+ }
+
+ DankIcon {
+ id: iconOnlyItem
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.left: parent.left
+ visible: !horizontalGroupItem.modelData.composite
+ name: {
+ switch (horizontalGroupItem.modelData.id) {
+ case "screenSharing":
+ return "screen_record";
+ case "network":
+ return root.getNetworkIconName();
+ case "vpn":
+ return "vpn_lock";
+ case "bluetooth":
+ return "bluetooth";
+ case "battery":
+ return Theme.getBatteryIcon(BatteryService.batteryLevel, BatteryService.isCharging, BatteryService.batteryAvailable);
+ case "printer":
+ return "print";
+ default:
+ return "settings";
+ }
+ }
+ size: root.getControlCenterIconSize()
+ color: {
+ switch (horizontalGroupItem.modelData.id) {
+ case "screenSharing":
+ return NiriService.hasActiveCast ? Theme.primary : Theme.surfaceText;
+ case "network":
+ return root.getNetworkIconColor();
+ case "vpn":
+ return NetworkService.vpnConnected ? Theme.primary : Theme.surfaceText;
+ case "bluetooth":
+ return BluetoothService.connected ? Theme.primary : Theme.surfaceText;
+ case "battery":
+ return root.getBatteryIconColor();
+ case "printer":
+ return Theme.primary;
+ default:
+ return Theme.widgetIconColor;
+ }
+ }
+ }
+
+ Rectangle {
+ id: audioGroup
+ width: audioContent.implicitWidth + 2
+ implicitWidth: width
+ height: parent.height
+ color: "transparent"
+ anchors.verticalCenter: parent.verticalCenter
+ visible: horizontalGroupItem.modelData.id === "audio"
+
+ Row {
+ id: audioContent
+ anchors.left: parent.left
+ anchors.leftMargin: 1
+ anchors.verticalCenter: parent.verticalCenter
+ spacing: 2
+
+ DankIcon {
+ id: audioIcon
+ name: root.getVolumeIconName()
+ size: root.getControlCenterIconSize()
+ color: Theme.widgetIconColor
+ anchors.verticalCenter: parent.verticalCenter
+ }
+
+ NumericText {
+ id: audioPercent
+ visible: root.showAudioPercent && isFinite(AudioService.sink?.audio?.volume)
+ text: Math.round((AudioService.sink?.audio?.volume ?? 0) * 100) + "%"
+ reserveText: "100%"
+ font.pixelSize: Theme.barTextSize(root.barThickness, root.barConfig?.fontScale, root.barConfig?.maximizeWidgetText)
+ color: Theme.widgetTextColor
+ anchors.verticalCenter: parent.verticalCenter
+ width: visible ? implicitWidth : 0
+ }
+ }
+ }
+
+ Rectangle {
+ id: micGroup
+ width: micContent.implicitWidth + 2
+ implicitWidth: width
+ height: parent.height
+ color: "transparent"
+ anchors.verticalCenter: parent.verticalCenter
+ visible: horizontalGroupItem.modelData.id === "microphone"
+
+ Row {
+ id: micContent
+ anchors.left: parent.left
+ anchors.leftMargin: 1
+ anchors.verticalCenter: parent.verticalCenter
+ spacing: 2
+
+ DankIcon {
+ id: micIcon
+ name: root.getMicIconName()
+ size: root.getControlCenterIconSize()
+ color: root.getMicIconColor()
+ anchors.verticalCenter: parent.verticalCenter
+ }
+
+ NumericText {
+ id: micPercent
+ visible: root.showMicPercent && isFinite(AudioService.source?.audio?.volume)
+ text: Math.round((AudioService.source?.audio?.volume ?? 0) * 100) + "%"
+ reserveText: "100%"
+ font.pixelSize: Theme.barTextSize(root.barThickness, root.barConfig?.fontScale, root.barConfig?.maximizeWidgetText)
+ color: Theme.widgetTextColor
+ anchors.verticalCenter: parent.verticalCenter
+ width: visible ? implicitWidth : 0
+ }
+ }
+ }
+
+ Rectangle {
+ id: brightnessGroup
+ width: brightnessContent.implicitWidth + 2
+ implicitWidth: width
+ height: parent.height
+ color: "transparent"
+ anchors.verticalCenter: parent.verticalCenter
+ visible: horizontalGroupItem.modelData.id === "brightness"
+
+ Row {
+ id: brightnessContent
+ anchors.left: parent.left
+ anchors.leftMargin: 1
+ anchors.verticalCenter: parent.verticalCenter
+ spacing: 2
+
+ DankIcon {
+ id: brightnessIcon
+ name: root.getBrightnessIconName()
+ size: root.getControlCenterIconSize()
+ color: Theme.widgetIconColor
+ anchors.verticalCenter: parent.verticalCenter
+ }
+
+ NumericText {
+ id: brightnessPercent
+ visible: root.showBrightnessPercent && isFinite(getBrightness())
+ text: Math.round(getBrightness() * 100) + "%"
+ reserveText: "100%"
+ font.pixelSize: Theme.barTextSize(root.barThickness, root.barConfig?.fontScale, root.barConfig?.maximizeWidgetText)
+ color: Theme.widgetTextColor
+ anchors.verticalCenter: parent.verticalCenter
+ width: visible ? implicitWidth : 0
+ }
+ }
+ }
+ }
+ }
+
+ DankIcon {
+ name: "settings"
+ size: root.getControlCenterIconSize()
+ color: root.isActive ? Theme.primary : Theme.widgetIconColor
+ anchors.verticalCenter: parent.verticalCenter
+ visible: root.hasNoVisibleIcons()
+ }
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ cursorShape: Qt.PointingHandCursor
+ acceptedButtons: Qt.NoButton
+ }
+ }
+ }
+}