Skip to content

Commit 6bf4814

Browse files
committed
feat: D-Bus method & signal to edit configuration properties
WARNING: There is no validation! Incorrect modifications will break the configuration. Usage examples: specific panel: qdbus luisbocanegra.panel.colorizer.c337.w2346 /preset luisbocanegra.panel.colorizer.c337.w2346.property 'stockPanelSettings.visible.value true' all panels: dbus-send --session --type=signal /preset luisbocanegra.panel.colorizer.all.property string:'stockPanelSettings.visible.value true' refs: #126
1 parent be3aba4 commit 6bf4814

File tree

5 files changed

+116
-4
lines changed

5 files changed

+116
-4
lines changed

package/contents/ui/DBusServiceModel.qml

+11-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ Item {
77
id: root
88
property bool enabled: false
99
property string preset: ""
10+
property string propertyToApply: ""
1011
property bool switchIsPending: false
1112
property int poolingRate: 250
1213

@@ -19,14 +20,19 @@ Item {
1920
property string pendingSwitchCmd: gdbusPartial +".pending_switch"
2021
property string switchDoneCmd: gdbusPartial +".switch_done"
2122
property string getPresetCmd: gdbusPartial +".preset"
23+
property string getPropertyToApplyCmd: gdbusPartial + ".property"
2224
property string quitServiceCmd: gdbusPartial +".quit"
2325

2426
RunCommand {
2527
id: runCommand
2628
onExited: (cmd, exitCode, exitStatus, stdout, stderr) => {
2729
// console.error(cmd, exitCode, exitStatus, stdout, stderr)
2830
if (exitCode!==0) return
29-
stdout = stdout.trim().replace(/[()',]/g, "")
31+
stdout = stdout
32+
.trim()
33+
.replace(/^\(\s*'/, '') // starting "('"
34+
.replace(/',?\s*\)$/, '') // ending "',)" or ")"
35+
.trim();
3036
// console.log("stdout parsed:", stdout)
3137
if(cmd === pendingSwitchCmd) {
3238
switchIsPending = stdout === "true"
@@ -35,6 +41,9 @@ Item {
3541
preset = stdout
3642
switchIsPending = false
3743
}
44+
if (cmd === getPropertyToApplyCmd) {
45+
propertyToApply = stdout
46+
}
3847
}
3948
}
4049

@@ -65,6 +74,7 @@ Item {
6574
running: enabled
6675
repeat: true
6776
onTriggered: {
77+
runCommand.run(getPropertyToApplyCmd)
6878
if (switchIsPending) return
6979
runCommand.run(pendingSwitchCmd)
7080
}

package/contents/ui/code/utils.js

+74-1
Original file line numberDiff line numberDiff line change
@@ -494,4 +494,77 @@ function getWidgetConfigIdx(id, name, config) {
494494

495495
function makeEven(n) {
496496
return n - n % 2
497-
}
497+
}
498+
499+
function parseValue(rawValue) {
500+
try {
501+
return JSON.parse(rawValue)
502+
} catch (e) {
503+
if (rawValue.toLowerCase() === "true") {
504+
return true
505+
}
506+
if (rawValue.toLowerCase() === "false") {
507+
return false
508+
}
509+
if (!isNaN(rawValue)) {
510+
return Number(rawValue)
511+
}
512+
513+
return rawValue
514+
}
515+
}
516+
517+
/**
518+
* Edit an existing object property using dot and square brackets notation
519+
* Overrides objects if the new value is also an object
520+
* For array allows setting per index (appending if not consecutive) or replacing with a new array
521+
* @param {Object} object - The object to set the property on.
522+
* @param {string} path - The path to the property.
523+
* @param {string} value - The value to set.
524+
*/
525+
function editProperty(object, path, value) {
526+
console.log(`editing property path: ${path}, value: ${value}`)
527+
value = parseValue(value)
528+
const keys = path.replace(/\[/g, ".").replace(/\]/g, "").split(".")
529+
let current = object
530+
531+
for (let i = 0; i < keys.length - 1; i++) {
532+
const key = keys[i]
533+
if (!current.hasOwnProperty(key)) return
534+
current = current[key]
535+
if (typeof current !== "object" || current === null) return
536+
}
537+
538+
const lastKey = keys[keys.length - 1]
539+
540+
// no new keys unless it's an array
541+
if (!current.hasOwnProperty(lastKey) && !Array.isArray(current)) return
542+
543+
console.log(lastKey)
544+
545+
if (Array.isArray(current)) {
546+
const index = parseInt(lastKey, 10)
547+
// add to array if it's the next index
548+
if (index === current.length) {
549+
current.push(value)
550+
} else if (index < current.length) {
551+
current[index] = value
552+
} else if (Array.isArray(value)) {
553+
current[lastKey] = value
554+
} else {
555+
return
556+
}
557+
} else if (
558+
typeof current[lastKey] === "object" &&
559+
current[lastKey] !== null
560+
) {
561+
// override only if the new value is an object
562+
if (typeof value === "object" && value !== null) {
563+
current[lastKey] = value
564+
} else {
565+
return
566+
}
567+
} else {
568+
current[lastKey] = value
569+
}
570+
}

package/contents/ui/configStockPanelSettings.qml

+2-2
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,7 @@ KCM.SimpleKCM {
327327

328328
Kirigami.Separator {
329329
Kirigami.FormData.isSection: true
330-
Kirigami.FormData.label: i18n("Show/Hide AKA Toggle panel")
330+
Kirigami.FormData.label: i18n("Show/Hide")
331331
}
332332

333333
CheckBox {
@@ -341,7 +341,7 @@ KCM.SimpleKCM {
341341
}
342342

343343
CheckBox {
344-
Kirigami.FormData.label: i18n("Visible:")
344+
Kirigami.FormData.label: i18n("Show:")
345345
id: visible
346346
checked: config.visible.value
347347
onCheckedChanged: {

package/contents/ui/main.qml

+5
Original file line numberDiff line numberDiff line change
@@ -1632,5 +1632,10 @@ PlasmoidItem {
16321632
onPresetChanged: {
16331633
applyPreset(preset)
16341634
}
1635+
onPropertyToApplyChanged: {
1636+
const [path, ...value] = propertyToApply.split(" ")
1637+
Utils.editProperty(main.cfg, path, value.join(" "))
1638+
plasmoid.configuration.globalSettings = JSON.stringify(main.cfg)
1639+
}
16351640
}
16361641
}

package/contents/ui/tools/service.py

+24
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ def __init__(self, bus: dbus.Bus):
2828
self._loop = GLib.MainLoop()
2929
self._last_preset = ""
3030
self._pending_witch = False
31+
self._property = ""
3132
self._bus = bus
3233
super().__init__()
3334

@@ -39,6 +40,11 @@ def run(self):
3940
dbus_interface=SHARED_INTERFACE,
4041
signal_name="preset",
4142
)
43+
self._bus.add_signal_receiver(
44+
self.on_shared_property_signal,
45+
dbus_interface=SHARED_INTERFACE,
46+
signal_name="property",
47+
)
4248
bus_name = dbus.service.BusName(SERVICE_NAME, dbus.SessionBus())
4349
dbus.service.Object.__init__(self, bus_name, PATH)
4450

@@ -63,6 +69,16 @@ def preset(self, m="") -> str:
6369
return "saved"
6470
return self._last_preset
6571

72+
@dbus.service.method(SERVICE_NAME, in_signature="s", out_signature="s")
73+
def property(self, m=""):
74+
"""Set a specific property using dot notation
75+
e.g `'stockPanelSettings.visible {"enabled": true, "value": false}'`
76+
"""
77+
if m:
78+
if m != self._property:
79+
self._property = m
80+
return self._property
81+
6682
def on_shared_preset_signal(self, preset_name: str):
6783
"""Handle the shared signal to set the preset
6884
@@ -71,6 +87,14 @@ def on_shared_preset_signal(self, preset_name: str):
7187
"""
7288
self.preset(preset_name)
7389

90+
def on_shared_property_signal(self, edited_property: str):
91+
"""Handle the shared signal to set the preset
92+
93+
Args:
94+
edited_property (str): The property from the signal
95+
"""
96+
self.property(edited_property)
97+
7498
@dbus.service.method(SERVICE_NAME, in_signature="", out_signature="b")
7599
def pending_switch(self) -> bool:
76100
"""Wether there is a pending preset switch

0 commit comments

Comments
 (0)