ControlCenter: revert to old layout

This commit is contained in:
lysec
2025-10-11 04:16:12 +02:00
parent 32c929c943
commit e86f4e56cb
9 changed files with 449 additions and 55 deletions
+4
View File
@@ -159,6 +159,10 @@ Singleton {
"id": "Tray"
}, {
"id": "NotificationHistory"
}, {
"id": "WiFi"
}, {
"id": "Bluetooth"
}, {
"id": "Battery"
}, {
@@ -0,0 +1,66 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell
import Quickshell.Services.UPower
import qs.Commons
import qs.Services
import qs.Widgets
// Power Profiles: performance, balanced, eco
NBox {
property real spacing: 0
// Centralized service
readonly property bool hasPP: PowerProfileService.available
RowLayout {
id: powerRow
anchors.fill: parent
anchors.margins: Style.marginS * scaling
spacing: spacing
Item {
Layout.fillWidth: true
}
// Performance
NIconButton {
icon: PowerProfileService.getIcon(PowerProfile.Performance)
tooltipText: I18n.tr("tooltips.set-power-profile", {
"profile": PowerProfileService.getName(PowerProfile.Performance)
})
enabled: hasPP
opacity: enabled ? Style.opacityFull : Style.opacityMedium
colorBg: (enabled && PowerProfileService.profile === PowerProfile.Performance) ? Color.mPrimary : Color.mSurfaceVariant
colorFg: (enabled && PowerProfileService.profile === PowerProfile.Performance) ? Color.mOnPrimary : Color.mPrimary
onClicked: PowerProfileService.setProfile(PowerProfile.Performance)
}
// Balanced
NIconButton {
icon: PowerProfileService.getIcon(PowerProfile.Balanced)
tooltipText: I18n.tr("tooltips.set-power-profile", {
"profile": PowerProfileService.getName(PowerProfile.Balanced)
})
enabled: hasPP
opacity: enabled ? Style.opacityFull : Style.opacityMedium
colorBg: (enabled && PowerProfileService.profile === PowerProfile.Balanced) ? Color.mPrimary : Color.mSurfaceVariant
colorFg: (enabled && PowerProfileService.profile === PowerProfile.Balanced) ? Color.mOnPrimary : Color.mPrimary
onClicked: PowerProfileService.setProfile(PowerProfile.Balanced)
}
// Eco
NIconButton {
icon: PowerProfileService.getIcon(PowerProfile.PowerSaver)
tooltipText: I18n.tr("tooltips.set-power-profile", {
"profile": PowerProfileService.getName(PowerProfile.PowerSaver)
})
enabled: hasPP
opacity: enabled ? Style.opacityFull : Style.opacityMedium
colorBg: (enabled && PowerProfileService.profile === PowerProfile.PowerSaver) ? Color.mPrimary : Color.mSurfaceVariant
colorFg: (enabled && PowerProfileService.profile === PowerProfile.PowerSaver) ? Color.mOnPrimary : Color.mPrimary
onClicked: PowerProfileService.setProfile(PowerProfile.PowerSaver)
}
Item {
Layout.fillWidth: true
}
}
}
+113
View File
@@ -0,0 +1,113 @@
import QtQuick
import QtQuick.Effects
import QtQuick.Layouts
import Quickshell
import Quickshell.Io
import Quickshell.Widgets
import qs.Modules.Settings
import qs.Modules.ControlCenter
import qs.Commons
import qs.Services
import qs.Widgets
// Header card with avatar, user and quick actions
NBox {
id: root
property string uptimeText: "--"
RowLayout {
id: content
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
anchors.margins: Style.marginM * scaling
spacing: Style.marginM * scaling
NImageCircled {
width: Style.baseWidgetSize * 1.25 * scaling
height: Style.baseWidgetSize * 1.25 * scaling
imagePath: Settings.data.general.avatarImage
fallbackIcon: "person"
borderColor: Color.mPrimary
borderWidth: Math.max(1, Style.borderM * scaling)
}
ColumnLayout {
Layout.fillWidth: true
spacing: Style.marginXXS * scaling
NText {
text: Quickshell.env("USER") || "user"
font.weight: Style.fontWeightBold
font.capitalization: Font.Capitalize
}
NText {
text: I18n.tr("system.uptime", {
"uptime": uptimeText
})
pointSize: Style.fontSizeS * scaling
color: Color.mOnSurfaceVariant
}
}
RowLayout {
spacing: Style.marginS * scaling
Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
Item {
Layout.fillWidth: true
}
NIconButton {
icon: "settings"
tooltipText: I18n.tr("tooltips.open-settings")
onClicked: {
settingsPanel.requestedTab = SettingsPanel.Tab.General
settingsPanel.open()
}
}
NIconButton {
icon: "power"
tooltipText: I18n.tr("tooltips.session-menu")
onClicked: {
sessionMenuPanel.open()
controlCenterPanel.close()
}
}
NIconButton {
icon: "close"
tooltipText: I18n.tr("tooltips.close")
onClicked: {
controlCenterPanel.close()
}
}
}
}
// ----------------------------------
// Uptime
Timer {
interval: 60000
repeat: true
running: true
onTriggered: uptimeProcess.running = true
}
Process {
id: uptimeProcess
command: ["cat", "/proc/uptime"]
running: true
stdout: StdioCollector {
onStreamFinished: {
var uptimeSeconds = parseFloat(this.text.trim().split(' ')[0])
uptimeText = Time.formatVagueHumanReadableDuration(uptimeSeconds)
uptimeProcess.running = false
}
}
}
function updateSystemInfo() {
uptimeProcess.running = true
}
}
@@ -9,10 +9,15 @@ import qs.Widgets
NBox {
id: root
RowLayout {
ColumnLayout {
id: content
anchors.fill: parent
anchors.margins: Style.marginXS * scaling
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
anchors.leftMargin: Style.marginS * scaling
anchors.rightMargin: Style.marginS * scaling
anchors.topMargin: Style.marginXS * scaling
anchors.bottomMargin: Style.marginM * scaling
spacing: Style.marginS * scaling
NCircleStat {
@@ -20,8 +25,8 @@ NBox {
icon: "cpu-usage"
flat: true
contentScale: 0.8
Layout.fillWidth: true
Layout.fillHeight: true
width: 72 * scaling
height: 68 * scaling
}
NCircleStat {
value: SystemStatService.cpuTemp
@@ -29,24 +34,24 @@ NBox {
icon: "cpu-temperature"
flat: true
contentScale: 0.8
Layout.fillWidth: true
Layout.fillHeight: true
width: 72 * scaling
height: 68 * scaling
}
NCircleStat {
value: SystemStatService.memPercent
icon: "memory"
flat: true
contentScale: 0.8
Layout.fillWidth: true
Layout.fillHeight: true
width: 72 * scaling
height: 68 * scaling
}
NCircleStat {
value: SystemStatService.diskPercent
icon: "storage"
flat: true
contentScale: 0.8
Layout.fillWidth: true
Layout.fillHeight: true
width: 72 * scaling
height: 68 * scaling
}
}
}
@@ -0,0 +1,66 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell
import qs.Commons
import qs.Modules.Settings
import qs.Services
import qs.Widgets
// Utilities: record & wallpaper
NBox {
property real spacing: 0
RowLayout {
id: utilRow
anchors.fill: parent
anchors.margins: Style.marginS * scaling
spacing: spacing
Item {
Layout.fillWidth: true
}
// Screen Recorder
NIconButton {
icon: "camera-video"
enabled: ScreenRecorderService.isAvailable
tooltipText: ScreenRecorderService.isAvailable ? (ScreenRecorderService.isRecording ? I18n.tr("tooltips.stop-screen-recording") : I18n.tr("tooltips.start-screen-recording")) : I18n.tr("tooltips.screen-recorder-not-installed")
colorBg: ScreenRecorderService.isRecording ? Color.mPrimary : Color.mSurfaceVariant
colorFg: ScreenRecorderService.isRecording ? Color.mOnPrimary : Color.mPrimary
onClicked: {
if (!ScreenRecorderService.isAvailable)
return
ScreenRecorderService.toggleRecording()
// If we were not recording and we just initiated a start, close the panel
if (!ScreenRecorderService.isRecording) {
var panel = PanelService.getPanel("controlCenterPanel")
panel?.close()
}
}
}
// Idle Inhibitor
NIconButton {
icon: IdleInhibitorService.isInhibited ? "keep-awake-on" : "keep-awake-off"
tooltipText: IdleInhibitorService.isInhibited ? I18n.tr("tooltips.disable-keep-awake") : I18n.tr("tooltips.enable-keep-awake")
colorBg: IdleInhibitorService.isInhibited ? Color.mPrimary : Color.mSurfaceVariant
colorFg: IdleInhibitorService.isInhibited ? Color.mOnPrimary : Color.mPrimary
onClicked: {
IdleInhibitorService.manualToggle()
}
}
// Wallpaper
NIconButton {
visible: Settings.data.wallpaper.enabled
icon: "wallpaper-selector"
tooltipText: I18n.tr("tooltips.wallpaper-selector")
onClicked: PanelService.getPanel("wallpaperPanel")?.toggle(this)
onRightClicked: WallpaperService.setRandomWallpaper()
}
Item {
Layout.fillWidth: true
}
}
}
+130
View File
@@ -0,0 +1,130 @@
import QtQuick
import QtQuick.Layouts
import Quickshell
import qs.Commons
import qs.Services
import qs.Widgets
// Weather overview card (placeholder data)
NBox {
id: root
readonly property bool weatherReady: (LocationService.data.weather !== null)
ColumnLayout {
id: content
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
anchors.margins: Style.marginM * scaling
spacing: Style.marginM * scaling
clip: true
RowLayout {
spacing: Style.marginS * scaling
NIcon {
Layout.alignment: Qt.AlignVCenter
icon: weatherReady ? LocationService.weatherSymbolFromCode(LocationService.data.weather.current_weather.weathercode) : ""
pointSize: Style.fontSizeXXXL * 1.75 * scaling
color: Color.mPrimary
}
ColumnLayout {
spacing: Style.marginXXS * scaling
NText {
text: {
// Ensure the name is not too long if one had to specify the country
const chunks = Settings.data.location.name.split(",")
return chunks[0]
}
pointSize: Style.fontSizeL * scaling
font.weight: Style.fontWeightBold
}
RowLayout {
NText {
visible: weatherReady
text: {
if (!weatherReady) {
return ""
}
var temp = LocationService.data.weather.current_weather.temperature
var suffix = "C"
if (Settings.data.location.useFahrenheit) {
temp = LocationService.celsiusToFahrenheit(temp)
var suffix = "F"
}
temp = Math.round(temp)
return `${temp}°${suffix}`
}
pointSize: Style.fontSizeXL * scaling
font.weight: Style.fontWeightBold
}
NText {
text: weatherReady ? `(${LocationService.data.weather.timezone_abbreviation})` : ""
pointSize: Style.fontSizeXS * scaling
color: Color.mOnSurfaceVariant
visible: LocationService.data.weather
}
}
}
}
NDivider {
visible: weatherReady
Layout.fillWidth: true
}
RowLayout {
visible: weatherReady
Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
spacing: Style.marginL * scaling
Repeater {
model: weatherReady ? LocationService.data.weather.daily.time : []
delegate: ColumnLayout {
Layout.alignment: Qt.AlignHCenter
spacing: Style.marginL * scaling
NText {
text: {
var weatherDate = new Date(LocationService.data.weather.daily.time[index].replace(/-/g, "/"))
return Qt.locale().toString(weatherDate, "ddd")
}
color: Color.mOnSurface
Layout.alignment: Qt.AlignHCenter
}
NIcon {
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
icon: LocationService.weatherSymbolFromCode(LocationService.data.weather.daily.weathercode[index])
pointSize: Style.fontSizeXXL * 1.6 * scaling
color: Color.mPrimary
}
NText {
Layout.alignment: Qt.AlignHCenter
text: {
var max = LocationService.data.weather.daily.temperature_2m_max[index]
var min = LocationService.data.weather.daily.temperature_2m_min[index]
if (Settings.data.location.useFahrenheit) {
max = LocationService.celsiusToFahrenheit(max)
min = LocationService.celsiusToFahrenheit(min)
}
max = Math.round(max)
min = Math.round(min)
return `${max}°/${min}°`
}
pointSize: Style.fontSizeXS * scaling
color: Color.mOnSurfaceVariant
}
}
}
}
RowLayout {
visible: !weatherReady
Layout.fillWidth: true
Layout.alignment: Qt.AlignHCenter
NBusyIndicator {}
}
}
}
+44 -36
View File
@@ -10,29 +10,10 @@ import qs.Widgets
NPanel {
id: root
preferredWidth: 400
preferredHeight: topHeight + midHeight + bottomHeight + audioHeight + Math.round(Style.marginL * 5)
preferredWidth: 460
preferredHeight: 734
panelKeyboardFocus: true
readonly property int topHeight: {
const columns = (Settings.data.controlCenter.quickSettingsStyle === "compact") ? 4 : 3
const rowsCount = Math.ceil(Settings.data.controlCenter.widgets.quickSettings.length / columns)
var buttonHeight
if (Settings.data.controlCenter.quickSettingsStyle === "classic") {
buttonHeight = Style.baseWidgetSize
} else if (Settings.data.controlCenter.quickSettingsStyle === "compact") {
buttonHeight = Style.baseWidgetSize * 0.8 // Smaller for compact
} else {
buttonHeight = 56
}
return (rowsCount * buttonHeight) + 120
}
readonly property int midHeight: 220
readonly property int bottomHeight: 80
readonly property int audioHeight: 120
// Positioning
readonly property string controlCenterPosition: Settings.data.controlCenter.position
panelAnchorHorizontalCenter: controlCenterPosition !== "close_to_bar_button" && controlCenterPosition.endsWith("_center")
@@ -50,33 +31,60 @@ NPanel {
// Layout content
ColumnLayout {
id: layout
anchors.fill: parent
anchors.margins: content.cardSpacing
x: content.cardSpacing
y: content.cardSpacing
width: parent.width - (2 * content.cardSpacing)
spacing: content.cardSpacing
// Top Card: profile + utilities
TopCard {
id: topCard
// Cards (consistent inter-card spacing via ColumnLayout spacing)
ProfileCard {
Layout.fillWidth: true
Layout.preferredHeight: topHeight * scaling
Layout.preferredHeight: Math.max(64 * scaling)
}
// Audio controls card
AudioCard {
WeatherCard {
Layout.fillWidth: true
Layout.preferredHeight: audioHeight * scaling
Layout.preferredHeight: Math.max(220 * scaling)
}
// Media card
MediaCard {
// Middle section: media + stats column
RowLayout {
Layout.fillWidth: true
Layout.preferredHeight: midHeight * scaling
Layout.preferredHeight: Math.max(310 * scaling)
spacing: content.cardSpacing
// Media card
MediaCard {
Layout.fillWidth: true
Layout.fillHeight: true
}
// System monitors combined in one card
SystemMonitorCard {
Layout.preferredWidth: Style.baseWidgetSize * 2.625 * scaling
Layout.fillHeight: true
}
}
// System monitors combined in one card
SystemMonitorCard {
// Bottom actions (two grouped rows of round buttons)
RowLayout {
Layout.fillWidth: true
Layout.preferredHeight: bottomHeight * scaling
Layout.preferredHeight: Math.max(60 * scaling)
spacing: content.cardSpacing
// Power Profiles switcher
PowerProfilesCard {
Layout.fillWidth: true
Layout.fillHeight: true
spacing: content.cardSpacing
}
// Utilities buttons
UtilitiesCard {
Layout.fillWidth: true
Layout.fillHeight: true
spacing: content.cardSpacing
}
}
}
}
+8 -6
View File
@@ -129,12 +129,14 @@ NPanel {
"label": "settings.bar.title",
"icon": "settings-bar",
"source": barTab
}, {
"id": SettingsPanel.Tab.ControlCenter,
"label": "settings.control-center.title",
"icon": "settings-bar",
"source": controlCenterTab
}, {
},
//{
// "id": SettingsPanel.Tab.ControlCenter,
// "label": "settings.control-center.title",
// "icon": "settings-bar",
// "source": controlCenterTab
//},
{
"id": SettingsPanel.Tab.Dock,
"label": "settings.dock.title",
"icon": "settings-dock",
+2 -2
View File
@@ -8,8 +8,8 @@ Singleton {
id: root
// Public properties
property string baseVersion: "2.17.1"
property bool isDevelopment: true
property string baseVersion: "2.17.2"
property bool isDevelopment: false
property string currentVersion: `v${!isDevelopment ? baseVersion : baseVersion + "-dev"}`