6

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): enter image description here

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)

  • QuickLists don't have submenus and I've not seen it being done. Have you considered making an indicator ? It is possible to have q menu with submenus, even dynamically made. – Sergiy Kolodyazhnyy Sep 13 '16 at 22:15
  • Yes, you are right, an indicator would be an option, technically. However, mye goal is to simulate Windows' ability to pin recent files to quicklaunch items, without resorting to two user interfaces which are phyiscally apart (quicklaunch and appindicator). I've updated my question to reflect my starting point with "Dbusmenu.MENUITEM_PROP_CHILD_DISPLAY" – hirsch Sep 14 '16 at 5:41
  • Something like this has been done already : askubuntu.com/a/747787/295286 – Sergiy Kolodyazhnyy Sep 14 '16 at 5:44
  • This is incorrect, my question about submenus isn't answered there. Regarding the underlying project: Yeah, but only for Libreoffice, as far as I can see. Mine already automatically gets ALL THE FILES for ALL THE LAUNCHERS :) – hirsch Sep 14 '16 at 5:48
  • 3
    I've put a bounty on this question. It expires within one week from today. If you see an answer here that fits your requirement, let me know and I'll award bounty to that post – Sergiy Kolodyazhnyy Sep 16 '16 at 3:20
0

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.

[Desktop Entry]
Name=Terminal
Comment=Use the command line
Keywords=shell;prompt;command;commandline;
TryExec=gnome-terminal
Exec=gnome-terminal
Icon=utilities-terminal
Type=Application
X-GNOME-DocPath=gnome-terminal/index.html
X-GNOME-Bugzilla-Version=3.16.2
Categories=GNOME;GTK;System;TerminalEmulator;
StartupNotify=true
X-GNOME-SingleWindow=false
OnlyShowIn=GNOME;Unity;
Actions=New;host1;host2
X-Ubuntu-Gettext-Domain=gnome-terminal

[Desktop Action New]
Name=New Terminal
Exec=gnome-terminal
OnlyShowIn=Unity

[Desktop Action host1]
Name=SSH to HOST1
Exec=gnome-terminal -e 'ssh host1' -t 'SSH to host1'
OnlyShowIn=Unity

[Desktop Action host2]
Name=SSH to HOST2
Exec=gnome-terminal -e 'ssh host2' -t 'SSH to host2'
OnlyShowIn=Unity
| improve this answer | |
  • dude, these are not submenus, and it's not in python either (you've said yourself it's static). Submenu = only pops up when you click (or place the cursor on) a menu item. My script can already do menus – hirsch Sep 16 '16 at 17:40
  • i have never seen one in unity and have used it daily for many years. – Amias Sep 18 '16 at 9:12
  • There is a reason it doesn't distinguish between right and left clicks , pretty sure its because its designed for touch as well as mice. That would also be the reason for not having submenus as they doesn't play nicely with touch like mice do. – Amias Sep 18 '16 at 9:16
  • I haven't seen one either, but the interface-defintions hint that it might be possible.. that's kind of the point of the question. Also, I can easily think of examples how an implementation on touch-devices would be possible: A long-press, double-tap, horizontal swipe or the android settings-button (in conjuntion with an ordinary tap) might do the trick (though I am by no means an interface designer) – hirsch Sep 18 '16 at 11:47
  • that might be possible on a tightly controlled platform like IOS which has tight hardware specs but with the generic hardware support required here it won't be. – Amias Sep 18 '16 at 11:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.