PushService: Fixed load error
[enigma2-plugins.git] / pushservice / src / ConfigScreen.py
1 #######################################################################
2 #
3 #    Push Service for Enigma-2
4 #    Coded by betonme (c) 2012 <glaserfrank(at)gmail.com>
5 #    Support: http://www.i-have-a-dreambox.com/wbb2/thread.php?threadid=167779
6 #
7 #    This program is free software; you can redistribute it and/or
8 #    modify it under the terms of the GNU General Public License
9 #    as published by the Free Software Foundation; either version 2
10 #    of the License, or (at your option) any later version.
11 #
12 #    This program is distributed in the hope that it will be useful,
13 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
14 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 #    GNU General Public License for more details.
16 #
17 #######################################################################
18
19 import sys, traceback
20
21 # Config
22 from Components.config import *
23 from Components.ConfigList import ConfigListScreen
24 from Components.Sources.StaticText import StaticText
25
26 # Screen
27 from Components.ActionMap import ActionMap
28 from Components.ActionMap import HelpableActionMap
29 from Components.ScrollLabel import ScrollLabel
30 from enigma import eSize, ePoint, getDesktop
31 from Screens.Screen import Screen
32 from Screens.Setup import SetupSummary
33 from Screens.ChoiceBox import ChoiceBox
34 from Screens.MessageBox import MessageBox
35 from Screens.HelpMenu import HelpableScreen
36 from Tools.BoundFunction import boundFunction
37
38 # Plugin internal
39 from . import _
40 from PushService import PushService
41 from PushServiceBase import PushServiceBase
42 from ModuleBase import ModuleBase
43 from ServiceBase import ServiceBase
44 from ControllerBase import ControllerBase
45
46
47 # States
48 (MAIN, SERVICES, PLUGINS) = range(3)
49 #IDEA combine into one screen
50 #(MAIN, SERVICES, ADDSERVICE, REMOVESERVICE, PLUGINS, ADDPLUGIN, REMOVEPLUGIN) = range(7)
51
52
53 #######################################################
54 # Configuration screen
55 class ConfigScreen(Screen, ConfigListScreen, HelpableScreen, PushServiceBase):
56
57         skin = """
58                 <screen name="ConfigScreen" title="" position="center,center" size="565,350">
59                         <ePixmap position="0,5" size="140,40" pixmap="skin_default/buttons/red.png" transparent="1" alphatest="on" />
60                         <ePixmap position="140,5" size="140,40" pixmap="skin_default/buttons/green.png" transparent="1" alphatest="on" />
61                         <ePixmap position="280,5" size="140,40" pixmap="skin_default/buttons/yellow.png" transparent="1" alphatest="on" />
62                         <ePixmap position="420,5" size="140,40" pixmap="skin_default/buttons/blue.png" transparent="1" alphatest="on" />
63                         <widget source="key_red" render="Label" position="0,5" zPosition="1" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
64                         <widget source="key_green" render="Label" position="140,5" zPosition="1" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
65                         <widget source="key_yellow" render="Label" position="280,5" zPosition="1" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
66                         <widget source="key_blue" render="Label" position="420,5" zPosition="1" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
67                         <widget name="config" position="5,50" size="555,225" enableWrapAround="1" scrollbarMode="showOnDemand" />
68                         <ePixmap pixmap="skin_default/div-h.png" position="0,275" zPosition="1" size="565,2" />
69                 </screen>
70         """
71
72         def __init__(self, session):
73                 Screen.__init__(self, session)
74                 HelpableScreen.__init__(self)
75                 self.skinName = ["ConfigScreen", "ConfigListScreen"]
76                 
77                 from plugin import NAME, VERSION, gPushService
78                 self.setup_title = NAME + " " + _("Configuration") + " " + VERSION
79                 
80                 PushServiceBase.__init__(self)
81                 if gPushService:
82                         gPushService.stop()
83                 
84                 # Load local plugins to work on
85                 self.load()
86                 
87                 # Buttons
88                 self["key_red"]    = StaticText("")
89                 self["key_green"]  = StaticText("")
90                 self["key_blue"]   = StaticText("")
91                 self["key_yellow"] = StaticText("")
92                 
93                 self.help_window = None
94                 
95                 # Define Actions
96                 #E2 Bug self["custom_actions"] = HelpableActionMap(self, ["SetupActions", "ColorActions", "PushServiceConfigActions"],
97                 self["custom_actions"] = HelpableActionMap(self, "PushServiceConfigActions",
98                 {
99                         "pageUp":                               (self.pageUp,       _("Page up")),
100                         "pageDown":                     (self.pageDown,     _("Page down")),
101                 }, -2) # higher priority
102                 
103                 self["main_actions"] = HelpableActionMap(self, "PushServiceConfigActions",
104                 {
105                         "red":                                  (self.keyCancel,       _("Exit without saving")),
106                         "green":                                (self.keySave,         _("Save and exit")),
107                 }, -2) # higher priority
108                 self["main_actions"].setEnabled(False)
109                 
110                 self["main_actions_enabled"] = HelpableActionMap(self, "PushServiceConfigActions",
111                 {
112                         "yellow":                               (self.showServices,    _("Show Services")),
113                         "blue":                                 (self.showPlugins,     _("Show Plugins")),
114                 }, -2) # higher priority
115                 self["main_actions_enabled"].setEnabled(False)
116                 
117                 self["service_actions"] = HelpableActionMap(self, "PushServiceConfigActions",
118                 {
119                         "red":                                  (self.showMain,        _("Back to main screen")),
120                         "green":                                (self.testService,     _("Test selected Service")),
121                         "yellow":                               (self.addServices,     _("Add Service")),
122                         "blue":                                 (self.removeServices,  _("Remove Service")),
123                 }, -2) # higher priority
124                 self["service_actions"].setEnabled(False)
125                 
126                 self["plugin_actions"] = HelpableActionMap(self, "PushServiceConfigActions",
127                 {
128                         "red":                                  (self.showMain,        _("Back to main screen")),
129                         "green":                                (self.testPlugin,      _("Test selected Plugin")),
130                         "yellow":                               (self.addPlugins,      _("Add Plugin")),
131                         "blue":                                 (self.removePlugins,   _("Remove Plugin")),
132                 }, -2) # higher priority
133                 self["plugin_actions"].setEnabled(False)
134                 
135                 # Initialize Configuration part
136                 self.list = []
137                 self.state = MAIN
138                 self.build()
139                 ConfigListScreen.__init__(self, self.list, session = session, on_change = self.change)
140                 
141                 # Override selectionChanged because our config tuples are bigger
142                 self.onChangedEntry = [ ]
143                 def selectionChanged():
144                         current = self["config"].getCurrent()
145                         if self["config"].current != current:
146                                 if self["config"].current:
147                                         self["config"].current[1].onDeselect(self.session)
148                                 if current:
149                                         current[1].onSelect(self.session)
150                                 self["config"].current = current
151                         for x in self["config"].onSelectionChanged:
152                                 x()
153                 self["config"].selectionChanged = selectionChanged
154                 
155                 self.setTitle(self.setup_title)
156
157         def change(self, uniqueid=None):
158                 select = self.build(uniqueid)
159                 self["config"].setList( self.list )
160                 
161                 if select is not None:
162                         self["config"].instance.moveSelectionTo(select)
163
164         def build(self, uniqueid=None):
165                 self.list = []
166                 select = None
167                 
168                 def buildEntries(entries):
169                         select = None
170                         if entries:
171                                 for idx, entry in enumerate(entries):
172                                         self.list.append( getConfigListEntry( entry.getNameId(), entry.getConfigEnable(), idx ) )
173                                         if entry.getUniqueID() == uniqueid:
174                                                 # Select the added entry
175                                                 select = len(self.list)-1
176                                         if entry.getEnable():
177                                                 for key, element, description in entry.getConfigOptions():
178                                                         self.list.append( getConfigListEntry( "  " + str(description), element, idx ) )
179                         return select
180                 
181                 if self.state == MAIN:
182                         self["key_red"].setText(_("Cancel"))
183                         self["key_green"].setText(_("OK"))
184                         self["service_actions"].setEnabled(False)
185                         self["plugin_actions"].setEnabled(False)
186                         self["main_actions"].setEnabled(True)
187                         if config.pushservice.enable.value:
188                                 self["key_yellow"].setText(_("Services"))
189                                 self["key_blue"].setText(_("Plugins"))
190                                 self["main_actions_enabled"].setEnabled(True)
191                         else:
192                                 self["key_yellow"].setText(_(""))
193                                 self["key_blue"].setText(_(""))
194                                 self["main_actions_enabled"].setEnabled(False)
195                         
196                         self.list.append( getConfigListEntry( _("Enable PushService"), config.pushservice.enable, 0 ) )
197                         
198                         if config.pushservice.enable.value:
199                                 self.list.append( getConfigListEntry( _("Dreambox name"), config.pushservice.boxname, 0 ) )
200                                 self.list.append( getConfigListEntry( _("Config file"), config.pushservice.xmlpath, 0 ) )
201                                 
202                                 self.list.append( getConfigListEntry( _("Start time (HH:MM)"), config.pushservice.time, 0 ) )
203                                 self.list.append( getConfigListEntry( _("Period in hours (0=disabled)"), config.pushservice.period, 0 ) )
204                                 self.list.append( getConfigListEntry( _("Run on boot"), config.pushservice.runonboot, 0 ) )
205                         
206                 elif self.state == SERVICES:
207                         self["key_red"].setText(_("Main"))
208                         self["key_green"].setText(_("Test"))
209                         self["key_yellow"].setText(_("Add service"))
210                         self["key_blue"].setText(_("Remove service"))
211                         self["main_actions"].setEnabled(False)
212                         self["main_actions_enabled"].setEnabled(False)
213                         self["plugin_actions"].setEnabled(False)
214                         self["service_actions"].setEnabled(True)
215                         
216                         select = buildEntries(self.getServices())
217                 
218                 elif self.state == PLUGINS:
219                         self["key_red"].setText(_("Main"))
220                         self["key_green"].setText(_("Test"))
221                         self["key_yellow"].setText(_("Add plugin"))
222                         self["key_blue"].setText(_("Remove plugin"))
223                         self["main_actions"].setEnabled(False)
224                         self["main_actions_enabled"].setEnabled(False)
225                         self["service_actions"].setEnabled(False)
226                         self["plugin_actions"].setEnabled(True)
227                         
228                         select = buildEntries(self.getPlugins())
229                         
230                 return select
231
232         def getCurrentEntry(self):
233                 current = self["config"].getCurrent()
234                 return current and current[0]
235
236         def getCurrentValue(self):
237                 current = self["config"].getCurrent()
238                 value = current and current[1]
239                 return value and str(value.getText()) or ""
240
241         def createSummary(self):
242                 return SetupSummary
243
244         def pageUp(self):
245                 self["config"].instance.moveSelection(self["config"].instance.pageUp)
246
247         def pageDown(self):
248                 self["config"].instance.moveSelection(self["config"].instance.pageDown)
249
250         def showMain(self):
251                 self.hideHelpWindow()
252                 self.state = MAIN
253                 self.change()
254
255         def showServices(self):
256                 self.hideHelpWindow()
257                 self.state = SERVICES
258                 self.change()
259
260         def addServices(self):
261                 self.hideHelpWindow()
262                 self.session.openWithCallback(self.addServicesCB, ChoiceBox,_("Add Service"), self.getAvlServices())
263
264         def addServicesCB(self, result):
265                 module = result and result[1]
266                 if module:
267                         id = self.addService(module)
268                         self.change( id )
269
270         def removeServices(self):
271                 self.hideHelpWindow()
272                 select = 0
273                 current = self["config"].getCurrent()
274                 if current:
275                         select = current[2]
276                 slist = self.getServiceInstances()
277                 if slist:
278                         self.session.openWithCallback(self.removeServicesCB, ChoiceBox,_("Remove plugin"), list=slist, selection=select)
279
280         def removeServicesCB(self, result):
281                 service = result and result[1]
282                 if service:
283                         self.removeService(service)
284                         self.change()
285
286         def showPlugins(self):
287                 self.hideHelpWindow()
288                 self.state = PLUGINS
289                 self.change()
290
291         def addPlugins(self):
292                 self.hideHelpWindow()
293                 self.session.openWithCallback(self.addPluginsCB, ChoiceBox,_("Add Plugin"), self.getAvlPlugins())
294
295         def addPluginsCB(self, result):
296                 module = result and result[1]
297                 if module:
298                         id = self.addPlugin(module)
299                         self.change( id )
300
301         def removePlugins(self):
302                 self.hideHelpWindow()
303                 select = 0
304                 current = self["config"].getCurrent()
305                 if current:
306                         select = current[2]
307                 plist = self.getPluginInstances()
308                 if plist:
309                         self.session.openWithCallback(self.removePluginsCB, ChoiceBox,_("Remove plugin"), list=plist, selection=select)
310
311         def removePluginsCB(self, result):
312                 plugin = result and result[1]
313                 if plugin:
314                         self.removePlugin(plugin)
315                         self.change()
316
317         # Overwrite ConfigListScreen keySave function
318         def keySave(self):
319                 self.hideHelpWindow()
320                 
321                 # Save E2 PushService config
322                 self.saveAll()
323                 
324                 # Build xml config and write it
325                 self.save()
326                 
327                 # If we need assign / "write" access import the plugin
328                 # global won't work across module scope
329                 import plugin
330                 if config.pushservice.enable.value:
331                         if plugin.gPushService:
332                                 plugin.gPushService.copyfrom(self)
333                                 plugin.gPushService.start()
334                         else:
335                                 #global gPushService
336                                 plugin.gPushService = PushService()
337                                 plugin.gPushService.start()
338                 else:
339                         #global gPushService
340                         plugin.gPushService = None
341                 
342                 self.close()
343
344         # Overwrite ConfigListScreen keyCancel function
345         def keyCancel(self):
346                 self.hideHelpWindow()
347                 # Always ask user, because we don't get a change notification from the services or plugins
348                 self.session.openWithCallback(self.cancelConfirm, MessageBox, _("Really close without saving settings?"))
349
350         # Overwrite ConfigListScreen cancelConfirm function
351         def cancelConfirm(self, result):
352                 from plugin import gPushService
353                 if gPushService:
354                         # Make sure the configuration is still consistent
355                         gPushService.load()
356                         gPushService.start()
357                 
358                 # Call baseclass function
359                 ConfigListScreen.cancelConfirm(self, result)
360
361         # Overwrite Screen close function
362         def close(self):
363                 self.hideHelpWindow()
364                 from plugin import ABOUT
365                 self.session.openWithCallback(self.closeConfirm, MessageBox, ABOUT, MessageBox.TYPE_INFO)
366
367         def closeConfirm(self, dummy=None):
368                 # Call baseclass function
369                 Screen.close(self)
370
371         def testService(self):
372                 # Allows testing the actually not saved configuration
373                 #if self.state != SERVICES: return
374                 self.hideHelpWindow()
375                 
376                 # Get the selected Service
377                 current = self["config"].getCurrent()
378                 service = current and self.getService(current[2])
379                 
380                 if service and service.getEnable():
381                         self.session.open(TestConsole, service)
382
383         def testPlugin(self):
384                 # Allows testing the actually not saved configuration
385                 #if self.state != PLUGINS: return
386                 self.hideHelpWindow()
387                 
388                 # Get the selected Plugin
389                 current = self["config"].getCurrent()
390                 plugin = current and self.getPlugin(current[2])
391                 
392                 if plugin and plugin.getEnable():
393                         self.session.open(TestConsole, plugin)
394
395         def hideHelpWindow(self):
396                 current = self["config"].getCurrent()
397                 if current and hasattr(current[1], "help_window"):
398                         help_window = current[1].help_window
399                         if help_window:
400                                 help_window.hide()
401
402
403 class TestConsole(Screen):
404         def __init__(self, session, test):
405                 Screen.__init__(self, session)
406                 self.skinName = ["TestBox", "Console"]
407                 title = ""
408                 text = ""
409                 self.test = test
410                 
411                 self["text"] = ScrollLabel("")
412                 self["actions"] = ActionMap(["WizardActions", "DirectionActions"], 
413                 {
414                         "ok":    self.cancel,
415                         "back":  self.cancel,
416                         "up":    self["text"].pageUp,
417                         "down":  self["text"].pageDown
418                 }, -1)
419                 
420                 # Set title and text
421                 test.begin()
422                 if isinstance(test, ServiceBase):
423                         title = _("Testing Service") + " " + test.getName()
424                         text = _("Testing...\n\nCancel?")
425                 elif isinstance(test, ControllerBase):
426                         title = _("Testing Plugin") + " " + test.getName()
427                         text = _("Testing...\n\nCancel?")
428                 else:
429                         title = _("Testing")
430                         text = _("Nothing to test")
431                 
432                 self.setTitle(title)
433                 self.setText(text)
434                 
435                 # Starting test
436                 try:
437                         if isinstance(test, ServiceBase):
438                                 test.push( self.callback, self.errback, _("PushService Config"), _("Push test"), _("If You can see this, Your configuration is correct.") )
439                         elif isinstance(test, ControllerBase):
440                                 test.run( self.callback, self.errback )
441                 except Exception, e:
442                         text = _("PushService Test exception:") + "\n\n"
443                         exc_type, exc_value, exc_traceback = sys.exc_info()
444                         traceback.print_exception(exc_type, exc_value, exc_traceback, file=sys.stdout)
445                         for line in traceback.format_exception(exc_type, exc_value, exc_traceback):
446                                 text += line
447                         self.setText(text)
448
449         def callback(self, *args):
450                 text = _("Test has been finished successfully") + "\n\n"
451                 if args:
452                         for arg in args:
453                                 text += str(arg) + "\n"
454                 elif self.test and isinstance(self.test, ControllerBase):
455                         text += _("Nothing to push")
456                 self.setText(text)
457
458         def errback(self, *args):
459                 text = ""
460                 for arg in args:
461                         if isinstance(arg, Exception):
462                                 text += _("Test failed:\n\n%s\n\n%s") % (arg.type, arg.value) + "\n"
463                         elif arg:
464                                 text += _("Test failed\n\n%s") % str(arg) + "\n"
465                         else:
466                                 text += _("Test failed") + "\n"
467                 self.setText(text)
468
469         def cancel(self):
470                 if self.test:
471                         self.test.cancel()
472                 self.close()
473
474         def setText(self, text):
475                 self["text"].setText(text)
476
477         def close(self):
478                 if self.test:
479                         self.test.end()
480                 Screen.close(self)