Add idle timeouts to the Quick Settings General tab
This commit is contained in:
1 parent
1f86bfd151
commit
4f2d319a35
4 files changed
+182
-16
No files matched your search
+9
-2
@@ -9,7 +9,7 @@ autostarted.
|
||||
|
||||
| Was | Is | Note |
|
||||
| --- | --- | --- |
|
||||
| `QuickSettings.tsx` (523 lines) | `shell/plugins/panels/quick-settings/` | split across 13 files, none over 350 lines, with four tabs |
|
||||
| `QuickSettings.tsx` (523 lines) | `shell/plugins/panels/quick-settings/` | split across 15 files, none over 350 lines, with four tabs |
|
||||
| `SysMonitor.tsx` (142) | `shell/plugins/panels/sysmon/` | CPU, memory, disk, temperature; the probes and bars are `Ui/SystemStats.qml` and `Ui/MetricBar.qml`, shared with the Performance tab |
|
||||
| `Notifications.tsx` (160) | `shell/plugins/notification-center/` | reads the notification service's own history files |
|
||||
| `WallPicker.tsx` (106) | the existing image picker | `blob-wallpaper-set --menu` now calls `blob-menu-images`, so wallpapers get the image grid instead of a text list |
|
||||
@@ -41,13 +41,20 @@ running `pamixer` and `playerctl` every second.
|
||||
|
||||
| Tab | Holds |
|
||||
| --- | --- |
|
||||
| General | the calendar and the brightness slider |
|
||||
| General | the calendar, the brightness slider, and the screensaver and lock timeouts |
|
||||
| Sound & Music | output and microphone volume (click the icon to mute), the media row with its controls, and buttons for the audio panel (picking devices) and the pavucontrol mixer |
|
||||
| Performance | CPU, memory, disk and temperature bars, the load average, the power profile (Power saver, Balanced, Performance, whichever the machine offers), and a button that opens btop |
|
||||
| Quick Settings | the toggle tiles: Wi-Fi, Bluetooth, Wallpaper, Silence, Night Light, Record, Stay Awake, Pick Color, Theme, Tablet Lock |
|
||||
|
||||
The weather card beside it is not part of the tabs and stays visible.
|
||||
|
||||
The two timeouts on the General tab are the `idle.screensaver` and `idle.lock`
|
||||
values in `~/.config/blob/shell.json`, in seconds. The minus and plus buttons
|
||||
step through 1, 2, 5, 10, 15, 30 and 60 minutes (and 2 hours for the lock),
|
||||
starting from whatever the file holds, and the idle service picks the new value
|
||||
up straight away. A value set by hand that is not a preset is shown as it is.
|
||||
While Stay Awake is on, the tab says so, since neither timeout runs then.
|
||||
|
||||
## Opening them
|
||||
|
||||
| Panel | Opened by |
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
import QtQuick
|
||||
import qs.Commons
|
||||
|
||||
Column {
|
||||
id: root
|
||||
|
||||
property bool polling: false
|
||||
property int brightness: 0
|
||||
property int screensaverSeconds: 0
|
||||
property int lockSeconds: 0
|
||||
property bool stayAwake: false
|
||||
|
||||
signal brightnessRequested(int value)
|
||||
signal timeoutRequested(string key, int seconds)
|
||||
|
||||
spacing: Style.spaceReal(12)
|
||||
|
||||
Calendar {
|
||||
width: parent.width
|
||||
polling: root.polling
|
||||
}
|
||||
|
||||
SliderRow {
|
||||
width: parent.width
|
||||
icon: ""
|
||||
value: root.brightness
|
||||
onValueRequested: function(next) { root.brightnessRequested(next) }
|
||||
}
|
||||
|
||||
TimeoutRow {
|
||||
width: parent.width
|
||||
icon: ""
|
||||
label: "Screensaver after"
|
||||
seconds: root.screensaverSeconds
|
||||
presetMinutes: [1, 2, 5, 10, 15, 30, 60]
|
||||
onSecondsRequested: function(seconds) { root.timeoutRequested("screensaver", seconds) }
|
||||
}
|
||||
|
||||
TimeoutRow {
|
||||
width: parent.width
|
||||
icon: ""
|
||||
label: "Lock after"
|
||||
seconds: root.lockSeconds
|
||||
presetMinutes: [1, 2, 5, 10, 15, 30, 60, 120]
|
||||
onSecondsRequested: function(seconds) { root.timeoutRequested("lock", seconds) }
|
||||
}
|
||||
|
||||
Text {
|
||||
width: parent.width
|
||||
visible: root.stayAwake
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
wrapMode: Text.WordWrap
|
||||
text: "Stay Awake is on, so neither starts until it is turned off."
|
||||
textFormat: Text.PlainText
|
||||
color: Util.alpha(Color.foreground, 0.6)
|
||||
font.family: Style.font.family
|
||||
font.pixelSize: Style.font.bodySmall
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,11 @@ Item {
|
||||
readonly property bool performanceVisible: opened && currentTab === "performance"
|
||||
readonly property bool quickVisible: opened && currentTab === "quick"
|
||||
|
||||
readonly property var idleConfig: root.shell && root.shell.shellConfig && root.shell.shellConfig.idle
|
||||
? root.shell.shellConfig.idle : ({})
|
||||
readonly property int screensaverSeconds: root.timeoutSeconds(idleConfig.screensaver, 150)
|
||||
readonly property int lockSeconds: root.timeoutSeconds(idleConfig.lock, 300)
|
||||
|
||||
readonly property int barInset: {
|
||||
var bar = root.shell ? root.shell.bar : null
|
||||
if (!bar || bar.barHidden === true) return 0
|
||||
@@ -78,6 +83,19 @@ Item {
|
||||
mediaValue.refresh()
|
||||
}
|
||||
|
||||
function timeoutSeconds(value, fallback) {
|
||||
var seconds = Number(value)
|
||||
return isFinite(seconds) && seconds >= 0 ? Math.floor(seconds) : fallback
|
||||
}
|
||||
|
||||
function setIdleTimeout(key, seconds) {
|
||||
if (!root.shell || typeof root.shell.mutateShellConfig !== "function") return
|
||||
root.shell.mutateShellConfig(function(config) {
|
||||
if (!config.idle || typeof config.idle !== "object") config.idle = {}
|
||||
config.idle[key] = seconds
|
||||
})
|
||||
}
|
||||
|
||||
function toggleAndRefresh(command) {
|
||||
root.run(command)
|
||||
stateSettleTimer.restart()
|
||||
@@ -109,7 +127,7 @@ Item {
|
||||
|
||||
PolledFlag {
|
||||
id: stayAwakeFlag
|
||||
polling: root.quickVisible
|
||||
polling: root.quickVisible || root.generalVisible
|
||||
command: "blob-toggle-idle status 2>/dev/null | grep -q '\"enabled\":true' && echo on || echo off"
|
||||
}
|
||||
|
||||
@@ -256,25 +274,19 @@ Item {
|
||||
onTabRequested: function(tabId) { root.currentTab = tabId }
|
||||
}
|
||||
|
||||
Column {
|
||||
GeneralTab {
|
||||
width: parent.width
|
||||
visible: root.currentTab === "general"
|
||||
spacing: Style.spaceReal(12)
|
||||
|
||||
Calendar {
|
||||
width: parent.width
|
||||
polling: root.generalVisible
|
||||
}
|
||||
|
||||
SliderRow {
|
||||
width: parent.width
|
||||
icon: "\uf185"
|
||||
value: Number(brightnessValue.value) || 0
|
||||
onValueRequested: function(next) {
|
||||
brightness: Number(brightnessValue.value) || 0
|
||||
screensaverSeconds: root.screensaverSeconds
|
||||
lockSeconds: root.lockSeconds
|
||||
stayAwake: stayAwakeFlag.value
|
||||
onBrightnessRequested: function(next) {
|
||||
root.run("brightnessctl set " + next + "%")
|
||||
brightnessValue.value = String(next)
|
||||
}
|
||||
}
|
||||
onTimeoutRequested: function(key, seconds) { root.setIdleTimeout(key, seconds) }
|
||||
}
|
||||
|
||||
SoundTab {
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
import QtQuick
|
||||
import qs.Commons
|
||||
import qs.Ui
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
property string icon: ""
|
||||
property string label: ""
|
||||
property int seconds: 0
|
||||
property var presetMinutes: []
|
||||
|
||||
signal secondsRequested(int seconds)
|
||||
|
||||
implicitHeight: Math.max(labelText.implicitHeight, controls.implicitHeight)
|
||||
|
||||
function formatSeconds(value) {
|
||||
if (value >= 3600 && value % 3600 === 0) return (value / 3600) + " h"
|
||||
if (value % 60 === 0) return (value / 60) + " min"
|
||||
return (Math.round(value / 6) / 10) + " min"
|
||||
}
|
||||
|
||||
function step(delta) {
|
||||
var minutes = root.seconds / 60
|
||||
var presets = root.presetMinutes
|
||||
var next = -1
|
||||
if (delta > 0) {
|
||||
for (var i = 0; i < presets.length; i++)
|
||||
if (presets[i] > minutes) { next = presets[i]; break }
|
||||
} else {
|
||||
for (var j = presets.length - 1; j >= 0; j--)
|
||||
if (presets[j] < minutes) { next = presets[j]; break }
|
||||
}
|
||||
if (next > 0) root.secondsRequested(next * 60)
|
||||
}
|
||||
|
||||
Text {
|
||||
id: iconText
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: Style.spaceReal(22)
|
||||
text: root.icon
|
||||
textFormat: Text.PlainText
|
||||
color: Color.magenta
|
||||
font.family: Style.font.family
|
||||
font.pixelSize: Style.font.body
|
||||
}
|
||||
|
||||
Text {
|
||||
id: labelText
|
||||
anchors.left: iconText.right
|
||||
anchors.leftMargin: Style.spaceReal(10)
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: root.label
|
||||
textFormat: Text.PlainText
|
||||
color: Color.foreground
|
||||
font.family: Style.font.family
|
||||
font.pixelSize: Style.font.bodySmall
|
||||
}
|
||||
|
||||
Row {
|
||||
id: controls
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
spacing: Style.spaceReal(8)
|
||||
|
||||
CardIconButton {
|
||||
icon: "-"
|
||||
onActivated: root.step(-1)
|
||||
}
|
||||
|
||||
Text {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: Style.spaceReal(52)
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
text: root.formatSeconds(root.seconds)
|
||||
textFormat: Text.PlainText
|
||||
color: Color.foreground
|
||||
font.family: Style.font.family
|
||||
font.pixelSize: Style.font.bodySmall
|
||||
}
|
||||
|
||||
CardIconButton {
|
||||
icon: "+"
|
||||
onActivated: root.step(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user