Push Version to 5.7
[enigma2-plugins.git] / weatherplugin / src / setup.py
1 # -*- coding: utf-8 -*-
2 #
3 # WeatherPlugin E2
4 #
5 # Coded by Dr.Best (c) 2012
6 # Support: www.dreambox-tools.info
7 # E-Mail: dr.best@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 Multimedia GmbH.
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 Multimedia GmbH.
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 # for localized messages
24 from . import _
25
26 from enigma import eListboxPythonMultiContent, gFont, RT_HALIGN_LEFT, \
27         RT_VALIGN_CENTER
28 from Screens.Screen import Screen
29 from Screens.MessageBox import MessageBox
30 from Components.MenuList import MenuList
31 from Components.Sources.StaticText import StaticText
32 from Components.ActionMap import ActionMap
33 from Components.ConfigList import ConfigList, ConfigListScreen
34 from Components.config import ConfigSubsection, ConfigText, ConfigSelection, \
35         getConfigListEntry, config, configfile
36 from xml.etree.cElementTree import fromstring as cet_fromstring
37 from twisted.web.client import getPage
38 from urllib import quote as urllib_quote
39
40 def initWeatherPluginEntryConfig():
41         s = ConfigSubsection()
42         s.city = ConfigText(default = "Heidelberg", visible_width = 100, fixed_size = False)
43         s.degreetype = ConfigSelection(choices = [("C", _("metric system")), ("F", _("imperial system"))], default = "C")
44         s.weatherlocationcode = ConfigText(default = "", visible_width = 100, fixed_size = False)
45         config.plugins.WeatherPlugin.Entry.append(s)
46         return s
47
48 def initConfig():
49         count = config.plugins.WeatherPlugin.entrycount.value
50         if count != 0:
51                 i = 0
52                 while i < count:
53                         initWeatherPluginEntryConfig()
54                         i += 1
55
56 class MSNWeatherPluginEntriesListConfigScreen(Screen):
57         skin = """
58                 <screen name="MSNWeatherPluginEntriesListConfigScreen" position="center,center" size="550,400">
59                         <widget render="Label" source="city" position="5,60" size="400,50" font="Regular;20" halign="left"/>
60                         <widget render="Label" source="degreetype" position="410,60" size="130,50" font="Regular;20" halign="left"/>
61                         <widget name="entrylist" position="0,80" size="550,300" scrollbarMode="showOnDemand"/>
62                         <widget render="Label" source="key_red" position="0,10" size="140,40" zPosition="5" valign="center" halign="center" backgroundColor="red" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
63                         <widget render="Label" source="key_green" position="140,10" size="140,40" zPosition="5" valign="center" halign="center" backgroundColor="green" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
64                         <widget render="Label" source="key_yellow" position="280,10" size="140,40" zPosition="5" valign="center" halign="center" backgroundColor="yellow" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
65                         <widget render="Label" source="key_blue" position="420,10" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
66                         <ePixmap position="0,10" zPosition="4" size="140,40" pixmap="skin_default/buttons/red.png" transparent="1" alphatest="on" />
67                         <ePixmap position="140,10" zPosition="4" size="140,40" pixmap="skin_default/buttons/green.png" transparent="1" alphatest="on" />
68                         <ePixmap position="280,10" zPosition="4" size="140,40" pixmap="skin_default/buttons/yellow.png" transparent="1" alphatest="on" />
69                         <ePixmap position="420,10" zPosition="4" size="140,40" pixmap="skin_default/buttons/blue.png" transparent="1" alphatest="on" />
70                 </screen>"""
71
72         def __init__(self, session):
73                 Screen.__init__(self, session)
74                 self.title = _("WeatherPlugin: List of Entries")
75                 self["city"] = StaticText(_("City"))
76                 self["degreetype"] = StaticText(_("System"))
77                 self["key_red"] = StaticText(_("Back"))
78                 self["key_green"] = StaticText(_("Add"))                
79                 self["key_yellow"] = StaticText(_("Edit"))
80                 self["key_blue"] = StaticText(_("Delete"))
81                 self["entrylist"] = WeatherPluginEntryList([])
82                 self["actions"] = ActionMap(["WizardActions","MenuActions","ShortcutActions"],
83                         {
84                          "ok"   :       self.keyOK,
85                          "back" :       self.keyClose,
86                          "red"  :       self.keyClose,
87                          "green":       self.keyGreen,                   
88                          "yellow":      self.keyYellow,
89                          "blue":        self.keyDelete,
90                          }, -1)
91                 self.updateList()
92
93         def updateList(self):
94                 self["entrylist"].buildList()
95
96         def keyClose(self):
97                 self.close(-1, None)
98
99         def keyGreen(self):
100                 self.session.openWithCallback(self.updateList,MSNWeatherPluginEntryConfigScreen,None)
101
102         def keyOK(self):
103                 try:sel = self["entrylist"].l.getCurrentSelection()[0]
104                 except: sel = None
105                 self.close(self["entrylist"].getCurrentIndex(), sel)
106
107         def keyYellow(self):
108                 try:sel = self["entrylist"].l.getCurrentSelection()[0]
109                 except: sel = None
110                 if sel is None:
111                         return
112                 self.session.openWithCallback(self.updateList,MSNWeatherPluginEntryConfigScreen,sel)
113
114         def keyDelete(self):
115                 try:sel = self["entrylist"].l.getCurrentSelection()[0]
116                 except: sel = None
117                 if sel is None:
118                         return
119                 self.session.openWithCallback(self.deleteConfirm, MessageBox, _("Really delete this WeatherPlugin Entry?"))
120
121         def deleteConfirm(self, result):
122                 if not result:
123                         return
124                 sel = self["entrylist"].l.getCurrentSelection()[0]
125                 config.plugins.WeatherPlugin.entrycount.value -= 1
126                 config.plugins.WeatherPlugin.entrycount.save()
127                 config.plugins.WeatherPlugin.Entry.remove(sel)
128                 config.plugins.WeatherPlugin.Entry.save()
129                 config.plugins.WeatherPlugin.save()
130                 configfile.save()
131                 self.updateList()
132
133 class WeatherPluginEntryList(MenuList):
134         def __init__(self, list, enableWrapAround = True):
135                 MenuList.__init__(self, list, enableWrapAround, eListboxPythonMultiContent)
136                 self.l.setFont(0, gFont("Regular", 20))
137                 self.l.setFont(1, gFont("Regular", 18))
138
139         def postWidgetCreate(self, instance):
140                 MenuList.postWidgetCreate(self, instance)
141                 instance.setItemHeight(20)
142
143         def getCurrentIndex(self):
144                 return self.instance.getCurrentIndex()
145
146         def buildList(self):
147                 list = []
148                 for c in config.plugins.WeatherPlugin.Entry:
149                         res = [
150                                 c,
151                                 (eListboxPythonMultiContent.TYPE_TEXT, 5, 0, 400, 20, 1, RT_HALIGN_LEFT|RT_VALIGN_CENTER, str(c.city.value)),
152                                 (eListboxPythonMultiContent.TYPE_TEXT, 410, 0, 80, 20, 1, RT_HALIGN_LEFT|RT_VALIGN_CENTER, str(c.degreetype .value)),
153                         ]
154                         list.append(res)
155                 self.list = list
156                 self.l.setList(list)
157                 self.moveToIndex(0)
158
159 class MSNWeatherPluginEntryConfigScreen(ConfigListScreen, Screen):
160         skin = """
161                 <screen name="MSNWeatherPluginEntryConfigScreen" position="center,center" size="550,400">
162                         <widget name="config" position="20,60" size="520,300" scrollbarMode="showOnDemand" />
163                         <ePixmap position="0,10" zPosition="4" size="140,40" pixmap="skin_default/buttons/red.png" transparent="1" alphatest="on" />
164                         <ePixmap position="140,10" zPosition="4" size="140,40" pixmap="skin_default/buttons/green.png" transparent="1" alphatest="on" />
165                         <ePixmap position="420,10" zPosition="4" size="140,40" pixmap="skin_default/buttons/blue.png" transparent="1" alphatest="on" />
166                         <ePixmap position="280,10" zPosition="4" size="140,40" pixmap="skin_default/buttons/yellow.png" transparent="1" alphatest="on" />
167                         <widget source="key_red" render="Label" position="0,10" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
168                         <widget source="key_green" render="Label" position="140,10" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
169                         <widget render="Label" source="key_yellow" position="280,10" size="140,40" zPosition="5" valign="center" halign="center" backgroundColor="yellow" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
170                         <widget source="key_blue" render="Label" position="420,10" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
171                 </screen>"""
172
173         def __init__(self, session, entry):
174                 Screen.__init__(self, session)
175                 self.title = _("WeatherPlugin: Edit Entry")
176                 self["actions"] = ActionMap(["SetupActions", "ColorActions"],
177                 {
178                         "green": self.keySave,
179                         "red": self.keyCancel,
180                         "blue": self.keyDelete,
181                         "yellow": self.searchLocation,
182                         "cancel": self.keyCancel
183                 }, -2)
184
185                 self["key_red"] = StaticText(_("Cancel"))
186                 self["key_green"] = StaticText(_("OK"))
187                 self["key_blue"] = StaticText(_("Delete"))
188                 self["key_yellow"] = StaticText(_("Search Code"))
189
190                 if entry is None:
191                         self.newmode = 1
192                         self.current = initWeatherPluginEntryConfig()
193                 else:
194                         self.newmode = 0
195                         self.current = entry
196
197                 cfglist = [
198                         getConfigListEntry(_("City"), self.current.city),
199                         getConfigListEntry(_("Location code"), self.current.weatherlocationcode),
200                         getConfigListEntry(_("System"), self.current.degreetype)
201                 ]
202
203                 ConfigListScreen.__init__(self, cfglist, session)
204                 
205         def searchLocation(self):
206                 if self.current.city.value != "":
207                         language = config.osd.language.value.replace("_","-")
208                         if language == "en-EN": # hack
209                                 language = "en-US"
210                         elif language == "no-NO": # hack
211                                 language = "nn-NO"
212                         url = "http://weather.service.msn.com/find.aspx?src=outlook&outputview=search&weasearchstr=%s&culture=%s" % (urllib_quote(self.current.city.value), language)
213                         getPage(url).addCallback(self.xmlCallback).addErrback(self.error)
214                 else:
215                         self.session.open(MessageBox, _("You need to enter a valid city name before you can search for the location code."), MessageBox.TYPE_ERROR)
216
217         def keySave(self):
218                 if self.current.city.value != "" and self.current.weatherlocationcode.value != "":
219                         if self.newmode == 1:
220                                 config.plugins.WeatherPlugin.entrycount.value = config.plugins.WeatherPlugin.entrycount.value + 1
221                                 config.plugins.WeatherPlugin.entrycount.save()
222                         ConfigListScreen.keySave(self)
223                         config.plugins.WeatherPlugin.save()
224                         configfile.save()
225                         self.close()
226                 else:
227                         if self.current.city.value == "":
228                                 self.session.open(MessageBox, _("Please enter a valid city name."), MessageBox.TYPE_ERROR)
229                         else:
230                                 self.session.open(MessageBox, _("Please enter a valid location code for the city."), MessageBox.TYPE_ERROR)
231
232         def keyCancel(self):
233                 if self.newmode == 1:
234                         config.plugins.WeatherPlugin.Entry.remove(self.current)
235                 ConfigListScreen.cancelConfirm(self, True)
236
237         def keyDelete(self):
238                 if self.newmode == 1:
239                         self.keyCancel()
240                 else:           
241                         self.session.openWithCallback(self.deleteConfirm, MessageBox, _("Really delete this WeatherPlugin Entry?"))
242
243         def deleteConfirm(self, result):
244                 if not result:
245                         return
246                 config.plugins.WeatherPlugin.entrycount.value = config.plugins.WeatherPlugin.entrycount.value - 1
247                 config.plugins.WeatherPlugin.entrycount.save()
248                 config.plugins.WeatherPlugin.Entry.remove(self.current)
249                 config.plugins.WeatherPlugin.Entry.save()
250                 config.plugins.WeatherPlugin.save()
251                 configfile.save()
252                 self.close()
253                 
254                 
255         def xmlCallback(self, xmlstring):
256                 if xmlstring:
257                         errormessage = ""
258                         root = cet_fromstring(xmlstring)
259                         for childs in root:
260                                 if childs.tag == "weather" and childs.attrib.has_key("errormessage"):
261                                         errormessage = childs.attrib.get("errormessage").encode("utf-8", 'ignore')
262                                         break
263                         if len(errormessage) !=0:
264                                 self.session.open(MessageBox, errormessage, MessageBox.TYPE_ERROR)                                      
265                         else:
266                                 self.session.openWithCallback(self.searchCallback, MSNWeatherPluginSearch, xmlstring)
267                         
268         def error(self, error = None):
269                 if error is not None:
270                         print error
271                 
272         def searchCallback(self, result):
273                 if result:
274                         self.current.weatherlocationcode.value = result[0]
275                         self.current.city.value = result[1]
276         
277                 
278                 
279 class MSNWeatherPluginSearch(Screen):
280         skin = """
281                 <screen name="MSNWeatherPluginSearch" position="center,center" size="550,400">
282                         <widget name="entrylist" position="0,60" size="550,200" scrollbarMode="showOnDemand"/>
283                         <widget render="Label" source="key_red" position="0,10" size="140,40" zPosition="5" valign="center" halign="center" backgroundColor="red" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
284                         <widget render="Label" source="key_green" position="140,10" size="140,40" zPosition="5" valign="center" halign="center" backgroundColor="green" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
285                         <ePixmap position="0,10" zPosition="4" size="140,40" pixmap="skin_default/buttons/red.png" transparent="1" alphatest="on" />
286                         <ePixmap position="140,10" zPosition="4" size="140,40" pixmap="skin_default/buttons/green.png" transparent="1" alphatest="on" />
287                         <ePixmap position="280,10" zPosition="4" size="140,40" pixmap="skin_default/buttons/yellow.png" transparent="1" alphatest="on" />
288                         <ePixmap position="420,10" zPosition="4" size="140,40" pixmap="skin_default/buttons/blue.png" transparent="1" alphatest="on" />
289                 </screen>""" 
290
291         def __init__(self, session, xmlstring):
292                 Screen.__init__(self, session)
293                 self.title = _("MSN location search result")
294                 self["key_red"] = StaticText(_("Back"))
295                 self["key_green"] = StaticText(_("OK"))         
296                 self["entrylist"] = MSNWeatherPluginSearchResultList([])
297                 self["actions"] = ActionMap(["WizardActions","MenuActions","ShortcutActions"],
298                         {
299                          "ok"   :       self.keyOK,
300                          "green": self.keyOK,
301                          "back" :       self.keyClose,
302                          "red": self.keyClose,
303                          }, -1)
304                 self.updateList(xmlstring)
305
306         def updateList(self, xmlstring):
307                 self["entrylist"].buildList(xmlstring)
308
309         def keyClose(self):
310                 self.close(None)
311
312         def keyOK(self):
313                 pass
314                 try:sel = self["entrylist"].l.getCurrentSelection()[0]
315                 except: sel = None
316                 self.close(sel)
317                 
318
319 class MSNWeatherPluginSearchResultList(MenuList):
320         def __init__(self, list, enableWrapAround = True):
321                 MenuList.__init__(self, list, enableWrapAround, eListboxPythonMultiContent)
322                 self.l.setFont(0, gFont("Regular", 20))
323                 self.l.setFont(1, gFont("Regular", 18))
324
325         def postWidgetCreate(self, instance):
326                 MenuList.postWidgetCreate(self, instance)
327                 instance.setItemHeight(44)
328
329         def getCurrentIndex(self):
330                 return self.instance.getCurrentIndex()
331
332         def buildList(self, xml):
333                 root = cet_fromstring(xml)
334                 searchlocation = ""
335                 searchresult = ""
336                 weatherlocationcode = ""
337                 list = []
338                 for childs in root:
339                         if childs.tag == "weather":
340                                 searchlocation = childs.attrib.get("weatherlocationname").encode("utf-8", 'ignore')
341                                 searchresult = childs.attrib.get("weatherfullname").encode("utf-8", 'ignore')
342                                 weatherlocationcode = childs.attrib.get("weatherlocationcode").encode("utf-8", 'ignore')
343                                 res = [
344                                         (weatherlocationcode, searchlocation),
345                                         (eListboxPythonMultiContent.TYPE_TEXT, 5, 0, 500, 20, 1, RT_HALIGN_LEFT|RT_VALIGN_CENTER, searchlocation),
346                                         (eListboxPythonMultiContent.TYPE_TEXT, 5, 22, 500, 20, 1, RT_HALIGN_LEFT|RT_VALIGN_CENTER, searchresult),
347                                 ]
348                                 list.append(res)
349                 self.list = list
350                 self.l.setList(list)
351                 self.moveToIndex(0)