How to make a submenu in a dynamic quicklist (of dbusMenuItems) in python?
The official documentation is very scarce:
https://wiki.ubuntu.com/Unity/LauncherAPI
Here is my minimal coding example: dbus_snippet.py
#!/usr/bin/env python
from gi.repository import Unity, Gio, GObject, Dbusmenu
import os
import subprocess
launchers = []
qlList = []
#(not all references are links due to askubuntu's reputation-system)
#askubuntu "how-to-add-checkbox-or-radio-buttons-to-a-unity-quicklist"
#https://lazka.github.io/pgi-docs/Dbusmenu-0.4/classes/Menuitem.html#Dbusmenu.Menuitem
#(project that this research may go into)
#(github thirschbuechler/ubuntu-recentquicklists)
def check_item_activated_callback (menuitem, a, b):#for the submenu
if menuitem.property_get_int (Dbusmenu.MENUITEM_PROP_TOGGLE_STATE) == Dbusmenu.MENUITEM_TOGGLE_STATE_CHECKED:
menuitem.property_set_int (Dbusmenu.MENUITEM_PROP_TOGGLE_STATE, Dbusmenu.MENUITEM_TOGGLE_STATE_UNCHECKED)
else:
menuitem.property_set_int (Dbusmenu.MENUITEM_PROP_TOGGLE_STATE, Dbusmenu.MENUITEM_TOGGLE_STATE_CHECKED)
def check_item_activated(menuitem, a, arg):#main menu item
process = subprocess.Popen("gedit ",shell=True)
def createItem(name, arg, qlnummer):
item = Dbusmenu.Menuitem.new()
item.property_set (Dbusmenu.MENUITEM_PROP_LABEL, name)
item.property_set_bool (Dbusmenu.MENUITEM_PROP_VISIBLE, True)
item.connect("item-activated", check_item_activated,arg)
check1 = Dbusmenu.Menuitem.new ()
check1.property_set (Dbusmenu.MENUITEM_PROP_LABEL, "Checkbox")
check1.property_set (Dbusmenu.MENUITEM_PROP_TOGGLE_TYPE, Dbusmenu.MENUITEM_TOGGLE_CHECK)
check1.property_set_int (Dbusmenu.MENUITEM_PROP_TOGGLE_STATE, Dbusmenu.MENUITEM_TOGGLE_STATE_CHECKED)
check1.property_set_bool (Dbusmenu.MENUITEM_PROP_VISIBLE, True)
check1.property_set (Dbusmenu.MENUITEM_PROP_CHILD_DISPLAY, Dbusmenu.MENUITEM_CHILD_DISPLAY_SUBMENU)
#check1.property_set (Dbusmenu.MENUITEM_PROP_CHILD_DISPLAY, 'children-display')
#https://lazka.github.io/pgi-docs/Dbusmenu-0.4/constants.html#Dbusmenu.MENUITEM_CHILD_DISPLAY_SUBMENU
check1.connect (Dbusmenu.MENUITEM_SIGNAL_ITEM_ACTIVATED, check_item_activated_callback, None)
item.child_append(check1)
qlList[qlnummer].child_append(item)
def update(a=None):
#delete old ones
for i in range(len(qlList)):
for c in qlList[i].get_children():
qlList[i].child_delete(c)
def main():
launchers.append(Unity.LauncherEntry.get_for_desktop_id ("nautilus.desktop"))
launchers.append(Unity.LauncherEntry.get_for_desktop_id ("nemo.desktop"))
for i in range(len(launchers)):
qli = Dbusmenu.Menuitem.new()
qlList.append(qli)
update()
for i in range(len(launchers)):
createItem("item1","arg1",i)
launchers[i].set_property("quicklist", qlList[i])
loop = GObject.MainLoop()
loop.run()
main()
What do I mean by submenu (made in gimp):
Why do I think this is even possible?
An option called Dbusmenu.MENUITEM_PROP_CHILD_DISPLAY
, reads "have the subitems displayed as a submenu" sounds awfully close to what I want to do, but I've failed to archive that.
The above snippet adds a dbus-item to another one, and sets the submenu-property (on the Nemo/Nautilus launcher)
(Bonus: I haven't found anything to make check_item_activated
distinguish rightclick, leftclick and middle-mouse-button, but prove me wrong)
Best Answer
I don't know how to do this with dbus but ....
You can just do this by editing .desktop files , the changes are automatically picked up. It should be simple enough to write a class to write or edit .desktop files in ~/.local/share/applications/
The launcher needs an Action line where the quicklist names are defined , for each of the names you need a [Desktop Action name] block which contains Name and Exec lines. Its documented in your link.
You can only go one level deep as far as i'm aware and i've not managed to add anything but launchers to the quicklist.
This has the benefit of ensuring that the menus are available after your program exits and on reboot.
Heres an example that lists various hosts as submenu items from the gnome-terminal icon.