[MerlinSkinThemes] - add config option to disable rebuild on boot
[enigma2-plugins.git] / merlinskinthemes / src / MerlinSkinThemes.py
1 #######################################################################
2 #
3 #  MerlinSkinThemes for Dreambox/Enigma2/Dreambox OS
4 #  Coded by marthom (c)2012 - 2019
5 #
6 #  Support: board.dreambox.tools
7 #  E-Mail: marthom@dreambox-tools.info
8 #
9 #  This plugin is open source but it is NOT free software.
10 #
11 #  This plugin may only be distributed to and executed on hardware which
12 #  is licensed by Dream Multimedia GmbH.
13 #  In other words:
14 #  It's NOT allowed to distribute any parts of this plugin or its source code in ANY way
15 #  to hardware which is NOT licensed by Dream Property.
16 #  It's NOT allowed to execute this plugin and its source code or even parts of it in ANY way
17 #  on hardware which is NOT licensed by Dream Property.
18 #
19 #  If you want to use or modify the code or parts of it,
20 #  you have to keep MY license and inform me about the modifications by mail.
21 #
22 #######################################################################
23
24 from Plugins.Plugin import PluginDescriptor
25
26 from Screens.Screen import Screen
27 from Screens.HelpMenu import HelpableScreen
28 from Screens.MessageBox import MessageBox
29 from Screens.InputBox import InputBox
30 from Screens.Standby import TryQuitMainloop
31
32 from skin import TemplatedListFonts, componentSizes
33
34 from Components.ActionMap import ActionMap, HelpableActionMap
35 from Components.Button import Button
36 from Components.Label import Label
37 from Components.Pixmap import Pixmap
38 from Components.MenuList import MenuList
39 from Components.config import config, configfile, ConfigYesNo, ConfigSubsection, getConfigListEntry, ConfigSelection, ConfigNumber, ConfigText, ConfigInteger, ConfigSubDict, ConfigBoolean
40 from Components.ConfigList import ConfigListScreen
41
42 from enigma import eListboxPythonMultiContent, gFont, RT_HALIGN_LEFT, RT_HALIGN_RIGHT, RT_VALIGN_CENTER, getEnigmaVersionString
43
44 from Tools.HardwareInfo import HardwareInfo
45 from Tools.Directories import resolveFilename, SCOPE_SKIN, SCOPE_PLUGINS, fileExists
46
47 import xml.etree.cElementTree as Tree
48
49 import shutil
50 import os
51
52 # =========================================
53 PluginVersion = "v2.7.0"
54 Title = "MerlinSkinThemes "
55 Author = "by marthom"
56 # =========================================
57
58 SkinXML = config.skin.primary_skin.value
59 SkinFile = resolveFilename(SCOPE_SKIN) + SkinXML
60 SkinName = SkinXML[0:SkinXML.find("/")]
61 ThemeFile = resolveFilename(SCOPE_SKIN) + SkinName + "/themes.xml"
62 skin_user_xml = "/etc/enigma2/skin_user.xml"
63 enigmacontrol = "/var/lib/opkg/info/enigma2.control"
64 merlinChk = "/usr/share/enigma2/merlin_setup.xml"
65 GP3Chk = "/usr/lib/enigma2/python/Plugins/Bp/geminimain/gVersion.py"
66 GP4Chk = "/usr/lib/enigma2/python/Plugins/GP4/geminilocale/gVersion.py"
67 ImageCreater = "/usr/lib/enigma2/python/Components/ImageCreater.py"
68 PIL = "/usr/lib/python2.7/site-packages/PIL/Image.py"
69
70 # Liste der Vorschaubilder
71 myList = ["InfoBar", "Menu", "PluginBrowser", "ChannelSelection", "MovieSelection", "MoviePlayer", "SecondInfoBar", "GraphMultiEPG", "MessageBox", "InputBox", "ChoiceBox", "Mute", "Volume", "MerlinMusicPlayer2", "ExtLCDInfoBar", "ExtLCDEventView", "ExtLCDStandby", "ExtLCDMoviePlayer", "ExtLCDMMP2", "OLEDInfoBar", "OLEDEventView", "OLEDStandby", "OLEDMoviePlayer", "OLEDMMP2", "LCDInfoBar", "LCDEventView", "LCDStandby", "LCDMoviePlayer", "LCDMMP2"]
72
73 # Enigma2Version
74 E2ver = _("not available")
75 if open("/proc/stb/info/model","rb").read() == "dm7080":
76         if fileExists(enigmacontrol):
77                 file = open(enigmacontrol, 'r')
78                 while 1:
79                         line = file.readline()
80                         if not line:break
81                         if line[:9] == "Version: ":
82                                 E2ver = line[9:-1]
83                 file.close()
84 else:
85         E2ver = getEnigmaVersionString()
86
87 # Merlin
88 Merlin = False
89 if fileExists(merlinChk):
90         Merlin = True
91
92 # GP3
93 GP3 = False
94 GP3ver = ""
95 if fileExists(GP3Chk):
96         GP3 = True
97         file = open(GP3Chk, 'r')
98         data = ""
99         while 1:
100                 line = file.readline()
101                 if not line:break
102                 data += line
103         file.close()
104         
105         data = data.split("'")
106         GP3ver = data[1]
107
108 # GP4
109 GP4 = False
110 GP4ver = ""
111 if fileExists(GP4Chk):
112         GP4 = True
113         file = open(GP4Chk, 'r')
114         data = ""
115         while 1:
116                 line = file.readline()
117                 if not line:break
118                 data += line
119         file.close()
120         
121         data = data.split("'")
122         GP4ver = data[1]
123
124 # Arm/mipsel/aarch64
125 ArchArm = False
126 Arch64 = False
127 ArchMipsel = False
128 if HardwareInfo().get_device_name() in ('dm900', 'dm920'):
129         ArchArm = True
130         ArchString = "ARM"
131         IdString = "3"
132         DisplayXY = "400x240"
133 elif HardwareInfo().get_device_name() in ('one', 'two'):
134         Arch64 = True
135         ArchString = "AARCH64"
136         IdString = "0" #no display
137         DisplayXY = "0x0"
138 else:
139         if HardwareInfo().get_device_name() == 'dm820':
140                 IdString = "2"
141                 DisplayXY = "96x64"
142         elif HardwareInfo().get_device_name() == 'dm7080':
143                 IdString = "1"
144                 DisplayXY = "132x64"
145         ArchMipsel = True
146         ArchString = "MIPSEL"
147 ModelString = HardwareInfo().get_device_name().upper()
148 displayDict = {"1": "lcdscreenthemes", "2": "oldescreenthemes", "3": "extlcdscreenthemes"}
149 displayTag = displayDict.get(IdString, None)
150
151 print "------------------------------------------------"
152 print HardwareInfo().get_device_name()
153 print PluginVersion
154 print "------------------------------------------------"
155
156 # skin_user.xml
157 SkinUser = False
158 if fileExists(skin_user_xml):
159         SkinUser = True
160         
161 # Config
162 config.plugins.MerlinSkinThemes = ConfigSubsection()
163 config.plugins.MerlinSkinThemes.rebuildSkinOnBoot = ConfigBoolean(default=True)
164 config.plugins.MerlinSkinThemes.Skin = ConfigText(default=SkinName)
165 config.plugins.MerlinSkinThemes.selSkin = ConfigText(default=SkinName)
166 config.plugins.MerlinSkinThemes.ShowPrevPNG = ConfigText(default="1")
167 config.plugins.MerlinSkinThemes.CornerRadius = ConfigText(default="")
168 config.plugins.MerlinSkinThemes.applied = ConfigBoolean(default=False)
169
170 def initConfigSubDict(sectionName=None):
171         if sectionName == "Design":
172                 config.plugins.MerlinSkinThemes.Designs = ConfigSubDict()
173         elif sectionName == "Themes":
174                 config.plugins.MerlinSkinThemes.Themes = ConfigSubDict()
175         elif sectionName == "Screens":
176                 config.plugins.MerlinSkinThemes.Screens = ConfigSubDict()
177         elif sectionName == "DisplayScreens":
178                 config.plugins.MerlinSkinThemes.DisplayScreens = ConfigSubDict()                
179
180 # list of display screens (a.k.a. summaries)
181 displayScreenList = ["InfoBarSummary", "EventView_summary", "StandbySummary", "InfoBarMoviePlayerSummary", "MerlinMusicPlayer2LCDScreen"]
182 # list of screens
183 screenList = ["InfoBar", "Menu", "PluginBrowser", "ChannelSelection", "MovieSelection", "MoviePlayer", "SecondInfoBar", "GraphMultiEPG", "EventView", "EPGSelection", "MessageBox", "InputBox", "ChoiceBox", "Mute", "Volume", "MerlinMusicPlayer2Screen", "MerlinMusicPlayer2Screen_%s" %(ArchString), "MerlinMusicPlayer2ScreenSaver", "MerlinMusicPlayer2ScreenSaver_%s" %(ArchString)]
184 # list of themes
185 themeList = ["ColorTheme", "SkinPathTheme", "FontTheme",  "BorderSetTheme", "WindowStyleScrollbarTheme", "ComponentTheme", "LayoutTheme", "GlobalsTheme", "PNGTheme" ]
186
187 # shared functions
188 # ImageCreator
189 import Image
190
191 class ImageCreator:
192         def __init__(self):
193                 pass
194
195         def createRectangle(self, width, height, color, filename):
196                 image = Image.new(mode='RGBA',size=(width,height),color=color)
197                 image.save(filename)
198
199 imageCreator = ImageCreator()
200
201 def hex2argb(value):
202         value = value.lstrip('#')
203         lv = len(value)
204         return tuple(int(value[i:i+lv/4], 16) for i in range(0, lv, lv/4))
205         
206 def XMLindent(elem, level):
207         i = "\n" + (level*"    ")
208         #a = "\n%%-%ds" % level
209         #i = a % '  '
210                 
211         if len(elem):
212                 if not elem.text or not elem.text.strip():
213                         elem.text = i + "    "
214                 if not elem.tail or not elem.tail.strip():
215                         elem.tail = i
216                 for elem in elem:
217                         XMLindent(elem, level+1)
218                 if not elem.tail or not elem.tail.strip():
219                         elem.tail = i
220         else:
221                 if level and (not elem.tail or not elem.tail.strip()):
222                         elem.tail = i
223
224 import datetime
225
226 def setThemes(themeFile=None, skinFile=None, configDict=None):
227         # set all "inactive", set new theme "active"
228         curTheme = Tree.parse(themeFile)
229         rootTheme = curTheme.getroot()
230
231         curSkin = Tree.parse(skinFile)
232         rootSkin = curSkin.getroot()
233
234         if rootSkin.find("merlinskinthemes") is None:
235                 mst = Tree.Element("merlinskinthemes", {"text":"Edited with MerlinSkinThemes"})
236                 rootSkin.insert(0, mst)
237
238         for theme in [("colortheme", "colors", "color"), ("fonttheme", "fonts", "font"), ("layouttheme", "layouts", "layout"), ("globalstheme", "globals", ""), ("bordersettheme", "", "borderset"), ("windowstylescrollbartheme", "", ""), ("componenttheme", "components", ""),("pngtheme", "", "")]:
239                 #find colortheme in themes.xml
240                 if rootTheme.find(theme[0]) is not None:
241                         # loop themes in selected theme
242                         for currenttheme in rootTheme.findall(theme[0]):
243                                 attributeDict = {}
244                                 # find selected theme
245                                 if configDict is None:
246                                         currentValue = config.plugins.MerlinSkinThemes.Themes[theme[0]].value
247                                 else:
248                                         currentValue = configDict.get("config.plugins.MerlinSkinThemes.Themes.%s" %(theme[0]), None)
249                                 if currenttheme.get("name") == currentValue:
250                                         # set theme active
251                                         currenttheme.set("value", "active")
252                                         # find all in skin.xml
253                                         if (theme[1] != "" and theme[2] != ""):
254                                                 skinElement = rootSkin.find(theme[1])
255                                                 # delete all in skin.xml
256                                                 if theme[1] != "layouts" and theme[1] != "components":
257                                                         for element in skinElement.findall(theme[2]):
258                                                                 skinElement.remove(element)
259                                         if theme[1] != "":                              
260                                                 # find all in themes.xml
261                                                 themeElement = currenttheme.find(theme[1])
262                                         # add all elements from themes.xml to skin.xml
263                                         if themeElement is not None:
264                                                 if theme[1] in ["layouts","components","globals"]:
265                                                         skinElement = rootSkin.find(theme[1])
266                                                         rootSkin.remove(skinElement)
267                                                         rootSkin.append(Tree.fromstring(Tree.tostring(themeElement)))
268                                                 elif theme[2] != "":
269                                                         for childElement in themeElement.findall(theme[2]):
270                                                                 if theme[0] in ["colortheme", "fonttheme"]:
271                                                                         name = childElement.get("name", None)
272                                                                         if name is not None:
273                                                                                 attributeDict["name"] = name
274                                                                         value = childElement.get("value", None)
275                                                                         if value is not None:
276                                                                                 attributeDict["value"] = value
277                                                                         filename = childElement.get("filename", None)
278                                                                         if filename is not None:
279                                                                                 attributeDict["filename"] = filename
280                                                                         scale = childElement.get("scale", None)
281                                                                         if scale is None and childElement == "font":
282                                                                                 scale = "100"
283                                                                         if scale is not None:
284                                                                                 attributeDict["scale"] = scale
285                                                                         replacement = childElement.get("replacement", None)
286                                                                         if replacement is None and childElement == "font":
287                                                                                 replacement = "0"
288                                                                         if replacement is not None:
289                                                                                 attributeDict["replacement"] = replacement
290                                                 
291                                                                         Tree.SubElement(skinElement, theme[2], attributeDict)
292                                         if theme[0] == "bordersettheme":
293                                                 ws = rootSkin.find("windowstyle")
294                                                 if ws.get("id") == "0":
295                                                         for bs in ws.findall(theme[2]):
296                                                                 if bs.get("name") == "bsWindow":
297                                                                         for px in bs.findall("pixmap"):
298                                                                                 bs.remove(px)
299                                                                                         
300                                                                         for tbs in currenttheme.findall(theme[2]):
301                                                                                 if tbs.get("name") == "bsWindow":
302                                                                                         for tpx in tbs.findall("pixmap"):
303                                                                                                 bs.append(Tree.fromstring(Tree.tostring(tpx)))
304                                                                 if bs.get("name") == "bsListboxEntry":
305                                                                         for px in bs.findall("pixmap"):
306                                                                                 bs.remove(px)
307                                         
308                                                                         for tbs in currenttheme.findall(theme[2]):
309                                                                                 if tbs.get("name") == "bsListboxEntry":
310                                                                                         for tpx in tbs.findall("pixmap"):
311                                                                                                 bs.append(Tree.fromstring(Tree.tostring(tpx)))
312                                         if theme[0] == "windowstylescrollbartheme":
313                                                 for wssb in rootSkin.findall("windowstylescrollbar"):
314                                                         if wssb.get("id") == "4":
315                                                                 for all in wssb.findall("*"):
316                                                                         wssb.remove(all)
317                                                         
318                                                                 for tall in currenttheme.findall("*"):
319                                                                         wssb.append(Tree.fromstring(Tree.tostring(tall)))       
320                                         if theme[0] == "pngtheme":
321                                                 for tp in currenttheme.findall("png"):
322                                                         png_name = tp.get("name")
323                                                         png_width = int(tp.get("width"))
324                                                         png_height = int(tp.get("height"))
325                                                         png_argb = tp.get("argb")
326                                                         acolor = hex2argb(png_argb)
327                                                 
328                                                         if png_name is not None and png_width is not None and png_height is not None and png_argb is not None:
329                                                                 imageCreator.createRectangle(png_width, png_height, (acolor[1], acolor[2], acolor[3], acolor[0]), resolveFilename(SCOPE_SKIN) + SkinName + "/" + png_name) 
330                                                                                                         
331                                 # if name does not match set it to inactive     
332                                 else:
333                                         currenttheme.set("value", "inactive")
334
335         if rootTheme.find("screenthemes") is not None:
336                 themes = rootTheme.find("screenthemes")
337                 for screens in themes.findall("screens"):
338                         for screenname in screenList:
339                                 if screens.get("name") == screenname:
340                                         for screen in screens.findall("screentheme"):
341                                                 if configDict is None:
342                                                         currentValue = config.plugins.MerlinSkinThemes.Screens[screenname].value
343                                                 else:
344                                                         currentValue = configDict.get("config.plugins.MerlinSkinThemes.Screens.%s" %(screenname),None)
345                                                 if screen.get("name") == currentValue:
346                                                         screen.set("value", "active")
347                                                         newscreen = screen.find("screen")
348
349                                                         # delete old screen
350                                                         for SkinScreen in rootSkin.findall("screen"):
351                                                                 if SkinScreen.get("name") == screenname:
352                                                                         rootSkin.remove(SkinScreen)
353                                                         
354                                                         # Set new screen
355                                                         rootSkin.append(Tree.fromstring(Tree.tostring(newscreen)))
356                                                                         
357                                                 else:
358                                                         screen.set("value", "inactive")
359
360         # LCD / OLED / External LCD
361         if displayTag is not None:
362                 if rootTheme.find(displayTag) is not None:
363                         themes = rootTheme.find(displayTag)
364                         for screens in themes.findall("screens"):
365                                 for displayscreenname in displayScreenList:
366                                         if screens.get("name") == displayscreenname:
367                                                 for screen in screens.findall(displayTag[:-1]):
368                                                         if configDict is None:
369                                                                 currentValue = config.plugins.MerlinSkinThemes.DisplayScreens[displayscreenname].value
370                                                         else:
371                                                                 currentValue = configDict.get("config.plugins.MerlinSkinThemes.DisplayScreens.%s" %(displayscreenname), None)
372                                                         if screen.get("name") == currentValue:
373                                                                 screen.set("value", "active")
374                                                                 newscreen = screen.find("screen")
375
376                                                                 # delete old screen
377                                                                 for SkinScreen in rootSkin.findall("screen"):
378                                                                         if SkinScreen.get("name") == displayscreenname and SkinScreen.get("id") == IdString:
379                                                                                 rootSkin.remove(SkinScreen)
380                                                         
381                                                                 # Set new screen
382                                                                 rootSkin.append(Tree.fromstring(Tree.tostring(newscreen)))
383                                                                         
384                                                         else:
385                                                                 screen.set("value", "inactive")
386
387         # corner Radius in skin.xml in allen eLabel ersetzen
388         if config.plugins.MerlinSkinThemes.CornerRadius.value <> "":
389                 for elabel in rootSkin.findall('.//eLabel[@cornerRadius]'):
390                         if 'cornerRadius' in elabel.attrib:
391                                 if rootTheme.find("cornerradius") is not None:
392                                         crtheme = rootTheme.find("cornerradius")
393                                         
394                                         if elabel.get("cornerRadius") <> crtheme.get("exclude"):
395                                                 elabel.set("cornerRadius", config.plugins.MerlinSkinThemes.CornerRadius.value)
396                                                         
397                                                 for r in crtheme.findall("radius"):
398                                                         if r.get("name") == config.plugins.MerlinSkinThemes.CornerRadius.value:
399                                                                 r.set("value", "active")
400                                                         else:
401                                                                 r.set("value", "inactive")
402
403         XMLindent(rootSkin, 0)
404         curSkin.write(skinFile)
405
406         # SkinPathTheme
407         xmlTree = Tree.parse(skinFile)
408         xmlRoot = xmlTree.getroot()
409         xmlString = Tree.tostring(xmlRoot)
410
411         if rootTheme.find("skinpaththemes") is not None:
412                 spt = rootTheme.find("skinpaththemes")
413                 for theme in spt.findall("theme"):
414                         if configDict is None:
415                                 currentValue = config.plugins.MerlinSkinThemes.Themes["skinpaththeme"].value
416                         else:
417                                 currentValue = configDict.get("config.plugins.MerlinSkinThemes.Themes.%s" %(skinpaththeme), None)
418                         if theme.get("name") == currentValue:
419                                 newPath = theme.get("path")
420                                 theme.set("value", "active")
421                         else:
422                                 theme.set("value", "inactive")
423                                         
424                 for theme in spt.findall("theme"):
425                         xmlString = xmlString.replace(theme.get("path"), newPath)
426                 
427                 xmlSkin = open(skinFile, "w")
428                 xmlSkin.write(xmlString)
429                 xmlSkin.close()
430
431         curTheme.write(themeFile)
432
433 class MerlinSkinThemes(Screen, HelpableScreen, ConfigListScreen):
434         skin = """
435                 <screen position="center,center" size="1920,1080" title="%s" backgroundColor="#00808080" >
436                         <widget name="DescLabel" position="10,10" size="1900,40" font="Regular;26" zPosition="2" valign="center" halign="center" />
437
438                         <widget name="ListLabel" position="10,60" size="945,40" font="Regular;26" zPosition="2" valign="center" halign="left" />
439                         <widget name="ImageInfo" position="965,60" size="945,40" font="Regular;26" zPosition="2" halign="left" />
440                         
441                         <widget name="SkinsList" position="10,110" size="945,910" scrollbarMode="showOnDemand" zPosition="1" />
442                         <widget name="config" position="10,110" size="945,910" scrollbarMode="showOnDemand" zPosition="1" /> 
443
444                         <widget name="SkinCopyright" position="965,110" size="945,200" font="Regular;18" zPosition="2" halign="left" />
445                         <widget name="Preview" position="965,320" size="945,700" alphatest="blend" />
446                         
447                         <widget name="key_red" position="10,1030" size="200,40" valign="center" halign="center" zPosition="3" transparent="1" font="Regular;24" />
448                         <widget name="key_green" position="258,1030" size="200,40" valign="center" halign="center" zPosition="3" transparent="1" font="Regular;24" />
449                         <widget name="key_yellow" position="506,1030" size="200,40" valign="center" halign="center" zPosition="3" transparent="1" font="Regular;24" />
450                         <widget name="key_blue" position="755,1030" size="200,40" valign="center" halign="center" zPosition="3" transparent="1" font="Regular;24" />
451
452                         <ePixmap name="red" position="10,1030" zPosition="1" size="200,40" pixmap="skin_default/buttons/red.png" transparent="1" alphatest="blend" />
453                         <ePixmap name="green" position="258,1030" zPosition="1" size="200,40" pixmap="skin_default/buttons/green.png" transparent="1" alphatest="blend" />
454                         <ePixmap name="yellow" position="506,1030" zPosition="1" size="200,40" pixmap="skin_default/buttons/yellow.png" transparent="1" alphatest="blend" />
455                         <ePixmap name="blue" position="755,1030" zPosition="1" size="200,40" pixmap="skin_default/buttons/blue.png" transparent="1" alphatest="blend" />
456                 </screen>"""% ("MerlinSkinThemes")
457
458         ThemeName = ""
459         selSkinName = ""
460         selThemeFile = ""
461         
462         def __init__(self, session):
463                 print "[MST] " + PluginVersion + " running..."
464                 
465                 self.session = session
466                 
467                 Screen.__init__(self, session)
468                 HelpableScreen.__init__(self)
469                 
470                 self.clist = []
471                 ConfigListScreen.__init__(self, self.clist)
472                 
473                 self.setTitle(Title + " " + PluginVersion + " - " + Author)
474
475                 if not SkinUser:
476                         self["ListLabel"] = Label(_("Skinlist") )
477                 else:
478                         self["ListLabel"] = Label(_("Skinlist") + " - ATTENTION: skin_user.xml found!!!")
479                 
480                 self["DescLabel"] = Label(Title + " " + PluginVersion + " " + Author)
481                 self["SkinCopyright"] = Label()
482                 self["Preview"] = Pixmap()
483                 self["ImageInfo"] = Label()
484                 
485                 self.curList = "SkinsList"
486                 
487                 self["key_red"] = Button(_("exit"))
488                 self["key_green"] = Button(_("switch to skin"))
489                 self["key_yellow"] = Button(_("save as design"))
490                 self["key_blue"] = Button(_("open config"))
491                 
492                 self.skinsList = []
493                 self["SkinsList"] = GetSkinsList([])
494
495                 self.onSelectionChanged = [ ]
496                 
497                 self["ColorActions"] = HelpableActionMap(self, "ColorActions",
498                 {
499                         "red":     self.buttonRed,
500                         "green":   self.buttonGreen,
501                         "yellow":  self.buttonYellow,
502                         "blue":    self.openConfig,
503                 }, -1)
504                 
505                 self["DirectionActions"] = HelpableActionMap(self, "DirectionActions",
506                 {
507                         "up":           (self.up, _("Move cursor up")),
508                         "down":         (self.down, _("Move cursor down")),
509                         "left":         (self.left, _("Move cursor left")),
510                         "right":        (self.right, _("Move cursor right")),
511                 }, -1)
512
513                 self["OkCancelActions"] = HelpableActionMap(self, "OkCancelActions",
514                 {
515                         "ok":           (self.ok, ""),
516                         "cancel":       (self.exit, _("Close plugin")),
517                 }, -1)
518
519                 self["TeleTextActions"] = HelpableActionMap(self, "TeleTextActions",
520                 {
521                         "help":         (self.Help, ""),
522                         "info":         (self.Info, ""),
523                 }, -1)
524
525                 self["MenuActions"] = HelpableActionMap(self, "MenuActions",
526                 {
527                         "menu":         (self.MSTMenu, ""),
528                 }, -1)
529                 
530                 self.updateSkinList()
531                 
532                 MerlinSkinThemes.selSkinName = self["SkinsList"].getCurrent()[1][7]
533                 MerlinSkinThemes.selSkinFile = resolveFilename(SCOPE_SKIN) + MerlinSkinThemes.selSkinName + "/skin.xml"
534                 MerlinSkinThemes.selThemeFile = resolveFilename(SCOPE_SKIN) + MerlinSkinThemes.selSkinName + "/themes.xml"
535                 
536                 self.onLayoutFinish.append(self.startRun)
537
538         def openConfig(self):
539                 self.session.open(MerlinSkinThemesConfig)
540
541         def startRun(self):
542                 self["SkinsList"].onSelectionChanged.append(self.changedSkinsList)
543
544                 MerlinSkinThemes.selSkinName = self["SkinsList"].getCurrent()[1][7]
545                 MerlinSkinThemes.selSkinFile = resolveFilename(SCOPE_SKIN) + MerlinSkinThemes.selSkinName + "/skin.xml"
546                 MerlinSkinThemes.selThemeFile = resolveFilename(SCOPE_SKIN) + MerlinSkinThemes.selSkinName + "/themes.xml"
547                 
548                 self["config"].hide()
549                 
550                 self["SkinsList"].moveToIndex(self["SkinsList"].selectedIndex)
551
552                 self.ImageInfo()
553                 if fileExists(MerlinSkinThemes.selSkinFile):
554                         self.CopyrightInfo()
555
556         # parse themes.xml
557         def readThemes(self):
558                 self.clist = []
559
560                 try:
561                         xml = Tree.parse(MerlinSkinThemes.selThemeFile)
562
563                         selSkinList = []
564                         selSkinList.append(MerlinSkinThemes.selSkinName)
565                         config.plugins.MerlinSkinThemes.selSkin = MyConfigSelection(default=MerlinSkinThemes.selSkinName, choices = selSkinList)
566                         self.clist.append(getConfigListEntry(" ", ))
567                         self.clist.append(getConfigListEntry("Skin", config.plugins.MerlinSkinThemes.selSkin))
568                         
569                         #####################
570                         #       -- Designs --   #
571                         #####################
572                         #       <designs>
573                         #               <design>
574                         #                       <xyzTheme />
575                         #               </design>
576                         #       </designs>
577                         # this reads all <design> and its themes that are defined in <designs>
578                         # name of <design> is read and displayed in the section DESIGNS, active one is set as default
579                         self.clist.append(getConfigListEntry(" ", ))
580                         self.clist.append(getConfigListEntry(" " + u'\u00b7' + " DESIGNS", ))
581         
582                         if xml.find("designs") is not None:
583                                 initDesignsDone = False
584                                 ds = xml.find("designs")
585                                 for element in ["design"]:
586                                         elementList = []
587                                         elementList.append("-none-")
588                                         defaultValue = "-none-"
589                                         for design in ds.findall(element):
590                                                 elementList.append(design.get("name"))
591                                                 #if design.get("value") == "active":
592                                                         #defaultValue = design.get("name")
593
594                                 if len(elementList) > 0:
595                                         if not initDesignsDone:
596                                                 initConfigSubDict("Design")
597                                                 initDesignsDone = True
598                                         config.plugins.MerlinSkinThemes.Designs[element] = MyConfigSelection(default=defaultValue, choices = elementList)
599                                         self.clist.append(getConfigListEntry("Design", config.plugins.MerlinSkinThemes.Designs[element]))
600
601                         ################
602                         # -- Themes -- #
603                         ################
604                         # name of theme is read and displayed in the section THEMES, active one is set as default
605                         self.clist.append(getConfigListEntry(" ", ))
606                         self.clist.append(getConfigListEntry(" " + u'\u00b7' + " THEMES", ))
607                         
608                         themesInitDone = False
609                         for element in themeList:
610                                 elementList = []
611                                 defaultValue = None
612                                 if xml.find(element.lower()) is not None:
613                                         for theme in xml.findall(element.lower()):
614                                                 elementList.append(theme.get("name"))
615                                                 if theme.get("value") == "active":
616                                                         defaultValue = theme.get("name")
617                                 
618                                 if len(elementList) > 0:
619                                         if not themesInitDone:
620                                                 initConfigSubDict("Themes")
621                                                 themesInitDone = True
622                                         config.plugins.MerlinSkinThemes.Themes[element.lower()] = MyConfigSelection(default=defaultValue, choices = elementList)
623                                         self.clist.append(getConfigListEntry(element, config.plugins.MerlinSkinThemes.Themes[element.lower()]))
624                         
625                         #################
626                         # -- SCREENS -- #
627                         #################
628                         #       <screenthemes>
629                         #               <!-- multiple screens possible -->
630                         #               <screens name="screenname">
631                         #                       <!-- multiple screentheme possible -->
632                         #                       <screentheme>
633                         #                               <screen>...</screen>
634                         #                       </screentheme>
635                         #               </screens>
636                         #       </screenthemes>
637                         self.clist.append(getConfigListEntry(" ", ))
638                         self.clist.append(getConfigListEntry(" " + u'\u00b7' + " SCREENS", ))
639
640                         if xml.find("screenthemes") is not None:
641                                 st = xml.find("screenthemes")
642                                 initScreenDone = False
643                                 for screens in st.findall("screens"):
644                                         for screenname in screenList:
645                                                 elementList = []
646                                                 defaultValue = None
647                                                 if screens.get("name") == screenname:
648                                                         for themes in screens.findall("screentheme"):
649                                                                 elementList.append(themes.get("name"))
650                                                                 if themes.get("value") == "active":
651                                                                         defaultValue = themes.get("name")
652                                                         if len(elementList)>0:
653                                                                 if not initScreenDone:
654                                                                         initConfigSubDict("Screens")
655                                                                         initScreenDone = True
656                                                                 config.plugins.MerlinSkinThemes.Screens[screenname] = MyConfigSelection(default=defaultValue, choices = elementList)
657                                                                 self.clist.append(getConfigListEntry(screenname, config.plugins.MerlinSkinThemes.Screens[screenname]))
658
659                         #########################
660                         # -- Display Screens -- #
661                         #########################
662                         #       <lcdscreenthemes> / <oledscreenthemes> / <extlcdscreenthemes>
663                         #               <!-- multiple screens possible -->
664                         #               <screens name="screenname">
665                         #                       <!-- multiple lcdscreentheme possible -->
666                         #                       <lcdscreentheme> / <oledscreentheme> / <extlcdscreentheme>
667                         #                               <screen>...</screen>
668                         #                       </lcdscreentheme> / </oledscreentheme> / </extlcdscreentheme>
669                         #               </screens>
670                         #       </lcdscreenthemes> / <oledscreenthemes> / </extlcdscreenthemes>
671                         
672                         if displayTag is not None:                      
673                                 if xml.find(displayTag) is not None:
674                                         self.clist.append(getConfigListEntry(" ", ))
675                                         self.clist.append(getConfigListEntry(" " + u'\u00b7' + " DISPLAY SCREENS ID=%s (%s) %s" %(IdString, ModelString, DisplayXY ), ))                
676                 
677                                         initDisplayScreenDone = False
678                                         for element in displayScreenList:
679                                                 elementList = []
680                                                 defaultValue = None
681                                                 st = xml.find(displayTag)
682                                                 if st.find("screens[@name='%s']" %(element)) is not None:
683                                                         lst = st.find("screens[@name='%s']" %(element))
684                                                         for th in lst.findall(displayTag[:-1]):
685                                                                 for screen in th.findall("screen"):
686                                                                         if screen.get("name") == element and screen.get("id") == IdString:
687                                                                                 elementList.append(th.get("name"))
688                                                                                 if th.get("value") == "active":
689                                                                                         defaultValue = th.get("name")
690                                                                                 
691                                                         if len(elementList) > 0:
692                                                                 if not initDisplayScreenDone:
693                                                                         initConfigSubDict("DisplayScreens")
694                                                                         initDisplayScreenDone = True
695                                                                 config.plugins.MerlinSkinThemes.DisplayScreens[element] = MyConfigSelection(default=defaultValue, choices = elementList)
696                                                                 self.clist.append(getConfigListEntry(element, config.plugins.MerlinSkinThemes.DisplayScreens[element]))
697                         
698                         ######################  
699                         # -- cornerRadius -- #
700                         ######################
701                         #       <cornerradius>
702                         #               <radius />
703                         #       </cornerradius>
704                         if xml.find("cornerradius") is not None:
705                                 self.clist.append(getConfigListEntry(" ", ))
706                                 self.clist.append(getConfigListEntry(" " + u'\u00b7' + " CORNERRADIUS", ))
707
708                                 elementList = []
709                                 defaultValue = None
710                                 cr = xml.find("cornerradius")
711                                 for cradius in cr.findall("radius"):
712                                         elementList.append(cradius.get("name"))
713                                         if cradius.get("value") == "active":
714                                                 defaultValue = cradius.get("name")
715
716                                 if len(elementList) > 0:
717                                         config.plugins.MerlinSkinThemes.CornerRadius = MyConfigSelection(default=defaultValue, choices = elementList)
718                                         self.clist.append(getConfigListEntry("CornerRadius", config.plugins.MerlinSkinThemes.CornerRadius))
719                                                 
720                 except Exception as error:
721                         print "Error", error
722                         print "[MST] themes.xml in " + MerlinSkinThemes.selSkinName + " corrupt!"
723                         self.clist.append(getConfigListEntry(" ", ))
724                         self.clist.append(getConfigListEntry(_(">>> ERROR - themes.xml in " + MerlinSkinThemes.selSkinName + " corrupt! <<<"), ))
725                         
726                 self["config"].setList(self.clist)
727                 
728         def buttonGreen(self):
729                 if self.curList == "SkinsList":
730                         # set new skin
731                         sel = self["SkinsList"].getCurrent()
732                         if sel[1][7] == "Default Skin":
733                                 skinfile = "skin.xml"
734                         else:
735                                 skinfile = "%s/skin.xml" % sel[1][7]
736
737                         # Dr. Best Infobar position
738                         if fileExists("/usr/share/enigma2/merlin_setup.xml"):
739                                 config.merlin2.infobar_position_offset_x.value = 0
740                                 config.merlin2.infobar_position_offset_x.save()
741                                 config.merlin2.infobar_position_offset_y.value = 0
742                                 config.merlin2.infobar_position_offset_y.save()
743                                 config.merlin2.movieplayer_infobar_position_offset_x.value = 0
744                                 config.merlin2.movieplayer_infobar_position_offset_x.save()
745                                 config.merlin2.movieplayer_infobar_position_offset_y.value = 0
746                                 config.merlin2.movieplayer_infobar_position_offset_y.save()
747                                 
748                         config.skin.primary_skin.value = skinfile
749                         config.skin.primary_skin.save()
750                         restartbox = self.session.openWithCallback(self.restartGUI,MessageBox,_("GUI needs a restart to apply a new skin\nDo you want to Restart the GUI now?"), MessageBox.TYPE_YESNO)
751                         restartbox.setTitle(_("Restart GUI now?"))
752                 elif self.curList == "ConfigList":
753                         askBox = self.session.openWithCallback(self.askYN,MessageBox,_("[apply themes] needs time to build new settings\nDo you want to do this now?"), MessageBox.TYPE_YESNO)
754                         askBox.setTitle(_("Apply themes now?"))
755
756         def askYN(self, answer):
757                 if answer is True:
758                         setThemes(MerlinSkinThemes.selThemeFile, MerlinSkinThemes.selSkinFile, None)
759                         config.plugins.MerlinSkinThemes.applied.value = True
760                         config.plugins.MerlinSkinThemes.applied.save()
761                         for x in self["config"].list:
762                                 if len(x) > 1:
763                                         x[1].save()
764                         configfile.save()
765                         if SkinName == MerlinSkinThemes.selSkinName:
766                                 restartbox = self.session.openWithCallback(self.restartGUI,MessageBox,_("GUI needs a restart to apply a new skin\nDo you want to Restart the GUI now?"), MessageBox.TYPE_YESNO)
767                                 restartbox.setTitle(_("Restart GUI now?"))
768                         
769                         else:
770                                 self.session.open(MessageBox, _("Changes to skin " + MerlinSkinThemes.selSkinName + " ready!"), MessageBox.TYPE_INFO)
771
772         def MSTScrFix(self, answer):
773                 if answer is True:
774                         curSkin = Tree.parse(MerlinSkinThemes.selSkinFile)
775                         rootSkin = curSkin.getroot()
776                         mstscreen = rootSkin.find("screen[@name='MerlinSkinThemes']")
777                         rootSkin.remove(mstscreen)
778
779                         XMLindent(rootSkin, 0)
780                         curSkin.write(MerlinSkinThemes.selSkinFile)
781                         
782                         self.updateSkinList()
783
784                         self.session.open(MessageBox, '<screen name="MerlinSkinThemes"...> was removed from selected skin.', MessageBox.TYPE_INFO)
785                         
786         def buttonRed(self):
787                 self.exit()
788                 
789         def buttonYellow(self):
790                 if self.curList == "SkinsList":
791                         if self["SkinsList"].getCurrent()[3][7] == _("no themes.xml"):
792                                 self.createThemes()
793
794                         if self["SkinsList"].getCurrent()[3][7] == _("no skin.xml"):
795                                 self.delSkinDir()
796                                 
797                 elif self.curList == "ConfigList":
798                         if self["config"].getCurrent()[0] == "Design":
799                                 # delete design
800                                 self.deleteDesign()
801                         
802                         else:
803                                 # save as design
804                                 self.session.openWithCallback(self.saveDesign, InputBox, title=_("Please enter designname!"))
805         
806         # write a new design into <designs>     
807         def saveDesign(self, designname):
808                 if designname is not None:
809                 
810                         designname = designname.strip()
811                         
812                         curTree = Tree.parse(MerlinSkinThemes.selThemeFile)
813                         xmlroot = curTree.getroot()
814                         
815                         if xmlroot.find("designs") is None:
816                                 xmldesigns = Tree.SubElement(xmlroot, "designs")
817                         else:
818                                 xmldesigns = xmlroot.find("designs")
819
820                         # check if design exists
821                         if xmldesigns.find("design[@name='" + designname + "']") is not None:
822                                 xmldesigns.remove(xmldesigns.find("design[@name='" + designname + "']"))
823                                 
824                         # write design
825                         xmldesign = Tree.SubElement(xmldesigns, "design", {"name": designname, "value": "active"})
826                         
827                         for element in themeList:
828                                 # remark: for now don't handle it here. Needs alignment
829                                 if element == "SkinPathTheme":
830                                         continue
831                                 # check if theme exists
832                                 if element.lower() in config.plugins.MerlinSkinThemes.Themes.keys():
833                                         if xmlroot.find("%s[@name='" %(element.lower()) + config.plugins.MerlinSkinThemes.Themes[element.lower()].value + "']" ) is not None:
834                                                 if xmldesign.find(element) is not None:
835                                                         td = xmldesign.find(element)
836                                                         td.set("name", config.plugins.MerlinSkinThemes.Themes[element.lower()].value)
837                                                 else:
838                                                         Tree.SubElement(xmldesign, element, {"name": config.plugins.MerlinSkinThemes.Themes[element.lower()].value })
839
840                         # SkinPathThemes
841                         # todo: same check required like for themes? is it really possible to define it in Designs?
842                         if xmlroot.find("skinpaththemes") is not None:
843                                 t = xmlroot.find("skinpaththemes")
844                                 
845                                 if t.find("theme[@name='" + config.plugins.MerlinSkinThemes.Themes["skinpaththemes"].value + "']") is not None:
846                                         if xmldesign.find("SkinPathTheme") is not None:
847                                                 td = xmldesign.find("SkinPathTheme")
848                                                 td.set("name", config.plugins.MerlinSkinThemes.Themes["skinpaththemes"].value)
849                                         else:
850                                                 Tree.SubElement(xmldesign, "SkinPathTheme", {"name": config.plugins.MerlinSkinThemes.Themes["skinpaththemes"].value})
851                                         
852                         # Screens
853                         if xmlroot.find("screenthemes") is not None:
854                                 t = xmlroot.find("screenthemes")
855                                 
856                                 for element in screenList:
857                                         if t.find("screens[@name='%s']" %(element)) is not None:
858                                                 ts = t.find("screens[@name='%s']" %(element))
859                                                 if ts.find("screentheme[@name='" + config.plugins.MerlinSkinThemes.Screens[element].value + "']") is not None:
860                                                         Tree.SubElement(xmldesign, element, {"name": config.plugins.MerlinSkinThemes.Screens[element].value})
861                                 
862                         # LCD Screens
863                         if displayTag is not None:
864                                 if xmlroot.find(displayTag) is not None:
865                                         t = xmlroot.find(displayTag) 
866                                 
867                                         for element in displayScreenList:
868                                                 if t.find("screens[@name='%s']" %(element)) is not None:
869                                                         ts = t.find("screens[@name='%s']" %(element))
870                                                         if ts.find("%s[@name='" %(displayTag[:-1]) + config.plugins.MerlinSkinThemes.DisplayScreens[element].value + "']") is not None:
871                                                         # todo: LCDInfoBar vs. InfoBarSummary!!!! wie geht das?
872                                                                 Tree.SubElement(xmldesign, element, {"name": config.plugins.MerlinSkinThemes.DisplayScreens[element].value})
873                         
874                         # cornerRadius
875                         if xmlroot.find("cornerradius") is not None:
876                                 if xmldesign.find("CornerRadius") is not None:
877                                         td = xmldesign.find("CornerRadius")
878                                         td.set("name", config.plugins.MerlinSkinThemes.CornerRadius.value)
879                                 else:
880                                         Tree.SubElement(xmldesign, "CornerRadius", {"name": config.plugins.MerlinSkinThemes.CornerRadius.value})
881                                                 
882                         XMLindent(xmlroot, 0)
883                         
884                         curTree.write(MerlinSkinThemes.selThemeFile)
885                                 
886                         self.readThemes()
887                                 
888         def deleteDesign(self):
889                 if config.plugins.MerlinSkinThemes.Designs["design"].value == "-none-":
890                         self.session.open(MessageBox,_("nothing to delete"), MessageBox.TYPE_ERROR)
891                 else:
892                         curTree = Tree.parse(MerlinSkinThemes.selThemeFile)
893                         xmlroot = curTree.getroot()
894                         designs = xmlroot.find("designs")
895                         for design in designs.findall("design"):
896                                 if design.get("name") == config.plugins.MerlinSkinThemes.Designs["design"].value:
897                                         designs.remove(design)
898                         
899                                         XMLindent(xmlroot, 0)
900
901                                         curTree.write(MerlinSkinThemes.selThemeFile)
902                 
903                                         self.readThemes()
904         
905         # update screen when a different design is selected in section DESIGNS
906         def setDesign(self):
907                 curTree = Tree.parse(MerlinSkinThemes.selThemeFile)
908                 xmlroot = curTree.getroot()
909                 designs = xmlroot.find("designs")
910                 for design in designs.findall("design"):
911                         # design matches the currently selected design in section DESIGN
912                         if design.get("name") == config.plugins.MerlinSkinThemes.Designs["design"].value:
913                                 # for each theme in the design set the value to the selected design
914                                 for element in themeList:
915                                         tmp = design.find(element)
916                                         if tmp is not None:
917                                                 try:
918                                                         if tmp.get("name", None) is not None:
919                                                                 config.plugins.MerlinSkinThemes.Themes[element.lower()].value = tmp.get("name")
920                                                 except:
921                                                         print "[MST] %s not found" %(element)
922
923                                 # for each screen in the design set the value to the selected design
924                                 for screenname in screenList:
925                                         elementList = []
926                                         defaultValue = None
927                                         tmp = design.find(screenname)
928                                         if tmp is not None:
929                                                 try:
930                                                         if tmp.get("name", None) is not None:
931                                                                 config.plugins.MerlinSkinThemes.Screens[screenname].value = tmp.get("name")
932                                                 except:
933                                                         print "[MST] %s not found" %(screenname)
934
935                                 #todo: maybe merge all displays into one config
936                                 # for each LCD screen in the design set the value to the selected design
937                                 for lcdscreen in displayScreenList:
938                                         if design.find(lcdscreen) is not None:
939                                                 tmp = design.find(lcdscreen)
940                                                 if tmp is not None:
941                                                         try:
942                                                                 if tmp.get("name", None) is not None:
943                                                                         config.plugins.MerlinSkinThemes.DisplayScreens[lcdscreen].value = tmp.get("name")
944                                                         except:
945                                                                 print "[MST] %s not found"
946                         
947                                 # for each corner radius in the design set the value to the selected design
948                                 if design.find("CornerRadius") is not None:
949                                         tmp = design.find("CornerRadius")
950                                         if tmp is not None:
951                                                 try:
952                                                         if tmp.get("name", None) is not None:
953                                                                 config.plugins.MerlinSkinThemes.CornerRadius.value = tmp.get("name")
954                                                 except:
955                                                         print "[MST] CornerRadius not found"                                    
956                 
957                                 # refresh Screen
958                                 self["config"].setList(self.clist)
959                                                 
960         def ok(self):
961                 if self.curList == "SkinsList":
962                         if self["SkinsList"].getCurrent()[3][7] == "":
963                                 self.curList = "ConfigList"
964                                 
965                                 if not SkinUser:
966                                         self["ListLabel"].setText(_("Configlist") )
967                                 else:
968                                         self["ListLabel"].setText(_("Configlist") + " - ATTENTION: skin_user.xml found!!!")
969
970                                 if fileExists(MerlinSkinThemes.selSkinFile):
971                                         self.CopyrightInfo()
972                                         
973                                 self.readThemes()
974
975                                 if self["config"].getCurrent()[0] == "Design":
976                                         self["key_green"].setText(_("apply themes"))
977                                         self["key_yellow"].setText(_("delete design"))
978                                 elif self["config"].getCurrent()[0] == "Skin":
979                                         self["key_green"].setText(_("apply themes"))
980                                         self["key_yellow"].setText(_("save as design"))
981                                 else:
982                                         self["key_green"].setText(_("apply themes"))
983                                         self["key_yellow"].setText(_("save as design"))
984                                 
985                                 self["key_green"].show()
986                                 self["key_yellow"].show()
987                                 
988                                 self["SkinsList"].hide()
989                                 self["config"].show()
990                                 
991                                 config.plugins.MerlinSkinThemes.Skin.value = self["SkinsList"].getCurrent()[1][7]
992                                 
993                         else:
994                                 self.CopyrightInfo()
995                                 self.session.open(MessageBox,_("No themes.xml or skin.xml found.\nPlease select a valid skin including themes.xml"), MessageBox.TYPE_ERROR, title=_("Error"))
996                                 
997                 else:
998                         self.curList = "SkinsList"
999                         
1000                         if not SkinUser:
1001                                 self["ListLabel"].setText(_("Skinlist") )
1002                         else:
1003                                 self["ListLabel"].setText(_("Skinlist") + " - ATTENTION: skin_user.xml found!!!")
1004                         
1005                         self["SkinCopyright"].setText("")
1006                         
1007                         self["key_green"].setText(_("switch to skin"))
1008                         self["key_green"].hide()
1009                         self["key_yellow"].setText("")
1010                         self["key_yellow"].hide()
1011
1012                         #t1 = time.time()
1013                         self.updateSkinList()
1014                         #t2 = time.time()
1015                         #print "[MST] updateSkinList: ", t2 - t1
1016                 
1017                         self["SkinsList"].show()
1018                         self["config"].hide()
1019
1020                         if fileExists(MerlinSkinThemes.selSkinFile):
1021                                 self.CopyrightInfo()
1022                         
1023         def up(self):
1024                 if self.curList == "SkinsList":
1025                         self[self.curList].up()
1026
1027                         if fileExists(MerlinSkinThemes.selSkinFile):
1028                                 self.CopyrightInfo()
1029                         
1030                 else:
1031                         self["config"].instance.moveSelection(self["config"].instance.moveUp)
1032                         if self["config"].getCurrent()[0] == "Design":
1033                                 self["key_green"].setText(_("apply themes"))
1034                                 self["key_yellow"].setText(_("delete design"))
1035                         elif self["config"].getCurrent()[0] == "Skin":
1036                                 self["key_green"].setText(_("apply themes"))
1037                                 self["key_yellow"].setText(_("save as design"))
1038                         else:
1039                                 self["key_green"].setText(_("apply themes"))
1040                                 self["key_yellow"].setText(_("save as design"))
1041         
1042         def down(self):
1043                 if self.curList == "SkinsList":
1044                         self[self.curList].down()
1045
1046                         if fileExists(MerlinSkinThemes.selSkinFile):
1047                                 self.CopyrightInfo()
1048                         
1049                 else:
1050                         self["config"].instance.moveSelection(self["config"].instance.moveDown)
1051                         if self["config"].getCurrent()[0] == "Design":
1052                                 self["key_green"].setText(_("apply themes"))
1053                                 self["key_yellow"].setText(_("delete design"))
1054                         elif self["config"].getCurrent()[0] == "Skin":
1055                                 self["key_green"].setText(_("apply themes"))
1056                                 self["key_yellow"].setText(_("save as design"))
1057                         else:
1058                                 self["key_green"].setText(_("apply themes"))
1059                                 self["key_yellow"].setText(_("save as design"))
1060         
1061         def left(self):
1062                 if self.curList == "SkinsList":
1063                         self[self.curList].pageUp()
1064                 else:
1065                         ConfigListScreen.keyLeft(self)
1066
1067                         if self["config"].getCurrent()[0] in myList:
1068                                 # PreviewPNG anzeigen
1069                                 pngpath = resolveFilename(SCOPE_SKIN) + MerlinSkinThemes.selSkinName + "/preview/" + self["config"].getCurrent()[0] + "/" + self["config"].getCurrent()[1].value + ".png"
1070
1071                                 if not fileExists(pngpath):
1072                                         pngpath = resolveFilename(SCOPE_PLUGINS) + "Extensions/MerlinSkinThemes/noprev.png"
1073
1074                                 self["Preview"].instance.setPixmapFromFile(pngpath)
1075                                 self["Preview"].show()
1076
1077                         if self["config"].getCurrent()[0] == "Design":
1078                                 if config.plugins.MerlinSkinThemes.Designs["design"].value == "-none-":
1079                                         self.readThemes()
1080                                 else:
1081                                         # PreviewPNG anzeigen
1082                                         pngpath = resolveFilename(SCOPE_SKIN) + MerlinSkinThemes.selSkinName + "/preview/" + config.plugins.MerlinSkinThemes.Designs["design"].value + ".png"
1083
1084                                         if not fileExists(pngpath):
1085                                                 pngpath = resolveFilename(SCOPE_PLUGINS) + "Extensions/MerlinSkinThemes/noprev.png"
1086
1087                                         self["Preview"].instance.setPixmapFromFile(pngpath)
1088                                         self["Preview"].show()
1089                                         
1090                                         self.setDesign()
1091                         else:
1092                                 if config.plugins.MerlinSkinThemes.Designs["design"].value != "-none-":
1093                                         config.plugins.MerlinSkinThemes.Designs["design"].value = "-none-"
1094                                         self["config"].invalidate(("Design", config.plugins.MerlinSkinThemes.Designs["design"]))
1095         
1096         def right(self):
1097                 if self.curList == "SkinsList":
1098                         self[self.curList].pageDown()
1099                 else:
1100                         ConfigListScreen.keyRight(self)
1101
1102                         if self["config"].getCurrent()[0] in myList:
1103                                 # PreviewPNG anzeigen
1104                                 pngpath = resolveFilename(SCOPE_SKIN) + MerlinSkinThemes.selSkinName + "/preview/" + self["config"].getCurrent()[0] + "/" + self["config"].getCurrent()[1].value + ".png"
1105
1106                                 if not fileExists(pngpath):
1107                                         pngpath = resolveFilename(SCOPE_PLUGINS) + "Extensions/MerlinSkinThemes/noprev.png"
1108
1109                                 self["Preview"].instance.setPixmapFromFile(pngpath)
1110                                 self["Preview"].show()
1111                                 
1112                         if self["config"].getCurrent()[0] == "Design":
1113                                 if config.plugins.MerlinSkinThemes.Designs["design"].value == "-none-":
1114                                         self.readThemes()
1115                                 else:
1116                                         # PreviewPNG anzeigen
1117                                         pngpath = resolveFilename(SCOPE_SKIN) + MerlinSkinThemes.selSkinName + "/preview/" + config.plugins.MerlinSkinThemes.Designs["design"].value + ".png"
1118
1119                                         if not fileExists(pngpath):
1120                                                 pngpath = resolveFilename(SCOPE_PLUGINS) + "Extensions/MerlinSkinThemes/noprev.png"
1121
1122                                         self["Preview"].instance.setPixmapFromFile(pngpath)
1123                                         self["Preview"].show()
1124
1125                                         self.setDesign()
1126                         else:
1127                                 if config.plugins.MerlinSkinThemes.Designs["design"].value != "-none-":
1128                                         config.plugins.MerlinSkinThemes.Designs["design"].value = "-none-"
1129                                         self["config"].invalidate(("Design", config.plugins.MerlinSkinThemes.Designs["design"]))
1130         
1131         def changedSkinsList(self):
1132                 self["SkinCopyright"].setText("")
1133                 
1134                 MerlinSkinThemes.selSkinName = self["SkinsList"].getCurrent()[1][7]
1135                 
1136                 MerlinSkinThemes.selSkinFile = resolveFilename(SCOPE_SKIN) + MerlinSkinThemes.selSkinName + "/skin.xml"
1137                 MerlinSkinThemes.selThemeFile = resolveFilename(SCOPE_SKIN) + MerlinSkinThemes.selSkinName + "/themes.xml"
1138                 
1139                 #if fileExists(MerlinSkinThemes.selSkinFile):
1140                 #       self.CopyrightInfo()
1141                         
1142                 if config.plugins.MerlinSkinThemes.ShowPrevPNG.value == "1":
1143                         self.loadPreview()
1144                 
1145                 if self["SkinsList"].getCurrent()[2][7] == _("active skin"):
1146                         self["key_green"].hide()
1147                 else:
1148                         self["key_green"].show()
1149
1150                 if self["SkinsList"].getCurrent()[3][7] == _("no skin.xml"):
1151                         self["key_green"].hide()
1152
1153                         self["key_yellow"].show()
1154                         self["key_yellow"].setText(_("delete"))
1155                         
1156                 elif self["SkinsList"].getCurrent()[3][7] == _("no themes.xml"):
1157                         self["key_green"].show()
1158                         
1159                         self["key_yellow"].show()
1160                         self["key_yellow"].setText(_("create themes"))
1161                         
1162                 else:
1163                         self["key_yellow"].show()
1164
1165                         self["key_yellow"].hide()
1166                         #self.readThemes()
1167                         
1168         def updateSkinList(self):
1169                 self["SkinsList"].buildList()
1170
1171         def createThemes(self):
1172                 if fileExists(MerlinSkinThemes.selThemeFile) == False:
1173                         themes = Tree.Element("themes")
1174                         
1175                         curTree = Tree.parse(MerlinSkinThemes.selSkinFile)
1176                         
1177                         for theme in [("colortheme", "colors", "color"), ("fonttheme", "fonts", "font"), ("layouttheme", "layouts", "layout"), ("globalstheme", "globals", ""), ("bordersettheme", "", "borderset"), ("windowstylescrollbartheme", "", ""), ("pngtheme", "", "")]:
1178                                 parentnode1 = Tree.SubElement(themes, theme[0], {"name": "orginal", "value": "active"})
1179                                 if theme[0] == "globalstheme":
1180                                         childnode1 = Tree.SubElement(parentnode1, theme[1], {"name": "sample", "value": "120,50"})
1181                                 elif theme[1] != "":
1182                                         childnode1 = Tree.SubElement(parentnode1, theme[1])
1183                                 parentnode2 = Tree.SubElement(themes, theme[0], {"name": "orginal - work", "value": "inactive"})
1184                                 if theme[0] == "globalstheme":
1185                                         childnode2 = Tree.SubElement(parentnode2, theme[1], {"name": "sample", "value": "120,50"})
1186                                 elif theme[1] != "":                            
1187                                         childnode2 = Tree.SubElement(parentnode2, theme[1])
1188
1189                                 parentnodeSkin = curTree.find(theme[1])                         
1190                                 if theme[0] in ["colortheme", "fonttheme"]:
1191                                         attributeDict = {}
1192                                         for element in parentnodeSkin.findall(theme[2]):
1193                                                 name = element.get("name", None)
1194                                                 if name is not None:
1195                                                         attributeDict["name"] = name
1196                                                 value = element.get("value", None)
1197                                                 if value is not None:
1198                                                         attributeDict["value"] = value
1199                                                 filename = element.get("filename", None)
1200                                                 if filename is not None:
1201                                                         attributeDict["filename"] = filename
1202                                                 scale = element.get("scale", None)
1203                                                 if scale is None and element == "font":
1204                                                         scale = "100"
1205                                                 if scale is not None:
1206                                                         attributeDict["scale"] = scale
1207                                                 replacement = element.get("replacement", None)
1208                                                 if replacement is None and element == "font":
1209                                                         replacement = "0"
1210                                                 if replacement is not None:
1211                                                         attributeDict["replacement"] = replacement
1212                                         
1213                                                 Tree.SubElement(childnode1, theme[2], attributeDict)
1214                                                 Tree.SubElement(childnode2, theme[2], attributeDict)
1215                                 # todo: check if it can be integrated in if
1216                                 elif theme[0] == "bordersettheme":
1217                                         ws = curTree.find("windowstyle")
1218                                         for bs in ws.findall(theme[2]):
1219                                                 if bs.get("name") == "bsWindow":
1220                                                         parentnode1.append(Tree.fromstring(Tree.tostring(bs)))
1221                                                         parentnode2.append(Tree.fromstring(Tree.tostring(bs)))
1222                         
1223                                                 if bs.get("name") == "bsListboxEntry":
1224                                                         parentnode1.append(Tree.fromstring(Tree.tostring(bs)))
1225                                                         parentnode2.append(Tree.fromstring(Tree.tostring(bs)))  
1226                                 elif theme[0] == "windowstylescrollbartheme":
1227                                         for wssb in curTree.findall("windowstylescrollbar"):
1228                                                 if wssb.get("id") == "4":
1229                                                         for sb in wssb.findall("*"):
1230                                                                 parentnode1.append(Tree.fromstring(Tree.tostring(sb)))
1231                                                                 parentnode2.append(Tree.fromstring(Tree.tostring(sb)))
1232                                 elif theme[0] == "layouttheme":
1233                                         Tree.SubElement(childnode1, theme[2], {"name": "sample"}).append(Tree.Comment('Sample: <widget source="Title" render="Label" position="200,77" size="400,40" halign="left" valign="center" font="Regular; 30" foregroundColor="title" backgroundColor="bg2" transparent="1" zPosition="1" />'))
1234                                         Tree.SubElement(childnode2, theme[2], {"name": "sample"})
1235                                 elif theme[0] == "pngtheme":
1236                                         parentnode1.append(Tree.Comment('Sample: name=path+png_name (root=skindir), argb=a:alpha r:red g:green b:blue'))
1237                                         parentnode1.append(Tree.Comment('<png name="design/progress.png" width="814" height="5" argb="#ff55a0ff" />'))
1238                                         parentnode2.append(Tree.Comment('<png name="design/progress.png" width="814" height="5" argb="#ffffa055" />'))
1239                         
1240                         # screenthemes
1241                         screenthemes = Tree.SubElement(themes, "screenthemes")
1242                         for screenname in screenList:
1243                                 screennode = Tree.SubElement(screenthemes, "screens", {"name": screenname })
1244                                 childnode1 = Tree.SubElement(screennode, "screentheme", {"name": "orginal", "value": "active"})
1245                                 childnode2 = Tree.SubElement(screennode, "screentheme", {"name": "orginal - work", "value": "inactive"})
1246                                 
1247                                 skinScreen = curTree.find("screen[@name='%s']" %(screenname))
1248                                 if skinScreen is not None:
1249                                         childnode1.append(Tree.fromstring(Tree.tostring(skinScreen)))
1250                                         childnode2.append(Tree.fromstring(Tree.tostring(skinScreen)))
1251                         
1252                         # displayscreenthemes
1253                         if displayTag is not None:
1254                                 displayscreenthemes = Tree.SubElement(themes, displayTag)
1255                                 for displayscreenname in displayScreenList: 
1256                                         displayscreennode = Tree.SubElement(displayscreenthemes, "screens", {"name": displayscreenname, "id": IdString})
1257                                         childnode1 = Tree.SubElement(displayscreennode, displayTag[:-1], {"name": "orginal", "value": "active"})
1258                                         childnode2 = Tree.SubElement(displayscreennode, displayTag[:-1], {"name": "orginal - work", "value": "inactive"})
1259                                         skinScreen = curTree.find("screen[@name='%s'][@id='%s']" %(displayscreenname, IdString))
1260                                         if skinScreen is not None:
1261                                                 childnode1.append(Tree.fromstring(Tree.tostring(skinScreen)))
1262                                                 childnode2.append(Tree.fromstring(Tree.tostring(skinScreen)))                           
1263
1264                         # Sort
1265                         XMLindent(themes, 0)
1266                         
1267                         # save xml
1268                         themexml = open(MerlinSkinThemes.selThemeFile, "w")
1269                         themexml.write(Tree.tostring(themes))
1270                         themexml.close()
1271                         
1272                         self.updateSkinList()
1273         
1274         def loadPreview(self):
1275                 pngpath = resolveFilename(SCOPE_SKIN) + MerlinSkinThemes.selSkinName + "/prev.png"
1276
1277                 if not fileExists(pngpath):
1278                         pngpath = resolveFilename(SCOPE_PLUGINS) + "Extensions/MerlinSkinThemes/noprev.png"
1279
1280                 self["Preview"].instance.setPixmapFromFile(pngpath)
1281
1282         def MSTMenu(self):
1283                 if fileExists(MerlinSkinThemes.selSkinFile):
1284                         xml = Tree.parse(MerlinSkinThemes.selSkinFile)
1285                         if xml.find("screen[@name='MerlinSkinThemes']"):
1286                                 MSTFixbox = self.session.openWithCallback(self.MSTScrFix,MessageBox,_("Delete screen to fix new MST version?"), MessageBox.TYPE_YESNO)
1287                                 MSTFixbox.setTitle(_("MST screen found"))
1288                         else:
1289                                 self.session.open(MessageBox, _("No MST screen found in this skin.xml!"), MessageBox.TYPE_INFO)
1290                 
1291         def Help(self):
1292                 if self.curList == "SkinsList":
1293                         HelpText = (
1294                                 _("[OK]\nswitch to themes/designs config screen for selected skin\n\n" + 
1295                                 "[create themes] and [delete]\ntakes some time - please wait\n\n" +
1296                                 '[menu]\nremove <screen name="MerlinSkinThemes"...> from selected skin.'
1297                                 "This can fix a greenscreen if skin is not up to date for MST.")
1298                         )
1299
1300                 elif self.curList == "ConfigList":
1301                         HelpText = (
1302                                 _("[OK]\nswitch to skin selection screen\n\n" + 
1303                                 "[apply themes] takes some time - please wait\n\n" + 
1304                                 "[delete design]\ndelete selected design\n\n" + 
1305                                 "[save as design]\nselected themes/screens stored in new design\n\n" +
1306                                 "choose Design: -none-\nto reset themes to active settings/themes")
1307                         )
1308                 
1309                 self.session.open(MessageBox, HelpText, MessageBox.TYPE_INFO, title=_("MerlinSkinThemes - Help"))
1310
1311         def ImageInfo(self):
1312                 InfoText = "Enigma: " + E2ver + " - "
1313
1314                 if Arch64:
1315                         InfoText += "ARM64: " + _("Yes") + " - "
1316
1317                 if ArchArm:
1318                         InfoText += "ARM: " + _("Yes") + " - "
1319
1320                 if ArchMipsel:
1321                         InfoText += "MIPSEL: " + _("Yes") + " - "       
1322                 
1323                 if Merlin:
1324                         InfoText += "Merlin: " + _("Yes") + " - "
1325                 else:
1326                         InfoText += "Merlin: " + _("No") + " - "
1327
1328                 if GP3:
1329                         InfoText += "GP3: " + GP3ver + " - "
1330                 else:
1331                         InfoText += "GP3: " + _("No") + " - "
1332
1333                 if GP4:
1334                         InfoText += "GP4: " + GP4ver
1335                 else:
1336                         InfoText += "GP4: " + _("No")
1337                 
1338                 self["ImageInfo"].setText(InfoText)
1339                 
1340         def CopyrightInfo(self):
1341                 InfoText = ""
1342                 
1343                 curSkin = Tree.parse(MerlinSkinThemes.selSkinFile)
1344                 rootSkin = curSkin.getroot()
1345                 if rootSkin.find("copyright") is not None:
1346                         copyright = rootSkin.find("copyright")
1347                         if copyright.find("orginal") is not None:
1348                                 org = copyright.find("orginal")
1349
1350                                 oAuthor = org.get("author")
1351                                 if oAuthor is None:
1352                                         oAuthor = ""
1353                                 oVersion = org.get("version")
1354                                 if oVersion is None:
1355                                         oVersion = ""
1356                                 oName = org.get("name")
1357                                 if oName is None:
1358                                         oName = ""
1359                                 oSupport = org.get("supporturl")
1360                                 if oSupport is None:
1361                                         oSupport = ""
1362                                 oLicense = org.get("license")
1363                                 if oLicense is None:
1364                                         oLicense = ""
1365                                 
1366                                 OrgText = (
1367                                         "Skin " + oName + " by " + oAuthor + " - Version " + oVersion + " - " + oSupport + "\n\n" +
1368                                         "License:\n" + oLicense
1369                                 )
1370                         
1371                         else:
1372                                 OrgText = (
1373                                         _("Skin ORGINAL - No info available")
1374                                 )
1375                 
1376                         if copyright.find("mod") is not None:
1377                                 mod = copyright.find("mod")
1378
1379                                 mAuthor = mod.get("author")
1380                                 if mAuthor is None:
1381                                         mAuthor = ""
1382                                 mVersion = mod.get("version")
1383                                 if mVersion is None:
1384                                         mVersion = ""
1385                                 mName = mod.get("name")
1386                                 if mName is None:
1387                                         mName = ""
1388                                 mSupport = mod.get("supporturl")
1389                                 if mSupport is None:
1390                                         mSupport = ""
1391                                 
1392                                 ModText = (
1393                                         "Mod:\nSkin " + mName + " by " + mAuthor + " - Version " + mVersion + " - " + mSupport
1394                                 )
1395                         
1396                         else:
1397                                 ModText = (
1398                                         _("Skin MOD - No info available")
1399                                 )
1400                 
1401                         InfoText = OrgText + "\n\n" + ModText
1402
1403                 else:
1404                         InfoText = _("No copyright info available")
1405                         
1406                 #self.session.open(MessageBox, InfoText, MessageBox.TYPE_INFO, title="About Skin - " + MerlinSkinThemes.selSkinName)
1407                 
1408                 self["SkinCopyright"].setText(InfoText)
1409                 
1410         def rgb2hex(self, r, g, b):
1411                 return "#%02X%02X%02X" % (r,g,b)
1412                 
1413         def hex2rgb(self, value):
1414                 value = value.lstrip('#')
1415                 lv = len(value)
1416                 return tuple(int(value[i:i+lv/3], 16) for i in range(0, lv, lv/3))
1417
1418         def argb2hex(self, a, r, g, b):
1419                 return "#%02X%02X%02X%02X" % (a,r,g,b)
1420                 
1421         def Info(self):
1422                 if config.plugins.MerlinSkinThemes.ShowPrevPNG.value == "1":
1423                         config.plugins.MerlinSkinThemes.ShowPrevPNG.value = "0"
1424                         self.session.open(MessageBox, _("Show prev.png - ") + _("Off"), MessageBox.TYPE_INFO, timeout=3)
1425                         self["Preview"].hide()
1426                 else:
1427                         config.plugins.MerlinSkinThemes.ShowPrevPNG.value = "1"
1428                         self.session.open(MessageBox, _("Show prev.png - ") + _("On"), MessageBox.TYPE_INFO, timeout=3)
1429                         self.loadPreview()
1430                         self["Preview"].show()
1431         
1432         def delSkinDir(self):
1433                 print "[MST] Delete: %s" % resolveFilename(SCOPE_SKIN) + MerlinSkinThemes.selSkinName + "/"
1434                 shutil.rmtree(resolveFilename(SCOPE_SKIN) + MerlinSkinThemes.selSkinName + "/")
1435                 self.updateSkinList()
1436                 
1437         def restartGUI(self, answer):
1438                 if answer is True:
1439                         #self.setTheme()
1440                         self.session.open(TryQuitMainloop, 3)
1441                 else:
1442                         self.exit(False)
1443
1444         def save(self):
1445                 restartbox = self.session.openWithCallback(self.restartGUI,MessageBox,_("Do you want to Restart the GUI now to apply new skin settings?"), MessageBox.TYPE_YESNO)
1446                 restartbox.setTitle(_("Restart GUI now?"))
1447
1448         def exit(self, cancel=True):
1449                 print '[MST] closing'
1450                 self["SkinsList"].onSelectionChanged.remove(self.changedSkinsList)
1451                 if cancel:
1452                         # exit means settings must not be stored
1453                         config.plugins.MerlinSkinThemes.Skin.cancel()
1454                         config.plugins.MerlinSkinThemes.selSkin.cancel()
1455                         config.plugins.MerlinSkinThemes.ShowPrevPNG.cancel()
1456                         config.plugins.MerlinSkinThemes.CornerRadius.cancel()
1457                         config.plugins.MerlinSkinThemes.applied.cancel()
1458                         if "Designs" in config.plugins.MerlinSkinThemes.dict():
1459                                 for key in config.plugins.MerlinSkinThemes.Designs:
1460                                         config.plugins.MerlinSkinThemes.Designs[key].cancel()
1461                         if "Themes" in config.plugins.MerlinSkinThemes.dict():
1462                                 for key in config.plugins.MerlinSkinThemes.Themes:
1463                                         config.plugins.MerlinSkinThemes.Themes[key].cancel()
1464                         if "Screens" in config.plugins.MerlinSkinThemes.dict():
1465                                 for key in config.plugins.MerlinSkinThemes.Screens:
1466                                         config.plugins.MerlinSkinThemes.Screens[key].cancel()
1467                         if "DisplayScreens" in config.plugins.MerlinSkinThemes.dict():
1468                                 for key in config.plugins.MerlinSkinThemes.DisplayScreens:
1469                                         config.plugins.MerlinSkinThemes.DisplayScreens[key].cancel()
1470                 self.close()
1471                 
1472 def main(session, **kwargs):
1473         session.open(MerlinSkinThemes)
1474
1475 def Plugins(path,**kwargs):
1476         list = [PluginDescriptor(name = "MerlinSkinThemes", description = "MerlinSkinThemes", where = PluginDescriptor.WHERE_PLUGINMENU, icon = "plugin.png", fnc = main)]
1477         return list             
1478
1479 class MerlinSkinThemesConfig(Screen, HelpableScreen, ConfigListScreen):
1480         skin = """
1481                 <screen position="center,center" size="600,200" title="Merlin Skin Themes - Config" backgroundColor="#00808080" >
1482                         <widget name="config" position="10,10" size="580,100" scrollbarMode="showOnDemand" zPosition="1" /> 
1483                         <widget name="key_red" position="10,150" size="200,40" valign="center" halign="center" zPosition="3" transparent="1" font="Regular;24" />
1484                         <widget name="key_green" position="390,150" size="200,40" valign="center" halign="center" zPosition="3" transparent="1" font="Regular;24" />
1485                         <ePixmap name="red" position="10,150" zPosition="1" size="200,40" pixmap="skin_default/buttons/red.png" transparent="1" alphatest="blend" />
1486                         <ePixmap name="green" position="390,150" zPosition="1" size="200,40" pixmap="skin_default/buttons/green.png" transparent="1" alphatest="blend" />
1487                 </screen>"""
1488                 
1489         def __init__(self, session):
1490                 Screen.__init__(self, session)
1491                 HelpableScreen.__init__(self)
1492                 
1493                 self["key_red"] = Button(_("Exit"))
1494                 self["key_green"] = Button(_("Save"))
1495
1496                 self["ColorActions"] = HelpableActionMap(self, "ColorActions",
1497                 {
1498                         "red":     (self.closePlugin, _("Close plugin")),
1499                         "green":   (self.saveSettings,_("Save settings")),
1500                 }, -1)
1501                 
1502                 self["OkCancelActions"] = HelpableActionMap(self, "OkCancelActions",
1503                 {
1504                         "ok":           (self.saveSettings, _("Save settings")),
1505                         "cancel":       (self.closePlugin, _("Close plugin")),
1506                 }, -1)
1507
1508                 self.list = []
1509                 self.list.append(getConfigListEntry(_("Rebuild skin on boot"), config.plugins.MerlinSkinThemes.rebuildSkinOnBoot))
1510                 
1511                 ConfigListScreen.__init__(self, self.list)
1512                 
1513                 self["config"].setList(self.list)
1514         
1515         def saveSettings(self):
1516                 config.plugins.MerlinSkinThemes.rebuildSkinOnBoot.save()
1517                 configfile.save()
1518                 self.close()
1519                 
1520         def closePlugin(self):
1521                 config.plugins.MerlinSkinThemes.rebuildSkinOnBoot.cancel()
1522                 configfile.save()
1523                 self.close()
1524
1525 # =================================================================================================
1526
1527 class GetSkinsList(MenuList, MerlinSkinThemes):
1528         SKIN_COMPONENT_KEY = "MerlinSkinThemesList"
1529         SKIN_COMPONENT_DIR_WIDTH = "dirWidth"
1530         SKIN_COMPONENT_STATUS_WIDTH = "statusWidth"
1531         SKIN_COMPONENT_INFO_WIDTH = "infoWidth"
1532
1533         def __init__(self, list, enableWrapAround = True):
1534                 MenuList.__init__(self, list, enableWrapAround, eListboxPythonMultiContent)
1535                 tlf = TemplatedListFonts()
1536                 self.l.setFont(0, gFont(tlf.face(tlf.MEDIUM), tlf.size(tlf.MEDIUM)))
1537                 self.l.setFont(1, gFont(tlf.face(tlf.SMALLER), tlf.size(tlf.SMALLER)))
1538                 self.l.setItemHeight(componentSizes.itemHeight(self.SKIN_COMPONENT_KEY, 30))
1539                 self.selectedIndex = 0
1540                 
1541         def buildList(self):
1542                 list = []
1543                 self.selectedIndex = 0
1544
1545                 sizes = componentSizes[GetSkinsList.SKIN_COMPONENT_KEY]
1546                 configEntryHeight = sizes.get(componentSizes.ITEM_HEIGHT, 30)
1547                 dirWidth = sizes.get(GetSkinsList.SKIN_COMPONENT_DIR_WIDTH, 310)
1548                 statusWidth = sizes.get(GetSkinsList.SKIN_COMPONENT_STATUS_WIDTH, 205)
1549                 infoWidth = sizes.get(GetSkinsList.SKIN_COMPONENT_INFO_WIDTH, 205)
1550                 
1551                 dirs = os.listdir(resolveFilename(SCOPE_SKIN))
1552                 for dir in dirs:
1553                         if os.path.isdir(resolveFilename(SCOPE_SKIN) + dir) is True:
1554                                 curSkinFile = resolveFilename(SCOPE_SKIN) + dir + "/skin.xml"
1555                                 curThemeFile = resolveFilename(SCOPE_SKIN) + dir + "/themes.xml"
1556                                 
1557                                 info = ""
1558                                 status = ""
1559
1560                                 skinxml = False;
1561                                 themexml = False;
1562                                 
1563                                 if fileExists(curSkinFile):
1564                                         skinxml = True;
1565
1566                                 if fileExists(curThemeFile):
1567                                         themexml = True;
1568                                         
1569                                 if skinxml or themexml:
1570                                         if skinxml is False:
1571                                                 info = _("no skin.xml")
1572
1573                                         if themexml is False:
1574                                                 info = _("no themes.xml")
1575
1576                                         if dir == SkinName:
1577                                                 status = _("active skin")
1578
1579                                         res = [
1580                                                 dir,
1581                                                 (eListboxPythonMultiContent.TYPE_TEXT, 5, 0, dirWidth, configEntryHeight, 0, RT_HALIGN_LEFT|RT_VALIGN_CENTER, dir),
1582                                                 (eListboxPythonMultiContent.TYPE_TEXT, 5 + dirWidth, 0, statusWidth, configEntryHeight, 1, RT_HALIGN_RIGHT|RT_VALIGN_CENTER, status),
1583                                                 (eListboxPythonMultiContent.TYPE_TEXT, 5 + dirWidth + statusWidth, 0, infoWidth, configEntryHeight, 1, RT_HALIGN_RIGHT|RT_VALIGN_CENTER, info),
1584                                         ]
1585                                         list.append(res)
1586
1587                                         
1588                 self.list = list.sort()
1589                 for x in range(len(list)):
1590                         if list[x][2][7] == _("active skin"):
1591                                 self.selectedIndex = x
1592
1593                         
1594                 self.l.setList(list)
1595         
1596 # =================================================================================================
1597                 
1598 class MyConfigSelection(ConfigSelection):
1599         def getText(self):
1600                 if self._descr is not None:
1601                         return self._descr
1602                 descr = self._descr = self.description[self.value]
1603                 return descr
1604                 
1605         def getMulti(self, selected):
1606                 if self._descr is not None:
1607                         descr = self._descr
1608                 else:
1609                         descr = self._descr = self.description[self.value]
1610                 if descr:
1611                         return ("text", descr)
1612                 return ("text", descr)