[WeatherPlugin] small fix for skincomponents
[enigma2-plugins.git] / weatherplugin / src / plugin.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 Plugins.Plugin import PluginDescriptor
27 from Screens.Screen import Screen
28 from Components.ActionMap import ActionMap
29 from Components.Sources.StaticText import StaticText
30 from Components.Pixmap import Pixmap
31 from enigma import ePicLoad, eRect, eSize, gPixmapPtr
32 from Components.AVSwitch import AVSwitch
33 from Components.config import ConfigSubsection, ConfigSubList, ConfigInteger, config
34 from setup import initConfig, MSNWeatherPluginEntriesListConfigScreen
35 from MSNWeather import MSNWeather
36 import time
37
38 try:
39         from Components.WeatherMSN import weathermsn
40         WeatherMSNComp = weathermsn
41 except:
42         WeatherMSNComp = None
43
44 config.plugins.WeatherPlugin = ConfigSubsection()
45 config.plugins.WeatherPlugin.entrycount =  ConfigInteger(0)
46 config.plugins.WeatherPlugin.Entry = ConfigSubList()
47 initConfig()
48
49
50 def main(session,**kwargs):
51         session.open(MSNWeatherPlugin)
52
53 def Plugins(**kwargs):
54         list = [PluginDescriptor(name=_("Weather Plugin"), description=_("Show Weather Forecast"), where = [PluginDescriptor.WHERE_PLUGINMENU, PluginDescriptor.WHERE_EXTENSIONSMENU], icon = "weather.png", fnc=main)]
55         return list
56
57 class MSNWeatherPlugin(Screen):
58
59         skin = """
60                 <screen name="MSNWeatherPlugin" position="center,center" size="720,400" title="Weather Plugin">
61                         <widget render="Label" source="caption" position="10,10" size="700,30" font="Regular;24"/>
62                         <widget render="Label" source="observationtime" position="430,45" size="280,25" font="Regular;16" halign="right" />
63                         <widget render="Label" source="observationpoint" position="110,70" size="600,25" font="Regular;16" halign="right" />
64                         <widget name="currenticon" position="10,115" size="55,45" alphatest="on"/>
65                         <widget render="Label" source="currentTemp" position="90,115" size="100,23" font="Regular;22"/>
66                         <widget render="Label" source="feelsliketemp" position="90,150" size="140,20" font="Regular;14"/>
67                         <widget render="Label" source="condition" position="320,115" size="380,20" font="Regular;18"/>
68                         <widget render="Label" source="wind_condition" position="320,145" size="380,20" font="Regular;18"/>
69                         <widget render="Label" source="humidity" position="320,165" size="380,20" font="Regular;18" valign="bottom"/>
70                         <widget render="Label" source="weekday1" position="35,210" size="105,40" halign="center" valign="center" font="Regular;18"/>
71                         <widget name="weekday1_icon" position="60,265" size="55,45" alphatest="on"/>
72                         <widget render="Label" source="weekday1_temp" position="35,320" size="105,60" halign="center" valign="top" font="Regular;16"/>
73                         <widget render="Label" source="weekday2" position="175,210" size="105,40" halign="center" valign="top" font="Regular;18"/>
74                         <widget name="weekday2_icon" position="200,265" size="55,45" alphatest="on"/>
75                         <widget render="Label" source="weekday2_temp" position="175,320" size="105,60" halign="center" valign="top" font="Regular;16"/>
76                         <widget render="Label" source="weekday3" position="315,210" size="105,40" halign="center" valign="top" font="Regular;18"/>
77                         <widget name="weekday3_icon" position="340,265" size="55,45" alphatest="on"/>
78                         <widget render="Label" source="weekday3_temp" position="315,320" size="105,60" halign="center" valign="top" font="Regular;16"/>
79                         <widget render="Label" source="weekday4" position="455,210" size="105,40" halign="center" valign="top" font="Regular;18"/>
80                         <widget name="weekday4_icon" position="480,265" size="55,45" alphatest="on"/>
81                         <widget render="Label" source="weekday4_temp" position="455,320" size="105,60" halign="center" valign="top" font="Regular;16"/>
82                         <widget render="Label" source="weekday5" position="595,210" size="105,40" halign="center" valign="top" font="Regular;18"/>
83                         <widget name="weekday5_icon" position="620,265" size="55,45" alphatest="on"/>
84                         <widget render="Label" source="weekday5_temp" position="595,320" size="105,60" halign="center" valign="top" font="Regular;16"/>
85                         <widget render="Label" source="statustext" position="0,0" size="720,400" font="Regular;20" halign="center" valign="center" transparent="1"/>
86                 </screen>"""
87         
88         def __init__(self, session):
89                 Screen.__init__(self, session)
90                 self.title = _("Weather Plugin")
91                 self["actions"] = ActionMap(["WizardActions", "DirectionActions", "ColorActions", "EPGSelectActions"],
92                 {
93                         "back": self.close,
94                         "input_date_time": self.config,
95                         "right": self.nextItem,
96                         "left": self.previousItem,
97                         "info": self.showWebsite
98                 }, -1)
99
100                 self["statustext"] = StaticText()
101                 self["currenticon"] = WeatherIcon()
102                 self["caption"] = StaticText()
103                 self["currentTemp"] = StaticText()
104                 self["condition"] = StaticText()
105                 self["wind_condition"] = StaticText()
106                 self["humidity"] = StaticText()
107                 self["observationtime"] = StaticText()
108                 self["observationpoint"] = StaticText()
109                 self["feelsliketemp"] = StaticText()
110                 
111                 i = 1
112                 while i <= 5:
113                         self["weekday%s" % i] = StaticText()
114                         self["weekday%s_icon" %i] = WeatherIcon()
115                         self["weekday%s_temp" % i] = StaticText()
116                         i += 1
117                 del i
118                 
119
120                 self.weatherPluginEntryIndex = -1
121                 self.weatherPluginEntryCount = config.plugins.WeatherPlugin.entrycount.value
122                 if self.weatherPluginEntryCount >= 1:
123                         self.weatherPluginEntry = config.plugins.WeatherPlugin.Entry[0]
124                         self.weatherPluginEntryIndex = 1
125                 else:
126                         self.weatherPluginEntry = None
127
128
129                 self.webSite = ""
130                 
131                 self.weatherData = None
132                 self.onLayoutFinish.append(self.startRun)
133                 self.onClose.append(self.__onClose)
134                 
135         def __onClose(self):
136                 if self.weatherData is not None:
137                         self.weatherData.cancel()
138
139         def startRun(self):
140                 if self.weatherPluginEntry is not None:
141                         self["statustext"].text = _("Getting weather information...")
142                         if self.weatherData is not None:
143                                 self.weatherData.cancel()
144                                 self.weatherData = None
145                         self.weatherData = MSNWeather()
146                         self.weatherData.getWeatherData(self.weatherPluginEntry.degreetype.value, self.weatherPluginEntry.weatherlocationcode.value, self.weatherPluginEntry.city.value, self.getWeatherDataCallback, self.showIcon)
147                 else:
148                         self["statustext"].text = _("No locations defined...\nPress 'Menu' to do that.")
149
150         def nextItem(self):
151                 if self.weatherPluginEntryCount != 0:
152                         if self.weatherPluginEntryIndex < self.weatherPluginEntryCount:
153                                 self.weatherPluginEntryIndex = self.weatherPluginEntryIndex + 1
154                         else:
155                                 self.weatherPluginEntryIndex = 1
156                         self.setItem()
157
158         def previousItem(self):
159                 if self.weatherPluginEntryCount != 0:
160                         if self.weatherPluginEntryIndex >= 2:
161                                 self.weatherPluginEntryIndex = self.weatherPluginEntryIndex - 1
162                         else:
163                                 self.weatherPluginEntryIndex = self.weatherPluginEntryCount
164                         self.setItem()
165
166         def setItem(self):
167                 self.weatherPluginEntry = config.plugins.WeatherPlugin.Entry[self.weatherPluginEntryIndex-1]
168                 self.clearFields()
169                 self.startRun()
170
171         def clearFields(self):
172                 self["caption"].text = ""
173                 self["currentTemp"].text = ""
174                 self["condition"].text = ""
175                 self["wind_condition"].text = ""
176                 self["humidity"].text = ""
177                 self["observationtime"].text = ""
178                 self["observationpoint"].text = ""
179                 self["feelsliketemp"].text = ""
180                 self["currenticon"].hide()
181                 self.webSite = ""
182                 i = 1
183                 while i <= 5:
184                         self["weekday%s" % i].text = ""
185                         self["weekday%s_icon" %i].hide()
186                         self["weekday%s_temp" % i].text = ""
187                         i += 1
188
189         def showIcon(self,index, filename):
190                 if index <> -1:
191                         self["weekday%s_icon" % index].updateIcon(filename)
192                         self["weekday%s_icon" % index].show()
193                 else:
194                         self["currenticon"].updateIcon(filename)
195                         self["currenticon"].show()
196
197         def getWeatherDataCallback(self, result, errortext):
198                 self["statustext"].text = ""
199                 if result == MSNWeather.ERROR:
200                         self.error(errortext)
201                 else:
202                         self["caption"].text = self.weatherData.city
203                         self.webSite = self.weatherData.url
204                         for weatherData in self.weatherData.weatherItems.items():
205                                 item = weatherData[1]
206                                 if weatherData[0] == "-1": # current
207                                         self["currentTemp"].text = "%s%s" % (item.temperature, self.weatherData.degreetype)
208                                         self["condition"].text = item.skytext
209                                         self["humidity"].text = _("Humidity: %s %%") % item.humidity
210                                         self["wind_condition"].text = item.winddisplay
211                                         c =  time.strptime(item.observationtime, "%H:%M:%S")
212                                         self["observationtime"].text = _("Observation time: %s") %  time.strftime("%H:%M",c)
213                                         self["observationpoint"].text = _("Observation point: %s") % item.observationpoint
214                                         self["feelsliketemp"].text = _("Feels like %s") % item.feelslike + "" +  self.weatherData.degreetype
215                                 else:
216                                         index = weatherData[0]
217                                         c = time.strptime(item.date,"%Y-%m-%d")
218                                         self["weekday%s" % index].text = "%s\n%s" % (item.day, time.strftime("%d. %b",c))
219                                         lowTemp = item.low
220                                         highTemp = item.high
221                                         self["weekday%s_temp" % index].text = "%s%s|%s%s\n%s" % (highTemp, self.weatherData.degreetype, lowTemp, self.weatherData.degreetype, item.skytextday)
222                 
223                 if self.weatherPluginEntryIndex == 1 and WeatherMSNComp is not None:
224                         WeatherMSNComp.updateWeather(self.weatherData, result, errortext)
225
226         def config(self):
227                 self.session.openWithCallback(self.setupFinished, MSNWeatherPluginEntriesListConfigScreen)
228
229         def setupFinished(self, index, entry = None):
230                 self.weatherPluginEntryCount = config.plugins.WeatherPlugin.entrycount.value
231                 if self.weatherPluginEntryCount >= 1:
232                         if entry is not None:
233                                 self.weatherPluginEntry = entry
234                                 self.weatherPluginEntryIndex = index + 1
235                         if self.weatherPluginEntry is None:
236                                 self.weatherPluginEntry = config.plugins.WeatherPlugin.Entry[0]
237                                 self.weatherPluginEntryIndex = 1
238                 else:
239                         self.weatherPluginEntry = None
240                         self.weatherPluginEntryIndex = -1
241
242                 self.clearFields()
243                 self.startRun()
244
245         def error(self, errortext):
246                 self.clearFields()
247                 self["statustext"].text = errortext
248
249         def showWebsite(self):
250                 try:
251                         from Plugins.Extensions.Browser.Browser import Browser
252                         if self.webSite:
253                                 self.session.open(Browser, config.plugins.WebBrowser.fullscreen.value, self.webSite, False)
254                 except: pass # I dont care if browser is installed or not...
255
256 class WeatherIcon(Pixmap):
257         def __init__(self):
258                 Pixmap.__init__(self)
259                 self.IconFileName = ""
260                 self.picload = ePicLoad()
261                 self.picload_conn = self.picload.PictureData.connect(self.paintIconPixmapCB)
262
263         def onShow(self):
264                 Pixmap.onShow(self)
265                 sc = AVSwitch().getFramebufferScale()
266                 self._aspectRatio = eSize(sc[0], sc[1])
267                 self._scaleSize = self.instance.size()
268                 self.picload.setPara((self._scaleSize.width(), self._scaleSize.height(), sc[0], sc[1], True, 2, '#ff000000'))
269
270         def paintIconPixmapCB(self, picInfo=None):
271                 ptr = self.picload.getData()
272                 if ptr is not None:
273                         pic_scale_size = eSize()
274                         # To be added in the future:
275                         if 'scale' in eSize.__dict__ and self._scaleSize.isValid() and self._aspectRatio.isValid():
276                                 pic_scale_size = ptr.size().scale(self._scaleSize, self._aspectRatio)
277                         # To be removed in the future:
278                         elif 'scaleSize' in gPixmapPtr.__dict__:
279                                 pic_scale_size = ptr.scaleSize()
280
281                         if pic_scale_size.isValid():
282                                 pic_scale_width = pic_scale_size.width()
283                                 pic_scale_height = pic_scale_size.height()
284                                 dest_rect = eRect(0, 0, pic_scale_width, pic_scale_height)
285                                 self.instance.setScale(1)
286                                 self.instance.setScaleDest(dest_rect)
287                         else:
288                                 self.instance.setScale(0)
289                         self.instance.setPixmap(ptr)
290                 else:
291                         self.instance.setPixmap(None)
292                 
293         def updateIcon(self, filename):
294                 new_IconFileName = filename
295                 if (self.IconFileName != new_IconFileName):
296                         self.IconFileName = new_IconFileName
297                         self.picload.startDecode(self.IconFileName)
298