1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2025-12-06 21:45:38 -05:00

replace qmlformat with a better tool

still not perfect, but well - what can ya do
This commit is contained in:
bbedward
2025-08-08 15:55:37 -04:00
parent 8dc6e2805d
commit 4d408c65f2
137 changed files with 30315 additions and 29625 deletions

View File

@@ -4,66 +4,66 @@ import qs.Common
import qs.Services
Item {
id: root
id: root
readonly property MprisPlayer activePlayer: MprisController.activePlayer
readonly property bool hasActiveMedia: activePlayer !== null
readonly property bool isPlaying: hasActiveMedia && activePlayer && activePlayer.playbackState === MprisPlaybackState.Playing
readonly property MprisPlayer activePlayer: MprisController.activePlayer
readonly property bool hasActiveMedia: activePlayer !== null
readonly property bool isPlaying: hasActiveMedia && activePlayer
&& activePlayer.playbackState === MprisPlaybackState.Playing
width: 20
height: Theme.iconSize
width: 20
height: Theme.iconSize
Ref {
service: CavaService
Ref {
service: CavaService
}
Timer {
id: fallbackTimer
running: !CavaService.cavaAvailable && isPlaying
interval: 256
repeat: true
onTriggered: {
CavaService.values = [Math.random() * 40 + 10, Math.random(
) * 60 + 20, Math.random() * 50 + 15, Math.random(
) * 35 + 20, Math.random() * 45 + 15, Math.random(
) * 55 + 25]
}
}
Timer {
id: fallbackTimer
Row {
anchors.centerIn: parent
spacing: 1.5
running: !CavaService.cavaAvailable && isPlaying
interval: 256
repeat: true
onTriggered: {
CavaService.values = [Math.random() * 40 + 10, Math.random() * 60 + 20, Math.random() * 50 + 15, Math.random() * 35 + 20, Math.random() * 45 + 15, Math.random() * 55 + 25];
Repeater {
model: 6
Rectangle {
width: 2
height: {
if (root.isPlaying && CavaService.values.length > index) {
const rawLevel = CavaService.values[index] || 0
const scaledLevel = Math.sqrt(Math.min(Math.max(rawLevel, 0),
100) / 100) * 100
const maxHeight = Theme.iconSize - 2
const minHeight = 3
return minHeight + (scaledLevel / 100) * (maxHeight - minHeight)
}
return 3
}
}
Row {
anchors.centerIn: parent
spacing: 1.5
Repeater {
model: 6
Rectangle {
width: 2
height: {
if (root.isPlaying && CavaService.values.length > index) {
const rawLevel = CavaService.values[index] || 0;
const scaledLevel = Math.sqrt(Math.min(Math.max(rawLevel, 0), 100) / 100) * 100;
const maxHeight = Theme.iconSize - 2;
const minHeight = 3;
return minHeight + (scaledLevel / 100) * (maxHeight - minHeight);
}
return 3;
}
radius: 1.5
color: Theme.primary
anchors.verticalCenter: parent.verticalCenter
Behavior on height {
NumberAnimation {
duration: Anims.durShort
easing.type: Easing.BezierSpline
easing.bezierCurve: Anims.standardDecel
}
}
}
radius: 1.5
color: Theme.primary
anchors.verticalCenter: parent.verticalCenter
Behavior on height {
NumberAnimation {
duration: Anims.durShort
easing.type: Easing.BezierSpline
easing.bezierCurve: Anims.standardDecel
}
}
}
}
}
}

View File

@@ -5,174 +5,172 @@ import qs.Services
import qs.Widgets
Rectangle {
id: battery
id: battery
property bool batteryPopupVisible: false
property string section: "right"
property var popupTarget: null
property var parentScreen: null
property bool batteryPopupVisible: false
property string section: "right"
property var popupTarget: null
property var parentScreen: null
signal toggleBatteryPopup()
signal toggleBatteryPopup
width: BatteryService.batteryAvailable ? 70 : 40
height: 30
width: BatteryService.batteryAvailable ? 70 : 40
height: 30
radius: Theme.cornerRadius
color: {
const baseColor = batteryArea.containsMouse
|| batteryPopupVisible ? Theme.primaryPressed : Theme.secondaryHover
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
}
visible: true
Row {
anchors.centerIn: parent
spacing: 4
DankIcon {
name: Theme.getBatteryIcon(BatteryService.batteryLevel,
BatteryService.isCharging,
BatteryService.batteryAvailable)
size: Theme.iconSize - 6
color: {
if (!BatteryService.batteryAvailable)
return Theme.surfaceText
if (BatteryService.isLowBattery && !BatteryService.isCharging)
return Theme.error
if (BatteryService.isCharging)
return Theme.primary
return Theme.surfaceText
}
anchors.verticalCenter: parent.verticalCenter
SequentialAnimation on opacity {
running: BatteryService.isCharging
loops: Animation.Infinite
NumberAnimation {
to: 0.6
duration: Anims.durLong
easing.type: Easing.BezierSpline
easing.bezierCurve: Anims.standard
}
NumberAnimation {
to: 1
duration: Anims.durLong
easing.type: Easing.BezierSpline
easing.bezierCurve: Anims.standard
}
}
}
StyledText {
text: BatteryService.batteryLevel + "%"
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
color: {
if (!BatteryService.batteryAvailable)
return Theme.surfaceText
if (BatteryService.isLowBattery && !BatteryService.isCharging)
return Theme.error
if (BatteryService.isCharging)
return Theme.primary
return Theme.surfaceText
}
anchors.verticalCenter: parent.verticalCenter
visible: BatteryService.batteryAvailable
}
}
MouseArea {
id: batteryArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
if (popupTarget && popupTarget.setTriggerPosition) {
var globalPos = mapToGlobal(0, 0)
var currentScreen = parentScreen || Screen
var screenX = currentScreen.x || 0
var relativeX = globalPos.x - screenX
popupTarget.setTriggerPosition(relativeX,
Theme.barHeight + Theme.spacingXS,
width, section, currentScreen)
}
toggleBatteryPopup()
}
}
Rectangle {
id: batteryTooltip
width: Math.max(120, tooltipText.contentWidth + Theme.spacingM * 2)
height: tooltipText.contentHeight + Theme.spacingS * 2
radius: Theme.cornerRadius
color: {
const baseColor = batteryArea.containsMouse || batteryPopupVisible ? Theme.primaryPressed : Theme.secondaryHover;
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
}
visible: true
color: Theme.surfaceContainer
border.color: Theme.surfaceVariantAlpha
border.width: 1
visible: batteryArea.containsMouse && !batteryPopupVisible
anchors.bottom: parent.top
anchors.bottomMargin: Theme.spacingS
anchors.horizontalCenter: parent.horizontalCenter
opacity: batteryArea.containsMouse ? 1 : 0
Row {
anchors.centerIn: parent
spacing: 4
Column {
anchors.centerIn: parent
spacing: 2
DankIcon {
name: Theme.getBatteryIcon(BatteryService.batteryLevel, BatteryService.isCharging, BatteryService.batteryAvailable)
size: Theme.iconSize - 6
color: {
if (!BatteryService.batteryAvailable)
return Theme.surfaceText;
StyledText {
id: tooltipText
if (BatteryService.isLowBattery && !BatteryService.isCharging)
return Theme.error;
text: {
if (!BatteryService.batteryAvailable) {
if (typeof PowerProfiles === "undefined")
return "Power Management"
if (BatteryService.isCharging)
return Theme.primary;
return Theme.surfaceText;
switch (PowerProfiles.profile) {
case PowerProfile.PowerSaver:
return "Power Profile: Power Saver"
case PowerProfile.Performance:
return "Power Profile: Performance"
default:
return "Power Profile: Balanced"
}
anchors.verticalCenter: parent.verticalCenter
SequentialAnimation on opacity {
running: BatteryService.isCharging
loops: Animation.Infinite
NumberAnimation {
to: 0.6
duration: Anims.durLong
easing.type: Easing.BezierSpline
easing.bezierCurve: Anims.standard
}
NumberAnimation {
to: 1
duration: Anims.durLong
easing.type: Easing.BezierSpline
easing.bezierCurve: Anims.standard
}
}
}
let status = BatteryService.batteryStatus
let level = BatteryService.batteryLevel + "%"
let time = BatteryService.formatTimeRemaining()
if (time !== "Unknown")
return status + " • " + level + " • " + time
else
return status + " • " + level
}
StyledText {
text: BatteryService.batteryLevel + "%"
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
color: {
if (!BatteryService.batteryAvailable)
return Theme.surfaceText;
if (BatteryService.isLowBattery && !BatteryService.isCharging)
return Theme.error;
if (BatteryService.isCharging)
return Theme.primary;
return Theme.surfaceText;
}
anchors.verticalCenter: parent.verticalCenter
visible: BatteryService.batteryAvailable
}
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
horizontalAlignment: Text.AlignHCenter
}
}
MouseArea {
id: batteryArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
if (popupTarget && popupTarget.setTriggerPosition) {
var globalPos = mapToGlobal(0, 0);
var currentScreen = parentScreen || Screen;
var screenX = currentScreen.x || 0;
var relativeX = globalPos.x - screenX;
popupTarget.setTriggerPosition(relativeX, Theme.barHeight + Theme.spacingXS, width, section, currentScreen);
}
toggleBatteryPopup();
}
Behavior on opacity {
NumberAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}
Rectangle {
id: batteryTooltip
width: Math.max(120, tooltipText.contentWidth + Theme.spacingM * 2)
height: tooltipText.contentHeight + Theme.spacingS * 2
radius: Theme.cornerRadius
color: Theme.surfaceContainer
border.color: Theme.surfaceVariantAlpha
border.width: 1
visible: batteryArea.containsMouse && !batteryPopupVisible
anchors.bottom: parent.top
anchors.bottomMargin: Theme.spacingS
anchors.horizontalCenter: parent.horizontalCenter
opacity: batteryArea.containsMouse ? 1 : 0
Column {
anchors.centerIn: parent
spacing: 2
StyledText {
id: tooltipText
text: {
if (!BatteryService.batteryAvailable) {
if (typeof PowerProfiles === "undefined")
return "Power Management";
switch (PowerProfiles.profile) {
case PowerProfile.PowerSaver:
return "Power Profile: Power Saver";
case PowerProfile.Performance:
return "Power Profile: Performance";
default:
return "Power Profile: Balanced";
}
}
let status = BatteryService.batteryStatus;
let level = BatteryService.batteryLevel + "%";
let time = BatteryService.formatTimeRemaining();
if (time !== "Unknown")
return status + " • " + level + " • " + time;
else
return status + " • " + level;
}
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
horizontalAlignment: Text.AlignHCenter
}
}
Behavior on opacity {
NumberAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
Behavior on color {
ColorAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
Behavior on color {
ColorAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -4,89 +4,91 @@ import qs.Common
import qs.Widgets
Rectangle {
id: root
id: root
property date currentDate: new Date()
property bool compactMode: false
property string section: "center"
property var popupTarget: null
property var parentScreen: null
property date currentDate: new Date()
property bool compactMode: false
property string section: "center"
property var popupTarget: null
property var parentScreen: null
signal clockClicked()
signal clockClicked
width: clockRow.implicitWidth + Theme.spacingS * 2
height: 30
radius: Theme.cornerRadius
color: {
const baseColor = clockMouseArea.containsMouse ? Theme.primaryHover : Theme.surfaceTextHover;
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
}
Component.onCompleted: {
root.currentDate = systemClock.date;
width: clockRow.implicitWidth + Theme.spacingS * 2
height: 30
radius: Theme.cornerRadius
color: {
const baseColor = clockMouseArea.containsMouse ? Theme.primaryHover : Theme.surfaceTextHover
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
}
Component.onCompleted: {
root.currentDate = systemClock.date
}
Row {
id: clockRow
anchors.centerIn: parent
spacing: Theme.spacingS
StyledText {
text: SettingsData.use24HourClock ? Qt.formatTime(root.currentDate,
"H:mm") : Qt.formatTime(
root.currentDate, "h:mm AP")
font.pixelSize: Theme.fontSizeMedium - 1
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
Row {
id: clockRow
anchors.centerIn: parent
spacing: Theme.spacingS
StyledText {
text: SettingsData.use24HourClock ? Qt.formatTime(root.currentDate, "H:mm") : Qt.formatTime(root.currentDate, "h:mm AP")
font.pixelSize: Theme.fontSizeMedium - 1
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: "•"
font.pixelSize: Theme.fontSizeSmall
color: Theme.outlineButton
anchors.verticalCenter: parent.verticalCenter
visible: !SettingsData.clockCompactMode
}
StyledText {
text: Qt.formatDate(root.currentDate, "ddd d")
font.pixelSize: Theme.fontSizeMedium - 1
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
visible: !SettingsData.clockCompactMode
}
StyledText {
text: "•"
font.pixelSize: Theme.fontSizeSmall
color: Theme.outlineButton
anchors.verticalCenter: parent.verticalCenter
visible: !SettingsData.clockCompactMode
}
SystemClock {
id: systemClock
precision: SystemClock.Seconds
onDateChanged: root.currentDate = systemClock.date
StyledText {
text: Qt.formatDate(root.currentDate, "ddd d")
font.pixelSize: Theme.fontSizeMedium - 1
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
visible: !SettingsData.clockCompactMode
}
}
MouseArea {
id: clockMouseArea
SystemClock {
id: systemClock
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
if (popupTarget && popupTarget.setTriggerPosition) {
var globalPos = mapToGlobal(0, 0);
var currentScreen = parentScreen || Screen;
var screenX = currentScreen.x || 0;
var relativeX = globalPos.x - screenX;
popupTarget.setTriggerPosition(relativeX, Theme.barHeight + Theme.spacingXS, width, section, currentScreen);
}
root.clockClicked();
}
precision: SystemClock.Seconds
onDateChanged: root.currentDate = systemClock.date
}
MouseArea {
id: clockMouseArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
if (popupTarget && popupTarget.setTriggerPosition) {
var globalPos = mapToGlobal(0, 0)
var currentScreen = parentScreen || Screen
var screenX = currentScreen.x || 0
var relativeX = globalPos.x - screenX
popupTarget.setTriggerPosition(relativeX,
Theme.barHeight + Theme.spacingXS,
width, section, currentScreen)
}
root.clockClicked()
}
}
Behavior on color {
ColorAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
Behavior on color {
ColorAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}

View File

@@ -4,140 +4,145 @@ import qs.Services
import qs.Widgets
Rectangle {
id: root
id: root
property bool isActive: false
property string section: "right"
property var popupTarget: null
property var parentScreen: null
property bool isActive: false
property string section: "right"
property var popupTarget: null
property var parentScreen: null
signal clicked()
signal clicked
function getWiFiSignalIcon(signalStrength) {
switch (signalStrength) {
case "excellent":
return "wifi";
case "good":
return "wifi_2_bar";
case "fair":
return "wifi_1_bar";
case "poor":
return "signal_wifi_0_bar";
default:
return "wifi";
}
function getWiFiSignalIcon(signalStrength) {
switch (signalStrength) {
case "excellent":
return "wifi"
case "good":
return "wifi_2_bar"
case "fair":
return "wifi_1_bar"
case "poor":
return "signal_wifi_0_bar"
default:
return "wifi"
}
}
width: Math.max(80, controlIndicators.implicitWidth + Theme.spacingS * 2)
height: 30
radius: Theme.cornerRadius
color: {
const baseColor = controlCenterArea.containsMouse
|| root.isActive ? Theme.primaryPressed : Theme.secondaryHover
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
}
Row {
id: controlIndicators
anchors.centerIn: parent
spacing: Theme.spacingXS
DankIcon {
name: {
if (NetworkService.networkStatus === "ethernet")
return "lan"
else if (NetworkService.networkStatus === "wifi")
return getWiFiSignalIcon(NetworkService.wifiSignalStrength)
else
return "wifi_off"
}
size: Theme.iconSize - 8
color: NetworkService.networkStatus !== "disconnected" ? Theme.primary : Theme.outlineButton
anchors.verticalCenter: parent.verticalCenter
visible: true
}
width: Math.max(80, controlIndicators.implicitWidth + Theme.spacingS * 2)
height: 30
radius: Theme.cornerRadius
color: {
const baseColor = controlCenterArea.containsMouse || root.isActive ? Theme.primaryPressed : Theme.secondaryHover;
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
DankIcon {
name: "bluetooth"
size: Theme.iconSize - 8
color: BluetoothService.enabled ? Theme.primary : Theme.outlineButton
anchors.verticalCenter: parent.verticalCenter
visible: BluetoothService.available && BluetoothService.enabled
}
Row {
id: controlIndicators
Rectangle {
width: audioIcon.implicitWidth + 4
height: audioIcon.implicitHeight + 4
color: "transparent"
anchors.verticalCenter: parent.verticalCenter
DankIcon {
id: audioIcon
name: (AudioService.sink && AudioService.sink.audio
&& AudioService.sink.audio.muted) ? "volume_off" : (AudioService.sink
&& AudioService.sink.audio
&& AudioService.sink.audio.volume * 100) < 33 ? "volume_down" : "volume_up"
size: Theme.iconSize - 8
color: audioWheelArea.containsMouse || controlCenterArea.containsMouse
|| root.isActive ? Theme.primary : Theme.surfaceText
anchors.centerIn: parent
spacing: Theme.spacingXS
}
DankIcon {
name: {
if (NetworkService.networkStatus === "ethernet")
return "lan";
else if (NetworkService.networkStatus === "wifi")
return getWiFiSignalIcon(NetworkService.wifiSignalStrength);
else
return "wifi_off";
}
size: Theme.iconSize - 8
color: NetworkService.networkStatus !== "disconnected" ? Theme.primary : Theme.outlineButton
anchors.verticalCenter: parent.verticalCenter
visible: true
}
DankIcon {
name: "bluetooth"
size: Theme.iconSize - 8
color: BluetoothService.enabled ? Theme.primary : Theme.outlineButton
anchors.verticalCenter: parent.verticalCenter
visible: BluetoothService.available && BluetoothService.enabled
}
Rectangle {
width: audioIcon.implicitWidth + 4
height: audioIcon.implicitHeight + 4
color: "transparent"
anchors.verticalCenter: parent.verticalCenter
DankIcon {
id: audioIcon
name: (AudioService.sink && AudioService.sink.audio && AudioService.sink.audio.muted) ? "volume_off" : (AudioService.sink && AudioService.sink.audio && AudioService.sink.audio.volume * 100) < 33 ? "volume_down" : "volume_up"
size: Theme.iconSize - 8
color: audioWheelArea.containsMouse || controlCenterArea.containsMouse || root.isActive ? Theme.primary : Theme.surfaceText
anchors.centerIn: parent
}
MouseArea {
id: audioWheelArea
anchors.fill: parent
hoverEnabled: true
acceptedButtons: Qt.NoButton
onWheel: function(wheelEvent) {
let delta = wheelEvent.angleDelta.y;
let currentVolume = (AudioService.sink && AudioService.sink.audio && AudioService.sink.audio.volume * 100) || 0;
let newVolume;
if (delta > 0)
newVolume = Math.min(100, currentVolume + 5);
else
newVolume = Math.max(0, currentVolume - 5);
if (AudioService.sink && AudioService.sink.audio) {
AudioService.sink.audio.muted = false;
AudioService.sink.audio.volume = newVolume / 100;
}
wheelEvent.accepted = true;
}
}
}
DankIcon {
name: "mic"
size: Theme.iconSize - 8
color: Theme.primary
anchors.verticalCenter: parent.verticalCenter
visible: false // TODO: Add mic detection
}
}
MouseArea {
id: controlCenterArea
MouseArea {
id: audioWheelArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
if (popupTarget && popupTarget.setTriggerPosition) {
var globalPos = mapToGlobal(0, 0);
var currentScreen = parentScreen || Screen;
var screenX = currentScreen.x || 0;
var relativeX = globalPos.x - screenX;
popupTarget.setTriggerPosition(relativeX, Theme.barHeight + Theme.spacingXS, width, section, currentScreen);
}
root.clicked();
acceptedButtons: Qt.NoButton
onWheel: function (wheelEvent) {
let delta = wheelEvent.angleDelta.y
let currentVolume = (AudioService.sink && AudioService.sink.audio
&& AudioService.sink.audio.volume * 100) || 0
let newVolume
if (delta > 0)
newVolume = Math.min(100, currentVolume + 5)
else
newVolume = Math.max(0, currentVolume - 5)
if (AudioService.sink && AudioService.sink.audio) {
AudioService.sink.audio.muted = false
AudioService.sink.audio.volume = newVolume / 100
}
wheelEvent.accepted = true
}
}
}
Behavior on color {
ColorAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
DankIcon {
name: "mic"
size: Theme.iconSize - 8
color: Theme.primary
anchors.verticalCenter: parent.verticalCenter
visible: false // TODO: Add mic detection
}
}
MouseArea {
id: controlCenterArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
if (popupTarget && popupTarget.setTriggerPosition) {
var globalPos = mapToGlobal(0, 0)
var currentScreen = parentScreen || Screen
var screenX = currentScreen.x || 0
var relativeX = globalPos.x - screenX
popupTarget.setTriggerPosition(relativeX,
Theme.barHeight + Theme.spacingXS,
width, section, currentScreen)
}
root.clicked()
}
}
Behavior on color {
ColorAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}

View File

@@ -5,81 +5,84 @@ import qs.Services
import qs.Widgets
Rectangle {
id: root
id: root
property bool showPercentage: true
property bool showIcon: true
property var toggleProcessList
property string section: "right"
property var popupTarget: null
property var parentScreen: null
property bool showPercentage: true
property bool showIcon: true
property var toggleProcessList
property string section: "right"
property var popupTarget: null
property var parentScreen: null
width: 55
height: 30
radius: Theme.cornerRadius
color: {
const baseColor = cpuArea.containsMouse ? Theme.primaryPressed : Theme.secondaryHover;
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
width: 55
height: 30
radius: Theme.cornerRadius
color: {
const baseColor = cpuArea.containsMouse ? Theme.primaryPressed : Theme.secondaryHover
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
}
Component.onCompleted: {
SysMonitorService.addRef()
}
Component.onDestruction: {
SysMonitorService.removeRef()
}
MouseArea {
id: cpuArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
if (popupTarget && popupTarget.setTriggerPosition) {
var globalPos = mapToGlobal(0, 0)
var currentScreen = parentScreen || Screen
var screenX = currentScreen.x || 0
var relativeX = globalPos.x - screenX
popupTarget.setTriggerPosition(relativeX,
Theme.barHeight + Theme.spacingXS,
width, section, currentScreen)
}
SysMonitorService.setSortBy("cpu")
if (root.toggleProcessList)
root.toggleProcessList()
}
Component.onCompleted: {
SysMonitorService.addRef();
}
Component.onDestruction: {
SysMonitorService.removeRef();
}
Row {
anchors.centerIn: parent
spacing: 3
DankIcon {
name: "memory"
size: Theme.iconSize - 8
color: {
if (SysMonitorService.cpuUsage > 80)
return Theme.tempDanger
if (SysMonitorService.cpuUsage > 60)
return Theme.tempWarning
return Theme.surfaceText
}
anchors.verticalCenter: parent.verticalCenter
}
MouseArea {
id: cpuArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
if (popupTarget && popupTarget.setTriggerPosition) {
var globalPos = mapToGlobal(0, 0);
var currentScreen = parentScreen || Screen;
var screenX = currentScreen.x || 0;
var relativeX = globalPos.x - screenX;
popupTarget.setTriggerPosition(relativeX, Theme.barHeight + Theme.spacingXS, width, section, currentScreen);
}
SysMonitorService.setSortBy("cpu");
if (root.toggleProcessList)
root.toggleProcessList();
StyledText {
text: {
if (SysMonitorService.cpuUsage === undefined
|| SysMonitorService.cpuUsage === null
|| SysMonitorService.cpuUsage === 0) {
return "--%"
}
return SysMonitorService.cpuUsage.toFixed(0) + "%"
}
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
Row {
anchors.centerIn: parent
spacing: 3
DankIcon {
name: "memory"
size: Theme.iconSize - 8
color: {
if (SysMonitorService.cpuUsage > 80)
return Theme.tempDanger;
if (SysMonitorService.cpuUsage > 60)
return Theme.tempWarning;
return Theme.surfaceText;
}
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: {
if (SysMonitorService.cpuUsage === undefined || SysMonitorService.cpuUsage === null || SysMonitorService.cpuUsage === 0) {
return "--%";
}
return SysMonitorService.cpuUsage.toFixed(0) + "%";
}
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
}
}

View File

@@ -5,87 +5,91 @@ import qs.Services
import qs.Widgets
Rectangle {
id: root
id: root
property bool showPercentage: true
property bool showIcon: true
property var toggleProcessList
property string section: "right"
property var popupTarget: null
property var parentScreen: null
property bool showPercentage: true
property bool showIcon: true
property var toggleProcessList
property string section: "right"
property var popupTarget: null
property var parentScreen: null
width: 55
height: 30
radius: Theme.cornerRadius
color: {
const baseColor = cpuTempArea.containsMouse ? Theme.primaryPressed : Theme.secondaryHover;
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
width: 55
height: 30
radius: Theme.cornerRadius
color: {
const baseColor = cpuTempArea.containsMouse ? Theme.primaryPressed : Theme.secondaryHover
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
}
Component.onCompleted: {
SysMonitorService.addRef()
}
Component.onDestruction: {
SysMonitorService.removeRef()
}
MouseArea {
id: cpuTempArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
if (popupTarget && popupTarget.setTriggerPosition) {
var globalPos = mapToGlobal(0, 0)
var currentScreen = parentScreen || Screen
var screenX = currentScreen.x || 0
var relativeX = globalPos.x - screenX
popupTarget.setTriggerPosition(relativeX,
Theme.barHeight + Theme.spacingXS,
width, section, currentScreen)
}
SysMonitorService.setSortBy("cpu")
if (root.toggleProcessList)
root.toggleProcessList()
}
Component.onCompleted: {
SysMonitorService.addRef();
}
Component.onDestruction: {
SysMonitorService.removeRef();
}
Row {
anchors.centerIn: parent
spacing: 3
DankIcon {
name: "memory"
size: Theme.iconSize - 8
color: {
if (SysMonitorService.cpuTemperature > 85)
return Theme.tempDanger
if (SysMonitorService.cpuTemperature > 69)
return Theme.tempWarning
return Theme.surfaceText
}
anchors.verticalCenter: parent.verticalCenter
}
MouseArea {
id: cpuTempArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
if (popupTarget && popupTarget.setTriggerPosition) {
var globalPos = mapToGlobal(0, 0);
var currentScreen = parentScreen || Screen;
var screenX = currentScreen.x || 0;
var relativeX = globalPos.x - screenX;
popupTarget.setTriggerPosition(relativeX, Theme.barHeight + Theme.spacingXS, width, section, currentScreen);
}
SysMonitorService.setSortBy("cpu");
if (root.toggleProcessList)
root.toggleProcessList();
StyledText {
text: {
if (SysMonitorService.cpuTemperature === undefined
|| SysMonitorService.cpuTemperature === null
|| SysMonitorService.cpuTemperature < 0) {
return "--°"
}
return Math.round(SysMonitorService.cpuTemperature) + "°"
}
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
Row {
anchors.centerIn: parent
spacing: 3
DankIcon {
name: "memory"
size: Theme.iconSize - 8
color: {
if (SysMonitorService.cpuTemperature > 85)
return Theme.tempDanger;
if (SysMonitorService.cpuTemperature > 69)
return Theme.tempWarning;
return Theme.surfaceText;
}
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: {
if (SysMonitorService.cpuTemperature === undefined || SysMonitorService.cpuTemperature === null || SysMonitorService.cpuTemperature < 0) {
return "--°";
}
return Math.round(SysMonitorService.cpuTemperature) + "°";
}
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
Behavior on color {
ColorAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
Behavior on color {
ColorAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}
}
}

View File

@@ -4,91 +4,93 @@ import qs.Services
import qs.Widgets
Rectangle {
id: root
id: root
property bool compactMode: false
property int availableWidth: 400
readonly property int baseWidth: contentRow.implicitWidth + Theme.spacingS * 2
readonly property int maxNormalWidth: 456
readonly property int maxCompactWidth: 288
property bool compactMode: false
property int availableWidth: 400
readonly property int baseWidth: contentRow.implicitWidth + Theme.spacingS * 2
readonly property int maxNormalWidth: 456
readonly property int maxCompactWidth: 288
width: compactMode ? Math.min(baseWidth, maxCompactWidth) : Math.min(baseWidth, maxNormalWidth)
height: 30
radius: Theme.cornerRadius
color: {
if (!FocusedWindowService.focusedAppName && !FocusedWindowService.focusedWindowTitle)
return "transparent";
width: compactMode ? Math.min(baseWidth,
maxCompactWidth) : Math.min(baseWidth,
maxNormalWidth)
height: 30
radius: Theme.cornerRadius
color: {
if (!FocusedWindowService.focusedAppName
&& !FocusedWindowService.focusedWindowTitle)
return "transparent"
const baseColor = mouseArea.containsMouse ? Theme.primaryHover : Theme.surfaceTextHover;
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
}
clip: true
visible: FocusedWindowService.niriAvailable && (FocusedWindowService.focusedAppName || FocusedWindowService.focusedWindowTitle)
const baseColor = mouseArea.containsMouse ? Theme.primaryHover : Theme.surfaceTextHover
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
}
clip: true
visible: FocusedWindowService.niriAvailable
&& (FocusedWindowService.focusedAppName
|| FocusedWindowService.focusedWindowTitle)
Row {
id: contentRow
Row {
id: contentRow
anchors.centerIn: parent
spacing: Theme.spacingS
anchors.centerIn: parent
spacing: Theme.spacingS
StyledText {
id: appText
text: FocusedWindowService.focusedAppName || ""
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
elide: Text.ElideRight
maximumLineCount: 1
width: Math.min(implicitWidth, compactMode ? 80 : 180)
}
StyledText {
text: "•"
font.pixelSize: Theme.fontSizeSmall
color: Theme.outlineButton
anchors.verticalCenter: parent.verticalCenter
visible: appText.text && titleText.text
}
StyledText {
id: titleText
text: FocusedWindowService.focusedWindowTitle || ""
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
elide: Text.ElideRight
maximumLineCount: 1
width: Math.min(implicitWidth, compactMode ? 180 : 250)
visible: text.length > 0
}
StyledText {
id: appText
text: FocusedWindowService.focusedAppName || ""
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
elide: Text.ElideRight
maximumLineCount: 1
width: Math.min(implicitWidth, compactMode ? 80 : 180)
}
MouseArea {
id: mouseArea
anchors.fill: parent
hoverEnabled: true
StyledText {
text: "•"
font.pixelSize: Theme.fontSizeSmall
color: Theme.outlineButton
anchors.verticalCenter: parent.verticalCenter
visible: appText.text && titleText.text
}
Behavior on color {
ColorAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
StyledText {
id: titleText
text: FocusedWindowService.focusedWindowTitle || ""
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
elide: Text.ElideRight
maximumLineCount: 1
width: Math.min(implicitWidth, compactMode ? 180 : 250)
visible: text.length > 0
}
}
Behavior on width {
NumberAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
MouseArea {
id: mouseArea
anchors.fill: parent
hoverEnabled: true
}
Behavior on color {
ColorAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
Behavior on width {
NumberAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}

View File

@@ -5,107 +5,115 @@ import qs.Services
import qs.Widgets
Rectangle {
id: root
id: root
property bool showPercentage: true
property bool showIcon: true
property var toggleProcessList
property string section: "right"
property var popupTarget: null
property var parentScreen: null
property var widgetData: null
property int selectedGpuIndex: (widgetData && widgetData.selectedGpuIndex !== undefined) ? widgetData.selectedGpuIndex : 0
Connections {
target: SettingsData
function onWidgetDataChanged() {
// Force property re-evaluation by triggering change detection
root.selectedGpuIndex = Qt.binding(() => {
return (root.widgetData && root.widgetData.selectedGpuIndex !== undefined) ? root.widgetData.selectedGpuIndex : 0;
});
property bool showPercentage: true
property bool showIcon: true
property var toggleProcessList
property string section: "right"
property var popupTarget: null
property var parentScreen: null
property var widgetData: null
property int selectedGpuIndex: (widgetData && widgetData.selectedGpuIndex
!== undefined) ? widgetData.selectedGpuIndex : 0
Connections {
target: SettingsData
function onWidgetDataChanged() {
// Force property re-evaluation by triggering change detection
root.selectedGpuIndex = Qt.binding(() => {
return (root.widgetData
&& root.widgetData.selectedGpuIndex !== undefined) ? root.widgetData.selectedGpuIndex : 0
})
}
}
width: 55
height: 30
radius: Theme.cornerRadius
color: {
const baseColor = gpuArea.containsMouse ? Theme.primaryPressed : Theme.secondaryHover
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
}
Component.onCompleted: {
SysMonitorService.addRef()
}
Component.onDestruction: {
SysMonitorService.removeRef()
}
property real displayTemp: {
if (!SysMonitorService.availableGpus
|| SysMonitorService.availableGpus.length === 0)
return 0
if (selectedGpuIndex >= 0
&& selectedGpuIndex < SysMonitorService.availableGpus.length) {
return SysMonitorService.availableGpus[selectedGpuIndex].temperature || 0
}
return 0
}
MouseArea {
id: gpuArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
if (popupTarget && popupTarget.setTriggerPosition) {
var globalPos = mapToGlobal(0, 0)
var currentScreen = parentScreen || Screen
var screenX = currentScreen.x || 0
var relativeX = globalPos.x - screenX
popupTarget.setTriggerPosition(relativeX,
Theme.barHeight + Theme.spacingXS,
width, section, currentScreen)
}
SysMonitorService.setSortBy("cpu")
if (root.toggleProcessList)
root.toggleProcessList()
}
}
Row {
anchors.centerIn: parent
spacing: 3
DankIcon {
name: "auto_awesome_mosaic"
size: Theme.iconSize - 8
color: {
if (root.displayTemp > 80)
return Theme.tempDanger
if (root.displayTemp > 65)
return Theme.tempWarning
return Theme.surfaceText
}
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: {
if (root.displayTemp === undefined || root.displayTemp === null
|| root.displayTemp === 0) {
return "--°"
}
return Math.round(root.displayTemp) + "°"
}
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
width: 55
height: 30
radius: Theme.cornerRadius
color: {
const baseColor = gpuArea.containsMouse ? Theme.primaryPressed : Theme.secondaryHover;
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
Behavior on color {
ColorAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
Component.onCompleted: {
SysMonitorService.addRef();
}
Component.onDestruction: {
SysMonitorService.removeRef();
}
property real displayTemp: {
if (!SysMonitorService.availableGpus || SysMonitorService.availableGpus.length === 0) return 0;
if (selectedGpuIndex >= 0 && selectedGpuIndex < SysMonitorService.availableGpus.length) {
return SysMonitorService.availableGpus[selectedGpuIndex].temperature || 0;
}
return 0;
}
MouseArea {
id: gpuArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
if (popupTarget && popupTarget.setTriggerPosition) {
var globalPos = mapToGlobal(0, 0);
var currentScreen = parentScreen || Screen;
var screenX = currentScreen.x || 0;
var relativeX = globalPos.x - screenX;
popupTarget.setTriggerPosition(relativeX, Theme.barHeight + Theme.spacingXS, width, section, currentScreen);
}
SysMonitorService.setSortBy("cpu");
if (root.toggleProcessList)
root.toggleProcessList();
}
}
Row {
anchors.centerIn: parent
spacing: 3
DankIcon {
name: "auto_awesome_mosaic"
size: Theme.iconSize - 8
color: {
if (root.displayTemp > 80)
return Theme.tempDanger;
if (root.displayTemp > 65)
return Theme.tempWarning;
return Theme.surfaceText;
}
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: {
if (root.displayTemp === undefined || root.displayTemp === null || root.displayTemp === 0) {
return "--°";
}
return Math.round(root.displayTemp) + "°";
}
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
Behavior on color {
ColorAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}
}
}

View File

@@ -4,65 +4,67 @@ import qs.Services
import qs.Widgets
Rectangle {
id: root
id: root
property bool isActive: false
property string section: "left" // Which section this button is in
property var popupTarget: null // Reference to the popup to position
property var parentScreen: null // The screen this button is on
property bool isActive: false
property string section: "left" // Which section this button is in
property var popupTarget: null // Reference to the popup to position
property var parentScreen: null // The screen this button is on
signal clicked()
signal clicked
width: 40
height: 30
radius: Theme.cornerRadius
color: {
const baseColor = launcherArea.containsMouse || isActive ? Theme.surfaceTextPressed : Theme.surfaceTextHover;
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
width: 40
height: 30
radius: Theme.cornerRadius
color: {
const baseColor = launcherArea.containsMouse
|| isActive ? Theme.surfaceTextPressed : Theme.surfaceTextHover
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
}
SystemLogo {
visible: SettingsData.useOSLogo
anchors.centerIn: parent
width: Theme.iconSize - 3
height: Theme.iconSize - 3
colorOverride: SettingsData.osLogoColorOverride
brightnessOverride: SettingsData.osLogoBrightness
contrastOverride: SettingsData.osLogoContrast
}
DankIcon {
visible: !SettingsData.useOSLogo
anchors.centerIn: parent
name: "apps"
size: Theme.iconSize - 6
color: Theme.surfaceText
}
MouseArea {
id: launcherArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
if (popupTarget && popupTarget.setTriggerPosition) {
var globalPos = mapToGlobal(0, 0)
var currentScreen = parentScreen || Screen
var screenX = currentScreen.x || 0
var relativeX = globalPos.x - screenX
popupTarget.setTriggerPosition(relativeX,
Theme.barHeight + Theme.spacingXS,
width, section, currentScreen)
}
root.clicked()
}
}
SystemLogo {
visible: SettingsData.useOSLogo
anchors.centerIn: parent
width: Theme.iconSize - 3
height: Theme.iconSize - 3
colorOverride: SettingsData.osLogoColorOverride
brightnessOverride: SettingsData.osLogoBrightness
contrastOverride: SettingsData.osLogoContrast
Behavior on color {
ColorAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
DankIcon {
visible: !SettingsData.useOSLogo
anchors.centerIn: parent
name: "apps"
size: Theme.iconSize - 6
color: Theme.surfaceText
}
MouseArea {
id: launcherArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
if (popupTarget && popupTarget.setTriggerPosition) {
var globalPos = mapToGlobal(0, 0);
var currentScreen = parentScreen || Screen;
var screenX = currentScreen.x || 0;
var relativeX = globalPos.x - screenX;
popupTarget.setTriggerPosition(relativeX, Theme.barHeight + Theme.spacingXS, width, section, currentScreen);
}
root.clicked();
}
}
Behavior on color {
ColorAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}
}

View File

@@ -5,260 +5,252 @@ import qs.Services
import qs.Widgets
Rectangle {
id: root
id: root
readonly property MprisPlayer activePlayer: MprisController.activePlayer
readonly property bool playerAvailable: activePlayer !== null
property bool compactMode: false
readonly property int baseContentWidth: mediaRow.implicitWidth + Theme.spacingS * 2
readonly property int normalContentWidth: Math.min(280, baseContentWidth)
readonly property int compactContentWidth: Math.min(120, baseContentWidth)
property string section: "center"
property var popupTarget: null
property var parentScreen: null
readonly property MprisPlayer activePlayer: MprisController.activePlayer
readonly property bool playerAvailable: activePlayer !== null
property bool compactMode: false
readonly property int baseContentWidth: mediaRow.implicitWidth + Theme.spacingS * 2
readonly property int normalContentWidth: Math.min(280, baseContentWidth)
readonly property int compactContentWidth: Math.min(120, baseContentWidth)
property string section: "center"
property var popupTarget: null
property var parentScreen: null
signal clicked()
signal clicked
height: 30
radius: Theme.cornerRadius
color: {
const baseColor = Theme.surfaceTextHover;
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
height: 30
radius: Theme.cornerRadius
color: {
const baseColor = Theme.surfaceTextHover
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
}
states: [
State {
name: "shown"
when: playerAvailable
PropertyChanges {
target: root
opacity: 1
width: SettingsData.mediaCompactMode ? compactContentWidth : normalContentWidth
}
},
State {
name: "hidden"
when: !playerAvailable
PropertyChanges {
target: root
opacity: 0
width: 0
}
}
states: [
State {
name: "shown"
when: playerAvailable
PropertyChanges {
target: root
opacity: 1
width: SettingsData.mediaCompactMode ? compactContentWidth : normalContentWidth
}
},
State {
name: "hidden"
when: !playerAvailable
PropertyChanges {
target: root
opacity: 0
width: 0
}
]
transitions: [
Transition {
from: "shown"
to: "hidden"
SequentialAnimation {
PauseAnimation {
duration: 500
}
]
transitions: [
Transition {
from: "shown"
to: "hidden"
SequentialAnimation {
PauseAnimation {
duration: 500
}
NumberAnimation {
properties: "opacity,width"
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
},
Transition {
from: "hidden"
to: "shown"
NumberAnimation {
properties: "opacity,width"
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
NumberAnimation {
properties: "opacity,width"
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
]
}
},
Transition {
from: "hidden"
to: "shown"
NumberAnimation {
properties: "opacity,width"
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
]
Row {
id: mediaRow
anchors.centerIn: parent
spacing: Theme.spacingXS
Row {
id: mediaRow
id: mediaInfo
anchors.centerIn: parent
spacing: Theme.spacingXS
spacing: Theme.spacingXS
Row {
id: mediaInfo
AudioVisualization {
anchors.verticalCenter: parent.verticalCenter
}
spacing: Theme.spacingXS
StyledText {
id: mediaText
AudioVisualization {
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
id: mediaText
anchors.verticalCenter: parent.verticalCenter
width: SettingsData.mediaCompactMode ? 60 : 140
visible: !SettingsData.mediaCompactMode
text: {
if (!activePlayer || !activePlayer.trackTitle)
return "";
let identity = activePlayer.identity || "";
let isWebMedia = identity.toLowerCase().includes("firefox") || identity.toLowerCase().includes("chrome") || identity.toLowerCase().includes("chromium") || identity.toLowerCase().includes("edge") || identity.toLowerCase().includes("safari");
let title = "";
let subtitle = "";
if (isWebMedia && activePlayer.trackTitle) {
title = activePlayer.trackTitle;
subtitle = activePlayer.trackArtist || identity;
} else {
title = activePlayer.trackTitle || "Unknown Track";
subtitle = activePlayer.trackArtist || "";
}
return subtitle.length > 0 ? title + " • " + subtitle : title;
}
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
font.weight: Font.Medium
elide: Text.ElideRight
wrapMode: Text.NoWrap
maximumLineCount: 1
MouseArea {
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
if (root.popupTarget && root.popupTarget.setTriggerPosition) {
var globalPos = mapToGlobal(0, 0);
var currentScreen = root.parentScreen || Screen;
var screenX = currentScreen.x || 0;
var relativeX = globalPos.x - screenX;
root.popupTarget.setTriggerPosition(relativeX, Theme.barHeight + Theme.spacingXS, root.width, root.section, currentScreen);
}
root.clicked();
}
}
}
anchors.verticalCenter: parent.verticalCenter
width: SettingsData.mediaCompactMode ? 60 : 140
visible: !SettingsData.mediaCompactMode
text: {
if (!activePlayer || !activePlayer.trackTitle)
return ""
let identity = activePlayer.identity || ""
let isWebMedia = identity.toLowerCase().includes("firefox")
|| identity.toLowerCase().includes(
"chrome") || identity.toLowerCase().includes("chromium")
|| identity.toLowerCase().includes(
"edge") || identity.toLowerCase().includes("safari")
let title = ""
let subtitle = ""
if (isWebMedia && activePlayer.trackTitle) {
title = activePlayer.trackTitle
subtitle = activePlayer.trackArtist || identity
} else {
title = activePlayer.trackTitle || "Unknown Track"
subtitle = activePlayer.trackArtist || ""
}
return subtitle.length > 0 ? title + " • " + subtitle : title
}
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
font.weight: Font.Medium
elide: Text.ElideRight
wrapMode: Text.NoWrap
maximumLineCount: 1
Row {
spacing: Theme.spacingXS
anchors.verticalCenter: parent.verticalCenter
Rectangle {
width: 20
height: 20
radius: 10
anchors.verticalCenter: parent.verticalCenter
color: prevArea.containsMouse ? Theme.primaryHover : "transparent"
visible: root.playerAvailable
opacity: (activePlayer && activePlayer.canGoPrevious) ? 1 : 0.3
DankIcon {
anchors.centerIn: parent
name: "skip_previous"
size: 12
color: Theme.surfaceText
}
MouseArea {
id: prevArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
if (activePlayer)
activePlayer.previous();
}
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
if (root.popupTarget && root.popupTarget.setTriggerPosition) {
var globalPos = mapToGlobal(0, 0)
var currentScreen = root.parentScreen || Screen
var screenX = currentScreen.x || 0
var relativeX = globalPos.x - screenX
root.popupTarget.setTriggerPosition(
relativeX, Theme.barHeight + Theme.spacingXS, root.width,
root.section, currentScreen)
}
Rectangle {
width: 24
height: 24
radius: 12
anchors.verticalCenter: parent.verticalCenter
color: activePlayer && activePlayer.playbackState === 1 ? Theme.primary : Theme.primaryHover
visible: root.playerAvailable
opacity: activePlayer ? 1 : 0.3
DankIcon {
anchors.centerIn: parent
name: activePlayer && activePlayer.playbackState === 1 ? "pause" : "play_arrow"
size: 14
color: activePlayer && activePlayer.playbackState === 1 ? Theme.background : Theme.primary
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
if (activePlayer)
activePlayer.togglePlaying();
}
}
}
Rectangle {
width: 20
height: 20
radius: 10
anchors.verticalCenter: parent.verticalCenter
color: nextArea.containsMouse ? Theme.primaryHover : "transparent"
visible: playerAvailable
opacity: (activePlayer && activePlayer.canGoNext) ? 1 : 0.3
DankIcon {
anchors.centerIn: parent
name: "skip_next"
size: 12
color: Theme.surfaceText
}
MouseArea {
id: nextArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
if (activePlayer)
activePlayer.next();
}
}
}
root.clicked()
}
}
}
}
Behavior on color {
ColorAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
Row {
spacing: Theme.spacingXS
anchors.verticalCenter: parent.verticalCenter
Rectangle {
width: 20
height: 20
radius: 10
anchors.verticalCenter: parent.verticalCenter
color: prevArea.containsMouse ? Theme.primaryHover : "transparent"
visible: root.playerAvailable
opacity: (activePlayer && activePlayer.canGoPrevious) ? 1 : 0.3
DankIcon {
anchors.centerIn: parent
name: "skip_previous"
size: 12
color: Theme.surfaceText
}
}
MouseArea {
id: prevArea
Behavior on width {
NumberAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
if (activePlayer)
activePlayer.previous()
}
}
}
Rectangle {
width: 24
height: 24
radius: 12
anchors.verticalCenter: parent.verticalCenter
color: activePlayer
&& activePlayer.playbackState === 1 ? Theme.primary : Theme.primaryHover
visible: root.playerAvailable
opacity: activePlayer ? 1 : 0.3
DankIcon {
anchors.centerIn: parent
name: activePlayer
&& activePlayer.playbackState === 1 ? "pause" : "play_arrow"
size: 14
color: activePlayer
&& activePlayer.playbackState === 1 ? Theme.background : Theme.primary
}
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
if (activePlayer)
activePlayer.togglePlaying()
}
}
}
Rectangle {
width: 20
height: 20
radius: 10
anchors.verticalCenter: parent.verticalCenter
color: nextArea.containsMouse ? Theme.primaryHover : "transparent"
visible: playerAvailable
opacity: (activePlayer && activePlayer.canGoNext) ? 1 : 0.3
DankIcon {
anchors.centerIn: parent
name: "skip_next"
size: 12
color: Theme.surfaceText
}
MouseArea {
id: nextArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
if (activePlayer)
activePlayer.next()
}
}
}
}
}
Behavior on color {
ColorAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
Behavior on width {
NumberAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}

View File

@@ -3,67 +3,70 @@ import qs.Common
import qs.Widgets
Rectangle {
id: root
id: root
property bool hasUnread: false
property bool isActive: false
property string section: "right"
property var popupTarget: null
property var parentScreen: null
property bool hasUnread: false
property bool isActive: false
property string section: "right"
property var popupTarget: null
property var parentScreen: null
signal clicked()
signal clicked
width: 40
height: 30
radius: Theme.cornerRadius
color: {
const baseColor = notificationArea.containsMouse || root.isActive ? Theme.primaryPressed : Theme.secondaryHover;
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
width: 40
height: 30
radius: Theme.cornerRadius
color: {
const baseColor = notificationArea.containsMouse
|| root.isActive ? Theme.primaryPressed : Theme.secondaryHover
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
}
DankIcon {
anchors.centerIn: parent
name: SessionData.doNotDisturb ? "notifications_off" : "notifications"
size: Theme.iconSize - 6
color: SessionData.doNotDisturb ? Theme.error : (notificationArea.containsMouse
|| root.isActive ? Theme.primary : Theme.surfaceText)
}
Rectangle {
width: 8
height: 8
radius: 4
color: Theme.error
anchors.right: parent.right
anchors.top: parent.top
anchors.rightMargin: 6
anchors.topMargin: 6
visible: root.hasUnread
}
MouseArea {
id: notificationArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
if (popupTarget && popupTarget.setTriggerPosition) {
var globalPos = mapToGlobal(0, 0)
var currentScreen = parentScreen || Screen
var screenX = currentScreen.x || 0
var relativeX = globalPos.x - screenX
popupTarget.setTriggerPosition(relativeX,
Theme.barHeight + Theme.spacingXS,
width, section, currentScreen)
}
root.clicked()
}
}
DankIcon {
anchors.centerIn: parent
name: SessionData.doNotDisturb ? "notifications_off" : "notifications"
size: Theme.iconSize - 6
color: SessionData.doNotDisturb ? Theme.error : (notificationArea.containsMouse || root.isActive ? Theme.primary : Theme.surfaceText)
Behavior on color {
ColorAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
Rectangle {
width: 8
height: 8
radius: 4
color: Theme.error
anchors.right: parent.right
anchors.top: parent.top
anchors.rightMargin: 6
anchors.topMargin: 6
visible: root.hasUnread
}
MouseArea {
id: notificationArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
if (popupTarget && popupTarget.setTriggerPosition) {
var globalPos = mapToGlobal(0, 0);
var currentScreen = parentScreen || Screen;
var screenX = currentScreen.x || 0;
var relativeX = globalPos.x - screenX;
popupTarget.setTriggerPosition(relativeX, Theme.barHeight + Theme.spacingXS, width, section, currentScreen);
}
root.clicked();
}
}
Behavior on color {
ColorAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}
}

View File

@@ -5,169 +5,166 @@ import qs.Services
import qs.Widgets
Rectangle {
id: root
id: root
property string section: "right"
property var popupTarget: null
property var parentScreen: null
property string section: "right"
property var popupTarget: null
property var parentScreen: null
readonly property bool hasActivePrivacy: PrivacyService.anyPrivacyActive
readonly property int activeCount: (PrivacyService.microphoneActive ? 1 : 0) + (PrivacyService.cameraActive ? 1 : 0) + (PrivacyService.screensharingActive ? 1 : 0)
width: hasActivePrivacy ? (activeCount > 1 ? 80 : 60) : 0
height: hasActivePrivacy ? 30 : 0
radius: Theme.cornerRadius
readonly property bool hasActivePrivacy: PrivacyService.anyPrivacyActive
readonly property int activeCount: PrivacyService.microphoneActive + PrivacyService.cameraActive
+ PrivacyService.screensharingActive
width: hasActivePrivacy ? (activeCount > 1 ? 80 : 60) : 0
height: hasActivePrivacy ? 30 : 0
radius: Theme.cornerRadius
visible: hasActivePrivacy
opacity: hasActivePrivacy ? 1 : 0
color: Qt.rgba(
privacyArea.containsMouse ? Theme.errorPressed.r : Theme.errorHover.r,
privacyArea.containsMouse ? Theme.errorPressed.g : Theme.errorHover.g,
privacyArea.containsMouse ? Theme.errorPressed.b : Theme.errorHover.b,
(privacyArea.containsMouse ? Theme.errorPressed.a : Theme.errorHover.a)
* Theme.widgetTransparency)
MouseArea {
id: privacyArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
}
}
Row {
anchors.centerIn: parent
spacing: Theme.spacingXS
visible: hasActivePrivacy
opacity: hasActivePrivacy ? 1 : 0
color: {
const baseColor = privacyArea.containsMouse ? Theme.errorPressed : Theme.errorHover;
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
}
Item {
width: 18
height: 18
visible: PrivacyService.microphoneActive
anchors.verticalCenter: parent.verticalCenter
MouseArea {
id: privacyArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
}
}
Row {
DankIcon {
name: "mic"
size: Theme.iconSizeSmall
color: Theme.error
filled: true
anchors.centerIn: parent
spacing: Theme.spacingXS
visible: hasActivePrivacy
Item {
width: 18
height: 18
visible: PrivacyService.microphoneActive
anchors.verticalCenter: parent.verticalCenter
DankIcon {
name: "mic"
size: Theme.iconSizeSmall
color: Theme.error
filled: true
anchors.centerIn: parent
}
}
Item {
width: 18
height: 18
visible: PrivacyService.cameraActive
anchors.verticalCenter: parent.verticalCenter
DankIcon {
name: "camera_video"
size: Theme.iconSizeSmall
color: Theme.surfaceText
filled: true
anchors.centerIn: parent
}
Rectangle {
width: 6
height: 6
radius: 3
color: Theme.error
anchors.right: parent.right
anchors.top: parent.top
anchors.rightMargin: -2
anchors.topMargin: -1
SequentialAnimation on opacity {
running: parent.visible
loops: Animation.Infinite
NumberAnimation {
to: 0.3
duration: Theme.longDuration
}
NumberAnimation {
to: 1.0
duration: Theme.longDuration
}
}
}
}
Item {
width: 18
height: 18
visible: PrivacyService.screensharingActive
anchors.verticalCenter: parent.verticalCenter
DankIcon {
name: "screen_share"
size: Theme.iconSizeSmall
color: Theme.warning
filled: true
anchors.centerIn: parent
}
}
}
}
Behavior on width {
NumberAnimation {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
Item {
width: 18
height: 18
visible: PrivacyService.cameraActive
anchors.verticalCenter: parent.verticalCenter
DankIcon {
name: "camera_video"
size: Theme.iconSizeSmall
color: Theme.surfaceText
filled: true
anchors.centerIn: parent
}
Rectangle {
width: 6
height: 6
radius: 3
color: Theme.error
anchors.right: parent.right
anchors.top: parent.top
anchors.rightMargin: -2
anchors.topMargin: -1
SequentialAnimation on opacity {
running: parent.visible && hasActivePrivacy
loops: Animation.Infinite
NumberAnimation {
to: 0.3
duration: Theme.longDuration
}
NumberAnimation {
to: 1.0
duration: Theme.longDuration
}
}
}
}
Item {
width: 18
height: 18
visible: PrivacyService.screensharingActive
anchors.verticalCenter: parent.verticalCenter
DankIcon {
name: "screen_share"
size: Theme.iconSizeSmall
color: Theme.warning
filled: true
anchors.centerIn: parent
}
}
}
Behavior on width {
enabled: hasActivePrivacy
NumberAnimation {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
Rectangle {
id: tooltip
width: tooltipText.contentWidth + Theme.spacingM * 2
height: tooltipText.contentHeight + Theme.spacingS * 2
radius: Theme.cornerRadius
color: Theme.popupBackground()
border.color: Theme.outlineMedium
border.width: 1
visible: false
opacity: privacyArea.containsMouse && hasActivePrivacy ? 1 : 0
z: 100
x: (parent.width - width) / 2
y: -height - Theme.spacingXS
StyledText {
id: tooltipText
anchors.centerIn: parent
text: PrivacyService.getPrivacySummary()
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
}
Behavior on opacity {
enabled: !hasActivePrivacy
NumberAnimation {
duration: Theme.mediumDuration
easing.type: Theme.standardEasing
}
enabled: hasActivePrivacy
NumberAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
Rectangle {
id: tooltip
width: tooltipText.contentWidth + Theme.spacingM * 2
height: tooltipText.contentHeight + Theme.spacingS * 2
radius: Theme.cornerRadius
color: Theme.popupBackground()
border.color: Theme.outlineMedium
border.width: 1
visible: privacyArea.containsMouse && hasActivePrivacy
opacity: visible ? 1 : 0
z: 100
x: (parent.width - width) / 2
y: -height - Theme.spacingXS
StyledText {
id: tooltipText
anchors.centerIn: parent
text: PrivacyService.getPrivacySummary()
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
}
Behavior on opacity {
NumberAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
Rectangle {
width: 8
height: 8
color: parent.color
border.color: parent.border.color
border.width: parent.border.width
rotation: 45
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.bottom
anchors.topMargin: -4
}
width: 8
height: 8
color: parent.color
border.color: parent.border.color
border.width: parent.border.width
rotation: 45
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.bottom
anchors.topMargin: -4
}
}
}

View File

@@ -5,81 +5,84 @@ import qs.Services
import qs.Widgets
Rectangle {
id: root
id: root
property bool showPercentage: true
property bool showIcon: true
property var toggleProcessList
property string section: "right"
property var popupTarget: null
property var parentScreen: null
property bool showPercentage: true
property bool showIcon: true
property var toggleProcessList
property string section: "right"
property var popupTarget: null
property var parentScreen: null
width: 55
height: 30
radius: Theme.cornerRadius
color: {
const baseColor = ramArea.containsMouse ? Theme.primaryPressed : Theme.secondaryHover;
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
width: 55
height: 30
radius: Theme.cornerRadius
color: {
const baseColor = ramArea.containsMouse ? Theme.primaryPressed : Theme.secondaryHover
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
}
Component.onCompleted: {
SysMonitorService.addRef()
}
Component.onDestruction: {
SysMonitorService.removeRef()
}
MouseArea {
id: ramArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
if (popupTarget && popupTarget.setTriggerPosition) {
var globalPos = mapToGlobal(0, 0)
var currentScreen = parentScreen || Screen
var screenX = currentScreen.x || 0
var relativeX = globalPos.x - screenX
popupTarget.setTriggerPosition(relativeX,
Theme.barHeight + Theme.spacingXS,
width, section, currentScreen)
}
SysMonitorService.setSortBy("memory")
if (root.toggleProcessList)
root.toggleProcessList()
}
Component.onCompleted: {
SysMonitorService.addRef();
}
Component.onDestruction: {
SysMonitorService.removeRef();
}
Row {
anchors.centerIn: parent
spacing: 3
DankIcon {
name: "developer_board"
size: Theme.iconSize - 8
color: {
if (SysMonitorService.memoryUsage > 90)
return Theme.tempDanger
if (SysMonitorService.memoryUsage > 75)
return Theme.tempWarning
return Theme.surfaceText
}
anchors.verticalCenter: parent.verticalCenter
}
MouseArea {
id: ramArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
if (popupTarget && popupTarget.setTriggerPosition) {
var globalPos = mapToGlobal(0, 0);
var currentScreen = parentScreen || Screen;
var screenX = currentScreen.x || 0;
var relativeX = globalPos.x - screenX;
popupTarget.setTriggerPosition(relativeX, Theme.barHeight + Theme.spacingXS, width, section, currentScreen);
}
SysMonitorService.setSortBy("memory");
if (root.toggleProcessList)
root.toggleProcessList();
StyledText {
text: {
if (SysMonitorService.memoryUsage === undefined
|| SysMonitorService.memoryUsage === null
|| SysMonitorService.memoryUsage === 0) {
return "--%"
}
return SysMonitorService.memoryUsage.toFixed(0) + "%"
}
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
Row {
anchors.centerIn: parent
spacing: 3
DankIcon {
name: "developer_board"
size: Theme.iconSize - 8
color: {
if (SysMonitorService.memoryUsage > 90)
return Theme.tempDanger;
if (SysMonitorService.memoryUsage > 75)
return Theme.tempWarning;
return Theme.surfaceText;
}
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: {
if (SysMonitorService.memoryUsage === undefined || SysMonitorService.memoryUsage === null || SysMonitorService.memoryUsage === 0) {
return "--%";
}
return SysMonitorService.memoryUsage.toFixed(0) + "%";
}
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
}
}

View File

@@ -4,114 +4,117 @@ import Quickshell.Services.SystemTray
import qs.Common
Rectangle {
id: root
property var parentWindow: null
property var parentScreen: null
id: root
readonly property int calculatedWidth: SystemTray.items.values.length > 0 ? SystemTray.items.values.length * 24 + (SystemTray.items.values.length - 1) * Theme.spacingXS + Theme.spacingS * 2 : 0
property var parentWindow: null
property var parentScreen: null
readonly property int calculatedWidth: SystemTray.items.values.length
> 0 ? SystemTray.items.values.length * 24
+ (SystemTray.items.values.length - 1)
* Theme.spacingXS + Theme.spacingS * 2 : 0
width: calculatedWidth
height: 30
radius: Theme.cornerRadius
color: {
if (SystemTray.items.values.length === 0)
return "transparent";
width: calculatedWidth
height: 30
radius: Theme.cornerRadius
color: {
if (SystemTray.items.values.length === 0)
return "transparent"
const baseColor = Theme.secondaryHover;
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
}
visible: SystemTray.items.values.length > 0
const baseColor = Theme.secondaryHover
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
}
visible: SystemTray.items.values.length > 0
Row {
id: systemTrayRow
Row {
id: systemTrayRow
anchors.centerIn: parent
spacing: Theme.spacingXS
anchors.centerIn: parent
spacing: Theme.spacingXS
Repeater {
model: SystemTray.items.values
delegate: Item {
property var trayItem: modelData
property string iconSource: {
let icon = trayItem && trayItem.icon;
if (typeof icon === 'string' || icon instanceof String) {
if (icon.includes("?path=")) {
const [name, path] = icon.split("?path=");
const fileName = name.substring(name.lastIndexOf("/") + 1);
return `file://${path}/${fileName}`;
}
return icon;
}
return "";
}
width: 24
height: 24
Rectangle {
anchors.fill: parent
radius: Theme.cornerRadiusSmall
color: trayItemArea.containsMouse ? Theme.primaryHover : "transparent"
Behavior on color {
enabled: trayItemArea.containsMouse !== undefined
ColorAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}
Image {
anchors.centerIn: parent
width: 18
height: 18
source: parent.iconSource
asynchronous: true
smooth: true
fillMode: Image.PreserveAspectFit
}
MouseArea {
id: trayItemArea
anchors.fill: parent
acceptedButtons: Qt.LeftButton | Qt.RightButton
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: (mouse) => {
if (!trayItem)
return
if (trayItem.hasMenu) {
var globalPos = mapToGlobal(0, 0)
var currentScreen = parentScreen || Screen
var screenX = currentScreen.x || 0
var relativeX = globalPos.x - screenX
menuAnchor.menu = trayItem.menu
menuAnchor.anchor.window = parentWindow
menuAnchor.anchor.rect = Qt.rect(relativeX, Theme.barHeight + Theme.spacingS, parent.width, 1)
menuAnchor.open()
} else if (mouse.button === Qt.LeftButton) {
trayItem.activate()
}
}
}
Repeater {
model: SystemTray.items.values
delegate: Item {
property var trayItem: modelData
property string iconSource: {
let icon = trayItem && trayItem.icon
if (typeof icon === 'string' || icon instanceof String) {
if (icon.includes("?path=")) {
const split = icon.split("?path=")
if (split.length !== 2)
return icon
const name = split[0]
const path = split[1]
const fileName = name.substring(name.lastIndexOf("/") + 1)
return `file://${path}/${fileName}`
}
return icon
}
return ""
}
}
width: 24
height: 24
QsMenuAnchor {
id: menuAnchor
}
Rectangle {
anchors.fill: parent
radius: Theme.cornerRadiusSmall
color: trayItemArea.containsMouse ? Theme.primaryHover : "transparent"
Behavior on color {
enabled: trayItemArea.containsMouse !== undefined
ColorAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}
Image {
anchors.centerIn: parent
width: 18
height: 18
source: parent.iconSource
asynchronous: true
smooth: true
fillMode: Image.PreserveAspectFit
}
MouseArea {
id: trayItemArea
anchors.fill: parent
acceptedButtons: Qt.LeftButton | Qt.RightButton
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: mouse => {
if (!trayItem)
return
if (trayItem.hasMenu) {
var globalPos = mapToGlobal(0, 0)
var currentScreen = parentScreen || Screen
var screenX = currentScreen.x || 0
var relativeX = globalPos.x - screenX
menuAnchor.menu = trayItem.menu
menuAnchor.anchor.window = parentWindow
menuAnchor.anchor.rect = Qt.rect(
relativeX, Theme.barHeight + Theme.spacingS,
parent.width, 1)
menuAnchor.open()
} else if (mouse.button === Qt.LeftButton) {
trayItem.activate()
}
}
}
}
}
}
QsMenuAnchor {
id: menuAnchor
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -4,87 +4,87 @@ import qs.Services
import qs.Widgets
Rectangle {
id: root
id: root
property string section: "center"
property var popupTarget: null
property var parentScreen: null
property string section: "center"
property var popupTarget: null
property var parentScreen: null
signal clicked()
signal clicked
visible: SettingsData.weatherEnabled
width: visible ? Math.min(100, weatherRow.implicitWidth + Theme.spacingS * 2) : 0
height: 30
radius: Theme.cornerRadius
color: {
const baseColor = weatherArea.containsMouse ? Theme.primaryHover : Theme.surfaceTextHover;
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
visible: SettingsData.weatherEnabled
width: visible ? Math.min(100,
weatherRow.implicitWidth + Theme.spacingS * 2) : 0
height: 30
radius: Theme.cornerRadius
color: {
const baseColor = weatherArea.containsMouse ? Theme.primaryHover : Theme.surfaceTextHover
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
}
Ref {
service: WeatherService
}
Row {
id: weatherRow
anchors.centerIn: parent
spacing: Theme.spacingXS
DankIcon {
name: WeatherService.getWeatherIcon(WeatherService.weather.wCode)
size: Theme.iconSize - 4
color: Theme.primary
anchors.verticalCenter: parent.verticalCenter
}
Ref {
service: WeatherService
}
Row {
id: weatherRow
anchors.centerIn: parent
spacing: Theme.spacingXS
DankIcon {
name: WeatherService.getWeatherIcon(WeatherService.weather.wCode)
size: Theme.iconSize - 4
color: Theme.primary
anchors.verticalCenter: parent.verticalCenter
StyledText {
text: {
var temp = SettingsData.useFahrenheit ? WeatherService.weather.tempF : WeatherService.weather.temp
if (temp === undefined || temp === null || temp === 0) {
return "--°" + (SettingsData.useFahrenheit ? "F" : "C")
}
StyledText {
text: {
var temp = SettingsData.useFahrenheit ? WeatherService.weather.tempF : WeatherService.weather.temp;
if (temp === undefined || temp === null || temp === 0) {
return "--°" + (SettingsData.useFahrenheit ? "F" : "C");
}
return temp + "°" + (SettingsData.useFahrenheit ? "F" : "C");
}
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
return temp + "°" + (SettingsData.useFahrenheit ? "F" : "C")
}
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
MouseArea {
id: weatherArea
MouseArea {
id: weatherArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
if (popupTarget && popupTarget.setTriggerPosition) {
var globalPos = mapToGlobal(0, 0);
var currentScreen = parentScreen || Screen;
var screenX = currentScreen.x || 0;
var relativeX = globalPos.x - screenX;
popupTarget.setTriggerPosition(relativeX, Theme.barHeight + Theme.spacingXS, width, section, currentScreen);
}
root.clicked();
}
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
if (popupTarget && popupTarget.setTriggerPosition) {
var globalPos = mapToGlobal(0, 0)
var currentScreen = parentScreen || Screen
var screenX = currentScreen.x || 0
var relativeX = globalPos.x - screenX
popupTarget.setTriggerPosition(relativeX,
Theme.barHeight + Theme.spacingXS,
width, section, currentScreen)
}
root.clicked()
}
}
Behavior on color {
ColorAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
Behavior on color {
ColorAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
Behavior on width {
NumberAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
Behavior on width {
NumberAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}

View File

@@ -6,155 +6,164 @@ import qs.Services
import qs.Widgets
Rectangle {
id: root
id: root
property string screenName: ""
property int currentWorkspace: getDisplayActiveWorkspace()
property var workspaceList: {
var baseList = getDisplayWorkspaces();
return SettingsData.showWorkspacePadding ? padWorkspaces(baseList) : baseList;
property string screenName: ""
property int currentWorkspace: getDisplayActiveWorkspace()
property var workspaceList: {
var baseList = getDisplayWorkspaces()
return SettingsData.showWorkspacePadding ? padWorkspaces(
baseList) : baseList
}
function padWorkspaces(list) {
var padded = list.slice()
while (padded.length < 3)
padded.push(-1) // Use -1 as a placeholder
return padded
}
function getDisplayWorkspaces() {
if (!NiriService.niriAvailable || NiriService.allWorkspaces.length === 0)
return [1, 2]
if (!root.screenName)
return NiriService.getCurrentOutputWorkspaceNumbers()
var displayWorkspaces = []
for (var i = 0; i < NiriService.allWorkspaces.length; i++) {
var ws = NiriService.allWorkspaces[i]
if (ws.output === root.screenName)
displayWorkspaces.push(ws.idx + 1)
}
return displayWorkspaces.length > 0 ? displayWorkspaces : [1, 2]
}
function getDisplayActiveWorkspace() {
if (!NiriService.niriAvailable || NiriService.allWorkspaces.length === 0)
return 1
if (!root.screenName)
return NiriService.getCurrentWorkspaceNumber()
for (var i = 0; i < NiriService.allWorkspaces.length; i++) {
var ws = NiriService.allWorkspaces[i]
if (ws.output === root.screenName && ws.is_active)
return ws.idx + 1
}
return 1
}
width: SettingsData.showWorkspacePadding ? Math.max(
120,
workspaceRow.implicitWidth + Theme.spacingL
* 2) : workspaceRow.implicitWidth
+ Theme.spacingL * 2
height: 30
radius: Theme.cornerRadiusLarge
color: {
const baseColor = Theme.surfaceTextHover
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
}
visible: NiriService.niriAvailable
Connections {
function onAllWorkspacesChanged() {
root.workspaceList
= SettingsData.showWorkspacePadding ? root.padWorkspaces(
root.getDisplayWorkspaces(
)) : root.getDisplayWorkspaces()
root.currentWorkspace = root.getDisplayActiveWorkspace()
}
function padWorkspaces(list) {
var padded = list.slice();
while (padded.length < 3)padded.push(-1) // Use -1 as a placeholder
return padded;
function onFocusedWorkspaceIndexChanged() {
root.currentWorkspace = root.getDisplayActiveWorkspace()
}
function getDisplayWorkspaces() {
if (!NiriService.niriAvailable || NiriService.allWorkspaces.length === 0)
return [1, 2];
if (!root.screenName)
return NiriService.getCurrentOutputWorkspaceNumbers();
var displayWorkspaces = [];
for (var i = 0; i < NiriService.allWorkspaces.length; i++) {
var ws = NiriService.allWorkspaces[i];
if (ws.output === root.screenName)
displayWorkspaces.push(ws.idx + 1);
}
return displayWorkspaces.length > 0 ? displayWorkspaces : [1, 2];
function onNiriAvailableChanged() {
if (NiriService.niriAvailable) {
root.workspaceList
= SettingsData.showWorkspacePadding ? root.padWorkspaces(
root.getDisplayWorkspaces(
)) : root.getDisplayWorkspaces()
root.currentWorkspace = root.getDisplayActiveWorkspace()
}
}
function getDisplayActiveWorkspace() {
if (!NiriService.niriAvailable || NiriService.allWorkspaces.length === 0)
return 1;
target: NiriService
}
if (!root.screenName)
return NiriService.getCurrentWorkspaceNumber();
for (var i = 0; i < NiriService.allWorkspaces.length; i++) {
var ws = NiriService.allWorkspaces[i];
if (ws.output === root.screenName && ws.is_active)
return ws.idx + 1;
}
return 1;
Connections {
function onShowWorkspacePaddingChanged() {
var baseList = root.getDisplayWorkspaces()
root.workspaceList = SettingsData.showWorkspacePadding ? root.padWorkspaces(
baseList) : baseList
}
width: SettingsData.showWorkspacePadding ? Math.max(120, workspaceRow.implicitWidth + Theme.spacingL * 2) : workspaceRow.implicitWidth + Theme.spacingL * 2
height: 30
radius: Theme.cornerRadiusLarge
color: {
const baseColor = Theme.surfaceTextHover;
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
}
visible: NiriService.niriAvailable
target: SettingsData
}
Connections {
function onAllWorkspacesChanged() {
root.workspaceList = SettingsData.showWorkspacePadding ? root.padWorkspaces(root.getDisplayWorkspaces()) : root.getDisplayWorkspaces();
root.currentWorkspace = root.getDisplayActiveWorkspace();
Row {
id: workspaceRow
anchors.centerIn: parent
spacing: Theme.spacingS
Repeater {
model: root.workspaceList
Rectangle {
property bool isActive: modelData === root.currentWorkspace
property bool isPlaceholder: modelData === -1
property bool isHovered: mouseArea.containsMouse
property int sequentialNumber: index + 1
width: isActive ? Theme.spacingXL + Theme.spacingM : Theme.spacingL + Theme.spacingXS
height: Theme.spacingL
radius: height / 2
color: isActive ? Theme.primary : isPlaceholder ? Theme.surfaceTextLight : isHovered ? Theme.outlineButton : Theme.surfaceTextAlpha
MouseArea {
id: mouseArea
anchors.fill: parent
hoverEnabled: !isPlaceholder
cursorShape: isPlaceholder ? Qt.ArrowCursor : Qt.PointingHandCursor
enabled: !isPlaceholder
onClicked: {
if (!isPlaceholder)
NiriService.switchToWorkspace(modelData - 1)
}
}
function onFocusedWorkspaceIndexChanged() {
root.currentWorkspace = root.getDisplayActiveWorkspace();
StyledText {
visible: SettingsData.showWorkspaceIndex
anchors.centerIn: parent
text: isPlaceholder ? sequentialNumber : sequentialNumber
color: isActive ? Qt.rgba(
Theme.surfaceContainer.r,
Theme.surfaceContainer.g,
Theme.surfaceContainer.b,
0.95) : isPlaceholder ? Theme.surfaceTextAlpha : Theme.surfaceTextMedium
font.pixelSize: Theme.fontSizeSmall
font.weight: isActive && !isPlaceholder ? Font.DemiBold : Font.Normal
}
function onNiriAvailableChanged() {
if (NiriService.niriAvailable) {
root.workspaceList = SettingsData.showWorkspacePadding ? root.padWorkspaces(root.getDisplayWorkspaces()) : root.getDisplayWorkspaces();
root.currentWorkspace = root.getDisplayActiveWorkspace();
}
Behavior on width {
NumberAnimation {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
target: NiriService
Behavior on color {
ColorAnimation {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
}
}
Connections {
function onShowWorkspacePaddingChanged() {
var baseList = root.getDisplayWorkspaces();
root.workspaceList = SettingsData.showWorkspacePadding ? root.padWorkspaces(baseList) : baseList;
}
target: SettingsData
}
Row {
id: workspaceRow
anchors.centerIn: parent
spacing: Theme.spacingS
Repeater {
model: root.workspaceList
Rectangle {
property bool isActive: modelData === root.currentWorkspace
property bool isPlaceholder: modelData === -1
property bool isHovered: mouseArea.containsMouse
property int sequentialNumber: index + 1
width: isActive ? Theme.spacingXL + Theme.spacingM : Theme.spacingL + Theme.spacingXS
height: Theme.spacingL
radius: height / 2
color: isActive ? Theme.primary : isPlaceholder ? Theme.surfaceTextLight : isHovered ? Theme.outlineButton : Theme.surfaceTextAlpha
MouseArea {
id: mouseArea
anchors.fill: parent
hoverEnabled: !isPlaceholder
cursorShape: isPlaceholder ? Qt.ArrowCursor : Qt.PointingHandCursor
enabled: !isPlaceholder
onClicked: {
if (!isPlaceholder)
NiriService.switchToWorkspace(modelData - 1);
}
}
StyledText {
visible: SettingsData.showWorkspaceIndex
anchors.centerIn: parent
text: isPlaceholder ? sequentialNumber : sequentialNumber
color: isActive ? Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.95) : isPlaceholder ? Theme.surfaceTextAlpha : Theme.surfaceTextMedium
font.pixelSize: Theme.fontSizeSmall
font.weight: isActive && !isPlaceholder ? Font.DemiBold : Font.Normal
}
Behavior on width {
NumberAnimation {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
Behavior on color {
ColorAnimation {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
}
}
}
}
}