WindowXML GUI Toolkit (replaces GUIBuilder for XBMC python scripts for GUI coding)

  Thread Rating:
  • 0 Votes - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Post Reply
donno Offline
Team-XBMC Python Developer
Posts: 130
Joined: Jan 2005
Reputation: 0
Location: Australia
Thumbs Up  WindowXML GUI Toolkit (replaces GUIBuilder for XBMC python scripts for GUI coding)
Post: #1
Hello, I finally had some success at adding a new Window Type. (Called WindowXML). The purpose of this is to remove the need for GUIBuilder and let XBMC load the xmls and handle it correctly. This even means onclicks for builtins, animation and visibility should work without the need for tons of python code powering it.

Class xbmcgui.WindowXML()
Function xbmcgui.WindowXML().onInit(self) #Replacement for __init__
Function xbmcgui.WindowXML().onAction(self,action)
Function xbmcgui.WindowXML().onClick(self,controlID) #Replacement for onControl
Function xbmcgui.WindowXML().onFocus(self,controlID)

If anyone is interested in having the onFocus stuff in old Window and WindowDialog please just say.

Ideas/Long Term Goals
XML PATH
Allow you to do specify currentscriptpath + "\\mainwindow.xml" and automatically check path that the xml is in for images (if it has a path) else it’s assumed that the xml is located in the current skin and images are in the media and XPR. Inital ideas are make the scripter detect if the xml they want such as youtube_window.xml is located in the currentskin\pal or NTSC folders else use the included xml/ stock graphics.

More Control Types
Allow for more controls types (port over more the controls available for skinning to be able to do even more.

Change the Way My Scripts works
Allow you to 'minimize' a script, then if you click on the script in my scripts give you the option to maximize or close it. Of course also have an option for scripter. (The maximize would work but remember the Window id given to the script while its running and activating that id when you click it in my scripts.

Way for Type Checking and Error handling
Way to check that when u get the control with id 2 that it is infact a button and a skinner hasn't made it a image instead Smile

Note) I Am going off to uni so i may not get a chance to work on this. Im hoping to create a branch to store my work in before I go.

Example Script showing it from the python scripters side
Code:
import xbmcgui

KEY_BUTTON_BACK = 275
KEY_KEYBOARD_ESC = 61467

"""
    Problems At The Moment
    - Requires the xml to be present in the current running skin (so no way to load a included xml and gfx)
    - Currently you can not get ControlList type returned if you do   self.getControl(id).
        Window.cpp  Window_GetControlByID in the switch(pGUIControl->GetControlType()) needs a case for case CGUIControl::GUICONTAINER_LIST: \_
        and a matching python type. Making it a ControlList causes access issues
    - 'Exiting Problem' if you do use <onclick> in the xml (builtins) [i find u have to activatewindow(13000) 'usually' to show the script again then ESC/BACK to close
"""

"""
    xbmcgui.WindowXML()
    xbmcgui.WindowXML().onInit(self)                Replacement for __init__
    xbmcgui.WindowXML().onAction(self,action)
    xbmcgui.WindowXML().onClick(self,controlID)        Replacement for onControl
    xbmcgui.WindowXML().onFocus(self,controlID)
"""

class WindowXML(xbmcgui.WindowXML):
    def onInit(self):
        """
            This function has been implemented and works
            The Idea for this function is to be used to get initial data and populate lists
        """
        print "onInit(): Window Initialized"
        #self.listctrl = self.getControl(50)
        #self.listctrl.addItem("hey")
        self.button = self.getControl(2) # Example of getting a control based on ID
        self.button.setLabel('Hello 2', 'font14', '0xFFFFFFFF', '0xFFFF3300', '0xFF000000')  # changing the control after its on screen

    def onAction(self, action):
        """"
            onAction in WindowXML works same as on a Window or WindowDialog its for keypress/controller buttons etc
            This function has been implemented and works
        """
        buttonCode =  action.getButtonCode()
        actionID   =  action.getId()
        print "onAction(): actionID=%i buttonCode=%i" % (actionID,buttonCode)
        if (buttonCode == KEY_BUTTON_BACK or buttonCode == KEY_KEYBOARD_ESC):
            self.close()

    def onClick(self, controlID):
        """
            onClick(self, controlID) is the replacement for onControl. It gives an interger.
            This function has been implemented and works
        """
        print "onclick(): control %i" % controlID

        if (controlID == 2):
            print "Some Control with id 2 was pressed"

    def onFocus(self, controlID):
        """"
            onFocus(self, int controlID)
            This function has been implemented and works
        """
        print "onFocus(): control %i" % controlID
        if (controlID == 5):
            print 'The control with id="5" just got focus'

if __name__ == '__main__':
    w = WindowXML("youtube.xml")
    w.doModal()
    del w

Any ideas, suggestions are appreciated.
More information should be up on http://darkdonno.googlepages.com/xbmc-dev once i get around to documenting more of it Smile
Spend quite a few hours today getting the actual code to work so far Smile
The goal is make scripts more like plug-ins that fit along with the rest of XBMC, and also try to make it easier and hopefully more efficient.

** Team XBMC Tester** XBMC 4 ever

Always read the XBMC online-manual, FAQ and search the forum before posting.
Do not e-mail XBMC-Team members directly asking for support. Read/follow the forum rules.
For troubleshooting and bug reporting please make sure you read this first.


[Image: badge.gif]
find quote
solexalex Offline
Skilled Python Coder
Posts: 707
Joined: Jul 2004
Reputation: 6
Post: #2
Congratulations !

Looking forward to it !!
find quote
Nuka1195 Offline
Skilled Python Coder
Posts: 3,910
Joined: Dec 2004
Reputation: 18
Post: #3
Congrats Donno. Smile

"Long Live GUIBuilder"

For python coding questions first see http://mirrors.xbmc.org/docs/python-docs/
find quote
FrostBox Offline
Skilled Python Coder
Posts: 100
Joined: Nov 2005
Reputation: 6
Location: Quebec City
Post: #4
Hi, Congratulation

This is good news.
I am impatient to test this.

Frost

For my bad English, sorry. I am French Canadian.
Admin @ Passion-XBMC.org
find quote
matthuisman Offline
Skilled Python Coder
Posts: 600
Joined: Sep 2006
Reputation: 5
Location: Chch, New Zealand
Post: #5
Hey, does this mean I will be able to have my script "sleep" and get control actions without the use of xbmc window class?
Hence, xbmc controls etc will still work...
find quote
Asteron Offline
"Skilled" Python Coder
Posts: 928
Joined: Feb 2004
Reputation: 0
Post: #6
Hey Donno,
Did you derive this from the standard xbmcgui.Window?

You really need its getControl(id) to allow you to modify controls like enable/disable buttons.

Actually looking at the xbmcgui api you still really need pretty everything but getFocus(), getWidth/Height/Coordinate resolution. After that there is no real reason to use th old window Smile

Ohh Im not really sure why you would want OnInit() instead of __init__ like every other python class... It doesnt seem like you would be able to pass parameters like that so it seems not as good...

One request I have is for an OnShow(). That seems very useful as you could do stuff like update lists or information you are about to display.

Also how about a keyword like fullscreen=True that determines whether the window behaves like a xbmcgui.Window or xbmcgui.WindowDialog ... or does the skin take care of that?

Maybe xbmcgui.SkinnedWindow would be better? It emphasizes the presentation over the implementation... not a big deal though
(This post was last modified: 2007-02-15 01:55 by Asteron.)
find quote
donno Offline
Team-XBMC Python Developer
Posts: 130
Joined: Jan 2005
Reputation: 0
Location: Australia
Post: #7
stanley87: nope it’s the same as Window/WindowXML in that aspect

Quote:You really need its getControl(id) to allow you to modify controls like enable/disable buttons.
Up as it’s based on the Window its already has that function. The problem is it only returns a 'Control' for some types of controls that don't currently exist in Python

Sorry for the confusion with onInit(), the reason for this is its actually called by the message manger in XBMC says the window has been initialized. You can still pass parameters and have a def __init__(self) as that a generic python function (same as constructors in C/C++) how ever OnInit can be used for modifying the UI. The __init__ is called when the object in python. and its ran before the XBMC has loaded the xml up so no controls would exist at that point so there would be no nice way of populate lists and other stuf at startup.
With reguards to xbmcgui.SkinnedWindow i ll still with WindowXML, as you can say the Window and WindowDialog is Skinned Smile

On the full screen/dialog effect It would be best if it was specified in the xml (by <window type="dialog">) how ever at the moment this doesn't work so needs some fixing there.

** Team XBMC Tester** XBMC 4 ever

Always read the XBMC online-manual, FAQ and search the forum before posting.
Do not e-mail XBMC-Team members directly asking for support. Read/follow the forum rules.
For troubleshooting and bug reporting please make sure you read this first.


[Image: badge.gif]
(This post was last modified: 2007-02-17 07:38 by donno.)
find quote
donno Offline
Team-XBMC Python Developer
Posts: 130
Joined: Jan 2005
Reputation: 0
Location: Australia
Star  Update
Post: #8
Made some great improvements for the fallback features with the help and pointers from Spiff Smile.

WindowXML now takes two arguments. Filename for the XML file to load for the window, and the 'fallback' path.

Exploitation Smile
Internally, XBMC will check to see if the filename given exists in the current skin. (eg CurrentSkin\Pal or CurrentSkin\720p etc). Now if the skin the user is running doesn't have the xml (such as youtube_mainwin.xml) it will then check in the Fallback path. A fallback path should be like Q:\scripts\youtube\DefaultSkin and have
Q:\scripts\youtube\DefaultSkin\PAL
Q:\scripts\youtube\DefaultSkin\NTSC\
Q:\scripts\youtube\DefaultSkin\PAL16x9
Q:\scripts\youtube\DefaultSkin\NTSC16x9
Q:\scripts\youtube\DefaultSkin\1080i
Q:\scripts\youtube\DefaultSkin\720p

import os, xbmcgui
scriptPath = os.getcwd().replace(";","") # The replace fixes the fact inside XBMC it adds a ; to the end of the path
i use WindowXML("youtube_mainwin.xml",os.path.join(scriptPath."DefaultSkin"))


Just realised a slight flaw in the way fallback works, as we don't load in our own skin.xml or lock it ot a standard (so it will check like PAL no matter what). So if someone a skin with the default set as NTSC. If you are running 720p for example it may fallback to NTSC16x9 (instead of PAL 16x9) and then NTSC (instead of PAL) like most skins do. So this fix is in my todo list, its an easy fix Smile just a matter of checking if g_SkinInfo.GetSkinPath(strXMLname,&res,strFallbackPath) exists if it doesn't do strFallbackPath + " \\pal\\" + strXMLName Smile. so at least the standard for scripts will be it checks pal last no matter what.
Spiff helped fix the problem i was having with the GUIWindow. (When giving it a path such as q:\script\Youtube\DefaultSkin\youtube.xml) it wouldn't do anything special so XBMC tried loading Q:\skin\project mayhem III\pal\q:\script\Youtube\DefaultSkin\youtube.xml . Now it loads the xmls correctly etc but u just can't see the window (its all black). You can navigate and click stuff thou, so I need to have a look into that.

Fews notes)
in the included skin 'the fallback one' for the sack of good practise yours shouldn't depend on includes (as this ties it to a skin). 2nd you should have every tag for every control in the XML leaving nothing left over to use the default defined by the skin (meaning in a <control type="label"> have a <textcolor> even if its the color you want it without it as it you change skin the default color for a label may be different.

IMO Once the fallback stuff renders correctly and all teh new lists types work in python it should be good enough to start using main stream and go in the trunk (if it doesn't create to many bugs)

Now depending on how much time i get and the avaliablity of the internet migth be a few days/weeks till i can get back on this Smile


Now depending on how much time i get and the avaliablity of the internet migth be a few days/weeks till i can get back on this Smile

** Team XBMC Tester** XBMC 4 ever

Always read the XBMC online-manual, FAQ and search the forum before posting.
Do not e-mail XBMC-Team members directly asking for support. Read/follow the forum rules.
For troubleshooting and bug reporting please make sure you read this first.


[Image: badge.gif]
find quote
Nuka1195 Offline
Skilled Python Coder
Posts: 3,910
Joined: Dec 2004
Reputation: 18
Post: #9
Hey donno, I have a good script that could be used to test this. XBMC Lyrics. Theres only like four required controls. I would like to play around with animation and things.

For python coding questions first see http://mirrors.xbmc.org/docs/python-docs/
find quote
spiff Offline
Retired Developer
Posts: 12,386
Joined: Nov 2003
Post: #10
nuka, its in a branch so play all you want Smile
find quote
asg Offline
Member
Posts: 80
Joined: Nov 2005
Reputation: 0
Post: #11
Hi donno,

i´ve just compiled the branched windowxml to test it. Could you post a more recent python example, so i could play with it a bit?

Thanks in advance
asciii
find quote
donno Offline
Team-XBMC Python Developer
Posts: 130
Joined: Jan 2005
Reputation: 0
Location: Australia
Post: #12
After much hard work I have finally got the lists/multi views to work.

This means instead of just having one list/type, you can add items to the 'window's list' and have it shared over up to 10 different lists.
ID 50 to 59 (same as Videos/Music/Pictures/Program windows in skinning Smile.
So you can have Wide Icons view/ List, List 2 type stuff for your own script.

ID 2 is reserved for the View button so if you don't want the view button or to use multi views simply do not use id 2, 3,4, 12 or 50-59 for any controls.
ID 2 is the View Button, 3 is the Sort Button, 4 is the Asc/Dsc button, 12 is
the number of objects label, 50-59 are the lists.

So if you have View button and lists with ids 50 to 59 Smile the following is of intrest
WindowXML Methods
refreshList() -- Updates the Windows Lists (any new items will be shown once this command is ran.

addItem(item[,refreshList]) -- Add a new item to windows list.
refreshList is 1 (true) by default what this means is
If TRUE it will perform a refresh/sync after every add so the lists will be up to date.
If FALSE then it won't perform a update of the lists so anything u added won't be seen until u run refreshList()

Reason for this refresh stuff is say u want to add a lot of entries to a list you may want to wait till they all were added to the internal list before showing them on the screen instead of showing them after each is added.
---------------------------------


I need to get "clearList() -- Clear the Window List" to work

Future) The ListItem may need to be improved so it can set stuff as 'album,artist,title' and such so info labels in the lists would work nicely Smile

Sorry if this post is confusing it was Smile 12am and im just trying to get down as much as I can think of.


Note) I need to fix the py docs for the window xml stuff Smile
I committed the WindowXMLExample script as a zip into the scripts folder in the branch
Download a XBMC_PC exe here If this link is broken it could mean threes a new version Smile or windowxml is completed in trunk.

TODO)
  • Fallback path rendering correctly and using fallbackpath\media [this needs to be done to make it trunk ready]
  • Open up more controls to python [this can always been done once it is in the trunk no hurry)
  • Extend ListItem [ Again its whenever]
  • Extend Script Window Functionality
  • Clean up file cosemetics (tabs/spaces)

Maybe its best try to read it then ask me little questions about it

** Team XBMC Tester** XBMC 4 ever

Always read the XBMC online-manual, FAQ and search the forum before posting.
Do not e-mail XBMC-Team members directly asking for support. Read/follow the forum rules.
For troubleshooting and bug reporting please make sure you read this first.


[Image: badge.gif]
find quote
asg Offline
Member
Posts: 80
Joined: Nov 2005
Reputation: 0
Post: #13
Very nice .. thanks donno! Is there already a way to use onControl events from the ListItems? Maybe i am just too dumb/blind ? Smile
find quote
matthuisman Offline
Skilled Python Coder
Posts: 600
Joined: Sep 2006
Reputation: 5
Location: Chch, New Zealand
Post: #14
def onClick(self, controlID):
if (controlID == 7):
xbmcgui.Dialog().ok(__title__ + ": About","Example Script coded by Donno Big Grin","WindowXML Class coded by Donno","With help from Spiff Smile")
find quote
matthuisman Offline
Skilled Python Coder
Posts: 600
Joined: Sep 2006
Reputation: 5
Location: Chch, New Zealand
Post: #15
oops, just re-read your message, good point.
find quote
Post Reply