diff --git a/Modules/ControlCenter/Details/NetworkDetail.qml b/Modules/ControlCenter/Details/NetworkDetail.qml index 32070202..cf6f9a34 100644 --- a/Modules/ControlCenter/Details/NetworkDetail.qml +++ b/Modules/ControlCenter/Details/NetworkDetail.qml @@ -65,74 +65,19 @@ Rectangle { height: parent.height } - Row { + DankButtonGroup { id: preferenceControls - spacing: Theme.spacingS anchors.verticalCenter: parent.verticalCenter visible: NetworkService.ethernetConnected && NetworkService.wifiConnected - - Rectangle { - property bool isActive: NetworkService.userPreference === "ethernet" - - width: 90 - height: 36 - radius: 18 - color: isActive ? Theme.surfaceContainerHigh : ethernetMouseArea.containsMouse ? Theme.surfaceHover : "transparent" - - StyledText { - anchors.centerIn: parent - text: "Ethernet" - color: parent.isActive ? Theme.primary : Theme.surfaceText - font.pixelSize: Theme.fontSizeMedium - font.weight: parent.isActive ? Font.Medium : Font.Normal - } - - MouseArea { - id: ethernetMouseArea - anchors.fill: parent - hoverEnabled: true - onClicked: NetworkService.setNetworkPreference("ethernet") - cursorShape: Qt.PointingHandCursor - } - - Behavior on color { - ColorAnimation { - duration: Theme.shortDuration - easing.type: Theme.standardEasing - } - } - } - - Rectangle { - property bool isActive: NetworkService.userPreference === "wifi" - - width: 70 - height: 36 - radius: 18 - color: isActive ? Theme.surfaceContainerHigh : wifiMouseArea.containsMouse ? Theme.surfaceHover : "transparent" - - StyledText { - anchors.centerIn: parent - text: "WiFi" - color: parent.isActive ? Theme.primary : Theme.surfaceText - font.pixelSize: Theme.fontSizeMedium - font.weight: parent.isActive ? Font.Medium : Font.Normal - } - - MouseArea { - id: wifiMouseArea - anchors.fill: parent - hoverEnabled: true - onClicked: NetworkService.setNetworkPreference("wifi") - cursorShape: Qt.PointingHandCursor - } - - Behavior on color { - ColorAnimation { - duration: Theme.shortDuration - easing.type: Theme.standardEasing - } - } + + property int currentPreferenceIndex: NetworkService.userPreference === "ethernet" ? 0 : 1 + + model: ["Ethernet", "WiFi"] + currentIndex: currentPreferenceIndex + selectionMode: "single" + onSelectionChanged: (index, selected) => { + if (!selected) return + NetworkService.setNetworkPreference(index === 0 ? "ethernet" : "wifi") } } } diff --git a/Modules/TopBar/BatteryPopout.qml b/Modules/TopBar/BatteryPopout.qml index a7ecafd6..09981c4f 100644 --- a/Modules/TopBar/BatteryPopout.qml +++ b/Modules/TopBar/BatteryPopout.qml @@ -56,7 +56,7 @@ DankPopout { Rectangle { id: batteryContent - implicitHeight: contentColumn.height + Theme.spacingL * 2 + implicitHeight: contentColumn.implicitHeight + Theme.spacingL * 2 color: Theme.popupBackground() radius: Theme.cornerRadius border.color: Theme.outlineMedium @@ -122,30 +122,158 @@ DankPopout { Column { id: contentColumn + width: parent.width - Theme.spacingL * 2 anchors.left: parent.left - anchors.right: parent.right anchors.top: parent.top anchors.margins: Theme.spacingL spacing: Theme.spacingL - Item { + Row { width: parent.width - height: 32 + height: 48 + spacing: Theme.spacingM - StyledText { - text: BatteryService.batteryAvailable ? "Battery Information" : "Power Management" - font.pixelSize: Theme.fontSizeLarge - color: Theme.surfaceText - font.weight: Font.Medium + DankIcon { + name: { + if (!BatteryService.batteryAvailable) + return "power"; + + if (!BatteryService.isCharging && BatteryService.isPluggedIn) { + if (BatteryService.batteryLevel >= 90) { + return "battery_charging_full"; + } + if (BatteryService.batteryLevel >= 80) { + return "battery_charging_90"; + } + if (BatteryService.batteryLevel >= 60) { + return "battery_charging_80"; + } + if (BatteryService.batteryLevel >= 50) { + return "battery_charging_60"; + } + if (BatteryService.batteryLevel >= 30) { + return "battery_charging_50"; + } + if (BatteryService.batteryLevel >= 20) { + return "battery_charging_30"; + } + return "battery_charging_20"; + } + if (BatteryService.isCharging) { + if (BatteryService.batteryLevel >= 90) { + return "battery_charging_full"; + } + if (BatteryService.batteryLevel >= 80) { + return "battery_charging_90"; + } + if (BatteryService.batteryLevel >= 60) { + return "battery_charging_80"; + } + if (BatteryService.batteryLevel >= 50) { + return "battery_charging_60"; + } + if (BatteryService.batteryLevel >= 30) { + return "battery_charging_50"; + } + if (BatteryService.batteryLevel >= 20) { + return "battery_charging_30"; + } + return "battery_charging_20"; + } else { + if (BatteryService.batteryLevel >= 95) { + return "battery_full"; + } + if (BatteryService.batteryLevel >= 85) { + return "battery_6_bar"; + } + if (BatteryService.batteryLevel >= 70) { + return "battery_5_bar"; + } + if (BatteryService.batteryLevel >= 55) { + return "battery_4_bar"; + } + if (BatteryService.batteryLevel >= 40) { + return "battery_3_bar"; + } + if (BatteryService.batteryLevel >= 25) { + return "battery_2_bar"; + } + return "battery_1_bar"; + } + } + size: Theme.iconSizeLarge + color: { + if (BatteryService.isLowBattery && !BatteryService.isCharging) + return Theme.error; + if (BatteryService.isCharging || BatteryService.isPluggedIn) + return Theme.primary; + return Theme.surfaceText; + } anchors.verticalCenter: parent.verticalCenter } + Column { + spacing: Theme.spacingXS + anchors.verticalCenter: parent.verticalCenter + width: parent.width - Theme.iconSizeLarge - 32 - Theme.spacingM * 2 + + Row { + spacing: Theme.spacingS + + StyledText { + text: BatteryService.batteryAvailable ? `${BatteryService.batteryLevel}%` : "Power" + font.pixelSize: Theme.fontSizeXLarge + color: { + if (BatteryService.isLowBattery && !BatteryService.isCharging) { + return Theme.error; + } + if (BatteryService.isCharging) { + return Theme.primary; + } + return Theme.surfaceText; + } + font.weight: Font.Bold + } + + StyledText { + text: BatteryService.batteryAvailable ? BatteryService.batteryStatus : "Management" + 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.Medium + anchors.verticalCenter: parent.verticalCenter + } + } + + StyledText { + text: { + if (!BatteryService.batteryAvailable) return "Power profile management available" + const time = BatteryService.formatTimeRemaining(); + if (time !== "Unknown") { + return BatteryService.isCharging ? `Time until full: ${time}` : `Time remaining: ${time}`; + } + return ""; + } + font.pixelSize: Theme.fontSizeSmall + color: Theme.surfaceTextMedium + visible: text.length > 0 + elide: Text.ElideRight + width: parent.width + } + } + Rectangle { width: 32 height: 32 radius: 16 color: closeBatteryArea.containsMouse ? Theme.errorHover : "transparent" - anchors.right: parent.right anchors.verticalCenter: parent.verticalCenter DankIcon { @@ -157,7 +285,6 @@ DankPopout { MouseArea { id: closeBatteryArea - anchors.fill: parent hoverEnabled: true cursorShape: Qt.PointingHandCursor @@ -165,427 +292,151 @@ DankPopout { root.close(); } } - } - } - Rectangle { - width: parent.width - height: 80 - radius: Theme.cornerRadius - color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, Theme.getContentBackgroundAlpha() * 0.4) - border.color: BatteryService.isCharging ? Theme.primary : (BatteryService.isLowBattery ? Theme.error : Theme.outlineMedium) - 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: { - if (!BatteryService.batteryAvailable) - return "power"; - - // Check if plugged in but not charging (like at 80% charge limit) - if (!BatteryService.isCharging && BatteryService.isPluggedIn) { - if (BatteryService.batteryLevel >= 90) { - return "battery_charging_full"; - } - - if (BatteryService.batteryLevel >= 80) { - return "battery_charging_90"; - } - - if (BatteryService.batteryLevel >= 60) { - return "battery_charging_80"; - } - - if (BatteryService.batteryLevel >= 50) { - return "battery_charging_60"; - } - - if (BatteryService.batteryLevel >= 30) { - return "battery_charging_50"; - } - - if (BatteryService.batteryLevel >= 20) { - return "battery_charging_30"; - } - - return "battery_charging_20"; - } - if (BatteryService.isCharging) { - if (BatteryService.batteryLevel >= 90) { - return "battery_charging_full"; - } - - if (BatteryService.batteryLevel >= 80) { - return "battery_charging_90"; - } - - if (BatteryService.batteryLevel >= 60) { - return "battery_charging_80"; - } - - if (BatteryService.batteryLevel >= 50) { - return "battery_charging_60"; - } - - if (BatteryService.batteryLevel >= 30) { - return "battery_charging_50"; - } - - if (BatteryService.batteryLevel >= 20) { - return "battery_charging_30"; - } - - return "battery_charging_20"; - } else { - if (BatteryService.batteryLevel >= 95) { - return "battery_full"; - } - - if (BatteryService.batteryLevel >= 85) { - return "battery_6_bar"; - } - - if (BatteryService.batteryLevel >= 70) { - return "battery_5_bar"; - } - - if (BatteryService.batteryLevel >= 55) { - return "battery_4_bar"; - } - - if (BatteryService.batteryLevel >= 40) { - return "battery_3_bar"; - } - - if (BatteryService.batteryLevel >= 25) { - return "battery_2_bar"; - } - - return "battery_1_bar"; - } - } - size: Theme.iconSizeLarge - color: { - if (BatteryService.isLowBattery && !BatteryService.isCharging) - return Theme.error; - - if (BatteryService.isCharging || BatteryService.isPluggedIn) - return Theme.primary; - - return Theme.surfaceText; - } - anchors.verticalCenter: parent.verticalCenter - } - - Column { - spacing: 2 - anchors.verticalCenter: parent.verticalCenter - - Row { - spacing: Theme.spacingM - - StyledText { - 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 - } - - StyledText { - 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 - } - - } - - StyledText { - text: { - const time = BatteryService.formatTimeRemaining(); - if (time !== "Unknown") { - return BatteryService.isCharging ? `Time until full: ${time}` : `Time remaining: ${time}`; - } - - return ""; - } - font.pixelSize: Theme.fontSizeSmall - color: Theme.surfaceTextMedium - visible: text.length > 0 - } - - } - - } - - } - - Rectangle { - width: parent.width - height: 80 - radius: Theme.cornerRadius - color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, Theme.getContentBackgroundAlpha() * 0.4) - border.color: Theme.outlineMedium - border.width: 1 - visible: !BatteryService.batteryAvailable - - Row { - anchors.centerIn: parent - spacing: Theme.spacingL - - DankIcon { - name: "power" - size: 36 - color: Theme.surfaceText - anchors.verticalCenter: parent.verticalCenter - } - - Column { - spacing: Theme.spacingS - anchors.verticalCenter: parent.verticalCenter - - StyledText { - text: "No Battery Detected" - font.pixelSize: Theme.fontSizeLarge - color: Theme.surfaceText - font.weight: Font.Medium - } - - StyledText { - text: "Power profile management is available" - font.pixelSize: Theme.fontSizeMedium - color: Theme.surfaceTextMedium - } - - } - - } - - } - - Column { + Row { width: parent.width spacing: Theme.spacingM visible: BatteryService.batteryAvailable - StyledText { - text: "Battery Details" - font.pixelSize: Theme.fontSizeLarge - color: Theme.surfaceText - font.weight: Font.Medium - } - - Row { - width: parent.width - spacing: Theme.spacingXL + StyledRect { + width: (parent.width - Theme.spacingM) / 2 + height: 64 + radius: Theme.cornerRadius + color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) + border.color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.2) + border.width: 1 Column { - spacing: 2 - width: (parent.width - Theme.spacingXL) / 2 + anchors.centerIn: parent + spacing: Theme.spacingXS StyledText { text: "Health" font.pixelSize: Theme.fontSizeSmall - color: Theme.surfaceTextMedium + color: Theme.primary font.weight: Font.Medium + anchors.horizontalCenter: parent.horizontalCenter } StyledText { text: BatteryService.batteryHealth - font.pixelSize: Theme.fontSizeMedium + font.pixelSize: Theme.fontSizeLarge color: { if (BatteryService.batteryHealth === "N/A") { return Theme.surfaceText; } - const healthNum = parseInt(BatteryService.batteryHealth); return healthNum < 80 ? Theme.error : Theme.surfaceText; } + font.weight: Font.Bold + anchors.horizontalCenter: parent.horizontalCenter } - } + } + + StyledRect { + width: (parent.width - Theme.spacingM) / 2 + height: 64 + radius: Theme.cornerRadius + color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) + border.color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.2) + border.width: 1 Column { - spacing: 2 - width: (parent.width - Theme.spacingXL) / 2 + anchors.centerIn: parent + spacing: Theme.spacingXS StyledText { text: "Capacity" font.pixelSize: Theme.fontSizeSmall - color: Theme.surfaceTextMedium + color: Theme.primary font.weight: Font.Medium + anchors.horizontalCenter: parent.horizontalCenter } StyledText { text: BatteryService.batteryCapacity > 0 ? `${BatteryService.batteryCapacity.toFixed(1)} Wh` : "Unknown" - font.pixelSize: Theme.fontSizeMedium + font.pixelSize: Theme.fontSizeLarge color: Theme.surfaceText + font.weight: Font.Bold + anchors.horizontalCenter: parent.horizontalCenter } - } - } - } - Column { - width: parent.width - spacing: Theme.spacingM - visible: true - - StyledText { - text: "Power Profile" - font.pixelSize: Theme.fontSizeLarge - color: Theme.surfaceText - font.weight: Font.Medium + DankButtonGroup { + property var profileModel: (typeof PowerProfiles !== "undefined") ? [PowerProfile.PowerSaver, PowerProfile.Balanced].concat(PowerProfiles.hasPerformanceProfile ? [PowerProfile.Performance] : []) : [PowerProfile.PowerSaver, PowerProfile.Balanced, PowerProfile.Performance] + property int currentProfileIndex: { + if (typeof PowerProfiles === "undefined") return 1 + return profileModel.findIndex(profile => root.isActiveProfile(profile)) } - 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 ? Theme.primaryHoverLight : (root.isActiveProfile(modelData) ? Theme.primaryPressed : Theme.surfaceLight) - border.color: root.isActiveProfile(modelData) ? Theme.primary : Theme.outlineLight - border.width: root.isActiveProfile(modelData) ? 2 : 1 - - 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: root.isActiveProfile(modelData) ? Theme.primary : Theme.surfaceText - anchors.verticalCenter: parent.verticalCenter - } - - Column { - spacing: 2 - anchors.verticalCenter: parent.verticalCenter - - StyledText { - text: Theme.getPowerProfileLabel(modelData) - font.pixelSize: Theme.fontSizeMedium - color: root.isActiveProfile(modelData) ? Theme.primary : Theme.surfaceText - font.weight: root.isActiveProfile(modelData) ? Font.Medium : Font.Normal - } - - StyledText { - text: Theme.getPowerProfileDescription(modelData) - font.pixelSize: Theme.fontSizeSmall - color: Theme.surfaceTextMedium - } - - } - - } - - MouseArea { - id: profileArea - - anchors.fill: parent - hoverEnabled: true - cursorShape: Qt.PointingHandCursor - onPressed: { - root.setProfile(modelData); - } - } - - } - - } - + model: profileModel.map(profile => Theme.getPowerProfileLabel(profile)) + currentIndex: currentProfileIndex + selectionMode: "single" + anchors.horizontalCenter: parent.horizontalCenter + onSelectionChanged: (index, selected) => { + if (!selected) return + root.setProfile(profileModel[index]) } - } - Rectangle { + StyledRect { width: parent.width - height: 60 + height: degradationContent.implicitHeight + Theme.spacingL * 2 radius: Theme.cornerRadius - color: Theme.errorHover - border.color: Theme.primarySelected + color: Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12) + border.color: Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.3) border.width: 1 visible: (typeof PowerProfiles !== "undefined") && PowerProfiles.degradationReason !== PerformanceDegradationReason.None - Row { + Column { + id: degradationContent + width: parent.width - Theme.spacingL * 2 anchors.left: parent.left - anchors.leftMargin: Theme.spacingL - anchors.verticalCenter: parent.verticalCenter - spacing: Theme.spacingM + anchors.top: parent.top + anchors.margins: Theme.spacingL + spacing: Theme.spacingS - DankIcon { - name: "warning" - size: Theme.iconSize - color: Theme.error - anchors.verticalCenter: parent.verticalCenter - } + Row { + width: parent.width + spacing: Theme.spacingM - Column { - spacing: 2 - anchors.verticalCenter: parent.verticalCenter - - StyledText { - text: "Power Profile Degradation" - font.pixelSize: Theme.fontSizeMedium + DankIcon { + name: "warning" + size: Theme.iconSize color: Theme.error - font.weight: Font.Medium + anchors.verticalCenter: parent.verticalCenter } - StyledText { - 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) - } + Column { + spacing: Theme.spacingXS + anchors.verticalCenter: parent.verticalCenter + width: parent.width - Theme.iconSize - Theme.spacingM + StyledText { + text: "Power Profile Degradation" + font.pixelSize: Theme.fontSizeLarge + color: Theme.error + font.weight: Font.Medium + } + + StyledText { + 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) + wrapMode: Text.WordWrap + width: parent.width + } + } } - } - } - } - } - } -} +} \ No newline at end of file