-from enigma import *
+from Tools.Profile import profile, profile_final
+
+profile("LOAD:minidom")
import xml.dom.minidom
-from xml.dom import EMPTY_NAMESPACE
-from Tools.Import import my_import
-import os
+from os import path
-from Components.config import ConfigSubsection, configElement, configText, config
-from Components.Element import Element
+profile("LOAD:enigma_skin")
+from enigma import eSize, ePoint, gFont, eWindow, eLabel, ePixmap, eWindowStyleManager, \
+ addFont, gRGB, eWindowStyleSkinned
+
+from Components.config import ConfigSubsection, ConfigText, config
from Components.Converter.Converter import Converter
+from Components.Sources.Source import Source, ObsoleteSource
+from Tools.Directories import resolveFilename, SCOPE_SKIN, SCOPE_SKIN_IMAGE, SCOPE_FONTS
+from Tools.Import import my_import
+from Tools.LoadPixmap import LoadPixmap
from Tools.XMLTools import elementsWithTag, mergeText
except:
None
-from Tools.Directories import resolveFilename, SCOPE_SKIN, SCOPE_SKIN_IMAGE, SCOPE_FONTS
-
class SkinError(Exception):
def __init__(self, message):
self.message = message
def loadSkin(name):
# read the skin
filename = resolveFilename(SCOPE_SKIN, name)
- path = os.path.dirname(filename) + "/"
- dom_skins.append((path, xml.dom.minidom.parse(filename)))
+ mpath = path.dirname(filename) + "/"
+ dom_skins.append((mpath, xml.dom.minidom.parse(filename)))
# we do our best to always select the "right" value
# skins are loaded in order of priority: skin with
# example: loadSkin("nemesis_greenline/skin.xml")
config.skin = ConfigSubsection()
-config.skin.primary_skin = configElement("config.skin.primary_skin", configText, "skin.xml", 0)
+config.skin.primary_skin = ConfigText(default = "skin.xml")
+profile("LoadSkin")
try:
loadSkin(config.skin.primary_skin.value)
-except SkinError, err:
+except (SkinError, IOError, AssertionError), err:
print "SKIN ERROR:", err
print "defaulting to standard skin..."
+ config.skin.primary_skin.value = 'skin.xml'
loadSkin('skin.xml')
+
+profile("LoadSkinDefault")
loadSkin('skin_default.xml')
+profile("LoadSkinDefaultDone")
def parsePosition(str):
x, y = str.split(',')
try:
return colorNames[str]
except:
- raise ("color '%s' must be #aarrggbb or valid named color" % (str))
+ raise SkinError("color '%s' must be #aarrggbb or valid named color" % (str))
return gRGB(int(str[1:], 0x10))
def collectAttributes(skinAttributes, node, skin_path_prefix=None, ignore=[]):
# TODO: localization? as in e1?
value = a.value.encode("utf-8")
- if attrib in ["pixmap", "pointer"]:
+ if attrib in ["pixmap", "pointer", "seek_pointer", "backgroundPixmap", "selectionPixmap"]:
value = resolveFilename(SCOPE_SKIN_IMAGE, value, path_prefix=skin_path_prefix)
if attrib not in ignore:
skinAttributes.append((attrib, value))
-def loadPixmap(path):
- ptr = loadPNG(path)
+def loadPixmap(path, desktop):
+ cached = False
+ option = path.find("#")
+ if option != -1:
+ options = path[option+1:].split(',')
+ path = path[:option]
+ cached = "cached" in options
+ ptr = LoadPixmap(path, desktop, cached)
if ptr is None:
- raise "pixmap file %s not found!" % (path)
+ raise SkinError("pixmap file %s not found!" % (path))
return ptr
def applySingleAttribute(guiObject, desktop, attrib, value):
elif attrib == 'title':
guiObject.setTitle(_(value))
elif attrib == 'text':
- guiObject.setText(value)
+ guiObject.setText(_(value))
elif attrib == 'font':
guiObject.setFont(parseFont(value))
elif attrib == 'zPosition':
guiObject.setZPosition(int(value))
- elif attrib == "pixmap":
- ptr = loadPixmap(value) # this should already have been filename-resolved.
- # that __deref__ still scares me!
- desktop.makeCompatiblePixmap(ptr.__deref__())
- guiObject.setPixmap(ptr.__deref__())
+ elif attrib in ["pixmap", "backgroundPixmap", "selectionPixmap"]:
+ ptr = loadPixmap(value, desktop) # this should already have been filename-resolved.
+ if attrib == "pixmap":
+ guiObject.setPixmap(ptr)
+ elif attrib == "backgroundPixmap":
+ guiObject.setBackgroundPicture(ptr)
+ elif attrib == "selectionPixmap":
+ guiObject.setSelectionPicture(ptr)
# guiObject.setPixmapFromFile(value)
elif attrib == "alphatest": # used by ePixmap
guiObject.setAlphatest(
- { "on": True,
- "off": False
+ { "on": 1,
+ "off": 0,
+ "blend": 2,
}[value])
elif attrib == "orientation": # used by eSlider
try:
print "illegal flag %s!" % f
elif attrib == "backgroundColor":
guiObject.setBackgroundColor(parseColor(value))
+ elif attrib == "backgroundColorSelected":
+ guiObject.setBackgroundColorSelected(parseColor(value))
elif attrib == "foregroundColor":
guiObject.setForegroundColor(parseColor(value))
+ elif attrib == "foregroundColorSelected":
+ guiObject.setForegroundColorSelected(parseColor(value))
elif attrib == "shadowColor":
guiObject.setShadowColor(parseColor(value))
elif attrib == "selectionDisabled":
}[value])
elif attrib == "enableWrapAround":
guiObject.setWrapAround(True)
- elif attrib == "pointer":
+ elif attrib == "pointer" or attrib == "seek_pointer":
(name, pos) = value.split(':')
pos = parsePosition(pos)
- ptr = loadPixmap(name)
- desktop.makeCompatiblePixmap(ptr.__deref__())
- guiObject.setPointer(ptr.__deref__(), pos)
+ ptr = loadPixmap(name, desktop)
+ guiObject.setPointer({"pointer": 0, "seek_pointer": 1}[attrib], ptr, pos)
elif attrib == 'shadowOffset':
guiObject.setShadowOffset(parsePosition(value))
+ elif attrib == 'noWrap':
+ guiObject.setNoWrap(1)
else:
- raise "unsupported attribute " + attrib + "=" + value
+ raise SkinError("unsupported attribute " + attrib + "=" + value)
except int:
# AttributeError:
print "widget %s (%s) doesn't support attribute %s!" % ("", guiObject.__class__.__name__, attrib)
skin = dom_skin.childNodes[0]
assert skin.tagName == "skin", "root element in skin must be 'skin'!"
-
+
+ for c in elementsWithTag(skin.childNodes, "output"):
+ id = int(c.getAttribute("id") or "0")
+ if id == 0: # framebuffer
+ for res in elementsWithTag(c.childNodes, "resolution"):
+ xres = int(res.getAttribute("xres" or "720"))
+ yres = int(res.getAttribute("yres" or "576"))
+ bpp = int(res.getAttribute("bpp" or "32"))
+
+ from enigma import gFBDC
+ i = gFBDC.getInstance()
+ i.setResolution(xres, yres)
+
+ if bpp != 32:
+ # load palette (not yet implemented)
+ pass
+
for c in elementsWithTag(skin.childNodes, "colors"):
for color in elementsWithTag(c.childNodes, "color"):
name = str(color.getAttribute("name"))
for windowstyle in elementsWithTag(skin.childNodes, "windowstyle"):
style = eWindowStyleSkinned()
+ id = int(windowstyle.getAttribute("id") or "0")
# defaults
font = gFont("Regular", 20)
bpName = str(pixmap.getAttribute("pos"))
filename = str(pixmap.getAttribute("filename"))
- png = loadPixmap(resolveFilename(SCOPE_SKIN_IMAGE, filename, path_prefix=path_prefix))
-
- # adapt palette
- desktop.makeCompatiblePixmap(png.__deref__())
- style.setPixmap(eWindowStyleSkinned.__dict__[bsName], eWindowStyleSkinned.__dict__[bpName], png.__deref__())
+ png = loadPixmap(resolveFilename(SCOPE_SKIN_IMAGE, filename, path_prefix=path_prefix), desktop)
+ style.setPixmap(eWindowStyleSkinned.__dict__[bsName], eWindowStyleSkinned.__dict__[bpName], png)
for color in elementsWithTag(windowstyle.childNodes, "color"):
type = str(color.getAttribute("name"))
except:
raise ("Unknown color %s" % (type))
- x = eWindowStyleManagerPtr()
- eWindowStyleManager.getInstance(x)
- x.setStyle(style)
+ x = eWindowStyleManager.getInstance()
+ x.setStyle(id, style)
def loadSkinData(desktop):
skins = dom_skins[:]
return x, path
return None, None
-def readSkin(screen, skin, name, desktop):
- myscreen, path = lookupScreen(name)
-
+def readSkin(screen, skin, names, desktop):
+ if not isinstance(names, list):
+ names = [names]
+
+ name = "<embedded-in-'%s'>" % screen.__class__.__name__
+
+ # try all skins, first existing one have priority
+ for n in names:
+ myscreen, path = lookupScreen(n)
+ if myscreen is not None:
+ # use this name for debug output
+ name = n
+ break
+
# otherwise try embedded skin
myscreen = myscreen or getattr(screen, "parsedSkin", None)
-
+
# try uncompiled embedded skin
if myscreen is None and getattr(screen, "skin", None):
myscreen = screen.parsedSkin = xml.dom.minidom.parseString(screen.skin).childNodes[0]
-
- assert myscreen is not None, "no skin for screen '" + name + "' found!"
+
+ assert myscreen is not None, "no skin for screen '" + repr(names) + "' found!"
screen.skinAttributes = [ ]
screen.additionalWidgets = [ ]
screen.renderer = [ ]
+ visited_components = set()
+
# now walk all widgets
for widget in elementsWithTag(myscreen.childNodes, "widget"):
# ok, we either have 1:1-mapped widgets ('old style'), or 1:n-mapped
wname = widget.getAttribute('name')
wsource = widget.getAttribute('source')
+
if wname is None and wsource is None:
print "widget has no name and no source!"
continue
if wname:
+ visited_components.add(wname)
+
# get corresponding 'gui' object
try:
attributes = screen[wname].skinAttributes = [ ]
raise SkinError("component with name '" + wname + "' was not found in skin of screen '" + name + "'!")
# assert screen[wname] is not Source
-
+
# and collect attributes for this
collectAttributes(attributes, widget, skin_path_prefix, ignore=['name'])
elif wsource:
# get corresponding source
- source = screen.get(wsource)
+
+ while True: # until we found a non-obsolete source
+
+ # parse our current "wsource", which might specifiy a "related screen" before the dot,
+ # for example to reference a parent, global or session-global screen.
+ scr = screen
+
+ # resolve all path components
+ path = wsource.split('.')
+ while len(path) > 1:
+ scr = screen.getRelatedScreen(path[0])
+ if scr is None:
+ print wsource
+ print name
+ raise SkinError("specified related screen '" + wsource + "' was not found in screen '" + name + "'!")
+ path = path[1:]
+
+ # resolve the source.
+ source = scr.get(path[0])
+ if isinstance(source, ObsoleteSource):
+ # however, if we found an "obsolete source", issue warning, and resolve the real source.
+ print "WARNING: SKIN '%s' USES OBSOLETE SOURCE '%s', USE '%s' INSTEAD!" % (name, wsource, source.new_source)
+ print "OBSOLETE SOURCE WILL BE REMOVED %s, PLEASE UPDATE!" % (source.removal_date)
+ if source.description:
+ print source.description
+
+ wsource = source.new_source
+ else:
+ # otherwise, use that source.
+ break
+
if source is None:
raise SkinError("source '" + wsource + "' was not found in screen '" + name + "'!")
c = converter_class(parms)
c.connect(source)
else:
- print "reused conveter!"
+ print "reused converter!"
source = c
screen.renderer.append(renderer)
+ from Components.GUIComponent import GUIComponent
+ nonvisited_components = [x for x in set(screen.keys()) - visited_components if isinstance(x, GUIComponent)]
+
+ assert not nonvisited_components, "the following components in %s don't have a skin entry: %s" % (name, ', '.join(nonvisited_components))
+
# now walk additional objects
for widget in elementsWithTag(myscreen.childNodes, lambda x: x != "widget"):
if widget.tagName == "applet":