Solved xbmcgui.Dialog().contextmenu() examples?
#1
Just wondering if anyone has some good examples where xbmcgui.Dialog().contextmenu() is used in an addon. I am thinking of moving some builtin functions from my skin to an addon. I was able to create my context menu using the Hello World example as a guide. Now I just need to figure out how to set conditional visibility for the items and their onclick actions.

Oh, and I might be a skilled skinner to some, but I'm definitely a Python newbie! Smile

Thanks!
Reply
#2
Just wanted to say welcome here! Your skinning is about to get a lot better! You can do alot of wonders with Python. :-)
Reply
#3
You basically use it the same as Dialog().select(), you just pass a list of strings to it.
Example: https://github.com/phil65/script.extende...fo.py#L142
Donate: https://kodi.tv/contribute/donate (foundation), 146Gr48FqHM7TPB9q33HHv6uWpgQqdz1yk (BTC personal)
Estuary: Kodis new default skin - ExtendedInfo Script - KodiDevKit
Reply
#4
Thanks guys, will take a look at how ExtendedInfo uses it!

Sent from my Nexus 6
Reply
#5
phil65, thanks for posting the ExtendedInfo example, that and your context menu addon helped a lot. I was able to get my context menu working, with one critical exception. In my code example below, if one of the menu items is not visible, the actions are out of sync because they are based on the index (hope that makes sense). Any way to correct for this?

Thanks!

Code:
import xbmcaddon
import xbmcgui

addon       = xbmcaddon.Addon()
addonname   = addon.getAddonInfo('name')

def main():
    if xbmc.getCondVisibility("!String.IsEmpty(ListItem.Art(fanart))"):
        options = ["View fanart"]
    if xbmc.getCondVisibility("System.HasAddon(script.ratingupdate) + [Container.Content(movies) | Container.Content(tvshows)]"):
        options.append("Update IMDb ratings")
    if xbmc.getCondVisibility("System.HasAddon(script.extendedinfo) + Container.Content(movies)"):
        options.append("ExtendedInfo")
    if xbmc.getCondVisibility("System.HasAddon(script.extendedinfo) + Container.Content(tvshows)"):
        options.append("ExtendedInfo")

    index = xbmcgui.Dialog().contextmenu(list=options)

    if index == 0:
        xbmc.executebuiltin("SetFocus(90400)")
    if index == 1:
        xbmc.executebuiltin("RunScript(script.ratingupdate,Single=Movie)")
    if index == 2:
        xbmc.executebuiltin("RunScript(script.extendedinfo,info=extendedinfo,dbid=%s,id=%s)" % (xbmc.getInfoLabel("ListItem.DBID"), xbmc.getInfoLabel("ListItem.Property(id)")))
    if index == 3:
        xbmc.executebuiltin("RunScript(script.extendedinfo,info=extendedtvinfo,dbid=%s,id=%s)" % (xbmc.getInfoLabel("ListItem.DBID"), xbmc.getInfoLabel("ListItem.Property(id)")))

if __name__ == '__main__':
    main()
Reply
#6
If the first condition is not met. There is no "options" to append to.
Also, i thought you could include the script to run in the list. If you can do that ypu could pass params with each click.
Reply
#7
Comparing the text of the item in the options list at the index selected would be one possible approach:-

Code:
if options[index] == "View fanart":
    xbmc.executebuiltin("SetFocus(90400)")
elif options[index] == "Update IMDb ratings":
    xbmc.executebuiltin("RunScript(script.ratingupdate,Single=Movie)")
elif options[index] == "ExtendedInfo":
    xbmc.executebuiltin("RunScript(script.extendedinfo,info=extendedinfo,dbid=%s,id=%s)" % (xbmc.getInfoLabel("ListItem.DBID"), xbmc.getInfoLabel("ListItem.Property(id)")))
Reply
#8
what i did in globalsearch was to create two lists, one for the labels and one for the actions.
(https://github.com/ronie/script.globalse...ui.py#L910)

perhaps you can use something similar...

untested!:
Code:
def main():
    options = []
    actions = []
    if xbmc.getCondVisibility("!String.IsEmpty(ListItem.Art(fanart))"):
        options.append("View fanart")
        actions.append('xbmc.executebuiltin("SetFocus(90400)")')
    if xbmc.getCondVisibility("System.HasAddon(script.ratingupdate) + [Container.Content(movies) | Container.Content(tvshows)]"):
        options.append("Update IMDb ratings")
        actions.append('xbmc.executebuiltin("RunScript(script.ratingupdate,Single=Movie)")')
    if xbmc.getCondVisibility("System.HasAddon(script.extendedinfo) + Container.Content(movies)"):
        options.append("ExtendedInfo")
        actions.append('xbmc.executebuiltin("RunScript(script.extendedinfo,info=extendedinfo,dbid=%s,id=%s)" % (xbmc.getInfoLabel("ListItem.DBID"), xbmc.getInfoLabel("ListItem.Property(id)")))')
    if xbmc.getCondVisibility("System.HasAddon(script.extendedinfo) + Container.Content(tvshows)"):
        options.append("ExtendedInfo")
        actions.append('xbmc.executebuiltin("RunScript(script.extendedinfo,info=extendedtvinfo,dbid=%s,id=%s)" % (xbmc.getInfoLabel("ListItem.DBID"), xbmc.getInfoLabel("ListItem.Property(id)")))')

    if options:     # don't show context menu if list is empty
        index = xbmcgui.Dialog().contextmenu(list=options)
        if index >= 0:     # don't execute action if dialog was cancelled
            actions[index]
Do not PM or e-mail Team-Kodi members directly asking for support.
Always read the Forum rules, Kodi online-manual, FAQ, Help and Search the forum before posting.
Reply
#9
Thanks for the replies everyone, will test tonight. I previously created the context menu using 2 lists in a custom xml window, was hoping to avoid that here. Cheers!

Update: Tried out all of the suggestions. When I first read 2 lists, I was thinking a lot of duplicate code like my custom xml window. But Ronie's solution is quite elegant, I really wanted to use it. Couldn't quite get it to work though, couldn't get the actions to fire. Ended up using Bob's suggestion to match the label + a few other fixes. Thanks again everyone.
Reply
#10
I'm a bit late to the party but...

I use a helper method to take the pain away.

Code:
def handleMenu(menu):
    param = -1
    list  = []

    for item in menu:
        list.append(item[0])

    param = xbmcgui.Dialog().contextmenu(list)

    if param > -1:
        param = menu[param][1]
    
    return param

# do menu
# options
UP           = 10
DOWN         = 20

METAMENU     = 100
EDITMETA     = 110
REMOVEMETA   = 120

DESCMENU     = 200
EDITDESC     = 210
REMOVEDESC   = 220


# build menu
menu = []
menu.append(['Move up',          UP])
menu.append(['Move down',        DOWN])
menu.append(['Description menu', DESCMENU])
menu.append(['Metadata menu ',   METAMENU])


# handle menu
param = handleMenu(menu)
menu  = [] #now reset menu contents


#is a sub-menu necessary
if param == METAMENU:
    menu.append(['Edit metadata',   EDITMETA])
    menu.append(['Remove metadata', REMOVEMETA])

if param == DESCMENU:
    menu.append(['Edit description',   EDITDESC])
    menu.append(['Remove description', REMOVEDESC])


# handle sub-menu
if len(menu) > 0:
    param = handleMenu(menu)    


#handle user's final selection
if param == UP:
    doUp()

if param == DOWN:
    doDown()

if param == EDITMETA:
    doEeditMeta()

if param == REMOVEMETA:
    doRemoveMeta()

if param == EDITDESC:
    doEditDdesc()

if param == REMOVEDESC:
    doRemoveDesc()

This removes the need for doubling up of lists (which could be prone to errors), and any potential indexing issues as the value returned is the actual value associated with the text label when the menu is created.
Also easy to extend and maintain.
Also very handy for handling sub-menus too, as can be seen in the above example.

@braz - happy to go through it via PM if you want.
Reply
#11
Or how about if you just want to call a bunch of methods that all take the same (or no) parameters

Code:
def handleMenu(menu):
    list  = []

    for item in menu:
        list.append(item[0])

    param = xbmcgui.Dialog().contextmenu(list)

    if param < 0:
        return None

    return menu[param][1]


# build menu
menu = []
menu.append(['Move up',   doUp])
menu.append(['Move down', doDown])


# handle menu
param = handleMenu(menu)

if param:
    param()
Reply
#12
Thanks spoyser, will try that out when I get a chance. Here's what I'm using right now, I'm sure it can be improved though.

https://github.com/braz96/script.mimic.e...r/addon.py
Reply
#13
(2016-04-23, 17:28)braz Wrote: Thanks spoyser, will try that out when I get a chance. Here's what I'm using right now, I'm sure it can be improved though.

https://github.com/braz96/script.mimic.e...r/addon.py

That's a lot of code!

Okay, here goes.

First add the menu handling method:

Code:
def handleMenu(menu):
    list  = []

    for item in menu:
        list.append(item[0])

    param = xbmcgui.Dialog().contextmenu(list)

    if param < 0:
        return None

    return menu[param][1]

Now build the menu (we need to get rid of some of the or statements too and handle them all separately, makes like easier at the end), so

Code:
#build menu
isMovie   = xbmc.getCondVisibility("String.IsEqual(ListItem.DBTYPE,movie)")
isTVShow  = xbmc.getCondVisibility("String.IsEqual(ListItem.DBTYPE,tvshow)")
isEpisode = xbmc.getCondVisibility("String.IsEqual(ListItem.DBTYPE,episode)")
isMusic   = xbmc.getCondVisibility("String.IsEqual(ListItem.DBTYPE,musicvideo)")

options = []

options.append([LANGUAGE(32000), "SetFocus(90400)"])
if xbmc.getCondVisibility("System.HasAddon(script.extendedinfo)"):
    if isMovie:
        options.append([LANGUAGE(32001), "RunScript(script.extendedinfo,info=extendedinfo,dbid=%s,id=%s)" % (xbmc.getInfoLabel("ListItem.DBID"), xbmc.getInfoLabel("ListItem.Property(id)"))])
    elif isTVShow:
        options.append([LANGUAGE(32001), "RunScript(script.extendedinfo,info=extendedtvinfo,dbid=%s,id=%s)" % (xbmc.getInfoLabel("ListItem.DBID"), xbmc.getInfoLabel("ListItem.Property(id)"))])

if xbmc.getCondVisibility("System.HasAddon(script.simpleplaylists)"):
    if isMovie or isTVShow:
        options.append([LANGUAGE(32002), "RunPlugin(plugin://script.simpleplaylists/?mode=addCurrentUrl)"])

if xbmc.getCondVisibility("System.HasAddon(script.artwork.downloader)"):
    if isMovie:
        options.append([LANGUAGE(32003), "RunScript(script.artwork.downloader,mediatype=movie,dbid=%s)"          % xbmc.getInfoLabel("ListItem.DBID")])
        options.append([LANGUAGE(32004), "RunScript(script.artwork.downloader,mode=gui,mediatype=movie,dbid=%s)" % xbmc.getInfoLabel("ListItem.DBID")])
    elif isTVShow:
        options.append([LANGUAGE(32003), "RunScript(script.artwork.downloader,mediatype=tvshow,dbid=%s)"          % xbmc.getInfoLabel("ListItem.DBID")])
        options.append([LANGUAGE(32004), "RunScript(script.artwork.downloader,mode=gui,mediatype=tvshow,dbid=%s)" % xbmc.getInfoLabel("ListItem.DBID")])

if xbmc.getCondVisibility("System.HasAddon(script.ratingupdate)"):
    if isMovie or isTVShow:
        options.append([LANGUAGE(32005), "RunScript(script.ratingupdate,Single=Movie)"])

if xbmc.getCondVisibility('String.IsEmpty(Window(movieinformation).Property("TvTunes_HideVideoInfoButton"))'):
    if isMovie or isTVShow or isMusic:
        options.append([LANGUAGE(32006), "RunScript(script.tvtunes,mode=solo)"])

if xbmc.getCondVisibility("System.HasAddon(script.cinemavision)"):
    if isMovie or isTVShow or isEpisode:
        options.append([LANGUAGE(32007), "SPECIALCASE1"]) #because it does 2 things

if xbmc.getCondVisibility("System.HasAddon(script.videoextras)"):
    if isMovie or isEpisode or isMusic:
        options.append([LANGUAGE(32008), "RunScript(script.videoextras,display,%s)" % (xbmc.getInfoLabel("ListItem.FilenameAndPath"))])
    elif isTVShow:
        options.append([LANGUAGE(32008), "RunScript(script.videoextras,display,%s)" % (xbmc.getInfoLabel("ListItem.Path"))])

Finally, show the menu and deal with the result:

Code:
action = handleMenu(options)
if not action:
    return

if action == 'SPECIALCASE1':
    xbmc.executebuiltin("Dialog.Close(movieinformation)")
    xbmc.executebuiltin("RunScript(script.cinemavision,experience)")
else:
    xbmc.executebuiltin('%s' % action)

Obviously, would have been more elegant without the special case (this could be handled using a list of actions to perform when building the menu array, but I thought that was a bit OTT for a single case).

HTH
Reply
#14
Thanks spoyser, that works great! Also made me think to shorten all of the DBTYPE conditions in my skin by using expressions.

A little off topic...you'll notice I have a menu item to add to SimplePlaylists. Is there a way to add to SuperFavourites from my context menu? I like to create my own "watchlist" and use it as a home screen widget. I've found that SimplePlaylists is slow to load and SuperFavourites is much faster. I realize it's also possible to add SF to the Kodi context menu via its settings but would like a simple Add to SF button.

Thanks again, appreciate it!
Reply
#15
(2016-04-24, 17:25)braz Wrote: Thanks spoyser, that works great! Also made me think to shorten all of the DBTYPE conditions in my skin by using expressions.

A little off topic...you'll notice I have a menu item to add to SimplePlaylists. Is there a way to add to SuperFavourites from my context menu? I like to create my own "watchlist" and use it as a home screen widget. I've found that SimplePlaylists is slow to load and SuperFavourites is much faster. I realize it's also possible to add SF to the Kodi context menu via its settings but would like a simple Add to SF button.

Thanks again, appreciate it!

Did you get the version I pointed you to in the other thread, if not this is the link again

https://dl.dropboxusercontent.com/u/1155...BMC/sf.zip

This gives you the option to put the "Add To SF" item on the standard menu.

Then to add it to your custom menu use this:
RunScript(special://home/addons/plugin.program.super.favourites/menu_addtofaves.py)
Reply

Logout Mark Read Team Forum Stats Members Help
xbmcgui.Dialog().contextmenu() examples?0