mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-01-27 06:52:50 -05:00
qmlfmt with 4 space
This commit is contained in:
@@ -4,71 +4,72 @@ import qs.Common
|
||||
import qs.Services
|
||||
|
||||
Item {
|
||||
id: root
|
||||
id: root
|
||||
|
||||
readonly property MprisPlayer activePlayer: MprisController.activePlayer
|
||||
readonly property bool hasActiveMedia: activePlayer !== null
|
||||
readonly property bool isPlaying: hasActiveMedia && activePlayer
|
||||
&& activePlayer.playbackState === MprisPlaybackState.Playing
|
||||
readonly property MprisPlayer activePlayer: MprisController.activePlayer
|
||||
readonly property bool hasActiveMedia: activePlayer !== null
|
||||
readonly property bool isPlaying: hasActiveMedia && activePlayer
|
||||
&& activePlayer.playbackState === MprisPlaybackState.Playing
|
||||
|
||||
width: 20
|
||||
height: Theme.iconSize
|
||||
width: 20
|
||||
height: Theme.iconSize
|
||||
|
||||
Loader {
|
||||
active: isPlaying
|
||||
sourceComponent: Component {
|
||||
Ref {
|
||||
service: CavaService
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: fallbackTimer
|
||||
|
||||
running: !CavaService.cavaAvailable && isPlaying
|
||||
interval: 256
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
CavaService.values = [Math.random() * 40 + 10, Math.random(
|
||||
) * 60 + 20, Math.random() * 50 + 15, Math.random(
|
||||
) * 35 + 20, Math.random() * 45 + 15, Math.random(
|
||||
) * 55 + 25]
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
anchors.centerIn: parent
|
||||
spacing: 1.5
|
||||
|
||||
Repeater {
|
||||
model: 6
|
||||
|
||||
Rectangle {
|
||||
width: 2
|
||||
height: {
|
||||
if (root.isPlaying && CavaService.values.length > index) {
|
||||
const rawLevel = CavaService.values[index] || 0
|
||||
const scaledLevel = Math.sqrt(Math.min(Math.max(rawLevel, 0),
|
||||
100) / 100) * 100
|
||||
const maxHeight = Theme.iconSize - 2
|
||||
const minHeight = 3
|
||||
return minHeight + (scaledLevel / 100) * (maxHeight - minHeight)
|
||||
}
|
||||
return 3
|
||||
Loader {
|
||||
active: isPlaying
|
||||
sourceComponent: Component {
|
||||
Ref {
|
||||
service: CavaService
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: fallbackTimer
|
||||
|
||||
running: !CavaService.cavaAvailable && isPlaying
|
||||
interval: 256
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
CavaService.values = [Math.random() * 40 + 10, Math.random(
|
||||
) * 60 + 20, Math.random() * 50 + 15, Math.random(
|
||||
) * 35 + 20, Math.random() * 45 + 15, Math.random(
|
||||
) * 55 + 25]
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
anchors.centerIn: parent
|
||||
spacing: 1.5
|
||||
|
||||
Repeater {
|
||||
model: 6
|
||||
|
||||
Rectangle {
|
||||
width: 2
|
||||
height: {
|
||||
if (root.isPlaying && CavaService.values.length > index) {
|
||||
const rawLevel = CavaService.values[index] || 0
|
||||
const scaledLevel = Math.sqrt(
|
||||
Math.min(Math.max(rawLevel, 0),
|
||||
100) / 100) * 100
|
||||
const maxHeight = Theme.iconSize - 2
|
||||
const minHeight = 3
|
||||
return minHeight + (scaledLevel / 100) * (maxHeight - minHeight)
|
||||
}
|
||||
return 3
|
||||
}
|
||||
radius: 1.5
|
||||
color: Theme.primary
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
Behavior on height {
|
||||
NumberAnimation {
|
||||
duration: Anims.durShort
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: Anims.standardDecel
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
radius: 1.5
|
||||
color: Theme.primary
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
Behavior on height {
|
||||
NumberAnimation {
|
||||
duration: Anims.durShort
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: Anims.standardDecel
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,202 +5,202 @@ import qs.Services
|
||||
import qs.Widgets
|
||||
|
||||
Rectangle {
|
||||
id: battery
|
||||
id: battery
|
||||
|
||||
property bool batteryPopupVisible: false
|
||||
property string section: "right"
|
||||
property var popupTarget: null
|
||||
property var parentScreen: null
|
||||
property bool batteryPopupVisible: false
|
||||
property string section: "right"
|
||||
property var popupTarget: null
|
||||
property var parentScreen: null
|
||||
|
||||
signal toggleBatteryPopup
|
||||
signal toggleBatteryPopup
|
||||
|
||||
width: BatteryService.batteryAvailable ? 70 : 40
|
||||
height: 30
|
||||
radius: Theme.cornerRadius
|
||||
color: {
|
||||
const baseColor = batteryArea.containsMouse
|
||||
|| batteryPopupVisible ? Theme.primaryPressed : Theme.secondaryHover
|
||||
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
|
||||
baseColor.a * Theme.widgetTransparency)
|
||||
}
|
||||
visible: true
|
||||
|
||||
Row {
|
||||
anchors.centerIn: parent
|
||||
spacing: 2
|
||||
|
||||
DankIcon {
|
||||
name: {
|
||||
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"
|
||||
}
|
||||
|
||||
// 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"
|
||||
}
|
||||
|
||||
// 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"
|
||||
}
|
||||
size: Theme.iconSize - 6
|
||||
color: {
|
||||
if (!BatteryService.batteryAvailable)
|
||||
return Theme.surfaceText
|
||||
|
||||
if (BatteryService.isLowBattery && !BatteryService.isCharging)
|
||||
return Theme.error
|
||||
|
||||
if (BatteryService.isCharging || BatteryService.isPluggedIn)
|
||||
return Theme.primary
|
||||
|
||||
return Theme.surfaceText
|
||||
}
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: BatteryService.batteryLevel + "%"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
font.weight: Font.Medium
|
||||
color: {
|
||||
if (!BatteryService.batteryAvailable)
|
||||
return Theme.surfaceText
|
||||
|
||||
if (BatteryService.isLowBattery && !BatteryService.isCharging)
|
||||
return Theme.error
|
||||
|
||||
if (BatteryService.isCharging)
|
||||
return Theme.primary
|
||||
|
||||
return Theme.surfaceText
|
||||
}
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
visible: BatteryService.batteryAvailable
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: batteryArea
|
||||
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
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,
|
||||
Theme.barHeight + Theme.spacingXS,
|
||||
width, section, currentScreen)
|
||||
}
|
||||
toggleBatteryPopup()
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: batteryTooltip
|
||||
|
||||
width: Math.max(120, tooltipText.contentWidth + Theme.spacingM * 2)
|
||||
height: tooltipText.contentHeight + Theme.spacingS * 2
|
||||
width: BatteryService.batteryAvailable ? 70 : 40
|
||||
height: 30
|
||||
radius: Theme.cornerRadius
|
||||
color: Theme.surfaceContainer
|
||||
border.color: Theme.surfaceVariantAlpha
|
||||
border.width: 1
|
||||
visible: batteryArea.containsMouse && !batteryPopupVisible
|
||||
anchors.bottom: parent.top
|
||||
anchors.bottomMargin: Theme.spacingS
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
opacity: batteryArea.containsMouse ? 1 : 0
|
||||
color: {
|
||||
const baseColor = batteryArea.containsMouse
|
||||
|| batteryPopupVisible ? Theme.primaryPressed : Theme.secondaryHover
|
||||
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
|
||||
baseColor.a * Theme.widgetTransparency)
|
||||
}
|
||||
visible: true
|
||||
|
||||
Column {
|
||||
anchors.centerIn: parent
|
||||
spacing: 2
|
||||
Row {
|
||||
anchors.centerIn: parent
|
||||
spacing: 2
|
||||
|
||||
StyledText {
|
||||
id: tooltipText
|
||||
DankIcon {
|
||||
name: {
|
||||
if (!BatteryService.batteryAvailable)
|
||||
return "power"
|
||||
|
||||
text: {
|
||||
if (!BatteryService.batteryAvailable) {
|
||||
if (typeof PowerProfiles === "undefined")
|
||||
return "Power Management"
|
||||
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"
|
||||
}
|
||||
|
||||
switch (PowerProfiles.profile) {
|
||||
case PowerProfile.PowerSaver:
|
||||
return "Power Profile: Power Saver"
|
||||
case PowerProfile.Performance:
|
||||
return "Power Profile: Performance"
|
||||
default:
|
||||
return "Power Profile: Balanced"
|
||||
// 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"
|
||||
}
|
||||
|
||||
// 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"
|
||||
}
|
||||
}
|
||||
let status = BatteryService.batteryStatus
|
||||
let level = BatteryService.batteryLevel + "%"
|
||||
let time = BatteryService.formatTimeRemaining()
|
||||
if (time !== "Unknown")
|
||||
return status + " • " + level + " • " + time
|
||||
else
|
||||
return status + " • " + level
|
||||
size: Theme.iconSize - 6
|
||||
color: {
|
||||
if (!BatteryService.batteryAvailable)
|
||||
return Theme.surfaceText
|
||||
|
||||
if (BatteryService.isLowBattery && !BatteryService.isCharging)
|
||||
return Theme.error
|
||||
|
||||
if (BatteryService.isCharging || BatteryService.isPluggedIn)
|
||||
return Theme.primary
|
||||
|
||||
return Theme.surfaceText
|
||||
}
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: BatteryService.batteryLevel + "%"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
font.weight: Font.Medium
|
||||
color: {
|
||||
if (!BatteryService.batteryAvailable)
|
||||
return Theme.surfaceText
|
||||
|
||||
if (BatteryService.isLowBattery && !BatteryService.isCharging)
|
||||
return Theme.error
|
||||
|
||||
if (BatteryService.isCharging)
|
||||
return Theme.primary
|
||||
|
||||
return Theme.surfaceText
|
||||
}
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
visible: BatteryService.batteryAvailable
|
||||
}
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceText
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
}
|
||||
}
|
||||
MouseArea {
|
||||
id: batteryArea
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
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, Theme.barHeight + Theme.spacingXS,
|
||||
width, section, currentScreen)
|
||||
}
|
||||
toggleBatteryPopup()
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: batteryTooltip
|
||||
|
||||
width: Math.max(120, tooltipText.contentWidth + Theme.spacingM * 2)
|
||||
height: tooltipText.contentHeight + Theme.spacingS * 2
|
||||
radius: Theme.cornerRadius
|
||||
color: Theme.surfaceContainer
|
||||
border.color: Theme.surfaceVariantAlpha
|
||||
border.width: 1
|
||||
visible: batteryArea.containsMouse && !batteryPopupVisible
|
||||
anchors.bottom: parent.top
|
||||
anchors.bottomMargin: Theme.spacingS
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
opacity: batteryArea.containsMouse ? 1 : 0
|
||||
|
||||
Column {
|
||||
anchors.centerIn: parent
|
||||
spacing: 2
|
||||
|
||||
StyledText {
|
||||
id: tooltipText
|
||||
|
||||
text: {
|
||||
if (!BatteryService.batteryAvailable) {
|
||||
if (typeof PowerProfiles === "undefined")
|
||||
return "Power Management"
|
||||
|
||||
switch (PowerProfiles.profile) {
|
||||
case PowerProfile.PowerSaver:
|
||||
return "Power Profile: Power Saver"
|
||||
case PowerProfile.Performance:
|
||||
return "Power Profile: Performance"
|
||||
default:
|
||||
return "Power Profile: Balanced"
|
||||
}
|
||||
}
|
||||
let status = BatteryService.batteryStatus
|
||||
let level = BatteryService.batteryLevel + "%"
|
||||
let time = BatteryService.formatTimeRemaining()
|
||||
if (time !== "Unknown")
|
||||
return status + " • " + level + " • " + time
|
||||
else
|
||||
return status + " • " + level
|
||||
}
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceText
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -12,17 +12,18 @@ Rectangle {
|
||||
property var popupTarget: null
|
||||
property var parentScreen: null
|
||||
|
||||
signal clockClicked()
|
||||
signal clockClicked
|
||||
|
||||
width: clockRow.implicitWidth + Theme.spacingS * 2
|
||||
height: 30
|
||||
radius: Theme.cornerRadius
|
||||
color: {
|
||||
const baseColor = clockMouseArea.containsMouse ? Theme.primaryHover : Theme.surfaceTextHover;
|
||||
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
|
||||
const baseColor = clockMouseArea.containsMouse ? Theme.primaryHover : Theme.surfaceTextHover
|
||||
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
|
||||
baseColor.a * Theme.widgetTransparency)
|
||||
}
|
||||
Component.onCompleted: {
|
||||
root.currentDate = systemClock.date;
|
||||
root.currentDate = systemClock.date
|
||||
}
|
||||
|
||||
Row {
|
||||
@@ -32,7 +33,10 @@ Rectangle {
|
||||
spacing: Theme.spacingS
|
||||
|
||||
StyledText {
|
||||
text: SettingsData.use24HourClock ? Qt.formatTime(root.currentDate, "H:mm") : Qt.formatTime(root.currentDate, "h:mm AP")
|
||||
text: SettingsData.use24HourClock ? Qt.formatTime(
|
||||
root.currentDate,
|
||||
"H:mm") : Qt.formatTime(
|
||||
root.currentDate, "h:mm AP")
|
||||
font.pixelSize: Theme.fontSizeMedium - 1
|
||||
color: Theme.surfaceText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
@@ -53,7 +57,6 @@ Rectangle {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
visible: !SettingsData.clockCompactMode
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
SystemClock {
|
||||
@@ -71,13 +74,15 @@ 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, Theme.barHeight + Theme.spacingXS, width, section, currentScreen);
|
||||
var globalPos = mapToGlobal(0, 0)
|
||||
var currentScreen = parentScreen || Screen
|
||||
var screenX = currentScreen.x || 0
|
||||
var relativeX = globalPos.x - screenX
|
||||
popupTarget.setTriggerPosition(
|
||||
relativeX, Theme.barHeight + Theme.spacingXS,
|
||||
width, section, currentScreen)
|
||||
}
|
||||
root.clockClicked();
|
||||
root.clockClicked()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,7 +91,5 @@ Rectangle {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -4,134 +4,139 @@ import qs.Services
|
||||
import qs.Widgets
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
id: root
|
||||
|
||||
property bool isActive: false
|
||||
property string section: "right"
|
||||
property var popupTarget: null
|
||||
property var parentScreen: null
|
||||
property bool isActive: false
|
||||
property string section: "right"
|
||||
property var popupTarget: null
|
||||
property var parentScreen: null
|
||||
|
||||
signal clicked
|
||||
signal clicked
|
||||
|
||||
width: Math.max(80, controlIndicators.implicitWidth + Theme.spacingS * 2)
|
||||
height: 30
|
||||
radius: Theme.cornerRadius
|
||||
color: {
|
||||
const baseColor = controlCenterArea.containsMouse
|
||||
|| root.isActive ? Theme.primaryPressed : Theme.secondaryHover
|
||||
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
|
||||
baseColor.a * Theme.widgetTransparency)
|
||||
}
|
||||
|
||||
Row {
|
||||
id: controlIndicators
|
||||
|
||||
anchors.centerIn: parent
|
||||
spacing: Theme.spacingXS
|
||||
|
||||
DankIcon {
|
||||
name: {
|
||||
if (NetworkService.networkStatus === "ethernet")
|
||||
return "lan"
|
||||
return NetworkService.wifiSignalIcon
|
||||
}
|
||||
size: Theme.iconSize - 8
|
||||
color: NetworkService.networkStatus !== "disconnected" ? Theme.primary : Theme.outlineButton
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
visible: true
|
||||
width: Math.max(80, controlIndicators.implicitWidth + Theme.spacingS * 2)
|
||||
height: 30
|
||||
radius: Theme.cornerRadius
|
||||
color: {
|
||||
const baseColor = controlCenterArea.containsMouse
|
||||
|| root.isActive ? Theme.primaryPressed : Theme.secondaryHover
|
||||
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
|
||||
baseColor.a * Theme.widgetTransparency)
|
||||
}
|
||||
|
||||
DankIcon {
|
||||
name: "bluetooth"
|
||||
size: Theme.iconSize - 8
|
||||
color: BluetoothService.enabled ? Theme.primary : Theme.outlineButton
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
visible: BluetoothService.available && BluetoothService.enabled
|
||||
}
|
||||
Row {
|
||||
id: controlIndicators
|
||||
|
||||
Rectangle {
|
||||
width: audioIcon.implicitWidth + 4
|
||||
height: audioIcon.implicitHeight + 4
|
||||
color: "transparent"
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
DankIcon {
|
||||
id: audioIcon
|
||||
|
||||
name: {
|
||||
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"
|
||||
}
|
||||
return "volume_up"
|
||||
}
|
||||
size: Theme.iconSize - 8
|
||||
color: audioWheelArea.containsMouse || controlCenterArea.containsMouse
|
||||
|| root.isActive ? Theme.primary : Theme.surfaceText
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
spacing: Theme.spacingXS
|
||||
|
||||
MouseArea {
|
||||
id: audioWheelArea
|
||||
DankIcon {
|
||||
name: {
|
||||
if (NetworkService.networkStatus === "ethernet")
|
||||
return "lan"
|
||||
return NetworkService.wifiSignalIcon
|
||||
}
|
||||
size: Theme.iconSize - 8
|
||||
color: NetworkService.networkStatus
|
||||
!== "disconnected" ? Theme.primary : Theme.outlineButton
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
visible: true
|
||||
}
|
||||
|
||||
DankIcon {
|
||||
name: "bluetooth"
|
||||
size: Theme.iconSize - 8
|
||||
color: BluetoothService.enabled ? Theme.primary : Theme.outlineButton
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
visible: BluetoothService.available && BluetoothService.enabled
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: audioIcon.implicitWidth + 4
|
||||
height: audioIcon.implicitHeight + 4
|
||||
color: "transparent"
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
DankIcon {
|
||||
id: audioIcon
|
||||
|
||||
name: {
|
||||
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"
|
||||
}
|
||||
return "volume_up"
|
||||
}
|
||||
size: Theme.iconSize - 8
|
||||
color: audioWheelArea.containsMouse
|
||||
|| controlCenterArea.containsMouse
|
||||
|| root.isActive ? Theme.primary : Theme.surfaceText
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: audioWheelArea
|
||||
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
acceptedButtons: Qt.NoButton
|
||||
onWheel: function (wheelEvent) {
|
||||
let delta = wheelEvent.angleDelta.y
|
||||
let currentVolume = (AudioService.sink
|
||||
&& AudioService.sink.audio
|
||||
&& AudioService.sink.audio.volume * 100)
|
||||
|| 0
|
||||
let newVolume
|
||||
if (delta > 0)
|
||||
newVolume = Math.min(100, currentVolume + 5)
|
||||
else
|
||||
newVolume = Math.max(0, currentVolume - 5)
|
||||
if (AudioService.sink && AudioService.sink.audio) {
|
||||
AudioService.sink.audio.muted = false
|
||||
AudioService.sink.audio.volume = newVolume / 100
|
||||
}
|
||||
wheelEvent.accepted = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DankIcon {
|
||||
name: "mic"
|
||||
size: Theme.iconSize - 8
|
||||
color: Theme.primary
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
visible: false // TODO: Add mic detection
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: controlCenterArea
|
||||
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
acceptedButtons: Qt.NoButton
|
||||
onWheel: function (wheelEvent) {
|
||||
let delta = wheelEvent.angleDelta.y
|
||||
let currentVolume = (AudioService.sink && AudioService.sink.audio
|
||||
&& AudioService.sink.audio.volume * 100) || 0
|
||||
let newVolume
|
||||
if (delta > 0)
|
||||
newVolume = Math.min(100, currentVolume + 5)
|
||||
else
|
||||
newVolume = Math.max(0, currentVolume - 5)
|
||||
if (AudioService.sink && AudioService.sink.audio) {
|
||||
AudioService.sink.audio.muted = false
|
||||
AudioService.sink.audio.volume = newVolume / 100
|
||||
}
|
||||
wheelEvent.accepted = true
|
||||
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, Theme.barHeight + Theme.spacingXS,
|
||||
width, section, currentScreen)
|
||||
}
|
||||
root.clicked()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DankIcon {
|
||||
name: "mic"
|
||||
size: Theme.iconSize - 8
|
||||
color: Theme.primary
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
visible: false // TODO: Add mic detection
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: controlCenterArea
|
||||
|
||||
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,
|
||||
Theme.barHeight + Theme.spacingXS,
|
||||
width, section, currentScreen)
|
||||
}
|
||||
root.clicked()
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,84 +5,84 @@ import qs.Services
|
||||
import qs.Widgets
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
id: root
|
||||
|
||||
property bool showPercentage: true
|
||||
property bool showIcon: true
|
||||
property var toggleProcessList
|
||||
property string section: "right"
|
||||
property var popupTarget: null
|
||||
property var parentScreen: null
|
||||
property bool showPercentage: true
|
||||
property bool showIcon: true
|
||||
property var toggleProcessList
|
||||
property string section: "right"
|
||||
property var popupTarget: null
|
||||
property var parentScreen: null
|
||||
|
||||
width: 55
|
||||
height: 30
|
||||
radius: Theme.cornerRadius
|
||||
color: {
|
||||
const baseColor = cpuArea.containsMouse ? Theme.primaryPressed : Theme.secondaryHover
|
||||
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
|
||||
baseColor.a * Theme.widgetTransparency)
|
||||
}
|
||||
Component.onCompleted: {
|
||||
DgopService.addRef(["cpu"])
|
||||
}
|
||||
Component.onDestruction: {
|
||||
DgopService.removeRef(["cpu"])
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: cpuArea
|
||||
|
||||
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,
|
||||
Theme.barHeight + Theme.spacingXS,
|
||||
width, section, currentScreen)
|
||||
}
|
||||
DgopService.setSortBy("cpu")
|
||||
if (root.toggleProcessList)
|
||||
root.toggleProcessList()
|
||||
width: 55
|
||||
height: 30
|
||||
radius: Theme.cornerRadius
|
||||
color: {
|
||||
const baseColor = cpuArea.containsMouse ? Theme.primaryPressed : Theme.secondaryHover
|
||||
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
|
||||
baseColor.a * Theme.widgetTransparency)
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
anchors.centerIn: parent
|
||||
spacing: 3
|
||||
|
||||
DankIcon {
|
||||
name: "memory"
|
||||
size: Theme.iconSize - 8
|
||||
color: {
|
||||
if (DgopService.cpuUsage > 80)
|
||||
return Theme.tempDanger
|
||||
|
||||
if (DgopService.cpuUsage > 60)
|
||||
return Theme.tempWarning
|
||||
|
||||
return Theme.surfaceText
|
||||
}
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
Component.onCompleted: {
|
||||
DgopService.addRef(["cpu"])
|
||||
}
|
||||
Component.onDestruction: {
|
||||
DgopService.removeRef(["cpu"])
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: {
|
||||
if (DgopService.cpuUsage === undefined
|
||||
|| DgopService.cpuUsage === null
|
||||
|| DgopService.cpuUsage === 0) {
|
||||
return "--%"
|
||||
MouseArea {
|
||||
id: cpuArea
|
||||
|
||||
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, Theme.barHeight + Theme.spacingXS,
|
||||
width, section, currentScreen)
|
||||
}
|
||||
DgopService.setSortBy("cpu")
|
||||
if (root.toggleProcessList)
|
||||
root.toggleProcessList()
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
anchors.centerIn: parent
|
||||
spacing: 3
|
||||
|
||||
DankIcon {
|
||||
name: "memory"
|
||||
size: Theme.iconSize - 8
|
||||
color: {
|
||||
if (DgopService.cpuUsage > 80)
|
||||
return Theme.tempDanger
|
||||
|
||||
if (DgopService.cpuUsage > 60)
|
||||
return Theme.tempWarning
|
||||
|
||||
return Theme.surfaceText
|
||||
}
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: {
|
||||
if (DgopService.cpuUsage === undefined
|
||||
|| DgopService.cpuUsage === null
|
||||
|| DgopService.cpuUsage === 0) {
|
||||
return "--%"
|
||||
}
|
||||
return DgopService.cpuUsage.toFixed(0) + "%"
|
||||
}
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
font.weight: Font.Medium
|
||||
color: Theme.surfaceText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
return DgopService.cpuUsage.toFixed(0) + "%"
|
||||
}
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
font.weight: Font.Medium
|
||||
color: Theme.surfaceText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,91 +5,91 @@ import qs.Services
|
||||
import qs.Widgets
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
id: root
|
||||
|
||||
property bool showPercentage: true
|
||||
property bool showIcon: true
|
||||
property var toggleProcessList
|
||||
property string section: "right"
|
||||
property var popupTarget: null
|
||||
property var parentScreen: null
|
||||
property bool showPercentage: true
|
||||
property bool showIcon: true
|
||||
property var toggleProcessList
|
||||
property string section: "right"
|
||||
property var popupTarget: null
|
||||
property var parentScreen: null
|
||||
|
||||
width: 55
|
||||
height: 30
|
||||
radius: Theme.cornerRadius
|
||||
color: {
|
||||
const baseColor = cpuTempArea.containsMouse ? Theme.primaryPressed : Theme.secondaryHover
|
||||
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
|
||||
baseColor.a * Theme.widgetTransparency)
|
||||
}
|
||||
Component.onCompleted: {
|
||||
DgopService.addRef(["cpu"])
|
||||
}
|
||||
Component.onDestruction: {
|
||||
DgopService.removeRef(["cpu"])
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: cpuTempArea
|
||||
|
||||
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,
|
||||
Theme.barHeight + Theme.spacingXS,
|
||||
width, section, currentScreen)
|
||||
}
|
||||
DgopService.setSortBy("cpu")
|
||||
if (root.toggleProcessList)
|
||||
root.toggleProcessList()
|
||||
width: 55
|
||||
height: 30
|
||||
radius: Theme.cornerRadius
|
||||
color: {
|
||||
const baseColor = cpuTempArea.containsMouse ? Theme.primaryPressed : Theme.secondaryHover
|
||||
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
|
||||
baseColor.a * Theme.widgetTransparency)
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
anchors.centerIn: parent
|
||||
spacing: 3
|
||||
|
||||
DankIcon {
|
||||
name: "memory"
|
||||
size: Theme.iconSize - 8
|
||||
color: {
|
||||
if (DgopService.cpuTemperature > 85)
|
||||
return Theme.tempDanger
|
||||
|
||||
if (DgopService.cpuTemperature > 69)
|
||||
return Theme.tempWarning
|
||||
|
||||
return Theme.surfaceText
|
||||
}
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
Component.onCompleted: {
|
||||
DgopService.addRef(["cpu"])
|
||||
}
|
||||
Component.onDestruction: {
|
||||
DgopService.removeRef(["cpu"])
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: {
|
||||
if (DgopService.cpuTemperature === undefined
|
||||
|| DgopService.cpuTemperature === null
|
||||
|| DgopService.cpuTemperature < 0) {
|
||||
return "--°"
|
||||
MouseArea {
|
||||
id: cpuTempArea
|
||||
|
||||
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, Theme.barHeight + Theme.spacingXS,
|
||||
width, section, currentScreen)
|
||||
}
|
||||
DgopService.setSortBy("cpu")
|
||||
if (root.toggleProcessList)
|
||||
root.toggleProcessList()
|
||||
}
|
||||
return Math.round(DgopService.cpuTemperature) + "°"
|
||||
}
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
font.weight: Font.Medium
|
||||
color: Theme.surfaceText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
Row {
|
||||
anchors.centerIn: parent
|
||||
spacing: 3
|
||||
|
||||
DankIcon {
|
||||
name: "memory"
|
||||
size: Theme.iconSize - 8
|
||||
color: {
|
||||
if (DgopService.cpuTemperature > 85)
|
||||
return Theme.tempDanger
|
||||
|
||||
if (DgopService.cpuTemperature > 69)
|
||||
return Theme.tempWarning
|
||||
|
||||
return Theme.surfaceText
|
||||
}
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: {
|
||||
if (DgopService.cpuTemperature === undefined
|
||||
|| DgopService.cpuTemperature === null
|
||||
|| DgopService.cpuTemperature < 0) {
|
||||
return "--°"
|
||||
}
|
||||
return Math.round(DgopService.cpuTemperature) + "°"
|
||||
}
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
font.weight: Font.Medium
|
||||
color: Theme.surfaceText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,15 +13,18 @@ Rectangle {
|
||||
readonly property int maxNormalWidth: 456
|
||||
readonly property int maxCompactWidth: 288
|
||||
|
||||
width: compactMode ? Math.min(baseWidth, maxCompactWidth) : Math.min(baseWidth, maxNormalWidth)
|
||||
width: compactMode ? Math.min(baseWidth,
|
||||
maxCompactWidth) : Math.min(baseWidth,
|
||||
maxNormalWidth)
|
||||
height: 30
|
||||
radius: Theme.cornerRadius
|
||||
color: {
|
||||
if (!NiriService.focusedWindowTitle)
|
||||
return "transparent";
|
||||
return "transparent"
|
||||
|
||||
const baseColor = mouseArea.containsMouse ? Theme.primaryHover : Theme.surfaceTextHover;
|
||||
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
|
||||
const baseColor = mouseArea.containsMouse ? Theme.primaryHover : Theme.surfaceTextHover
|
||||
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
|
||||
baseColor.a * Theme.widgetTransparency)
|
||||
}
|
||||
clip: true
|
||||
visible: NiriService.niriAvailable && NiriService.focusedWindowTitle
|
||||
@@ -37,16 +40,17 @@ Rectangle {
|
||||
|
||||
text: {
|
||||
if (!NiriService.focusedWindowId)
|
||||
return "";
|
||||
return ""
|
||||
|
||||
var window = NiriService.windows.find((w) => {
|
||||
return w.id == NiriService.focusedWindowId;
|
||||
});
|
||||
var window = NiriService.windows.find(w => {
|
||||
return w.id == NiriService.focusedWindowId
|
||||
})
|
||||
if (!window || !window.app_id)
|
||||
return "";
|
||||
return ""
|
||||
|
||||
var desktopEntry = DesktopEntries.byId(window.app_id);
|
||||
return desktopEntry && desktopEntry.name ? desktopEntry.name : window.app_id;
|
||||
var desktopEntry = DesktopEntries.byId(window.app_id)
|
||||
return desktopEntry
|
||||
&& desktopEntry.name ? desktopEntry.name : window.app_id
|
||||
}
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
font.weight: Font.Medium
|
||||
@@ -70,20 +74,24 @@ Rectangle {
|
||||
id: titleText
|
||||
|
||||
text: {
|
||||
var title = NiriService.focusedWindowTitle || "";
|
||||
var appName = appText.text;
|
||||
|
||||
if (!title || !appName) return title;
|
||||
|
||||
var title = NiriService.focusedWindowTitle || ""
|
||||
var 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);
|
||||
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).replace(
|
||||
/ - $/, "")
|
||||
}
|
||||
|
||||
return title;
|
||||
|
||||
return title
|
||||
}
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
font.weight: Font.Medium
|
||||
@@ -94,7 +102,6 @@ Rectangle {
|
||||
width: Math.min(implicitWidth, compactMode ? 280 : 250)
|
||||
visible: text.length > 0
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
@@ -109,7 +116,6 @@ Rectangle {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Behavior on width {
|
||||
@@ -117,7 +123,5 @@ Rectangle {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,182 +5,185 @@ import qs.Services
|
||||
import qs.Widgets
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
id: root
|
||||
|
||||
property bool showPercentage: true
|
||||
property bool showIcon: true
|
||||
property var toggleProcessList
|
||||
property string section: "right"
|
||||
property var popupTarget: null
|
||||
property var parentScreen: null
|
||||
property var widgetData: null
|
||||
property int selectedGpuIndex: (widgetData && widgetData.selectedGpuIndex
|
||||
!== undefined) ? widgetData.selectedGpuIndex : 0
|
||||
property bool showPercentage: true
|
||||
property bool showIcon: true
|
||||
property var toggleProcessList
|
||||
property string section: "right"
|
||||
property var popupTarget: null
|
||||
property var parentScreen: null
|
||||
property var widgetData: null
|
||||
property int selectedGpuIndex: (widgetData && widgetData.selectedGpuIndex
|
||||
!== undefined) ? widgetData.selectedGpuIndex : 0
|
||||
|
||||
Connections {
|
||||
target: SettingsData
|
||||
function onWidgetDataChanged() {
|
||||
// Force property re-evaluation by triggering change detection
|
||||
root.selectedGpuIndex = Qt.binding(() => {
|
||||
return (root.widgetData
|
||||
&& root.widgetData.selectedGpuIndex !== undefined) ? root.widgetData.selectedGpuIndex : 0
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
width: 55
|
||||
height: 30
|
||||
radius: Theme.cornerRadius
|
||||
color: {
|
||||
const baseColor = gpuArea.containsMouse ? Theme.primaryPressed : Theme.secondaryHover
|
||||
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
|
||||
baseColor.a * Theme.widgetTransparency)
|
||||
}
|
||||
Component.onCompleted: {
|
||||
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)
|
||||
} else {
|
||||
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
|
||||
}
|
||||
}
|
||||
Component.onDestruction: {
|
||||
DgopService.removeRef(["gpu"])
|
||||
// Remove this widget's PCI ID from the service
|
||||
if (widgetData && 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
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: gpuArea
|
||||
|
||||
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,
|
||||
Theme.barHeight + Theme.spacingXS,
|
||||
width, section, currentScreen)
|
||||
}
|
||||
DgopService.setSortBy("cpu")
|
||||
if (root.toggleProcessList)
|
||||
root.toggleProcessList()
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
anchors.centerIn: parent
|
||||
spacing: 3
|
||||
|
||||
DankIcon {
|
||||
name: "auto_awesome_mosaic"
|
||||
size: Theme.iconSize - 8
|
||||
color: {
|
||||
if (root.displayTemp > 80)
|
||||
return Theme.tempDanger
|
||||
|
||||
if (root.displayTemp > 65)
|
||||
return Theme.tempWarning
|
||||
|
||||
return Theme.surfaceText
|
||||
}
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: {
|
||||
if (root.displayTemp === undefined || root.displayTemp === null
|
||||
|| root.displayTemp === 0) {
|
||||
return "--°"
|
||||
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
|
||||
})
|
||||
}
|
||||
return Math.round(root.displayTemp) + "°"
|
||||
}
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
font.weight: Font.Medium
|
||||
color: Theme.surfaceText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
width: 55
|
||||
height: 30
|
||||
radius: Theme.cornerRadius
|
||||
color: {
|
||||
const baseColor = gpuArea.containsMouse ? Theme.primaryPressed : Theme.secondaryHover
|
||||
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
|
||||
baseColor.a * Theme.widgetTransparency)
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
Component.onCompleted: {
|
||||
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)
|
||||
} else {
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
Component.onDestruction: {
|
||||
DgopService.removeRef(["gpu"])
|
||||
// Remove this widget's PCI ID from the service
|
||||
if (widgetData && 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
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: gpuArea
|
||||
|
||||
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, Theme.barHeight + Theme.spacingXS,
|
||||
width, section, currentScreen)
|
||||
}
|
||||
DgopService.setSortBy("cpu")
|
||||
if (root.toggleProcessList)
|
||||
root.toggleProcessList()
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
anchors.centerIn: parent
|
||||
spacing: 3
|
||||
|
||||
DankIcon {
|
||||
name: "auto_awesome_mosaic"
|
||||
size: Theme.iconSize - 8
|
||||
color: {
|
||||
if (root.displayTemp > 80)
|
||||
return Theme.tempDanger
|
||||
|
||||
if (root.displayTemp > 65)
|
||||
return Theme.tempWarning
|
||||
|
||||
return Theme.surfaceText
|
||||
}
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: {
|
||||
if (root.displayTemp === undefined || root.displayTemp === null
|
||||
|| root.displayTemp === 0) {
|
||||
return "--°"
|
||||
}
|
||||
return Math.round(root.displayTemp) + "°"
|
||||
}
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
font.weight: Font.Medium
|
||||
color: Theme.surfaceText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,46 +7,43 @@ import qs.Widgets
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
|
||||
|
||||
property string section: "right"
|
||||
property var popupTarget: null
|
||||
property var parentScreen: null
|
||||
|
||||
|
||||
width: 40
|
||||
height: 30
|
||||
radius: Theme.cornerRadius
|
||||
color: {
|
||||
const baseColor = mouseArea.containsMouse
|
||||
? Theme.primaryPressed
|
||||
: (IdleInhibitorService.idleInhibited ? Theme.primaryHover : Theme.secondaryHover)
|
||||
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
|
||||
baseColor.a * Theme.widgetTransparency)
|
||||
const baseColor = mouseArea.containsMouse ? Theme.primaryPressed : (IdleInhibitorService.idleInhibited ? Theme.primaryHover : Theme.secondaryHover)
|
||||
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
|
||||
baseColor.a * Theme.widgetTransparency)
|
||||
}
|
||||
|
||||
|
||||
DankIcon {
|
||||
anchors.centerIn: parent
|
||||
name: IdleInhibitorService.idleInhibited ? "motion_sensor_active" : "motion_sensor_idle"
|
||||
size: Theme.iconSize - 6
|
||||
color: Theme.surfaceText
|
||||
}
|
||||
|
||||
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
|
||||
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
|
||||
|
||||
onClicked: {
|
||||
IdleInhibitorService.toggleIdleInhibit()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,63 +4,62 @@ import qs.Services
|
||||
import qs.Widgets
|
||||
|
||||
Item {
|
||||
id: root
|
||||
id: root
|
||||
|
||||
property bool isActive: false
|
||||
property string section: "left"
|
||||
property var popupTarget: null
|
||||
property var parentScreen: null
|
||||
property bool isActive: false
|
||||
property string section: "left"
|
||||
property var popupTarget: null
|
||||
property var parentScreen: null
|
||||
|
||||
signal clicked
|
||||
signal clicked
|
||||
|
||||
width: 40
|
||||
height: 30
|
||||
width: 40
|
||||
height: 30
|
||||
|
||||
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,
|
||||
Theme.barHeight + Theme.spacingXS,
|
||||
width, section, currentScreen)
|
||||
}
|
||||
root.clicked()
|
||||
}
|
||||
}
|
||||
MouseArea {
|
||||
id: launcherArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
acceptedButtons: Qt.LeftButton
|
||||
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
radius: Theme.cornerRadius
|
||||
color: Qt.rgba(Theme.surfaceTextHover.r, Theme.surfaceTextHover.g, Theme.surfaceTextHover.b,
|
||||
Theme.surfaceTextHover.a * Theme.widgetTransparency)
|
||||
|
||||
SystemLogo {
|
||||
visible: SettingsData.useOSLogo
|
||||
anchors.centerIn: parent
|
||||
width: Theme.iconSize - 3
|
||||
height: Theme.iconSize - 3
|
||||
colorOverride: SettingsData.osLogoColorOverride
|
||||
brightnessOverride: SettingsData.osLogoBrightness
|
||||
contrastOverride: SettingsData.osLogoContrast
|
||||
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, Theme.barHeight + Theme.spacingXS,
|
||||
width, section, currentScreen)
|
||||
}
|
||||
root.clicked()
|
||||
}
|
||||
}
|
||||
|
||||
DankIcon {
|
||||
visible: !SettingsData.useOSLogo
|
||||
anchors.centerIn: parent
|
||||
name: "apps"
|
||||
size: Theme.iconSize - 6
|
||||
color: Theme.surfaceText
|
||||
}
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
radius: Theme.cornerRadius
|
||||
color: Qt.rgba(Theme.surfaceTextHover.r, Theme.surfaceTextHover.g,
|
||||
Theme.surfaceTextHover.b,
|
||||
Theme.surfaceTextHover.a * Theme.widgetTransparency)
|
||||
|
||||
}
|
||||
}
|
||||
SystemLogo {
|
||||
visible: SettingsData.useOSLogo
|
||||
anchors.centerIn: parent
|
||||
width: Theme.iconSize - 3
|
||||
height: Theme.iconSize - 3
|
||||
colorOverride: SettingsData.osLogoColorOverride
|
||||
brightnessOverride: SettingsData.osLogoBrightness
|
||||
contrastOverride: SettingsData.osLogoContrast
|
||||
}
|
||||
|
||||
DankIcon {
|
||||
visible: !SettingsData.useOSLogo
|
||||
anchors.centerIn: parent
|
||||
name: "apps"
|
||||
size: Theme.iconSize - 6
|
||||
color: Theme.surfaceText
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,312 +5,328 @@ import qs.Services
|
||||
import qs.Widgets
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
id: root
|
||||
|
||||
readonly property MprisPlayer activePlayer: MprisController.activePlayer
|
||||
readonly property bool playerAvailable: activePlayer !== null
|
||||
property bool compactMode: false
|
||||
readonly property int textWidth: {
|
||||
switch(SettingsData.mediaSize) {
|
||||
case 0: return 0 // No text in small mode
|
||||
case 2: return 180 // Large text area
|
||||
default: return 120 // Medium text area
|
||||
readonly property MprisPlayer activePlayer: MprisController.activePlayer
|
||||
readonly property bool playerAvailable: activePlayer !== null
|
||||
property bool compactMode: false
|
||||
readonly property int textWidth: {
|
||||
switch (SettingsData.mediaSize) {
|
||||
case 0:
|
||||
return 0 // No text in small mode
|
||||
case 2:
|
||||
return 180 // Large text area
|
||||
default:
|
||||
return 120 // Medium text area
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
readonly property int currentContentWidth: {
|
||||
// AudioViz (20) + spacing + text + spacing + controls (~90) + padding
|
||||
const baseWidth = 20 + Theme.spacingXS + 90 + Theme.spacingS * 2
|
||||
return baseWidth + textWidth + (textWidth > 0 ? Theme.spacingXS : 0)
|
||||
}
|
||||
property string section: "center"
|
||||
property var popupTarget: null
|
||||
property var parentScreen: null
|
||||
|
||||
signal clicked
|
||||
|
||||
height: 30
|
||||
radius: Theme.cornerRadius
|
||||
color: {
|
||||
const baseColor = Theme.surfaceTextHover
|
||||
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
|
||||
baseColor.a * Theme.widgetTransparency)
|
||||
}
|
||||
states: [
|
||||
State {
|
||||
name: "shown"
|
||||
when: playerAvailable
|
||||
|
||||
PropertyChanges {
|
||||
target: root
|
||||
opacity: 1
|
||||
width: currentContentWidth
|
||||
}
|
||||
},
|
||||
State {
|
||||
name: "hidden"
|
||||
when: !playerAvailable
|
||||
|
||||
PropertyChanges {
|
||||
target: root
|
||||
opacity: 0
|
||||
width: 0
|
||||
}
|
||||
readonly property int currentContentWidth: {
|
||||
// AudioViz (20) + spacing + text + spacing + controls (~90) + padding
|
||||
const baseWidth = 20 + Theme.spacingXS + 90 + Theme.spacingS * 2
|
||||
return baseWidth + textWidth + (textWidth > 0 ? Theme.spacingXS : 0)
|
||||
}
|
||||
]
|
||||
transitions: [
|
||||
Transition {
|
||||
from: "shown"
|
||||
to: "hidden"
|
||||
property string section: "center"
|
||||
property var popupTarget: null
|
||||
property var parentScreen: null
|
||||
|
||||
SequentialAnimation {
|
||||
PauseAnimation {
|
||||
duration: 500
|
||||
signal clicked
|
||||
|
||||
height: 30
|
||||
radius: Theme.cornerRadius
|
||||
color: {
|
||||
const baseColor = Theme.surfaceTextHover
|
||||
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
|
||||
baseColor.a * Theme.widgetTransparency)
|
||||
}
|
||||
states: [
|
||||
State {
|
||||
name: "shown"
|
||||
when: playerAvailable
|
||||
|
||||
PropertyChanges {
|
||||
target: root
|
||||
opacity: 1
|
||||
width: currentContentWidth
|
||||
}
|
||||
},
|
||||
State {
|
||||
name: "hidden"
|
||||
when: !playerAvailable
|
||||
|
||||
PropertyChanges {
|
||||
target: root
|
||||
opacity: 0
|
||||
width: 0
|
||||
}
|
||||
}
|
||||
]
|
||||
transitions: [
|
||||
Transition {
|
||||
from: "shown"
|
||||
to: "hidden"
|
||||
|
||||
SequentialAnimation {
|
||||
PauseAnimation {
|
||||
duration: 500
|
||||
}
|
||||
|
||||
NumberAnimation {
|
||||
properties: "opacity,width"
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
}
|
||||
},
|
||||
Transition {
|
||||
from: "hidden"
|
||||
to: "shown"
|
||||
|
||||
NumberAnimation {
|
||||
properties: "opacity,width"
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
Row {
|
||||
id: mediaRow
|
||||
|
||||
anchors.centerIn: parent
|
||||
spacing: Theme.spacingXS
|
||||
|
||||
Row {
|
||||
id: mediaInfo
|
||||
|
||||
spacing: Theme.spacingXS
|
||||
|
||||
AudioVisualization {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: textContainer
|
||||
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: textWidth
|
||||
height: 20
|
||||
visible: SettingsData.mediaSize > 0
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
SequentialAnimation {
|
||||
id: scrollAnimation
|
||||
running: mediaText.needsScrolling
|
||||
&& textContainer.visible
|
||||
loops: Animation.Infinite
|
||||
|
||||
PauseAnimation {
|
||||
duration: 2000
|
||||
}
|
||||
|
||||
NumberAnimation {
|
||||
target: mediaText
|
||||
property: "scrollOffset"
|
||||
from: 0
|
||||
to: mediaText.implicitWidth - textContainer.width + 5
|
||||
duration: Math.max(
|
||||
1000,
|
||||
(mediaText.implicitWidth - textContainer.width + 5) * 60)
|
||||
easing.type: Easing.Linear
|
||||
}
|
||||
|
||||
PauseAnimation {
|
||||
duration: 2000
|
||||
}
|
||||
|
||||
NumberAnimation {
|
||||
target: mediaText
|
||||
property: "scrollOffset"
|
||||
to: 0
|
||||
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
|
||||
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,
|
||||
Theme.barHeight + Theme.spacingXS,
|
||||
root.width, root.section, currentScreen)
|
||||
}
|
||||
root.clicked()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
spacing: Theme.spacingXS
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
Rectangle {
|
||||
width: 20
|
||||
height: 20
|
||||
radius: 10
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
color: prevArea.containsMouse ? Theme.primaryHover : "transparent"
|
||||
visible: root.playerAvailable
|
||||
opacity: (activePlayer && activePlayer.canGoPrevious) ? 1 : 0.3
|
||||
|
||||
DankIcon {
|
||||
anchors.centerIn: parent
|
||||
name: "skip_previous"
|
||||
size: 12
|
||||
color: Theme.surfaceText
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: prevArea
|
||||
|
||||
anchors.fill: parent
|
||||
enabled: root.playerAvailable && root.width > 0
|
||||
hoverEnabled: enabled
|
||||
cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||
onClicked: {
|
||||
if (activePlayer)
|
||||
activePlayer.previous()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: 24
|
||||
height: 24
|
||||
radius: 12
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
color: activePlayer
|
||||
&& activePlayer.playbackState === 1 ? Theme.primary : Theme.primaryHover
|
||||
visible: root.playerAvailable
|
||||
opacity: activePlayer ? 1 : 0.3
|
||||
|
||||
DankIcon {
|
||||
anchors.centerIn: parent
|
||||
name: activePlayer
|
||||
&& activePlayer.playbackState === 1 ? "pause" : "play_arrow"
|
||||
size: 14
|
||||
color: activePlayer
|
||||
&& activePlayer.playbackState === 1 ? Theme.background : Theme.primary
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
enabled: root.playerAvailable && root.width > 0
|
||||
hoverEnabled: enabled
|
||||
cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||
onClicked: {
|
||||
if (activePlayer)
|
||||
activePlayer.togglePlaying()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: 20
|
||||
height: 20
|
||||
radius: 10
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
color: nextArea.containsMouse ? Theme.primaryHover : "transparent"
|
||||
visible: playerAvailable
|
||||
opacity: (activePlayer && activePlayer.canGoNext) ? 1 : 0.3
|
||||
|
||||
DankIcon {
|
||||
anchors.centerIn: parent
|
||||
name: "skip_next"
|
||||
size: 12
|
||||
color: Theme.surfaceText
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: nextArea
|
||||
|
||||
anchors.fill: parent
|
||||
enabled: root.playerAvailable && root.width > 0
|
||||
hoverEnabled: enabled
|
||||
cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||
onClicked: {
|
||||
if (activePlayer)
|
||||
activePlayer.next()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on width {
|
||||
NumberAnimation {
|
||||
properties: "opacity,width"
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
}
|
||||
},
|
||||
Transition {
|
||||
from: "hidden"
|
||||
to: "shown"
|
||||
|
||||
NumberAnimation {
|
||||
properties: "opacity,width"
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
Row {
|
||||
id: mediaRow
|
||||
|
||||
anchors.centerIn: parent
|
||||
spacing: Theme.spacingXS
|
||||
|
||||
Row {
|
||||
id: mediaInfo
|
||||
|
||||
spacing: Theme.spacingXS
|
||||
|
||||
AudioVisualization {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: textContainer
|
||||
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: textWidth
|
||||
height: 20
|
||||
visible: SettingsData.mediaSize > 0
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
SequentialAnimation {
|
||||
id: scrollAnimation
|
||||
running: mediaText.needsScrolling && textContainer.visible
|
||||
loops: Animation.Infinite
|
||||
|
||||
PauseAnimation { duration: 2000 }
|
||||
|
||||
NumberAnimation {
|
||||
target: mediaText
|
||||
property: "scrollOffset"
|
||||
from: 0
|
||||
to: mediaText.implicitWidth - textContainer.width + 5
|
||||
duration: Math.max(1000, (mediaText.implicitWidth - textContainer.width + 5) * 60)
|
||||
easing.type: Easing.Linear
|
||||
}
|
||||
|
||||
PauseAnimation { duration: 2000 }
|
||||
|
||||
NumberAnimation {
|
||||
target: mediaText
|
||||
property: "scrollOffset"
|
||||
to: 0
|
||||
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
|
||||
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, Theme.barHeight + Theme.spacingXS, root.width,
|
||||
root.section, currentScreen)
|
||||
}
|
||||
root.clicked()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
spacing: Theme.spacingXS
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
Rectangle {
|
||||
width: 20
|
||||
height: 20
|
||||
radius: 10
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
color: prevArea.containsMouse ? Theme.primaryHover : "transparent"
|
||||
visible: root.playerAvailable
|
||||
opacity: (activePlayer && activePlayer.canGoPrevious) ? 1 : 0.3
|
||||
|
||||
DankIcon {
|
||||
anchors.centerIn: parent
|
||||
name: "skip_previous"
|
||||
size: 12
|
||||
color: Theme.surfaceText
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: prevArea
|
||||
|
||||
anchors.fill: parent
|
||||
enabled: root.playerAvailable && root.width > 0
|
||||
hoverEnabled: enabled
|
||||
cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||
onClicked: {
|
||||
if (activePlayer)
|
||||
activePlayer.previous()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: 24
|
||||
height: 24
|
||||
radius: 12
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
color: activePlayer
|
||||
&& activePlayer.playbackState === 1 ? Theme.primary : Theme.primaryHover
|
||||
visible: root.playerAvailable
|
||||
opacity: activePlayer ? 1 : 0.3
|
||||
|
||||
DankIcon {
|
||||
anchors.centerIn: parent
|
||||
name: activePlayer
|
||||
&& activePlayer.playbackState === 1 ? "pause" : "play_arrow"
|
||||
size: 14
|
||||
color: activePlayer
|
||||
&& activePlayer.playbackState === 1 ? Theme.background : Theme.primary
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
enabled: root.playerAvailable && root.width > 0
|
||||
hoverEnabled: enabled
|
||||
cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||
onClicked: {
|
||||
if (activePlayer)
|
||||
activePlayer.togglePlaying()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: 20
|
||||
height: 20
|
||||
radius: 10
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
color: nextArea.containsMouse ? Theme.primaryHover : "transparent"
|
||||
visible: playerAvailable
|
||||
opacity: (activePlayer && activePlayer.canGoNext) ? 1 : 0.3
|
||||
|
||||
DankIcon {
|
||||
anchors.centerIn: parent
|
||||
name: "skip_next"
|
||||
size: 12
|
||||
color: Theme.surfaceText
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: nextArea
|
||||
|
||||
anchors.fill: parent
|
||||
enabled: root.playerAvailable && root.width > 0
|
||||
hoverEnabled: enabled
|
||||
cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||
onClicked: {
|
||||
if (activePlayer)
|
||||
activePlayer.next()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on width {
|
||||
NumberAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,70 +3,70 @@ import qs.Common
|
||||
import qs.Widgets
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
id: root
|
||||
|
||||
property bool hasUnread: false
|
||||
property bool isActive: false
|
||||
property string section: "right"
|
||||
property var popupTarget: null
|
||||
property var parentScreen: null
|
||||
property bool hasUnread: false
|
||||
property bool isActive: false
|
||||
property string section: "right"
|
||||
property var popupTarget: null
|
||||
property var parentScreen: null
|
||||
|
||||
signal clicked
|
||||
signal clicked
|
||||
|
||||
width: 40
|
||||
height: 30
|
||||
radius: Theme.cornerRadius
|
||||
color: {
|
||||
const baseColor = notificationArea.containsMouse
|
||||
|| root.isActive ? Theme.primaryPressed : Theme.secondaryHover
|
||||
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
|
||||
baseColor.a * Theme.widgetTransparency)
|
||||
}
|
||||
|
||||
DankIcon {
|
||||
anchors.centerIn: parent
|
||||
name: SessionData.doNotDisturb ? "notifications_off" : "notifications"
|
||||
size: Theme.iconSize - 6
|
||||
color: SessionData.doNotDisturb ? Theme.error : (notificationArea.containsMouse
|
||||
|| root.isActive ? Theme.primary : Theme.surfaceText)
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: 8
|
||||
height: 8
|
||||
radius: 4
|
||||
color: Theme.error
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
anchors.rightMargin: 6
|
||||
anchors.topMargin: 6
|
||||
visible: root.hasUnread
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: notificationArea
|
||||
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
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,
|
||||
Theme.barHeight + Theme.spacingXS,
|
||||
width, section, currentScreen)
|
||||
}
|
||||
root.clicked()
|
||||
width: 40
|
||||
height: 30
|
||||
radius: Theme.cornerRadius
|
||||
color: {
|
||||
const baseColor = notificationArea.containsMouse
|
||||
|| root.isActive ? Theme.primaryPressed : Theme.secondaryHover
|
||||
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
|
||||
baseColor.a * Theme.widgetTransparency)
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
DankIcon {
|
||||
anchors.centerIn: parent
|
||||
name: SessionData.doNotDisturb ? "notifications_off" : "notifications"
|
||||
size: Theme.iconSize - 6
|
||||
color: SessionData.doNotDisturb ? Theme.error : (notificationArea.containsMouse
|
||||
|| root.isActive ? Theme.primary : Theme.surfaceText)
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: 8
|
||||
height: 8
|
||||
radius: 4
|
||||
color: Theme.error
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
anchors.rightMargin: 6
|
||||
anchors.topMargin: 6
|
||||
visible: root.hasUnread
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: notificationArea
|
||||
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
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, Theme.barHeight + Theme.spacingXS,
|
||||
width, section, currentScreen)
|
||||
}
|
||||
root.clicked()
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,155 +5,154 @@ import qs.Services
|
||||
import qs.Widgets
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
id: root
|
||||
|
||||
property string section: "right"
|
||||
property var popupTarget: null
|
||||
property var parentScreen: null
|
||||
property string section: "right"
|
||||
property var popupTarget: null
|
||||
property var parentScreen: null
|
||||
|
||||
readonly property bool hasActivePrivacy: PrivacyService.anyPrivacyActive
|
||||
readonly property int activeCount: PrivacyService.microphoneActive + PrivacyService.cameraActive
|
||||
+ PrivacyService.screensharingActive
|
||||
readonly property bool hasActivePrivacy: PrivacyService.anyPrivacyActive
|
||||
readonly property int activeCount: PrivacyService.microphoneActive + PrivacyService.cameraActive
|
||||
+ PrivacyService.screensharingActive
|
||||
|
||||
width: hasActivePrivacy ? (activeCount > 1 ? 80 : 60) : 0
|
||||
height: hasActivePrivacy ? 30 : 0
|
||||
radius: Theme.cornerRadius
|
||||
visible: hasActivePrivacy
|
||||
opacity: hasActivePrivacy ? 1 : 0
|
||||
enabled: hasActivePrivacy
|
||||
|
||||
color: Qt.rgba(
|
||||
privacyArea.containsMouse ? Theme.errorPressed.r : Theme.errorHover.r,
|
||||
privacyArea.containsMouse ? Theme.errorPressed.g : Theme.errorHover.g,
|
||||
privacyArea.containsMouse ? Theme.errorPressed.b : Theme.errorHover.b,
|
||||
(privacyArea.containsMouse ? Theme.errorPressed.a : Theme.errorHover.a)
|
||||
* Theme.widgetTransparency)
|
||||
|
||||
MouseArea {
|
||||
id: privacyArea
|
||||
|
||||
anchors.fill: parent
|
||||
hoverEnabled: hasActivePrivacy
|
||||
enabled: hasActivePrivacy
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
anchors.centerIn: parent
|
||||
spacing: Theme.spacingXS
|
||||
visible: hasActivePrivacy
|
||||
|
||||
Item {
|
||||
width: 18
|
||||
height: 18
|
||||
visible: PrivacyService.microphoneActive
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
DankIcon {
|
||||
name: "mic"
|
||||
size: Theme.iconSizeSmall
|
||||
color: Theme.error
|
||||
filled: true
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
width: 18
|
||||
height: 18
|
||||
visible: PrivacyService.cameraActive
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
DankIcon {
|
||||
name: "camera_video"
|
||||
size: Theme.iconSizeSmall
|
||||
color: Theme.surfaceText
|
||||
filled: true
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: 6
|
||||
height: 6
|
||||
radius: 3
|
||||
color: Theme.error
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
anchors.rightMargin: -2
|
||||
anchors.topMargin: -1
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
width: 18
|
||||
height: 18
|
||||
visible: PrivacyService.screensharingActive
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
DankIcon {
|
||||
name: "screen_share"
|
||||
size: Theme.iconSizeSmall
|
||||
color: Theme.warning
|
||||
filled: true
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on width {
|
||||
enabled: hasActivePrivacy && visible
|
||||
NumberAnimation {
|
||||
duration: Theme.mediumDuration
|
||||
easing.type: Theme.emphasizedEasing
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: tooltip
|
||||
|
||||
width: tooltipText.contentWidth + Theme.spacingM * 2
|
||||
height: tooltipText.contentHeight + Theme.spacingS * 2
|
||||
width: hasActivePrivacy ? (activeCount > 1 ? 80 : 60) : 0
|
||||
height: hasActivePrivacy ? 30 : 0
|
||||
radius: Theme.cornerRadius
|
||||
color: Theme.popupBackground()
|
||||
border.color: Theme.outlineMedium
|
||||
border.width: 1
|
||||
visible: false
|
||||
opacity: privacyArea.containsMouse && hasActivePrivacy ? 1 : 0
|
||||
z: 100
|
||||
visible: hasActivePrivacy
|
||||
opacity: hasActivePrivacy ? 1 : 0
|
||||
enabled: hasActivePrivacy
|
||||
|
||||
x: (parent.width - width) / 2
|
||||
y: -height - Theme.spacingXS
|
||||
color: Qt.rgba(
|
||||
privacyArea.containsMouse ? Theme.errorPressed.r : Theme.errorHover.r,
|
||||
privacyArea.containsMouse ? Theme.errorPressed.g : Theme.errorHover.g,
|
||||
privacyArea.containsMouse ? Theme.errorPressed.b : Theme.errorHover.b,
|
||||
(privacyArea.containsMouse ? Theme.errorPressed.a : Theme.errorHover.a)
|
||||
* Theme.widgetTransparency)
|
||||
|
||||
StyledText {
|
||||
id: tooltipText
|
||||
anchors.centerIn: parent
|
||||
text: PrivacyService.getPrivacySummary()
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceText
|
||||
MouseArea {
|
||||
id: privacyArea
|
||||
|
||||
anchors.fill: parent
|
||||
hoverEnabled: hasActivePrivacy
|
||||
enabled: hasActivePrivacy
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on opacity {
|
||||
enabled: hasActivePrivacy && root.visible
|
||||
NumberAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
Row {
|
||||
anchors.centerIn: parent
|
||||
spacing: Theme.spacingXS
|
||||
visible: hasActivePrivacy
|
||||
|
||||
Item {
|
||||
width: 18
|
||||
height: 18
|
||||
visible: PrivacyService.microphoneActive
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
DankIcon {
|
||||
name: "mic"
|
||||
size: Theme.iconSizeSmall
|
||||
color: Theme.error
|
||||
filled: true
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
width: 18
|
||||
height: 18
|
||||
visible: PrivacyService.cameraActive
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
DankIcon {
|
||||
name: "camera_video"
|
||||
size: Theme.iconSizeSmall
|
||||
color: Theme.surfaceText
|
||||
filled: true
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: 6
|
||||
height: 6
|
||||
radius: 3
|
||||
color: Theme.error
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
anchors.rightMargin: -2
|
||||
anchors.topMargin: -1
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
width: 18
|
||||
height: 18
|
||||
visible: PrivacyService.screensharingActive
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
DankIcon {
|
||||
name: "screen_share"
|
||||
size: Theme.iconSizeSmall
|
||||
color: Theme.warning
|
||||
filled: true
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on width {
|
||||
enabled: hasActivePrivacy && visible
|
||||
NumberAnimation {
|
||||
duration: Theme.mediumDuration
|
||||
easing.type: Theme.emphasizedEasing
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: 8
|
||||
height: 8
|
||||
color: parent.color
|
||||
border.color: parent.border.color
|
||||
border.width: parent.border.width
|
||||
rotation: 45
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.top: parent.bottom
|
||||
anchors.topMargin: -4
|
||||
id: tooltip
|
||||
|
||||
width: tooltipText.contentWidth + Theme.spacingM * 2
|
||||
height: tooltipText.contentHeight + Theme.spacingS * 2
|
||||
radius: Theme.cornerRadius
|
||||
color: Theme.popupBackground()
|
||||
border.color: Theme.outlineMedium
|
||||
border.width: 1
|
||||
visible: false
|
||||
opacity: privacyArea.containsMouse && hasActivePrivacy ? 1 : 0
|
||||
z: 100
|
||||
|
||||
x: (parent.width - width) / 2
|
||||
y: -height - Theme.spacingXS
|
||||
|
||||
StyledText {
|
||||
id: tooltipText
|
||||
anchors.centerIn: parent
|
||||
text: PrivacyService.getPrivacySummary()
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceText
|
||||
}
|
||||
|
||||
Behavior on opacity {
|
||||
enabled: hasActivePrivacy && root.visible
|
||||
NumberAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: 8
|
||||
height: 8
|
||||
color: parent.color
|
||||
border.color: parent.border.color
|
||||
border.width: parent.border.width
|
||||
rotation: 45
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.top: parent.bottom
|
||||
anchors.topMargin: -4
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,84 +5,84 @@ import qs.Services
|
||||
import qs.Widgets
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
id: root
|
||||
|
||||
property bool showPercentage: true
|
||||
property bool showIcon: true
|
||||
property var toggleProcessList
|
||||
property string section: "right"
|
||||
property var popupTarget: null
|
||||
property var parentScreen: null
|
||||
property bool showPercentage: true
|
||||
property bool showIcon: true
|
||||
property var toggleProcessList
|
||||
property string section: "right"
|
||||
property var popupTarget: null
|
||||
property var parentScreen: null
|
||||
|
||||
width: 55
|
||||
height: 30
|
||||
radius: Theme.cornerRadius
|
||||
color: {
|
||||
const baseColor = ramArea.containsMouse ? Theme.primaryPressed : Theme.secondaryHover
|
||||
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
|
||||
baseColor.a * Theme.widgetTransparency)
|
||||
}
|
||||
Component.onCompleted: {
|
||||
DgopService.addRef(["memory"])
|
||||
}
|
||||
Component.onDestruction: {
|
||||
DgopService.removeRef(["memory"])
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: ramArea
|
||||
|
||||
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,
|
||||
Theme.barHeight + Theme.spacingXS,
|
||||
width, section, currentScreen)
|
||||
}
|
||||
DgopService.setSortBy("memory")
|
||||
if (root.toggleProcessList)
|
||||
root.toggleProcessList()
|
||||
width: 55
|
||||
height: 30
|
||||
radius: Theme.cornerRadius
|
||||
color: {
|
||||
const baseColor = ramArea.containsMouse ? Theme.primaryPressed : Theme.secondaryHover
|
||||
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
|
||||
baseColor.a * Theme.widgetTransparency)
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
anchors.centerIn: parent
|
||||
spacing: 3
|
||||
|
||||
DankIcon {
|
||||
name: "developer_board"
|
||||
size: Theme.iconSize - 8
|
||||
color: {
|
||||
if (DgopService.memoryUsage > 90)
|
||||
return Theme.tempDanger
|
||||
|
||||
if (DgopService.memoryUsage > 75)
|
||||
return Theme.tempWarning
|
||||
|
||||
return Theme.surfaceText
|
||||
}
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
Component.onCompleted: {
|
||||
DgopService.addRef(["memory"])
|
||||
}
|
||||
Component.onDestruction: {
|
||||
DgopService.removeRef(["memory"])
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: {
|
||||
if (DgopService.memoryUsage === undefined
|
||||
|| DgopService.memoryUsage === null
|
||||
|| DgopService.memoryUsage === 0) {
|
||||
return "--%"
|
||||
MouseArea {
|
||||
id: ramArea
|
||||
|
||||
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, Theme.barHeight + Theme.spacingXS,
|
||||
width, section, currentScreen)
|
||||
}
|
||||
DgopService.setSortBy("memory")
|
||||
if (root.toggleProcessList)
|
||||
root.toggleProcessList()
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
anchors.centerIn: parent
|
||||
spacing: 3
|
||||
|
||||
DankIcon {
|
||||
name: "developer_board"
|
||||
size: Theme.iconSize - 8
|
||||
color: {
|
||||
if (DgopService.memoryUsage > 90)
|
||||
return Theme.tempDanger
|
||||
|
||||
if (DgopService.memoryUsage > 75)
|
||||
return Theme.tempWarning
|
||||
|
||||
return Theme.surfaceText
|
||||
}
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: {
|
||||
if (DgopService.memoryUsage === undefined
|
||||
|| DgopService.memoryUsage === null
|
||||
|| DgopService.memoryUsage === 0) {
|
||||
return "--%"
|
||||
}
|
||||
return DgopService.memoryUsage.toFixed(0) + "%"
|
||||
}
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
font.weight: Font.Medium
|
||||
color: Theme.surfaceText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
return DgopService.memoryUsage.toFixed(0) + "%"
|
||||
}
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
font.weight: Font.Medium
|
||||
color: Theme.surfaceText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,11 +17,13 @@ Rectangle {
|
||||
property Item windowRoot: (Window.window ? Window.window.contentItem : null)
|
||||
readonly property int windowCount: NiriService.windows.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 + Theme.spacingS * 2;
|
||||
return windowCount * 24 + (windowCount - 1) * Theme.spacingXS + Theme.spacingS * 2
|
||||
} else {
|
||||
return windowCount * (24 + Theme.spacingXS + 120) + (windowCount - 1) * Theme.spacingXS + Theme.spacingS * 2;
|
||||
return windowCount * (24 + Theme.spacingXS + 120)
|
||||
+ (windowCount - 1) * Theme.spacingXS + Theme.spacingS * 2
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,10 +34,11 @@ Rectangle {
|
||||
clip: false
|
||||
color: {
|
||||
if (windowCount === 0)
|
||||
return "transparent";
|
||||
return "transparent"
|
||||
|
||||
const baseColor = Theme.secondaryHover;
|
||||
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
|
||||
const baseColor = Theme.secondaryHover
|
||||
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
|
||||
baseColor.a * Theme.widgetTransparency)
|
||||
}
|
||||
|
||||
Row {
|
||||
@@ -52,17 +55,19 @@ Rectangle {
|
||||
delegate: Item {
|
||||
id: delegateItem
|
||||
|
||||
property bool isFocused: String(modelData.id) === String(NiriService.focusedWindowId)
|
||||
property bool isFocused: String(modelData.id) === String(
|
||||
NiriService.focusedWindowId)
|
||||
property string appId: modelData.app_id || ""
|
||||
property string windowTitle: modelData.title || "(Unnamed)"
|
||||
property int windowId: modelData.id
|
||||
property string tooltipText: {
|
||||
var appName = "Unknown";
|
||||
var appName = "Unknown"
|
||||
if (appId) {
|
||||
var desktopEntry = DesktopEntries.byId(appId);
|
||||
appName = desktopEntry && desktopEntry.name ? desktopEntry.name : appId;
|
||||
var desktopEntry = DesktopEntries.byId(appId)
|
||||
appName = desktopEntry
|
||||
&& desktopEntry.name ? desktopEntry.name : appId
|
||||
}
|
||||
return appName + (windowTitle ? " • " + windowTitle : "");
|
||||
return appName + (windowTitle ? " • " + windowTitle : "")
|
||||
}
|
||||
|
||||
width: SettingsData.runningAppsCompactMode ? 24 : (24 + Theme.spacingXS + 120)
|
||||
@@ -73,9 +78,21 @@ Rectangle {
|
||||
radius: Theme.cornerRadius
|
||||
color: {
|
||||
if (isFocused)
|
||||
return mouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.3) : Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.2);
|
||||
return mouseArea.containsMouse ? Qt.rgba(
|
||||
Theme.primary.r,
|
||||
Theme.primary.g,
|
||||
Theme.primary.b,
|
||||
0.3) : Qt.rgba(
|
||||
Theme.primary.r,
|
||||
Theme.primary.g,
|
||||
Theme.primary.b,
|
||||
0.2)
|
||||
else
|
||||
return mouseArea.containsMouse ? Qt.rgba(Theme.primaryHover.r, Theme.primaryHover.g, Theme.primaryHover.b, 0.1) : "transparent";
|
||||
return mouseArea.containsMouse ? Qt.rgba(
|
||||
Theme.primaryHover.r,
|
||||
Theme.primaryHover.g,
|
||||
Theme.primaryHover.b,
|
||||
0.1) : "transparent"
|
||||
}
|
||||
|
||||
Behavior on color {
|
||||
@@ -83,9 +100,7 @@ Rectangle {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// App icon
|
||||
@@ -99,14 +114,17 @@ Rectangle {
|
||||
height: 18
|
||||
source: {
|
||||
if (!appId)
|
||||
return "";
|
||||
return ""
|
||||
|
||||
var desktopEntry = DesktopEntries.byId(appId);
|
||||
var desktopEntry = DesktopEntries.byId(appId)
|
||||
if (desktopEntry && desktopEntry.icon) {
|
||||
var iconPath = Quickshell.iconPath(desktopEntry.icon, SettingsData.iconTheme === "System Default" ? "" : SettingsData.iconTheme);
|
||||
return iconPath;
|
||||
var iconPath = Quickshell.iconPath(
|
||||
desktopEntry.icon,
|
||||
SettingsData.iconTheme
|
||||
=== "System Default" ? "" : SettingsData.iconTheme)
|
||||
return iconPath
|
||||
}
|
||||
return "";
|
||||
return ""
|
||||
}
|
||||
smooth: true
|
||||
mipmap: true
|
||||
@@ -122,13 +140,13 @@ Rectangle {
|
||||
visible: !iconImg.visible
|
||||
text: {
|
||||
if (!appId)
|
||||
return "?";
|
||||
return "?"
|
||||
|
||||
var desktopEntry = DesktopEntries.byId(appId);
|
||||
var desktopEntry = DesktopEntries.byId(appId)
|
||||
if (desktopEntry && desktopEntry.name)
|
||||
return desktopEntry.name.charAt(0).toUpperCase();
|
||||
return desktopEntry.name.charAt(0).toUpperCase()
|
||||
|
||||
return appId.charAt(0).toUpperCase();
|
||||
return appId.charAt(0).toUpperCase()
|
||||
}
|
||||
font.pixelSize: 10
|
||||
color: Theme.surfaceText
|
||||
@@ -158,32 +176,33 @@ Rectangle {
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
NiriService.focusWindow(windowId);
|
||||
NiriService.focusWindow(windowId)
|
||||
}
|
||||
onEntered: {
|
||||
root.hoveredItem = delegateItem;
|
||||
var globalPos = delegateItem.mapToGlobal(delegateItem.width / 2, delegateItem.height);
|
||||
tooltipLoader.active = true;
|
||||
root.hoveredItem = delegateItem
|
||||
var globalPos = delegateItem.mapToGlobal(
|
||||
delegateItem.width / 2, delegateItem.height)
|
||||
tooltipLoader.active = true
|
||||
if (tooltipLoader.item) {
|
||||
var tooltipY = Theme.barHeight + SettingsData.topBarSpacing + Theme.spacingXS;
|
||||
tooltipLoader.item.showTooltip(delegateItem.tooltipText, globalPos.x, tooltipY, root.parentScreen);
|
||||
var tooltipY = Theme.barHeight
|
||||
+ SettingsData.topBarSpacing + Theme.spacingXS
|
||||
tooltipLoader.item.showTooltip(
|
||||
delegateItem.tooltipText, globalPos.x,
|
||||
tooltipY, root.parentScreen)
|
||||
}
|
||||
}
|
||||
onExited: {
|
||||
if (root.hoveredItem === delegateItem) {
|
||||
root.hoveredItem = null;
|
||||
root.hoveredItem = null
|
||||
if (tooltipLoader.item)
|
||||
tooltipLoader.item.hideTooltip();
|
||||
tooltipLoader.item.hideTooltip()
|
||||
|
||||
tooltipLoader.active = false;
|
||||
tooltipLoader.active = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Loader {
|
||||
@@ -191,9 +210,6 @@ Rectangle {
|
||||
|
||||
active: false
|
||||
|
||||
sourceComponent: RunningAppsTooltip {
|
||||
}
|
||||
|
||||
sourceComponent: RunningAppsTooltip {}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,53 +5,55 @@ import qs.Common
|
||||
|
||||
PanelWindow {
|
||||
id: root
|
||||
|
||||
|
||||
property string tooltipText: ""
|
||||
property real targetX: 0
|
||||
property real targetY: 0
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
function hideTooltip() {
|
||||
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
|
||||
|
||||
|
||||
anchors {
|
||||
top: true
|
||||
left: true
|
||||
}
|
||||
|
||||
|
||||
margins {
|
||||
left: Math.round(targetX - implicitWidth / 2)
|
||||
top: Math.round(targetY)
|
||||
}
|
||||
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: Theme.surfaceContainer
|
||||
radius: Theme.cornerRadius
|
||||
border.width: 1
|
||||
border.color: Theme.outlineMedium
|
||||
|
||||
|
||||
Text {
|
||||
id: textContent
|
||||
anchors.centerIn: parent
|
||||
@@ -64,4 +66,4 @@ PanelWindow {
|
||||
width: parent.width - Theme.spacingM * 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,29 +92,30 @@ Rectangle {
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: mouse => {
|
||||
if (!trayItem)
|
||||
return
|
||||
if (!trayItem)
|
||||
return
|
||||
|
||||
if (mouse.button === Qt.LeftButton && !trayItem.onlyMenu) {
|
||||
trayItem.activate()
|
||||
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 (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()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,90 +31,103 @@ PanelWindow {
|
||||
let fonts = Qt.fontFamilies()
|
||||
if (fonts.indexOf("Material Symbols Rounded") === -1)
|
||||
ToastService.showError(
|
||||
"Please install Material Symbols Rounded and Restart your Shell. See README.md for instructions")
|
||||
"Please install Material Symbols Rounded and Restart your Shell. See README.md for instructions")
|
||||
|
||||
SettingsData.forceTopBarLayoutRefresh.connect(function () {
|
||||
Qt.callLater(() => {
|
||||
leftSection.visible = false
|
||||
centerSection.visible = false
|
||||
rightSection.visible = false
|
||||
Qt.callLater(() => {
|
||||
leftSection.visible = true
|
||||
centerSection.visible = true
|
||||
rightSection.visible = true
|
||||
})
|
||||
})
|
||||
leftSection.visible = false
|
||||
centerSection.visible = false
|
||||
rightSection.visible = false
|
||||
Qt.callLater(() => {
|
||||
leftSection.visible = true
|
||||
centerSection.visible = true
|
||||
rightSection.visible = true
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
// Configure GPU temperature monitoring based on widget configuration
|
||||
updateGpuTempConfig()
|
||||
|
||||
|
||||
// Force widget initialization after brief delay to ensure services are loaded
|
||||
Qt.callLater(() => {
|
||||
Qt.callLater(() => {
|
||||
forceWidgetRefresh()
|
||||
})
|
||||
})
|
||||
Qt.callLater(() => {
|
||||
forceWidgetRefresh()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function forceWidgetRefresh() {
|
||||
// Force reload of all widget sections to handle race condition on desktop hardware
|
||||
if (leftSection) leftSection.visible = false
|
||||
if (centerSection) centerSection.visible = false
|
||||
if (rightSection) rightSection.visible = false
|
||||
|
||||
if (leftSection)
|
||||
leftSection.visible = false
|
||||
if (centerSection)
|
||||
centerSection.visible = false
|
||||
if (rightSection)
|
||||
rightSection.visible = false
|
||||
|
||||
Qt.callLater(() => {
|
||||
if (leftSection) leftSection.visible = true
|
||||
if (centerSection) centerSection.visible = true
|
||||
if (rightSection) rightSection.visible = true
|
||||
})
|
||||
if (leftSection)
|
||||
leftSection.visible = true
|
||||
if (centerSection)
|
||||
centerSection.visible = true
|
||||
if (rightSection)
|
||||
rightSection.visible = true
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function updateGpuTempConfig() {
|
||||
const allWidgets = [...(SettingsData.topBarLeftWidgets || []),
|
||||
...(SettingsData.topBarCenterWidgets || []),
|
||||
...(SettingsData.topBarRightWidgets || [])]
|
||||
|
||||
const allWidgets = [...(SettingsData.topBarLeftWidgets
|
||||
|| []), ...(SettingsData.topBarCenterWidgets
|
||||
|| []), ...(SettingsData.topBarRightWidgets
|
||||
|| [])]
|
||||
|
||||
const hasGpuTempWidget = allWidgets.some(widget => {
|
||||
const widgetId = typeof widget === "string" ? widget : widget.id
|
||||
const widgetEnabled = typeof widget === "string" ? true : (widget.enabled !== false)
|
||||
return widgetId === "gpuTemp" && widgetEnabled
|
||||
})
|
||||
|
||||
DgopService.gpuTempEnabled = hasGpuTempWidget || SessionData.nvidiaGpuTempEnabled || SessionData.nonNvidiaGpuTempEnabled
|
||||
DgopService.nvidiaGpuTempEnabled = hasGpuTempWidget || SessionData.nvidiaGpuTempEnabled
|
||||
DgopService.nonNvidiaGpuTempEnabled = hasGpuTempWidget || SessionData.nonNvidiaGpuTempEnabled
|
||||
const widgetId = typeof widget
|
||||
=== "string" ? widget : widget.id
|
||||
const widgetEnabled = typeof widget === "string" ? true : (widget.enabled !== false)
|
||||
return widgetId === "gpuTemp"
|
||||
&& widgetEnabled
|
||||
})
|
||||
|
||||
DgopService.gpuTempEnabled = hasGpuTempWidget
|
||||
|| SessionData.nvidiaGpuTempEnabled
|
||||
|| SessionData.nonNvidiaGpuTempEnabled
|
||||
DgopService.nvidiaGpuTempEnabled = hasGpuTempWidget
|
||||
|| SessionData.nvidiaGpuTempEnabled
|
||||
DgopService.nonNvidiaGpuTempEnabled = hasGpuTempWidget
|
||||
|| SessionData.nonNvidiaGpuTempEnabled
|
||||
}
|
||||
|
||||
Connections {
|
||||
function onTopBarTransparencyChanged() {
|
||||
root.backgroundTransparency = SettingsData.topBarTransparency
|
||||
}
|
||||
|
||||
|
||||
function onTopBarLeftWidgetsChanged() {
|
||||
root.updateGpuTempConfig()
|
||||
}
|
||||
|
||||
|
||||
function onTopBarCenterWidgetsChanged() {
|
||||
root.updateGpuTempConfig()
|
||||
}
|
||||
|
||||
|
||||
function onTopBarRightWidgetsChanged() {
|
||||
root.updateGpuTempConfig()
|
||||
}
|
||||
|
||||
target: SettingsData
|
||||
}
|
||||
|
||||
|
||||
Connections {
|
||||
function onNvidiaGpuTempEnabledChanged() {
|
||||
root.updateGpuTempConfig()
|
||||
}
|
||||
|
||||
|
||||
function onNonNvidiaGpuTempEnabledChanged() {
|
||||
root.updateGpuTempConfig()
|
||||
}
|
||||
|
||||
|
||||
target: SessionData
|
||||
}
|
||||
|
||||
@@ -189,8 +202,10 @@ PanelWindow {
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
radius: SettingsData.topBarSquareCorners ? 0 : Theme.cornerRadius
|
||||
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g,
|
||||
Theme.surfaceContainer.b, root.backgroundTransparency)
|
||||
color: Qt.rgba(Theme.surfaceContainer.r,
|
||||
Theme.surfaceContainer.g,
|
||||
Theme.surfaceContainer.b,
|
||||
root.backgroundTransparency)
|
||||
layer.enabled: true
|
||||
|
||||
Rectangle {
|
||||
@@ -203,7 +218,8 @@ PanelWindow {
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: Qt.rgba(Theme.surfaceTint.r, Theme.surfaceTint.g,
|
||||
color: Qt.rgba(Theme.surfaceTint.r,
|
||||
Theme.surfaceTint.g,
|
||||
Theme.surfaceTint.b, 0.04)
|
||||
radius: parent.radius
|
||||
|
||||
@@ -242,8 +258,7 @@ PanelWindow {
|
||||
readonly property int launcherButtonWidth: 40
|
||||
readonly property int workspaceSwitcherWidth: 120 // Approximate
|
||||
readonly property int focusedAppMaxWidth: 456 // Fixed width since we don't have focusedApp reference
|
||||
readonly property int estimatedLeftSectionWidth: launcherButtonWidth + workspaceSwitcherWidth
|
||||
+ focusedAppMaxWidth + (Theme.spacingXS * 2)
|
||||
readonly property int estimatedLeftSectionWidth: launcherButtonWidth + workspaceSwitcherWidth + focusedAppMaxWidth + (Theme.spacingXS * 2)
|
||||
readonly property int rightSectionWidth: rightSection.width
|
||||
readonly property int clockWidth: 120 // Approximate clock width
|
||||
readonly property int mediaMaxWidth: 280 // Normal max width
|
||||
@@ -254,19 +269,17 @@ PanelWindow {
|
||||
readonly property int clockLeftEdge: (availableWidth - clockWidth) / 2
|
||||
readonly property int clockRightEdge: clockLeftEdge + clockWidth
|
||||
readonly property int leftSectionRightEdge: estimatedLeftSectionWidth
|
||||
readonly property int mediaLeftEdge: clockLeftEdge - mediaMaxWidth - Theme.spacingS
|
||||
readonly property int mediaLeftEdge: clockLeftEdge - mediaMaxWidth
|
||||
- Theme.spacingS
|
||||
readonly property int rightSectionLeftEdge: availableWidth - rightSectionWidth
|
||||
readonly property int leftToClockGap: Math.max(
|
||||
0,
|
||||
clockLeftEdge - leftSectionRightEdge)
|
||||
readonly property int leftToMediaGap: mediaMaxWidth > 0 ? Math.max(
|
||||
0,
|
||||
mediaLeftEdge - leftSectionRightEdge) : leftToClockGap
|
||||
0,
|
||||
clockLeftEdge - leftSectionRightEdge)
|
||||
readonly property int leftToMediaGap: mediaMaxWidth > 0 ? Math.max(0, mediaLeftEdge - leftSectionRightEdge) : leftToClockGap
|
||||
readonly property int mediaToClockGap: mediaMaxWidth > 0 ? Theme.spacingS : 0
|
||||
readonly property int clockToRightGap: validLayout ? Math.max(
|
||||
0,
|
||||
rightSectionLeftEdge
|
||||
- clockRightEdge) : 1000
|
||||
0,
|
||||
rightSectionLeftEdge - clockRightEdge) : 1000
|
||||
readonly property bool spacingTight: validLayout
|
||||
&& (leftToMediaGap < 150
|
||||
|| clockToRightGap < 100)
|
||||
@@ -396,9 +409,12 @@ PanelWindow {
|
||||
property int spacerSize: model.size || 20
|
||||
|
||||
anchors.verticalCenter: parent ? parent.verticalCenter : undefined
|
||||
active: topBarContent.getWidgetVisible(model.widgetId)
|
||||
sourceComponent: topBarContent.getWidgetComponent(model.widgetId)
|
||||
opacity: topBarContent.getWidgetEnabled(model.enabled) ? 1 : 0
|
||||
active: topBarContent.getWidgetVisible(
|
||||
model.widgetId)
|
||||
sourceComponent: topBarContent.getWidgetComponent(
|
||||
model.widgetId)
|
||||
opacity: topBarContent.getWidgetEnabled(
|
||||
model.enabled) ? 1 : 0
|
||||
asynchronous: false
|
||||
}
|
||||
}
|
||||
@@ -443,7 +459,8 @@ PanelWindow {
|
||||
let parentCenterX = width / 2
|
||||
if (totalWidgets % 2 === 1) {
|
||||
let middleIndex = Math.floor(totalWidgets / 2)
|
||||
let currentX = parentCenterX - (centerWidgets[middleIndex].width / 2)
|
||||
let currentX = parentCenterX
|
||||
- (centerWidgets[middleIndex].width / 2)
|
||||
centerWidgets[middleIndex].x = currentX
|
||||
centerWidgets[middleIndex].anchors.horizontalCenter = undefined
|
||||
currentX = centerWidgets[middleIndex].x
|
||||
@@ -452,7 +469,8 @@ PanelWindow {
|
||||
centerWidgets[i].x = currentX
|
||||
centerWidgets[i].anchors.horizontalCenter = undefined
|
||||
}
|
||||
currentX = centerWidgets[middleIndex].x + centerWidgets[middleIndex].width
|
||||
currentX = centerWidgets[middleIndex].x
|
||||
+ centerWidgets[middleIndex].width
|
||||
for (var i = middleIndex + 1; i < totalWidgets; i++) {
|
||||
currentX += spacing
|
||||
centerWidgets[i].x = currentX
|
||||
@@ -465,7 +483,7 @@ PanelWindow {
|
||||
let gapCenter = parentCenterX
|
||||
let halfSpacing = spacing / 2
|
||||
centerWidgets[leftMiddleIndex].x = gapCenter - halfSpacing
|
||||
- centerWidgets[leftMiddleIndex].width
|
||||
- centerWidgets[leftMiddleIndex].width
|
||||
centerWidgets[leftMiddleIndex].anchors.horizontalCenter = undefined
|
||||
centerWidgets[rightMiddleIndex].x = gapCenter + halfSpacing
|
||||
centerWidgets[rightMiddleIndex].anchors.horizontalCenter = undefined
|
||||
@@ -475,7 +493,8 @@ PanelWindow {
|
||||
centerWidgets[i].x = currentX
|
||||
centerWidgets[i].anchors.horizontalCenter = undefined
|
||||
}
|
||||
currentX = centerWidgets[rightMiddleIndex].x + centerWidgets[rightMiddleIndex].width
|
||||
currentX = centerWidgets[rightMiddleIndex].x
|
||||
+ centerWidgets[rightMiddleIndex].width
|
||||
for (var i = rightMiddleIndex + 1; i < totalWidgets; i++) {
|
||||
currentX += spacing
|
||||
centerWidgets[i].x = currentX
|
||||
@@ -490,8 +509,8 @@ PanelWindow {
|
||||
anchors.centerIn: parent
|
||||
Component.onCompleted: {
|
||||
Qt.callLater(() => {
|
||||
Qt.callLater(updateLayout)
|
||||
})
|
||||
Qt.callLater(updateLayout)
|
||||
})
|
||||
}
|
||||
|
||||
onWidthChanged: {
|
||||
@@ -517,18 +536,23 @@ PanelWindow {
|
||||
property int spacerSize: model.size || 20
|
||||
|
||||
anchors.verticalCenter: parent ? parent.verticalCenter : undefined
|
||||
active: topBarContent.getWidgetVisible(model.widgetId)
|
||||
sourceComponent: topBarContent.getWidgetComponent(model.widgetId)
|
||||
opacity: topBarContent.getWidgetEnabled(model.enabled) ? 1 : 0
|
||||
active: topBarContent.getWidgetVisible(
|
||||
model.widgetId)
|
||||
sourceComponent: topBarContent.getWidgetComponent(
|
||||
model.widgetId)
|
||||
opacity: topBarContent.getWidgetEnabled(
|
||||
model.enabled) ? 1 : 0
|
||||
asynchronous: false
|
||||
|
||||
|
||||
onLoaded: {
|
||||
if (item) {
|
||||
item.onWidthChanged.connect(centerSection.updateLayout)
|
||||
item.onWidthChanged.connect(
|
||||
centerSection.updateLayout)
|
||||
if (model.widgetId === "spacer")
|
||||
item.spacerSize = Qt.binding(() => {
|
||||
return model.size || 20
|
||||
})
|
||||
return model.size
|
||||
|| 20
|
||||
})
|
||||
Qt.callLater(centerSection.updateLayout)
|
||||
}
|
||||
}
|
||||
@@ -564,15 +588,17 @@ PanelWindow {
|
||||
property int spacerSize: model.size || 20
|
||||
|
||||
anchors.verticalCenter: parent ? parent.verticalCenter : undefined
|
||||
active: topBarContent.getWidgetVisible(model.widgetId)
|
||||
sourceComponent: topBarContent.getWidgetComponent(model.widgetId)
|
||||
opacity: topBarContent.getWidgetEnabled(model.enabled) ? 1 : 0
|
||||
active: topBarContent.getWidgetVisible(
|
||||
model.widgetId)
|
||||
sourceComponent: topBarContent.getWidgetComponent(
|
||||
model.widgetId)
|
||||
opacity: topBarContent.getWidgetEnabled(
|
||||
model.enabled) ? 1 : 0
|
||||
asynchronous: false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Component {
|
||||
id: clipboardComponent
|
||||
|
||||
@@ -582,8 +608,10 @@ PanelWindow {
|
||||
radius: Theme.cornerRadius
|
||||
color: {
|
||||
const baseColor = clipboardArea.containsMouse ? Theme.primaryHover : Theme.secondaryHover
|
||||
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)
|
||||
}
|
||||
|
||||
DankIcon {
|
||||
@@ -695,7 +723,8 @@ PanelWindow {
|
||||
onClockClicked: {
|
||||
centcomPopoutLoader.active = true
|
||||
if (centcomPopoutLoader.item) {
|
||||
centcomPopoutLoader.item.calendarVisible = !centcomPopoutLoader.item.calendarVisible
|
||||
centcomPopoutLoader.item.calendarVisible
|
||||
= !centcomPopoutLoader.item.calendarVisible
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -705,7 +734,8 @@ PanelWindow {
|
||||
id: mediaComponent
|
||||
|
||||
Media {
|
||||
compactMode: topBarContent.spacingTight || topBarContent.overlapping
|
||||
compactMode: topBarContent.spacingTight
|
||||
|| topBarContent.overlapping
|
||||
section: {
|
||||
if (parent && parent.parent === leftSection)
|
||||
return "left"
|
||||
@@ -723,7 +753,8 @@ PanelWindow {
|
||||
onClicked: {
|
||||
centcomPopoutLoader.active = true
|
||||
if (centcomPopoutLoader.item) {
|
||||
centcomPopoutLoader.item.calendarVisible = !centcomPopoutLoader.item.calendarVisible
|
||||
centcomPopoutLoader.item.calendarVisible
|
||||
= !centcomPopoutLoader.item.calendarVisible
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -750,7 +781,8 @@ PanelWindow {
|
||||
onClicked: {
|
||||
centcomPopoutLoader.active = true
|
||||
if (centcomPopoutLoader.item) {
|
||||
centcomPopoutLoader.item.calendarVisible = !centcomPopoutLoader.item.calendarVisible
|
||||
centcomPopoutLoader.item.calendarVisible
|
||||
= !centcomPopoutLoader.item.calendarVisible
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -801,10 +833,10 @@ PanelWindow {
|
||||
}
|
||||
parentScreen: root.screen
|
||||
toggleProcessList: () => {
|
||||
processListPopoutLoader.active = true
|
||||
if (processListPopoutLoader.item)
|
||||
return processListPopoutLoader.item.toggle()
|
||||
}
|
||||
processListPopoutLoader.active = true
|
||||
if (processListPopoutLoader.item)
|
||||
return processListPopoutLoader.item.toggle()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -827,10 +859,10 @@ PanelWindow {
|
||||
}
|
||||
parentScreen: root.screen
|
||||
toggleProcessList: () => {
|
||||
processListPopoutLoader.active = true
|
||||
if (processListPopoutLoader.item)
|
||||
return processListPopoutLoader.item.toggle()
|
||||
}
|
||||
processListPopoutLoader.active = true
|
||||
if (processListPopoutLoader.item)
|
||||
return processListPopoutLoader.item.toggle()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -853,10 +885,10 @@ PanelWindow {
|
||||
}
|
||||
parentScreen: root.screen
|
||||
toggleProcessList: () => {
|
||||
processListPopoutLoader.active = true
|
||||
if (processListPopoutLoader.item)
|
||||
return processListPopoutLoader.item.toggle()
|
||||
}
|
||||
processListPopoutLoader.active = true
|
||||
if (processListPopoutLoader.item)
|
||||
return processListPopoutLoader.item.toggle()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -880,10 +912,10 @@ PanelWindow {
|
||||
parentScreen: root.screen
|
||||
widgetData: parent.widgetData
|
||||
toggleProcessList: () => {
|
||||
processListPopoutLoader.active = true
|
||||
if (processListPopoutLoader.item)
|
||||
return processListPopoutLoader.item.toggle()
|
||||
}
|
||||
processListPopoutLoader.active = true
|
||||
if (processListPopoutLoader.item)
|
||||
return processListPopoutLoader.item.toggle()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1004,7 +1036,8 @@ PanelWindow {
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: "transparent"
|
||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
|
||||
border.color: Qt.rgba(Theme.outline.r,
|
||||
Theme.outline.g,
|
||||
Theme.outline.b, 0.1)
|
||||
border.width: 1
|
||||
radius: 2
|
||||
|
||||
@@ -4,87 +4,87 @@ import qs.Services
|
||||
import qs.Widgets
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
id: root
|
||||
|
||||
property string section: "center"
|
||||
property var popupTarget: null
|
||||
property var parentScreen: null
|
||||
property string section: "center"
|
||||
property var popupTarget: null
|
||||
property var parentScreen: null
|
||||
|
||||
signal clicked
|
||||
signal clicked
|
||||
|
||||
visible: SettingsData.weatherEnabled
|
||||
width: visible ? Math.min(100,
|
||||
weatherRow.implicitWidth + Theme.spacingS * 2) : 0
|
||||
height: 30
|
||||
radius: Theme.cornerRadius
|
||||
color: {
|
||||
const baseColor = weatherArea.containsMouse ? Theme.primaryHover : Theme.surfaceTextHover
|
||||
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
|
||||
baseColor.a * Theme.widgetTransparency)
|
||||
}
|
||||
|
||||
Ref {
|
||||
service: WeatherService
|
||||
}
|
||||
|
||||
Row {
|
||||
id: weatherRow
|
||||
|
||||
anchors.centerIn: parent
|
||||
spacing: Theme.spacingXS
|
||||
|
||||
DankIcon {
|
||||
name: WeatherService.getWeatherIcon(WeatherService.weather.wCode)
|
||||
size: Theme.iconSize - 4
|
||||
color: Theme.primary
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
visible: SettingsData.weatherEnabled
|
||||
width: visible ? Math.min(100,
|
||||
weatherRow.implicitWidth + Theme.spacingS * 2) : 0
|
||||
height: 30
|
||||
radius: Theme.cornerRadius
|
||||
color: {
|
||||
const baseColor = weatherArea.containsMouse ? Theme.primaryHover : Theme.surfaceTextHover
|
||||
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
|
||||
baseColor.a * Theme.widgetTransparency)
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: {
|
||||
var temp = SettingsData.useFahrenheit ? WeatherService.weather.tempF : WeatherService.weather.temp
|
||||
if (temp === undefined || temp === null || temp === 0) {
|
||||
return "--°" + (SettingsData.useFahrenheit ? "F" : "C")
|
||||
Ref {
|
||||
service: WeatherService
|
||||
}
|
||||
|
||||
Row {
|
||||
id: weatherRow
|
||||
|
||||
anchors.centerIn: parent
|
||||
spacing: Theme.spacingXS
|
||||
|
||||
DankIcon {
|
||||
name: WeatherService.getWeatherIcon(WeatherService.weather.wCode)
|
||||
size: Theme.iconSize - 4
|
||||
color: Theme.primary
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
return temp + "°" + (SettingsData.useFahrenheit ? "F" : "C")
|
||||
}
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: weatherArea
|
||||
|
||||
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,
|
||||
Theme.barHeight + Theme.spacingXS,
|
||||
width, section, currentScreen)
|
||||
}
|
||||
root.clicked()
|
||||
StyledText {
|
||||
text: {
|
||||
var temp = SettingsData.useFahrenheit ? WeatherService.weather.tempF : WeatherService.weather.temp
|
||||
if (temp === undefined || temp === null || temp === 0) {
|
||||
return "--°" + (SettingsData.useFahrenheit ? "F" : "C")
|
||||
}
|
||||
return temp + "°" + (SettingsData.useFahrenheit ? "F" : "C")
|
||||
}
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
}
|
||||
MouseArea {
|
||||
id: weatherArea
|
||||
|
||||
Behavior on width {
|
||||
NumberAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
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, Theme.barHeight + Theme.spacingXS,
|
||||
width, section, currentScreen)
|
||||
}
|
||||
root.clicked()
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on width {
|
||||
NumberAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,203 +6,209 @@ import qs.Services
|
||||
import qs.Widgets
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
id: root
|
||||
|
||||
property string screenName: ""
|
||||
property int currentWorkspace: getDisplayActiveWorkspace()
|
||||
property var workspaceList: {
|
||||
var baseList = getDisplayWorkspaces()
|
||||
return SettingsData.showWorkspacePadding ? padWorkspaces(
|
||||
baseList) : baseList
|
||||
}
|
||||
|
||||
function padWorkspaces(list) {
|
||||
var padded = list.slice()
|
||||
while (padded.length < 3)
|
||||
padded.push(-1) // Use -1 as a placeholder
|
||||
return padded
|
||||
}
|
||||
|
||||
function getDisplayWorkspaces() {
|
||||
if (!NiriService.niriAvailable || NiriService.allWorkspaces.length === 0)
|
||||
return [1, 2]
|
||||
|
||||
if (!root.screenName)
|
||||
return NiriService.getCurrentOutputWorkspaceNumbers()
|
||||
|
||||
var displayWorkspaces = []
|
||||
for (var i = 0; i < NiriService.allWorkspaces.length; i++) {
|
||||
var ws = NiriService.allWorkspaces[i]
|
||||
if (ws.output === root.screenName)
|
||||
displayWorkspaces.push(ws.idx + 1)
|
||||
}
|
||||
return displayWorkspaces.length > 0 ? displayWorkspaces : [1, 2]
|
||||
}
|
||||
|
||||
function getDisplayActiveWorkspace() {
|
||||
if (!NiriService.niriAvailable || NiriService.allWorkspaces.length === 0)
|
||||
return 1
|
||||
|
||||
if (!root.screenName)
|
||||
return NiriService.getCurrentWorkspaceNumber()
|
||||
|
||||
for (var i = 0; i < NiriService.allWorkspaces.length; i++) {
|
||||
var ws = NiriService.allWorkspaces[i]
|
||||
if (ws.output === root.screenName && ws.is_active)
|
||||
return ws.idx + 1
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
width: SettingsData.showWorkspacePadding ? Math.max(
|
||||
120,
|
||||
workspaceRow.implicitWidth + Theme.spacingL
|
||||
* 2) : workspaceRow.implicitWidth
|
||||
+ Theme.spacingL * 2
|
||||
height: 30
|
||||
radius: Theme.cornerRadius
|
||||
color: {
|
||||
const baseColor = Theme.surfaceTextHover
|
||||
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
|
||||
baseColor.a * Theme.widgetTransparency)
|
||||
}
|
||||
visible: NiriService.niriAvailable
|
||||
|
||||
Connections {
|
||||
function onAllWorkspacesChanged() {
|
||||
root.workspaceList
|
||||
= SettingsData.showWorkspacePadding ? root.padWorkspaces(
|
||||
root.getDisplayWorkspaces(
|
||||
)) : root.getDisplayWorkspaces()
|
||||
root.currentWorkspace = root.getDisplayActiveWorkspace()
|
||||
property string screenName: ""
|
||||
property int currentWorkspace: getDisplayActiveWorkspace()
|
||||
property var workspaceList: {
|
||||
var baseList = getDisplayWorkspaces()
|
||||
return SettingsData.showWorkspacePadding ? padWorkspaces(
|
||||
baseList) : baseList
|
||||
}
|
||||
|
||||
function onFocusedWorkspaceIndexChanged() {
|
||||
root.currentWorkspace = root.getDisplayActiveWorkspace()
|
||||
function padWorkspaces(list) {
|
||||
var padded = list.slice()
|
||||
while (padded.length < 3)
|
||||
padded.push(-1) // Use -1 as a placeholder
|
||||
return padded
|
||||
}
|
||||
|
||||
function onNiriAvailableChanged() {
|
||||
if (NiriService.niriAvailable) {
|
||||
root.workspaceList
|
||||
= SettingsData.showWorkspacePadding ? root.padWorkspaces(
|
||||
root.getDisplayWorkspaces(
|
||||
)) : root.getDisplayWorkspaces()
|
||||
root.currentWorkspace = root.getDisplayActiveWorkspace()
|
||||
}
|
||||
}
|
||||
function getDisplayWorkspaces() {
|
||||
if (!NiriService.niriAvailable
|
||||
|| NiriService.allWorkspaces.length === 0)
|
||||
return [1, 2]
|
||||
|
||||
target: NiriService
|
||||
}
|
||||
if (!root.screenName)
|
||||
return NiriService.getCurrentOutputWorkspaceNumbers()
|
||||
|
||||
Connections {
|
||||
function onShowWorkspacePaddingChanged() {
|
||||
var baseList = root.getDisplayWorkspaces()
|
||||
root.workspaceList = SettingsData.showWorkspacePadding ? root.padWorkspaces(
|
||||
baseList) : baseList
|
||||
}
|
||||
|
||||
target: SettingsData
|
||||
}
|
||||
|
||||
Row {
|
||||
id: workspaceRow
|
||||
|
||||
anchors.centerIn: parent
|
||||
spacing: Theme.spacingS
|
||||
|
||||
Repeater {
|
||||
model: root.workspaceList
|
||||
|
||||
Rectangle {
|
||||
property bool isActive: modelData === root.currentWorkspace
|
||||
property bool isPlaceholder: modelData === -1
|
||||
property bool isHovered: mouseArea.containsMouse
|
||||
property int sequentialNumber: index + 1
|
||||
property var workspaceData: {
|
||||
if (isPlaceholder || !NiriService.niriAvailable) return null
|
||||
for (var i = 0; i < NiriService.allWorkspaces.length; i++) {
|
||||
var displayWorkspaces = []
|
||||
for (var i = 0; i < NiriService.allWorkspaces.length; i++) {
|
||||
var ws = NiriService.allWorkspaces[i]
|
||||
if (ws.idx + 1 === modelData) return ws
|
||||
}
|
||||
return null
|
||||
if (ws.output === root.screenName)
|
||||
displayWorkspaces.push(ws.idx + 1)
|
||||
}
|
||||
return displayWorkspaces.length > 0 ? displayWorkspaces : [1, 2]
|
||||
}
|
||||
|
||||
function getDisplayActiveWorkspace() {
|
||||
if (!NiriService.niriAvailable
|
||||
|| NiriService.allWorkspaces.length === 0)
|
||||
return 1
|
||||
|
||||
if (!root.screenName)
|
||||
return NiriService.getCurrentWorkspaceNumber()
|
||||
|
||||
for (var i = 0; i < NiriService.allWorkspaces.length; i++) {
|
||||
var ws = NiriService.allWorkspaces[i]
|
||||
if (ws.output === root.screenName && ws.is_active)
|
||||
return ws.idx + 1
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
width: SettingsData.showWorkspacePadding ? Math.max(
|
||||
120,
|
||||
workspaceRow.implicitWidth + Theme.spacingL
|
||||
* 2) : workspaceRow.implicitWidth
|
||||
+ Theme.spacingL * 2
|
||||
height: 30
|
||||
radius: Theme.cornerRadius
|
||||
color: {
|
||||
const baseColor = Theme.surfaceTextHover
|
||||
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b,
|
||||
baseColor.a * Theme.widgetTransparency)
|
||||
}
|
||||
visible: NiriService.niriAvailable
|
||||
|
||||
Connections {
|
||||
function onAllWorkspacesChanged() {
|
||||
root.workspaceList
|
||||
= SettingsData.showWorkspacePadding ? root.padWorkspaces(
|
||||
root.getDisplayWorkspaces(
|
||||
)) : root.getDisplayWorkspaces()
|
||||
root.currentWorkspace = root.getDisplayActiveWorkspace()
|
||||
}
|
||||
|
||||
function onFocusedWorkspaceIndexChanged() {
|
||||
root.currentWorkspace = root.getDisplayActiveWorkspace()
|
||||
}
|
||||
|
||||
function onNiriAvailableChanged() {
|
||||
if (NiriService.niriAvailable) {
|
||||
root.workspaceList = SettingsData.showWorkspacePadding ? root.padWorkspaces(root.getDisplayWorkspaces()) : root.getDisplayWorkspaces()
|
||||
root.currentWorkspace = root.getDisplayActiveWorkspace()
|
||||
}
|
||||
}
|
||||
|
||||
target: NiriService
|
||||
}
|
||||
|
||||
Connections {
|
||||
function onShowWorkspacePaddingChanged() {
|
||||
var baseList = root.getDisplayWorkspaces()
|
||||
root.workspaceList = SettingsData.showWorkspacePadding ? root.padWorkspaces(
|
||||
baseList) : baseList
|
||||
}
|
||||
|
||||
target: SettingsData
|
||||
}
|
||||
|
||||
Row {
|
||||
id: workspaceRow
|
||||
|
||||
anchors.centerIn: parent
|
||||
spacing: Theme.spacingS
|
||||
|
||||
Repeater {
|
||||
model: root.workspaceList
|
||||
|
||||
Rectangle {
|
||||
property bool isActive: modelData === root.currentWorkspace
|
||||
property bool isPlaceholder: modelData === -1
|
||||
property bool isHovered: mouseArea.containsMouse
|
||||
property int sequentialNumber: index + 1
|
||||
property var workspaceData: {
|
||||
if (isPlaceholder || !NiriService.niriAvailable)
|
||||
return null
|
||||
for (var i = 0; i < NiriService.allWorkspaces.length; i++) {
|
||||
var ws = NiriService.allWorkspaces[i]
|
||||
if (ws.idx + 1 === modelData)
|
||||
return ws
|
||||
}
|
||||
return null
|
||||
}
|
||||
property var iconData: workspaceData
|
||||
&& workspaceData.name ? SettingsData.getWorkspaceNameIcon(
|
||||
workspaceData.name) : null
|
||||
property bool hasIcon: iconData !== null
|
||||
|
||||
width: isActive ? Theme.spacingXL + Theme.spacingM : Theme.spacingL
|
||||
+ Theme.spacingXS
|
||||
height: Theme.spacingL
|
||||
radius: height / 2
|
||||
color: isActive ? Theme.primary : isPlaceholder ? Theme.surfaceTextLight : isHovered ? Theme.outlineButton : Theme.surfaceTextAlpha
|
||||
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
|
||||
anchors.fill: parent
|
||||
hoverEnabled: !isPlaceholder
|
||||
cursorShape: isPlaceholder ? Qt.ArrowCursor : Qt.PointingHandCursor
|
||||
enabled: !isPlaceholder
|
||||
onClicked: {
|
||||
if (!isPlaceholder)
|
||||
NiriService.switchToWorkspace(modelData - 1)
|
||||
}
|
||||
}
|
||||
|
||||
// Icon display (priority over numbers)
|
||||
DankIcon {
|
||||
visible: hasIcon && iconData.type === "icon"
|
||||
anchors.centerIn: parent
|
||||
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
|
||||
weight: isActive && !isPlaceholder ? 500 : 400
|
||||
}
|
||||
|
||||
// Custom text display (priority over numbers)
|
||||
StyledText {
|
||||
visible: hasIcon && iconData.type === "text"
|
||||
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
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
font.weight: isActive
|
||||
&& !isPlaceholder ? Font.DemiBold : Font.Normal
|
||||
}
|
||||
|
||||
// Number display (secondary priority, only when no icon)
|
||||
StyledText {
|
||||
visible: SettingsData.showWorkspaceIndex && !hasIcon
|
||||
anchors.centerIn: parent
|
||||
text: isPlaceholder ? sequentialNumber : sequentialNumber
|
||||
color: isActive ? Qt.rgba(
|
||||
Theme.surfaceContainer.r,
|
||||
Theme.surfaceContainer.g,
|
||||
Theme.surfaceContainer.b,
|
||||
0.95) : isPlaceholder ? Theme.surfaceTextAlpha : Theme.surfaceTextMedium
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
font.weight: isActive
|
||||
&& !isPlaceholder ? Font.DemiBold : Font.Normal
|
||||
}
|
||||
|
||||
Behavior on width {
|
||||
NumberAnimation {
|
||||
duration: Theme.mediumDuration
|
||||
easing.type: Theme.emphasizedEasing
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: Theme.mediumDuration
|
||||
easing.type: Theme.emphasizedEasing
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
property var iconData: workspaceData && workspaceData.name ? SettingsData.getWorkspaceNameIcon(workspaceData.name) : null
|
||||
property bool hasIcon: iconData !== null
|
||||
|
||||
width: isActive ? Theme.spacingXL + Theme.spacingM : Theme.spacingL + Theme.spacingXS
|
||||
height: Theme.spacingL
|
||||
radius: height / 2
|
||||
color: isActive ? Theme.primary : isPlaceholder ? Theme.surfaceTextLight : isHovered ? Theme.outlineButton : Theme.surfaceTextAlpha
|
||||
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
|
||||
anchors.fill: parent
|
||||
hoverEnabled: !isPlaceholder
|
||||
cursorShape: isPlaceholder ? Qt.ArrowCursor : Qt.PointingHandCursor
|
||||
enabled: !isPlaceholder
|
||||
onClicked: {
|
||||
if (!isPlaceholder)
|
||||
NiriService.switchToWorkspace(modelData - 1)
|
||||
}
|
||||
}
|
||||
|
||||
// Icon display (priority over numbers)
|
||||
DankIcon {
|
||||
visible: hasIcon && iconData.type === "icon"
|
||||
anchors.centerIn: parent
|
||||
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
|
||||
weight: isActive && !isPlaceholder ? 500 : 400
|
||||
}
|
||||
|
||||
// Custom text display (priority over numbers)
|
||||
StyledText {
|
||||
visible: hasIcon && iconData.type === "text"
|
||||
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
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
font.weight: isActive && !isPlaceholder ? Font.DemiBold : Font.Normal
|
||||
}
|
||||
|
||||
// Number display (secondary priority, only when no icon)
|
||||
StyledText {
|
||||
visible: SettingsData.showWorkspaceIndex && !hasIcon
|
||||
anchors.centerIn: parent
|
||||
text: isPlaceholder ? sequentialNumber : sequentialNumber
|
||||
color: isActive ? Qt.rgba(
|
||||
Theme.surfaceContainer.r,
|
||||
Theme.surfaceContainer.g,
|
||||
Theme.surfaceContainer.b,
|
||||
0.95) : isPlaceholder ? Theme.surfaceTextAlpha : Theme.surfaceTextMedium
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
font.weight: isActive && !isPlaceholder ? Font.DemiBold : Font.Normal
|
||||
}
|
||||
|
||||
Behavior on width {
|
||||
NumberAnimation {
|
||||
duration: Theme.mediumDuration
|
||||
easing.type: Theme.emphasizedEasing
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: Theme.mediumDuration
|
||||
easing.type: Theme.emphasizedEasing
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user