1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-01-26 22:42:50 -05:00

modules cleanup and qmlfmt everywhere

- throw in 24H clock fix and app drawer fix too
This commit is contained in:
bbedward
2025-09-03 23:26:07 -04:00
parent 178ccd3634
commit 21867c842f
55 changed files with 2720 additions and 3236 deletions

View File

@@ -8,19 +8,21 @@ Item {
readonly property MprisPlayer activePlayer: MprisController.activePlayer
readonly property bool hasActiveMedia: activePlayer !== null
readonly property bool isPlaying: hasActiveMedia && activePlayer
&& activePlayer.playbackState === MprisPlaybackState.Playing
readonly property bool isPlaying: hasActiveMedia && activePlayer && activePlayer.playbackState === MprisPlaybackState.Playing
width: 20
height: Theme.iconSize
Loader {
active: isPlaying
sourceComponent: Component {
Ref {
service: CavaService
}
}
}
Timer {
@@ -30,10 +32,7 @@ Item {
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]
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];
}
}
@@ -48,15 +47,13 @@ Item {
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)
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
return 3;
}
radius: 1.5
color: Theme.primary
@@ -68,8 +65,13 @@ Item {
easing.type: Easing.BezierSpline
easing.bezierCurve: Anims.standardDecel
}
}
}
}
}
}

View File

@@ -15,113 +15,156 @@ Rectangle {
property real barHeight: 48
readonly property real horizontalPadding: SettingsData.topBarNoBackground ? 0 : Math.max(Theme.spacingXS, Theme.spacingS * (widgetHeight / 30))
signal toggleBatteryPopup
signal toggleBatteryPopup()
width: batteryContent.implicitWidth + horizontalPadding * 2
height: widgetHeight
radius: SettingsData.topBarNoBackground ? 0 : Theme.cornerRadius
color: {
if (SettingsData.topBarNoBackground) return "transparent"
const baseColor = batteryArea.containsMouse
|| batteryPopupVisible ? Theme.primaryPressed : Theme.secondaryHover
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
if (SettingsData.topBarNoBackground)
return "transparent";
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 {
id: batteryContent
anchors.centerIn: parent
spacing: SettingsData.topBarNoBackground ? 1 : 2
DankIcon {
name: {
if (!BatteryService.batteryAvailable)
return "power"
if (!BatteryService.batteryAvailable) {
return "power";
}
if (BatteryService.isCharging) {
if (BatteryService.batteryLevel >= 90)
return "battery_charging_full"
if (BatteryService.batteryLevel >= 80)
return "battery_charging_90"
if (BatteryService.batteryLevel >= 60)
return "battery_charging_80"
if (BatteryService.batteryLevel >= 50)
return "battery_charging_60"
if (BatteryService.batteryLevel >= 30)
return "battery_charging_50"
if (BatteryService.batteryLevel >= 20)
return "battery_charging_30"
return "battery_charging_20"
}
if (BatteryService.batteryLevel >= 90) {
return "battery_charging_full";
}
if (BatteryService.batteryLevel >= 80) {
return "battery_charging_90";
}
if (BatteryService.batteryLevel >= 60) {
return "battery_charging_80";
}
if (BatteryService.batteryLevel >= 50) {
return "battery_charging_60";
}
if (BatteryService.batteryLevel >= 30) {
return "battery_charging_50";
}
if (BatteryService.batteryLevel >= 20) {
return "battery_charging_30";
}
return "battery_charging_20";
}
// Check if plugged in but not charging (like at 80% charge limit)
if (BatteryService.isPluggedIn) {
if (BatteryService.batteryLevel >= 90)
return "battery_charging_full"
if (BatteryService.batteryLevel >= 80)
return "battery_charging_90"
if (BatteryService.batteryLevel >= 60)
return "battery_charging_80"
if (BatteryService.batteryLevel >= 50)
return "battery_charging_60"
if (BatteryService.batteryLevel >= 30)
return "battery_charging_50"
if (BatteryService.batteryLevel >= 20)
return "battery_charging_30"
return "battery_charging_20"
if (BatteryService.batteryLevel >= 90) {
return "battery_charging_full";
}
if (BatteryService.batteryLevel >= 80) {
return "battery_charging_90";
}
if (BatteryService.batteryLevel >= 60) {
return "battery_charging_80";
}
if (BatteryService.batteryLevel >= 50) {
return "battery_charging_60";
}
if (BatteryService.batteryLevel >= 30) {
return "battery_charging_50";
}
if (BatteryService.batteryLevel >= 20) {
return "battery_charging_30";
}
return "battery_charging_20";
}
// On battery power
if (BatteryService.batteryLevel >= 95) {
return "battery_full";
}
// On battery power
if (BatteryService.batteryLevel >= 95)
return "battery_full"
if (BatteryService.batteryLevel >= 85)
return "battery_6_bar"
if (BatteryService.batteryLevel >= 70)
return "battery_5_bar"
if (BatteryService.batteryLevel >= 55)
return "battery_4_bar"
if (BatteryService.batteryLevel >= 40)
return "battery_3_bar"
if (BatteryService.batteryLevel >= 25)
return "battery_2_bar"
return "battery_1_bar"
if (BatteryService.batteryLevel >= 85) {
return "battery_6_bar";
}
if (BatteryService.batteryLevel >= 70) {
return "battery_5_bar";
}
if (BatteryService.batteryLevel >= 55) {
return "battery_4_bar";
}
if (BatteryService.batteryLevel >= 40) {
return "battery_3_bar";
}
if (BatteryService.batteryLevel >= 25) {
return "battery_2_bar";
}
return "battery_1_bar";
}
size: Theme.iconSize - 6
color: {
if (!BatteryService.batteryAvailable)
return Theme.surfaceText
if (!BatteryService.batteryAvailable) {
return Theme.surfaceText;
}
if (BatteryService.isLowBattery && !BatteryService.isCharging)
return Theme.error
if (BatteryService.isLowBattery && !BatteryService.isCharging) {
return Theme.error;
}
if (BatteryService.isCharging || BatteryService.isPluggedIn)
return Theme.primary
if (BatteryService.isCharging || BatteryService.isPluggedIn) {
return Theme.primary;
}
return Theme.surfaceText
return Theme.surfaceText;
}
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: BatteryService.batteryLevel + "%"
text: `${BatteryService.batteryLevel}%`
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
color: {
if (!BatteryService.batteryAvailable)
return Theme.surfaceText
if (!BatteryService.batteryAvailable) {
return Theme.surfaceText;
}
if (BatteryService.isLowBattery && !BatteryService.isCharging)
return Theme.error
if (BatteryService.isLowBattery && !BatteryService.isCharging) {
return Theme.error;
}
if (BatteryService.isCharging)
return Theme.primary
if (BatteryService.isCharging) {
return Theme.primary;
}
return Theme.surfaceText
return Theme.surfaceText;
}
anchors.verticalCenter: parent.verticalCenter
visible: BatteryService.batteryAvailable
}
}
MouseArea {
@@ -132,15 +175,13 @@ Rectangle {
cursorShape: Qt.PointingHandCursor
onPressed: {
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, barHeight + Theme.spacingXS,
width, section, currentScreen)
const globalPos = mapToGlobal(0, 0);
const currentScreen = parentScreen || Screen;
const screenX = currentScreen.x || 0;
const relativeX = globalPos.x - screenX;
popupTarget.setTriggerPosition(relativeX, barHeight + Theme.spacingXS, width, section, currentScreen);
}
toggleBatteryPopup()
toggleBatteryPopup();
}
}
@@ -168,30 +209,33 @@ Rectangle {
text: {
if (!BatteryService.batteryAvailable) {
if (typeof PowerProfiles === "undefined")
return "Power Management"
if (typeof PowerProfiles === "undefined") {
return "Power Management";
}
switch (PowerProfiles.profile) {
case PowerProfile.PowerSaver:
return "Power Profile: Power Saver"
return "Power Profile: Power Saver";
case PowerProfile.Performance:
return "Power Profile: Performance"
return "Power Profile: Performance";
default:
return "Power Profile: Balanced"
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
const status = BatteryService.batteryStatus;
const level = `${BatteryService.batteryLevel}%`;
const 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 {
@@ -199,7 +243,9 @@ Rectangle {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}
Behavior on color {
@@ -207,5 +253,7 @@ Rectangle {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}

View File

@@ -15,28 +15,31 @@ DankPopout {
property var triggerScreen: null
function setTriggerPosition(x, y, width, section, screen) {
triggerX = x
triggerY = y
triggerWidth = width
triggerSection = section
triggerScreen = screen
triggerX = x;
triggerY = y;
triggerWidth = width;
triggerSection = section;
triggerScreen = screen;
}
function isActiveProfile(profile) {
if (typeof PowerProfiles === "undefined")
return false
if (typeof PowerProfiles === "undefined") {
return false;
}
return PowerProfiles.profile === profile
return PowerProfiles.profile === profile;
}
function setProfile(profile) {
if (typeof PowerProfiles === "undefined") {
ToastService.showError("power-profiles-daemon not available")
return
ToastService.showError("power-profiles-daemon not available");
return ;
}
PowerProfiles.profile = profile
if (PowerProfiles.profile !== profile)
ToastService.showError("Failed to set power profile")
PowerProfiles.profile = profile;
if (PowerProfiles.profile !== profile) {
ToastService.showError("Failed to set power profile");
}
}
popupWidth: 400
@@ -62,26 +65,29 @@ DankPopout {
antialiasing: true
smooth: true
focus: true
Component.onCompleted: {
if (root.shouldBeVisible)
forceActiveFocus()
}
if (root.shouldBeVisible) {
forceActiveFocus();
}
Keys.onPressed: function (event) {
}
Keys.onPressed: function(event) {
if (event.key === Qt.Key_Escape) {
root.close()
event.accepted = true
root.close();
event.accepted = true;
}
}
Connections {
function onShouldBeVisibleChanged() {
if (root.shouldBeVisible)
Qt.callLater(function () {
batteryContent.forceActiveFocus()
})
if (root.shouldBeVisible) {
Qt.callLater(function() {
batteryContent.forceActiveFocus();
});
}
}
target: root
}
@@ -116,6 +122,7 @@ DankPopout {
Column {
id: contentColumn
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
@@ -156,23 +163,21 @@ DankPopout {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onPressed: {
root.close()
root.close();
}
}
}
}
Rectangle {
width: parent.width
height: 80
radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r,
Theme.surfaceVariant.g,
Theme.surfaceVariant.b,
Theme.getContentBackgroundAlpha() * 0.4)
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, Theme.getContentBackgroundAlpha() * 0.4)
border.color: BatteryService.isCharging ? Theme.primary : (BatteryService.isLowBattery ? Theme.error : Theme.outlineMedium)
border.width: BatteryService.isCharging
|| BatteryService.isLowBattery ? 2 : 1
border.width: BatteryService.isCharging || BatteryService.isLowBattery ? 2 : 1
visible: BatteryService.batteryAvailable
Row {
@@ -184,67 +189,99 @@ DankPopout {
DankIcon {
name: {
if (!BatteryService.batteryAvailable)
return "power"
return "power";
// Check if plugged in but not charging (like at 80% charge limit)
if (!BatteryService.isCharging
&& BatteryService.isPluggedIn) {
if (BatteryService.batteryLevel >= 90)
return "battery_charging_full"
if (BatteryService.batteryLevel >= 80)
return "battery_charging_90"
if (BatteryService.batteryLevel >= 60)
return "battery_charging_80"
if (BatteryService.batteryLevel >= 50)
return "battery_charging_60"
if (BatteryService.batteryLevel >= 30)
return "battery_charging_50"
if (BatteryService.batteryLevel >= 20)
return "battery_charging_30"
return "battery_charging_20"
}
if (!BatteryService.isCharging && BatteryService.isPluggedIn) {
if (BatteryService.batteryLevel >= 90) {
return "battery_charging_full";
}
if (BatteryService.batteryLevel >= 80) {
return "battery_charging_90";
}
if (BatteryService.batteryLevel >= 60) {
return "battery_charging_80";
}
if (BatteryService.batteryLevel >= 50) {
return "battery_charging_60";
}
if (BatteryService.batteryLevel >= 30) {
return "battery_charging_50";
}
if (BatteryService.batteryLevel >= 20) {
return "battery_charging_30";
}
return "battery_charging_20";
}
if (BatteryService.isCharging) {
if (BatteryService.batteryLevel >= 90)
return "battery_charging_full"
if (BatteryService.batteryLevel >= 80)
return "battery_charging_90"
if (BatteryService.batteryLevel >= 60)
return "battery_charging_80"
if (BatteryService.batteryLevel >= 50)
return "battery_charging_60"
if (BatteryService.batteryLevel >= 30)
return "battery_charging_50"
if (BatteryService.batteryLevel >= 20)
return "battery_charging_30"
return "battery_charging_20"
if (BatteryService.batteryLevel >= 90) {
return "battery_charging_full";
}
if (BatteryService.batteryLevel >= 80) {
return "battery_charging_90";
}
if (BatteryService.batteryLevel >= 60) {
return "battery_charging_80";
}
if (BatteryService.batteryLevel >= 50) {
return "battery_charging_60";
}
if (BatteryService.batteryLevel >= 30) {
return "battery_charging_50";
}
if (BatteryService.batteryLevel >= 20) {
return "battery_charging_30";
}
return "battery_charging_20";
} else {
if (BatteryService.batteryLevel >= 95)
return "battery_full"
if (BatteryService.batteryLevel >= 85)
return "battery_6_bar"
if (BatteryService.batteryLevel >= 70)
return "battery_5_bar"
if (BatteryService.batteryLevel >= 55)
return "battery_4_bar"
if (BatteryService.batteryLevel >= 40)
return "battery_3_bar"
if (BatteryService.batteryLevel >= 25)
return "battery_2_bar"
return "battery_1_bar"
if (BatteryService.batteryLevel >= 95) {
return "battery_full";
}
if (BatteryService.batteryLevel >= 85) {
return "battery_6_bar";
}
if (BatteryService.batteryLevel >= 70) {
return "battery_5_bar";
}
if (BatteryService.batteryLevel >= 55) {
return "battery_4_bar";
}
if (BatteryService.batteryLevel >= 40) {
return "battery_3_bar";
}
if (BatteryService.batteryLevel >= 25) {
return "battery_2_bar";
}
return "battery_1_bar";
}
}
size: Theme.iconSizeLarge
color: {
if (BatteryService.isLowBattery
&& !BatteryService.isCharging)
return Theme.error
if (BatteryService.isLowBattery && !BatteryService.isCharging)
return Theme.error;
if (BatteryService.isCharging
|| BatteryService.isPluggedIn)
return Theme.primary
if (BatteryService.isCharging || BatteryService.isPluggedIn)
return Theme.primary;
return Theme.surfaceText
return Theme.surfaceText;
}
anchors.verticalCenter: parent.verticalCenter
}
@@ -257,17 +294,18 @@ DankPopout {
spacing: Theme.spacingM
StyledText {
text: BatteryService.batteryLevel + "%"
text: `${BatteryService.batteryLevel}%`
font.pixelSize: Theme.fontSizeLarge
color: {
if (BatteryService.isLowBattery
&& !BatteryService.isCharging)
return Theme.error
if (BatteryService.isLowBattery && !BatteryService.isCharging) {
return Theme.error;
}
if (BatteryService.isCharging)
return Theme.primary
if (BatteryService.isCharging) {
return Theme.primary;
}
return Theme.surfaceText
return Theme.surfaceText;
}
font.weight: Font.Bold
}
@@ -276,44 +314,47 @@ DankPopout {
text: BatteryService.batteryStatus
font.pixelSize: Theme.fontSizeMedium
color: {
if (BatteryService.isLowBattery
&& !BatteryService.isCharging)
return Theme.error
if (BatteryService.isLowBattery && !BatteryService.isCharging) {
return Theme.error;
}
if (BatteryService.isCharging)
return Theme.primary
if (BatteryService.isCharging) {
return Theme.primary;
}
return Theme.surfaceText
return Theme.surfaceText;
}
font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter
}
}
StyledText {
text: {
let time = BatteryService.formatTimeRemaining()
if (time !== "Unknown")
return BatteryService.isCharging ? "Time until full: " + time : "Time remaining: " + time
const time = BatteryService.formatTimeRemaining();
if (time !== "Unknown") {
return BatteryService.isCharging ? `Time until full: ${time}` : `Time remaining: ${time}`;
}
return ""
return "";
}
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceTextMedium
visible: text.length > 0
}
}
}
}
Rectangle {
width: parent.width
height: 80
radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r,
Theme.surfaceVariant.g,
Theme.surfaceVariant.b,
Theme.getContentBackgroundAlpha() * 0.4)
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, Theme.getContentBackgroundAlpha() * 0.4)
border.color: Theme.outlineMedium
border.width: 1
visible: !BatteryService.batteryAvailable
@@ -345,8 +386,11 @@ DankPopout {
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceTextMedium
}
}
}
}
Column {
@@ -380,14 +424,15 @@ DankPopout {
text: BatteryService.batteryHealth
font.pixelSize: Theme.fontSizeMedium
color: {
if (BatteryService.batteryHealth === "N/A")
return Theme.surfaceText
if (BatteryService.batteryHealth === "N/A") {
return Theme.surfaceText;
}
var healthNum = parseInt(
BatteryService.batteryHealth)
return healthNum < 80 ? Theme.error : Theme.surfaceText
const healthNum = parseInt(BatteryService.batteryHealth);
return healthNum < 80 ? Theme.error : Theme.surfaceText;
}
}
}
Column {
@@ -402,14 +447,15 @@ DankPopout {
}
StyledText {
text: BatteryService.batteryCapacity
> 0 ? BatteryService.batteryCapacity.toFixed(
1) + " Wh" : "Unknown"
text: BatteryService.batteryCapacity > 0 ? `${BatteryService.batteryCapacity.toFixed(1)} Wh` : "Unknown"
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceText
}
}
}
}
Column {
@@ -436,10 +482,8 @@ DankPopout {
height: 50
radius: Theme.cornerRadius
color: profileArea.containsMouse ? Theme.primaryHoverLight : (root.isActiveProfile(modelData) ? Theme.primaryPressed : Theme.surfaceLight)
border.color: root.isActiveProfile(
modelData) ? Theme.primary : Theme.outlineLight
border.width: root.isActiveProfile(
modelData) ? 2 : 1
border.color: root.isActiveProfile(modelData) ? Theme.primary : Theme.outlineLight
border.width: root.isActiveProfile(modelData) ? 2 : 1
Row {
anchors.left: parent.left
@@ -448,11 +492,9 @@ DankPopout {
spacing: Theme.spacingM
DankIcon {
name: Theme.getPowerProfileIcon(
modelData)
name: Theme.getPowerProfileIcon(modelData)
size: Theme.iconSize
color: root.isActiveProfile(
modelData) ? Theme.primary : Theme.surfaceText
color: root.isActiveProfile(modelData) ? Theme.primary : Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
@@ -461,22 +503,20 @@ DankPopout {
anchors.verticalCenter: parent.verticalCenter
StyledText {
text: Theme.getPowerProfileLabel(
modelData)
text: Theme.getPowerProfileLabel(modelData)
font.pixelSize: Theme.fontSizeMedium
color: root.isActiveProfile(
modelData) ? Theme.primary : Theme.surfaceText
font.weight: root.isActiveProfile(
modelData) ? Font.Medium : Font.Normal
color: root.isActiveProfile(modelData) ? Theme.primary : Theme.surfaceText
font.weight: root.isActiveProfile(modelData) ? Font.Medium : Font.Normal
}
StyledText {
text: Theme.getPowerProfileDescription(
modelData)
text: Theme.getPowerProfileDescription(modelData)
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceTextMedium
}
}
}
MouseArea {
@@ -486,12 +526,16 @@ DankPopout {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onPressed: {
root.setProfile(modelData)
root.setProfile(modelData);
}
}
}
}
}
}
Rectangle {
@@ -501,9 +545,7 @@ DankPopout {
color: Theme.errorHover
border.color: Theme.primarySelected
border.width: 1
visible: (typeof PowerProfiles !== "undefined")
&& PowerProfiles.degradationReason
!== PerformanceDegradationReason.None
visible: (typeof PowerProfiles !== "undefined") && PowerProfiles.degradationReason !== PerformanceDegradationReason.None
Row {
anchors.left: parent.left
@@ -530,17 +572,21 @@ DankPopout {
}
StyledText {
text: (typeof PowerProfiles
!== "undefined") ? PerformanceDegradationReason.toString(
PowerProfiles.degradationReason) : ""
text: (typeof PowerProfiles !== "undefined") ? PerformanceDegradationReason.toString(PowerProfiles.degradationReason) : ""
font.pixelSize: Theme.fontSizeSmall
color: Qt.rgba(Theme.error.r, Theme.error.g,
Theme.error.b, 0.8)
color: Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.8)
}
}
}
}
}
}
}
}

View File

@@ -21,10 +21,12 @@ Rectangle {
height: widgetHeight
radius: SettingsData.topBarNoBackground ? 0 : Theme.cornerRadius
color: {
if (SettingsData.topBarNoBackground) return "transparent"
if (SettingsData.topBarNoBackground) {
return "transparent"
}
const baseColor = clockMouseArea.containsMouse ? Theme.primaryHover : Theme.surfaceTextHover
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency)
}
Component.onCompleted: {
root.currentDate = systemClock.date
@@ -39,7 +41,7 @@ Rectangle {
StyledText {
text: {
if (SettingsData.use24HourClock) {
return root.currentDate.toLocaleTimeString(Qt.locale(), Locale.ShortFormat)
return root.currentDate.toLocaleTimeString(Qt.locale(), "HH:mm")
} else {
return root.currentDate.toLocaleTimeString(Qt.locale(), "h:mm AP")
}
@@ -62,6 +64,7 @@ Rectangle {
if (SettingsData.clockDateFormat && SettingsData.clockDateFormat.length > 0) {
return root.currentDate.toLocaleDateString(Qt.locale(), SettingsData.clockDateFormat)
}
return root.currentDate.toLocaleDateString(Qt.locale(), "ddd d")
}
font.pixelSize: Theme.fontSizeMedium - 1
@@ -86,13 +89,11 @@ Rectangle {
cursorShape: Qt.PointingHandCursor
onPressed: {
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, barHeight + Theme.spacingXS,
width, section, currentScreen)
const globalPos = mapToGlobal(0, 0)
const currentScreen = parentScreen || Screen
const screenX = currentScreen.x || 0
const relativeX = globalPos.x - screenX
popupTarget.setTriggerPosition(relativeX, barHeight + Theme.spacingXS, width, section, currentScreen)
}
root.clockClicked()
}

View File

@@ -11,7 +11,6 @@ Rectangle {
property var popupTarget: null
property var parentScreen: null
property var widgetData: null
property bool showNetworkIcon: SettingsData.controlCenterShowNetworkIcon
property bool showBluetoothIcon: SettingsData.controlCenterShowBluetoothIcon
property bool showAudioIcon: SettingsData.controlCenterShowAudioIcon
@@ -19,17 +18,18 @@ Rectangle {
property real barHeight: 48
readonly property real horizontalPadding: SettingsData.topBarNoBackground ? 0 : Math.max(Theme.spacingXS, Theme.spacingS * (widgetHeight / 30))
signal clicked
signal clicked()
width: controlIndicators.implicitWidth + horizontalPadding * 2
height: widgetHeight
radius: SettingsData.topBarNoBackground ? 0 : Theme.cornerRadius
color: {
if (SettingsData.topBarNoBackground) return "transparent"
const baseColor = controlCenterArea.containsMouse
|| root.isActive ? Theme.primaryPressed : Theme.secondaryHover
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
if (SettingsData.topBarNoBackground) {
return "transparent";
}
const baseColor = controlCenterArea.containsMouse || root.isActive ? Theme.primaryPressed : Theme.secondaryHover;
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
}
Row {
@@ -40,21 +40,29 @@ Rectangle {
DankIcon {
id: networkIcon
name: {
if (NetworkService.wifiToggling)
return "sync"
if (NetworkService.networkStatus === "ethernet")
return "lan"
return NetworkService.wifiSignalIcon
if (NetworkService.wifiToggling) {
return "sync";
}
if (NetworkService.networkStatus === "ethernet") {
return "lan";
}
return NetworkService.wifiSignalIcon;
}
size: Theme.iconSize - 8
color: {
if (NetworkService.wifiToggling) return Theme.primary
return NetworkService.networkStatus !== "disconnected" ? Theme.primary : Theme.outlineButton
if (NetworkService.wifiToggling) {
return Theme.primary;
}
return NetworkService.networkStatus !== "disconnected" ? Theme.primary : Theme.outlineButton;
}
anchors.verticalCenter: parent.verticalCenter
visible: root.showNetworkIcon
RotationAnimation on rotation {
running: NetworkService.wifiToggling
loops: Animation.Infinite
@@ -62,10 +70,12 @@ Rectangle {
to: 360
duration: 1000
}
}
DankIcon {
id: bluetoothIcon
name: "bluetooth"
size: Theme.iconSize - 8
color: BluetoothService.enabled ? Theme.primary : Theme.outlineButton
@@ -85,15 +95,15 @@ Rectangle {
name: {
if (AudioService.sink && AudioService.sink.audio) {
if (AudioService.sink.audio.muted
|| AudioService.sink.audio.volume === 0)
return "volume_off"
else if (AudioService.sink.audio.volume * 100 < 33)
return "volume_down"
else
return "volume_up"
if (AudioService.sink.audio.muted || AudioService.sink.audio.volume === 0) {
return "volume_off";
} else if (AudioService.sink.audio.volume * 100 < 33) {
return "volume_down";
} else {
return "volume_up";
}
}
return "volume_up"
return "volume_up";
}
size: Theme.iconSize - 8
color: Theme.surfaceText
@@ -106,25 +116,24 @@ Rectangle {
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
AudioService.volumeChanged()
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);
}
wheelEvent.accepted = true
if (AudioService.sink && AudioService.sink.audio) {
AudioService.sink.audio.muted = false;
AudioService.sink.audio.volume = newVolume / 100;
AudioService.volumeChanged();
}
wheelEvent.accepted = true;
}
}
}
DankIcon {
@@ -143,6 +152,7 @@ Rectangle {
anchors.verticalCenter: parent.verticalCenter
visible: !root.showNetworkIcon && !root.showBluetoothIcon && !root.showAudioIcon
}
}
MouseArea {
@@ -153,16 +163,13 @@ Rectangle {
cursorShape: Qt.PointingHandCursor
onPressed: {
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, barHeight + Theme.spacingXS,
width, section, currentScreen)
const globalPos = mapToGlobal(0, 0);
const currentScreen = parentScreen || Screen;
const screenX = currentScreen.x || 0;
const relativeX = globalPos.x - screenX;
popupTarget.setTriggerPosition(relativeX, barHeight + Theme.spacingXS, width, section, currentScreen);
}
root.clicked()
root.clicked();
}
}
@@ -171,5 +178,7 @@ Rectangle {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}

View File

@@ -21,16 +21,18 @@ Rectangle {
height: widgetHeight
radius: SettingsData.topBarNoBackground ? 0 : Theme.cornerRadius
color: {
if (SettingsData.topBarNoBackground) return "transparent"
const baseColor = cpuArea.containsMouse ? Theme.primaryPressed : Theme.secondaryHover
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
if (SettingsData.topBarNoBackground) {
return "transparent";
}
const baseColor = cpuArea.containsMouse ? Theme.primaryPressed : Theme.secondaryHover;
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
}
Component.onCompleted: {
DgopService.addRef(["cpu"])
DgopService.addRef(["cpu"]);
}
Component.onDestruction: {
DgopService.removeRef(["cpu"])
DgopService.removeRef(["cpu"]);
}
MouseArea {
@@ -41,22 +43,23 @@ Rectangle {
cursorShape: Qt.PointingHandCursor
onPressed: {
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, barHeight + Theme.spacingXS,
width, section, currentScreen)
const globalPos = mapToGlobal(0, 0);
const currentScreen = parentScreen || Screen;
const screenX = currentScreen.x || 0;
const relativeX = globalPos.x - screenX;
popupTarget.setTriggerPosition(relativeX, barHeight + Theme.spacingXS, width, section, currentScreen);
}
DgopService.setSortBy("cpu")
if (root.toggleProcessList)
root.toggleProcessList()
DgopService.setSortBy("cpu");
if (root.toggleProcessList) {
root.toggleProcessList();
}
}
}
Row {
id: cpuContent
anchors.centerIn: parent
spacing: 3
@@ -64,30 +67,33 @@ Rectangle {
name: "memory"
size: Theme.iconSize - 8
color: {
if (DgopService.cpuUsage > 80)
return Theme.tempDanger
if (DgopService.cpuUsage > 80) {
return Theme.tempDanger;
}
if (DgopService.cpuUsage > 60)
return Theme.tempWarning
if (DgopService.cpuUsage > 60) {
return Theme.tempWarning;
}
return Theme.surfaceText
return Theme.surfaceText;
}
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: {
if (DgopService.cpuUsage === undefined
|| DgopService.cpuUsage === null
|| DgopService.cpuUsage === 0) {
return "--%"
if (DgopService.cpuUsage === undefined || DgopService.cpuUsage === null || DgopService.cpuUsage === 0) {
return "--%";
}
return DgopService.cpuUsage.toFixed(0) + "%"
return DgopService.cpuUsage.toFixed(0) + "%";
}
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
}

View File

@@ -21,16 +21,18 @@ Rectangle {
height: widgetHeight
radius: SettingsData.topBarNoBackground ? 0 : Theme.cornerRadius
color: {
if (SettingsData.topBarNoBackground) return "transparent"
const baseColor = cpuTempArea.containsMouse ? Theme.primaryPressed : Theme.secondaryHover
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
if (SettingsData.topBarNoBackground) {
return "transparent";
}
const baseColor = cpuTempArea.containsMouse ? Theme.primaryPressed : Theme.secondaryHover;
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
}
Component.onCompleted: {
DgopService.addRef(["cpu"])
DgopService.addRef(["cpu"]);
}
Component.onDestruction: {
DgopService.removeRef(["cpu"])
DgopService.removeRef(["cpu"]);
}
MouseArea {
@@ -41,22 +43,23 @@ Rectangle {
cursorShape: Qt.PointingHandCursor
onPressed: {
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, barHeight + Theme.spacingXS,
width, section, currentScreen)
const globalPos = mapToGlobal(0, 0);
const currentScreen = parentScreen || Screen;
const screenX = currentScreen.x || 0;
const relativeX = globalPos.x - screenX;
popupTarget.setTriggerPosition(relativeX, barHeight + Theme.spacingXS, width, section, currentScreen);
}
DgopService.setSortBy("cpu")
if (root.toggleProcessList)
root.toggleProcessList()
DgopService.setSortBy("cpu");
if (root.toggleProcessList) {
root.toggleProcessList();
}
}
}
Row {
id: cpuTempContent
anchors.centerIn: parent
spacing: 3
@@ -64,31 +67,33 @@ Rectangle {
name: "memory"
size: Theme.iconSize - 8
color: {
if (DgopService.cpuTemperature > 85)
return Theme.tempDanger
if (DgopService.cpuTemperature > 85) {
return Theme.tempDanger;
}
if (DgopService.cpuTemperature > 69)
return Theme.tempWarning
if (DgopService.cpuTemperature > 69) {
return Theme.tempWarning;
}
return Theme.surfaceText
return Theme.surfaceText;
}
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: {
if (DgopService.cpuTemperature === undefined
|| DgopService.cpuTemperature === null
|| DgopService.cpuTemperature < 0) {
return "--°"
if (DgopService.cpuTemperature === undefined || DgopService.cpuTemperature === null || DgopService.cpuTemperature < 0) {
return "--°";
}
return Math.round(DgopService.cpuTemperature) + "°"
return Math.round(DgopService.cpuTemperature) + "°";
}
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
Behavior on color {
@@ -96,5 +101,7 @@ Rectangle {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}

View File

@@ -1,6 +1,6 @@
import QtQuick
import Quickshell
import Quickshell.Wayland
import QtQuick
import qs.Common
import qs.Services
import qs.Widgets
@@ -17,19 +17,20 @@ Rectangle {
readonly property int maxCompactWidth: 288
readonly property Toplevel activeWindow: ToplevelManager.activeToplevel
width: compactMode ? Math.min(baseWidth,
maxCompactWidth) : Math.min(baseWidth,
maxNormalWidth)
width: compactMode ? Math.min(baseWidth, maxCompactWidth) : Math.min(baseWidth, maxNormalWidth)
height: widgetHeight
radius: SettingsData.topBarNoBackground ? 0 : Theme.cornerRadius
color: {
if (!activeWindow || !activeWindow.title)
return "transparent"
if (SettingsData.topBarNoBackground) return "transparent"
const baseColor = mouseArea.containsMouse ? Theme.primaryHover : Theme.surfaceTextHover
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
if (!activeWindow || !activeWindow.title) {
return "transparent";
}
if (SettingsData.topBarNoBackground) {
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: activeWindow && activeWindow.title
@@ -44,12 +45,12 @@ Rectangle {
id: appText
text: {
if (!activeWindow || !activeWindow.appId)
return ""
if (!activeWindow || !activeWindow.appId) {
return "";
}
var desktopEntry = DesktopEntries.heuristicLookup(activeWindow.appId)
return desktopEntry
&& desktopEntry.name ? desktopEntry.name : activeWindow.appId
const desktopEntry = DesktopEntries.heuristicLookup(activeWindow.appId);
return desktopEntry && desktopEntry.name ? desktopEntry.name : activeWindow.appId;
}
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
@@ -73,24 +74,22 @@ Rectangle {
id: titleText
text: {
var title = activeWindow && activeWindow.title ? activeWindow.title : ""
var appName = appText.text
if (!title || !appName)
return title
const title = activeWindow && activeWindow.title ? activeWindow.title : "";
const appName = appText.text;
if (!title || !appName) {
return title;
}
// Remove app name from end of title if it exists there
if (title.endsWith(" - " + appName)) {
return title.substring(
0, title.length - (" - " + appName).length)
}
if (title.endsWith(appName)) {
return title.substring(
0, title.length - appName.length).replace(
/ - $/, "")
return title.substring(0, title.length - (" - " + appName).length);
}
return title
if (title.endsWith(appName)) {
return title.substring(0, title.length - appName.length).replace(/ - $/, "");
}
return title;
}
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
@@ -101,6 +100,7 @@ Rectangle {
width: Math.min(implicitWidth, compactMode ? 280 : 250)
visible: text.length > 0
}
}
MouseArea {
@@ -115,6 +115,7 @@ Rectangle {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
Behavior on width {
@@ -122,5 +123,7 @@ Rectangle {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}

View File

@@ -16,64 +16,97 @@ Rectangle {
property var widgetData: null
property real barHeight: 48
property real widgetHeight: 30
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 int selectedGpuIndex: (widgetData && widgetData.selectedGpuIndex !== undefined) ? widgetData.selectedGpuIndex : 0
readonly property real horizontalPadding: SettingsData.topBarNoBackground ? 0 : Math.max(Theme.spacingXS, Theme.spacingS * (widgetHeight / 30))
property real displayTemp: {
if (!DgopService.availableGpus || DgopService.availableGpus.length === 0) {
return 0;
}
if (selectedGpuIndex >= 0 && selectedGpuIndex < DgopService.availableGpus.length) {
return DgopService.availableGpus[selectedGpuIndex].temperature || 0;
}
return 0;
}
readonly property real horizontalPadding: SettingsData.topBarNoBackground ? 0 : Math.max(Theme.spacingXS, Theme.spacingS * (widgetHeight / 30))
function updateWidgetPciId(pciId) {
// Find and update this widget's pciId in the settings
const sections = ["left", "center", "right"];
for (let s = 0; s < sections.length; s++) {
const sectionId = sections[s];
let widgets = [];
if (sectionId === "left") {
widgets = SettingsData.topBarLeftWidgets.slice();
} else if (sectionId === "center") {
widgets = SettingsData.topBarCenterWidgets.slice();
} else if (sectionId === "right") {
widgets = SettingsData.topBarRightWidgets.slice();
}
for (let i = 0; i < widgets.length; i++) {
const widget = widgets[i];
if (typeof widget === "object" && widget.id === "gpuTemp" && (!widget.pciId || widget.pciId === "")) {
widgets[i] = {
"id": widget.id,
"enabled": widget.enabled !== undefined ? widget.enabled : true,
"selectedGpuIndex": 0,
"pciId": pciId
};
if (sectionId === "left") {
SettingsData.setTopBarLeftWidgets(widgets);
} else if (sectionId === "center") {
SettingsData.setTopBarCenterWidgets(widgets);
} else if (sectionId === "right") {
SettingsData.setTopBarRightWidgets(widgets);
}
return ;
}
}
}
}
width: gpuTempContent.implicitWidth + horizontalPadding * 2
height: widgetHeight
radius: SettingsData.topBarNoBackground ? 0 : Theme.cornerRadius
color: {
if (SettingsData.topBarNoBackground) return "transparent"
const baseColor = gpuArea.containsMouse ? Theme.primaryPressed : Theme.secondaryHover
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
if (SettingsData.topBarNoBackground) {
return "transparent";
}
const baseColor = gpuArea.containsMouse ? Theme.primaryPressed : Theme.secondaryHover;
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
}
Component.onCompleted: {
DgopService.addRef(["gpu"])
console.log("GpuTemperature widget - pciId:",
widgetData ? widgetData.pciId : "no widgetData",
"selectedGpuIndex:",
widgetData ? widgetData.selectedGpuIndex : "no widgetData")
DgopService.addRef(["gpu"]);
console.log("GpuTemperature widget - pciId:", widgetData ? widgetData.pciId : "no widgetData", "selectedGpuIndex:", widgetData ? widgetData.selectedGpuIndex : "no widgetData");
// Add this widget's PCI ID to the service
if (widgetData && widgetData.pciId) {
console.log("Adding GPU PCI ID to service:", widgetData.pciId)
DgopService.addGpuPciId(widgetData.pciId)
console.log("Adding GPU PCI ID to service:", widgetData.pciId);
DgopService.addGpuPciId(widgetData.pciId);
} else {
console.log("No PCI ID in widget data, starting auto-detection")
console.log("No PCI ID in widget data, starting auto-detection");
// No PCI ID saved, auto-detect and save the first GPU
autoSaveTimer.running = true
autoSaveTimer.running = true;
}
}
Component.onDestruction: {
DgopService.removeRef(["gpu"])
DgopService.removeRef(["gpu"]);
// Remove this widget's PCI ID from the service
if (widgetData && widgetData.pciId) {
DgopService.removeGpuPciId(widgetData.pciId)
DgopService.removeGpuPciId(widgetData.pciId);
}
}
property real displayTemp: {
if (!DgopService.availableGpus
|| DgopService.availableGpus.length === 0)
return 0
if (selectedGpuIndex >= 0
&& selectedGpuIndex < DgopService.availableGpus.length) {
return DgopService.availableGpus[selectedGpuIndex].temperature || 0
Connections {
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;
});
}
return 0
target: SettingsData
}
MouseArea {
@@ -84,22 +117,23 @@ Rectangle {
cursorShape: Qt.PointingHandCursor
onPressed: {
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, barHeight + Theme.spacingXS,
width, section, currentScreen)
const globalPos = mapToGlobal(0, 0);
const currentScreen = parentScreen || Screen;
const screenX = currentScreen.x || 0;
const relativeX = globalPos.x - screenX;
popupTarget.setTriggerPosition(relativeX, barHeight + Theme.spacingXS, width, section, currentScreen);
}
DgopService.setSortBy("cpu")
if (root.toggleProcessList)
root.toggleProcessList()
DgopService.setSortBy("cpu");
if (root.toggleProcessList) {
root.toggleProcessList();
}
}
}
Row {
id: gpuTempContent
anchors.centerIn: parent
spacing: 3
@@ -107,30 +141,50 @@ Rectangle {
name: "auto_awesome_mosaic"
size: Theme.iconSize - 8
color: {
if (root.displayTemp > 80)
return Theme.tempDanger
if (root.displayTemp > 80) {
return Theme.tempDanger;
}
if (root.displayTemp > 65)
return Theme.tempWarning
if (root.displayTemp > 65) {
return Theme.tempWarning;
}
return Theme.surfaceText
return Theme.surfaceText;
}
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: {
if (root.displayTemp === undefined || root.displayTemp === null
|| root.displayTemp === 0) {
return "--°"
if (root.displayTemp === undefined || root.displayTemp === null || root.displayTemp === 0) {
return "--°";
}
return Math.round(root.displayTemp) + "°"
return Math.round(root.displayTemp) + "°";
}
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
Timer {
id: autoSaveTimer
interval: 100
running: false
onTriggered: {
if (DgopService.availableGpus && DgopService.availableGpus.length > 0) {
const firstGpu = DgopService.availableGpus[0];
if (firstGpu && firstGpu.pciId) {
// Save the first GPU's PCI ID to this widget's settings
updateWidgetPciId(firstGpu.pciId);
DgopService.addGpuPciId(firstGpu.pciId);
}
}
}
}
Behavior on color {
@@ -138,58 +192,7 @@ Rectangle {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
Timer {
id: autoSaveTimer
interval: 100
running: false
onTriggered: {
if (DgopService.availableGpus
&& DgopService.availableGpus.length > 0) {
const firstGpu = DgopService.availableGpus[0]
if (firstGpu && firstGpu.pciId) {
// Save the first GPU's PCI ID to this widget's settings
updateWidgetPciId(firstGpu.pciId)
DgopService.addGpuPciId(firstGpu.pciId)
}
}
}
}
function updateWidgetPciId(pciId) {
// Find and update this widget's pciId in the settings
var sections = ["left", "center", "right"]
for (var s = 0; s < sections.length; s++) {
var sectionId = sections[s]
var widgets = []
if (sectionId === "left")
widgets = SettingsData.topBarLeftWidgets.slice()
else if (sectionId === "center")
widgets = SettingsData.topBarCenterWidgets.slice()
else if (sectionId === "right")
widgets = SettingsData.topBarRightWidgets.slice()
for (var i = 0; i < widgets.length; i++) {
var widget = widgets[i]
if (typeof widget === "object" && widget.id === "gpuTemp"
&& (!widget.pciId || widget.pciId === "")) {
widgets[i] = {
"id": widget.id,
"enabled": widget.enabled !== undefined ? widget.enabled : true,
"selectedGpuIndex": 0,
"pciId": pciId
}
if (sectionId === "left")
SettingsData.setTopBarLeftWidgets(widgets)
else if (sectionId === "center")
SettingsData.setTopBarCenterWidgets(widgets)
else if (sectionId === "right")
SettingsData.setTopBarRightWidgets(widgets)
return
}
}
}
}
}

View File

@@ -18,14 +18,17 @@ Rectangle {
height: widgetHeight
radius: SettingsData.topBarNoBackground ? 0 : Theme.cornerRadius
color: {
if (SettingsData.topBarNoBackground) return "transparent"
const baseColor = mouseArea.containsMouse ? Theme.primaryPressed : (SessionService.idleInhibited ? Theme.primaryHover : Theme.secondaryHover)
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
if (SettingsData.topBarNoBackground) {
return "transparent";
}
const baseColor = mouseArea.containsMouse ? Theme.primaryPressed : (SessionService.idleInhibited ? Theme.primaryHover : Theme.secondaryHover);
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
}
DankIcon {
id: idleIcon
anchors.centerIn: parent
name: SessionService.idleInhibited ? "motion_sensor_active" : "motion_sensor_idle"
size: Theme.iconSize - 6
@@ -38,9 +41,8 @@ Rectangle {
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
SessionService.toggleIdleInhibit()
SessionService.toggleIdleInhibit();
}
}
@@ -49,5 +51,7 @@ Rectangle {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}

View File

@@ -1,9 +1,9 @@
import QtQuick
import QtQuick.Controls
import qs.Common
import qs.Modules.ProcessList
import qs.Services
import qs.Widgets
import qs.Modules.ProcessList
Rectangle {
id: root
@@ -13,12 +13,13 @@ Rectangle {
width: contentRow.implicitWidth + horizontalPadding * 2
height: widgetHeight
radius: SettingsData.topBarNoBackground ? 0 : Theme.cornerRadius
color: {
if (SettingsData.topBarNoBackground) return "transparent"
const baseColor = mouseArea.containsMouse ? Theme.primaryPressed : Theme.secondaryHover
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
if (SettingsData.topBarNoBackground) {
return "transparent";
}
const baseColor = mouseArea.containsMouse ? Theme.primaryPressed : Theme.secondaryHover;
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
}
MouseArea {
@@ -27,9 +28,8 @@ Rectangle {
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
NiriService.cycleKeyboardLayout()
NiriService.cycleKeyboardLayout();
}
}
@@ -45,6 +45,7 @@ Rectangle {
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
Behavior on color {
@@ -52,5 +53,7 @@ Rectangle {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}

View File

@@ -14,41 +14,42 @@ Item {
property real barHeight: 48
readonly property real horizontalPadding: SettingsData.topBarNoBackground ? 0 : Math.max(Theme.spacingXS, Theme.spacingS * (widgetHeight / 30))
signal clicked
signal clicked()
width: Theme.iconSize + horizontalPadding * 2
height: widgetHeight
MouseArea {
id: launcherArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
acceptedButtons: Qt.LeftButton
onPressed: {
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, barHeight + Theme.spacingXS,
width, section, currentScreen)
const globalPos = mapToGlobal(0, 0);
const currentScreen = parentScreen || Screen;
const screenX = currentScreen.x || 0;
const relativeX = globalPos.x - screenX;
popupTarget.setTriggerPosition(relativeX, barHeight + Theme.spacingXS, width, section, currentScreen);
}
root.clicked()
root.clicked();
}
}
Rectangle {
id: launcherContent
anchors.fill: parent
radius: SettingsData.topBarNoBackground ? 0 : Theme.cornerRadius
color: {
if (SettingsData.topBarNoBackground) return "transparent"
const baseColor = launcherArea.containsMouse ? Theme.primaryPressed : (SessionService.idleInhibited ? Theme.primaryHover : Theme.secondaryHover)
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
if (SettingsData.topBarNoBackground) {
return "transparent";
}
const baseColor = launcherArea.containsMouse ? Theme.primaryPressed : (SessionService.idleInhibited ? Theme.primaryHover : Theme.secondaryHover);
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
}
SystemLogo {
@@ -74,6 +75,9 @@ Item {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}
}

View File

@@ -13,21 +13,21 @@ Rectangle {
readonly property int textWidth: {
switch (SettingsData.mediaSize) {
case 0:
return 0 // No text in small mode
return 0; // No text in small mode
case 2:
return 180 // Large text area
return 180; // Large text area
default:
return 120 // Medium text area
return 120; // Medium text area
}
}
readonly property int currentContentWidth: {
// Calculate actual content width:
// AudioViz (20) + spacing + [text + spacing] + controls (prev:20 + spacing + play:24 + spacing + next:20) + padding
const controlsWidth = 20 + Theme.spacingXS + 24 + Theme.spacingXS + 20 // ~72px total
const audioVizWidth = 20
const contentWidth = audioVizWidth + Theme.spacingXS + controlsWidth
return contentWidth + (textWidth > 0 ? textWidth + Theme.spacingXS : 0) + horizontalPadding * 2
const controlsWidth = 20 + Theme.spacingXS + 24 + Theme.spacingXS + 20;
// ~72px total
const audioVizWidth = 20;
const contentWidth = audioVizWidth + Theme.spacingXS + controlsWidth;
return contentWidth + (textWidth > 0 ? textWidth + Theme.spacingXS : 0) + horizontalPadding * 2;
}
property string section: "center"
property var popupTarget: null
@@ -36,15 +36,17 @@ Rectangle {
property real widgetHeight: 30
readonly property real horizontalPadding: SettingsData.topBarNoBackground ? 0 : Math.max(Theme.spacingXS, Theme.spacingS * (widgetHeight / 30))
signal clicked
signal clicked()
height: widgetHeight
radius: SettingsData.topBarNoBackground ? 0 : Theme.cornerRadius
color: {
if (SettingsData.topBarNoBackground) return "transparent"
const baseColor = Theme.surfaceTextHover
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
if (SettingsData.topBarNoBackground) {
return "transparent";
}
const baseColor = Theme.surfaceTextHover;
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
}
states: [
State {
@@ -56,6 +58,7 @@ Rectangle {
opacity: 1
width: currentContentWidth
}
},
State {
name: "hidden"
@@ -66,6 +69,7 @@ Rectangle {
opacity: 0
width: 0
}
}
]
transitions: [
@@ -83,7 +87,9 @@ Rectangle {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
},
Transition {
from: "hidden"
@@ -94,6 +100,7 @@ Rectangle {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
]
@@ -115,6 +122,25 @@ Rectangle {
Rectangle {
id: textContainer
property string displayText: {
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;
}
anchors.verticalCenter: parent.verticalCenter
width: textWidth
height: 20
@@ -122,48 +148,28 @@ Rectangle {
clip: true
color: "transparent"
property string displayText: {
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
}
StyledText {
id: mediaText
property bool needsScrolling: implicitWidth > textContainer.width
property real scrollOffset: 0
anchors.verticalCenter: parent.verticalCenter
text: textContainer.displayText
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
font.weight: Font.Medium
wrapMode: Text.NoWrap
property bool needsScrolling: implicitWidth > textContainer.width
property real scrollOffset: 0
x: needsScrolling ? -scrollOffset : 0
onTextChanged: {
scrollOffset = 0;
scrollAnimation.restart();
}
SequentialAnimation {
id: scrollAnimation
running: mediaText.needsScrolling
&& textContainer.visible
running: mediaText.needsScrolling && textContainer.visible
loops: Animation.Infinite
PauseAnimation {
@@ -175,9 +181,7 @@ Rectangle {
property: "scrollOffset"
from: 0
to: mediaText.implicitWidth - textContainer.width + 5
duration: Math.max(
1000,
(mediaText.implicitWidth - textContainer.width + 5) * 60)
duration: Math.max(1000, (mediaText.implicitWidth - textContainer.width + 5) * 60)
easing.type: Easing.Linear
}
@@ -189,41 +193,33 @@ Rectangle {
target: mediaText
property: "scrollOffset"
to: 0
duration: Math.max(
1000,
(mediaText.implicitWidth - textContainer.width + 5) * 60)
duration: Math.max(1000, (mediaText.implicitWidth - textContainer.width + 5) * 60)
easing.type: Easing.Linear
}
}
onTextChanged: {
scrollOffset = 0
scrollAnimation.restart()
}
}
MouseArea {
anchors.fill: parent
enabled: root.playerAvailable && root.opacity > 0
&& root.width > 0 && textContainer.visible
enabled: root.playerAvailable && root.opacity > 0 && root.width > 0 && textContainer.visible
hoverEnabled: enabled
cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
onPressed: {
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,
barHeight + Theme.spacingXS,
root.width, root.section, currentScreen)
if (root.popupTarget && root.popupTarget.setTriggerPosition) {
const globalPos = mapToGlobal(0, 0);
const currentScreen = root.parentScreen || Screen;
const screenX = currentScreen.x || 0;
const relativeX = globalPos.x - screenX;
root.popupTarget.setTriggerPosition(relativeX, barHeight + Theme.spacingXS, root.width, root.section, currentScreen);
}
root.clicked()
root.clicked();
}
}
}
}
Row {
@@ -254,10 +250,12 @@ Rectangle {
hoverEnabled: enabled
cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
onClicked: {
if (activePlayer)
activePlayer.previous()
if (activePlayer) {
activePlayer.previous();
}
}
}
}
Rectangle {
@@ -265,18 +263,15 @@ Rectangle {
height: 24
radius: 12
anchors.verticalCenter: parent.verticalCenter
color: activePlayer
&& activePlayer.playbackState === 1 ? Theme.primary : Theme.primaryHover
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"
name: activePlayer && activePlayer.playbackState === 1 ? "pause" : "play_arrow"
size: 14
color: activePlayer
&& activePlayer.playbackState === 1 ? Theme.background : Theme.primary
color: activePlayer && activePlayer.playbackState === 1 ? Theme.background : Theme.primary
}
MouseArea {
@@ -285,10 +280,12 @@ Rectangle {
hoverEnabled: enabled
cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
onClicked: {
if (activePlayer)
activePlayer.togglePlaying()
if (activePlayer) {
activePlayer.togglePlaying();
}
}
}
}
Rectangle {
@@ -315,12 +312,16 @@ Rectangle {
hoverEnabled: enabled
cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
onClicked: {
if (activePlayer)
activePlayer.next()
if (activePlayer) {
activePlayer.next();
}
}
}
}
}
}
Behavior on color {
@@ -328,6 +329,7 @@ Rectangle {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
Behavior on width {
@@ -335,5 +337,7 @@ Rectangle {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}

View File

@@ -1,9 +1,9 @@
import QtQuick
import QtQuick.Controls
import qs.Common
import qs.Modules.ProcessList
import qs.Services
import qs.Widgets
import qs.Modules.ProcessList
Rectangle {
id: root
@@ -11,37 +11,36 @@ Rectangle {
property int availableWidth: 400
readonly property int baseWidth: contentRow.implicitWidth + Theme.spacingS * 2
readonly property int maxNormalWidth: 456
readonly property real horizontalPadding: SettingsData.topBarNoBackground ? 0 : Math.max(Theme.spacingXS, Theme.spacingS * (widgetHeight / 30))
function formatNetworkSpeed(bytesPerSec) {
if (bytesPerSec < 1024)
return bytesPerSec.toFixed(0) + " B/s"
else if (bytesPerSec < 1024 * 1024)
return (bytesPerSec / 1024).toFixed(1) + " KB/s"
else if (bytesPerSec < 1024 * 1024 * 1024)
return (bytesPerSec / (1024 * 1024)).toFixed(1) + " MB/s"
else
return (bytesPerSec / (1024 * 1024 * 1024)).toFixed(1) + " GB/s"
if (bytesPerSec < 1024) {
return bytesPerSec.toFixed(0) + " B/s";
} else if (bytesPerSec < 1024 * 1024) {
return (bytesPerSec / 1024).toFixed(1) + " KB/s";
} else if (bytesPerSec < 1024 * 1024 * 1024) {
return (bytesPerSec / (1024 * 1024)).toFixed(1) + " MB/s";
} else {
return (bytesPerSec / (1024 * 1024 * 1024)).toFixed(1) + " GB/s";
}
}
readonly property real horizontalPadding: SettingsData.topBarNoBackground ? 0 : Math.max(Theme.spacingXS, Theme.spacingS * (widgetHeight / 30))
width: contentRow.implicitWidth + horizontalPadding * 2
height: widgetHeight
radius: SettingsData.topBarNoBackground ? 0 : Theme.cornerRadius
color: {
if (SettingsData.topBarNoBackground) return "transparent"
const baseColor = networkArea.containsMouse ? Theme.primaryPressed : Theme.secondaryHover
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
}
if (SettingsData.topBarNoBackground) {
return "transparent";
}
const baseColor = networkArea.containsMouse ? Theme.primaryPressed : Theme.secondaryHover;
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
}
Component.onCompleted: {
DgopService.addRef(["network"])
DgopService.addRef(["network"]);
}
Component.onDestruction: {
DgopService.removeRef(["network"])
DgopService.removeRef(["network"]);
}
MouseArea {
@@ -76,13 +75,13 @@ Rectangle {
}
StyledText {
text: DgopService.networkRxRate > 0 ? formatNetworkSpeed(
DgopService.networkRxRate) : "0 B/s"
text: DgopService.networkRxRate > 0 ? formatNetworkSpeed(DgopService.networkRxRate) : "0 B/s"
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
Row {
@@ -96,14 +95,15 @@ Rectangle {
}
StyledText {
text: DgopService.networkTxRate > 0 ? formatNetworkSpeed(
DgopService.networkTxRate) : "0 B/s"
text: DgopService.networkTxRate > 0 ? formatNetworkSpeed(DgopService.networkTxRate) : "0 B/s"
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
}
Behavior on color {
@@ -111,5 +111,7 @@ Rectangle {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}

View File

@@ -13,21 +13,23 @@ Rectangle {
property real barHeight: 48
readonly property real horizontalPadding: SettingsData.topBarNoBackground ? 0 : Math.max(Theme.spacingXS, Theme.spacingS * (widgetHeight / 30))
signal clicked
signal clicked()
width: notepadIcon.width + horizontalPadding * 2
height: widgetHeight
radius: SettingsData.topBarNoBackground ? 0 : Theme.cornerRadius
color: {
if (SettingsData.topBarNoBackground) return "transparent"
const baseColor = notepadArea.containsMouse
|| root.isActive ? Theme.primaryPressed : Theme.secondaryHover
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
if (SettingsData.topBarNoBackground) {
return "transparent";
}
const baseColor = notepadArea.containsMouse || root.isActive ? Theme.primaryPressed : Theme.secondaryHover;
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
}
DankIcon {
id: notepadIcon
anchors.centerIn: parent
name: "assignment"
size: Theme.iconSize - 6
@@ -54,7 +56,7 @@ Rectangle {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onPressed: {
root.clicked()
root.clicked();
}
}
@@ -63,5 +65,7 @@ Rectangle {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}
}

View File

@@ -14,26 +14,27 @@ Rectangle {
property real barHeight: 48
readonly property real horizontalPadding: SettingsData.topBarNoBackground ? 0 : Math.max(Theme.spacingXS, Theme.spacingS * (widgetHeight / 30))
signal clicked
signal clicked()
width: notificationIcon.width + horizontalPadding * 2
height: widgetHeight
radius: SettingsData.topBarNoBackground ? 0 : Theme.cornerRadius
color: {
if (SettingsData.topBarNoBackground) return "transparent"
const baseColor = notificationArea.containsMouse
|| root.isActive ? Theme.primaryPressed : Theme.secondaryHover
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
if (SettingsData.topBarNoBackground) {
return "transparent";
}
const baseColor = notificationArea.containsMouse || root.isActive ? Theme.primaryPressed : Theme.secondaryHover;
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
}
DankIcon {
id: notificationIcon
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)
color: SessionData.doNotDisturb ? Theme.error : (notificationArea.containsMouse || root.isActive ? Theme.primary : Theme.surfaceText)
}
Rectangle {
@@ -56,15 +57,13 @@ Rectangle {
cursorShape: Qt.PointingHandCursor
onPressed: {
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, barHeight + Theme.spacingXS,
width, section, currentScreen)
const globalPos = mapToGlobal(0, 0);
const currentScreen = parentScreen || Screen;
const screenX = currentScreen.x || 0;
const relativeX = globalPos.x - screenX;
popupTarget.setTriggerPosition(relativeX, barHeight + Theme.spacingXS, width, section, currentScreen);
}
root.clicked()
root.clicked();
}
}
@@ -73,5 +72,7 @@ Rectangle {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}

View File

@@ -12,10 +12,8 @@ Rectangle {
property var parentScreen: null
property real widgetHeight: 30
readonly property real horizontalPadding: SettingsData.topBarNoBackground ? 2 : Theme.spacingS
readonly property bool hasActivePrivacy: PrivacyService.anyPrivacyActive
readonly property int activeCount: PrivacyService.microphoneActive + PrivacyService.cameraActive
+ PrivacyService.screensharingActive
readonly property int activeCount: PrivacyService.microphoneActive + PrivacyService.cameraActive + PrivacyService.screensharingActive
readonly property real contentWidth: hasActivePrivacy ? (activeCount * 18 + (activeCount - 1) * Theme.spacingXS) : 0
width: hasActivePrivacy ? (contentWidth + horizontalPadding * 2) : 0
@@ -24,18 +22,17 @@ Rectangle {
visible: hasActivePrivacy
opacity: hasActivePrivacy ? 1 : 0
enabled: hasActivePrivacy
color: {
if (SettingsData.topBarNoBackground) return "transparent"
return 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)
if (SettingsData.topBarNoBackground) {
return "transparent";
}
return 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 {
// Privacy indicator click handler
id: privacyArea
anchors.fill: parent
@@ -43,7 +40,6 @@ Rectangle {
enabled: hasActivePrivacy
cursorShape: Qt.PointingHandCursor
onClicked: {
}
}
@@ -65,6 +61,7 @@ Rectangle {
filled: true
anchors.centerIn: parent
}
}
Item {
@@ -91,6 +88,7 @@ Rectangle {
anchors.rightMargin: -2
anchors.topMargin: -1
}
}
Item {
@@ -106,15 +104,9 @@ Rectangle {
filled: true
anchors.centerIn: parent
}
}
}
Behavior on width {
enabled: hasActivePrivacy && visible
NumberAnimation {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
Rectangle {
@@ -129,26 +121,18 @@ Rectangle {
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 && root.visible
NumberAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
Rectangle {
width: 8
height: 8
@@ -160,5 +144,27 @@ Rectangle {
anchors.top: parent.bottom
anchors.topMargin: -4
}
Behavior on opacity {
enabled: hasActivePrivacy && root.visible
NumberAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}
Behavior on width {
enabled: hasActivePrivacy && visible
NumberAnimation {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
}

View File

@@ -21,16 +21,18 @@ Rectangle {
height: widgetHeight
radius: SettingsData.topBarNoBackground ? 0 : Theme.cornerRadius
color: {
if (SettingsData.topBarNoBackground) return "transparent"
const baseColor = ramArea.containsMouse ? Theme.primaryPressed : Theme.secondaryHover
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
if (SettingsData.topBarNoBackground) {
return "transparent";
}
const baseColor = ramArea.containsMouse ? Theme.primaryPressed : Theme.secondaryHover;
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
}
Component.onCompleted: {
DgopService.addRef(["memory"])
DgopService.addRef(["memory"]);
}
Component.onDestruction: {
DgopService.removeRef(["memory"])
DgopService.removeRef(["memory"]);
}
MouseArea {
@@ -41,22 +43,23 @@ Rectangle {
cursorShape: Qt.PointingHandCursor
onPressed: {
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, barHeight + Theme.spacingXS,
width, section, currentScreen)
const globalPos = mapToGlobal(0, 0);
const currentScreen = parentScreen || Screen;
const screenX = currentScreen.x || 0;
const relativeX = globalPos.x - screenX;
popupTarget.setTriggerPosition(relativeX, barHeight + Theme.spacingXS, width, section, currentScreen);
}
DgopService.setSortBy("memory")
if (root.toggleProcessList)
root.toggleProcessList()
DgopService.setSortBy("memory");
if (root.toggleProcessList) {
root.toggleProcessList();
}
}
}
Row {
id: ramContent
anchors.centerIn: parent
spacing: 3
@@ -64,30 +67,33 @@ Rectangle {
name: "developer_board"
size: Theme.iconSize - 8
color: {
if (DgopService.memoryUsage > 90)
return Theme.tempDanger
if (DgopService.memoryUsage > 90) {
return Theme.tempDanger;
}
if (DgopService.memoryUsage > 75)
return Theme.tempWarning
if (DgopService.memoryUsage > 75) {
return Theme.tempWarning;
}
return Theme.surfaceText
return Theme.surfaceText;
}
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: {
if (DgopService.memoryUsage === undefined
|| DgopService.memoryUsage === null
|| DgopService.memoryUsage === 0) {
return "--%"
if (DgopService.memoryUsage === undefined || DgopService.memoryUsage === null || DgopService.memoryUsage === 0) {
return "--%";
}
return DgopService.memoryUsage.toFixed(0) + "%"
return DgopService.memoryUsage.toFixed(0) + "%";
}
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
}

View File

@@ -19,20 +19,21 @@ Rectangle {
// The visual root for this window
property Item windowRoot: (Window.window ? Window.window.contentItem : null)
readonly property var sortedToplevels: {
if (SettingsData.runningAppsCurrentWorkspace){
return CompositorService.filterCurrentWorkspace(CompositorService.sortedToplevels, parentScreen.name)
}
return CompositorService.sortedToplevels
if (SettingsData.runningAppsCurrentWorkspace) {
return CompositorService.filterCurrentWorkspace(CompositorService.sortedToplevels, parentScreen.name);
}
return CompositorService.sortedToplevels;
}
readonly property int windowCount: sortedToplevels.length
readonly property int calculatedWidth: {
if (windowCount === 0)
return 0
if (windowCount === 0) {
return 0;
}
if (SettingsData.runningAppsCompactMode) {
return windowCount * 24 + (windowCount - 1) * Theme.spacingXS + horizontalPadding * 2
return windowCount * 24 + (windowCount - 1) * Theme.spacingXS + horizontalPadding * 2;
} else {
return windowCount * (24 + Theme.spacingXS + 120)
+ (windowCount - 1) * Theme.spacingXS + horizontalPadding * 2
+ (windowCount - 1) * Theme.spacingXS + horizontalPadding * 2;
}
}
@@ -42,13 +43,16 @@ Rectangle {
visible: windowCount > 0
clip: false
color: {
if (windowCount === 0)
return "transparent"
if (windowCount === 0) {
return "transparent";
}
if (SettingsData.topBarNoBackground) return "transparent"
const baseColor = Theme.secondaryHover
if (SettingsData.topBarNoBackground) {
return "transparent";
}
const baseColor = Theme.secondaryHover;
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
baseColor.a * Theme.widgetTransparency);
}
MouseArea {
@@ -60,26 +64,26 @@ Rectangle {
property real touchpadThreshold: 500
onWheel: (wheel) => {
const deltaY = wheel.angleDelta.y
const deltaY = wheel.angleDelta.y;
const isMouseWheel = Math.abs(deltaY) >= 120
&& (Math.abs(deltaY) % 120) === 0
&& (Math.abs(deltaY) % 120) === 0;
var windows = root.sortedToplevels;
const windows = root.sortedToplevels;
if (windows.length < 2) {
return;
}
if (isMouseWheel) {
// Direct mouse wheel action
var currentIndex = -1;
for (var i = 0; i < windows.length; i++) {
let currentIndex = -1;
for (let i = 0; i < windows.length; i++) {
if (windows[i].activated) {
currentIndex = i;
break;
}
}
var nextIndex;
let nextIndex;
if (deltaY < 0) {
if (currentIndex === -1) {
nextIndex = 0;
@@ -94,24 +98,24 @@ Rectangle {
}
}
var nextWindow = windows[nextIndex];
const nextWindow = windows[nextIndex];
if (nextWindow) {
nextWindow.activate();
}
} else {
// Touchpad - accumulate small deltas
scrollAccumulator += deltaY
scrollAccumulator += deltaY;
if (Math.abs(scrollAccumulator) >= touchpadThreshold) {
var currentIndex = -1;
for (var i = 0; i < windows.length; i++) {
let currentIndex = -1;
for (let i = 0; i < windows.length; i++) {
if (windows[i].activated) {
currentIndex = i;
break;
}
}
var nextIndex;
let nextIndex;
if (scrollAccumulator < 0) {
if (currentIndex === -1) {
nextIndex = 0;
@@ -126,16 +130,16 @@ Rectangle {
}
}
var nextWindow = windows[nextIndex];
const nextWindow = windows[nextIndex];
if (nextWindow) {
nextWindow.activate();
}
scrollAccumulator = 0
scrollAccumulator = 0;
}
}
wheel.accepted = true
wheel.accepted = true;
}
}
@@ -158,11 +162,11 @@ Rectangle {
property string windowTitle: modelData.title || "(Unnamed)"
property var toplevelObject: modelData
property string tooltipText: {
var appName = "Unknown"
let appName = "Unknown";
if (appId) {
var desktopEntry = DesktopEntries.heuristicLookup(appId)
const desktopEntry = DesktopEntries.heuristicLookup(appId);
appName = desktopEntry
&& desktopEntry.name ? desktopEntry.name : appId
&& desktopEntry.name ? desktopEntry.name : appId;
}
return appName + (windowTitle ? " • " + windowTitle : "")
}
@@ -174,7 +178,7 @@ Rectangle {
anchors.fill: parent
radius: Theme.cornerRadius
color: {
if (isFocused)
if (isFocused) {
return mouseArea.containsMouse ? Qt.rgba(
Theme.primary.r,
Theme.primary.g,
@@ -183,13 +187,14 @@ Rectangle {
Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.2)
else
0.2);
} else {
return mouseArea.containsMouse ? Qt.rgba(
Theme.primaryHover.r,
Theme.primaryHover.g,
Theme.primaryHover.b,
0.1) : "transparent"
0.1) : "transparent";
}
}
Behavior on color {
@@ -220,14 +225,16 @@ Rectangle {
anchors.centerIn: parent
visible: !iconImg.visible
text: {
if (!appId)
return "?"
if (!appId) {
return "?";
}
var desktopEntry = DesktopEntries.heuristicLookup(appId)
if (desktopEntry && desktopEntry.name)
return desktopEntry.name.charAt(0).toUpperCase()
const desktopEntry = DesktopEntries.heuristicLookup(appId);
if (desktopEntry && desktopEntry.name) {
return desktopEntry.name.charAt(0).toUpperCase();
}
return appId.charAt(0).toUpperCase()
return appId.charAt(0).toUpperCase();
}
font.pixelSize: 10
color: Theme.surfaceText
@@ -260,45 +267,47 @@ Rectangle {
onClicked: (mouse) => {
if (mouse.button === Qt.LeftButton) {
if (toplevelObject) {
toplevelObject.activate()
toplevelObject.activate();
}
} else if (mouse.button === Qt.RightButton) {
if (tooltipLoader.item)
tooltipLoader.item.hideTooltip()
tooltipLoader.active = false
if (tooltipLoader.item) {
tooltipLoader.item.hideTooltip();
}
tooltipLoader.active = false;
windowContextMenuLoader.active = true
windowContextMenuLoader.active = true;
if (windowContextMenuLoader.item) {
windowContextMenuLoader.item.currentWindow = toplevelObject
var globalPos = delegateItem.mapToGlobal(delegateItem.width / 2, 0)
var screenX = root.parentScreen ? root.parentScreen.x : 0
var screenY = root.parentScreen ? root.parentScreen.y : 0
var relativeX = globalPos.x - screenX
var yPos = Theme.barHeight + SettingsData.topBarSpacing - 7
windowContextMenuLoader.item.showAt(relativeX, yPos)
windowContextMenuLoader.item.currentWindow = toplevelObject;
const globalPos = delegateItem.mapToGlobal(delegateItem.width / 2, 0);
const screenX = root.parentScreen ? root.parentScreen.x : 0;
const screenY = root.parentScreen ? root.parentScreen.y : 0;
const relativeX = globalPos.x - screenX;
const yPos = Theme.barHeight + SettingsData.topBarSpacing - 7;
windowContextMenuLoader.item.showAt(relativeX, yPos);
}
}
}
onEntered: {
root.hoveredItem = delegateItem
var globalPos = delegateItem.mapToGlobal(
delegateItem.width / 2, delegateItem.height)
tooltipLoader.active = true
root.hoveredItem = delegateItem;
const globalPos = delegateItem.mapToGlobal(
delegateItem.width / 2, delegateItem.height);
tooltipLoader.active = true;
if (tooltipLoader.item) {
var tooltipY = Theme.barHeight
+ SettingsData.topBarSpacing + Theme.spacingXS
const tooltipY = Theme.barHeight
+ SettingsData.topBarSpacing + Theme.spacingXS;
tooltipLoader.item.showTooltip(
delegateItem.tooltipText, globalPos.x,
tooltipY, root.parentScreen)
tooltipY, root.parentScreen);
}
}
onExited: {
if (root.hoveredItem === delegateItem) {
root.hoveredItem = null
if (tooltipLoader.item)
tooltipLoader.item.hideTooltip()
root.hoveredItem = null;
if (tooltipLoader.item) {
tooltipLoader.item.hideTooltip();
}
tooltipLoader.active = false
tooltipLoader.active = false;
}
}
}
@@ -325,16 +334,16 @@ Rectangle {
property point anchorPos: Qt.point(0, 0)
function showAt(x, y) {
screen = root.parentScreen
anchorPos = Qt.point(x, y)
isVisible = true
visible = true
screen = root.parentScreen;
anchorPos = Qt.point(x, y);
isVisible = true;
visible = true;
}
function close() {
isVisible = false
visible = false
windowContextMenuLoader.active = false
isVisible = false;
visible = false;
windowContextMenuLoader.active = false;
}
implicitWidth: 100
@@ -355,15 +364,15 @@ Rectangle {
MouseArea {
anchors.fill: parent
onClicked: contextMenuWindow.close()
onClicked: contextMenuWindow.close();
}
Rectangle {
x: {
var left = 10
var right = contextMenuWindow.width - width - 10
var want = contextMenuWindow.anchorPos.x - width / 2
return Math.max(left, Math.min(right, want))
const left = 10;
const right = contextMenuWindow.width - width - 10;
const want = contextMenuWindow.anchorPos.x - width / 2;
return Math.max(left, Math.min(right, want));
}
y: contextMenuWindow.anchorPos.y
width: 100
@@ -394,9 +403,9 @@ Rectangle {
cursorShape: Qt.PointingHandCursor
onClicked: {
if (contextMenuWindow.currentWindow) {
contextMenuWindow.currentWindow.close()
contextMenuWindow.currentWindow.close();
}
contextMenuWindow.close()
contextMenuWindow.close();
}
}
}

View File

@@ -12,28 +12,23 @@ PanelWindow {
property var targetScreen: null
function showTooltip(text, x, y, screen) {
tooltipText = text
targetScreen = screen
var screenX = screen ? screen.x : 0
targetX = x - screenX
targetY = y
visible = true
tooltipText = text;
targetScreen = screen;
const screenX = screen ? screen.x : 0;
targetX = x - screenX;
targetY = y;
visible = true;
}
function hideTooltip() {
visible = false
visible = false;
}
screen: targetScreen
implicitWidth: Math.min(300, Math.max(
120,
textContent.implicitWidth + Theme.spacingM * 2))
implicitWidth: Math.min(300, Math.max(120, textContent.implicitWidth + Theme.spacingM * 2))
implicitHeight: textContent.implicitHeight + Theme.spacingS * 2
color: "transparent"
visible: false
WlrLayershell.layer: WlrLayershell.Overlay
WlrLayershell.exclusiveZone: -1
@@ -56,6 +51,7 @@ PanelWindow {
Text {
id: textContent
anchors.centerIn: parent
text: root.tooltipText
font.pixelSize: Theme.fontSizeSmall
@@ -65,5 +61,7 @@ PanelWindow {
elide: Text.ElideRight
width: parent.width - Theme.spacingM * 2
}
}
}

View File

@@ -11,22 +11,22 @@ Rectangle {
property var parentScreen: null
property real widgetHeight: 30
readonly property real horizontalPadding: SettingsData.topBarNoBackground ? 2 : Theme.spacingS
readonly property int calculatedWidth: SystemTray.items.values.length
> 0 ? SystemTray.items.values.length
* 24 + horizontalPadding * 2 : 0
readonly property int calculatedWidth: SystemTray.items.values.length > 0 ? SystemTray.items.values.length * 24 + horizontalPadding * 2 : 0
width: calculatedWidth
height: widgetHeight
radius: SettingsData.topBarNoBackground ? 0 : Theme.cornerRadius
color: {
if (SystemTray.items.values.length === 0)
return "transparent"
if (SettingsData.topBarNoBackground) return "transparent"
const baseColor = Theme.secondaryHover
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
if (SystemTray.items.values.length === 0) {
return "transparent";
}
if (SettingsData.topBarNoBackground) {
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
@@ -42,21 +42,22 @@ Rectangle {
delegate: Item {
property var trayItem: modelData
property string iconSource: {
let icon = trayItem && trayItem.icon
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}`
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 icon;
}
return ""
return "";
}
width: 24
@@ -74,7 +75,9 @@ Rectangle {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}
IconImage {
@@ -94,37 +97,36 @@ Rectangle {
acceptedButtons: Qt.LeftButton | Qt.RightButton
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: mouse => {
if (!trayItem)
return
onClicked: (mouse) => {
if (!trayItem) {
return;
}
if (mouse.button === Qt.LeftButton
&& !trayItem.onlyMenu) {
trayItem.activate()
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()
}
}
if (mouse.button === Qt.LeftButton && !trayItem.onlyMenu) {
trayItem.activate();
return ;
}
if (trayItem.hasMenu) {
const globalPos = mapToGlobal(0, 0);
const currentScreen = parentScreen || Screen;
const screenX = currentScreen.x || 0;
const 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();
}
}
}
}
}
}
QsMenuAnchor {
id: menuAnchor
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -13,22 +13,25 @@ Rectangle {
property string section: "right"
property var popupTarget: null
property var parentScreen: null
readonly property real horizontalPadding: SettingsData.topBarNoBackground ? 0 : Math.max(Theme.spacingXS, Theme.spacingS * (widgetHeight / 30))
signal toggleVpnPopup()
readonly property real horizontalPadding: SettingsData.topBarNoBackground ? 0 : Math.max(Theme.spacingXS, Theme.spacingS * (widgetHeight / 30))
width: Theme.iconSize + horizontalPadding * 2
height: widgetHeight
radius: SettingsData.topBarNoBackground ? 0 : Theme.cornerRadius
color: {
if (SettingsData.topBarNoBackground) return "transparent"
const base = clickArea.containsMouse || (popupTarget && popupTarget.shouldBeVisible) ? Theme.primaryPressed : Theme.secondaryHover
return Qt.rgba(base.r, base.g, base.b, base.a * Theme.widgetTransparency)
if (SettingsData.topBarNoBackground) {
return "transparent";
}
const base = clickArea.containsMouse || (popupTarget && popupTarget.shouldBeVisible) ? Theme.primaryPressed : Theme.secondaryHover;
return Qt.rgba(base.r, base.g, base.b, base.a * Theme.widgetTransparency);
}
DankIcon {
id: icon
name: VpnService.isBusy ? "sync" : (VpnService.connected ? "vpn_lock" : "vpn_key_off")
size: Theme.iconSize - 6
color: VpnService.connected ? Theme.primary : Theme.surfaceText
@@ -41,27 +44,30 @@ Rectangle {
to: 360
duration: 900
}
}
MouseArea {
id: clickArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onPressed: {
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, barHeight + Theme.spacingXS, width, section, currentScreen)
const globalPos = mapToGlobal(0, 0);
const currentScreen = parentScreen || Screen;
const screenX = currentScreen.x || 0;
const relativeX = globalPos.x - screenX;
popupTarget.setTriggerPosition(relativeX, barHeight + Theme.spacingXS, width, section, currentScreen);
}
root.toggleVpnPopup()
root.toggleVpnPopup();
}
}
Rectangle {
id: tooltip
width: Math.max(120, tooltipText.contentWidth + Theme.spacingM * 2)
height: tooltipText.contentHeight + Theme.spacingS * 2
radius: Theme.cornerRadius
@@ -76,19 +82,32 @@ Rectangle {
Text {
id: tooltipText
anchors.centerIn: parent
text: {
if (!VpnService.connected) return "VPN Disconnected"
const names = VpnService.activeNames || []
if (names.length <= 1) return "VPN Connected • " + (names[0] || "")
return "VPN Connected • " + names[0] + " +" + (names.length - 1)
if (!VpnService.connected) {
return "VPN Disconnected";
}
const names = VpnService.activeNames || [];
if (names.length <= 1) {
return "VPN Connected • " + (names[0] || "");
}
return "VPN Connected • " + names[0] + " +" + (names.length - 1);
}
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
}
Behavior on opacity {
NumberAnimation { duration: Theme.shortDuration; easing.type: Theme.standardEasing }
NumberAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}
}

View File

@@ -1,13 +1,14 @@
// No external details import; content inlined for consistency
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell
import Quickshell.Wayland
import Quickshell.Widgets
import qs.Widgets
import qs.Common
import qs.Services
// No external details import; content inlined for consistency
import qs.Widgets
DankPopout {
id: root
@@ -16,11 +17,11 @@ DankPopout {
property var triggerScreen: null
function setTriggerPosition(x, y, width, section, screen) {
triggerX = x
triggerY = y
triggerWidth = width
triggerSection = section
triggerScreen = screen
triggerX = x;
triggerY = y;
triggerWidth = width;
triggerSection = section;
triggerScreen = screen;
}
popupWidth: 360
@@ -37,6 +38,7 @@ DankPopout {
content: Component {
Rectangle {
id: content
implicitHeight: contentColumn.height + Theme.spacingL * 2
color: Theme.popupBackground()
radius: Theme.cornerRadius
@@ -45,11 +47,10 @@ DankPopout {
antialiasing: true
smooth: true
focus: true
Keys.onPressed: function (event) {
Keys.onPressed: function(event) {
if (event.key === Qt.Key_Escape) {
root.close()
event.accepted = true
root.close();
event.accepted = true;
}
}
@@ -85,6 +86,7 @@ DankPopout {
Column {
id: contentColumn
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
@@ -94,6 +96,7 @@ DankPopout {
Item {
width: parent.width
height: 32
StyledText {
text: "VPN Connections"
font.pixelSize: Theme.fontSizeLarge
@@ -120,17 +123,21 @@ DankPopout {
MouseArea {
id: closeArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onPressed: root.close()
}
}
}
// Inlined VPN details
Rectangle {
id: vpnDetail
width: parent.width
implicitHeight: detailsColumn.implicitHeight + Theme.spacingM * 2
radius: Theme.cornerRadius
@@ -141,6 +148,7 @@ DankPopout {
Column {
id: detailsColumn
anchors.fill: parent
anchors.margins: Theme.spacingM
spacing: Theme.spacingS
@@ -151,20 +159,32 @@ DankPopout {
StyledText {
text: {
if (!VpnService.connected) return "Active: None"
const names = VpnService.activeNames || []
if (names.length <= 1) return "Active: " + (names[0] || "VPN")
return "Active: " + names[0] + " +" + (names.length - 1)
if (!VpnService.connected) {
return "Active: None";
}
const names = VpnService.activeNames || [];
if (names.length <= 1) {
return "Active: " + (names[0] || "VPN");
}
return "Active: " + names[0] + " +" + (names.length - 1);
}
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceText
font.weight: Font.Medium
}
Item { Layout.fillWidth: true; height: 1 }
Item {
Layout.fillWidth: true
height: 1
}
// Removed Quick Connect for clarity
Item { width: 1; height: 1 }
Item {
width: 1
height: 1
}
// Disconnect all (shown only when any active)
Rectangle {
@@ -180,21 +200,40 @@ DankPopout {
Row {
anchors.centerIn: parent
spacing: Theme.spacingXS
DankIcon { name: "link_off"; size: Theme.fontSizeSmall; color: Theme.surfaceText }
StyledText { text: "Disconnect"; font.pixelSize: Theme.fontSizeSmall; color: Theme.surfaceText; font.weight: Font.Medium }
DankIcon {
name: "link_off"
size: Theme.fontSizeSmall
color: Theme.surfaceText
}
StyledText {
text: "Disconnect"
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
font.weight: Font.Medium
}
}
MouseArea {
id: discAllArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: VpnService.disconnectAllActive()
}
}
}
Rectangle { height: 1; width: parent.width; color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12) }
Rectangle {
height: 1
width: parent.width
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
}
DankFlickable {
width: parent.width
@@ -204,6 +243,7 @@ DankPopout {
Column {
id: listCol
width: parent.width
spacing: Theme.spacingXS
@@ -215,16 +255,38 @@ DankPopout {
Column {
anchors.centerIn: parent
spacing: Theme.spacingS
DankIcon { name: "playlist_remove"; size: 36; color: Theme.surfaceVariantText; anchors.horizontalCenter: parent.horizontalCenter }
StyledText { text: "No VPN profiles found"; font.pixelSize: Theme.fontSizeMedium; color: Theme.surfaceVariantText; anchors.horizontalCenter: parent.horizontalCenter }
StyledText { text: "Add a VPN in NetworkManager"; font.pixelSize: Theme.fontSizeSmall; color: Theme.surfaceVariantText; anchors.horizontalCenter: parent.horizontalCenter }
DankIcon {
name: "playlist_remove"
size: 36
color: Theme.surfaceVariantText
anchors.horizontalCenter: parent.horizontalCenter
}
StyledText {
text: "No VPN profiles found"
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceVariantText
anchors.horizontalCenter: parent.horizontalCenter
}
StyledText {
text: "Add a VPN in NetworkManager"
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
anchors.horizontalCenter: parent.horizontalCenter
}
}
}
Repeater {
model: VpnService.profiles
delegate: Rectangle {
required property var modelData
width: parent ? parent.width : 300
height: 50
radius: Theme.cornerRadius
@@ -249,56 +311,109 @@ DankPopout {
Column {
spacing: 2
Layout.alignment: Qt.AlignVCenter
StyledText {
text: modelData.name
font.pixelSize: Theme.fontSizeMedium
color: VpnService.isActiveUuid(modelData.uuid) ? Theme.primary : Theme.surfaceText
StyledText {
text: modelData.name
font.pixelSize: Theme.fontSizeMedium
color: VpnService.isActiveUuid(modelData.uuid) ? Theme.primary : Theme.surfaceText
}
StyledText {
text: {
if (modelData.type === "wireguard") {
return "WireGuard";
}
const svc = modelData.serviceType || "";
if (svc.indexOf("openvpn") !== -1) {
return "OpenVPN";
}
if (svc.indexOf("wireguard") !== -1) {
return "WireGuard (plugin)";
}
if (svc.indexOf("openconnect") !== -1) {
return "OpenConnect";
}
if (svc.indexOf("fortissl") !== -1 || svc.indexOf("forti") !== -1) {
return "Fortinet";
}
if (svc.indexOf("strongswan") !== -1) {
return "IPsec (strongSwan)";
}
if (svc.indexOf("libreswan") !== -1) {
return "IPsec (Libreswan)";
}
if (svc.indexOf("l2tp") !== -1) {
return "L2TP/IPsec";
}
if (svc.indexOf("pptp") !== -1) {
return "PPTP";
}
if (svc.indexOf("vpnc") !== -1) {
return "Cisco (vpnc)";
}
if (svc.indexOf("sstp") !== -1) {
return "SSTP";
}
if (svc) {
const parts = svc.split('.');
return parts[parts.length - 1];
}
return "VPN";
}
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceTextMedium
}
}
StyledText {
text: {
if (modelData.type === "wireguard") return "WireGuard"
var svc = modelData.serviceType || ""
if (svc.indexOf("openvpn") !== -1) return "OpenVPN"
if (svc.indexOf("wireguard") !== -1) return "WireGuard (plugin)"
if (svc.indexOf("openconnect") !== -1) return "OpenConnect"
if (svc.indexOf("fortissl") !== -1 || svc.indexOf("forti") !== -1) return "Fortinet"
if (svc.indexOf("strongswan") !== -1) return "IPsec (strongSwan)"
if (svc.indexOf("libreswan") !== -1) return "IPsec (Libreswan)"
if (svc.indexOf("l2tp") !== -1) return "L2TP/IPsec"
if (svc.indexOf("pptp") !== -1) return "PPTP"
if (svc.indexOf("vpnc") !== -1) return "Cisco (vpnc)"
if (svc.indexOf("sstp") !== -1) return "SSTP"
if (svc) {
var parts = svc.split('.')
return parts[parts.length-1]
}
return "VPN"
}
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceTextMedium
Item {
Layout.fillWidth: true
height: 1
}
}
Item { Layout.fillWidth: true; height: 1 }
}
MouseArea {
id: rowArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: VpnService.toggle(modelData.uuid)
}
}
}
Item {
height: 1
width: 1
}
Item { height: 1; width: 1 }
}
}
}
}
}
}
}
}

View File

@@ -13,18 +13,19 @@ Rectangle {
property real widgetHeight: 30
readonly property real horizontalPadding: SettingsData.topBarNoBackground ? 2 : Theme.spacingS
signal clicked
signal clicked()
visible: SettingsData.weatherEnabled
width: visible ? Math.min(100,
weatherRow.implicitWidth + horizontalPadding * 2) : 0
width: visible ? Math.min(100, weatherRow.implicitWidth + horizontalPadding * 2) : 0
height: widgetHeight
radius: SettingsData.topBarNoBackground ? 0 : Theme.cornerRadius
color: {
if (SettingsData.topBarNoBackground) return "transparent"
const baseColor = weatherArea.containsMouse ? Theme.primaryHover : Theme.surfaceTextHover
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
if (SettingsData.topBarNoBackground) {
return "transparent";
}
const baseColor = weatherArea.containsMouse ? Theme.primaryHover : Theme.surfaceTextHover;
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
}
Ref {
@@ -46,16 +47,18 @@ Rectangle {
StyledText {
text: {
var temp = SettingsData.useFahrenheit ? WeatherService.weather.tempF : WeatherService.weather.temp
const temp = SettingsData.useFahrenheit ? WeatherService.weather.tempF : WeatherService.weather.temp;
if (temp === undefined || temp === null || temp === 0) {
return "--°" + (SettingsData.useFahrenheit ? "F" : "C")
return "--°" + (SettingsData.useFahrenheit ? "F" : "C");
}
return temp + "°" + (SettingsData.useFahrenheit ? "F" : "C")
return temp + "°" + (SettingsData.useFahrenheit ? "F" : "C");
}
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
MouseArea {
@@ -66,15 +69,13 @@ Rectangle {
cursorShape: Qt.PointingHandCursor
onPressed: {
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, barHeight + Theme.spacingXS,
width, section, currentScreen)
const globalPos = mapToGlobal(0, 0);
const currentScreen = parentScreen || Screen;
const screenX = currentScreen.x || 0;
const relativeX = globalPos.x - screenX;
popupTarget.setTriggerPosition(relativeX, barHeight + Theme.spacingXS, width, section, currentScreen);
}
root.clicked()
root.clicked();
}
}
@@ -83,6 +84,7 @@ Rectangle {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
Behavior on width {
@@ -90,5 +92,7 @@ Rectangle {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}

View File

@@ -22,260 +22,190 @@ Rectangle {
}
property var workspaceList: {
if (CompositorService.isNiri) {
var baseList = getNiriWorkspaces()
const baseList = getNiriWorkspaces()
return SettingsData.showWorkspacePadding ? padWorkspaces(baseList) : baseList
} else if (CompositorService.isHyprland) {
var workspaces = Hyprland.workspaces ? Hyprland.workspaces.values : []
}
if (CompositorService.isHyprland) {
const workspaces = Hyprland.workspaces?.values || []
if (workspaces.length === 0) {
return [{id: 1, name: "1"}]
return [{
"id": 1,
"name": "1"
}]
}
var sorted = workspaces.slice().sort((a, b) => a.id - b.id)
const sorted = workspaces.slice().sort((a, b) => a.id - b.id)
return SettingsData.showWorkspacePadding ? padWorkspaces(sorted) : sorted
}
return [1]
}
function getWorkspaceIcons(ws) {
if (!SettingsData.showWorkspaceApps) return []
var chunks = []
if (!ws) return chunks
if (!SettingsData.showWorkspaceApps || !ws) {
return []
}
var targetWorkspaceId
let targetWorkspaceId
if (CompositorService.isNiri) {
// For Niri, we need to find the workspace ID from allWorkspaces
var wsNumber = typeof ws === "number" ? ws : -1
if (wsNumber > 0) {
for (var j = 0; j < NiriService.allWorkspaces.length; j++) {
var workspace = NiriService.allWorkspaces[j]
if (workspace.idx + 1 === wsNumber && workspace.output === root.screenName) {
targetWorkspaceId = workspace.id
break
}
}
const wsNumber = typeof ws === "number" ? ws : -1
if (wsNumber <= 0) {
return []
}
if (targetWorkspaceId === undefined) return chunks
const workspace = NiriService.allWorkspaces.find(w => w.idx + 1 === wsNumber && w.output === root.screenName)
if (!workspace) {
return []
}
targetWorkspaceId = workspace.id
} else if (CompositorService.isHyprland) {
targetWorkspaceId = ws.id !== undefined ? ws.id : ws
} else {
return chunks
return []
}
var wins = []
if (CompositorService.isNiri) {
wins = NiriService.windows || []
} else if (CompositorService.isHyprland) {
wins = Hyprland.clients ? Hyprland.clients.values : []
}
const wins = CompositorService.isNiri ? (NiriService.windows || []) : (Hyprland.clients?.values || [])
var byApp = {}
var isActiveWs = false
if (CompositorService.isNiri) {
for (var j = 0; j < NiriService.allWorkspaces.length; j++) {
var ws2 = NiriService.allWorkspaces[j]
if (ws2.id === targetWorkspaceId && ws2.is_active) {
isActiveWs = true
break
}
}
} else if (CompositorService.isHyprland) {
isActiveWs = targetWorkspaceId === root.currentWorkspace
}
const byApp = {}
const isActiveWs = CompositorService.isNiri ? NiriService.allWorkspaces.some(ws => ws.id === targetWorkspaceId && ws.is_active) : targetWorkspaceId === root.currentWorkspace
for (var i = 0; i < wins.length; i++) {
var w = wins[i]
if (!w) continue
wins.forEach((w, i) => {
if (!w) {
return
}
var winWs
if (CompositorService.isNiri) {
winWs = w.workspace_id
} else if (CompositorService.isHyprland) {
winWs = w.workspace && w.workspace.id !== undefined ? w.workspace.id : w.workspaceId
}
if (winWs === undefined || winWs === null) continue
if (winWs !== targetWorkspaceId) continue
const winWs = CompositorService.isNiri ? w.workspace_id : (w.workspace?.id ?? w.workspaceId)
var keyBase = (w.app_id || w.appId || w.class || w.windowClass || w.exe || "unknown").toLowerCase()
var key = isActiveWs ? keyBase + "_" + i : keyBase
if (winWs === undefined || winWs === null || winWs !== targetWorkspaceId) {
return
}
if (!byApp[key]) {
var icon = Quickshell.iconPath(DesktopEntries.heuristicLookup(Paths.moddedAppId(keyBase))?.icon, true)
byApp[key] = {
type: "icon",
icon: icon,
active: !!w.is_focused || !!w.activated,
count: 1,
windowId: w.id || w.address,
fallbackText: w.app_id || w.appId || w.class || w.title || ""
}
} else {
byApp[key].count++
if (w.is_focused || w.activated) byApp[key].active = true
}
}
const keyBase = (w.app_id || w.appId || w.class || w.windowClass || w.exe || "unknown").toLowerCase()
const key = isActiveWs ? `${keyBase}_${i}` : keyBase
for (var k in byApp)
chunks.push(byApp[k])
if (!byApp[key]) {
const icon = Quickshell.iconPath(DesktopEntries.heuristicLookup(Paths.moddedAppId(keyBase))?.icon, true)
byApp[key] = {
"type": "icon",
"icon": icon,
"active": !!(w.is_focused || w.activated),
"count": 1,
"windowId": w.id || w.address,
"fallbackText": w.app_id || w.appId || w.class || w.title || ""
}
} else {
byApp[key].count++
if (w.is_focused || w.activated) {
byApp[key].active = true
}
}
})
return chunks
return Object.values(byApp)
}
function padWorkspaces(list) {
var padded = list.slice()
const padded = list.slice()
const placeholder = CompositorService.isHyprland ? {
"id": -1,
"name": ""
} : -1
while (padded.length < 3) {
if (CompositorService.isHyprland) {
padded.push({id: -1, name: ""})
} else {
padded.push(-1)
}
padded.push(placeholder)
}
return padded
}
function getNiriWorkspaces() {
if (NiriService.allWorkspaces.length === 0)
if (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)
}
if (!root.screenName) {
return NiriService.getCurrentOutputWorkspaceNumbers()
}
const displayWorkspaces = NiriService.allWorkspaces.filter(ws => ws.output === root.screenName).map(ws => ws.idx + 1)
return displayWorkspaces.length > 0 ? displayWorkspaces : [1, 2]
}
function getNiriActiveWorkspace() {
if (NiriService.allWorkspaces.length === 0)
if (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
if (!root.screenName) {
return NiriService.getCurrentWorkspaceNumber()
}
const activeWs = NiriService.allWorkspaces.find(ws => ws.output === root.screenName && ws.is_active)
return activeWs ? activeWs.idx + 1 : 1
}
readonly property real padding: (widgetHeight - workspaceRow.implicitHeight) / 2
function getRealWorkspaces() {
return root.workspaceList.filter(ws => {
if (CompositorService.isHyprland) {
return ws && ws.id !== -1
}
return ws !== -1
})
}
function switchWorkspace(direction) {
if (CompositorService.isNiri) {
const realWorkspaces = getRealWorkspaces()
if (realWorkspaces.length < 2) {
return
}
const currentIndex = realWorkspaces.findIndex(ws => ws === root.currentWorkspace)
const validIndex = currentIndex === -1 ? 0 : currentIndex
const nextIndex = direction > 0 ? (validIndex + 1) % realWorkspaces.length : (validIndex - 1 + realWorkspaces.length) % realWorkspaces.length
NiriService.switchToWorkspace(realWorkspaces[nextIndex] - 1)
} else if (CompositorService.isHyprland) {
const command = direction > 0 ? "workspace r+1" : "workspace r-1"
Hyprland.dispatch(command)
}
}
width: workspaceRow.implicitWidth + padding * 2
height: widgetHeight
radius: SettingsData.topBarNoBackground ? 0 : Theme.cornerRadius
color: {
if (SettingsData.topBarNoBackground) return "transparent"
if (SettingsData.topBarNoBackground)
return "transparent"
const baseColor = Theme.surfaceTextHover
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
baseColor.a * Theme.widgetTransparency)
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency)
}
visible: CompositorService.isNiri || CompositorService.isHyprland
MouseArea {
anchors.fill: parent
hoverEnabled: true
acceptedButtons: Qt.NoButton
property real scrollAccumulator: 0
property real touchpadThreshold: 500
onWheel: (wheel) => {
const deltaY = wheel.angleDelta.y
const isMouseWheel = Math.abs(deltaY) >= 120
&& (Math.abs(deltaY) % 120) === 0
if (isMouseWheel) {
// Direct mouse wheel action
if (CompositorService.isNiri) {
var realWorkspaces = [];
for (var i = 0; i < root.workspaceList.length; i++) {
if (root.workspaceList[i] !== -1) {
realWorkspaces.push(root.workspaceList[i]);
}
}
if (realWorkspaces.length < 2) return;
onWheel: wheel => {
const deltaY = wheel.angleDelta.y
const isMouseWheel = Math.abs(deltaY) >= 120 && (Math.abs(deltaY) % 120) === 0
const direction = deltaY < 0 ? 1 : -1
var currentIndex = -1;
for (var i = 0; i < realWorkspaces.length; i++) {
if (realWorkspaces[i] === root.currentWorkspace) {
currentIndex = i;
break;
}
}
if (currentIndex === -1) currentIndex = 0;
if (isMouseWheel) {
switchWorkspace(direction)
} else {
scrollAccumulator += deltaY
var nextIndex;
if (deltaY < 0) {
nextIndex = (currentIndex + 1) % realWorkspaces.length;
} else {
nextIndex = (currentIndex - 1 + realWorkspaces.length) % realWorkspaces.length;
}
NiriService.switchToWorkspace(realWorkspaces[nextIndex] - 1);
if (Math.abs(scrollAccumulator) >= touchpadThreshold) {
const touchDirection = scrollAccumulator < 0 ? 1 : -1
switchWorkspace(touchDirection)
scrollAccumulator = 0
}
}
} else if (CompositorService.isHyprland) {
if (deltaY < 0) {
Hyprland.dispatch("workspace r+1");
} else {
Hyprland.dispatch("workspace r-1");
}
}
} else {
// Touchpad - accumulate small deltas
scrollAccumulator += deltaY
if (Math.abs(scrollAccumulator) >= touchpadThreshold) {
if (CompositorService.isNiri) {
var realWorkspaces = [];
for (var i = 0; i < root.workspaceList.length; i++) {
if (root.workspaceList[i] !== -1) {
realWorkspaces.push(root.workspaceList[i]);
}
}
if (realWorkspaces.length < 2) {
scrollAccumulator = 0;
return;
}
var currentIndex = -1;
for (var i = 0; i < realWorkspaces.length; i++) {
if (realWorkspaces[i] === root.currentWorkspace) {
currentIndex = i;
break;
}
}
if (currentIndex === -1) currentIndex = 0;
var nextIndex;
if (scrollAccumulator < 0) {
nextIndex = (currentIndex + 1) % realWorkspaces.length;
} else {
nextIndex = (currentIndex - 1 + realWorkspaces.length) % realWorkspaces.length;
}
NiriService.switchToWorkspace(realWorkspaces[nextIndex] - 1);
} else if (CompositorService.isHyprland) {
if (scrollAccumulator < 0) {
Hyprland.dispatch("workspace r+1");
} else {
Hyprland.dispatch("workspace r-1");
}
}
scrollAccumulator = 0
}
}
wheel.accepted = true
}
wheel.accepted = true
}
}
Row {
@@ -302,23 +232,16 @@ Rectangle {
}
property bool isHovered: mouseArea.containsMouse
property var workspaceData: {
if (isPlaceholder)
if (isPlaceholder) {
return null
if (CompositorService.isNiri) {
for (var i = 0; i < NiriService.allWorkspaces.length; i++) {
var ws = NiriService.allWorkspaces[i]
if (ws.idx + 1 === modelData && ws.output === root.screenName)
return ws
}
} else if (CompositorService.isHyprland) {
return modelData
}
return null
if (CompositorService.isNiri) {
return NiriService.allWorkspaces.find(ws => ws.idx + 1 === modelData && ws.output === root.screenName) || null
}
return CompositorService.isHyprland ? modelData : null
}
property var iconData: workspaceData
&& workspaceData.name ? SettingsData.getWorkspaceNameIcon(
workspaceData.name) : null
property var iconData: workspaceData?.name ? SettingsData.getWorkspaceNameIcon(workspaceData.name) : null
property bool hasIcon: iconData !== null
property var icons: SettingsData.showWorkspaceApps ? root.getWorkspaceIcons(CompositorService.isHyprland ? modelData : (modelData === -1 ? null : modelData)) : []
@@ -344,14 +267,14 @@ Rectangle {
cursorShape: isPlaceholder ? Qt.ArrowCursor : Qt.PointingHandCursor
enabled: !isPlaceholder
onClicked: {
if (!isPlaceholder) {
if (CompositorService.isNiri) {
NiriService.switchToWorkspace(modelData - 1)
} else if (CompositorService.isHyprland) {
if (modelData && modelData.id) {
Hyprland.dispatch(`workspace ${modelData.id}`)
}
}
if (isPlaceholder) {
return
}
if (CompositorService.isNiri) {
NiriService.switchToWorkspace(modelData - 1)
} else if (CompositorService.isHyprland && modelData?.id) {
Hyprland.dispatch(`workspace ${modelData.id}`)
}
}
}
@@ -416,53 +339,36 @@ Rectangle {
DankIcon {
visible: hasIcon && iconData.type === "icon" && (!SettingsData.showWorkspaceApps || icons.length === 0)
anchors.centerIn: parent
name: hasIcon
&& iconData.type === "icon" ? iconData.value : ""
name: (hasIcon && iconData.type === "icon") ? iconData.value : ""
size: Theme.fontSizeSmall
color: isActive ? Qt.rgba(Theme.surfaceContainer.r,
Theme.surfaceContainer.g,
Theme.surfaceContainer.b,
0.95) : Theme.surfaceTextMedium
color: isActive ? Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.95) : Theme.surfaceTextMedium
weight: isActive && !isPlaceholder ? 500 : 400
}
StyledText {
visible: hasIcon && iconData.type === "text" && (!SettingsData.showWorkspaceApps || icons.length === 0)
anchors.centerIn: parent
text: hasIcon
&& iconData.type === "text" ? iconData.value : ""
color: isActive ? Qt.rgba(Theme.surfaceContainer.r,
Theme.surfaceContainer.g,
Theme.surfaceContainer.b,
0.95) : Theme.surfaceTextMedium
text: (hasIcon && iconData.type === "text") ? iconData.value : ""
color: isActive ? Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.95) : Theme.surfaceTextMedium
font.pixelSize: Theme.fontSizeSmall
font.weight: isActive
&& !isPlaceholder ? Font.DemiBold : Font.Normal
font.weight: (isActive && !isPlaceholder) ? Font.DemiBold : Font.Normal
}
StyledText {
visible: (SettingsData.showWorkspaceIndex && !hasIcon && (!SettingsData.showWorkspaceApps || icons.length === 0))
anchors.centerIn: parent
text: {
if (CompositorService.isHyprland) {
if (modelData && modelData.id === -1) {
return index + 1
}
return modelData && modelData.id ? modelData.id : ""
}
if (modelData === -1) {
const isPlaceholder = CompositorService.isHyprland ? (modelData?.id === -1) : (modelData === -1)
if (isPlaceholder) {
return index + 1
}
return modelData - 1
return CompositorService.isHyprland ? (modelData?.id || "") : (modelData - 1)
}
color: isActive ? Qt.rgba(
Theme.surfaceContainer.r,
Theme.surfaceContainer.g,
Theme.surfaceContainer.b,
0.95) : isPlaceholder ? Theme.surfaceTextAlpha : Theme.surfaceTextMedium
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
font.weight: (isActive && !isPlaceholder) ? Font.DemiBold : Font.Normal
}
Behavior on width {
@@ -481,4 +387,4 @@ Rectangle {
}
}
}
}
}