1 # -*- coding: utf-8 -*-
7 # Coded by Dr.Best (c) 2009
8 # Support: www.dreambox-tools.info
10 # This program is free software; you can redistribute it and/or
11 # modify it under the terms of the GNU General Public License
12 # as published by the Free Software Foundation; either version 2
13 # of the License, or (at your option) any later version.
15 # This program is distributed in the hope that it will be useful,
16 # but WITHOUT ANY WARRANTY; without even the implied warranty of
17 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 # GNU General Public License for more details.
21 from Plugins.Plugin import PluginDescriptor
22 from Screens.Screen import Screen
23 from Components.ActionMap import ActionMap
24 from Components.Label import Label
25 from Components.Button import Button
26 from Tools.LoadPixmap import LoadPixmap
27 import xml.etree.cElementTree
28 from twisted.internet import reactor, defer
29 from twisted.web import client
31 from Components.Pixmap import Pixmap
32 from enigma import ePicLoad
35 from enigma import getDesktop
36 from Components.ConfigList import ConfigList, ConfigListScreen
37 from Components.AVSwitch import AVSwitch
38 from Components.ConfigList import ConfigList, ConfigListScreen
39 from Components.config import ConfigSubsection, ConfigSubList, ConfigText, ConfigInteger, config
40 from setup import initConfig, WeatherPluginEntriesListConfigScreen
42 config.plugins.WeatherPlugin = ConfigSubsection()
43 config.plugins.WeatherPlugin.entriescount = ConfigInteger(0)
44 config.plugins.WeatherPlugin.Entries = ConfigSubList()
47 UserAgent = "Mozilla/5.0 (X11; U; Linux x86_64; de; rv:1.9.0.15) Gecko/2009102815 Ubuntu/9.04 (jaunty) Firefox/3."
49 class WeatherIconItem:
50 def __init__(self, url = "", filename = "", index = -1, error = False):
52 self.filename = filename
57 return client.getPage(url, agent=UserAgent)
60 return client.downloadPage(item.url, file(item.filename, 'wb'), agent=UserAgent)
63 def main(session,**kwargs):
64 session.open(WeatherPlugin)
66 def Plugins(**kwargs):
67 list = [PluginDescriptor(name="Weather Plugin", description=_("Weather Plugin"), where = [PluginDescriptor.WHERE_EXTENSIONSMENU], fnc=main)]
71 class WeatherPlugin(Screen):
74 <screen name="WeatherPlugin" position="center,center" size="664,170" title="Weather Plugin">
75 <widget name="caption" position="10,20" zPosition="1" size="300,23" font="Regular;22" transparent="1"/>
76 <widget name="currentTemp" position="10,45" zPosition="1" size="300,23" font="Regular;22" transparent="1"/>
77 <widget name="condition" position="10,80" zPosition="1" size="300,20" font="Regular;18" transparent="1"/>
78 <widget name="wind_condition" position="10,105" zPosition="1" size="300,20" font="Regular;18" transparent="1"/>
79 <widget name="humidity" position="10,130" zPosition="1" size="300,20" font="Regular;18" valign="bottom" transparent="1"/>
80 <widget name="weekday1" position="255,30" zPosition="1" size="72,20" halign="center" valign="center" font="Regular;18" transparent="1"/>
81 <widget name="weekday1_icon" position="255,50" zPosition="1" size="72,72" alphatest="blend"/>
82 <widget name="weekday1_temp" position="241,130" zPosition="1" size="100,20" halign="center" valign="bottom" font="Regular;16" transparent="1"/>
83 <widget name="weekday2" position="358,30" zPosition="1" size="72,20" halign="center" valign="center" font="Regular;18" transparent="1"/>
84 <widget name="weekday2_icon" position="358,50" zPosition="1" size="72,72" alphatest="blend"/>
85 <widget name="weekday2_temp" position="344,130" zPosition="1" size="100,20" halign="center" valign="bottom" font="Regular;16" transparent="1"/>
86 <widget name="weekday3" position="461,30" zPosition="1" size="72,20" halign="center" valign="center" font="Regular;18" transparent="1"/>
87 <widget name="weekday3_icon" position="461,50" zPosition="1" size="72,72" alphatest="blend"/>
88 <widget name="weekday3_temp" position="448,130" zPosition="1" size="100,20" halign="center" valign="bottom" font="Regular;16" transparent="1"/>
89 <widget name="weekday4" position="564,30" zPosition="1" size="72,20" halign="center" valign="center" font="Regular;18" transparent="1"/>
90 <widget name="weekday4_icon" position="564,50" zPosition="1" size="72,72" alphatest="blend"/>
91 <widget name="weekday4_temp" position="550,130" zPosition="1" size="100,20" halign="center" valign="bottom" font="Regular;16" transparent="1"/>
92 <widget name="statustext" position="0,0" zPosition="1" size="664,170" font="Regular;20" halign="center" valign="center" transparent="1"/>
95 def __init__(self, session):
96 self.session = session
97 Screen.__init__(self, session)
98 self["actions"] = ActionMap(["WizardActions", "DirectionActions", "ColorActions", "EPGSelectActions"],
101 "input_date_time": self.config,
102 "right": self.nextItem,
103 "left": self.previousItem
106 self["statustext"] = Label()
108 self["caption"] = Label()
109 self["currentTemp"] = Label()
110 self["condition"] = Label()
111 self["wind_condition"] = Label()
112 self["humidity"] = Label()
114 for i in range(1, 5):
115 self["weekday%s" % i] = Label()
116 self["weekday%s_icon" %i] = WeatherIcon()
117 self["weekday%s_temp" % i] = Label()
119 self.appdir = "/usr/lib/enigma2/python/Plugins/Extensions/WeatherPlugin/icons/"
120 if not os.path.exists(self.appdir):
121 os.mkdir(self.appdir)
123 self.weatherPluginEntryIndex = -1
124 self.weatherPluginEntryCount = config.plugins.WeatherPlugin.entriescount.value
125 if self.weatherPluginEntryCount >= 1:
126 self.weatherPluginEntry = config.plugins.WeatherPlugin.Entries[0]
127 self.weatherPluginEntryIndex = 1
129 self.weatherPluginEntry = None
131 self.onLayoutFinish.append(self.startRun)
134 if self.weatherPluginEntry is not None:
135 self["statustext"].setText(_("Getting weather information..."))
136 url = ("http://www.google.com/ig/api?weather=%s&hl=%s" % (urllib.quote(self.weatherPluginEntry.city.value), self.weatherPluginEntry.language.value))
137 getXML(url).addCallback(self.xmlCallback).addErrback(self.error)
139 self["statustext"].setText(_("No locations defined...\nPress 'Menu' to do that."))
140 self["statustext"].show()
143 if self.weatherPluginEntryCount != 0:
144 if self.weatherPluginEntryIndex < self.weatherPluginEntryCount:
145 self.weatherPluginEntryIndex = self.weatherPluginEntryIndex + 1
147 self.weatherPluginEntryIndex = 1
150 def previousItem(self):
151 if self.weatherPluginEntryCount != 0:
152 if self.weatherPluginEntryIndex >= 2:
153 self.weatherPluginEntryIndex = self.weatherPluginEntryIndex - 1
155 self.weatherPluginEntryIndex = self.weatherPluginEntryCount
159 self.weatherPluginEntry = config.plugins.WeatherPlugin.Entries[self.weatherPluginEntryIndex-1]
163 def clearFields(self):
164 self["caption"].setText("")
165 self["currentTemp"].setText("")
166 self["condition"].setText("")
167 self["wind_condition"].setText("")
168 self["humidity"].setText("")
169 for i in range(1, 5):
170 self["weekday%s" % i].setText("")
171 self["weekday%s_icon" %i].hide()
172 self["weekday%s_temp" % i].setText("")
174 def errorIconDownload(self, error = None, item = None):
177 def finishedIconDownload(self, result, item):
179 self.showIcon(item.index,item.filename)
181 def showIcon(self,index, filename):
182 self["weekday%s_icon" % index].updateIcon(filename)
183 self["weekday%s_icon" % index].show()
185 def xmlCallback(self, xmlstring):
186 self["statustext"].hide()
190 IconDownloadList = []
191 root = xml.etree.cElementTree.fromstring(xmlstring)
192 for childs in root.findall("weather"):
194 if items.tag == "problem_cause":
195 self["statustext"].setText(items.attrib.get("data").encode("utf-8", 'ignore'))
196 self["statustext"].show()
197 if items.tag == "forecast_information":
199 if items2.tag == "city":
200 self["caption"].setText(items2.attrib.get("data").encode("utf-8", 'ignore'))
201 elif items2.tag == "unit_system":
202 if items2.attrib.get("data").encode("utf-8", 'ignore') == "SI":
205 elif items.tag == "current_conditions":
207 if items2.tag == "condition":
208 self["condition"].setText(_("Current: %s") % items2.attrib.get("data").encode("utf-8", 'ignore'))
209 elif items2.tag == "temp_f" and metric == 0:
210 self["currentTemp"].setText( ("%s °F" % items2.attrib.get("data").encode("utf-8", 'ignore')) )
211 elif items2.tag == "temp_c" and metric == 1:
212 self["currentTemp"].setText( ("%s °C" % items2.attrib.get("data").encode("utf-8", 'ignore')) )
213 elif items2.tag == "humidity":
214 self["humidity"].setText(items2.attrib.get("data").encode("utf-8", 'ignore'))
215 elif items2.tag == "wind_condition":
216 self["wind_condition"].setText(items2.attrib.get("data").encode("utf-8", 'ignore'))
217 elif items.tag == "forecast_conditions":
223 if items2.tag == "day_of_week":
224 self["weekday%s" % index].setText(items2.attrib.get("data").encode("utf-8", 'ignore'))
225 if items2.tag == "low":
226 lowTemp = items2.attrib.get("data").encode("utf-8", 'ignore')
227 if items2.tag == "high":
228 highTemp = items2.attrib.get("data").encode("utf-8", 'ignore')
229 self["weekday%s_temp" % index].setText("%s °%s | %s °%s" % (highTemp, UnitSystemText, lowTemp, UnitSystemText))
230 if items2.tag == "icon":
231 url = "http://www.google.com%s" % items2.attrib.get("data").encode("utf-8", 'ignore')
232 parts = string.split(url,"/")
233 filename = self.appdir + parts[-1]
234 if not os.path.exists(filename):
235 IconDownloadList.append(WeatherIconItem(url = url,filename = filename, index = index))
237 self.showIcon(index,filename)
238 if len(IconDownloadList) != 0:
239 ds = defer.DeferredSemaphore(tokens=len(IconDownloadList))
240 downloads = [ds.run(download,item ).addErrback(self.errorIconDownload, item).addCallback(self.finishedIconDownload,item) for item in IconDownloadList]
241 finished = defer.DeferredList(downloads).addErrback(self.error)
244 self.session.openWithCallback(self.setupFinished, WeatherPluginEntriesListConfigScreen)
246 def setupFinished(self, index, entry = None):
247 self.weatherPluginEntryCount = config.plugins.WeatherPlugin.entriescount.value
248 if self.weatherPluginEntryCount >= 1:
249 if entry is not None:
250 self.weatherPluginEntry = entry
251 self.weatherPluginEntryIndex = index + 1
252 if self.weatherPluginEntry is None:
253 self.weatherPluginEntry = config.plugins.WeatherPlugin.Entries[0]
254 self.weatherPluginEntryIndex = 1
256 self.weatherPluginEntry = None
257 self.weatherPluginEntryIndex = -1
262 def error(self, error = None):
263 if error is not None:
265 self["statustext"].setText(str(error.getErrorMessage()))
266 self["statustext"].show()
269 class WeatherIcon(Pixmap):
271 Pixmap.__init__(self)
272 self.IconFileName = ""
273 self.picload = ePicLoad()
274 self.picload.PictureData.get().append(self.paintIconPixmapCB)
278 sc = AVSwitch().getFramebufferScale()
279 self.picload.setPara((self.instance.size().width(), self.instance.size().height(), sc[0], sc[1], 0, 0, '#00000000'))
281 def paintIconPixmapCB(self, picInfo=None):
282 ptr = self.picload.getData()
284 self.instance.setPixmap(ptr.__deref__())
286 def updateIcon(self, filename):
287 new_IconFileName = filename
288 if (self.IconFileName != new_IconFileName):
289 self.IconFileName = new_IconFileName
290 self.picload.startDecode(self.IconFileName)