[solved] How to handle multiple widgets with script skinshortcuts?
#16
@"nfm886" , here are some excerpts from my script-skinshortcuts.xml that might help:

Next, you will see the buttons I am using for configuring widgets 1 and 2.  As you will see, what I do in these buttons is set the focus to control ID 312 for widget 1, and control id 4312 for widget 2:

xml:

<control type="button" id="800">
              <visible>String.IsEqual(Window.Property(groupname),mainmenu) + !Skin.HasSetting(Hide.AllShelves)</visible>
              <description>Widget</description>
              <label>$LOCALIZE[31491] 1</label>
              <label2>$INFO[Container(211).ListItem.Property(widgetName)]</label2>
              <onfocus condition="!String.IsEmpty(Window(Home).Property(skinshortcuts-Widget))">ClearProperty(skinshortcuts-Widget,Home)</onfocus>
              <onclick>SetProperty(skinshortcuts-Widget,1,Home)</onclick>
              <onclick>Control.SetFocus(312)</onclick>
              <height>60</height>
              <width>1340</width>
              <texturenofocus border="3">buttons/ButtonNF.png</texturenofocus>
              <font>ListDetails</font>
             <visible>!String.IsEqual(Container(211).ListItem.Property(skinshortcuts-disabled),True)</visible>
 </control>
                <control type="button" id="801">
                    <visible>String.IsEqual(Window.Property(groupname),mainmenu) </visible>
                    <description>Widget 2</description>
                    <label>$LOCALIZE[31491] 2</label>
                    <label2>$INFO[Container(211).ListItem.Property(widgetName.2)]</label2>
                    <onfocus condition="!String.IsEmpty(Window(Home).Property(skinshortcuts-Widget))">ClearProperty(skinshortcuts-Widget,Home)</onfocus>
                    <onclick>SetProperty(skinshortcuts-Widget,2,Home)</onclick>
                    <onclick>Control.SetFocus(4312)</onclick>
                    <height>60</height>
                    <width>1340</width>
                    <texturenofocus border="3">buttons/ButtonNF.png</texturenofocus>
                    <font>ListDetails</font>
                    <visible>!String.IsEqual(Container(211).ListItem.Property(skinshortcuts-disabled),True)</visible>
                </control>

Also, in my case, all of the menu item properties for widget 2 end in .2, for widget 3 they end in .3, and so on.  I support up to 6 widgets in Amber.

Here's the code for button 312.  Notice that there is no onclick for it, since the script already knows that you configure a widget when you click on this button.  I am not setting a widgetID window property for this button, so all of the widget 1 properties do not have a suffix.  If you want all of your widget 1 properties to be suffixed with .1, then you can set the window property to 1.

xml:

<control type="button" id="312">
                    <label>$LOCALIZE[31491] 1</label>
                    <label2>$INFO[Container(211).ListItem.Property(widgetName)]</label2>
                    <height>60</height>
                    <width>1340</width>
                    <texturenofocus border="3">buttons/ButtonNF.png</texturenofocus>
                    <font>ListDetails</font>
                </control>

Now, here is the code for button 4312, for widget 2.  So, all you need to do is set the window property widgetID to 2 (in this example), and send a click to button 312.  This should allow you to choose what you want for the widget, and the resulting path will be stored in Container(211).ListItem.Property(widgetPath.2).  All of the widget 2 properties will be suffixed with .2

xml:

<control type="button" id="4312">
                    <label>$LOCALIZE[31491] 2</label>
                    <label2>$INFO[Container(211).ListItem.Property(widgetName.2)]</label2>
                    <onclick>SetProperty(widgetID,2)</onclick>
                    <onclick>SendClick(312)</onclick>
                    <height>60</height>
                    <width>1340</width>
                    <texturenofocus border="3">buttons/ButtonNF.png</texturenofocus>
                    <font>ListDetails</font>
                </control>

It is important that you tell script.skinshortcuts where to go back to from any of the buttons you use to configure widget properties, because usually Back will close the management dialog.  You do this in the "overrides.xml" file in the shortcuts folder.  In the example below, I am telling script.skinshortcuts to go back to button 800 from button 312 (back to the Widget 1 button), and to button 801 from button 4312 (back to the Widget 2 button):

xml:

<!-- On backs for management dialog -->
    <onback to="800">312</onback>
    <onback to="801">4312</onback>

In my template.xml, I have an include for each widget (1 through 6).  In Amber, widgets are called shelves, so in the template.xml I have a "shelgroup1" include, a "shelfgroup2" include, and so on.  Here is the start of the include for widget 2:

xml:

<other include="shelfgroup2">
        <!-- Widget condition: a path is needed -->
        <condition tag="property" attribute="name|widgetPath.2" />
        <condition tag="property" attribute="name|widgetContent.2">default</condition>
       <!-- Retrieve id -->
        <property name="id" tag="mainmenuid" />
        <!-- Retrieve properties -->
        <property name="label2" tag="property" attribute="name|widgetName.2" />
        <property name="path2" tag="property" attribute="name|widgetPath.2" />
        <property name="target2" tag="property" attribute="name|widgetTarget.2" />
        <property name="type2" tag="property" attribute="name|widgetType.2" />
        <property name="widget2" tag="property" attribute="name|widget.2" />
        <property name="sortby2" tag="property" attribute="name|widgetSortBy.2" />
        <property name="sortorder2" tag="property" attribute="name|widgetSortOrder.2" />
        <property name="limit2" tag="property" attribute="name|widgetLimit.2" />

So, basically I am telling the script that include "skinshortcuts-template-shelfgroup2" needs to be generated if the menu item has a widgetPath.2 property, and in my case, if the content type (a custom property I created) is set to default (I do this to separate the static-content widgets from the dynamic content widgets; the includes for static widgets are separate).

I get the mainmenu item id, and then I also get all of the widget properties so I can use them in the include.  Sort by, Sort order and Limit are set in the management dialog via separate buttons for each widget.  Feel free to look at the script.skinshortcuts.xml in Amber for working examples.

To display all of my widgets, I do something like the following.  The excerpt is from the "Includes_Horizontal_Home.xml" in Amber:

xml:

<!-- Widgets -->
        <control type="group" id="700">
            <include>skinshortcuts-template-shelfgroup1</include>
            <include>skinshortcuts-template-shelfgroup2</include>
            <include>skinshortcuts-template-shelfgroup3</include>
            <include>skinshortcuts-template-shelfgroup4</include>
            <include>skinshortcuts-template-shelfgroup5</include>
            <include>skinshortcuts-template-shelfgroup6</include>
            <control type="group">
                <include>PVRRecordingWidgets</include>
            </control>
        </control>

As you can see from the above, I include all of my six template includes for my widgets.  Not necessarily each menu items has 6 widgets, or even 1.  The conditions in the template.xml for each widget include determine which ones are generated for which menu item.

I hope this info is useful, and I am more than happy to answer any other questions you might have.

Please bear in mind that this is how I have done things.  I am aware that this is not the most elegant or concise code, but it does work for me.  @jurialmunkey has much more elegant code in his skins, and I think it would be a good idea for you to look at his code to get a better idea of what can be done.  Thanks.

Regards,

Bart
Amber Maintainer
Main HTPC: Intel Core i7, 32GB, nVidia GTX1080, Windows 11 Soundbar: Samsung HW-Q950A TV: LG CX Kodi: 19.3 Skin: Amber
Reply
#17
(2021-07-19, 23:30)bsoriano Wrote: @"nfm886" , here are some excerpts from my script-skinshortcuts.xml that might help:

Next, you will see the buttons I am using for configuring widgets 1 and 2.  As you will see, what I do in these buttons is set the focus to control ID 312 for widget 1, and control id 4312 for widget 2:

xml:

<control type="button" id="800">
              <visible>String.IsEqual(Window.Property(groupname),mainmenu) + !Skin.HasSetting(Hide.AllShelves)</visible>
              <description>Widget</description>
              <label>$LOCALIZE[31491] 1</label>
              <label2>$INFO[Container(211).ListItem.Property(widgetName)]</label2>
              <onfocus condition="!String.IsEmpty(Window(Home).Property(skinshortcuts-Widget))">ClearProperty(skinshortcuts-Widget,Home)</onfocus>
              <onclick>SetProperty(skinshortcuts-Widget,1,Home)</onclick>
              <onclick>Control.SetFocus(312)</onclick>
              <height>60</height>
              <width>1340</width>
              <texturenofocus border="3">buttons/ButtonNF.png</texturenofocus>
              <font>ListDetails</font>
             <visible>!String.IsEqual(Container(211).ListItem.Property(skinshortcuts-disabled),True)</visible>
 </control>
                <control type="button" id="801">
                    <visible>String.IsEqual(Window.Property(groupname),mainmenu) </visible>
                    <description>Widget 2</description>
                    <label>$LOCALIZE[31491] 2</label>
                    <label2>$INFO[Container(211).ListItem.Property(widgetName.2)]</label2>
                    <onfocus condition="!String.IsEmpty(Window(Home).Property(skinshortcuts-Widget))">ClearProperty(skinshortcuts-Widget,Home)</onfocus>
                    <onclick>SetProperty(skinshortcuts-Widget,2,Home)</onclick>
                    <onclick>Control.SetFocus(4312)</onclick>
                    <height>60</height>
                    <width>1340</width>
                    <texturenofocus border="3">buttons/ButtonNF.png</texturenofocus>
                    <font>ListDetails</font>
                    <visible>!String.IsEqual(Container(211).ListItem.Property(skinshortcuts-disabled),True)</visible>
                </control>

Also, in my case, all of the menu item properties for widget 2 end in .2, for widget 3 they end in .3, and so on.  I support up to 6 widgets in Amber.

Here's the code for button 312.  Notice that there is no onclick for it, since the script already knows that you configure a widget when you click on this button.  I am not setting a widgetID window property for this button, so all of the widget 1 properties do not have a suffix.  If you want all of your widget 1 properties to be suffixed with .1, then you can set the window property to 1.

xml:

<control type="button" id="312">
                    <label>$LOCALIZE[31491] 1</label>
                    <label2>$INFO[Container(211).ListItem.Property(widgetName)]</label2>
                    <height>60</height>
                    <width>1340</width>
                    <texturenofocus border="3">buttons/ButtonNF.png</texturenofocus>
                    <font>ListDetails</font>
                </control>

Now, here is the code for button 4312, for widget 2.  So, all you need to do is set the window property widgetID to 2 (in this example), and send a click to button 312.  This should allow you to choose what you want for the widget, and the resulting path will be stored in Container(211).ListItem.Property(widgetPath.2).  All of the widget 2 properties will be suffixed with .2

xml:

<control type="button" id="4312">
                    <label>$LOCALIZE[31491] 2</label>
                    <label2>$INFO[Container(211).ListItem.Property(widgetName.2)]</label2>
                    <onclick>SetProperty(widgetID,2)</onclick>
                    <onclick>SendClick(312)</onclick>
                    <height>60</height>
                    <width>1340</width>
                    <texturenofocus border="3">buttons/ButtonNF.png</texturenofocus>
                    <font>ListDetails</font>
                </control>

It is important that you tell script.skinshortcuts where to go back to from any of the buttons you use to configure widget properties, because usually Back will close the management dialog.  You do this in the "overrides.xml" file in the shortcuts folder.  In the example below, I am telling script.skinshortcuts to go back to button 800 from button 312 (back to the Widget 1 button), and to button 801 from button 4312 (back to the Widget 2 button):

xml:

<!-- On backs for management dialog -->
    <onback to="800">312</onback>
    <onback to="801">4312</onback>

In my template.xml, I have an include for each widget (1 through 6).  In Amber, widgets are called shelves, so in the template.xml I have a "shelgroup1" include, a "shelfgroup2" include, and so on.  Here is the start of the include for widget 2:

xml:

<other include="shelfgroup2">
        <!-- Widget condition: a path is needed -->
        <condition tag="property" attribute="name|widgetPath.2" />
        <condition tag="property" attribute="name|widgetContent.2">default</condition>
       <!-- Retrieve id -->
        <property name="id" tag="mainmenuid" />
        <!-- Retrieve properties -->
        <property name="label2" tag="property" attribute="name|widgetName.2" />
        <property name="path2" tag="property" attribute="name|widgetPath.2" />
        <property name="target2" tag="property" attribute="name|widgetTarget.2" />
        <property name="type2" tag="property" attribute="name|widgetType.2" />
        <property name="widget2" tag="property" attribute="name|widget.2" />
        <property name="sortby2" tag="property" attribute="name|widgetSortBy.2" />
        <property name="sortorder2" tag="property" attribute="name|widgetSortOrder.2" />
        <property name="limit2" tag="property" attribute="name|widgetLimit.2" />

So, basically I am telling the script that include "skinshortcuts-template-shelfgroup2" needs to be generated if the menu item has a widgetPath.2 property, and in my case, if the content type (a custom property I created) is set to default (I do this to separate the static-content widgets from the dynamic content widgets; the includes for static widgets are separate).

I get the mainmenu item id, and then I also get all of the widget properties so I can use them in the include.  Sort by, Sort order and Limit are set in the management dialog via separate buttons for each widget.  Feel free to look at the script.skinshortcuts.xml in Amber for working examples.

To display all of my widgets, I do something like the following.  The excerpt is from the "Includes_Horizontal_Home.xml" in Amber:

xml:

<!-- Widgets -->
        <control type="group" id="700">
            <include>skinshortcuts-template-shelfgroup1</include>
            <include>skinshortcuts-template-shelfgroup2</include>
            <include>skinshortcuts-template-shelfgroup3</include>
            <include>skinshortcuts-template-shelfgroup4</include>
            <include>skinshortcuts-template-shelfgroup5</include>
            <include>skinshortcuts-template-shelfgroup6</include>
            <control type="group">
                <include>PVRRecordingWidgets</include>
            </control>
        </control>

As you can see from the above, I include all of my six template includes for my widgets.  Not necessarily each menu items has 6 widgets, or even 1.  The conditions in the template.xml for each widget include determine which ones are generated for which menu item.

I hope this info is useful, and I am more than happy to answer any other questions you might have.

Please bear in mind that this is how I have done things.  I am aware that this is not the most elegant or concise code, but it does work for me.  @jurialmunkey has much more elegant code in his skins, and I think it would be a good idea for you to look at his code to get a better idea of what can be done.  Thanks.

Regards,

Bart

Hey my friend!
Thank you so much for your explanation.
Yeah, maybe it's not the most elegant way to do this but... I made it support up to 6 widgets in your's way Smile
I see one more thing in log file. 
After opening SkinShortcuts dialog window, it throws some errors:

Code:
2021-07-20 09:48:01.095 T:19546    INFO <general>: Python interpreter stopped
2021-07-20 09:48:11.220 T:19462    INFO <general>: Loading skin file: SkinSettings.xml, load type: LOAD_EVERY_TIME
2021-07-20 09:48:15.212 T:19736    INFO <general>: initializing python engine.
2021-07-20 09:48:15.334 T:19462    INFO <general>: Loading skin file: /home/piotr/.kodi/addons/skin.cosmic/xml/script-skinshortcuts.xml, load type: LOAD_ON_GUI_INIT
2021-07-20 09:48:15.352 T:19736   ERROR <general>: EXCEPTION: Non-Existent Control 111
2021-07-20 09:48:15.355 T:19736   ERROR <general>: EXCEPTION: Non-Existent Control 309
2021-07-20 09:48:15.359 T:19738   ERROR <general>: GetDirectory - Error getting /home/piotr/.kodi/userdata/library/video
2021-07-20 09:48:15.365 T:19738   ERROR <general>: GetDirectory - Error getting /home/piotr/.kodi/userdata/library/music
2021-07-20 09:48:15.374 T:19738   ERROR <general>: GetDirectory - Error getting upnp://
2021-07-20 09:48:15.378 T:19738   ERROR <general>: Traceback (most recent call last):
                                                   
2021-07-20 09:48:15.378 T:19738   ERROR <general>: 
2021-07-20 09:48:15.378 T:19738   ERROR <general>:   File "/home/piotr/.kodi/addons/script.skinshortcuts/resources/lib/library.py", line 971, in playlists
                                                       for line in xmldata.getiterator():
                                                   
2021-07-20 09:48:15.378 T:19738   ERROR <general>: 
2021-07-20 09:48:15.378 T:19738   ERROR <general>: AttributeError: 'xml.etree.ElementTree.Element' object has no attribute 'getiterator'
                                                   
2021-07-20 09:48:15.378 T:19738   ERROR <general>: 
2021-07-20 09:48:15.381 T:19738   ERROR <general>: Traceback (most recent call last):
                                                   
2021-07-20 09:48:15.381 T:19738   ERROR <general>: 
2021-07-20 09:48:15.381 T:19738   ERROR <general>:   File "/home/piotr/.kodi/addons/script.skinshortcuts/resources/lib/library.py", line 971, in playlists
                                                       for line in xmldata.getiterator():
                                                   
2021-07-20 09:48:15.381 T:19738   ERROR <general>: 
2021-07-20 09:48:15.381 T:19738   ERROR <general>: AttributeError: 'xml.etree.ElementTree.Element' object has no attribute 'getiterator'
                                                   
2021-07-20 09:48:15.381 T:19738   ERROR <general>: 
2021-07-20 09:48:15.381 T:19738   ERROR <general>: Traceback (most recent call last):
                                                   
2021-07-20 09:48:15.381 T:19738   ERROR <general>: 
2021-07-20 09:48:15.381 T:19738   ERROR <general>:   File "/home/piotr/.kodi/addons/script.skinshortcuts/resources/lib/library.py", line 971, in playlists
                                                       for line in xmldata.getiterator():
                                                   
2021-07-20 09:48:15.381 T:19738   ERROR <general>: 
2021-07-20 09:48:15.381 T:19738   ERROR <general>: AttributeError: 'xml.etree.ElementTree.Element' object has no attribute 'getiterator'
                                                   
2021-07-20 09:48:15.381 T:19738   ERROR <general>: 
2021-07-20 09:48:15.381 T:19738   ERROR <general>: Traceback (most recent call last):
                                                   
2021-07-20 09:48:15.381 T:19738   ERROR <general>: 
2021-07-20 09:48:15.381 T:19738   ERROR <general>:   File "/home/piotr/.kodi/addons/script.skinshortcuts/resources/lib/library.py", line 971, in playlists
                                                       for line in xmldata.getiterator():
                                                   
2021-07-20 09:48:15.381 T:19738   ERROR <general>: 
2021-07-20 09:48:15.381 T:19738   ERROR <general>: AttributeError: 'xml.etree.ElementTree.Element' object has no attribute 'getiterator'
                                                   
2021-07-20 09:48:15.381 T:19738   ERROR <general>: 
2021-07-20 09:48:15.382 T:19738   ERROR <general>: Traceback (most recent call last):
                                                   
2021-07-20 09:48:15.382 T:19738   ERROR <general>: 
2021-07-20 09:48:15.382 T:19738   ERROR <general>:   File "/home/piotr/.kodi/addons/script.skinshortcuts/resources/lib/library.py", line 971, in playlists
                                                       for line in xmldata.getiterator():
                                                   
2021-07-20 09:48:15.382 T:19738   ERROR <general>: 
2021-07-20 09:48:15.382 T:19738   ERROR <general>: AttributeError: 'xml.etree.ElementTree.Element' object has no attribute 'getiterator'
                                                   
2021-07-20 09:48:15.382 T:19738   ERROR <general>: 
2021-07-20 09:48:15.382 T:19738   ERROR <general>: Traceback (most recent call last):
                                                   
2021-07-20 09:48:15.382 T:19738   ERROR <general>: 
2021-07-20 09:48:15.382 T:19738   ERROR <general>:   File "/home/piotr/.kodi/addons/script.skinshortcuts/resources/lib/library.py", line 971, in playlists
                                                       for line in xmldata.getiterator():
                                                   
2021-07-20 09:48:15.382 T:19738   ERROR <general>: 
2021-07-20 09:48:15.382 T:19738   ERROR <general>: AttributeError: 'xml.etree.ElementTree.Element' object has no attribute 'getiterator'
                                                   
2021-07-20 09:48:15.382 T:19738   ERROR <general>: 
2021-07-20 09:48:15.382 T:19738   ERROR <general>: Traceback (most recent call last):
                                                   
2021-07-20 09:48:15.382 T:19738   ERROR <general>: 
2021-07-20 09:48:15.382 T:19738   ERROR <general>:   File "/home/piotr/.kodi/addons/script.skinshortcuts/resources/lib/library.py", line 971, in playlists
                                                       for line in xmldata.getiterator():
                                                   
2021-07-20 09:48:15.382 T:19738   ERROR <general>: 
2021-07-20 09:48:15.382 T:19738   ERROR <general>: AttributeError: 'xml.etree.ElementTree.Element' object has no attribute 'getiterator'
                                                   
2021-07-20 09:48:15.382 T:19738   ERROR <general>: 
2021-07-20 09:48:15.382 T:19738   ERROR <general>: Traceback (most recent call last):
                                                   
2021-07-20 09:48:15.382 T:19738   ERROR <general>: 
2021-07-20 09:48:15.382 T:19738   ERROR <general>:   File "/home/piotr/.kodi/addons/script.skinshortcuts/resources/lib/library.py", line 971, in playlists
                                                       for line in xmldata.getiterator():
                                                   
2021-07-20 09:48:15.382 T:19738   ERROR <general>: 
2021-07-20 09:48:15.382 T:19738   ERROR <general>: AttributeError: 'xml.etree.ElementTree.Element' object has no attribute 'getiterator'
                                                   
2021-07-20 09:48:15.382 T:19738   ERROR <general>: 
2021-07-20 09:48:15.382 T:19738   ERROR <general>: Traceback (most recent call last):
                                                   
2021-07-20 09:48:15.382 T:19738   ERROR <general>: 
2021-07-20 09:48:15.382 T:19738   ERROR <general>:   File "/home/piotr/.kodi/addons/script.skinshortcuts/resources/lib/library.py", line 971, in playlists
                                                       for line in xmldata.getiterator():
                                                   
2021-07-20 09:48:15.382 T:19738   ERROR <general>: 
2021-07-20 09:48:15.382 T:19738   ERROR <general>: AttributeError: 'xml.etree.ElementTree.Element' object has no attribute 'getiterator'
                                                   
2021-07-20 09:48:15.382 T:19738   ERROR <general>: 
2021-07-20 09:48:15.382 T:19738   ERROR <general>: Traceback (most recent call last):
                                                   
2021-07-20 09:48:15.382 T:19738   ERROR <general>: 
2021-07-20 09:48:15.382 T:19738   ERROR <general>:   File "/home/piotr/.kodi/addons/script.skinshortcuts/resources/lib/library.py", line 971, in playlists
                                                       for line in xmldata.getiterator():
                                                   
2021-07-20 09:48:15.382 T:19738   ERROR <general>: 
2021-07-20 09:48:15.382 T:19738   ERROR <general>: AttributeError: 'xml.etree.ElementTree.Element' object has no attribute 'getiterator'
                                                   
2021-07-20 09:48:15.382 T:19738   ERROR <general>: 
2021-07-20 09:48:15.382 T:19738   ERROR <general>: Traceback (most recent call last):
                                                   
2021-07-20 09:48:15.382 T:19738   ERROR <general>: 
2021-07-20 09:48:15.382 T:19738   ERROR <general>:   File "/home/piotr/.kodi/addons/script.skinshortcuts/resources/lib/library.py", line 971, in playlists
                                                       for line in xmldata.getiterator():
                                                   
2021-07-20 09:48:15.382 T:19738   ERROR <general>: 
2021-07-20 09:48:15.382 T:19738   ERROR <general>: AttributeError: 'xml.etree.ElementTree.Element' object has no attribute 'getiterator'
                                                   
2021-07-20 09:48:15.382 T:19738   ERROR <general>: 
2021-07-20 09:48:15.382 T:19738   ERROR <general>: Traceback (most recent call last):
                                                   
2021-07-20 09:48:15.382 T:19738   ERROR <general>: 
2021-07-20 09:48:15.382 T:19738   ERROR <general>:   File "/home/piotr/.kodi/addons/script.skinshortcuts/resources/lib/library.py", line 971, in playlists
                                                       for line in xmldata.getiterator():
                                                   
2021-07-20 09:48:15.382 T:19738   ERROR <general>: 
2021-07-20 09:48:15.382 T:19738   ERROR <general>: AttributeError: 'xml.etree.ElementTree.Element' object has no attribute 'getiterator'
                                                   
2021-07-20 09:48:15.382 T:19738   ERROR <general>: 
2021-07-20 09:48:15.383 T:19738   ERROR <general>: Traceback (most recent call last):
                                                   
2021-07-20 09:48:15.383 T:19738   ERROR <general>: 
2021-07-20 09:48:15.383 T:19738   ERROR <general>:   File "/home/piotr/.kodi/addons/script.skinshortcuts/resources/lib/library.py", line 971, in playlists
                                                       for line in xmldata.getiterator():
                                                   
2021-07-20 09:48:15.383 T:19738   ERROR <general>: 
2021-07-20 09:48:15.383 T:19738   ERROR <general>: AttributeError: 'xml.etree.ElementTree.Element' object has no attribute 'getiterator'
                                                   
2021-07-20 09:48:15.383 T:19738   ERROR <general>: 
2021-07-20 09:48:15.383 T:19738   ERROR <general>: Traceback (most recent call last):
                                                   
2021-07-20 09:48:15.383 T:19738   ERROR <general>: 
2021-07-20 09:48:15.383 T:19738   ERROR <general>:   File "/home/piotr/.kodi/addons/script.skinshortcuts/resources/lib/library.py", line 971, in playlists
                                                       for line in xmldata.getiterator():
                                                   
2021-07-20 09:48:15.383 T:19738   ERROR <general>: 
2021-07-20 09:48:15.383 T:19738   ERROR <general>: AttributeError: 'xml.etree.ElementTree.Element' object has no attribute 'getiterator'
                                                   
2021-07-20 09:48:15.383 T:19738   ERROR <general>: 

From what I understand, there should be 2 controls more. But, I did not saw it in AZ2 skin and it did not throws any errors. Do I have to put those controls in script-skinshortcuts.xml?

To summarize all, it is the way I did it Smile

buttons:

 
xml:
<control type="button" id="312">
<label>$LOCALIZE[31176]</label>
<label2>$INFO[Container(211).ListItem.Property(widgetName)]</label2>
<include>DialogSettingButton</include>
<visible>String.IsEqual(Window.Property(groupname),mainmenu)</visible>
<visible>!String.IsEqual(Container(211).ListItem.Property(skinshortcuts-disabled),True)</visible>
<include>DialogSettingButton</include>
<visible>!String.EndsWith(Window.Property(groupname),.1)</visible>
</control>

<control type="button" id="2312">
<label>$LOCALIZE[31177]</label>
<label2>$INFO[Container(211).ListItem.Property(widgetName.2)]</label2>
<onclick>SetProperty(widgetID,2)</onclick>
<onclick>SendClick(312)</onclick>
<include>DialogSettingButton</include>
<visible>String.IsEqual(Window.Property(groupname),mainmenu)</visible>
<visible>!String.IsEqual(Container(211).ListItem.Property(skinshortcuts-disabled),True)</visible>
<include>DialogSettingButton</include>
<visible>!String.EndsWith(Window.Property(groupname),.1)</visible>
</control>

<control type="button" id="3312">
<label>$LOCALIZE[31178]</label>
<label2>$INFO[Container(211).ListItem.Property(widgetName.3)]</label2>
<onclick>SetProperty(widgetID,3)</onclick>
<onclick>SendClick(312)</onclick>
<include>DialogSettingButton</include>
<visible>String.IsEqual(Window.Property(groupname),mainmenu)</visible>
<visible>!String.IsEqual(Container(211).ListItem.Property(skinshortcuts-disabled),True)</visible>
<include>DialogSettingButton</include>
<visible>!String.EndsWith(Window.Property(groupname),.1)</visible>
</control>

<control type="button" id="4312">
<label>$LOCALIZE[31179]</label>
<label2>$INFO[Container(211).ListItem.Property(widgetName.4)]</label2>
<onclick>SetProperty(widgetID,4)</onclick>
<onclick>SendClick(312)</onclick>
<include>DialogSettingButton</include>
<visible>String.IsEqual(Window.Property(groupname),mainmenu)</visible>
<visible>!String.IsEqual(Container(211).ListItem.Property(skinshortcuts-disabled),True)</visible>
<include>DialogSettingButton</include>
<visible>!String.EndsWith(Window.Property(groupname),.1)</visible>
</control>

<control type="button" id="5312">
<label>$LOCALIZE[31180]</label>
<label2>$INFO[Container(211).ListItem.Property(widgetName.5)]</label2>
<onclick>SetProperty(widgetID,5)</onclick>
<onclick>SendClick(312)</onclick>
<include>DialogSettingButton</include>
<visible>String.IsEqual(Window.Property(groupname),mainmenu)</visible>
<visible>!String.IsEqual(Container(211).ListItem.Property(skinshortcuts-disabled),True)</visible>
<include>DialogSettingButton</include>
<visible>!String.EndsWith(Window.Property(groupname),.1)</visible>
</control>

<control type="button" id="6312">
<label>$LOCALIZE[31181]</label>
<label2>$INFO[Container(211).ListItem.Property(widgetName.6)]</label2>
<onclick>SetProperty(widgetID,6)</onclick>
<onclick>SendClick(312)</onclick>
<include>DialogSettingButton</include>
<visible>String.IsEqual(Window.Property(groupname),mainmenu)</visible>
<visible>!String.IsEqual(Container(211).ListItem.Property(skinshortcuts-disabled),True)</visible>
<include>DialogSettingButton</include>
<visible>!String.EndsWith(Window.Property(groupname),.1)</visible>
</control>

template

xml:
<other include="widget1">
<condition tag="property" attribute="name|widgetPath" />

<property name="content" tag="property" attribute="name|widgetPath" />
<property name="target" tag="property" attribute="name|widgetTarget" />

<property name="artwork" tag="property" attribute="name|widgetType" value="tvshows">$INFO[ListItem.Art(tvshow.poster)]</property>
<property name="artwork">$INFO[ListItem.Art(poster)]</property>

<controls>
<control type="fixedlist" id="9002">
<onfocus>Notification(Test, $SKINSHORTCUTS[content])</onfocus>
<orientation>horizontal</orientation>
<top>112.5</top>
<onup>9001</onup>
<ondown>9003</ondown>
<onleft>9000</onleft>
<height>400</height>
<include content="Object_Widget_Content">
<param name="image" value="$SKINSHORTCUTS[artwork]" />
</include>
<content target="$SKINSHORTCUTS[target]">$SKINSHORTCUTS[content]</content>
<skinshortcuts>visibility</skinshortcuts>
</control>
</controls>
</other>

<other include="widget2">
<!-- Widget condition: a path is needed -->
<condition tag="property" attribute="name|widgetPath.2" />
<!-- Retrieve id -->
<property name="id" tag="mainmenuid" />
<!-- Retrieve properties -->
<property name="label2" tag="property" attribute="name|widgetName.2" />
<property name="path2" tag="property" attribute="name|widgetPath.2" />
<property name="target2" tag="property" attribute="name|widgetTarget.2" />
<property name="type2" tag="property" attribute="name|widgetType.2" />
<property name="widget2" tag="property" attribute="name|widget.2" />
<property name="sortby2" tag="property" attribute="name|widgetSortBy.2" />
<property name="sortorder2" tag="property" attribute="name|widgetSortOrder.2" />
<property name="limit2" tag="property" attribute="name|widgetLimit.2" />

<property name="artwork" tag="property" attribute="name|widgetType.2" value="tvshows">$INFO[ListItem.Art(tvshow.poster)]</property>
<property name="artwork">$INFO[ListItem.Art(poster)]</property>

<controls>
<control type="fixedlist" id="9003">
<onfocus>Notification(Test, $SKINSHORTCUTS[path2])</onfocus>
<orientation>horizontal</orientation>
<top>212.5</top>
<onup>9002</onup>
<ondown>9004</ondown>
<onleft>9000</onleft>
<height>400</height>
<include content="Object_Widget_Content">
<param name="image" value="$SKINSHORTCUTS[artwork]" />
</include>
<content target="$SKINSHORTCUTS[target2]">$SKINSHORTCUTS[path2]</content>
<skinshortcuts>visibility</skinshortcuts>
</control>
</controls>
</other>

<other include="widget3">
<!-- Widget condition: a path is needed -->
<condition tag="property" attribute="name|widgetPath.3" />
<!-- Retrieve id -->
<property name="id" tag="mainmenuid" />
<!-- Retrieve properties -->
<property name="label3" tag="property" attribute="name|widgetName.3" />
<property name="path3" tag="property" attribute="name|widgetPath.3" />
<property name="target3" tag="property" attribute="name|widgetTarget.3" />
<property name="type3" tag="property" attribute="name|widgetType.3" />
<property name="widget3" tag="property" attribute="name|widget.3" />
<property name="sortby3" tag="property" attribute="name|widgetSortBy.3" />
<property name="sortorder3" tag="property" attribute="name|widgetSortOrder.3" />
<property name="limit3" tag="property" attribute="name|widgetLimit.3" />

<property name="artwork" tag="property" attribute="name|widgetType.3" value="tvshows">$INFO[ListItem.Art(tvshow.poster)]</property>
<property name="artwork">$INFO[ListItem.Art(poster)]</property>

<controls>
<control type="fixedlist" id="9004">
<onfocus>Notification(Test, $SKINSHORTCUTS[path2])</onfocus>
<orientation>horizontal</orientation>
<top>312.5</top>
<onup>9003</onup>
<ondown>9005</ondown>
<onleft>9000</onleft>
<height>400</height>
<include content="Object_Widget_Content">
<param name="image" value="$SKINSHORTCUTS[artwork]" />
</include>
<content target="$SKINSHORTCUTS[target3]">$SKINSHORTCUTS[path3]</content>
<skinshortcuts>visibility</skinshortcuts>
</control>
</controls>
</other>

<other include="widget4">
<!-- Widget condition: a path is needed -->
<condition tag="property" attribute="name|widgetPath.4" />
<!-- Retrieve id -->
<property name="id" tag="mainmenuid" />
<!-- Retrieve properties -->
<property name="label4" tag="property" attribute="name|widgetName.4" />
<property name="path4" tag="property" attribute="name|widgetPath.4" />
<property name="target4" tag="property" attribute="name|widgetTarget.4" />
<property name="type4" tag="property" attribute="name|widgetType.4" />
<property name="widget4" tag="property" attribute="name|widget.4" />
<property name="sortby4" tag="property" attribute="name|widgetSortBy.4" />
<property name="sortorder4" tag="property" attribute="name|widgetSortOrder.4" />
<property name="limit4" tag="property" attribute="name|widgetLimit.4" />

<property name="artwork" tag="property" attribute="name|widgetType.4" value="tvshows">$INFO[ListItem.Art(tvshow.poster)]</property>
<property name="artwork">$INFO[ListItem.Art(poster)]</property>

<controls>
<control type="fixedlist" id="9005">
<onfocus>Notification(Test, $SKINSHORTCUTS[path2])</onfocus>
<orientation>horizontal</orientation>
<top>412.5</top>
<onup>9004</onup>
<ondown>9006</ondown>
<onleft>9000</onleft>
<height>400</height>
<include content="Object_Widget_Content">
<param name="image" value="$SKINSHORTCUTS[artwork]" />
</include>
<content target="$SKINSHORTCUTS[target4]">$SKINSHORTCUTS[path4]</content>
<skinshortcuts>visibility</skinshortcuts>
</control>
</controls>
</other>

<other include="widget5">
<!-- Widget condition: a path is needed -->
<condition tag="property" attribute="name|widgetPath.5" />
<!-- Retrieve id -->
<property name="id" tag="mainmenuid" />
<!-- Retrieve properties -->
<property name="label5" tag="property" attribute="name|widgetName.5" />
<property name="path5" tag="property" attribute="name|widgetPath.5" />
<property name="target5" tag="property" attribute="name|widgetTarget.5" />
<property name="type5" tag="property" attribute="name|widgetType.5" />
<property name="widget5" tag="property" attribute="name|widget.5" />
<property name="sortby5" tag="property" attribute="name|widgetSortBy.5" />
<property name="sortorder5" tag="property" attribute="name|widgetSortOrder.5" />
<property name="limit5" tag="property" attribute="name|widgetLimit.5" />

<property name="artwork" tag="property" attribute="name|widgetType.5" value="tvshows">$INFO[ListItem.Art(tvshow.poster)]</property>
<property name="artwork">$INFO[ListItem.Art(poster)]</property>

<controls>
<control type="fixedlist" id="9006">
<onfocus>Notification(Test, $SKINSHORTCUTS[path2])</onfocus>
<orientation>horizontal</orientation>
<top>512.5</top>
<onup>9005</onup>
<onleft>9000</onleft>
<ondown>9007</ondown>
<height>400</height>
<include content="Object_Widget_Content">
<param name="image" value="$SKINSHORTCUTS[artwork]" />
</include>
<content target="$SKINSHORTCUTS[target5]">$SKINSHORTCUTS[path5]</content>
<skinshortcuts>visibility</skinshortcuts>
</control>
</controls>
</other>

<other include="widget6">
<!-- Widget condition: a path is needed -->
<condition tag="property" attribute="name|widgetPath.6" />
<!-- Retrieve id -->
<property name="id" tag="mainmenuid" />
<!-- Retrieve properties -->
<property name="label6" tag="property" attribute="name|widgetName.6" />
<property name="path6" tag="property" attribute="name|widgetPath.6" />
<property name="target6" tag="property" attribute="name|widgetTarget.6" />
<property name="type6" tag="property" attribute="name|widgetType.6" />
<property name="widget6" tag="property" attribute="name|widget.6" />
<property name="sortby6" tag="property" attribute="name|widgetSortBy.6" />
<property name="sortorder6" tag="property" attribute="name|widgetSortOrder.6" />
<property name="limit6" tag="property" attribute="name|widgetLimit.6" />

<property name="artwork" tag="property" attribute="name|widgetType.6" value="tvshows">$INFO[ListItem.Art(tvshow.poster)]</property>
<property name="artwork">$INFO[ListItem.Art(poster)]</property>

<controls>
<control type="fixedlist" id="9007">
<onfocus>Notification(Test, $SKINSHORTCUTS[path2])</onfocus>
<orientation>horizontal</orientation>
<top>612.6</top>
<onup>9006</onup>
<onleft>9000</onleft>
<height>400</height>
<include content="Object_Widget_Content">
<param name="image" value="$SKINSHORTCUTS[artwork]" />
</include>
<content target="$SKINSHORTCUTS[target6]">$SKINSHORTCUTS[path6]</content>
<skinshortcuts>visibility</skinshortcuts>
</control>
</controls>
</other>

includes

xml:
<control type="group" d="800">
<include>skinshortcuts-template</include>
<include>skinshortcuts-template-widget1</include>
<include>skinshortcuts-template-widget2</include>
<include>skinshortcuts-template-widget3</include>
<include>skinshortcuts-template-widget4</include>
<include>skinshortcuts-template-widget5</include>
<include>skinshortcuts-template-widget6</include>
</control>

Hmm... Now how to solve this: what if I want to set a sort method or limit? My dialog window looks like this: https://imgur.com/P2By9Um so there is no definitely place to put more buttons ^^

Thanks again, my friend, you are the man! Smile
Reply
#18
Maybe a look at the OSMC Skin's dialog might help. It doesn't use buttons for each widget, but simply allows adding an infinite amount of widgets for each home menu item thus not needing a lot of space in the configuration dialog: https://github.com/Ch1llb0/skin.osmc/blo...rtcuts.xml

It looks like this:

Image
OSMC Skinner      |    The OSMC Skin for Kodi v20 Nexus (native 16:9, 21:9 and 4:3 skin, special cinemascope/CIH version available)      |     GitHub: https://github.com/Ch1llb0/skin.osmc
Reply
#19
(2021-07-20, 09:57)nfm886 Wrote: Hmm... Now how to solve this: what if I want to set a sort method or limit? My dialog window looks like this: https://imgur.com/P2By9Um so there is no definitely place to put more buttons ^^

Thanks again, my friend, you are the man! Smile

I have implemented it like this:

watch gallery


Therfore you can use window properties by using <onclick>SetProperty(skinshortcuts-Widget,1,Home)</onclick> for selecting e.g. widget 1 and for the releated buttons/grouplist <visible>String.IsEqual(Window(Home).Property(skinshortcuts-Widget),1)</visible>
Reply
#20
(2021-07-20, 10:16)Chillbo Wrote: Maybe a look at the OSMC Skin's dialog might help. It doesn't use buttons for each widget, but simply allows adding an infinite amount of widgets for each home menu item thus not needing a lot of space in the configuration dialog: https://github.com/Ch1llb0/skin.osmc/blo...rtcuts.xml

It looks like this:

Image

Yes, that's the way I wanted to implement. I had this in AZ2 but could not manage it to work :/ I will look into this code, maybe it will be more clear to do, thanks Smile
Reply
#21
(2021-07-20, 10:16)beatmasterrs Wrote:
(2021-07-20, 09:57)nfm886 Wrote: Hmm... Now how to solve this: what if I want to set a sort method or limit? My dialog window looks like this: https://imgur.com/P2By9Um so there is no definitely place to put more buttons ^^

Thanks again, my friend, you are the man! Smile

I have implemented it like this:

watch gallery


Therfore you can use window properties by using <onclick>SetProperty(skinshortcuts-Widget,1,Home)</onclick> for selecting e.g. widget 1 and for the releated buttons/grouplist <visible>String.IsEqual(Window(Home).Property(skinshortcuts-Widget),1)</visible>
That sounds easy to implement. If I won't find better way I will do this Smile
Reply
#22
We did it boys! Smile
I manage to implement dynamic widgets from OSMC skin. That was kind of easy I think and clear to read Big Grin
Please take a look: https://streamable.com/6k7tmk

Of course I'm sharing the code for future use Wink

buttons:

xml:

<!-- Manage widgets -->
<control type="button" id="406">
<label>$LOCALIZE[31176]</label>
<include>DialogSettingButton</include>
<visible>String.IsEqual(Window.Property(groupname),mainmenu)</visible>
</control>

<!-- Select widget -->
<control type="button" id="312">
<label>$ADDON[script.skinshortcuts 32044]</label>
<label2>$INFO[Container(211).ListItem.Property(widgetName)]</label2>
<include>DialogSettingButton</include>
<visible>String.EndsWith(Window.Property(groupname),.1)</visible>
</control>

<!-- Widget sort by -->
<control type="button" id="502">
<label>$LOCALIZE[31177]</label>
<include>DialogSettingButton</include>
<enable>!String.IsEmpty(Container(211).ListItem.Property(widget))</enable>
<visible>String.EndsWith(Window.Property(groupname),.1)</visible>
<onclick>SetProperty(chooseProperty,widgetSortBy)</onclick>
<onclick>SendClick(404)</onclick>
</control>

<!-- Widget sort direction -->
<control type="button" id="503">
<label>$LOCALIZE[31178]</label>
<include>DialogSettingButton</include>
<enable>!String.IsEmpty(Container(211).ListItem.Property(widget))</enable>
<visible>String.EndsWith(Window.Property(groupname),.1)</visible>
<onclick>SetProperty(chooseProperty,widgetSortDirection)</onclick>
<onclick>SendClick(404)</onclick>
</control>

<!-- Widget limit items -->
<control type="button" id="504">
<label>$LOCALIZE[31179]</label>
<include>DialogSettingButton</include>
<enable>!String.IsEmpty(Container(211).ListItem.Property(widget))</enable>
<visible>String.EndsWith(Window.Property(groupname),.1)</visible>
<onclick>SetProperty(chooseProperty,widgetLimit)</onclick>
<onclick>SendClick(404)</onclick>
</control>
 

template

xml:

<other>
<controls>
<description>This is a fake template which is needed to trick Skin Shortcuts into building the submenuOther templates</description>
</controls>
</other>

<submenuOther include="horizontal" level="1">
<condition tag="property" attribute="name|widgetPath" />

<property name="id" tag="mainmenuid" />
<property name="sortby" tag="property" attribute="name|widgetSortBy" />
<property name="limit" tag="property" attribute="name|widgetLimit" />
<property name="sortdirection" tag="property" attribute="name|widgetSortDirection" />

<propertyGroup>mainmenuWidgets</propertyGroup>

<controls>
<control type="list" id="1$SKINSHORTCUTS[id]00">
<orientation>horizontal</orientation>
<top>$SKINSHORTCUTS[id]12.5</top>
<onup>1$PYTHON[int($SKINSHORTCUTS[id])-1]00</onup>
<ondown>1$PYTHON[int($SKINSHORTCUTS[id])+1]00</ondown>
<onleft>9000</onleft>
<height>400</height>
<include content="Object_Widget_Content">
<param name="label" value="$SKINSHORTCUTS[itemLabel]" />
<param name="image" value="$SKINSHORTCUTS[artwork]" />
</include>
<content limit="$SKINSHORTCUTS[limit]" sortby="$SKINSHORTCUTS[sortby]" sortorder="$SKINSHORTCUTS[sortdirection]" target="$SKINSHORTCUTS[target]">$SKINSHORTCUTS[path]</content>
<skinshortcuts>visibility</skinshortcuts>
</control>
</controls>
</submenuOther>

<propertyGroup name="mainmenuWidgets">
<property name="id" tag="mainmenuid" />
<property name="name" tag="property" attribute="name|widgetName" />
<property name="path" tag="property" attribute="name|widgetPath" />
<property name="target" tag="property" attribute="name|widgetTarget" />
<property name="target"></property>
<property name="path">$INCLUDE[skinshortcuts-group-$SKINSHORTCUTS[submenuVisibility]]</property>

<!-- For TV Shows, we want to specify the artwork as the tv show poster, otherwise we'll use the icon -->
<property name="artwork" tag="property" attribute="name|widgetType" value="tvshows">$INFO[ListItem.Art(tvshow.poster)]</property>
<property name="artwork">$INFO[ListItem.Icon]</property>

<property name="widgetInclude" tag="property" attribute="name|widgetPath">Object_Widget_Content</property>

<property name="submenuVisibility" tag="property" attribute="name|submenuVisibility" />
<property name="label" tag="label" />
<property name="background" tag="property" attribute="name|background" />

</propertyGroup>

includes

xml:

<control type="group" d="800">
<include>skinshortcuts-template</include>
<include>skinshortcuts-template-horizontal</include>
</control>

Thank you, you helped me a lot and I'm learned new stuff Smile
Have a nice day!
Reply
#23
@"nfm886" , way to go! I am glad you got it working as you wanted.  @Chillbo , thank you as well, I will be looking at the OSMC skin code to see how I can adapt it for the skins I am maintaining.

Regards,

Bart
Amber Maintainer
Main HTPC: Intel Core i7, 32GB, nVidia GTX1080, Windows 11 Soundbar: Samsung HW-Q950A TV: LG CX Kodi: 19.3 Skin: Amber
Reply
#24
(2021-07-20, 15:57)bsoriano Wrote: @"nfm886" , way to go! I am glad you got it working as you wanted.  @Chillbo , thank you as well, I will be looking at the OSMC skin code to see how I can adapt it for the skins I am maintaining.

Regards,

Bart
Thank you my friend Smile
Could you please look at this error: https://forum.kodi.tv/showthread.php?tid...pid3050429
I'm trying to figure it out but no luck so far... Sad
Reply
#25
(2021-07-20, 16:08)nfm886 Wrote:
(2021-07-20, 15:57)bsoriano Wrote: @"nfm886" , way to go! I am glad you got it working as you wanted.  @Chillbo , thank you as well, I will be looking at the OSMC skin code to see how I can adapt it for the skins I am maintaining.

Regards,

Bart
Thank you my friend Smile
Could you please look at this error: https://forum.kodi.tv/showthread.php?tid...pid3050429
I'm trying to figure it out but no luck so far... Sad
@"nfm886" , what version of skinshortcuts are you using? The latest should be 1.1.5 from the Kodi Matrix repo.  I ask just in case that you are not using that version, since I have not seen that error before.

Regards,

Bart
Amber Maintainer
Main HTPC: Intel Core i7, 32GB, nVidia GTX1080, Windows 11 Soundbar: Samsung HW-Q950A TV: LG CX Kodi: 19.3 Skin: Amber
Reply
#26
(2021-07-20, 16:41)bsoriano Wrote:
(2021-07-20, 16:08)nfm886 Wrote:
(2021-07-20, 15:57)bsoriano Wrote: @"nfm886" , way to go! I am glad you got it working as you wanted.  @Chillbo , thank you as well, I will be looking at the OSMC skin code to see how I can adapt it for the skins I am maintaining.

Regards,

Bart
Thank you my friend Smile
Could you please look at this error: https://forum.kodi.tv/showthread.php?tid...pid3050429
I'm trying to figure it out but no luck so far... Sad
@"nfm886" , what version of skinshortcuts are you using? The latest should be 1.1.5 from the Kodi Matrix repo.  I ask just in case that you are not using that version, since I have not seen that error before.

Regards,

Bart
It's 1.1.5. Hmm... Maybe I will try with another fresh install.

#edit
Unfortunately, fresh install did not resolve the issue.
Maybe @mikeSiLVO can say something about it?
Reply

Logout Mark Read Team Forum Stats Members Help
[solved] How to handle multiple widgets with script skinshortcuts?0