class GUISkin: __module__ = __name__ def __init__(self): self["Title"] = StaticText() self.onLayoutFinish = [ ] self.summaries = CList() self.instance = None self.desktop = None def createGUIScreen(self, parent, desktop, updateonly = False): for val in self.renderer: if isinstance(val, GUIComponent): if not updateonly: val.GUIcreate(parent) if not val.applySkin(desktop, self): print "warning, skin is missing renderer", val, "in", self for key in self: val = self[key] if isinstance(val, GUIComponent): if not updateonly: val.GUIcreate(parent) depr = val.deprecationInfo if val.applySkin(desktop, self): if depr: print "WARNING: OBSOLETE COMPONENT '%s' USED IN SKIN. USE '%s' INSTEAD!" % (key, depr[0]) print "OBSOLETE COMPONENT WILL BE REMOVED %s, PLEASE UPDATE!" % (depr[1]) elif not depr: print "warning, skin is missing element", key, "in", self for w in self.additionalWidgets: if not updateonly: w.instance = w.widget(parent) # w.instance.thisown = 0 applyAllAttributes(w.instance, desktop, w.skinAttributes, self.scale) for f in self.onLayoutFinish: if type(f) is not type(self.close): # is this the best way to do this? exec(f) in globals(), locals() else: f() def deleteGUIScreen(self): for (name, val) in self.items(): if isinstance(val, GUIComponent): val.GUIdelete() def close(self): self.deleteGUIScreen() def createSummary(self): return None def addSummary(self, summary): if summary is not None: self.summaries.append(summary) def removeSummary(self, summary): if summary is not None: self.summaries.remove(summary) def setTitle(self, title): if self.instance: self.instance.setTitle(title) self["Title"].text = title self.summaries.setTitle(title) def getTitle(self): return self["Title"].text def getSkinTitle(self): return hasattr(self, "skin_title") and self.skin_title or "" title = property(getTitle, setTitle) def setDesktop(self, desktop): self.desktop = desktop def applySkin(self): self.skin_title = "" z = 0 baseres = (720, 576) # FIXME: a skin might have set another resolution, which should be the base res idx = 0 skin_title_idx = -1 title = self.title for (key, value) in self.skinAttributes: if key == "zPosition": z = int(value) elif key == "title": self.skin_title = value skin_title_idx = idx if title: self.skinAttributes[skin_title_idx] = ("title", title) else: self["Title"].text = value self.summaries.setTitle(value) elif key == "baseResolution": baseres = tuple([int(x) for x in value.split(',')]) idx += 1 self.scale = ((baseres[0], baseres[0]), (baseres[1], baseres[1])) if not self.instance: from enigma import eWindow self.instance = eWindow(self.desktop, z) if skin_title_idx == -1 and title: self.skinAttributes.append(("title", title)) # we need to make sure that certain attributes come last self.skinAttributes.sort(key=lambda a: {"position": 1}.get(a[0], 0)) applyAllAttributes(self.instance, self.desktop, self.skinAttributes, self.scale) self.createGUIScreen(self.instance, self.desktop)
class GUISkin: __module__ = __name__ def __init__(self): self["Title"] = StaticText() self.onLayoutFinish = [ ] self.summaries = CList() self.instance = None self.desktop = None def createGUIScreen(self, parent, desktop, updateonly = False): for val in self.renderer: if isinstance(val, GUIComponent): if not updateonly: val.GUIcreate(parent) if not val.applySkin(desktop, self): print "[GUISkin] warning, skin is missing renderer", val, "in", self for key in self: val = self[key] if isinstance(val, GUIComponent): if not updateonly: val.GUIcreate(parent) depr = val.deprecationInfo if val.applySkin(desktop, self): if depr: print "[GUISkin] WARNING: OBSOLETE COMPONENT '%s' USED IN SKIN. USE '%s' INSTEAD!" % (key, depr[0]) print "[GUISkin] OBSOLETE COMPONENT WILL BE REMOVED %s, PLEASE UPDATE!" % (depr[1]) elif not depr: print "[GUISkin] warning, skin is missing element", key, "in", self for w in self.additionalWidgets: if not updateonly: w.instance = w.widget(parent) # w.instance.thisown = 0 applyAllAttributes(w.instance, desktop, w.skinAttributes, self.scale) for f in self.onLayoutFinish: if type(f) is not type(self.close): # is this the best way to do this? exec f in globals(), locals() else: f() def deleteGUIScreen(self): for (name, val) in self.items(): if isinstance(val, GUIComponent): val.GUIdelete() def close(self): self.deleteGUIScreen() def createSummary(self): return None def addSummary(self, summary): if summary is not None: self.summaries.append(summary) def removeSummary(self, summary): if summary is not None: self.summaries.remove(summary) def setTitle(self, title): try: if self.instance: self.instance.setTitle(title) self["Title"].text = title self.summaries.setTitle(title) except: pass def getTitle(self): return self["Title"].text title = property(getTitle, setTitle) def setDesktop(self, desktop): self.desktop = desktop def applySkin(self): z = 0 baseres = (720, 576) # FIXME: a skin might have set another resolution, which should be the base res idx = 0 skin_title_idx = -1 title = self.title for (key, value) in self.skinAttributes: if key == "zPosition": z = int(value) elif key == "title": skin_title_idx = idx if title: self.skinAttributes[skin_title_idx] = ("title", title) else: self["Title"].text = value self.summaries.setTitle(value) elif key == "baseResolution": baseres = tuple([int(x) for x in value.split(',')]) idx += 1 self.scale = ((baseres[0], baseres[0]), (baseres[1], baseres[1])) if not self.instance: from enigma import eWindow self.instance = eWindow(self.desktop, z) if skin_title_idx == -1 and title: self.skinAttributes.append(("title", title)) # we need to make sure that certain attributes come last self.skinAttributes.sort(key=lambda a: {"position": 1}.get(a[0], 0)) applyAllAttributes(self.instance, self.desktop, self.skinAttributes, self.scale) self.createGUIScreen(self.instance, self.desktop)
class Element(object): CHANGED_DEFAULT = 0 # initial "pull" state CHANGED_ALL = 1 # really everything changed CHANGED_CLEAR = 2 # we're expecting a real update soon. don't bother polling NOW, but clear data. CHANGED_SPECIFIC = 3 # second tuple will specify what exactly changed CHANGED_POLL = 4 # a timer expired SINGLE_SOURCE = True def __init__(self): self.downstream_elements = CList() self.master = None self.sources = [ ] self.source = None self.__suspended = True self.cache = None def connectDownstream(self, downstream): self.downstream_elements.append(downstream) if self.master is None: self.master = downstream def connectUpstream(self, upstream): assert not self.SINGLE_SOURCE or self.source is None self.sources.append(upstream) # self.source always refers to the last recent source added. self.source = upstream self.changed((self.CHANGED_DEFAULT,)) def connect(self, upstream): self.connectUpstream(upstream) upstream.connectDownstream(self) # we disconnect from down to up def disconnectAll(self): # we should not disconnect from upstream if # there are still elements depending on us. assert len(self.downstream_elements) == 0, "there are still downstream elements left" # Sources don't have a source themselves. don't do anything here. for s in self.sources: s.disconnectDownstream(self) if self.source: # sources are owned by the Screen, so don't destroy them here. self.destroy() self.source = None self.sources = [ ] def disconnectDownstream(self, downstream): self.downstream_elements.remove(downstream) if self.master == downstream: self.master = None if len(self.downstream_elements) == 0: self.disconnectAll() # default action: push downstream def changed(self, *args, **kwargs): self.cache = { } self.downstream_elements.changed(*args, **kwargs) self.cache = None def setSuspend(self, suspended): changed = self.__suspended != suspended if not self.__suspended and suspended: self.doSuspend(1) elif self.__suspended and not suspended: self.doSuspend(0) self.__suspended = suspended if changed: for s in self.sources: s.checkSuspend() suspended = property(lambda self: self.__suspended, setSuspend) def checkSuspend(self): self.suspended = reduce(lambda x, y: x and y.__suspended, self.downstream_elements, True) def doSuspend(self, suspend): pass def destroy(self): pass
class Screen(dict): NO_SUSPEND, SUSPEND_STOPS, SUSPEND_PAUSES = range(3) ALLOW_SUSPEND = NO_SUSPEND globalScreen = None def __init__(self, session, parent=None, mandatoryWidgets=None): dict.__init__(self) self.skinName = self.__class__.__name__ self.session = session self.parent = parent self.mandatoryWidgets = mandatoryWidgets self.onClose = [] self.onFirstExecBegin = [] self.onExecBegin = [] self.onExecEnd = [] self.onLayoutFinish = [] self.onShown = [] self.onShow = [] self.onHide = [] self.execing = False self.shown = True # DEBUG: Variable already_shown used in CutListEditor/ui.py and StartKodi/plugin.py... # DEBUG: self.alreadyShown = False # Already shown is false until the screen is really shown (after creation). self.already_shown = False # Already shown is false until the screen is really shown (after creation). self.renderer = [] self.helpList = [] # In order to support screens *without* a help, we need the list in every screen. how ironic. self.close_on_next_exec = None # DEBUG: Variable already_shown used in webinterface/src/WebScreens.py... # DEBUG: self.standAlone = False # Stand alone screens (for example web screens) don't care about having or not having focus. self.stand_alone = False # Stand alone screens (for example web screens) don't care about having or not having focus. self.keyboardMode = None self.desktop = None self.instance = None self.summaries = CList() self["Title"] = StaticText() self["ScreenPath"] = StaticText() self.screenPath = "" # This is the current screen path without the title. self.screenTitle = "" # This is the current screen title without the path. def __repr__(self): return str(type(self)) def execBegin(self): self.active_components = [] if self.close_on_next_exec is not None: tmp = self.close_on_next_exec self.close_on_next_exec = None self.execing = True self.close(*tmp) else: single = self.onFirstExecBegin self.onFirstExecBegin = [] for x in self.onExecBegin + single: x() # DEBUG: if not self.standAlone and self.session.current_dialog != self: if not self.stand_alone and self.session.current_dialog != self: return # assert self.session is None, "a screen can only exec once per time" # self.session = session for val in list(self.values()) + self.renderer: val.execBegin() # DEBUG: if not self.standAlone and self.session.current_dialog != self: if not self.stand_alone and self.session.current_dialog != self: return self.active_components.append(val) self.execing = True for x in self.onShown: x() def execEnd(self): active_components = self.active_components # for (name, val) in self.items(): self.active_components = [] for val in active_components: val.execEnd() # assert self.session is not None, "execEnd on non-execing screen!" # self.session = None self.execing = False for x in self.onExecEnd: x() def doClose(self): # Never call this directly - it will be called from the session! self.hide() for x in self.onClose: x() del self.helpList # Fixup circular references. self.deleteGUIScreen() # First disconnect all render from their sources. We might split this out into # a "unskin"-call, but currently we destroy the screen afterwards anyway. for val in self.renderer: val.disconnectAll() # Disconnect converter/sources and probably destroy them. Sources will not be destroyed. del self.session for (name, val) in list(self.items()): val.destroy() del self[name] self.renderer = [] self.__dict__.clear() # Really delete all elements now. def close(self, *retval): if not self.execing: self.close_on_next_exec = retval else: self.session.close(self, *retval) def show(self): print("[Screen] Showing screen '%s'." % self.skinName) # To ease identification of screens. # DEBUG: if (self.shown and self.alreadyShown) or not self.instance: if (self.shown and self.already_shown) or not self.instance: return self.shown = True # DEBUG: self.alreadyShown = True self.already_shown = True self.instance.show() for x in self.onShow: x() for val in list(self.values()) + self.renderer: if isinstance(val, GUIComponent) or isinstance(val, Source): val.onShow() def hide(self): if not self.shown or not self.instance: return self.shown = False self.instance.hide() for x in self.onHide: x() for val in list(self.values()) + self.renderer: if isinstance(val, GUIComponent) or isinstance(val, Source): val.onHide() def getScreenPath(self): return self.screenPath def setTitle(self, title, showPath=True): try: # This protects against calls to setTitle() before being fully initialised like self.session is accessed *before* being defined. self.screenPath = "" if self.session.dialog_stack: screenclasses = [ds[0].__class__.__name__ for ds in self.session.dialog_stack] if "MainMenu" in screenclasses: index = screenclasses.index("MainMenu") if self.session and len(screenclasses) > index: self.screenPath = " > ".join(ds[0].getTitle() for ds in self.session.dialog_stack[index:]) if self.instance: self.instance.setTitle(title) self.summaries.setTitle(title) except AttributeError: pass self.screenTitle = title if showPath and config.usage.showScreenPath.value == "large" and title: screenPath = "" screenTitle = "%s > %s" % (self.screenPath, title) if self.screenPath else title elif showPath and config.usage.showScreenPath.value == "small": screenPath = "%s >" % self.screenPath if self.screenPath else "" screenTitle = title else: screenPath = "" screenTitle = title self["ScreenPath"].text = screenPath self["Title"].text = screenTitle def getTitle(self): return self.screenTitle title = property(getTitle, setTitle) def setFocus(self, o): self.instance.setFocus(o.instance) def setKeyboardModeNone(self): rcinput = eRCInput.getInstance() rcinput.setKeyboardMode(rcinput.kmNone) def setKeyboardModeAscii(self): rcinput = eRCInput.getInstance() rcinput.setKeyboardMode(rcinput.kmAscii) def restoreKeyboardMode(self): rcinput = eRCInput.getInstance() if self.keyboardMode is not None: rcinput.setKeyboardMode(self.keyboardMode) def saveKeyboardMode(self): rcinput = eRCInput.getInstance() self.keyboardMode = rcinput.getKeyboardMode() def setDesktop(self, desktop): self.desktop = desktop def setAnimationMode(self, mode): if self.instance: self.instance.setAnimationMode(mode) def getRelatedScreen(self, name): if name == "session": return self.session.screen elif name == "parent": return self.parent elif name == "global": return self.globalScreen return None def callLater(self, function): self.__callLaterTimer = eTimer() self.__callLaterTimer.callback.append(function) self.__callLaterTimer.start(0, True) def applySkin(self): # DEBUG: baseRes = (getDesktop(GUI_SKIN_ID).size().width(), getDesktop(GUI_SKIN_ID).size().height()) baseRes = (720, 576) # FIXME: A skin might have set another resolution, which should be the base res. zPosition = 0 for (key, value) in self.skinAttributes: if key == "baseResolution": baseRes = tuple([int(x) for x in value.split(",")]) elif key == "zPosition": zPosition = int(value) self.scale = ((baseRes[0], baseRes[0]), (baseRes[1], baseRes[1])) if not self.instance: self.instance = eWindow(self.desktop, zPosition) if "title" not in self.skinAttributes and self.screenTitle: self.skinAttributes.append(("title", self.screenTitle)) else: for attribute in self.skinAttributes: if attribute[0] == "title": self.setTitle(_(attribute[1])) self.skinAttributes.sort(key=lambda a: {"position": 1}.get(a[0], 0)) # We need to make sure that certain attributes come last. applyAllAttributes(self.instance, self.desktop, self.skinAttributes, self.scale) self.createGUIScreen(self.instance, self.desktop) def createGUIScreen(self, parent, desktop, updateonly=False): for val in self.renderer: if isinstance(val, GUIComponent): if not updateonly: val.GUIcreate(parent) if not val.applySkin(desktop, self): print("[Screen] Warning: Skin is missing renderer '%s' in %s." % (val, str(self))) for key in self: val = self[key] if isinstance(val, GUIComponent): if not updateonly: val.GUIcreate(parent) depr = val.deprecationInfo if val.applySkin(desktop, self): if depr: print("[Screen] WARNING: OBSOLETE COMPONENT '%s' USED IN SKIN. USE '%s' INSTEAD!" % (key, depr[0])) print("[Screen] OBSOLETE COMPONENT WILL BE REMOVED %s, PLEASE UPDATE!" % depr[1]) elif not depr: print("[Screen] Warning: Skin is missing element '%s' in %s." % (key, str(self))) for w in self.additionalWidgets: if not updateonly: w.instance = w.widget(parent) # w.instance.thisown = 0 applyAllAttributes(w.instance, desktop, w.skinAttributes, self.scale) for f in self.onLayoutFinish: if not isinstance(f, type(self.close)): if PY2: exec f in globals(), locals() else: exec(f, globals(), locals()) else: f() def deleteGUIScreen(self): for (name, val) in self.items(): if isinstance(val, GUIComponent): val.GUIdelete() def createSummary(self): return None def addSummary(self, summary): if summary is not None: self.summaries.append(summary) def removeSummary(self, summary): if summary is not None: self.summaries.remove(summary)
class Element(object): CHANGED_DEFAULT = 0 CHANGED_ALL = 1 CHANGED_CLEAR = 2 CHANGED_SPECIFIC = 3 CHANGED_POLL = 4 SINGLE_SOURCE = True def __init__(self): self.downstream_elements = CList() self.master = None self.sources = [] self.source = None self.__suspended = True self.cache = None return def connectDownstream(self, downstream): self.downstream_elements.append(downstream) if self.master is None: self.master = downstream return def connectUpstream(self, upstream): self.sources.append(upstream) self.source = upstream self.changed((self.CHANGED_DEFAULT, )) def connect(self, upstream): self.connectUpstream(upstream) upstream.connectDownstream(self) def disconnectAll(self): for s in self.sources: s.disconnectDownstream(self) if self.source: self.destroy() self.source = None self.sources = [] return def disconnectDownstream(self, downstream): self.downstream_elements.remove(downstream) if self.master == downstream: self.master = None if len(self.downstream_elements) == 0: self.disconnectAll() return def changed(self, *args, **kwargs): self.cache = {} self.downstream_elements.changed(*args, **kwargs) self.cache = None return def setSuspend(self, suspended): changed = self.__suspended != suspended if not self.__suspended and suspended: self.doSuspend(1) elif self.__suspended and not suspended: self.doSuspend(0) self.__suspended = suspended if changed: for s in self.sources: s.checkSuspend() suspended = property(lambda self: self.__suspended, setSuspend) def checkSuspend(self): self.suspended = reduce(lambda x, y: x and y.__suspended, self.downstream_elements, True) def doSuspend(self, suspend): pass def destroy(self): pass
class GUISkin: __module__ = __name__ def __init__(self): self['Title'] = StaticText() self.onLayoutFinish = [] self.summaries = CList() self.instance = None self.desktop = None def createGUIScreen(self, parent, desktop, updateonly=False): for val in self.renderer: if isinstance(val, GUIComponent): if not updateonly: val.GUIcreate(parent) if not val.applySkin(desktop, self): print 'warning, skin is missing renderer', val, 'in', self for key in self: val = self[key] if isinstance(val, GUIComponent): if not updateonly: val.GUIcreate(parent) depr = val.deprecationInfo if val.applySkin(desktop, self): if depr: print "WARNING: OBSOLETE COMPONENT '%s' USED IN SKIN. USE '%s' INSTEAD!" % ( key, depr[0]) print 'OBSOLETE COMPONENT WILL BE REMOVED %s, PLEASE UPDATE!' % depr[ 1] elif not depr: print 'warning, skin is missing element', key, 'in', self for w in self.additionalWidgets: if not updateonly: w.instance = w.widget(parent) applyAllAttributes(w.instance, desktop, w.skinAttributes, self.scale) for f in self.onLayoutFinish: if type(f) is not type(self.close): exec f in globals(), locals() else: f() def deleteGUIScreen(self): for name, val in self.items(): if isinstance(val, GUIComponent): val.GUIdelete() def close(self): self.deleteGUIScreen() def createSummary(self): return None def addSummary(self, summary): self.summaries.append(summary) def removeSummary(self, summary): self.summaries.remove(summary) def setTitle(self, title): try: if self.instance: self.instance.setTitle(title) self['Title'].text = title self.summaries.setTitle(title) except: pass def getTitle(self): return self['Title'].text def getSkinTitle(self): return hasattr(self, 'skin_title') and self.skin_title or '' title = property(getTitle, setTitle) def setDesktop(self, desktop): self.desktop = desktop def applySkin(self): z = 0 baseres = (720, 576) idx = 0 skin_title_idx = -1 title = self.title for key, value in self.skinAttributes: if key == 'zPosition': z = int(value) elif key == 'title': skin_title_idx = idx if title: self.skinAttributes[skin_title_idx] = ('title', title) else: self['Title'].text = value self.summaries.setTitle(value) elif key == 'baseResolution': baseres = tuple([int(x) for x in value.split(',')]) idx += 1 self.scale = ((baseres[0], baseres[0]), (baseres[1], baseres[1])) if not self.instance: from enigma import eWindow self.instance = eWindow(self.desktop, z) if skin_title_idx == -1 and title: self.skinAttributes.append(('title', title)) self.skinAttributes.sort(key=lambda a: {'position': 1}.get(a[0], 0)) applyAllAttributes(self.instance, self.desktop, self.skinAttributes, self.scale) self.createGUIScreen(self.instance, self.desktop)
class Element(object): CHANGED_DEFAULT = 0 CHANGED_ALL = 1 CHANGED_CLEAR = 2 CHANGED_SPECIFIC = 3 CHANGED_POLL = 4 SINGLE_SOURCE = True def __init__(self): self.downstream_elements = CList() self.master = None self.sources = [] self.source = None self.__suspended = True self.cache = None return def connectDownstream(self, downstream): self.downstream_elements.append(downstream) if self.master is None: self.master = downstream return def connectUpstream(self, upstream): self.sources.append(upstream) self.source = upstream self.changed((self.CHANGED_DEFAULT,)) def connect(self, upstream): self.connectUpstream(upstream) upstream.connectDownstream(self) def disconnectAll(self): for s in self.sources: s.disconnectDownstream(self) if self.source: self.destroy() self.source = None self.sources = [] return def disconnectDownstream(self, downstream): self.downstream_elements.remove(downstream) if self.master == downstream: self.master = None if len(self.downstream_elements) == 0: self.disconnectAll() return def changed(self, *args, **kwargs): self.cache = {} self.downstream_elements.changed(*args, **kwargs) self.cache = None return def setSuspend(self, suspended): changed = self.__suspended != suspended if not self.__suspended and suspended: self.doSuspend(1) elif self.__suspended and not suspended: self.doSuspend(0) self.__suspended = suspended if changed: for s in self.sources: s.checkSuspend() suspended = property(lambda self: self.__suspended, setSuspend) def checkSuspend(self): self.suspended = reduce(lambda x, y: x and y.__suspended, self.downstream_elements, True) def doSuspend(self, suspend): pass def destroy(self): pass
class GUISkin: __module__ = __name__ def __init__(self): self['Title'] = StaticText() self.onLayoutFinish = [] self.summaries = CList() self.instance = None self.desktop = None def createGUIScreen(self, parent, desktop, updateonly = False): for val in self.renderer: if isinstance(val, GUIComponent): if not updateonly: val.GUIcreate(parent) if not val.applySkin(desktop, self): print 'warning, skin is missing renderer', val, 'in', self for key in self: val = self[key] if isinstance(val, GUIComponent): if not updateonly: val.GUIcreate(parent) depr = val.deprecationInfo if val.applySkin(desktop, self): if depr: print "WARNING: OBSOLETE COMPONENT '%s' USED IN SKIN. USE '%s' INSTEAD!" % (key, depr[0]) print 'OBSOLETE COMPONENT WILL BE REMOVED %s, PLEASE UPDATE!' % depr[1] elif not depr: print 'warning, skin is missing element', key, 'in', self for w in self.additionalWidgets: if not updateonly: w.instance = w.widget(parent) applyAllAttributes(w.instance, desktop, w.skinAttributes, self.scale) for f in self.onLayoutFinish: if type(f) is not type(self.close): exec f in globals(), locals() else: f() def deleteGUIScreen(self): for name, val in self.items(): if isinstance(val, GUIComponent): val.GUIdelete() def close(self): self.deleteGUIScreen() def createSummary(self): return None def addSummary(self, summary): self.summaries.append(summary) def removeSummary(self, summary): self.summaries.remove(summary) def setTitle(self, title): try: if self.instance: self.instance.setTitle(title) self['Title'].text = title self.summaries.setTitle(title) except: pass def getTitle(self): return self['Title'].text title = property(getTitle, setTitle) def setDesktop(self, desktop): self.desktop = desktop def applySkin(self): z = 0 baseres = (720, 576) idx = 0 skin_title_idx = -1 title = self.title for key, value in self.skinAttributes: if key == 'zPosition': z = int(value) elif key == 'title': skin_title_idx = idx if title: self.skinAttributes[skin_title_idx] = ('title', title) else: self['Title'].text = value self.summaries.setTitle(value) elif key == 'baseResolution': baseres = tuple([ int(x) for x in value.split(',') ]) idx += 1 self.scale = ((baseres[0], baseres[0]), (baseres[1], baseres[1])) if not self.instance: from enigma import eWindow self.instance = eWindow(self.desktop, z) if skin_title_idx == -1 and title: self.skinAttributes.append(('title', title)) self.skinAttributes.sort(key=lambda a: {'position': 1}.get(a[0], 0)) applyAllAttributes(self.instance, self.desktop, self.skinAttributes, self.scale) self.createGUIScreen(self.instance, self.desktop)