control center update
|
@ -8,6 +8,7 @@
|
||||||
<import addon="script.module.torrent2http"/>
|
<import addon="script.module.torrent2http"/>
|
||||||
<import addon="script.module.pyrrent2http"/>
|
<import addon="script.module.pyrrent2http"/>
|
||||||
<import addon="script.module.chardet" />
|
<import addon="script.module.chardet" />
|
||||||
|
<import addon="script.module.pyxbmct" version="1.2.0"/>
|
||||||
</requires>
|
</requires>
|
||||||
<extension point="xbmc.python.pluginsource" provides="video" library="default.py">
|
<extension point="xbmc.python.pluginsource" provides="video" library="default.py">
|
||||||
<provides>video</provides>
|
<provides>video</provides>
|
||||||
|
|
|
@ -24,7 +24,7 @@ import xbmcaddon
|
||||||
import xbmc
|
import xbmc
|
||||||
import xbmcgui
|
import xbmcgui
|
||||||
from functions import getParameters, HistoryDB, Searchers, log
|
from functions import getParameters, HistoryDB, Searchers, log
|
||||||
from resources.pyxbmct.addonwindow import *
|
import pyxbmct
|
||||||
|
|
||||||
__settings__ = xbmcaddon.Addon(id='plugin.video.torrenter')
|
__settings__ = xbmcaddon.Addon(id='plugin.video.torrenter')
|
||||||
__language__ = __settings__.getLocalizedString
|
__language__ = __settings__.getLocalizedString
|
||||||
|
@ -39,7 +39,7 @@ if len(sys.argv) > 1:
|
||||||
else:
|
else:
|
||||||
params = {}
|
params = {}
|
||||||
|
|
||||||
class ControlCenter(AddonDialogWindow):
|
class ControlCenter(pyxbmct.AddonDialogWindow):
|
||||||
def __init__(self, title, addtime=None):
|
def __init__(self, title, addtime=None):
|
||||||
super(ControlCenter, self).__init__(title)
|
super(ControlCenter, self).__init__(title)
|
||||||
|
|
||||||
|
@ -57,18 +57,17 @@ class ControlCenter(AddonDialogWindow):
|
||||||
if not providers:
|
if not providers:
|
||||||
self.db.set_providers(addtime, self.dic)
|
self.db.set_providers(addtime, self.dic)
|
||||||
else:
|
else:
|
||||||
for searcher in self.keys:
|
for searcher in self.dic.keys():
|
||||||
self.dic[searcher] = False
|
self.dic[searcher] = False
|
||||||
for searcher in providers:
|
for searcher in providers:
|
||||||
try:
|
try:
|
||||||
if searcher in self.keys:
|
if searcher in self.dic.keys():
|
||||||
self.dic[searcher] = True
|
self.dic[searcher] = True
|
||||||
except:
|
except:
|
||||||
pass
|
log('self.dic[searcher] except')
|
||||||
|
|
||||||
self.keys = self.dic.keys()
|
self.keys = self.dic.keys()
|
||||||
self.placed, self.button_columns, self.last_column_row = self.place()
|
self.placed, self.button_columns, self.last_column_row = self.place()
|
||||||
#print str((self.placed, self.button_columns, self.last_column_row))
|
|
||||||
else:
|
else:
|
||||||
self.button_columns=0
|
self.button_columns=0
|
||||||
|
|
||||||
|
@ -78,7 +77,7 @@ class ControlCenter(AddonDialogWindow):
|
||||||
self.set_active_controls()
|
self.set_active_controls()
|
||||||
self.set_navigation()
|
self.set_navigation()
|
||||||
# Connect a key action (Backspace) to close the window.
|
# Connect a key action (Backspace) to close the window.
|
||||||
self.connect(ACTION_NAV_BACK, self.close)
|
self.connect(pyxbmct.ACTION_NAV_BACK, self.close)
|
||||||
|
|
||||||
def place(self):
|
def place(self):
|
||||||
placed = {}
|
placed = {}
|
||||||
|
@ -90,7 +89,6 @@ class ControlCenter(AddonDialogWindow):
|
||||||
else:
|
else:
|
||||||
i += 1
|
i += 1
|
||||||
placed[item] = (j, i)
|
placed[item] = (j, i)
|
||||||
#print item+str((j, i))
|
|
||||||
return placed, j, i
|
return placed, j, i
|
||||||
|
|
||||||
def set_info_controls(self):
|
def set_info_controls(self):
|
||||||
|
@ -103,7 +101,7 @@ class ControlCenter(AddonDialogWindow):
|
||||||
self.radiobutton_top, self.radiobutton_bottom = [None, None, None], [None, None, None]
|
self.radiobutton_top, self.radiobutton_bottom = [None, None, None], [None, None, None]
|
||||||
for searcher in self.keys:
|
for searcher in self.keys:
|
||||||
place = self.placed[searcher]
|
place = self.placed[searcher]
|
||||||
self.radiobutton[searcher] = RadioButton(searcher)
|
self.radiobutton[searcher] = pyxbmct.RadioButton(searcher)
|
||||||
self.placeControl(self.radiobutton[searcher], place[0], place[1])
|
self.placeControl(self.radiobutton[searcher], place[0], place[1])
|
||||||
self.radiobutton[searcher].setSelected(self.dic[searcher])
|
self.radiobutton[searcher].setSelected(self.dic[searcher])
|
||||||
self.connect(self.radiobutton[searcher], self.radio_update)
|
self.connect(self.radiobutton[searcher], self.radio_update)
|
||||||
|
@ -112,32 +110,32 @@ class ControlCenter(AddonDialogWindow):
|
||||||
self.radiobutton_bottom[place[1]] = self.radiobutton[searcher]
|
self.radiobutton_bottom[place[1]] = self.radiobutton[searcher]
|
||||||
|
|
||||||
# Button
|
# Button
|
||||||
self.button_install = Button(__language__(30415))
|
self.button_install = pyxbmct.Button(__language__(30415))
|
||||||
self.placeControl(self.button_install, 2 + self.button_columns, 0)
|
self.placeControl(self.button_install, 2 + self.button_columns, 0)
|
||||||
self.connect(self.button_install, self.installSearcher)
|
self.connect(self.button_install, self.installSearcher)
|
||||||
|
|
||||||
# Button
|
# Button
|
||||||
self.button_openserchset = Button(__language__(30416))
|
self.button_openserchset = pyxbmct.Button(__language__(30416))
|
||||||
self.placeControl(self.button_openserchset, 2 + self.button_columns, 1)
|
self.placeControl(self.button_openserchset, 2 + self.button_columns, 1)
|
||||||
self.connect(self.button_openserchset, self.openSearcherSettings)
|
self.connect(self.button_openserchset, self.openSearcherSettings)
|
||||||
|
|
||||||
# Button
|
# Button
|
||||||
self.button_clearstor = Button(__language__(30417))
|
self.button_clearstor = pyxbmct.Button(__language__(30417))
|
||||||
self.placeControl(self.button_clearstor, 2 + self.button_columns, 2)
|
self.placeControl(self.button_clearstor, 2 + self.button_columns, 2)
|
||||||
self.connect(self.button_clearstor, self.clearStorage)
|
self.connect(self.button_clearstor, self.clearStorage)
|
||||||
|
|
||||||
# Button
|
# Button
|
||||||
self.button_openset = Button(__language__(30413))
|
self.button_openset = pyxbmct.Button(__language__(30413))
|
||||||
self.placeControl(self.button_openset, 3 + self.button_columns, 0)
|
self.placeControl(self.button_openset, 3 + self.button_columns, 0)
|
||||||
self.connect(self.button_openset, self.openSettings)
|
self.connect(self.button_openset, self.openSettings)
|
||||||
|
|
||||||
# Button
|
# Button
|
||||||
self.button_utorrent = Button(__language__(30414))
|
self.button_utorrent = pyxbmct.Button(__language__(30414))
|
||||||
self.placeControl(self.button_utorrent, 3 + self.button_columns, 1)
|
self.placeControl(self.button_utorrent, 3 + self.button_columns, 1)
|
||||||
self.connect(self.button_utorrent, self.openUtorrent)
|
self.connect(self.button_utorrent, self.openUtorrent)
|
||||||
|
|
||||||
# Button
|
# Button
|
||||||
self.button_close = Button(__language__(30412))
|
self.button_close = pyxbmct.Button(__language__(30412))
|
||||||
self.placeControl(self.button_close, 3 + self.button_columns, 2)
|
self.placeControl(self.button_close, 3 + self.button_columns, 2)
|
||||||
self.connect(self.button_close, self.close)
|
self.connect(self.button_close, self.close)
|
||||||
|
|
||||||
|
@ -171,8 +169,6 @@ class ControlCenter(AddonDialogWindow):
|
||||||
ser = placed_keys[placed_values.index((place[0], place[1] - 1))]
|
ser = placed_keys[placed_values.index((place[0], place[1] - 1))]
|
||||||
self.radiobutton[searcher].controlLeft(self.radiobutton[ser])
|
self.radiobutton[searcher].controlLeft(self.radiobutton[ser])
|
||||||
|
|
||||||
#print str((self.button_columns, self.last_column_row))
|
|
||||||
#print searcher
|
|
||||||
if self.more_two_searcher:
|
if self.more_two_searcher:
|
||||||
if place == (self.button_columns, self.last_column_row) and self.last_column_row < 2:
|
if place == (self.button_columns, self.last_column_row) and self.last_column_row < 2:
|
||||||
ser = placed_keys[placed_values.index((place[0] - 1, place[1] + 1))]
|
ser = placed_keys[placed_values.index((place[0] - 1, place[1] + 1))]
|
||||||
|
@ -247,7 +243,10 @@ class ControlCenter(AddonDialogWindow):
|
||||||
def openSearcherSettings(self):
|
def openSearcherSettings(self):
|
||||||
slist=Searchers().activeExternal()
|
slist=Searchers().activeExternal()
|
||||||
if len(slist)>0:
|
if len(slist)>0:
|
||||||
ret = xbmcgui.Dialog().select(__language__(30418), slist)
|
if len(slist) == 1:
|
||||||
|
ret = 0
|
||||||
|
else:
|
||||||
|
ret = xbmcgui.Dialog().select(__language__(30418), slist)
|
||||||
if ret > -1 and ret < len(slist):
|
if ret > -1 and ret < len(slist):
|
||||||
sid = slist[ret]
|
sid = slist[ret]
|
||||||
Searcher=xbmcaddon.Addon(id='torrenter.searcher.'+sid)
|
Searcher=xbmcaddon.Addon(id='torrenter.searcher.'+sid)
|
||||||
|
|
|
@ -917,7 +917,6 @@ class HistoryDB:
|
||||||
self.cur.execute('select providers from history where addtime="' + addtime + '"')
|
self.cur.execute('select providers from history where addtime="' + addtime + '"')
|
||||||
x = self.cur.fetchone()
|
x = self.cur.fetchone()
|
||||||
self._close()
|
self._close()
|
||||||
# print 'get_providers: '+str(x[0].split(',') if x and x[0]!='' else None)
|
|
||||||
return x[0].split(',') if x and x[0] != '' else None
|
return x[0].split(',') if x and x[0] != '' else None
|
||||||
|
|
||||||
def set_providers(self, addtime, providers):
|
def set_providers(self, addtime, providers):
|
||||||
|
@ -934,7 +933,7 @@ class HistoryDB:
|
||||||
self._close()
|
self._close()
|
||||||
|
|
||||||
def change_providers(self, addtime, searcher):
|
def change_providers(self, addtime, searcher):
|
||||||
self._connect()
|
#self._connect()
|
||||||
providers = self.get_providers(addtime)
|
providers = self.get_providers(addtime)
|
||||||
keys = Searchers().dic().keys()
|
keys = Searchers().dic().keys()
|
||||||
if providers and len(providers) > 0:
|
if providers and len(providers) > 0:
|
||||||
|
@ -946,8 +945,8 @@ class HistoryDB:
|
||||||
if i not in keys:
|
if i not in keys:
|
||||||
providers.remove(i)
|
providers.remove(i)
|
||||||
self.set_providers(addtime, providers)
|
self.set_providers(addtime, providers)
|
||||||
self.db.commit()
|
#self.db.commit()
|
||||||
self._close()
|
#self._close()
|
||||||
|
|
||||||
def add(self, url):
|
def add(self, url):
|
||||||
self._connect()
|
self._connect()
|
||||||
|
|
|
@ -82,21 +82,21 @@ class KickAssSo(Content.Content):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def get_contentList(self, category, subcategory=None, apps_property=None):
|
def get_contentList(self, category, subcategory=None, apps_property=None):
|
||||||
|
self.debug = self.log
|
||||||
contentList = []
|
contentList = []
|
||||||
url = self.get_url(category, subcategory, apps_property)
|
url = self.get_url(category, subcategory, apps_property)
|
||||||
|
|
||||||
response = self.makeRequest(url, headers=self.headers)
|
response = self.makeRequest(url, headers=self.headers)
|
||||||
|
|
||||||
if None != response and 0 < len(response):
|
if None != response and 0 < len(response):
|
||||||
# print response
|
self.debug(response)
|
||||||
if category:
|
if category:
|
||||||
contentList = self.mode(response)
|
contentList = self.mode(response)
|
||||||
# print str(contentList)
|
self.debug(str(contentList))
|
||||||
return contentList
|
return contentList
|
||||||
|
|
||||||
def mode(self, response):
|
def mode(self, response):
|
||||||
contentList = []
|
contentList = []
|
||||||
# print str(result)
|
|
||||||
num = 51
|
num = 51
|
||||||
good_forums = ['TV', 'Anime', 'Movies']
|
good_forums = ['TV', 'Anime', 'Movies']
|
||||||
regex = '''<tr class=".+?" id=.+?</tr>'''
|
regex = '''<tr class=".+?" id=.+?</tr>'''
|
||||||
|
@ -129,6 +129,7 @@ class KickAssSo(Content.Content):
|
||||||
return contentList
|
return contentList
|
||||||
|
|
||||||
def get_info(self, url):
|
def get_info(self, url):
|
||||||
|
self.debug = self.log
|
||||||
movieInfo = {}
|
movieInfo = {}
|
||||||
color = '[COLOR blue]%s:[/COLOR] %s\r\n'
|
color = '[COLOR blue]%s:[/COLOR] %s\r\n'
|
||||||
response = self.makeRequest(url, headers=self.headers)
|
response = self.makeRequest(url, headers=self.headers)
|
||||||
|
@ -190,7 +191,5 @@ class KickAssSo(Content.Content):
|
||||||
if i == 'IMDb link':
|
if i == 'IMDb link':
|
||||||
movieInfo['kinopoisk'] = 'http://imdb.snick.ru/ratefor/02/tt%s.png' % info.get(i)
|
movieInfo['kinopoisk'] = 'http://imdb.snick.ru/ratefor/02/tt%s.png' % info.get(i)
|
||||||
|
|
||||||
|
self.debug(str(movieInfo))
|
||||||
# print str(info)
|
|
||||||
|
|
||||||
return movieInfo
|
return movieInfo
|
||||||
|
|
|
@ -1,786 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
# This is a "local" version of PyXBMCt to be used in standalone addons.
|
|
||||||
#
|
|
||||||
# PyXBMCt is a mini-framework for creating XBMC Python addons with arbitrary UI
|
|
||||||
# made of controls - decendants of xbmcgui.Control class.
|
|
||||||
# The framework uses image textures from XBMC Confluence skin.
|
|
||||||
#
|
|
||||||
# Licence: GPL v.3 http://www.gnu.org/licenses/gpl.html
|
|
||||||
#
|
|
||||||
## @package addonwindow
|
|
||||||
# PyXBMCt framework module
|
|
||||||
|
|
||||||
import os
|
|
||||||
|
|
||||||
import xbmc
|
|
||||||
import xbmcgui
|
|
||||||
|
|
||||||
|
|
||||||
# _addon = xbmcaddon.Addon()
|
|
||||||
_images = os.path.join(os.path.dirname(__file__), 'textures', 'default')
|
|
||||||
|
|
||||||
|
|
||||||
# Text alighnment constants. Mixed variants are obtained by bit OR (|)
|
|
||||||
ALIGN_LEFT = 0
|
|
||||||
ALIGN_RIGHT = 1
|
|
||||||
ALIGN_CENTER_X = 2
|
|
||||||
ALIGN_CENTER_Y = 4
|
|
||||||
ALIGN_CENTER = 6
|
|
||||||
ALIGN_TRUNCATED = 8
|
|
||||||
ALIGN_JUSTIFY = 10
|
|
||||||
|
|
||||||
# XBMC key action codes.
|
|
||||||
# More codes at https://github.com/xbmc/xbmc/blob/master/xbmc/guilib/Key.h
|
|
||||||
## ESC action
|
|
||||||
ACTION_PREVIOUS_MENU = 10
|
|
||||||
## Backspace action
|
|
||||||
ACTION_NAV_BACK = 92
|
|
||||||
## Left arrow key
|
|
||||||
ACTION_MOVE_LEFT = 1
|
|
||||||
## Right arrow key
|
|
||||||
ACTION_MOVE_RIGHT = 2
|
|
||||||
## Up arrow key
|
|
||||||
ACTION_MOVE_UP = 3
|
|
||||||
## Down arrow key
|
|
||||||
ACTION_MOVE_DOWN = 4
|
|
||||||
## Mouse wheel up
|
|
||||||
ACTION_MOUSE_WHEEL_UP = 104
|
|
||||||
## Mouse wheel down
|
|
||||||
ACTION_MOUSE_WHEEL_DOWN = 105
|
|
||||||
## Mouse drag
|
|
||||||
ACTION_MOUSE_DRAG = 106
|
|
||||||
## Mouse move
|
|
||||||
ACTION_MOUSE_MOVE = 107
|
|
||||||
|
|
||||||
|
|
||||||
def _set_textures(textures={}, kwargs={}):
|
|
||||||
"""Set texture arguments for controls."""
|
|
||||||
for texture in textures.keys():
|
|
||||||
try:
|
|
||||||
kwargs[texture]
|
|
||||||
except KeyError:
|
|
||||||
kwargs[texture] = textures[texture]
|
|
||||||
|
|
||||||
|
|
||||||
class AddonWindowError(Exception):
|
|
||||||
"""Custom exception."""
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class Label(xbmcgui.ControlLabel):
|
|
||||||
"""ControlLabel class.
|
|
||||||
|
|
||||||
Parameters:
|
|
||||||
label: string or unicode - text string.
|
|
||||||
font: string - font used for label text. (e.g. 'font13')
|
|
||||||
textColor: hexstring - color of enabled label's label. (e.g. '0xFFFFFFFF')
|
|
||||||
disabledColor: hexstring - color of disabled label's label. (e.g. '0xFFFF3300')
|
|
||||||
alignment: integer - alignment of label - *Note, see xbfont.h
|
|
||||||
hasPath: bool - True=stores a path / False=no path.
|
|
||||||
angle: integer - angle of control. (+ rotates CCW, - rotates CW)"
|
|
||||||
|
|
||||||
Note:
|
|
||||||
After you create the control, you need to add it to the window with placeControl().
|
|
||||||
|
|
||||||
Example:
|
|
||||||
self.label = Label('Status', angle=45)
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __new__(cls, *args, **kwargs):
|
|
||||||
return super(Label, cls).__new__(cls, -10, -10, 1, 1, *args, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class FadeLabel(xbmcgui.ControlFadeLabel):
|
|
||||||
"""Control that scrolls label text.
|
|
||||||
|
|
||||||
Parameters:
|
|
||||||
font: string - font used for label text. (e.g. 'font13')
|
|
||||||
textColor: hexstring - color of fadelabel's labels. (e.g. '0xFFFFFFFF')
|
|
||||||
_alignment: integer - alignment of label - *Note, see xbfont.h
|
|
||||||
|
|
||||||
Note:
|
|
||||||
After you create the control, you need to add it to the window with placeControl().
|
|
||||||
|
|
||||||
Example:
|
|
||||||
self.fadelabel = FadeLabel(textColor='0xFFFFFFFF')
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __new__(cls, *args, **kwargs):
|
|
||||||
return super(FadeLabel, cls).__new__(cls, -10, -10, 1, 1, *args, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class TextBox(xbmcgui.ControlTextBox):
|
|
||||||
"""ControlTextBox class.
|
|
||||||
|
|
||||||
Parameters:
|
|
||||||
font: string - font used for text. (e.g. 'font13')
|
|
||||||
textColor: hexstring - color of textbox's text. (e.g. '0xFFFFFFFF')
|
|
||||||
|
|
||||||
Note:
|
|
||||||
After you create the control, you need to add it to the window with placeControl().
|
|
||||||
|
|
||||||
Example:
|
|
||||||
self.textbox = TextBox(textColor='0xFFFFFFFF')
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __new__(cls, *args, **kwargs):
|
|
||||||
return super(TextBox, cls).__new__(cls, -10, -10, 1, 1, *args, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class Image(xbmcgui.ControlImage):
|
|
||||||
"""ControlImage class.
|
|
||||||
|
|
||||||
Parameters:
|
|
||||||
filename: string - image filename.
|
|
||||||
colorKey: hexString - (example, '0xFFFF3300')
|
|
||||||
aspectRatio: integer - (values 0 = stretch (default), 1 = scale up (crops), 2 = scale down (black bars)
|
|
||||||
colorDiffuse: hexString - (example, '0xC0FF0000' (red tint)).
|
|
||||||
|
|
||||||
Note:
|
|
||||||
After you create the control, you need to add it to the window with placeControl().
|
|
||||||
|
|
||||||
Example:
|
|
||||||
self.image = Image('d:\images\picture.jpg', aspectRatio=2)
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __new__(cls, *args, **kwargs):
|
|
||||||
return super(Image, cls).__new__(cls, -10, -10, 1, 1, *args, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class Button(xbmcgui.ControlButton):
|
|
||||||
"""ControlButton class.
|
|
||||||
|
|
||||||
Parameters:
|
|
||||||
label: string or unicode - text string.
|
|
||||||
focusTexture: string - filename for focus texture.
|
|
||||||
noFocusTexture: string - filename for no focus texture.
|
|
||||||
textOffsetX: integer - x offset of label.
|
|
||||||
textOffsetY: integer - y offset of label.
|
|
||||||
alignment: integer - alignment of label - *Note, see xbfont.h
|
|
||||||
font: string - font used for label text. (e.g. 'font13')
|
|
||||||
textColor: hexstring - color of enabled button's label. (e.g. '0xFFFFFFFF')
|
|
||||||
disabledColor: hexstring - color of disabled button's label. (e.g. '0xFFFF3300')
|
|
||||||
angle: integer - angle of control. (+ rotates CCW, - rotates CW)
|
|
||||||
shadowColor: hexstring - color of button's label's shadow. (e.g. '0xFF000000')
|
|
||||||
focusedColor: hexstring - color of focused button's label. (e.g. '0xFF00FFFF')
|
|
||||||
|
|
||||||
Note:
|
|
||||||
After you create the control, you need to add it to the window with placeControl().
|
|
||||||
|
|
||||||
Example:
|
|
||||||
self.button = Button('Status', font='font14')
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __new__(cls, *args, **kwargs):
|
|
||||||
textures = {'focusTexture': os.path.join(_images, 'Button', 'KeyboardKey.png'),
|
|
||||||
'noFocusTexture': os.path.join(_images, 'Button', 'KeyboardKeyNF.png')}
|
|
||||||
_set_textures(textures, kwargs)
|
|
||||||
try:
|
|
||||||
kwargs['alignment']
|
|
||||||
except KeyError:
|
|
||||||
kwargs['alignment'] = ALIGN_CENTER
|
|
||||||
return super(Button, cls).__new__(cls, -10, -10, 1, 1, *args, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class RadioButton(xbmcgui.ControlRadioButton):
|
|
||||||
"""ControlRadioButton class.
|
|
||||||
|
|
||||||
Parameters:
|
|
||||||
label: string or unicode - text string.
|
|
||||||
focusTexture: string - filename for focus texture.
|
|
||||||
noFocusTexture: string - filename for no focus texture.
|
|
||||||
textOffsetX: integer - x offset of label.
|
|
||||||
textOffsetY: integer - y offset of label.
|
|
||||||
_alignment: integer - alignment of label - *Note, see xbfont.h
|
|
||||||
font: string - font used for label text. (e.g. 'font13')
|
|
||||||
textColor: hexstring - color of enabled radio button's label. (e.g. '0xFFFFFFFF')
|
|
||||||
disabledColor: hexstring - color of disabled radio button's label. (e.g. '0xFFFF3300')
|
|
||||||
angle: integer - angle of control. (+ rotates CCW, - rotates CW)
|
|
||||||
shadowColor: hexstring - color of radio button's label's shadow. (e.g. '0xFF000000')
|
|
||||||
focusedColor: hexstring - color of focused radio button's label. (e.g. '0xFF00FFFF')
|
|
||||||
focusOnTexture: string - filename for radio focused/checked texture.
|
|
||||||
noFocusOnTexture: string - filename for radio not focused/checked texture.
|
|
||||||
focusOffTexture: string - filename for radio focused/unchecked texture.
|
|
||||||
noFocusOffTexture: string - filename for radio not focused/unchecked texture.
|
|
||||||
Note: To customize RadioButton all 4 abovementioned textures need to be provided.
|
|
||||||
|
|
||||||
Note:
|
|
||||||
After you create the control, you need to add it to the window with placeControl().
|
|
||||||
|
|
||||||
Example:
|
|
||||||
self.radiobutton = RadioButton('Status', font='font14')
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __new__(cls, *args, **kwargs):
|
|
||||||
if int(xbmc.getInfoLabel('System.BuildVersion')[:2]) >= 13:
|
|
||||||
textures = {'focusTexture': os.path.join(_images, 'RadioButton', 'MenuItemFO.png'),
|
|
||||||
'noFocusTexture': os.path.join(_images, 'RadioButton', 'MenuItemNF.png'),
|
|
||||||
'focusOnTexture': os.path.join(_images, 'RadioButton', 'radiobutton-focus.png'),
|
|
||||||
'noFocusOnTexture': os.path.join(_images, 'RadioButton', 'radiobutton-focus.png'),
|
|
||||||
'focusOffTexture': os.path.join(_images, 'RadioButton', 'radiobutton-nofocus.png'),
|
|
||||||
'noFocusOffTexture': os.path.join(_images, 'RadioButton', 'radiobutton-nofocus.png')}
|
|
||||||
else: # This is for compatibility with Frodo and earlier versions.
|
|
||||||
textures = {'focusTexture': os.path.join(_images, 'RadioButton', 'MenuItemFO.png'),
|
|
||||||
'noFocusTexture': os.path.join(_images, 'RadioButton', 'MenuItemNF.png'),
|
|
||||||
'TextureRadioFocus': os.path.join(_images, 'RadioButton', 'radiobutton-focus.png'),
|
|
||||||
'TextureRadioNoFocus': os.path.join(_images, 'RadioButton', 'radiobutton-nofocus.png')}
|
|
||||||
_set_textures(textures, kwargs)
|
|
||||||
return super(RadioButton, cls).__new__(cls, -10, -10, 1, 1, *args, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class Edit(xbmcgui.ControlEdit):
|
|
||||||
"""
|
|
||||||
ControlEdit class.
|
|
||||||
|
|
||||||
Edit(label[, font, textColor, disabledColor, alignment, focusTexture, noFocusTexture])
|
|
||||||
|
|
||||||
Parameters:
|
|
||||||
label : string or unicode - text string.
|
|
||||||
font : [opt] string - font used for label text. (e.g. 'font13')
|
|
||||||
textColor : [opt] hexstring - color of enabled label's label. (e.g. '0xFFFFFFFF')
|
|
||||||
disabledColor : [opt] hexstring - color of disabled label's label. (e.g. '0xFFFF3300')
|
|
||||||
_alignment : [opt] integer - alignment of label - *Note, see xbfont.h
|
|
||||||
focusTexture : [opt] string - filename for focus texture.
|
|
||||||
noFocusTexture : [opt] string - filename for no focus texture.
|
|
||||||
isPassword : [opt] bool - if true, mask text value.
|
|
||||||
|
|
||||||
*Note, You can use the above as keywords for arguments and skip certain optional arguments.
|
|
||||||
Once you use a keyword, all following arguments require the keyword.
|
|
||||||
After you create the control, you need to add it to the window with palceControl().
|
|
||||||
|
|
||||||
example:
|
|
||||||
- self.edit = Edit('Status')
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __new__(cls, *args, **kwargs):
|
|
||||||
textures = {'focusTexture': os.path.join(_images, 'Edit', 'button-focus.png'),
|
|
||||||
'noFocusTexture': os.path.join(_images, 'Edit', 'black-back2.png')}
|
|
||||||
_set_textures(textures, kwargs)
|
|
||||||
return super(Edit, cls).__new__(cls, -10, -10, 1, 1, *args, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class List(xbmcgui.ControlList):
|
|
||||||
"""ControlList class.
|
|
||||||
|
|
||||||
Parameters:
|
|
||||||
font: string - font used for items label. (e.g. 'font13')
|
|
||||||
textColor: hexstring - color of items label. (e.g. '0xFFFFFFFF')
|
|
||||||
buttonTexture: string - filename for no focus texture.
|
|
||||||
buttonFocusTexture: string - filename for focus texture.
|
|
||||||
selectedColor: integer - x offset of label.
|
|
||||||
_imageWidth: integer - width of items icon or thumbnail.
|
|
||||||
_imageHeight: integer - height of items icon or thumbnail.
|
|
||||||
_itemTextXOffset: integer - x offset of items label.
|
|
||||||
_itemTextYOffset: integer - y offset of items label.
|
|
||||||
_itemHeight: integer - height of items.
|
|
||||||
_space: integer - space between items.
|
|
||||||
_alignmentY: integer - Y-axis alignment of items label - *Note, see xbfont.h
|
|
||||||
|
|
||||||
Note:
|
|
||||||
After you create the control, you need to add it to the window with placeControl().
|
|
||||||
|
|
||||||
Example:
|
|
||||||
self.cList = List('font14', space=5)
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __new__(cls, *args, **kwargs):
|
|
||||||
textures = {'buttonTexture': os.path.join(_images, 'List', 'MenuItemNF.png'),
|
|
||||||
'buttonFocusTexture': os.path.join(_images, 'List', 'MenuItemFO.png')}
|
|
||||||
_set_textures(textures, kwargs)
|
|
||||||
return super(List, cls).__new__(cls, -10, -10, 1, 1, *args, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class Slider(xbmcgui.ControlSlider):
|
|
||||||
"""ControlSlider class.
|
|
||||||
|
|
||||||
Parameters:
|
|
||||||
textureback: string - image filename.
|
|
||||||
texture: string - image filename.
|
|
||||||
texturefocus: string - image filename.
|
|
||||||
|
|
||||||
Note:
|
|
||||||
After you create the control, you need to add it to the window with placeControl().
|
|
||||||
|
|
||||||
Example:
|
|
||||||
self.slider = Slider()
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __new__(cls, *args, **kwargs):
|
|
||||||
textures = {'textureback': os.path.join(_images, 'Slider', 'osd_slider_bg.png'),
|
|
||||||
'texture': os.path.join(_images, 'Slider', 'osd_slider_nibNF.png'),
|
|
||||||
'texturefocus': os.path.join(_images, 'Slider', 'osd_slider_nib.png')}
|
|
||||||
_set_textures(textures, kwargs)
|
|
||||||
return super(Slider, cls).__new__(cls, -10, -10, 1, 1, *args, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class _AbstractWindow(object):
|
|
||||||
"""
|
|
||||||
Top-level control window.
|
|
||||||
|
|
||||||
The control windows serves as a parent widget for other XBMC UI controls
|
|
||||||
much like Tkinter.Tk or PyQt QWidget class.
|
|
||||||
This is an abstract class which is not supposed to be instantiated directly
|
|
||||||
and will raise exeptions.
|
|
||||||
|
|
||||||
This class is a basic "skeleton" for a control window.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
"""Constructor method."""
|
|
||||||
self.actions_connected = []
|
|
||||||
self.controls_connected = []
|
|
||||||
|
|
||||||
def setGeometry(self, width_, height_, rows_, columns_, pos_x=-1, pos_y=-1):
|
|
||||||
"""
|
|
||||||
Set width, height, Grid layout, and coordinates (optional) for a new control window.
|
|
||||||
|
|
||||||
Parameters:
|
|
||||||
width_, height_: widgh and height of the created window.
|
|
||||||
rows_, columns_: rows and colums of the Grid layout to place controls on.
|
|
||||||
pos_x, pos_y (optional): coordinates of the top left corner of the window.
|
|
||||||
If pos_x and pos_y are not privided, the window will be placed
|
|
||||||
at the center of the screen.
|
|
||||||
Example:
|
|
||||||
self.setGeometry(400, 500, 5, 4)
|
|
||||||
"""
|
|
||||||
self.width = width_
|
|
||||||
self.height = height_
|
|
||||||
self.rows = rows_
|
|
||||||
self.columns = columns_
|
|
||||||
if pos_x > 0 and pos_y > 0:
|
|
||||||
self.x = pos_x
|
|
||||||
self.y = pos_y
|
|
||||||
else:
|
|
||||||
self.x = 640 - self.width / 2
|
|
||||||
self.y = 360 - self.height / 2
|
|
||||||
self.setGrid()
|
|
||||||
|
|
||||||
def setGrid(self):
|
|
||||||
"""
|
|
||||||
Set window grid layout of rows * columns.
|
|
||||||
This is a helper method not to be called directly.
|
|
||||||
"""
|
|
||||||
self.grid_x = self.x
|
|
||||||
self.grid_y = self.y
|
|
||||||
self.tile_width = self.width / self.columns
|
|
||||||
self.tile_height = self.height / self.rows
|
|
||||||
|
|
||||||
def placeControl(self, control, row, column, rowspan=1, columnspan=1, pad_x=5, pad_y=5):
|
|
||||||
"""
|
|
||||||
Place a control within the window grid layout.
|
|
||||||
|
|
||||||
pad_x, pad_y: horisontal and vertical padding for control's
|
|
||||||
size and aspect adjustments. Negative values can be used
|
|
||||||
to make a control overlap with grid cells next to it, if necessary.
|
|
||||||
Raises AddonWindowError if a grid has not yet been set.
|
|
||||||
Example:
|
|
||||||
self.placeControl(self.label, 0, 1)
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
control_x = (self.grid_x + self.tile_width * column) + pad_x
|
|
||||||
control_y = (self.grid_y + self.tile_height * row) + pad_y
|
|
||||||
control_width = self.tile_width * columnspan - 2 * pad_x
|
|
||||||
control_height = self.tile_height * rowspan - 2 * pad_y
|
|
||||||
except AttributeError:
|
|
||||||
raise AddonWindowError('Window geometry is not defined! Call setGeometry first.')
|
|
||||||
control.setPosition(control_x, control_y)
|
|
||||||
control.setWidth(control_width)
|
|
||||||
control.setHeight(control_height)
|
|
||||||
self.addControl(control)
|
|
||||||
self.setAnimation(control)
|
|
||||||
|
|
||||||
def getX(self):
|
|
||||||
"""Get X coordinate of the top-left corner of the window."""
|
|
||||||
try:
|
|
||||||
return self.x
|
|
||||||
except AttributeError:
|
|
||||||
raise AddonWindowError('Window geometry is not defined! Call setGeometry first.')
|
|
||||||
|
|
||||||
def getY(self):
|
|
||||||
"""Get Y coordinate of the top-left corner of the window."""
|
|
||||||
try:
|
|
||||||
return self.y
|
|
||||||
except AttributeError:
|
|
||||||
raise AddonWindowError('Window geometry is not defined! Call setGeometry first.')
|
|
||||||
|
|
||||||
def getWindowWidth(self):
|
|
||||||
"""Get window width."""
|
|
||||||
try:
|
|
||||||
return self.width
|
|
||||||
except AttributeError:
|
|
||||||
raise AddonWindowError('Window geometry is not defined! Call setGeometry first.')
|
|
||||||
|
|
||||||
def getWindowHeight(self):
|
|
||||||
"""Get window height."""
|
|
||||||
try:
|
|
||||||
return self.height
|
|
||||||
except AttributeError:
|
|
||||||
raise AddonWindowError('Window geometry is not defined! Call setGeometry first.')
|
|
||||||
|
|
||||||
def getRows(self):
|
|
||||||
"""
|
|
||||||
Get grid rows count.
|
|
||||||
Raises AddonWindowError if a grid has not yet been set.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
return self.rows
|
|
||||||
except AttributeError:
|
|
||||||
raise AddonWindowError('Grid layot is not set! Call setGeometry first.')
|
|
||||||
|
|
||||||
def getColumns(self):
|
|
||||||
"""
|
|
||||||
Get grid columns count.
|
|
||||||
Raises AddonWindowError if a grid has not yet been set.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
return self.columns
|
|
||||||
except AttributeError:
|
|
||||||
raise AddonWindowError('Grid layout is not set! Call setGeometry first.')
|
|
||||||
|
|
||||||
def connect(self, event, function):
|
|
||||||
"""
|
|
||||||
Connect an event to a function.
|
|
||||||
|
|
||||||
An event can be an inctance of a Control object or an integer key action code.
|
|
||||||
Several basic key action codes are provided by PyXBMCT. More action codes can be found at
|
|
||||||
https://github.com/xbmc/xbmc/blob/master/xbmc/guilib/Key.h
|
|
||||||
|
|
||||||
You can connect the following Controls: Button, RadioButton and List. Other Controls do not
|
|
||||||
generate any control events when activated so their connections won't work.
|
|
||||||
To catch Slider events you need to connect the following key actions:
|
|
||||||
ACTION_MOVE_LEFT, ACTION_MOVE_RIGHT and ACTION_MOUSE_DRAG, and do a check
|
|
||||||
whether the Slider is focused.
|
|
||||||
|
|
||||||
"function" parameter is a function or a method to be executed. Note that you must provide
|
|
||||||
a function object [without brackets ()], not a function call!
|
|
||||||
lambda can be used as a function to call another function or method with parameters.
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
self.connect(self.exit_button, self.close)
|
|
||||||
or
|
|
||||||
self.connect(ACTION_NAV_BACK, self.close)
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
self.disconnect(event)
|
|
||||||
except AddonWindowError:
|
|
||||||
if type(event) == int:
|
|
||||||
self.actions_connected.append([event, function])
|
|
||||||
else:
|
|
||||||
self.controls_connected.append([event, function])
|
|
||||||
|
|
||||||
def connectEventList(self, events, function):
|
|
||||||
"""
|
|
||||||
Connect a list of controls/action codes to a function.
|
|
||||||
See connect docstring for more info.
|
|
||||||
"""
|
|
||||||
[self.connect(event, function) for event in events]
|
|
||||||
|
|
||||||
def disconnect(self, event):
|
|
||||||
"""
|
|
||||||
Disconnect an event from a function.
|
|
||||||
|
|
||||||
An event can be an inctance of a Control object or an integer key action code
|
|
||||||
which has previously been connected to a function or a method.
|
|
||||||
Raises AddonWindowError if an event is not connected to any function.
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
self.disconnect(self.exit_button)
|
|
||||||
or
|
|
||||||
self.disconnect(ACTION_NAV_BACK)
|
|
||||||
"""
|
|
||||||
if type(event) == int:
|
|
||||||
event_list = self.actions_connected
|
|
||||||
else:
|
|
||||||
event_list = self.controls_connected
|
|
||||||
for index in range(len(event_list)):
|
|
||||||
if event == event_list[index][0]:
|
|
||||||
event_list.pop(index)
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
raise AddonWindowError('The action or control %s is not connected!' % event)
|
|
||||||
|
|
||||||
def disconnectEventList(self, events):
|
|
||||||
"""
|
|
||||||
Disconnect a list of controls/action codes from functions.
|
|
||||||
See disconnect docstring for more info.
|
|
||||||
Raises AddonWindowError if at least one event in the list
|
|
||||||
is not connected to any function.
|
|
||||||
"""
|
|
||||||
[self.disconnect(event) for event in events]
|
|
||||||
|
|
||||||
def executeConnected(self, event, connected_list):
|
|
||||||
"""
|
|
||||||
Execute a connected event (an action or a control).
|
|
||||||
This is a helper method not to be called directly.
|
|
||||||
"""
|
|
||||||
for item in connected_list:
|
|
||||||
if event == item[0]:
|
|
||||||
item[1]()
|
|
||||||
break
|
|
||||||
|
|
||||||
def setAnimation(self, control):
|
|
||||||
"""
|
|
||||||
This method is called to set animation properties for all controls
|
|
||||||
added to the current addon window instance - both built-in controls
|
|
||||||
(window background, title bar etc.) and controls added with placeControl().
|
|
||||||
It receives a control instance as the 2nd positional argument (besides self).
|
|
||||||
By default the method does nothing, i.e. no animation is set for controls.
|
|
||||||
To add animation you need to re-implement this menthod in your child class.
|
|
||||||
|
|
||||||
E.g:
|
|
||||||
def setAnimation(self, control):
|
|
||||||
control.setAnimations([('WindowOpen', 'effect=fade start=0 end=100 time=1000',),
|
|
||||||
('WindowClose', 'effect=fade start=100 end=0 time=1000',)])
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class _AddonWindow(_AbstractWindow):
|
|
||||||
"""
|
|
||||||
Top-level control window.
|
|
||||||
|
|
||||||
The control windows serves as a parent widget for other XBMC UI controls
|
|
||||||
much like Tkinter.Tk or PyQt QWidget class.
|
|
||||||
This is an abstract class which is not supposed to be instantiated directly
|
|
||||||
and will raise exeptions. It is designed to be implemented in a grand-child class
|
|
||||||
with the second inheritance from xbmcgui.Window or xbmcgui.WindowDialog
|
|
||||||
in a direct child class.
|
|
||||||
|
|
||||||
This class provides a control window with a background and a header
|
|
||||||
similar to top-level widgets of desktop UI frameworks.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, title=''):
|
|
||||||
"""Constructor method."""
|
|
||||||
super(_AddonWindow, self).__init__()
|
|
||||||
self.setFrame(title)
|
|
||||||
|
|
||||||
def setFrame(self, title):
|
|
||||||
"""
|
|
||||||
Define paths to images for window background and title background textures,
|
|
||||||
and set control position adjustment constants used in setGrid.
|
|
||||||
This is a helper method not to be called directly.
|
|
||||||
"""
|
|
||||||
# Window background image
|
|
||||||
self.background_img = os.path.join(_images, 'AddonWindow', 'ContentPanel.png')
|
|
||||||
# Background for a window header
|
|
||||||
self.title_background_img = os.path.join(_images, 'AddonWindow', 'dialogheader.png')
|
|
||||||
# Horisontal adjustment for a header background if the main background has transparent edges.
|
|
||||||
self.X_MARGIN = 5
|
|
||||||
# Vertical adjustment for a header background if the main background has transparent edges
|
|
||||||
self.Y_MARGIN = 5
|
|
||||||
# Header position adjustment if the main backround has visible borders.
|
|
||||||
self.Y_SHIFT = 4
|
|
||||||
# The height of a window header (for the title background and the title label).
|
|
||||||
self.HEADER_HEIGHT = 35
|
|
||||||
self.background = xbmcgui.ControlImage(-10, -10, 1, 1, self.background_img)
|
|
||||||
self.addControl(self.background)
|
|
||||||
self.setAnimation(self.background)
|
|
||||||
self.title_background = xbmcgui.ControlImage(-10, -10, 1, 1, self.title_background_img)
|
|
||||||
self.addControl(self.title_background)
|
|
||||||
self.setAnimation(self.title_background)
|
|
||||||
self.title_bar = xbmcgui.ControlLabel(-10, -10, 1, 1, title, alignment=ALIGN_CENTER, textColor='0xFFFFA500',
|
|
||||||
font='font13_title')
|
|
||||||
self.addControl(self.title_bar)
|
|
||||||
self.setAnimation(self.title_bar)
|
|
||||||
self.window_close_button = xbmcgui.ControlButton(-100, -100, 60, 30, '',
|
|
||||||
focusTexture=os.path.join(_images, 'AddonWindow',
|
|
||||||
'DialogCloseButton-focus.png'),
|
|
||||||
noFocusTexture=os.path.join(_images, 'AddonWindow',
|
|
||||||
'DialogCloseButton.png'))
|
|
||||||
self.addControl(self.window_close_button)
|
|
||||||
self.setAnimation(self.window_close_button)
|
|
||||||
|
|
||||||
def setGeometry(self, width_, height_, rows_, columns_, pos_x=-1, pos_y=-1, padding=5):
|
|
||||||
"""
|
|
||||||
Set width, height, Grid layout, and coordinates (optional) for a new control window.
|
|
||||||
|
|
||||||
Parameters:
|
|
||||||
width_, height_: widgh and height of the created window.
|
|
||||||
rows_, columns_: rows and colums of the Grid layout to place controls on.
|
|
||||||
pos_x, pos_y (optional): coordinates of the top left corner of the window.
|
|
||||||
If pos_x and pos_y are not privided, the window will be placed
|
|
||||||
at the center of the screen.
|
|
||||||
padding (optional): padding between outer edges of the window and
|
|
||||||
controls placed on it.
|
|
||||||
Example:
|
|
||||||
self.setGeometry(400, 500, 5, 4)
|
|
||||||
"""
|
|
||||||
self.win_padding = padding
|
|
||||||
super(_AddonWindow, self).setGeometry(width_, height_, rows_, columns_, pos_x, pos_y)
|
|
||||||
self.background.setPosition(self.x, self.y)
|
|
||||||
self.background.setWidth(self.width)
|
|
||||||
self.background.setHeight(self.height)
|
|
||||||
self.title_background.setPosition(self.x + self.X_MARGIN, self.y + self.Y_MARGIN + self.Y_SHIFT)
|
|
||||||
self.title_background.setWidth(self.width - 2 * self.X_MARGIN)
|
|
||||||
self.title_background.setHeight(self.HEADER_HEIGHT)
|
|
||||||
self.title_bar.setPosition(self.x + self.X_MARGIN, self.y + self.Y_MARGIN + self.Y_SHIFT)
|
|
||||||
self.title_bar.setWidth(self.width - 2 * self.X_MARGIN)
|
|
||||||
self.title_bar.setHeight(self.HEADER_HEIGHT)
|
|
||||||
self.window_close_button.setPosition(self.x + self.width - 70, self.y + self.Y_MARGIN + self.Y_SHIFT)
|
|
||||||
|
|
||||||
def setGrid(self):
|
|
||||||
"""
|
|
||||||
Set window grid layout of rows * columns.
|
|
||||||
This is a helper method not to be called directly.
|
|
||||||
"""
|
|
||||||
self.grid_x = self.x + self.X_MARGIN + self.win_padding
|
|
||||||
self.grid_y = self.y + self.Y_MARGIN + self.Y_SHIFT + self.HEADER_HEIGHT + self.win_padding
|
|
||||||
self.tile_width = (self.width - 2 * (self.X_MARGIN + self.win_padding)) / self.columns
|
|
||||||
self.tile_height = (
|
|
||||||
self.height - self.HEADER_HEIGHT - self.Y_SHIFT - 2 * (
|
|
||||||
self.Y_MARGIN + self.win_padding)) / self.rows
|
|
||||||
|
|
||||||
def setWindowTitle(self, title=''):
|
|
||||||
"""
|
|
||||||
Set window title.
|
|
||||||
This method must be called AFTER (!!!) setGeometry(),
|
|
||||||
otherwise there is some werid bug with all skin text labels set to the 'title' text.
|
|
||||||
Example:
|
|
||||||
self.setWindowTitle('My Cool Addon')
|
|
||||||
"""
|
|
||||||
self.title_bar.setLabel(title)
|
|
||||||
|
|
||||||
def getWindowTitle(self):
|
|
||||||
"""Get window title."""
|
|
||||||
return self.title_bar.getLabel()
|
|
||||||
|
|
||||||
|
|
||||||
class _FullWindow(xbmcgui.Window):
|
|
||||||
"""An abstract class to define window event processing."""
|
|
||||||
|
|
||||||
def onAction(self, action):
|
|
||||||
"""
|
|
||||||
Catch button actions.
|
|
||||||
Note that, despite being compared to an integer,
|
|
||||||
action is an instance of xbmcgui.Action class.
|
|
||||||
"""
|
|
||||||
if action == ACTION_PREVIOUS_MENU:
|
|
||||||
self.close()
|
|
||||||
else:
|
|
||||||
self.executeConnected(action, self.actions_connected)
|
|
||||||
|
|
||||||
def onControl(self, control):
|
|
||||||
"""
|
|
||||||
Catch activated controls.
|
|
||||||
Control is an instance of xbmcgui.Control class.
|
|
||||||
"""
|
|
||||||
if control == self.window_close_button:
|
|
||||||
self.close()
|
|
||||||
else:
|
|
||||||
self.executeConnected(control, self.controls_connected)
|
|
||||||
|
|
||||||
|
|
||||||
class _DialogWindow(xbmcgui.WindowDialog):
|
|
||||||
"""An abstract class to define window event processing."""
|
|
||||||
|
|
||||||
def onAction(self, action):
|
|
||||||
"""
|
|
||||||
Catch button actions.
|
|
||||||
Note that, despite being compared to an integer,
|
|
||||||
action is an instance of xbmcgui.Action class.
|
|
||||||
"""
|
|
||||||
if action == ACTION_PREVIOUS_MENU:
|
|
||||||
self.close()
|
|
||||||
else:
|
|
||||||
self.executeConnected(action, self.actions_connected)
|
|
||||||
|
|
||||||
def onControl(self, control):
|
|
||||||
"""
|
|
||||||
Catch activated controls.
|
|
||||||
Control is an instance of xbmcgui.Control class.
|
|
||||||
"""
|
|
||||||
if control == self.window_close_button:
|
|
||||||
self.close()
|
|
||||||
else:
|
|
||||||
self.executeConnected(control, self.controls_connected)
|
|
||||||
|
|
||||||
|
|
||||||
class BlankFullWindow(_FullWindow, _AbstractWindow):
|
|
||||||
"""
|
|
||||||
Addon UI container with a solid background.
|
|
||||||
This is a blank window with a black background and without any elements whatsoever.
|
|
||||||
The decoration and layout are completely up to an addon developer.
|
|
||||||
The window controls can hide under video or music visualization.
|
|
||||||
Window ID can be passed on class instantiation an agrument
|
|
||||||
but __init__ must have the 2nd fake argument, e.g:
|
|
||||||
|
|
||||||
def __init__(self, *args)
|
|
||||||
|
|
||||||
Minimal example:
|
|
||||||
|
|
||||||
addon = MyAddon('My Cool Addon')
|
|
||||||
addon.setGeometry(400, 300, 4, 3)
|
|
||||||
addon.doModal()
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class BlankDialogWindow(_DialogWindow, _AbstractWindow):
|
|
||||||
"""
|
|
||||||
Addon UI container with a transparent background.
|
|
||||||
This is a blank window with a transparent background and without any elements whatsoever.
|
|
||||||
The decoration and layout are completely up to an addon developer.
|
|
||||||
The window controls are always displayed over video or music visualization.
|
|
||||||
Minimal example:
|
|
||||||
|
|
||||||
addon = MyAddon('My Cool Addon')
|
|
||||||
addon.setGeometry(400, 300, 4, 3)
|
|
||||||
addon.doModal()
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class AddonFullWindow(_FullWindow, _AddonWindow):
|
|
||||||
"""
|
|
||||||
Addon UI container with a solid background.
|
|
||||||
Control window is displayed on top of the main background image - self.main_bg.
|
|
||||||
Video and music visualization are displayed unhindered.
|
|
||||||
Window ID can be passed on class instantiation as the 2nd positional agrument
|
|
||||||
but __init__ must have the 3rd fake argument, e.g:
|
|
||||||
|
|
||||||
def __init__(self, title='', *args)
|
|
||||||
|
|
||||||
Minimal example:
|
|
||||||
|
|
||||||
addon = MyAddon('My Cool Addon')
|
|
||||||
addon.setGeometry(400, 300, 4, 3)
|
|
||||||
addon.doModal()
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __new__(cls, title='', *args, **kwargs):
|
|
||||||
return super(AddonFullWindow, cls).__new__(cls, *args, **kwargs)
|
|
||||||
|
|
||||||
def setFrame(self, title):
|
|
||||||
"""
|
|
||||||
Set the image for for the fullscreen background.
|
|
||||||
"""
|
|
||||||
# Image for the fullscreen background.
|
|
||||||
self.main_bg_img = os.path.join(_images, 'AddonWindow', 'SKINDEFAULT.jpg')
|
|
||||||
# Fullscreen background image control.
|
|
||||||
self.main_bg = xbmcgui.ControlImage(1, 1, 1280, 720, self.main_bg_img)
|
|
||||||
self.addControl(self.main_bg)
|
|
||||||
super(AddonFullWindow, self).setFrame(title)
|
|
||||||
|
|
||||||
def setBackground(self, image=''):
|
|
||||||
"""
|
|
||||||
Set the main bacground to an image file.
|
|
||||||
image: path to an image file as str.
|
|
||||||
Example:
|
|
||||||
self.setBackground('d:\images\bacground.png')
|
|
||||||
"""
|
|
||||||
self.main_bg.setImage(image)
|
|
||||||
|
|
||||||
|
|
||||||
class AddonDialogWindow(_DialogWindow, _AddonWindow):
|
|
||||||
"""
|
|
||||||
Addon UI container with a transparent background.
|
|
||||||
Control window is displayed on top of XBMC UI,
|
|
||||||
including video an music visualization!
|
|
||||||
Minimal example:
|
|
||||||
|
|
||||||
addon = MyAddon('My Cool Addon')
|
|
||||||
addon.setGeometry(400, 300, 4, 3)
|
|
||||||
addon.doModal()
|
|
||||||
"""
|
|
||||||
pass
|
|
Before Width: | Height: | Size: 52 KiB |
Before Width: | Height: | Size: 5.1 KiB |
Before Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 122 KiB |
Before Width: | Height: | Size: 4.8 KiB |
Before Width: | Height: | Size: 5.8 KiB |
Before Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 5.5 KiB |
Before Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 5.1 KiB |
Before Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 2.7 KiB |