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": "Tray"
}, { }, {
"id": "NotificationHistory" "id": "NotificationHistory"
}, {
"id": "WiFi"
}, {
"id": "Bluetooth"
}, { }, {
"id": "Battery" "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 { NBox {
id: root id: root
RowLayout { ColumnLayout {
id: content id: content
anchors.fill: parent anchors.left: parent.left
anchors.margins: Style.marginXS * scaling 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 spacing: Style.marginS * scaling
NCircleStat { NCircleStat {
@@ -20,8 +25,8 @@ NBox {
icon: "cpu-usage" icon: "cpu-usage"
flat: true flat: true
contentScale: 0.8 contentScale: 0.8
Layout.fillWidth: true width: 72 * scaling
Layout.fillHeight: true height: 68 * scaling
} }
NCircleStat { NCircleStat {
value: SystemStatService.cpuTemp value: SystemStatService.cpuTemp
@@ -29,24 +34,24 @@ NBox {
icon: "cpu-temperature" icon: "cpu-temperature"
flat: true flat: true
contentScale: 0.8 contentScale: 0.8
Layout.fillWidth: true width: 72 * scaling
Layout.fillHeight: true height: 68 * scaling
} }
NCircleStat { NCircleStat {
value: SystemStatService.memPercent value: SystemStatService.memPercent
icon: "memory" icon: "memory"
flat: true flat: true
contentScale: 0.8 contentScale: 0.8
Layout.fillWidth: true width: 72 * scaling
Layout.fillHeight: true height: 68 * scaling
} }
NCircleStat { NCircleStat {
value: SystemStatService.diskPercent value: SystemStatService.diskPercent
icon: "storage" icon: "storage"
flat: true flat: true
contentScale: 0.8 contentScale: 0.8
Layout.fillWidth: true width: 72 * scaling
Layout.fillHeight: true 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 { NPanel {
id: root id: root
preferredWidth: 400 preferredWidth: 460
preferredHeight: topHeight + midHeight + bottomHeight + audioHeight + Math.round(Style.marginL * 5) preferredHeight: 734
panelKeyboardFocus: true 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 // Positioning
readonly property string controlCenterPosition: Settings.data.controlCenter.position readonly property string controlCenterPosition: Settings.data.controlCenter.position
panelAnchorHorizontalCenter: controlCenterPosition !== "close_to_bar_button" && controlCenterPosition.endsWith("_center") panelAnchorHorizontalCenter: controlCenterPosition !== "close_to_bar_button" && controlCenterPosition.endsWith("_center")
@@ -50,33 +31,60 @@ NPanel {
// Layout content // Layout content
ColumnLayout { ColumnLayout {
id: layout id: layout
anchors.fill: parent x: content.cardSpacing
anchors.margins: content.cardSpacing y: content.cardSpacing
width: parent.width - (2 * content.cardSpacing)
spacing: content.cardSpacing spacing: content.cardSpacing
// Top Card: profile + utilities // Cards (consistent inter-card spacing via ColumnLayout spacing)
TopCard { ProfileCard {
id: topCard
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: topHeight * scaling Layout.preferredHeight: Math.max(64 * scaling)
} }
// Audio controls card WeatherCard {
AudioCard {
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: audioHeight * scaling Layout.preferredHeight: Math.max(220 * scaling)
} }
// Media card // Middle section: media + stats column
MediaCard { RowLayout {
Layout.fillWidth: true 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 // Bottom actions (two grouped rows of round buttons)
SystemMonitorCard { RowLayout {
Layout.fillWidth: true 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", "label": "settings.bar.title",
"icon": "settings-bar", "icon": "settings-bar",
"source": barTab "source": barTab
}, { },
"id": SettingsPanel.Tab.ControlCenter, //{
"label": "settings.control-center.title", // "id": SettingsPanel.Tab.ControlCenter,
"icon": "settings-bar", // "label": "settings.control-center.title",
"source": controlCenterTab // "icon": "settings-bar",
}, { // "source": controlCenterTab
//},
{
"id": SettingsPanel.Tab.Dock, "id": SettingsPanel.Tab.Dock,
"label": "settings.dock.title", "label": "settings.dock.title",
"icon": "settings-dock", "icon": "settings-dock",
+2 -2
View File
@@ -8,8 +8,8 @@ Singleton {
id: root id: root
// Public properties // Public properties
property string baseVersion: "2.17.1" property string baseVersion: "2.17.2"
property bool isDevelopment: true property bool isDevelopment: false
property string currentVersion: `v${!isDevelopment ? baseVersion : baseVersion + "-dev"}` property string currentVersion: `v${!isDevelopment ? baseVersion : baseVersion + "-dev"}`