mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2025-12-06 21:45:38 -05:00
smarter distance calculation
This commit is contained in:
@@ -23,15 +23,14 @@ Item {
|
|||||||
running: true
|
running: true
|
||||||
onExited: (exitCode) => {
|
onExited: (exitCode) => {
|
||||||
root.cavaAvailable = exitCode === 0;
|
root.cavaAvailable = exitCode === 0;
|
||||||
if (root.cavaAvailable) {
|
if (root.cavaAvailable)
|
||||||
cavaProcess.running = Qt.binding(() => {
|
cavaProcess.running = Qt.binding(() => {
|
||||||
return root.hasActiveMedia && root.activePlayer && root.activePlayer.playbackState === MprisPlaybackState.Playing;
|
return root.hasActiveMedia && root.activePlayer && root.activePlayer.playbackState === MprisPlaybackState.Playing;
|
||||||
});
|
});
|
||||||
} else {
|
else
|
||||||
fallbackTimer.running = Qt.binding(() => {
|
fallbackTimer.running = Qt.binding(() => {
|
||||||
return root.hasActiveMedia && root.activePlayer && root.activePlayer.playbackState === MprisPlaybackState.Playing;
|
return root.hasActiveMedia && root.activePlayer && root.activePlayer.playbackState === MprisPlaybackState.Playing;
|
||||||
});
|
});
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ PanelWindow {
|
|||||||
PowerProfiles.profile = profile;
|
PowerProfiles.profile = profile;
|
||||||
if (PowerProfiles.profile !== profile)
|
if (PowerProfiles.profile !== profile)
|
||||||
ToastService.showError("Failed to set power profile");
|
ToastService.showError("Failed to set power profile");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
visible: batteryPopupVisible
|
visible: batteryPopupVisible
|
||||||
@@ -51,381 +52,190 @@ PanelWindow {
|
|||||||
onClicked: function(mouse) {
|
onClicked: function(mouse) {
|
||||||
// Only close if click is outside the content loader
|
// Only close if click is outside the content loader
|
||||||
var localPos = mapToItem(contentLoader, mouse.x, mouse.y);
|
var localPos = mapToItem(contentLoader, mouse.x, mouse.y);
|
||||||
if (localPos.x < 0 || localPos.x > contentLoader.width ||
|
if (localPos.x < 0 || localPos.x > contentLoader.width || localPos.y < 0 || localPos.y > contentLoader.height)
|
||||||
localPos.y < 0 || localPos.y > contentLoader.height) {
|
|
||||||
batteryPopupVisible = false;
|
batteryPopupVisible = false;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Loader {
|
Loader {
|
||||||
id: contentLoader
|
id: contentLoader
|
||||||
asynchronous: true
|
|
||||||
active: batteryPopupVisible
|
|
||||||
|
|
||||||
readonly property real targetWidth: Math.min(380, Screen.width - Theme.spacingL * 2)
|
readonly property real targetWidth: Math.min(380, Screen.width - Theme.spacingL * 2)
|
||||||
readonly property real targetHeight: Math.min(450, Screen.height - Theme.barHeight - Theme.spacingS * 2)
|
readonly property real targetHeight: Math.min(450, Screen.height - Theme.barHeight - Theme.spacingS * 2)
|
||||||
|
|
||||||
|
asynchronous: true
|
||||||
|
active: batteryPopupVisible
|
||||||
width: targetWidth
|
width: targetWidth
|
||||||
height: targetHeight
|
height: targetHeight
|
||||||
x: Math.max(Theme.spacingL, Screen.width - targetWidth - Theme.spacingL)
|
x: Math.max(Theme.spacingL, Screen.width - targetWidth - Theme.spacingL)
|
||||||
y: Theme.barHeight + Theme.spacingS
|
y: Theme.barHeight + Theme.spacingS
|
||||||
|
|
||||||
// GPU-accelerated scale + opacity animation
|
// GPU-accelerated scale + opacity animation
|
||||||
opacity: batteryPopupVisible ? 1 : 0
|
opacity: batteryPopupVisible ? 1 : 0
|
||||||
scale: batteryPopupVisible ? 1 : 0.9
|
scale: batteryPopupVisible ? 1 : 0.9
|
||||||
|
|
||||||
Behavior on opacity {
|
Behavior on opacity {
|
||||||
NumberAnimation {
|
NumberAnimation {
|
||||||
duration: Anims.durMed
|
duration: Anims.durMed
|
||||||
easing.type: Easing.BezierSpline
|
easing.type: Easing.BezierSpline
|
||||||
easing.bezierCurve: Anims.emphasized
|
easing.bezierCurve: Anims.emphasized
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Behavior on scale {
|
Behavior on scale {
|
||||||
NumberAnimation {
|
NumberAnimation {
|
||||||
duration: Anims.durMed
|
duration: Anims.durMed
|
||||||
easing.type: Easing.BezierSpline
|
easing.type: Easing.BezierSpline
|
||||||
easing.bezierCurve: Anims.emphasized
|
easing.bezierCurve: Anims.emphasized
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sourceComponent: Rectangle {
|
sourceComponent: Rectangle {
|
||||||
color: Theme.popupBackground()
|
color: Theme.popupBackground()
|
||||||
radius: Theme.cornerRadiusLarge
|
radius: Theme.cornerRadiusLarge
|
||||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
|
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
|
||||||
border.width: 1
|
border.width: 1
|
||||||
|
|
||||||
// Remove layer rendering for better performance
|
// Remove layer rendering for better performance
|
||||||
antialiasing: true
|
antialiasing: true
|
||||||
smooth: true
|
smooth: true
|
||||||
|
|
||||||
|
ScrollView {
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: Theme.spacingL
|
||||||
|
clip: true
|
||||||
|
|
||||||
ScrollView {
|
Column {
|
||||||
anchors.fill: parent
|
|
||||||
anchors.margins: Theme.spacingL
|
|
||||||
clip: true
|
|
||||||
|
|
||||||
Column {
|
|
||||||
width: parent.width
|
|
||||||
spacing: Theme.spacingL
|
|
||||||
|
|
||||||
// Header
|
|
||||||
Row {
|
|
||||||
width: parent.width
|
width: parent.width
|
||||||
|
spacing: Theme.spacingL
|
||||||
|
|
||||||
Text {
|
// Header
|
||||||
text: BatteryService.batteryAvailable ? "Battery Information" : "Power Management"
|
Row {
|
||||||
font.pixelSize: Theme.fontSizeLarge
|
width: parent.width
|
||||||
color: Theme.surfaceText
|
|
||||||
font.weight: Font.Medium
|
Text {
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
text: BatteryService.batteryAvailable ? "Battery Information" : "Power Management"
|
||||||
}
|
font.pixelSize: Theme.fontSizeLarge
|
||||||
|
color: Theme.surfaceText
|
||||||
|
font.weight: Font.Medium
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
width: parent.width - 200
|
||||||
|
height: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
width: 32
|
||||||
|
height: 32
|
||||||
|
radius: 16
|
||||||
|
color: closeBatteryArea.containsMouse ? Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12) : "transparent"
|
||||||
|
|
||||||
|
DankIcon {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
name: "close"
|
||||||
|
size: Theme.iconSize - 4
|
||||||
|
color: closeBatteryArea.containsMouse ? Theme.error : Theme.surfaceText
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: closeBatteryArea
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
onClicked: {
|
||||||
|
batteryPopupVisible = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
Item {
|
|
||||||
width: parent.width - 200
|
|
||||||
height: 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
width: 32
|
|
||||||
height: 32
|
|
||||||
radius: 16
|
|
||||||
color: closeBatteryArea.containsMouse ? Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12) : "transparent"
|
|
||||||
|
|
||||||
DankIcon {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
name: "close"
|
|
||||||
size: Theme.iconSize - 4
|
|
||||||
color: closeBatteryArea.containsMouse ? Theme.error : Theme.surfaceText
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
id: closeBatteryArea
|
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
hoverEnabled: true
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
onClicked: {
|
|
||||||
batteryPopupVisible = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
width: parent.width
|
|
||||||
height: 80
|
|
||||||
radius: Theme.cornerRadius
|
|
||||||
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.5)
|
|
||||||
border.color: BatteryService.isCharging ? Theme.primary : (BatteryService.isLowBattery ? Theme.error : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12))
|
|
||||||
border.width: BatteryService.isCharging || BatteryService.isLowBattery ? 2 : 1
|
|
||||||
visible: BatteryService.batteryAvailable
|
|
||||||
|
|
||||||
Row {
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.leftMargin: Theme.spacingL
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
spacing: Theme.spacingL
|
|
||||||
|
|
||||||
DankIcon {
|
|
||||||
name: Theme.getBatteryIcon(BatteryService.batteryLevel, BatteryService.isCharging, BatteryService.batteryAvailable)
|
|
||||||
size: Theme.iconSizeLarge
|
|
||||||
color: {
|
|
||||||
if (BatteryService.isLowBattery && !BatteryService.isCharging)
|
|
||||||
return Theme.error;
|
|
||||||
|
|
||||||
if (BatteryService.isCharging)
|
|
||||||
return Theme.primary;
|
|
||||||
|
|
||||||
return Theme.surfaceText;
|
|
||||||
}
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
}
|
|
||||||
|
|
||||||
Column {
|
|
||||||
spacing: 2
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
|
|
||||||
Row {
|
|
||||||
spacing: Theme.spacingM
|
|
||||||
|
|
||||||
Text {
|
|
||||||
text: BatteryService.batteryLevel + "%"
|
|
||||||
font.pixelSize: Theme.fontSizeLarge
|
|
||||||
color: {
|
|
||||||
if (BatteryService.isLowBattery && !BatteryService.isCharging)
|
|
||||||
return Theme.error;
|
|
||||||
|
|
||||||
if (BatteryService.isCharging)
|
|
||||||
return Theme.primary;
|
|
||||||
|
|
||||||
return Theme.surfaceText;
|
|
||||||
}
|
|
||||||
font.weight: Font.Bold
|
|
||||||
}
|
|
||||||
|
|
||||||
Text {
|
|
||||||
text: BatteryService.batteryStatus
|
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
|
||||||
color: {
|
|
||||||
if (BatteryService.isLowBattery && !BatteryService.isCharging)
|
|
||||||
return Theme.error;
|
|
||||||
|
|
||||||
if (BatteryService.isCharging)
|
|
||||||
return Theme.primary;
|
|
||||||
|
|
||||||
return Theme.surfaceText;
|
|
||||||
}
|
|
||||||
font.weight: Font.Medium
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Text {
|
|
||||||
text: {
|
|
||||||
let time = BatteryService.formatTimeRemaining();
|
|
||||||
if (time !== "Unknown")
|
|
||||||
return BatteryService.isCharging ? "Time until full: " + time : "Time remaining: " + time;
|
|
||||||
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
|
||||||
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
|
|
||||||
visible: text.length > 0
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// No battery info card
|
|
||||||
Rectangle {
|
|
||||||
width: parent.width
|
|
||||||
height: 80
|
|
||||||
radius: Theme.cornerRadius
|
|
||||||
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.5)
|
|
||||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
|
|
||||||
border.width: 1
|
|
||||||
visible: !BatteryService.batteryAvailable
|
|
||||||
|
|
||||||
Row {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
spacing: Theme.spacingL
|
|
||||||
|
|
||||||
DankIcon {
|
|
||||||
name: Theme.getBatteryIcon(0, false, false)
|
|
||||||
size: 36
|
|
||||||
color: Theme.surfaceText
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
}
|
|
||||||
|
|
||||||
Column {
|
|
||||||
spacing: Theme.spacingS
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
|
|
||||||
Text {
|
|
||||||
text: "No Battery Detected"
|
|
||||||
font.pixelSize: Theme.fontSizeLarge
|
|
||||||
color: Theme.surfaceText
|
|
||||||
font.weight: Font.Medium
|
|
||||||
}
|
|
||||||
|
|
||||||
Text {
|
|
||||||
text: "Power profile management is available"
|
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
|
||||||
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Battery details
|
|
||||||
Column {
|
|
||||||
width: parent.width
|
|
||||||
spacing: Theme.spacingM
|
|
||||||
visible: BatteryService.batteryAvailable
|
|
||||||
|
|
||||||
Text {
|
|
||||||
text: "Battery Details"
|
|
||||||
font.pixelSize: Theme.fontSizeLarge
|
|
||||||
color: Theme.surfaceText
|
|
||||||
font.weight: Font.Medium
|
|
||||||
}
|
|
||||||
|
|
||||||
Row {
|
|
||||||
width: parent.width
|
width: parent.width
|
||||||
spacing: Theme.spacingXL
|
height: 80
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.5)
|
||||||
|
border.color: BatteryService.isCharging ? Theme.primary : (BatteryService.isLowBattery ? Theme.error : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12))
|
||||||
|
border.width: BatteryService.isCharging || BatteryService.isLowBattery ? 2 : 1
|
||||||
|
visible: BatteryService.batteryAvailable
|
||||||
|
|
||||||
// Health
|
Row {
|
||||||
Column {
|
anchors.left: parent.left
|
||||||
spacing: 2
|
anchors.leftMargin: Theme.spacingL
|
||||||
width: (parent.width - Theme.spacingXL) / 2
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
spacing: Theme.spacingL
|
||||||
|
|
||||||
Text {
|
DankIcon {
|
||||||
text: "Health"
|
name: Theme.getBatteryIcon(BatteryService.batteryLevel, BatteryService.isCharging, BatteryService.batteryAvailable)
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
size: Theme.iconSizeLarge
|
||||||
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
|
|
||||||
font.weight: Font.Medium
|
|
||||||
}
|
|
||||||
|
|
||||||
Text {
|
|
||||||
text: BatteryService.batteryHealth
|
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
|
||||||
color: {
|
color: {
|
||||||
if (BatteryService.batteryHealth === "N/A")
|
if (BatteryService.isLowBattery && !BatteryService.isCharging)
|
||||||
return Theme.surfaceText;
|
return Theme.error;
|
||||||
|
|
||||||
var healthNum = parseInt(BatteryService.batteryHealth);
|
if (BatteryService.isCharging)
|
||||||
return healthNum < 80 ? Theme.error : Theme.surfaceText;
|
return Theme.primary;
|
||||||
|
|
||||||
|
return Theme.surfaceText;
|
||||||
}
|
}
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
Column {
|
||||||
|
spacing: 2
|
||||||
// Capacity
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
Column {
|
|
||||||
spacing: 2
|
|
||||||
width: (parent.width - Theme.spacingXL) / 2
|
|
||||||
|
|
||||||
Text {
|
|
||||||
text: "Capacity"
|
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
|
||||||
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
|
|
||||||
font.weight: Font.Medium
|
|
||||||
}
|
|
||||||
|
|
||||||
Text {
|
|
||||||
text: BatteryService.batteryCapacity > 0 ? BatteryService.batteryCapacity.toFixed(1) + " Wh" : "Unknown"
|
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
|
||||||
color: Theme.surfaceText
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Power profiles
|
|
||||||
Column {
|
|
||||||
width: parent.width
|
|
||||||
spacing: Theme.spacingM
|
|
||||||
visible: true
|
|
||||||
|
|
||||||
Text {
|
|
||||||
text: "Power Profile"
|
|
||||||
font.pixelSize: Theme.fontSizeLarge
|
|
||||||
color: Theme.surfaceText
|
|
||||||
font.weight: Font.Medium
|
|
||||||
}
|
|
||||||
|
|
||||||
Column {
|
|
||||||
width: parent.width
|
|
||||||
spacing: Theme.spacingS
|
|
||||||
|
|
||||||
Repeater {
|
|
||||||
model: (typeof PowerProfiles !== "undefined") ? [PowerProfile.PowerSaver, PowerProfile.Balanced].concat(PowerProfiles.hasPerformanceProfile ? [PowerProfile.Performance] : []) : [PowerProfile.PowerSaver, PowerProfile.Balanced, PowerProfile.Performance]
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
width: parent.width
|
|
||||||
height: 50
|
|
||||||
radius: Theme.cornerRadius
|
|
||||||
color: profileArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : (batteryPopout.isActiveProfile(modelData) ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.16) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.08))
|
|
||||||
border.color: batteryPopout.isActiveProfile(modelData) ? Theme.primary : "transparent"
|
|
||||||
border.width: 2
|
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.leftMargin: Theme.spacingL
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
spacing: Theme.spacingM
|
spacing: Theme.spacingM
|
||||||
|
|
||||||
DankIcon {
|
Text {
|
||||||
name: Theme.getPowerProfileIcon(modelData)
|
text: BatteryService.batteryLevel + "%"
|
||||||
size: Theme.iconSize
|
font.pixelSize: Theme.fontSizeLarge
|
||||||
color: batteryPopout.isActiveProfile(modelData) ? Theme.primary : Theme.surfaceText
|
color: {
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
if (BatteryService.isLowBattery && !BatteryService.isCharging)
|
||||||
|
return Theme.error;
|
||||||
|
|
||||||
|
if (BatteryService.isCharging)
|
||||||
|
return Theme.primary;
|
||||||
|
|
||||||
|
return Theme.surfaceText;
|
||||||
|
}
|
||||||
|
font.weight: Font.Bold
|
||||||
}
|
}
|
||||||
|
|
||||||
Column {
|
Text {
|
||||||
spacing: 2
|
text: BatteryService.batteryStatus
|
||||||
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
|
color: {
|
||||||
|
if (BatteryService.isLowBattery && !BatteryService.isCharging)
|
||||||
|
return Theme.error;
|
||||||
|
|
||||||
|
if (BatteryService.isCharging)
|
||||||
|
return Theme.primary;
|
||||||
|
|
||||||
|
return Theme.surfaceText;
|
||||||
|
}
|
||||||
|
font.weight: Font.Medium
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|
||||||
Text {
|
|
||||||
text: Theme.getPowerProfileLabel(modelData)
|
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
|
||||||
color: batteryPopout.isActiveProfile(modelData) ? Theme.primary : Theme.surfaceText
|
|
||||||
font.weight: batteryPopout.isActiveProfile(modelData) ? Font.Medium : Font.Normal
|
|
||||||
}
|
|
||||||
|
|
||||||
Text {
|
|
||||||
text: Theme.getPowerProfileDescription(modelData)
|
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
|
||||||
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseArea {
|
Text {
|
||||||
id: profileArea
|
text: {
|
||||||
|
let time = BatteryService.formatTimeRemaining();
|
||||||
|
if (time !== "Unknown")
|
||||||
|
return BatteryService.isCharging ? "Time until full: " + time : "Time remaining: " + time;
|
||||||
|
|
||||||
anchors.fill: parent
|
return "";
|
||||||
hoverEnabled: true
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
onClicked: {
|
|
||||||
batteryPopout.setProfile(modelData);
|
|
||||||
}
|
}
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
|
||||||
|
visible: text.length > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -434,46 +244,238 @@ PanelWindow {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
// No battery info card
|
||||||
|
Rectangle {
|
||||||
|
width: parent.width
|
||||||
|
height: 80
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.5)
|
||||||
|
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
|
||||||
|
border.width: 1
|
||||||
|
visible: !BatteryService.batteryAvailable
|
||||||
|
|
||||||
// Degradation reason warning
|
Row {
|
||||||
Rectangle {
|
anchors.centerIn: parent
|
||||||
width: parent.width
|
spacing: Theme.spacingL
|
||||||
height: 60
|
|
||||||
radius: Theme.cornerRadius
|
|
||||||
color: Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12)
|
|
||||||
border.color: Theme.error
|
|
||||||
border.width: 2
|
|
||||||
visible: (typeof PowerProfiles !== "undefined") && PowerProfiles.degradationReason !== PerformanceDegradationReason.None
|
|
||||||
|
|
||||||
Row {
|
DankIcon {
|
||||||
anchors.left: parent.left
|
name: Theme.getBatteryIcon(0, false, false)
|
||||||
anchors.leftMargin: Theme.spacingL
|
size: 36
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
color: Theme.surfaceText
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
Column {
|
||||||
|
spacing: Theme.spacingS
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|
||||||
|
Text {
|
||||||
|
text: "No Battery Detected"
|
||||||
|
font.pixelSize: Theme.fontSizeLarge
|
||||||
|
color: Theme.surfaceText
|
||||||
|
font.weight: Font.Medium
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
text: "Power profile management is available"
|
||||||
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
|
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Battery details
|
||||||
|
Column {
|
||||||
|
width: parent.width
|
||||||
spacing: Theme.spacingM
|
spacing: Theme.spacingM
|
||||||
|
visible: BatteryService.batteryAvailable
|
||||||
|
|
||||||
DankIcon {
|
Text {
|
||||||
name: "warning"
|
text: "Battery Details"
|
||||||
size: Theme.iconSize
|
font.pixelSize: Theme.fontSizeLarge
|
||||||
color: Theme.error
|
color: Theme.surfaceText
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
font.weight: Font.Medium
|
||||||
|
}
|
||||||
|
|
||||||
|
Row {
|
||||||
|
width: parent.width
|
||||||
|
spacing: Theme.spacingXL
|
||||||
|
|
||||||
|
// Health
|
||||||
|
Column {
|
||||||
|
spacing: 2
|
||||||
|
width: (parent.width - Theme.spacingXL) / 2
|
||||||
|
|
||||||
|
Text {
|
||||||
|
text: "Health"
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
|
||||||
|
font.weight: Font.Medium
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
text: BatteryService.batteryHealth
|
||||||
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
|
color: {
|
||||||
|
if (BatteryService.batteryHealth === "N/A")
|
||||||
|
return Theme.surfaceText;
|
||||||
|
|
||||||
|
var healthNum = parseInt(BatteryService.batteryHealth);
|
||||||
|
return healthNum < 80 ? Theme.error : Theme.surfaceText;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Capacity
|
||||||
|
Column {
|
||||||
|
spacing: 2
|
||||||
|
width: (parent.width - Theme.spacingXL) / 2
|
||||||
|
|
||||||
|
Text {
|
||||||
|
text: "Capacity"
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
|
||||||
|
font.weight: Font.Medium
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
text: BatteryService.batteryCapacity > 0 ? BatteryService.batteryCapacity.toFixed(1) + " Wh" : "Unknown"
|
||||||
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
|
color: Theme.surfaceText
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Power profiles
|
||||||
|
Column {
|
||||||
|
width: parent.width
|
||||||
|
spacing: Theme.spacingM
|
||||||
|
visible: true
|
||||||
|
|
||||||
|
Text {
|
||||||
|
text: "Power Profile"
|
||||||
|
font.pixelSize: Theme.fontSizeLarge
|
||||||
|
color: Theme.surfaceText
|
||||||
|
font.weight: Font.Medium
|
||||||
}
|
}
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
spacing: 2
|
width: parent.width
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
spacing: Theme.spacingS
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
model: (typeof PowerProfiles !== "undefined") ? [PowerProfile.PowerSaver, PowerProfile.Balanced].concat(PowerProfiles.hasPerformanceProfile ? [PowerProfile.Performance] : []) : [PowerProfile.PowerSaver, PowerProfile.Balanced, PowerProfile.Performance]
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
width: parent.width
|
||||||
|
height: 50
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
color: profileArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : (batteryPopout.isActiveProfile(modelData) ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.16) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.08))
|
||||||
|
border.color: batteryPopout.isActiveProfile(modelData) ? Theme.primary : "transparent"
|
||||||
|
border.width: 2
|
||||||
|
|
||||||
|
Row {
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: Theme.spacingL
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
spacing: Theme.spacingM
|
||||||
|
|
||||||
|
DankIcon {
|
||||||
|
name: Theme.getPowerProfileIcon(modelData)
|
||||||
|
size: Theme.iconSize
|
||||||
|
color: batteryPopout.isActiveProfile(modelData) ? Theme.primary : Theme.surfaceText
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
Column {
|
||||||
|
spacing: 2
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|
||||||
|
Text {
|
||||||
|
text: Theme.getPowerProfileLabel(modelData)
|
||||||
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
|
color: batteryPopout.isActiveProfile(modelData) ? Theme.primary : Theme.surfaceText
|
||||||
|
font.weight: batteryPopout.isActiveProfile(modelData) ? Font.Medium : Font.Normal
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
text: Theme.getPowerProfileDescription(modelData)
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: profileArea
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
onClicked: {
|
||||||
|
batteryPopout.setProfile(modelData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
Text {
|
|
||||||
text: "Power Profile Degradation"
|
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
|
||||||
color: Theme.error
|
|
||||||
font.weight: Font.Medium
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Text {
|
}
|
||||||
text: (typeof PowerProfiles !== "undefined") ? PerformanceDegradationReason.toString(PowerProfiles.degradationReason) : ""
|
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
}
|
||||||
color: Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.8)
|
|
||||||
|
// Degradation reason warning
|
||||||
|
Rectangle {
|
||||||
|
width: parent.width
|
||||||
|
height: 60
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
color: Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12)
|
||||||
|
border.color: Theme.error
|
||||||
|
border.width: 2
|
||||||
|
visible: (typeof PowerProfiles !== "undefined") && PowerProfiles.degradationReason !== PerformanceDegradationReason.None
|
||||||
|
|
||||||
|
Row {
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: Theme.spacingL
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
spacing: Theme.spacingM
|
||||||
|
|
||||||
|
DankIcon {
|
||||||
|
name: "warning"
|
||||||
|
size: Theme.iconSize
|
||||||
|
color: Theme.error
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
Column {
|
||||||
|
spacing: 2
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|
||||||
|
Text {
|
||||||
|
text: "Power Profile Degradation"
|
||||||
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
|
color: Theme.error
|
||||||
|
font.weight: Font.Medium
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
text: (typeof PowerProfiles !== "undefined") ? PerformanceDegradationReason.toString(PowerProfiles.degradationReason) : ""
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
color: Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.8)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -486,9 +488,6 @@ PanelWindow {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ Rectangle {
|
|||||||
id: root
|
id: root
|
||||||
|
|
||||||
property date currentDate: new Date()
|
property date currentDate: new Date()
|
||||||
|
property bool compactMode: false
|
||||||
|
|
||||||
signal clockClicked()
|
signal clockClicked()
|
||||||
|
|
||||||
@@ -36,6 +37,7 @@ Rectangle {
|
|||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.5)
|
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.5)
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
visible: !compactMode
|
||||||
}
|
}
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
@@ -44,6 +46,7 @@ Rectangle {
|
|||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
visible: !compactMode
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,11 +16,9 @@ Rectangle {
|
|||||||
height: 30
|
height: 30
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: cpuArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.16) : Qt.rgba(Theme.secondary.r, Theme.secondary.g, Theme.secondary.b, 0.08)
|
color: cpuArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.16) : Qt.rgba(Theme.secondary.r, Theme.secondary.g, Theme.secondary.b, 0.08)
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
SysMonitorService.addRef();
|
SysMonitorService.addRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onDestruction: {
|
Component.onDestruction: {
|
||||||
SysMonitorService.removeRef();
|
SysMonitorService.removeRef();
|
||||||
}
|
}
|
||||||
@@ -35,6 +33,7 @@ Rectangle {
|
|||||||
SysMonitorService.setSortBy("cpu");
|
SysMonitorService.setSortBy("cpu");
|
||||||
if (root.toggleProcessList)
|
if (root.toggleProcessList)
|
||||||
root.toggleProcessList();
|
root.toggleProcessList();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,64 +5,13 @@ import qs.Services
|
|||||||
Rectangle {
|
Rectangle {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
// Dynamic screen detection for laptop vs desktop monitor
|
property bool compactMode: false
|
||||||
readonly property bool isSmallScreen: {
|
property int availableWidth: 400
|
||||||
// Walk up the parent chain to find the TopBar PanelWindow
|
readonly property int baseWidth: contentRow.implicitWidth + Theme.spacingS * 2
|
||||||
let current = root.parent
|
readonly property int maxNormalWidth: 456
|
||||||
while (current && !current.screen) {
|
readonly property int maxCompactWidth: 200
|
||||||
current = current.parent
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!current || !current.screen) {
|
|
||||||
return true // Default to small if we can't detect
|
|
||||||
}
|
|
||||||
|
|
||||||
const s = current.screen
|
|
||||||
|
|
||||||
// Multi-method detection for laptop/small screens:
|
|
||||||
|
|
||||||
// Method 1: Check screen name for laptop indicators
|
|
||||||
const screenName = (s.name || "").toLowerCase()
|
|
||||||
if (screenName.includes("edp") || screenName.includes("lvds")) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Method 2: Check pixel density if available
|
|
||||||
try {
|
|
||||||
if (s.pixelDensity && s.pixelDensity > 1.5) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
} catch (e) { /* ignore */ }
|
|
||||||
|
|
||||||
// Method 3: Check device pixel ratio if available
|
|
||||||
try {
|
|
||||||
if (s.devicePixelRatio && s.devicePixelRatio > 1.25) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
} catch (e) { /* ignore */ }
|
|
||||||
|
|
||||||
// Method 4: Resolution-based fallback for smaller displays
|
|
||||||
if (s.width <= 1920 && s.height <= 1200) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Method 5: Check for high-res laptop displays
|
|
||||||
if ((s.width === 2400 && s.height === 1600) ||
|
|
||||||
(s.width === 2560 && s.height === 1600) ||
|
|
||||||
(s.width === 2880 && s.height === 1800)) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false // Default to large screen
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dynamic sizing based on screen type
|
|
||||||
readonly property int maxWidth: isSmallScreen ? 288 : 456
|
|
||||||
readonly property int appNameMaxWidth: isSmallScreen ? 130 : 180
|
|
||||||
readonly property int separatorWidth: 15
|
|
||||||
readonly property int titleMaxWidth: maxWidth - appNameMaxWidth - separatorWidth - (Theme.spacingS * 2)
|
|
||||||
|
|
||||||
width: Math.min(contentRow.implicitWidth + Theme.spacingS * 2, maxWidth)
|
width: compactMode ? Math.min(baseWidth, maxCompactWidth) : Math.min(baseWidth, maxNormalWidth)
|
||||||
height: 30
|
height: 30
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: mouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.08)
|
color: mouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.08)
|
||||||
@@ -83,10 +32,9 @@ Rectangle {
|
|||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
// App name gets reasonable space - only truncate if absolutely necessary
|
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
maximumLineCount: 1
|
maximumLineCount: 1
|
||||||
width: Math.min(implicitWidth, root.appNameMaxWidth)
|
width: Math.min(implicitWidth, compactMode ? 80 : 180)
|
||||||
}
|
}
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
@@ -105,17 +53,15 @@ Rectangle {
|
|||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
// Window title gets remaining space and shows ellipsis when truncated
|
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
maximumLineCount: 1
|
maximumLineCount: 1
|
||||||
width: Math.min(implicitWidth, root.titleMaxWidth)
|
width: Math.min(implicitWidth, compactMode ? 60 : 250)
|
||||||
|
visible: !compactMode || text.length < 15
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
// Non-interactive widget - just provides hover state for visual feedback
|
|
||||||
|
|
||||||
id: mouseArea
|
id: mouseArea
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
@@ -130,7 +76,6 @@ Rectangle {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Smooth width animation when the text changes
|
|
||||||
Behavior on width {
|
Behavior on width {
|
||||||
NumberAnimation {
|
NumberAnimation {
|
||||||
duration: Theme.shortDuration
|
duration: Theme.shortDuration
|
||||||
|
|||||||
@@ -9,59 +9,10 @@ Rectangle {
|
|||||||
|
|
||||||
readonly property MprisPlayer activePlayer: MprisController.activePlayer
|
readonly property MprisPlayer activePlayer: MprisController.activePlayer
|
||||||
readonly property bool playerAvailable: activePlayer !== null
|
readonly property bool playerAvailable: activePlayer !== null
|
||||||
|
property bool compactMode: false
|
||||||
// Screen detection for responsive design (same logic as FocusedApp)
|
readonly property int baseContentWidth: mediaRow.implicitWidth + Theme.spacingS * 2
|
||||||
readonly property bool isSmallScreen: {
|
readonly property int normalContentWidth: Math.min(280, baseContentWidth)
|
||||||
// Walk up the parent chain to find the TopBar PanelWindow
|
readonly property int compactContentWidth: Math.min(120, baseContentWidth)
|
||||||
let current = root.parent
|
|
||||||
while (current && !current.screen) {
|
|
||||||
current = current.parent
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!current || !current.screen) {
|
|
||||||
return true // Default to small if we can't detect
|
|
||||||
}
|
|
||||||
|
|
||||||
const s = current.screen
|
|
||||||
|
|
||||||
// Multi-method detection for laptop/small screens:
|
|
||||||
|
|
||||||
// Method 1: Check screen name for laptop indicators
|
|
||||||
const screenName = (s.name || "").toLowerCase()
|
|
||||||
if (screenName.includes("edp") || screenName.includes("lvds")) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Method 2: Check pixel density if available
|
|
||||||
try {
|
|
||||||
if (s.pixelDensity && s.pixelDensity > 1.5) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
} catch (e) { /* ignore */ }
|
|
||||||
|
|
||||||
// Method 3: Check device pixel ratio if available
|
|
||||||
try {
|
|
||||||
if (s.devicePixelRatio && s.devicePixelRatio > 1.25) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
} catch (e) { /* ignore */ }
|
|
||||||
|
|
||||||
// Method 4: Resolution-based fallback for smaller displays
|
|
||||||
if (s.width <= 1920 && s.height <= 1200) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Method 5: Check for high-res laptop displays
|
|
||||||
if ((s.width === 2400 && s.height === 1600) ||
|
|
||||||
(s.width === 2560 && s.height === 1600) ||
|
|
||||||
(s.width === 2880 && s.height === 1800)) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false // Default to large screen
|
|
||||||
}
|
|
||||||
|
|
||||||
readonly property int contentWidth: Math.min(280, mediaRow.implicitWidth + Theme.spacingS * 2)
|
|
||||||
|
|
||||||
signal clicked()
|
signal clicked()
|
||||||
|
|
||||||
@@ -76,7 +27,7 @@ Rectangle {
|
|||||||
PropertyChanges {
|
PropertyChanges {
|
||||||
target: root
|
target: root
|
||||||
opacity: 1
|
opacity: 1
|
||||||
width: contentWidth
|
width: compactMode ? compactContentWidth : normalContentWidth
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
@@ -130,7 +81,6 @@ Rectangle {
|
|||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
spacing: Theme.spacingXS
|
spacing: Theme.spacingXS
|
||||||
|
|
||||||
// Media info section (clickable to open full player)
|
|
||||||
Row {
|
Row {
|
||||||
id: mediaInfo
|
id: mediaInfo
|
||||||
|
|
||||||
@@ -144,8 +94,8 @@ Rectangle {
|
|||||||
id: mediaText
|
id: mediaText
|
||||||
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
width: 140
|
width: compactMode ? 60 : 140
|
||||||
visible: !root.isSmallScreen // Hide title text on small screens
|
visible: !compactMode
|
||||||
text: {
|
text: {
|
||||||
if (!activePlayer || !activePlayer.trackTitle)
|
if (!activePlayer || !activePlayer.trackTitle)
|
||||||
return "";
|
return "";
|
||||||
@@ -185,12 +135,10 @@ Rectangle {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Control buttons
|
|
||||||
Row {
|
Row {
|
||||||
spacing: Theme.spacingXS
|
spacing: Theme.spacingXS
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|
||||||
// Previous button
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
width: 20
|
width: 20
|
||||||
height: 20
|
height: 20
|
||||||
@@ -222,7 +170,6 @@ Rectangle {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Play/Pause button
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
width: 24
|
width: 24
|
||||||
height: 24
|
height: 24
|
||||||
@@ -252,7 +199,6 @@ Rectangle {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Next button
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
width: 20
|
width: 20
|
||||||
height: 20
|
height: 20
|
||||||
|
|||||||
@@ -16,11 +16,9 @@ Rectangle {
|
|||||||
height: 30
|
height: 30
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: ramArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.16) : Qt.rgba(Theme.secondary.r, Theme.secondary.g, Theme.secondary.b, 0.08)
|
color: ramArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.16) : Qt.rgba(Theme.secondary.r, Theme.secondary.g, Theme.secondary.b, 0.08)
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
SysMonitorService.addRef();
|
SysMonitorService.addRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onDestruction: {
|
Component.onDestruction: {
|
||||||
SysMonitorService.removeRef();
|
SysMonitorService.removeRef();
|
||||||
}
|
}
|
||||||
@@ -35,6 +33,7 @@ Rectangle {
|
|||||||
SysMonitorService.setSortBy("memory");
|
SysMonitorService.setSortBy("memory");
|
||||||
if (root.toggleProcessList)
|
if (root.toggleProcessList)
|
||||||
root.toggleProcessList();
|
root.toggleProcessList();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -44,14 +44,17 @@ Rectangle {
|
|||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
radius: Theme.cornerRadiusSmall
|
radius: Theme.cornerRadiusSmall
|
||||||
color: trayItemArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
|
color: trayItemArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
|
||||||
|
|
||||||
Behavior on color {
|
Behavior on color {
|
||||||
enabled: trayItemArea.containsMouse !== undefined
|
enabled: trayItemArea.containsMouse !== undefined
|
||||||
|
|
||||||
ColorAnimation {
|
ColorAnimation {
|
||||||
duration: Theme.shortDuration
|
duration: Theme.shortDuration
|
||||||
easing.type: Theme.standardEasing
|
easing.type: Theme.standardEasing
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Image {
|
Image {
|
||||||
@@ -66,23 +69,27 @@ Rectangle {
|
|||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
id: trayItemArea
|
id: trayItemArea
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
onClicked: (mouse) => {
|
onClicked: (mouse) => {
|
||||||
if (!trayItem) return;
|
if (!trayItem)
|
||||||
|
return ;
|
||||||
|
|
||||||
if (mouse.button === Qt.LeftButton) {
|
if (mouse.button === Qt.LeftButton) {
|
||||||
if (!trayItem.onlyMenu)
|
if (!trayItem.onlyMenu)
|
||||||
trayItem.activate();
|
trayItem.activate();
|
||||||
|
|
||||||
} else if (mouse.button === Qt.RightButton) {
|
} else if (mouse.button === Qt.RightButton) {
|
||||||
if (trayItem && trayItem.hasMenu) {
|
if (trayItem && trayItem.hasMenu)
|
||||||
root.menuRequested(null, trayItem, mouse.x, mouse.y);
|
root.menuRequested(null, trayItem, mouse.x, mouse.y);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -110,6 +110,27 @@ PanelWindow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
|
id: topBarContent
|
||||||
|
|
||||||
|
readonly property int availableWidth: width
|
||||||
|
readonly property int leftSectionWidth: leftSection.width
|
||||||
|
readonly property int rightSectionWidth: rightSection.width
|
||||||
|
readonly property int clockWidth: clock.width
|
||||||
|
readonly property int mediaWidth: media.visible ? media.width : 0
|
||||||
|
readonly property int weatherWidth: weather.visible ? weather.width : 0
|
||||||
|
readonly property bool validLayout: availableWidth > 100 && leftSectionWidth > 0 && rightSectionWidth > 0
|
||||||
|
readonly property int clockLeftEdge: validLayout ? (availableWidth - clockWidth) / 2 : 0
|
||||||
|
readonly property int clockRightEdge: clockLeftEdge + clockWidth
|
||||||
|
readonly property int leftSectionRightEdge: leftSectionWidth
|
||||||
|
readonly property int mediaLeftEdge: clockLeftEdge - mediaWidth - Theme.spacingS
|
||||||
|
readonly property int rightSectionLeftEdge: availableWidth - rightSectionWidth
|
||||||
|
readonly property int leftToClockGap: validLayout ? Math.max(0, clockLeftEdge - leftSectionRightEdge) : 1000
|
||||||
|
readonly property int leftToMediaGap: (mediaWidth > 0 && validLayout) ? Math.max(0, mediaLeftEdge - leftSectionRightEdge) : leftToClockGap
|
||||||
|
readonly property int mediaToClockGap: mediaWidth > 0 ? Theme.spacingS : 0
|
||||||
|
readonly property int clockToRightGap: validLayout ? Math.max(0, rightSectionLeftEdge - clockRightEdge) : 1000
|
||||||
|
readonly property bool spacingTight: validLayout && (leftToMediaGap < 100 || clockToRightGap < 100)
|
||||||
|
readonly property bool overlapping: validLayout && (leftToMediaGap < 50 || clockToRightGap < 50)
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.leftMargin: Theme.spacingM
|
anchors.leftMargin: Theme.spacingM
|
||||||
anchors.rightMargin: Theme.spacingM
|
anchors.rightMargin: Theme.spacingM
|
||||||
@@ -129,8 +150,9 @@ PanelWindow {
|
|||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
isActive: appDrawerPopout ? appDrawerPopout.isVisible : false
|
isActive: appDrawerPopout ? appDrawerPopout.isVisible : false
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (appDrawerPopout)
|
if (appDrawerPopout)
|
||||||
appDrawerPopout.toggle();
|
appDrawerPopout.toggle();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,8 +162,12 @@ PanelWindow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
FocusedApp {
|
FocusedApp {
|
||||||
|
id: focusedApp
|
||||||
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
visible: Prefs.showFocusedWindow
|
visible: Prefs.showFocusedWindow
|
||||||
|
compactMode: topBarContent.spacingTight
|
||||||
|
availableWidth: topBarContent.leftToMediaGap
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -150,16 +176,20 @@ PanelWindow {
|
|||||||
id: clock
|
id: clock
|
||||||
|
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
|
compactMode: topBarContent.overlapping
|
||||||
onClockClicked: {
|
onClockClicked: {
|
||||||
centcomPopout.calendarVisible = !centcomPopout.calendarVisible;
|
centcomPopout.calendarVisible = !centcomPopout.calendarVisible;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Media {
|
Media {
|
||||||
|
id: media
|
||||||
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
anchors.right: clock.left
|
anchors.right: clock.left
|
||||||
anchors.rightMargin: Theme.spacingS
|
anchors.rightMargin: Theme.spacingS
|
||||||
visible: Prefs.showMusic && MprisController.activePlayer
|
visible: Prefs.showMusic && MprisController.activePlayer
|
||||||
|
compactMode: topBarContent.spacingTight || topBarContent.overlapping
|
||||||
onClicked: {
|
onClicked: {
|
||||||
centcomPopout.calendarVisible = !centcomPopout.calendarVisible;
|
centcomPopout.calendarVisible = !centcomPopout.calendarVisible;
|
||||||
}
|
}
|
||||||
@@ -237,21 +267,31 @@ PanelWindow {
|
|||||||
Loader {
|
Loader {
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
active: Prefs.showSystemResources
|
active: Prefs.showSystemResources
|
||||||
|
|
||||||
sourceComponent: Component {
|
sourceComponent: Component {
|
||||||
CpuMonitor {
|
CpuMonitor {
|
||||||
toggleProcessList: () => processListPopout.toggle()
|
toggleProcessList: () => {
|
||||||
|
return processListPopout.toggle();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Loader {
|
Loader {
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
active: Prefs.showSystemResources
|
active: Prefs.showSystemResources
|
||||||
|
|
||||||
sourceComponent: Component {
|
sourceComponent: Component {
|
||||||
RamMonitor {
|
RamMonitor {
|
||||||
toggleProcessList: () => processListPopout.toggle()
|
toggleProcessList: () => {
|
||||||
|
return processListPopout.toggle();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NotificationCenterButton {
|
NotificationCenterButton {
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ Rectangle {
|
|||||||
height: 30
|
height: 30
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: weatherArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.08)
|
color: weatherArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.08)
|
||||||
|
|
||||||
Ref {
|
Ref {
|
||||||
service: WeatherService
|
service: WeatherService
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user