Merge lp:~jtasker/weather-indicator/cloudy into lp:weather-indicator
- cloudy
- Merge into rainy
Status: | Merged |
---|---|
Approved by: | Joshua Tasker |
Approved revision: | 325 |
Merged at revision: | 312 |
Proposed branch: | lp:~jtasker/weather-indicator/cloudy |
Merge into: | lp:weather-indicator |
Diff against target: |
5722 lines (+2158/-964) 16 files modified
AUTHORS (+1/-0) bin/indicator-weather (+1225/-641) data/indicator-weather.gschema.xml (+25/-0) data/ui/Assistant.ui (+85/-40) data/ui/ExtendedForecast.ui (+129/-14) data/ui/PreferencesDialog.ui (+454/-97) debian/changelog (+35/-0) debian/control (+26/-19) debian/copyright (+29/-10) debian/indicator-weather.install (+1/-0) debian/postinst (+6/-7) debian/rules (+10/-4) indicator_weather/helpers.py (+9/-9) indicator_weather/indicator_weatherconfig.py (+2/-2) po/indicator-weather.pot (+117/-118) setup.py (+4/-3) |
To merge this branch: | bzr merge lp:~jtasker/weather-indicator/cloudy |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Vadim Rutkovsky | Approve | ||
Review via email: mp+164598@code.launchpad.net |
Commit message
Description of the change
This fixes all the "SIGSEGV" bugs related to glib/dbus; (libdbus is not thread-safe - I re-wrote some of the threading code to deal with this)
I also updated it to use Gtk3 and GObject, instead of the now-deprecated PyGtk.
Finally, I added code to calculate humidex/wind chill, and added a related tab to the Preferences Dialog.
Note that this version requires pywapi 0.3.1, which is available here:
http://
deb packages for pywapi 0.3.1 are available here:
https:/
From the changelog:
* Ported to GTK3 and GObject from PyGTK
* Rewrite threading code to avoid dbus-related crashes (LP: #743541)
* Added "feels like" temperature (humidex/heat index/wind chill)
* New "Conditions" tab in Preferences dialog to choose temperature
formulas and toggle display of some condition information
* Bumped version number to reflect massive changes
Note that it still sometimes gives LIBDBUSMENU-GLIB warnings to .xsession-errors, but they can be safely ignored - I have left it running for a week straight with no crashes.
Joshua Tasker (jtasker) wrote : | # |
Vadim Rutkovsky (roignac) wrote : | # |
Great, thanks!
Unfortunately, I can't test the changes, but it seems that you've tested them pretty good
- 320. By Joshua Tasker
-
* Missing comma in debian/control file
- 321. By Joshua Tasker
-
Update changelog
- 322. By Joshua Tasker
-
Fix 4-day forecast display (LP: #1182324)
'OK' button in Preferences Dialog is now more responsive - 323. By Joshua Tasker
-
update changelog
- 324. By Joshua Tasker
-
Prepare for release
- 325. By Joshua Tasker
-
typo in debian/control
Preview Diff
1 | === modified file 'AUTHORS' | |||
2 | --- AUTHORS 2011-03-19 09:27:37 +0000 | |||
3 | +++ AUTHORS 2013-05-22 05:08:27 +0000 | |||
4 | @@ -1,3 +1,4 @@ | |||
5 | 1 | Copyright (C) 2010 Sebastian MacDonald Sebas310@gmail.com | 1 | Copyright (C) 2010 Sebastian MacDonald Sebas310@gmail.com |
6 | 2 | Copyright (C) 2010 Mehdi Rejraji mehd36@gmail.com | 2 | Copyright (C) 2010 Mehdi Rejraji mehd36@gmail.com |
7 | 3 | Copyright (C) 2010 Vadim Rutkovsky roignac@gmail.com | 3 | Copyright (C) 2010 Vadim Rutkovsky roignac@gmail.com |
8 | 4 | Copyright (C) 2013 Joshua Tasker jtasker@gmail.com | ||
9 | 4 | 5 | ||
10 | === modified file 'bin/indicator-weather' | |||
11 | --- bin/indicator-weather 2012-07-30 04:02:24 +0000 | |||
12 | +++ bin/indicator-weather 2013-05-22 05:08:27 +0000 | |||
13 | @@ -4,6 +4,7 @@ | |||
14 | 4 | # Copyright (C) 2010 Sebastian MacDonald Sebas310@gmail.com | 4 | # Copyright (C) 2010 Sebastian MacDonald Sebas310@gmail.com |
15 | 5 | # Copyright (C) 2010 Mehdi Rejraji mehd36@gmail.com | 5 | # Copyright (C) 2010 Mehdi Rejraji mehd36@gmail.com |
16 | 6 | # Copyright (C) 2011 Vadim Rutkovsky roignac@gmail.com | 6 | # Copyright (C) 2011 Vadim Rutkovsky roignac@gmail.com |
17 | 7 | # Copyright (C) 2013 Joshua Tasker jtasker@gmail.com | ||
18 | 7 | # This program is free software: you can redistribute it and/or modify it | 8 | # This program is free software: you can redistribute it and/or modify it |
19 | 8 | # under the terms of the GNU General Public License version 3, as published | 9 | # under the terms of the GNU General Public License version 3, as published |
20 | 9 | # by the Free Software Foundation. | 10 | # by the Free Software Foundation. |
21 | @@ -17,29 +18,26 @@ | |||
22 | 17 | # with this program. If not, see <http://www.gnu.org/licenses/>. | 18 | # with this program. If not, see <http://www.gnu.org/licenses/>. |
23 | 18 | ### END LICENSE | 19 | ### END LICENSE |
24 | 19 | 20 | ||
29 | 20 | try: | 21 | from gi.repository import Gio, GLib, Gtk, Gdk, Notify, GObject, GdkPixbuf |
30 | 21 | from gi.repository import Gio | 22 | from gi.repository import AppIndicator3 as AppIndicator |
31 | 22 | except ImportError: | 23 | |
28 | 23 | pass | ||
32 | 24 | import sys, os, shutil, tempfile | 24 | import sys, os, shutil, tempfile |
36 | 25 | import gtk, pygtk, gobject, pynotify | 25 | |
34 | 26 | pygtk.require('2.0') | ||
35 | 27 | import appindicator | ||
37 | 28 | import urllib2, urllib | 26 | import urllib2, urllib |
38 | 29 | from urllib import urlencode | 27 | from urllib import urlencode |
39 | 30 | import re | 28 | import re |
40 | 31 | import locale | 29 | import locale |
41 | 32 | from xml.dom.minidom import parseString | 30 | from xml.dom.minidom import parseString |
42 | 33 | import datetime | 31 | import datetime |
44 | 34 | import dbus | 32 | #import dbus |
45 | 35 | import time | 33 | import time |
46 | 36 | import traceback | 34 | import traceback |
47 | 37 | import types | 35 | import types |
50 | 38 | # Will be used for humidex | 36 | from math import exp |
49 | 39 | #import math | ||
51 | 40 | import commands, threading | 37 | import commands, threading |
52 | 41 | import logging, logging.handlers | 38 | import logging, logging.handlers |
53 | 42 | import pywapi | 39 | import pywapi |
54 | 40 | import Queue | ||
55 | 43 | 41 | ||
56 | 44 | import gettext | 42 | import gettext |
57 | 45 | from gettext import gettext as _ | 43 | from gettext import gettext as _ |
58 | @@ -55,7 +53,7 @@ | |||
59 | 55 | sys.path.insert(0, PROJECT_ROOT_DIRECTORY) | 53 | sys.path.insert(0, PROJECT_ROOT_DIRECTORY) |
60 | 56 | os.putenv('PYTHONPATH', PROJECT_ROOT_DIRECTORY) # for subprocesses | 54 | os.putenv('PYTHONPATH', PROJECT_ROOT_DIRECTORY) # for subprocesses |
61 | 57 | 55 | ||
63 | 58 | VERSION = "12.07.30 'Cloudy 10'" | 56 | VERSION = "13.05.26 'Rainy'" |
64 | 59 | 57 | ||
65 | 60 | from indicator_weather.helpers import * | 58 | from indicator_weather.helpers import * |
66 | 61 | 59 | ||
67 | @@ -69,11 +67,16 @@ | |||
68 | 69 | WEATHER_KEY = 'weather' | 67 | WEATHER_KEY = 'weather' |
69 | 70 | LOCATIONS_KEY = 'locations' | 68 | LOCATIONS_KEY = 'locations' |
70 | 71 | INDICATOR_DISPLAY = 'show_label' | 69 | INDICATOR_DISPLAY = 'show_label' |
71 | 70 | RELATIVE_DISPLAY = 'show_relative' | ||
72 | 71 | WIND_DISPLAY = 'show_wind' | ||
73 | 72 | SUNTIMES_DISPLAY = 'show_suntimes' | ||
74 | 72 | NOTIFICATIONS = 'notif' | 73 | NOTIFICATIONS = 'notif' |
75 | 73 | WEATHER_SOURCE = 'data_source' | 74 | WEATHER_SOURCE = 'data_source' |
76 | 74 | REFRESH_RATE = 'refresh_rate' | 75 | REFRESH_RATE = 'refresh_rate' |
77 | 75 | METRIC_SYSTEM = 'unit' | 76 | METRIC_SYSTEM = 'unit' |
78 | 76 | WIND_UNIT = 'wind' | 77 | WIND_UNIT = 'wind' |
79 | 78 | HEAT_ESTIMATE = 'heat' | ||
80 | 79 | CHILL_ESTIMATE = 'chill' | ||
81 | 77 | PLACECHOSEN = 'placechosen' | 80 | PLACECHOSEN = 'placechosen' |
82 | 78 | PLACES = 'places' | 81 | PLACES = 'places' |
83 | 79 | 82 | ||
84 | @@ -84,48 +87,70 @@ | |||
85 | 84 | INDICATOR_DISPLAY : { | 87 | INDICATOR_DISPLAY : { |
86 | 85 | INFO_TYPE : types.IntType, | 88 | INFO_TYPE : types.IntType, |
87 | 86 | INFO_SETTING : 'indicator-display' | 89 | INFO_SETTING : 'indicator-display' |
89 | 87 | }, | 90 | }, |
90 | 91 | RELATIVE_DISPLAY : { | ||
91 | 92 | INFO_TYPE : types.BooleanType, | ||
92 | 93 | INFO_SETTING : 'relative-display' | ||
93 | 94 | }, | ||
94 | 95 | WIND_DISPLAY : { | ||
95 | 96 | INFO_TYPE : types.BooleanType, | ||
96 | 97 | INFO_SETTING : 'wind-display' | ||
97 | 98 | }, | ||
98 | 99 | SUNTIMES_DISPLAY : { | ||
99 | 100 | INFO_TYPE : types.BooleanType, | ||
100 | 101 | INFO_SETTING : 'suntimes-display' | ||
101 | 102 | }, | ||
102 | 88 | NOTIFICATIONS : { | 103 | NOTIFICATIONS : { |
103 | 89 | INFO_TYPE : types.StringType, | 104 | INFO_TYPE : types.StringType, |
104 | 90 | INFO_SETTING : 'notifications' | 105 | INFO_SETTING : 'notifications' |
106 | 91 | }, | 106 | }, |
107 | 92 | WEATHER_SOURCE : { | 107 | WEATHER_SOURCE : { |
108 | 93 | INFO_TYPE : types.StringType, | 108 | INFO_TYPE : types.StringType, |
109 | 94 | INFO_SETTING : 'weather-source' | 109 | INFO_SETTING : 'weather-source' |
111 | 95 | }, | 110 | }, |
112 | 96 | REFRESH_RATE : { | 111 | REFRESH_RATE : { |
113 | 97 | INFO_TYPE : types.IntType, | 112 | INFO_TYPE : types.IntType, |
114 | 98 | INFO_SETTING : 'refresh-rate' | 113 | INFO_SETTING : 'refresh-rate' |
116 | 99 | }, | 114 | }, |
117 | 100 | METRIC_SYSTEM : { | 115 | METRIC_SYSTEM : { |
118 | 101 | INFO_TYPE : types.StringType, | 116 | INFO_TYPE : types.StringType, |
119 | 102 | INFO_SETTING : 'metric-system' | 117 | INFO_SETTING : 'metric-system' |
121 | 103 | }, | 118 | }, |
122 | 104 | WIND_UNIT : { | 119 | WIND_UNIT : { |
123 | 105 | INFO_TYPE : types.StringType, | 120 | INFO_TYPE : types.StringType, |
124 | 106 | INFO_SETTING : 'wind-unit' | 121 | INFO_SETTING : 'wind-unit' |
126 | 107 | }, | 122 | }, |
127 | 123 | HEAT_ESTIMATE: { | ||
128 | 124 | INFO_TYPE : types.StringType, | ||
129 | 125 | INFO_SETTING : 'heat-estimate' | ||
130 | 126 | }, | ||
131 | 127 | CHILL_ESTIMATE: { | ||
132 | 128 | INFO_TYPE : types.StringType, | ||
133 | 129 | INFO_SETTING : 'chill-estimate' | ||
134 | 130 | }, | ||
135 | 108 | PLACECHOSEN : { | 131 | PLACECHOSEN : { |
136 | 109 | INFO_TYPE : types.IntType, | 132 | INFO_TYPE : types.IntType, |
137 | 110 | INFO_SETTING: 'placechosen' | 133 | INFO_SETTING: 'placechosen' |
139 | 111 | }, | 134 | }, |
140 | 112 | PLACES : { | 135 | PLACES : { |
141 | 113 | INFO_TYPE : types.ListType, | 136 | INFO_TYPE : types.ListType, |
142 | 114 | INFO_SETTING: 'places' | 137 | INFO_SETTING: 'places' |
144 | 115 | }, | 138 | }, |
145 | 116 | } | 139 | } |
146 | 117 | 140 | ||
147 | 118 | # Open the DB | ||
148 | 119 | def prepare_settings_store(self): | 141 | def prepare_settings_store(self): |
149 | 142 | """ Open the DB """ | ||
150 | 120 | log.debug("Settings: preparing settings store") | 143 | log.debug("Settings: preparing settings store") |
151 | 121 | try: | 144 | try: |
152 | 122 | self.db = Gio.Settings.new(self.BASE_KEY) | 145 | self.db = Gio.Settings.new(self.BASE_KEY) |
153 | 123 | except Exception as e: | 146 | except Exception as e: |
155 | 124 | log.debug("Settings: exception occurred while opening settings:\n %s" % str(e)) | 147 | log.debug("Settings: exception occurred while " |
156 | 148 | "opening settings:\n %s" % str(e)) | ||
157 | 125 | 149 | ||
158 | 126 | # Make sure autostart file is installed. Inspired by GTG. | ||
159 | 127 | def check_autostart(self): | 150 | def check_autostart(self): |
161 | 128 | autostart_dir = os.path.join(os.path.expanduser("~"),".config/autostart/") | 151 | """ Make sure autostart file is installed. Inspired by GTG. """ |
162 | 152 | autostart_dir = os.path.join(os.path.expanduser("~"), | ||
163 | 153 | ".config/autostart/") | ||
164 | 129 | autostart_file = "indicator-weather.desktop" | 154 | autostart_file = "indicator-weather.desktop" |
165 | 130 | autostart_path = os.path.join(autostart_dir, autostart_file) | 155 | autostart_path = os.path.join(autostart_dir, autostart_file) |
166 | 131 | if not os.path.isfile(autostart_path): | 156 | if not os.path.isfile(autostart_path): |
167 | @@ -135,12 +160,12 @@ | |||
168 | 135 | "/usr/local/share/applications"] | 160 | "/usr/local/share/applications"] |
169 | 136 | this_directory = os.path.dirname(os.path.abspath(__file__)) | 161 | this_directory = os.path.dirname(os.path.abspath(__file__)) |
170 | 137 | for path in desktop_file_directories: | 162 | for path in desktop_file_directories: |
173 | 138 | fullpath = os.path.normpath(os.path.join(this_directory, path, \ | 163 | fullpath = os.path.normpath(os.path.join(this_directory, path, |
174 | 139 | autostart_file)) | 164 | autostart_file)) |
175 | 140 | if os.path.isfile(fullpath): | 165 | if os.path.isfile(fullpath): |
176 | 141 | desktop_file_path = fullpath | 166 | desktop_file_path = fullpath |
177 | 142 | break | 167 | break |
179 | 143 | #If we have found the desktop file, we make a link to in in | 168 | # If we have found the desktop file, we make a link to in in |
180 | 144 | # autostart_path. | 169 | # autostart_path. |
181 | 145 | if desktop_file_path: | 170 | if desktop_file_path: |
182 | 146 | if not os.path.exists(autostart_dir): | 171 | if not os.path.exists(autostart_dir): |
183 | @@ -149,8 +174,8 @@ | |||
184 | 149 | log.debug("Installing autostart file.") | 174 | log.debug("Installing autostart file.") |
185 | 150 | os.symlink(desktop_file_path, autostart_path) | 175 | os.symlink(desktop_file_path, autostart_path) |
186 | 151 | 176 | ||
187 | 152 | # Get a value of the setting | ||
188 | 153 | def get_value(self, setting, return_id = False): | 177 | def get_value(self, setting, return_id = False): |
189 | 178 | """ Get a value of the specified setting """ | ||
190 | 154 | log.debug("Settings: getting value for %s" % setting) | 179 | log.debug("Settings: getting value for %s" % setting) |
191 | 155 | setting_name = Settings.INFO[setting][INFO_SETTING] | 180 | setting_name = Settings.INFO[setting][INFO_SETTING] |
192 | 156 | try: | 181 | try: |
193 | @@ -162,15 +187,15 @@ | |||
194 | 162 | types.ListType: self.db.get_string, | 187 | types.ListType: self.db.get_string, |
195 | 163 | types.DictType: self.db.get_string, | 188 | types.DictType: self.db.get_string, |
196 | 164 | types.NoneType: self.db.get_value, | 189 | types.NoneType: self.db.get_value, |
198 | 165 | }[setting_type] | 190 | }[setting_type] |
199 | 166 | return get_func(setting_name) | 191 | return get_func(setting_name) |
200 | 167 | except: | 192 | except: |
202 | 168 | self.log.debug("Settings: can't find value for %s" % setting) | 193 | log.debug("Settings: can't find value for %s" % setting) |
203 | 169 | return None | 194 | return None |
204 | 170 | 195 | ||
206 | 171 | # Set a setting value | 196 | |
207 | 172 | def set_value(self, setting, value): | 197 | def set_value(self, setting, value): |
209 | 173 | 198 | """ Set a value for the specified setting """ | |
210 | 174 | value = '' if value is None else value | 199 | value = '' if value is None else value |
211 | 175 | value = str(value) if type(value) is types.ListType else value | 200 | value = str(value) if type(value) is types.ListType else value |
212 | 176 | log.debug("Settings: setting '%s'='%s'" % (setting, value)) | 201 | log.debug("Settings: setting '%s'='%s'" % (setting, value)) |
213 | @@ -185,17 +210,20 @@ | |||
214 | 185 | types.ListType: self.db.set_string, | 210 | types.ListType: self.db.set_string, |
215 | 186 | types.DictType: self.db.set_string, | 211 | types.DictType: self.db.set_string, |
216 | 187 | types.NoneType: self.db.set_value, | 212 | types.NoneType: self.db.set_value, |
218 | 188 | }[setting_type] | 213 | }[setting_type] |
219 | 189 | set_func(setting_name, value) | 214 | set_func(setting_name, value) |
220 | 190 | except: | 215 | except: |
221 | 191 | log.debug( \ | 216 | log.debug( \ |
222 | 192 | "Settings: schema for '%s' not found, aborting" % setting) | 217 | "Settings: schema for '%s' not found, aborting" % setting) |
223 | 193 | 218 | ||
224 | 194 | # Get cached weather by location code. | ||
225 | 195 | # If return_id is True, only document id is returned, otherwise - full weather data | ||
226 | 196 | def get_weather(self, location_code, return_id = False): | 219 | def get_weather(self, location_code, return_id = False): |
229 | 197 | log.debug("Settings: getting cached weather for %s" % \ | 220 | """Get cached weather by location code. |
230 | 198 | location_code) | 221 | If return_id is True, only document id is returned, |
231 | 222 | otherwise full weather data is returned. | ||
232 | 223 | |||
233 | 224 | """ | ||
234 | 225 | log.debug("Settings: getting cached weather for %s" % | ||
235 | 226 | location_code) | ||
236 | 199 | try: | 227 | try: |
237 | 200 | cached_weather_string = self.db.get_string(self.WEATHER_KEY) | 228 | cached_weather_string = self.db.get_string(self.WEATHER_KEY) |
238 | 201 | cached_weather = {} if cached_weather_string == ''\ | 229 | cached_weather = {} if cached_weather_string == ''\ |
239 | @@ -207,22 +235,22 @@ | |||
240 | 207 | "Settings: can't find value for %s" % location_code) | 235 | "Settings: can't find value for %s" % location_code) |
241 | 208 | return None | 236 | return None |
242 | 209 | except: | 237 | except: |
244 | 210 | log.debug("Settings: can't find %s setting" % WEATHER_KEY) | 238 | log.debug("Settings: can't find %s setting" % self.WEATHER_KEY) |
245 | 211 | return None | 239 | return None |
246 | 212 | 240 | ||
247 | 213 | # Save weather info in cache for specific location | ||
248 | 214 | def save_weather(self, weather, location_code): | 241 | def save_weather(self, weather, location_code): |
250 | 215 | 242 | """ Save weather info in cache for specific location """ | |
251 | 216 | record = { | 243 | record = { |
261 | 217 | "label" : weather.get_temperature(needs_rounding=True), | 244 | ## "label" : weather.get_temperature(needs_rounding=True), |
262 | 218 | "condition": weather.get_condition_label(), | 245 | "label" : weather.get_temperature_string(), |
263 | 219 | "icon" : weather.get_icon_name(), | 246 | "condition" : weather.get_condition_label(), |
264 | 220 | "temper" : weather.get_temperature_label(), | 247 | "icon" : weather.get_icon_name(), |
265 | 221 | "humidex" : weather.get_humidex_label(), | 248 | "temper" : weather.get_temperature_label(), |
266 | 222 | "humidity" : weather.get_humidity_label(), | 249 | "feelslike" : weather.get_relative_label(), |
267 | 223 | "wind" : weather.get_wind_label(), | 250 | "humidity" : weather.get_humidity_label(), |
268 | 224 | "sunrise" : weather.get_sunrise_label(), | 251 | "wind" : weather.get_wind_label(), |
269 | 225 | "sunset" : weather.get_sunset_label() | 252 | "sunrise" : weather.get_sunrise_label(), |
270 | 253 | "sunset" : weather.get_sunset_label() | ||
271 | 226 | } | 254 | } |
272 | 227 | log.debug("Settings: setting '%s'='%s'" % (location_code, record)) | 255 | log.debug("Settings: setting '%s'='%s'" % (location_code, record)) |
273 | 228 | 256 | ||
274 | @@ -234,12 +262,17 @@ | |||
275 | 234 | cached_weather_string = str(cached_weather) | 262 | cached_weather_string = str(cached_weather) |
276 | 235 | self.db.set_string(self.WEATHER_KEY, cached_weather_string) | 263 | self.db.set_string(self.WEATHER_KEY, cached_weather_string) |
277 | 236 | except: | 264 | except: |
280 | 237 | log.debug(\ | 265 | log.debug( |
281 | 238 | "Settings: schema for '%s' not found, aborting" % setting) | 266 | "Settings: schema for '%s' not found, aborting" % |
282 | 267 | self.WEATHER_KEY | ||
283 | 268 | ) | ||
284 | 239 | 269 | ||
285 | 240 | # Get location details by location code | ||
286 | 241 | # If return_id is True, only document id is returned, otherwise - full location data | ||
287 | 242 | def get_location_details(self, location_code, return_id = False): | 270 | def get_location_details(self, location_code, return_id = False): |
288 | 271 | """ Get location details by location code | ||
289 | 272 | If return_id is True, only document id is returned, | ||
290 | 273 | otherwise - full location data is returned | ||
291 | 274 | |||
292 | 275 | """ | ||
293 | 243 | try: | 276 | try: |
294 | 244 | locations_string = self.db.get_string(self.LOCATIONS_KEY) | 277 | locations_string = self.db.get_string(self.LOCATIONS_KEY) |
295 | 245 | locations = {} if locations_string == ''\ | 278 | locations = {} if locations_string == ''\ |
296 | @@ -247,19 +280,19 @@ | |||
297 | 247 | if location_code in locations.keys(): | 280 | if location_code in locations.keys(): |
298 | 248 | return str(locations[location_code]) | 281 | return str(locations[location_code]) |
299 | 249 | else: | 282 | else: |
302 | 250 | log.debug(\ | 283 | log.debug( |
303 | 251 | "Settings: can't find value for %s" % location_code) | 284 | "Settings: can't find value for %s" % location_code |
304 | 285 | ) | ||
305 | 252 | return None | 286 | return None |
306 | 253 | except: | 287 | except: |
309 | 254 | log.debug("Settings: can't find location details for %s" % \ | 288 | log.debug("Settings: can't find location details for %s" % |
310 | 255 | location_code) | 289 | location_code) |
311 | 256 | return None | 290 | return None |
312 | 257 | 291 | ||
313 | 258 | # Save location details | ||
314 | 259 | def save_location_details(self, location_details, location_code): | 292 | def save_location_details(self, location_details, location_code): |
318 | 260 | log.debug("Settings: setting '%s'='%s'" %\ | 293 | """ Save location details """ |
319 | 261 | (location_code, location_details)) | 294 | log.debug("Settings: setting '%s'='%s'" % |
320 | 262 | 295 | (location_code, location_details)) | |
321 | 263 | try: | 296 | try: |
322 | 264 | locations_string = self.db.get_string(self.LOCATIONS_KEY) | 297 | locations_string = self.db.get_string(self.LOCATIONS_KEY) |
323 | 265 | locations = {} if locations_string == ''\ | 298 | locations = {} if locations_string == ''\ |
324 | @@ -270,8 +303,8 @@ | |||
325 | 270 | except: | 303 | except: |
326 | 271 | pass | 304 | pass |
327 | 272 | 305 | ||
330 | 273 | class MetricSystem: | 306 | class UnitSystem: |
331 | 274 | """ Class with available metric systems units """ | 307 | """ Class with available measurement unit systems """ |
332 | 275 | SI = 1 | 308 | SI = 1 |
333 | 276 | IMPERIAL = 2 | 309 | IMPERIAL = 2 |
334 | 277 | 310 | ||
335 | @@ -285,52 +318,64 @@ | |||
336 | 285 | 318 | ||
337 | 286 | class WeatherDataSource: | 319 | class WeatherDataSource: |
338 | 287 | """ Class for available weather data sources """ | 320 | """ Class for available weather data sources """ |
341 | 288 | GOOGLE = 1 | 321 | YAHOO = 1 |
342 | 289 | YAHOO = 2 | 322 | WEATHER_COM = 2 |
343 | 290 | 323 | ||
344 | 324 | class RelativeFormula: | ||
345 | 325 | """ Class for relative temperature formulas """ | ||
346 | 326 | HEATINDEX = 1 | ||
347 | 327 | HUMIDEX = 2 | ||
348 | 328 | WINDCHILL = 3 | ||
349 | 329 | APPARENT = 4 | ||
350 | 330 | |||
351 | 291 | class Location: | 331 | class Location: |
352 | 292 | """ Data object to store location details """ | 332 | """ Data object to store location details """ |
353 | 293 | 333 | ||
356 | 294 | # Initialize an object with a label | 334 | def __init__(self, metric_system, wind_unit, heat_index, |
357 | 295 | def __init__(self, metric_system, wind_unit, location_details = None): | 335 | chill_index, location_details = None): |
358 | 336 | """ Initialize an object with a label """ | ||
359 | 296 | self.metric_system = metric_system | 337 | self.metric_system = metric_system |
360 | 297 | self.wind_unit = wind_unit | 338 | self.wind_unit = wind_unit |
361 | 339 | self.heat_index = heat_index | ||
362 | 340 | self.chill_index = chill_index | ||
363 | 298 | self.location_details = location_details | 341 | self.location_details = location_details |
364 | 299 | 342 | ||
365 | 300 | # Convert coordinate for google | ||
366 | 301 | def convert_coordinate_for_google(self, value): | 343 | def convert_coordinate_for_google(self, value): |
369 | 302 | value = float(value) * 1e6 | 344 | """ Convert coordinate for google """ |
370 | 303 | return int(round(value)) | 345 | value = float(value) * 1e6 |
371 | 346 | return int(round(value)) | ||
372 | 304 | 347 | ||
373 | 305 | # Get necessary location details by its GeoNames details | ||
374 | 306 | def prepare_location(self, geonames_details): | 348 | def prepare_location(self, geonames_details): |
375 | 349 | """ Get necessary location details by its GeoNames details """ | ||
376 | 307 | self.location_details = {} | 350 | self.location_details = {} |
377 | 308 | self.location_details['full name'] = geonames_details[0] | 351 | self.location_details['full name'] = geonames_details[0] |
378 | 309 | self.location_details['latitude'] = geonames_details[2] | 352 | self.location_details['latitude'] = geonames_details[2] |
379 | 310 | self.location_details['longitude'] = geonames_details[3] | 353 | self.location_details['longitude'] = geonames_details[3] |
380 | 311 | self.prepare_location_for_google(geonames_details) | 354 | self.prepare_location_for_google(geonames_details) |
381 | 312 | self.prepare_location_for_yahoo(geonames_details) | 355 | self.prepare_location_for_yahoo(geonames_details) |
382 | 356 | self.prepare_location_for_weather_com(geonames_details) | ||
383 | 313 | #TODO: Get noaa id from geonames service | 357 | #TODO: Get noaa id from geonames service |
384 | 314 | self.location_details['noaa id'] = "woot" | 358 | self.location_details['noaa id'] = "woot" |
385 | 315 | 359 | ||
386 | 316 | # check mandatory attributes | 360 | # check mandatory attributes |
387 | 317 | if not hasattr(self, 'location_code') or \ | 361 | if not hasattr(self, 'location_code') or \ |
390 | 318 | 'latitude' not in self.location_details or \ | 362 | 'latitude' not in self.location_details or \ |
391 | 319 | 'longitude' not in self.location_details: | 363 | 'longitude' not in self.location_details: |
392 | 320 | return False | 364 | return False |
393 | 321 | 365 | ||
394 | 322 | # check that we have at least one supported data source | 366 | # check that we have at least one supported data source |
395 | 323 | if 'google id' not in self.location_details and \ | 367 | if 'google id' not in self.location_details and \ |
397 | 324 | 'yahoo id' not in self.location_details: | 368 | 'yahoo id' not in self.location_details and \ |
398 | 369 | 'weather-com id' not in self.location_details: | ||
399 | 325 | log.error(("Location '%s'" % | 370 | log.error(("Location '%s'" % |
401 | 326 | self.location_details['full name'])) + \ | 371 | self.location_details['full name'])) + \ |
402 | 327 | "is not supported by current data sources" | 372 | "is not supported by current data sources" |
403 | 328 | return False | 373 | return False |
404 | 329 | 374 | ||
405 | 330 | return True | 375 | return True |
406 | 331 | 376 | ||
407 | 332 | def prepare_location_for_google(self, geonames_details): | 377 | def prepare_location_for_google(self, geonames_details): |
409 | 333 | # Format latitude and longitude for Google needs | 378 | """ Format latitude and longitude for Google needs """ |
410 | 334 | try: | 379 | try: |
411 | 335 | lat = self.convert_coordinate_for_google(geonames_details[2]) | 380 | lat = self.convert_coordinate_for_google(geonames_details[2]) |
412 | 336 | lon = self.convert_coordinate_for_google(geonames_details[3]) | 381 | lon = self.convert_coordinate_for_google(geonames_details[3]) |
413 | @@ -340,7 +385,7 @@ | |||
414 | 340 | log.error(e) | 385 | log.error(e) |
415 | 341 | 386 | ||
416 | 342 | def prepare_location_for_yahoo(self, geonames_details): | 387 | def prepare_location_for_yahoo(self, geonames_details): |
418 | 343 | # Get location details in english for Yahoo | 388 | """ Get location details in English for Yahoo """ |
419 | 344 | baseurl = 'http://api.geonames.org/getJSON' | 389 | baseurl = 'http://api.geonames.org/getJSON' |
420 | 345 | params = {'geonameId': geonames_details[1], 'username': 'indicatorweather'} | 390 | params = {'geonameId': geonames_details[1], 'username': 'indicatorweather'} |
421 | 346 | url = '?'.join((baseurl, urlencode(params))) | 391 | url = '?'.join((baseurl, urlencode(params))) |
422 | @@ -356,19 +401,13 @@ | |||
423 | 356 | return | 401 | return |
424 | 357 | 402 | ||
425 | 358 | # Get YAHOO WOEID by english name of location | 403 | # Get YAHOO WOEID by english name of location |
436 | 359 | baseurl = 'http://where.yahooapis.com/geocode' | 404 | woeid_result = pywapi.get_woeid_from_yahoo(displayed_city_name) |
437 | 360 | params = {'location': displayed_city_name, 'appid': 'mOawLd4s', 'flags': 'J'} | 405 | if woeid_result.has_key('error'): |
438 | 361 | url = '?'.join((baseurl, urlencode(params))) | 406 | log.error("Location: Yahoo woeid return error. Full response:\n %s" % woeid_result['error']) |
429 | 362 | log.debug("Location: Get Yahoo WOEID, url %s" % url) | ||
430 | 363 | f = urllib2.urlopen(url) | ||
431 | 364 | s=f.read() | ||
432 | 365 | null = None | ||
433 | 366 | yahoo_woeid_result = eval(s) | ||
434 | 367 | if (yahoo_woeid_result['ResultSet']['Error'] != 0) and (yahoo_woeid_result['ResultSet']['Results'] != None): | ||
435 | 368 | log.error("Location: Yahoo woeid return error. Full response:\n %s" % str(yahoo_woeid_result)) | ||
439 | 369 | return | 407 | return |
440 | 370 | else: | 408 | else: |
442 | 371 | woeid = yahoo_woeid_result['ResultSet']['Results'][0]['woeid'] | 409 | # only look at the the first woeid result |
443 | 410 | woeid = woeid_result[0][0] | ||
444 | 372 | self.location_code = woeid | 411 | self.location_code = woeid |
445 | 373 | log.debug("Location: woeid is %s" % woeid) | 412 | log.debug("Location: woeid is %s" % woeid) |
446 | 374 | 413 | ||
447 | @@ -400,21 +439,54 @@ | |||
448 | 400 | except Exception, e: | 439 | except Exception, e: |
449 | 401 | log.error(e) | 440 | log.error(e) |
450 | 402 | 441 | ||
452 | 403 | # Return lcoation code and location details | 442 | def prepare_location_for_weather_com(self, geonames_details): |
453 | 443 | """ Get location details in English for Weather.com """ | ||
454 | 444 | baseurl = 'http://api.geonames.org/getJSON' | ||
455 | 445 | params = {'geonameId': geonames_details[1], 'username': 'indicatorweather'} | ||
456 | 446 | url = '?'.join((baseurl, urlencode(params))) | ||
457 | 447 | log.debug("Location: Get GeoNames location details, url %s" % url) | ||
458 | 448 | try: | ||
459 | 449 | city = eval(urllib2.urlopen(url).read()) | ||
460 | 450 | if 'adminName1' in city: | ||
461 | 451 | displayed_city_name = "%s, %s, %s" % (city['name'], city['adminName1'], city['countryName']) | ||
462 | 452 | elif 'name' in city: | ||
463 | 453 | displayed_city_name = "%s, %s" % (city['name'], city['countryName']) | ||
464 | 454 | else: | ||
465 | 455 | log.error("Location: Cannot find GeoNames info for code %s Full Response:\n %s" % (geonames_details[1], str(city))) | ||
466 | 456 | return | ||
467 | 457 | |||
468 | 458 | # Get Weather.com Location ID by English name of location | ||
469 | 459 | locid_result = pywapi.get_location_ids(displayed_city_name) | ||
470 | 460 | if locid_result.has_key('error'): | ||
471 | 461 | log.error("Location: Weather.com locid return error. Full response:\n %s" % locid_result['error']) | ||
472 | 462 | return | ||
473 | 463 | else: | ||
474 | 464 | # only look at the the first locid result | ||
475 | 465 | locid = locid_result[0][0] | ||
476 | 466 | self.location_details['weather-com id'] = locid | ||
477 | 467 | log.debug("Location: locid is %s" % locid) | ||
478 | 468 | |||
479 | 469 | except urllib2.URLError: | ||
480 | 470 | log.error("Location: error reaching url '%s'" % url) | ||
481 | 471 | |||
482 | 472 | except Exception, e: | ||
483 | 473 | log.error(e) | ||
484 | 474 | |||
485 | 404 | def export_location_details(self): | 475 | def export_location_details(self): |
486 | 476 | """ Return location code and location details """ | ||
487 | 405 | return (self.location_code, self.location_details) | 477 | return (self.location_code, self.location_details) |
488 | 406 | 478 | ||
489 | 407 | # Get fresh weather data and store it to weather object | ||
490 | 408 | def update_weather_data(self, source): | 479 | def update_weather_data(self, source): |
492 | 409 | # gather existing source keys | 480 | """ Get fresh weather data and store it to weather object """ |
493 | 410 | valid_source = None | 481 | valid_source = None |
494 | 411 | loc_ids = {} | 482 | loc_ids = {} |
495 | 412 | 483 | ||
496 | 413 | SOURCES = { | 484 | SOURCES = { |
499 | 414 | WeatherDataSource.GOOGLE : ("google id", "Google"), | 485 | WeatherDataSource.WEATHER_COM : ("weather-com id", "Weather.com"), |
500 | 415 | WeatherDataSource.YAHOO : ("yahoo id", "Yahoo"), | 486 | WeatherDataSource.YAHOO : ("yahoo id", "Yahoo") |
501 | 416 | } | 487 | } |
502 | 417 | 488 | ||
503 | 489 | # gather existing source keys | ||
504 | 418 | for source_id in SOURCES.keys(): | 490 | for source_id in SOURCES.keys(): |
505 | 419 | if SOURCES[source_id][0] in self.location_details: | 491 | if SOURCES[source_id][0] in self.location_details: |
506 | 420 | loc_ids[source_id] = SOURCES[source_id][0] | 492 | loc_ids[source_id] = SOURCES[source_id][0] |
507 | @@ -423,158 +495,145 @@ | |||
508 | 423 | if source in loc_ids: | 495 | if source in loc_ids: |
509 | 424 | valid_source = source | 496 | valid_source = source |
510 | 425 | log.debug(("Location: default weather source '%s' " + | 497 | log.debug(("Location: default weather source '%s' " + |
513 | 426 | "chosen for '%s'") % (SOURCES[valid_source][1], | 498 | "chosen for '%s'") % (SOURCES[valid_source][1], |
514 | 427 | self.location_details['label'])) | 499 | self.location_details['label'])) |
515 | 428 | 500 | ||
516 | 429 | # try with the first alternative | 501 | # try with the first alternative |
517 | 430 | elif len(loc_ids.keys()): | 502 | elif len(loc_ids.keys()): |
518 | 431 | valid_source = loc_ids.keys()[0] | 503 | valid_source = loc_ids.keys()[0] |
519 | 432 | log.debug(("Location: non default weather source '%s' " + | ||
520 | 433 | "chosen for '%s'") % (SOURCES[valid_source][1], | ||
521 | 434 | self.location_details['label'])) | ||
522 | 435 | 504 | ||
523 | 436 | if valid_source is None: | 505 | if valid_source is None: |
524 | 437 | log.error(("Location: no valid weather source can be " + | 506 | log.error(("Location: no valid weather source can be " + |
527 | 438 | "chosen for '%s'") % ( | 507 | "chosen for '%s'") % ( |
528 | 439 | self.location_details['label'])) | 508 | self.location_details['label'])) |
529 | 440 | self.weather = None | 509 | self.weather = None |
530 | 441 | else: | 510 | else: |
531 | 511 | log.debug(("Location: non default weather source '%s' " + | ||
532 | 512 | "chosen for '%s'") % (SOURCES[valid_source][1], | ||
533 | 513 | self.location_details['label'])) | ||
534 | 442 | self.weather = Weather( | 514 | self.weather = Weather( |
535 | 443 | self.location_details[loc_ids[valid_source]], | 515 | self.location_details[loc_ids[valid_source]], |
536 | 444 | valid_source, self.metric_system, self.wind_unit, | 516 | valid_source, self.metric_system, self.wind_unit, |
537 | 517 | self.heat_index, self.chill_index, | ||
538 | 445 | self.location_details['latitude'], | 518 | self.location_details['latitude'], |
539 | 446 | self.location_details['longitude']) | 519 | self.location_details['longitude']) |
540 | 447 | 520 | ||
541 | 521 | |||
542 | 448 | class Forecast: | 522 | class Forecast: |
543 | 449 | """ Class to get forecast information """ | 523 | """ Class to get forecast information """ |
544 | 450 | 524 | ||
547 | 451 | # Initialize a class with metric system, wind units, location and current user locale | 525 | def __init__ (self, units, location_id, locale): |
548 | 452 | def __init__ (self, units, lat, lon, locale): | 526 | """Initialize a class with metric system, wind units, |
549 | 527 | location code and current user locale | ||
550 | 528 | |||
551 | 529 | """ | ||
552 | 453 | self.metric_system = units | 530 | self.metric_system = units |
555 | 454 | self.lat = self.convert_coordinate_for_google(lat) | 531 | self.location_id = location_id |
554 | 455 | self.lon = self.convert_coordinate_for_google(lon) | ||
556 | 456 | self.locale = locale | 532 | self.locale = locale |
557 | 457 | 533 | ||
558 | 458 | # Convert coordinate for google | ||
559 | 459 | def convert_coordinate_for_google(self, value): | ||
560 | 460 | value = float(value) * 1e6 | ||
561 | 461 | return int(round(value)) | ||
562 | 462 | |||
563 | 463 | # Get and store forecast data. For now using Google only | ||
564 | 464 | def prepare_forecast_data(self): | 534 | def prepare_forecast_data(self): |
565 | 535 | """ Get and store forecast data. For now using Weather.com only. """ | ||
566 | 536 | # TODO: Implement for NOAA | ||
567 | 465 | self.daysofweek = [] | 537 | self.daysofweek = [] |
568 | 466 | self.icons = [] | 538 | self.icons = [] |
569 | 467 | self.conditions = [] | 539 | self.conditions = [] |
570 | 468 | self.error_message = None | 540 | self.error_message = None |
571 | 469 | try: | 541 | try: |
576 | 470 | # Generate a fake location by current coordinates | 542 | log.debug("Forecast: units set to %s" % self.metric_system) |
577 | 471 | location_name = ",,,%s,%s" % (self.lat, self.lon) | 543 | # Check units, default to imperial |
578 | 472 | self.forecast = pywapi.get_weather_from_google (location_name, hl = self.locale) | 544 | if self.metric_system == UnitSystem.SI: |
579 | 473 | self.unitsystem = self.forecast['forecast_information']['unit_system'] | 545 | self.unitsystem = 'metric' |
580 | 546 | elif self.metric_system == UnitSystem.IMPERIAL: | ||
581 | 547 | self.unitsystem = 'imperial' | ||
582 | 548 | else: | ||
583 | 549 | self.unitsystem = 'imperial' | ||
584 | 550 | |||
585 | 551 | self.forecast = pywapi.get_weather_from_weather_com(self.location_id, self.unitsystem) | ||
586 | 474 | 552 | ||
587 | 475 | for forecast in self.forecast['forecasts']: | 553 | for forecast in self.forecast['forecasts']: |
588 | 476 | self.daysofweek.append(forecast["day_of_week"]) | 554 | self.daysofweek.append(forecast["day_of_week"]) |
595 | 477 | forecast_icon = str(forecast["icon"]) | 555 | |
596 | 478 | if "/ig/images/weather/" in forecast_icon: | 556 | # Yahoo forecast icon URL is "http://l.yimg.com/a/i/us/we/52/<code>.gif" |
597 | 479 | self.icons.append(forecast_icon.split("/ig/images/weather/")[-1].split(".gif")[0]) | 557 | self.icons.append(forecast["day"]["icon"]) |
598 | 480 | elif "http://g0.gstatic.com/images/icons/onebox" in forecast_icon: | 558 | self.conditions.append(forecast["day"]["brief_text"]) |
599 | 481 | self.icons.append(forecast_icon.split("http://g0.gstatic.com/images/icons/onebox/weather_")[-1].split("-40.gif")[0]) | 559 | |
594 | 482 | self.conditions.append(forecast["condition"]) | ||
600 | 483 | self.error_message = None | 560 | self.error_message = None |
601 | 484 | 561 | ||
602 | 485 | except urllib2.URLError: | 562 | except urllib2.URLError: |
604 | 486 | log.error("Forecast: error reading forecast for %s" % location_name) | 563 | log.error("Forecast: error reading forecast for %s" % self.location_id) |
605 | 487 | except KeyError: | 564 | except KeyError: |
607 | 488 | log.error("Forecast: returned empty forecast %s" % location_name) | 565 | log.error("Forecast: returned empty forecast for %s" % self.location_id) |
608 | 489 | self.error_message = _('Unknown error occurred while picking up weather data') | 566 | self.error_message = _('Unknown error occurred while picking up weather data') |
609 | 490 | 567 | ||
610 | 491 | # Parse high values for forecast data | ||
611 | 492 | def get_forecast_data(self): | 568 | def get_forecast_data(self): |
612 | 569 | """ Parse high and low values for forecast data """ | ||
613 | 493 | self.highdata = [] | 570 | self.highdata = [] |
614 | 494 | self.lowdata = [] | 571 | self.lowdata = [] |
615 | 495 | 572 | ||
636 | 496 | if not hasattr(self, 'unitsystem'): | 573 | # Since we are now using Weather.com, forecast will always be in correct units |
637 | 497 | return None | 574 | for forecast in self.forecast['forecasts']: |
638 | 498 | 575 | self.highdata.append(forecast["high"]) | |
639 | 499 | if ((self.unitsystem == 'SI') and (self.metric_system == MetricSystem.SI)) or ((self.unitsystem == 'US') and (self.metric_system == MetricSystem.IMPERIAL)): | 576 | self.lowdata.append(forecast["low"]) |
620 | 500 | #correct scale selected | ||
621 | 501 | for forecast in self.forecast['forecasts']: | ||
622 | 502 | self.highdata.append(forecast["high"]) | ||
623 | 503 | self.lowdata.append(forecast["low"]) | ||
624 | 504 | |||
625 | 505 | elif ((self.unitsystem == 'SI') and (self.metric_system == MetricSystem.IMPERIAL)): | ||
626 | 506 | #convert from SI to imperial | ||
627 | 507 | for forecast in self.forecast['forecasts']: | ||
628 | 508 | self.highdata.append(int(((int(forecast["high"])*9)/5)+32)) | ||
629 | 509 | self.lowdata.append(int(((int(forecast["low"])*9)/5)+32)) | ||
630 | 510 | |||
631 | 511 | elif ((self.unitsystem == 'US') and (self.metric_system == MetricSystem.SI)): | ||
632 | 512 | #convert from imperial to SI | ||
633 | 513 | for forecast in self.forecast['forecasts']: | ||
634 | 514 | self.highdata.append(int((((int(forecast["high"]))-32)*5)/9)) | ||
635 | 515 | self.lowdata.append(int((((int(forecast["low"]))-32)*5)/9)) | ||
640 | 516 | 577 | ||
641 | 517 | return (self.highdata, self.lowdata) | 578 | return (self.highdata, self.lowdata) |
642 | 518 | 579 | ||
643 | 519 | # Parse a list of days of week with forecast data | ||
644 | 520 | def get_forecast_daysofweek(self): | 580 | def get_forecast_daysofweek(self): |
645 | 581 | """ Parse a list of days of week with forecast data """ | ||
646 | 521 | return self.daysofweek | 582 | return self.daysofweek |
647 | 522 | 583 | ||
648 | 523 | # Parse icons for forecast data | ||
649 | 524 | def get_forecast_icons(self): | 584 | def get_forecast_icons(self): |
650 | 585 | """ Parse icons for forecast data """ | ||
651 | 525 | return self.icons | 586 | return self.icons |
652 | 526 | 587 | ||
653 | 527 | # Parse conditions for forecast data | ||
654 | 528 | def get_forecast_conditions(self): | 588 | def get_forecast_conditions(self): |
655 | 589 | """ Parse conditions for forecast data """ | ||
656 | 529 | return self.conditions | 590 | return self.conditions |
657 | 530 | 591 | ||
658 | 531 | class Weather: | 592 | class Weather: |
705 | 532 | """ | 593 | """Data object to parse weather data with unit conversion """ |
706 | 533 | Data object to parse weather data with unit convertion | 594 | |
707 | 534 | """ | 595 | ## #Available conditions by google icon |
708 | 535 | 596 | ## #Format: Google icon name: (day icon, night icon, is a severe weather condition) | |
709 | 536 | #Available conditions by google icon | 597 | ## #Reference: http://www.blindmotion.com/2009/03/google-weather-api-images/ |
710 | 537 | #Format: Google icon name: (day icon, night icon, is a severe weather condition) | 598 | ## _GoogleConditions = { |
711 | 538 | #Reference: http://www.blindmotion.com/2009/03/google-weather-api-images/ | 599 | ## "sunny" : ( "weather-clear", "weather-clear-night", False), |
712 | 539 | _GoogleConditions = { | 600 | ## "mostly_sunny" : ( "weather-clear", "weather-clear-night", False), |
713 | 540 | "sunny" : ( "weather-clear", "weather-clear-night", False), | 601 | ## "partlycloudy" : ( "weather-few-clouds", "weather-few-clouds-night", False), |
714 | 541 | "mostly_sunny" : ( "weather-clear", "weather-clear-night", False), | 602 | ## "partly_cloudy" : ( "weather-few-clouds", "weather-few-clouds-night", False), |
715 | 542 | "partlycloudy" : ( "weather-few-clouds", "weather-few-clouds-night", False), | 603 | ## "windy" : ( "weather-few-clouds", "weather-few-clouds-night", False), |
716 | 543 | "partly_cloudy" : ( "weather-few-clouds", "weather-few-clouds-night", False), | 604 | ## "cloudy" : ( "weather-clouds", "weather-clouds-night", False), |
717 | 544 | "windy" : ( "weather-few-clouds", "weather-few-clouds-night", False), | 605 | ## "mostlycloudy" : ( "weather-overcast", "weather-overcast", False), |
718 | 545 | "cloudy" : ( "weather-clouds", "weather-clouds-night", False), | 606 | ## "mostly_cloudy" : ( "weather-overcast", "weather-overcast", False), |
719 | 546 | "mostlycloudy" : ( "weather-overcast", "weather-overcast", False), | 607 | ## "overcast" : ( "weather-overcast", "weather-overcast", False), |
720 | 547 | "mostly_cloudy" : ( "weather-overcast", "weather-overcast", False), | 608 | ## "rain" : ( "weather-showers", "weather-showers", False), |
721 | 548 | "overcast" : ( "weather-overcast", "weather-overcast", False), | 609 | ## "chanceofrain" : ( "weather-showers", "weather-showers", False), |
722 | 549 | "rain" : ( "weather-showers", "weather-showers", False), | 610 | ## "chance_of_rain" : ( "weather-showers", "weather-showers", False), |
723 | 550 | "chanceofrain" : ( "weather-showers", "weather-showers", False), | 611 | ## "heavyrain" : ( "weather-showers", "weather-showers", False), |
724 | 551 | "chance_of_rain" : ( "weather-showers", "weather-showers", False), | 612 | ## "drizzle" : ( "weather-showers", "weather-showers", False), |
725 | 552 | "heavyrain" : ( "weather-showers", "weather-showers", False), | 613 | ## "sleet" : ( "weather-snow", "weather-snow", False), |
726 | 553 | "drizzle" : ( "weather-showers", "weather-showers", False), | 614 | ## "rain_snow" : ( "weather-snow", "weather-snow", False), |
727 | 554 | "sleet" : ( "weather-snow", "weather-snow", False), | 615 | ## "rainsnow" : ( "weather-snow", "weather-snow", False), |
728 | 555 | "rain_snow" : ( "weather-snow", "weather-snow", False), | 616 | ## "snow" : ( "weather-snow", "weather-snow", False), |
729 | 556 | "rainsnow" : ( "weather-snow", "weather-snow", False), | 617 | ## "chanceofsnow" : ( "weather-snow", "weather-snow", False), |
730 | 557 | "snow" : ( "weather-snow", "weather-snow", False), | 618 | ## "chance_of_snow" : ( "weather-snow", "weather-snow", False), |
731 | 558 | "chanceofsnow" : ( "weather-snow", "weather-snow", False), | 619 | ## "heavysnow" : ( "weather-snow", "weather-snow", False), |
732 | 559 | "chance_of_snow" : ( "weather-snow", "weather-snow", False), | 620 | ## "icy" : ( "weather-snow", "weather-snow", False), |
733 | 560 | "heavysnow" : ( "weather-snow", "weather-snow", False), | 621 | ## "snowflurries" : ( "weather-snow", "weather-snow", False), |
734 | 561 | "icy" : ( "weather-snow", "weather-snow", False), | 622 | ## "flurries" : ( "weather-snow", "weather-snow", False), |
735 | 562 | "snowflurries" : ( "weather-snow", "weather-snow", False), | 623 | ## "dust" : ( "weather-fog", "weather-fog", False), |
736 | 563 | "flurries" : ( "weather-snow", "weather-snow", False), | 624 | ## "fog" : ( "weather-fog", "weather-fog", False), |
737 | 564 | "dust" : ( "weather-fog", "weather-fog", False), | 625 | ## "smoke" : ( "weather-fog", "weather-fog", False), |
738 | 565 | "fog" : ( "weather-fog", "weather-fog", False), | 626 | ## "haze" : ( "weather-fog", "weather-fog", False), |
739 | 566 | "smoke" : ( "weather-fog", "weather-fog", False), | 627 | ## "mist" : ( "weather-fog", "weather-fog", False), |
740 | 567 | "haze" : ( "weather-fog", "weather-fog", False), | 628 | ## "thunderstorm" : ( "weather-storm", "weather-storm", True), |
741 | 568 | "mist" : ( "weather-fog", "weather-fog", False), | 629 | ## "chance_of_storm" : ( "weather-storm", "weather-storm", True), |
742 | 569 | "thunderstorm" : ( "weather-storm", "weather-storm", True), | 630 | ## "thunderstorms" : ( "weather-storm", "weather-storm", True), |
743 | 570 | "chance_of_storm" : ( "weather-storm", "weather-storm", True), | 631 | ## "scatteredshowers" : ( "weather-showers-scattered", "weather-showers-scattered", True), |
744 | 571 | "thunderstorms" : ( "weather-storm", "weather-storm", True), | 632 | ## "scatteredthunderstorms" : ( "weather-storm", "weather-storm", True), |
745 | 572 | "scatteredshowers" : ( "weather-showers-scattered", "weather-showers-scattered", True), | 633 | ## } |
746 | 573 | "scatteredthunderstorms" : ( "weather-storm", "weather-storm", True), | 634 | |
747 | 574 | } | 635 | # Available conditions by yahoo condition code |
748 | 575 | 636 | # Format: condition code: (day icon, night icon, is a severe weather condition, localized condition name) | |
703 | 576 | #Available conditions by yahoo condition code | ||
704 | 577 | #Format: condition code: (day icon, night icon, is a severe weather condition, localized condition name) | ||
749 | 578 | _YahooConditions = { | 637 | _YahooConditions = { |
750 | 579 | '0' : ("weather-storm", "weather-storm", True, _("Tornado")), | 638 | '0' : ("weather-storm", "weather-storm", True, _("Tornado")), |
751 | 580 | '1' : ("weather-storm", "weather-storm", True, _("Tropical storm")), | 639 | '1' : ("weather-storm", "weather-storm", True, _("Tropical storm")), |
752 | @@ -628,55 +687,60 @@ | |||
753 | 628 | '3200': (False, False, False, _("Unknown condition")) | 687 | '3200': (False, False, False, _("Unknown condition")) |
754 | 629 | } | 688 | } |
755 | 630 | 689 | ||
758 | 631 | # Initialize and get fresh data | 690 | # Available conditions by Weather.com condition code; same as Yahoo |
759 | 632 | def __init__(self, location_id, weather_datasource, metric_system, wind_unit, lat, lon): | 691 | _WeathercomConditions = _YahooConditions |
760 | 692 | |||
761 | 693 | def __init__(self, location_id, weather_datasource, metric_system, | ||
762 | 694 | wind_unit, heat_index, chill_index, lat, lon): | ||
763 | 695 | """ Initialize and get fresh weather data """ | ||
764 | 633 | self.__weather_datasource = weather_datasource | 696 | self.__weather_datasource = weather_datasource |
765 | 634 | self.__metric_system = metric_system | 697 | self.__metric_system = metric_system |
766 | 635 | self._wind_unit = wind_unit | 698 | self._wind_unit = wind_unit |
767 | 636 | self.__current_condition = None | 699 | self.__current_condition = None |
768 | 700 | self.__heat_index = heat_index | ||
769 | 701 | self.__chill_index = chill_index | ||
770 | 637 | self.__lat = lat | 702 | self.__lat = lat |
771 | 638 | self.__lon = lon | 703 | self.__lon = lon |
772 | 639 | 704 | ||
780 | 640 | # Get data from Google | 705 | if self.__metric_system == UnitSystem.SI: |
781 | 641 | if self.__weather_datasource == WeatherDataSource.GOOGLE: | 706 | unit_system = 'metric' |
782 | 642 | # Get data in english locale, then - switch back | 707 | elif self.__metric_system == UnitSystem.IMPERIAL: |
783 | 643 | self.__report = pywapi.get_weather_from_google (location_id, hl = 'en') | 708 | unit_system = 'imperial' |
784 | 644 | # Get data in original locale for condition name | 709 | else: |
785 | 645 | self.__localized_report = pywapi.get_weather_from_google (location_id, hl = locale_name) | 710 | unit_system = 'imperial' |
786 | 646 | 711 | ||
787 | 712 | # Get data from Weather.com | ||
788 | 713 | if self.__weather_datasource == WeatherDataSource.WEATHER_COM: | ||
789 | 714 | self.__report = pywapi.get_weather_from_weather_com( | ||
790 | 715 | location_id, unit_system) | ||
791 | 716 | ##self.__localized_report = self.__report | ||
792 | 717 | log.debug("Weather: checking Weather.com report for " | ||
793 | 718 | "weather condition and icon name") | ||
794 | 647 | if 'current_conditions' not in self.__report.keys(): | 719 | if 'current_conditions' not in self.__report.keys(): |
796 | 648 | log.error("Weather: could not get Google weather condition from report") | 720 | icon_name = "" |
797 | 721 | log.error("Weather: could not get Weather.com " | ||
798 | 722 | "weather condition from report") | ||
799 | 649 | log.error("Weather: got data '%s'" % str(self.__report)) | 723 | log.error("Weather: got data '%s'" % str(self.__report)) |
800 | 650 | self.__current_condition = (False, False, False, _("Unknown condition")) | 724 | self.__current_condition = (False, False, False, _("Unknown condition")) |
801 | 651 | 725 | ||
806 | 652 | if 'current_conditions' not in self.__localized_report.keys(): | 726 | elif 'icon' in self.__report['current_conditions'].keys(): |
807 | 653 | log.error("Weather: could not get Google weather condition from localized report") | 727 | icon_name = self.__report['current_conditions']['icon'] |
808 | 654 | log.error("Weather: got data '%s'" % str(self.__localized_report)) | 728 | self.__current_condition = self._WeathercomConditions.get(icon_name) |
805 | 655 | self.__current_condition = (False, False, False, _("Unknown condition")) | ||
809 | 656 | 729 | ||
810 | 657 | if 'icon' in self.__report['current_conditions'].keys(): | ||
811 | 658 | icon_path = self.__report['current_conditions']['icon'] | ||
812 | 659 | if '/ig/images/weather/' in icon_path: | ||
813 | 660 | icon_name = icon_path.replace('/ig/images/weather/', '').replace('.gif', '') | ||
814 | 661 | elif 'http://g0.gstatic.com/images/icons/onebox' in icon_path: | ||
815 | 662 | icon_name = icon_path.replace('http://g0.gstatic.com/images/icons/onebox/weather_', '').replace('-40.gif', '') | ||
816 | 663 | else: | ||
817 | 664 | icon_name = icon_path | ||
818 | 665 | else: | 730 | else: |
820 | 666 | log.error("Weather: could not get weather icon from report") | 731 | icon_name = "" |
821 | 732 | log.error("Weather: could not get icon name from Weather.com report") | ||
822 | 667 | log.error("Weather: got data '%s'" % str(self.__report['current_conditions'])) | 733 | log.error("Weather: got data '%s'" % str(self.__report['current_conditions'])) |
823 | 668 | icon_name = "" | ||
824 | 669 | |||
825 | 670 | self.__current_condition = self._GoogleConditions.get(icon_name) | ||
826 | 671 | if self.__current_condition == None: | ||
827 | 672 | log.error("ExtendedForecast: unknown Google weather condition '%s'" % icon_name) | ||
828 | 673 | self.__current_condition = (False, False, False, _("Unknown condition")) | 734 | self.__current_condition = (False, False, False, _("Unknown condition")) |
830 | 674 | 735 | ||
831 | 675 | # Get data from Yahoo | 736 | # Get data from Yahoo |
832 | 676 | if self.__weather_datasource == WeatherDataSource.YAHOO: | 737 | if self.__weather_datasource == WeatherDataSource.YAHOO: |
835 | 677 | self.__report = pywapi.get_weather_from_yahoo (location_id, 'imperial') | 738 | self.__report = pywapi.get_weather_from_yahoo(location_id, unit_system) |
836 | 678 | self.__localized_report = self.__report | 739 | ##self.__localized_report = self.__report |
837 | 740 | log.debug("Weather: checking Yahoo report for " | ||
838 | 741 | "weather condition and icon name") | ||
839 | 679 | if 'condition' not in self.__report.keys(): | 742 | if 'condition' not in self.__report.keys(): |
840 | 743 | icon_name = "" | ||
841 | 680 | log.error("Weather: could not get Yahoo weather condition from report") | 744 | log.error("Weather: could not get Yahoo weather condition from report") |
842 | 681 | log.error("Weather: got data '%s'" % str(self.__report)) | 745 | log.error("Weather: got data '%s'" % str(self.__report)) |
843 | 682 | self.__current_condition = (False, False, False, _("Unknown condition")) | 746 | self.__current_condition = (False, False, False, _("Unknown condition")) |
844 | @@ -695,8 +759,8 @@ | |||
845 | 695 | #Prepare sunrise/sunset data | 759 | #Prepare sunrise/sunset data |
846 | 696 | self.get_sun_data() | 760 | self.get_sun_data() |
847 | 697 | 761 | ||
848 | 698 | #Get sunrise/sunset times, calculate whether it is night already | ||
849 | 699 | def get_sun_data(self): | 762 | def get_sun_data(self): |
850 | 763 | """ Get sunrise/sunset times and calculate whether it is night already """ | ||
851 | 700 | self.__night = False | 764 | self.__night = False |
852 | 701 | self.__sunrise_t = None | 765 | self.__sunrise_t = None |
853 | 702 | self.__sunset_t = None | 766 | self.__sunset_t = None |
854 | @@ -714,7 +778,7 @@ | |||
855 | 714 | "dst")[0].firstChild.nodeValue | 778 | "dst")[0].firstChild.nodeValue |
856 | 715 | # strip timezone info | 779 | # strip timezone info |
857 | 716 | localtime = datetime.datetime.strptime(localtime.rsplit(' ',1)[0], | 780 | localtime = datetime.datetime.strptime(localtime.rsplit(' ',1)[0], |
859 | 717 | '%Y-%m-%d %H:%M:%S') | 781 | '%Y-%m-%d %H:%M:%S') |
860 | 718 | dst = 1 if dst == "True" else 0 | 782 | dst = 1 if dst == "True" else 0 |
861 | 719 | 783 | ||
862 | 720 | except urllib2.URLError: | 784 | except urllib2.URLError: |
863 | @@ -725,6 +789,7 @@ | |||
864 | 725 | url = 'http://www.earthtools.org/sun/%s/%s/%s/%s/99/%s' % \ | 789 | url = 'http://www.earthtools.org/sun/%s/%s/%s/%s/99/%s' % \ |
865 | 726 | (self.__lat, self.__lon, localtime.day, localtime.month, dst) | 790 | (self.__lat, self.__lon, localtime.day, localtime.month, dst) |
866 | 727 | try: | 791 | try: |
867 | 792 | log.debug("Weather: get_sun_data: getting sunrise/sunset data") | ||
868 | 728 | f = urllib2.urlopen(url) | 793 | f = urllib2.urlopen(url) |
869 | 729 | s=f.read() | 794 | s=f.read() |
870 | 730 | parsed = parseString(s) | 795 | parsed = parseString(s) |
871 | @@ -742,20 +807,20 @@ | |||
872 | 742 | else: | 807 | else: |
873 | 743 | self.__night = False | 808 | self.__night = False |
874 | 744 | log.debug("Weather: got localtime " + | 809 | log.debug("Weather: got localtime " + |
877 | 745 | "%s, dst %s, sunrise '%s', sunset '%s', night = %s" % ( | 810 | "%s, dst %s, sunrise '%s', sunset '%s', night = %s" % ( |
878 | 746 | localtime, dst, self.__sunrise_t, self.__sunset_t, self.__night)) | 811 | localtime, dst, self.__sunrise_t, self.__sunset_t, self.__night)) |
879 | 747 | 812 | ||
880 | 748 | # Return True, if weather condition is severe | ||
881 | 749 | def condition_is_severe(self): | 813 | def condition_is_severe(self): |
882 | 814 | """ Return True if weather condition is severe """ | ||
883 | 750 | if self.__current_condition != None: | 815 | if self.__current_condition != None: |
884 | 751 | log.debug("Weather: got severe condition '%s'" % self.__current_condition[2]) | 816 | log.debug("Weather: got severe condition '%s'" % self.__current_condition[2]) |
885 | 752 | return self.__current_condition[2] | 817 | return self.__current_condition[2] |
886 | 753 | else: | 818 | else: |
887 | 754 | log.error("Weather: condition is not set while condition severity check") | 819 | log.error("Weather: condition is not set while condition severity check") |
889 | 755 | return False; | 820 | return False |
890 | 756 | 821 | ||
891 | 757 | # Get associated icon name | ||
892 | 758 | def get_icon_name(self): | 822 | def get_icon_name(self): |
893 | 823 | """ Get icon name associated with current condition """ | ||
894 | 759 | if self.__current_condition != None: | 824 | if self.__current_condition != None: |
895 | 760 | if self.__night: | 825 | if self.__night: |
896 | 761 | log.debug("Weather: night, show '%s' icon" % self.__current_condition[1]) | 826 | log.debug("Weather: night, show '%s' icon" % self.__current_condition[1]) |
897 | @@ -767,217 +832,440 @@ | |||
898 | 767 | log.error("Weather: return 'offline' icon due to empty condition") | 832 | log.error("Weather: return 'offline' icon due to empty condition") |
899 | 768 | return False | 833 | return False |
900 | 769 | 834 | ||
901 | 770 | # Get condition text | ||
902 | 771 | def get_condition_label(self): | 835 | def get_condition_label(self): |
908 | 772 | if self.__weather_datasource == WeatherDataSource.GOOGLE: | 836 | """ Get text of current condition """ |
909 | 773 | if 'condition' in self.__localized_report['current_conditions'].keys(): | 837 | if self.__weather_datasource == WeatherDataSource.WEATHER_COM: |
910 | 774 | condition = self.__localized_report['current_conditions']['condition'] | 838 | condition = self.__report['current_conditions']['text'] |
906 | 775 | else: | ||
907 | 776 | condition = _("Unknown condition") | ||
911 | 777 | if self.__weather_datasource == WeatherDataSource.YAHOO: | 839 | if self.__weather_datasource == WeatherDataSource.YAHOO: |
912 | 778 | condition = self.__current_condition[3] | 840 | condition = self.__current_condition[3] |
913 | 779 | return condition | 841 | return condition |
914 | 780 | 842 | ||
915 | 781 | # Get humidity label | ||
916 | 782 | def get_humidity_label(self): | 843 | def get_humidity_label(self): |
917 | 844 | """ Get text string for current humidity """ | ||
918 | 783 | humidity = "%s: ---%%" % (_("Humidity")) | 845 | humidity = "%s: ---%%" % (_("Humidity")) |
922 | 784 | if self.__weather_datasource == WeatherDataSource.GOOGLE \ | 846 | if self.__weather_datasource == WeatherDataSource.WEATHER_COM \ |
923 | 785 | and 'humidity' in self.__localized_report['current_conditions']: | 847 | and 'humidity' in self.__report['current_conditions']: |
924 | 786 | humidity = self.__localized_report['current_conditions']['humidity'] | 848 | humidity = "%s: %s%%" % (_("Humidity"), self.__report['current_conditions']['humidity']) |
925 | 787 | if self.__weather_datasource == WeatherDataSource.YAHOO \ | 849 | if self.__weather_datasource == WeatherDataSource.YAHOO \ |
928 | 788 | and 'humidity' in self.__localized_report['atmosphere']: | 850 | and 'humidity' in self.__report['atmosphere']: |
929 | 789 | humidity = "%s: %s%%" % (_("Humidity"), self.__localized_report['atmosphere']['humidity']) | 851 | humidity = "%s: %s%%" % (_("Humidity"), self.__report['atmosphere']['humidity']) |
930 | 790 | return humidity | 852 | return humidity |
931 | 791 | 853 | ||
932 | 792 | # Get dew point - using in humidex calculation | ||
933 | 793 | #TODO: Update with NOAA | ||
934 | 794 | def get_dew_point_label(self): | 854 | def get_dew_point_label(self): |
937 | 795 | if self.__weather_datasource == WeatherDataSource.GOOGLE or self.__weather_datasource == WeatherDataSource.YAHOO: | 855 | """ Get dew point, which is used in humidex calculation """ |
938 | 796 | # Not returned by Google and Yahoo | 856 | #TODO: Update with NOAA |
939 | 857 | _value = "---" | ||
940 | 858 | _unit = "" | ||
941 | 859 | if self.__weather_datasource == WeatherDataSource.YAHOO: | ||
942 | 860 | # Not returned by Yahoo | ||
943 | 797 | return None | 861 | return None |
944 | 862 | if self.__weather_datasource == WeatherDataSource.WEATHER_COM: | ||
945 | 863 | _value = self.__report['current_conditions']['dewpoint'] | ||
946 | 864 | _unit = self.__report['units']['temperature'] | ||
947 | 865 | return u"%s: %s °%s" % (_("Dewpoint"), _value, _unit) | ||
948 | 798 | 866 | ||
949 | 799 | # Get pressure label | ||
950 | 800 | def get_pressure_label(self): | 867 | def get_pressure_label(self): |
955 | 801 | if self.__weather_datasource == WeatherDataSource.GOOGLE: | 868 | """ Get text string for current air pressure """ |
956 | 802 | # TODO: Empty for Google, use NOAA data? | 869 | _value = "---" |
957 | 803 | value = "---" | 870 | _unit = "" |
958 | 804 | unit = "" | 871 | if self.__weather_datasource == WeatherDataSource.WEATHER_COM \ |
959 | 872 | and 'barometer' in self.__report['current_conditions'].keys() \ | ||
960 | 873 | and 'pressure' in self.__report['units'].keys(): | ||
961 | 874 | _value = self.__report['current_conditions']['barometer']['reading'] | ||
962 | 875 | _unit = self.__report['units']['pressure'] | ||
963 | 805 | if self.__weather_datasource == WeatherDataSource.YAHOO \ | 876 | if self.__weather_datasource == WeatherDataSource.YAHOO \ |
969 | 806 | and 'pressure' in self.__localized_report['atmosphere'].keys() \ | 877 | and 'pressure' in self.__report['atmosphere'].keys() \ |
970 | 807 | and 'pressure' in self.__localized_report['units'].keys(): | 878 | and 'pressure' in self.__report['units'].keys(): |
971 | 808 | value = self.__localized_report['atmosphere']['pressure'] | 879 | _value = self.__report['atmosphere']['pressure'] |
972 | 809 | unit = self.__localized_report['units']['pressure'] | 880 | _unit = self.__report['units']['pressure'] |
973 | 810 | return "%s: %s %s" % (_("Pressure"), value, units) | 881 | return "%s: %s %s" % (_("Pressure"), _value, _unit) |
974 | 811 | 882 | ||
978 | 812 | # Get temperature with units value - doesn't include 'Temperature' label | 883 | ## def get_temperature(self, needs_rounding = False): |
979 | 813 | def get_temperature(self, needs_rounding = False): | 884 | def get_temperature(self): |
980 | 814 | _value = "---" | 885 | """ Get temperature value and units string """ |
981 | 886 | _value = None | ||
982 | 815 | _unit = "" | 887 | _unit = "" |
998 | 816 | if self.__weather_datasource == WeatherDataSource.GOOGLE: | 888 | if (self.__weather_datasource == WeatherDataSource.WEATHER_COM and |
999 | 817 | if (self.__metric_system == MetricSystem.SI) \ | 889 | 'temperature' in self.__report['current_conditions'].keys() and |
1000 | 818 | and 'temp_c' in self.__report['current_conditions'].keys(): | 890 | 'temperature' in self.__report['units'].keys()): |
1001 | 819 | _value = self.__report['current_conditions']['temp_c'] | 891 | if ((self.__metric_system == UnitSystem.SI and |
1002 | 820 | _unit = "ËšC" | 892 | self.__report['units']['temperature'] == u"C") or |
1003 | 821 | elif 'temp_f' in self.__report['current_conditions'].keys(): | 893 | (self.__metric_system == UnitSystem.IMPERIAL and |
1004 | 822 | _value = self.__report['current_conditions']['temp_f'] | 894 | self.__report['units']['temperature' ] == u"F")): |
1005 | 823 | _unit = "ËšF" | 895 | _value = self.__report['current_conditions']['temperature'] |
1006 | 824 | if self.__weather_datasource == WeatherDataSource.YAHOO: | 896 | _unit = u"°%s" % self.__report['units']['temperature'] |
1007 | 825 | if (self.__metric_system == MetricSystem.SI) \ | 897 | if (self.__weather_datasource == WeatherDataSource.YAHOO and |
1008 | 826 | and 'temp' in self.__report['condition'].keys(): | 898 | 'temp' in self.__report['condition'].keys() and |
1009 | 827 | _value = NumberFormatter.format_float( | 899 | 'temperature' in self.__report['units'].keys()): |
1010 | 828 | ((float(self.__report['condition']['temp']) - 32) * 5/9), 1) | 900 | if ((self.__metric_system == UnitSystem.SI and |
1011 | 829 | _unit = "ËšC" | 901 | self.__report['units']['temperature'] == u"C") or |
1012 | 830 | else: | 902 | (self.__metric_system == UnitSystem.IMPERIAL and |
1013 | 903 | self.__report['units']['temperature'] == u"F")): | ||
1014 | 831 | _value = self.__report['condition']['temp'] | 904 | _value = self.__report['condition']['temp'] |
1022 | 832 | _unit = "˚F" | 905 | _unit = u"°%s" % self.__report['units']['temperature'] |
1023 | 833 | # round the value if required | 906 | ## # round the value if required |
1024 | 834 | if needs_rounding and _value != "---": | 907 | ## if needs_rounding and _value != "---": |
1025 | 835 | _value = NumberFormatter.format_float(locale.atof(_value), 0) | 908 | ## _value = NumberFormatter.format_float(locale.atof(_value), 0) |
1026 | 836 | return ("%s %s" % (_value, _unit)) | 909 | return (_value, _unit) |
1027 | 837 | 910 | ||
1028 | 838 | # Get temperature label | 911 | def get_temperature_string(self): |
1029 | 912 | """ Get temperature with units value - doesn't include 'Temperature' string """ | ||
1030 | 913 | (_value, _unit) = self.get_temperature() | ||
1031 | 914 | if _value is None: | ||
1032 | 915 | _value = "---" | ||
1033 | 916 | _unit = "" | ||
1034 | 917 | return (u"%s %s" % (_value, _unit)) | ||
1035 | 918 | |||
1036 | 839 | def get_temperature_label(self): | 919 | def get_temperature_label(self): |
1052 | 840 | return "%s: %s" % (_("Temperature"), self.get_temperature()) | 920 | """ Get text string for current temperature label """ |
1053 | 841 | 921 | return "%s: %s" % (_("Temperature"), self.get_temperature_string()) | |
1054 | 842 | # Get humidex parameter | 922 | |
1055 | 843 | def get_humidex_label(self): | 923 | def get_relative_string(self): |
1056 | 844 | if self.__weather_datasource == WeatherDataSource.GOOGLE or self.__weather_datasource == WeatherDataSource.YAHOO: | 924 | """ Get relative temperature with units value - doesn't include 'Feels Like' string """ |
1057 | 845 | #Empty for Yahoo and Google | 925 | # try relative heat |
1058 | 846 | return None | 926 | if self.__heat_index == RelativeFormula.HUMIDEX: |
1059 | 847 | #TODO: Update with NOAA data | 927 | (_value, _unit) = self.get_humidex() |
1060 | 848 | #dewPoint=2 | 928 | if self.__heat_index == RelativeFormula.HEATINDEX: |
1061 | 849 | #temp_c = 1 | 929 | (_value, _unit) = self.get_heat_index() |
1062 | 850 | #self.vapour_pressure = 6.11 * math.exp(5417.7530 * ( (1/273.16) - (1/(dewPoint+273.16)))) | 930 | if _value is not None: |
1063 | 851 | #self.humidex = temp_c + (0.5555)*(self.vapour_pressure - 10.0); | 931 | return (u"%s %s" % (_value, _unit)) |
1064 | 852 | #return ("%s: %.1f" % (_("Humidex"), self.humidex)).replace(".0", "") | 932 | # try relative chill |
1065 | 853 | 933 | if self.__chill_index == RelativeFormula.WINDCHILL: | |
1066 | 854 | # Get wind label | 934 | (_value, _unit) = self.get_wind_chill() |
1067 | 935 | if self.__chill_index == RelativeFormula.APPARENT: | ||
1068 | 936 | (_value, _unit) = self.get_apparent_temp() | ||
1069 | 937 | if _value is not None: | ||
1070 | 938 | return (u"%s %s" % (_value, _unit)) | ||
1071 | 939 | # use current temperature | ||
1072 | 940 | return self.get_temperature_string() | ||
1073 | 941 | |||
1074 | 942 | def get_relative_label(self): | ||
1075 | 943 | """ Get text string for relative temperature ("feels like") label """ | ||
1076 | 944 | return "%s: %s" % (_("Feels Like"), self.get_relative_string()) | ||
1077 | 945 | |||
1078 | 946 | def get_humidex(self): | ||
1079 | 947 | """ Calculate humidex and get value and units | ||
1080 | 948 | |||
1081 | 949 | The standard Humidex formula used by Environment Canada is: | ||
1082 | 950 | |||
1083 | 951 | humidex = (air temperature) + h | ||
1084 | 952 | |||
1085 | 953 | h = (0.5555)*(e - 10.0); | ||
1086 | 954 | e = vapour pressure in hPa (mbar), given by: | ||
1087 | 955 | e = 6.11 * exp [5417.7530 * ( (1/273.16) - (1/dewpoint) ) ] | ||
1088 | 956 | where dewpoint is expressed in Kelvins | ||
1089 | 957 | (temperature in K = temperature in °C + 273.1) | ||
1090 | 958 | and 5417.7530 is a rounded constant based on the molecular weight | ||
1091 | 959 | of water, latent heat of evaporation, and the universal gas constant. | ||
1092 | 960 | |||
1093 | 961 | """ | ||
1094 | 962 | #TODO: Update with NOAA data | ||
1095 | 963 | if self.__weather_datasource == WeatherDataSource.YAHOO: | ||
1096 | 964 | # Empty for Yahoo | ||
1097 | 965 | return (None, "") | ||
1098 | 966 | if self.__weather_datasource == WeatherDataSource.WEATHER_COM: | ||
1099 | 967 | if self.__report['units']['temperature'] == "F": | ||
1100 | 968 | # Humidex is calculated in C | ||
1101 | 969 | dew_point_f = float(self.__report['current_conditions']['dewpoint']) | ||
1102 | 970 | temp_f = float(self.__report['current_conditions']['temperature']) | ||
1103 | 971 | dew_point_c = ((dew_point_f - 32.0) * 5.0/9.0) | ||
1104 | 972 | temp_c = ((temp_f - 32.0) * 5.0/9.0) | ||
1105 | 973 | else: | ||
1106 | 974 | dew_point_c = float(self.__report['current_conditions']['dewpoint']) | ||
1107 | 975 | temp_c = float(self.__report['current_conditions']['temperature']) | ||
1108 | 976 | vapour_pressure = 6.11 * exp(5417.7530 * ( (1/273.16) - (1/(dew_point_c+273.16)))) | ||
1109 | 977 | humidex = temp_c + (0.5555)*(vapour_pressure - 10.0) | ||
1110 | 978 | # Humidex is meaningless if it is lower than temperature | ||
1111 | 979 | if humidex < temp_c: | ||
1112 | 980 | #return (u"%s: N/A" % _("Humidex")) | ||
1113 | 981 | return (None, "") | ||
1114 | 982 | if self.__report['units']['temperature'] == "F": | ||
1115 | 983 | humidex_f = (humidex*9.0/5.0) + 32.0 | ||
1116 | 984 | # Humidex is unitless (represents Celsius) so in F show units | ||
1117 | 985 | #return (u"%s: %s°F" % (_("Humidex"), NumberFormatter.format_float(humidex_f, 1))).replace(".0", "") | ||
1118 | 986 | #return (NumberFormatter.format_float(humidex_f, 1).replace(".0", ""), u"°F") | ||
1119 | 987 | return (int(round(humidex_f)), u"°F") | ||
1120 | 988 | else: | ||
1121 | 989 | #return ("%s: %.1f" % (_("Humidex"), humidex)).replace(".0", "") | ||
1122 | 990 | #return (u"%s: %s" % (_("Humidex"), NumberFormatter.format_float(humidex, 1))).replace(".0", "") | ||
1123 | 991 | #return (NumberFormatter.format_float(humidex, 1).replace(".0", ""), u"°C") | ||
1124 | 992 | return (int(round(humidex)), u"°C") | ||
1125 | 993 | |||
1126 | 994 | def get_heat_index(self): | ||
1127 | 995 | """ Calculate heat index and get value and units | ||
1128 | 996 | |||
1129 | 997 | The formula below approximates the heat index in degrees | ||
1130 | 998 | Fahrenheit, to within ±1.3 °F. It is the result of a | ||
1131 | 999 | multivariate fit (temperature equal to or greater than | ||
1132 | 1000 | 80°F and relative humidity equal to or greater than 40%) | ||
1133 | 1001 | to a model of the human body. | ||
1134 | 1002 | |||
1135 | 1003 | Heat Index = c_1 + (c_2 * T) + (c_3 * R) + (c_4 * T * R) + | ||
1136 | 1004 | (c_5 * T^2) + (c_6 * R^2) + (c_7 * T^2 * R) + | ||
1137 | 1005 | (c_8 * T * R^2) + (c_9 * T^2 * R^2) | ||
1138 | 1006 | where: | ||
1139 | 1007 | T = ambient dry-bulb temperature (in degrees Fahrenheit) | ||
1140 | 1008 | R = relative humidity (percentage value between 0 and 100) | ||
1141 | 1009 | |||
1142 | 1010 | """ | ||
1143 | 1011 | #TODO: Update with NOAA data | ||
1144 | 1012 | _value = None | ||
1145 | 1013 | |||
1146 | 1014 | if self.__weather_datasource == WeatherDataSource.YAHOO: | ||
1147 | 1015 | log.debug("Weather: get_heat_index: weather_datasource is Yahoo, " | ||
1148 | 1016 | "checking temp and humidity") | ||
1149 | 1017 | if self.__report['units']['temperature'] == "C": | ||
1150 | 1018 | units = 'metric' | ||
1151 | 1019 | elif self.__report['units']['temperature'] == "F": # else here? | ||
1152 | 1020 | units = 'imperial' | ||
1153 | 1021 | T = float(self.__report['condition']['temp']) | ||
1154 | 1022 | R = float(self.__report['atmosphere']['humidity']) | ||
1155 | 1023 | _value = pywapi.heat_index(T, R, units) | ||
1156 | 1024 | |||
1157 | 1025 | if self.__weather_datasource == WeatherDataSource.WEATHER_COM: | ||
1158 | 1026 | log.debug("Weather: get_heat_index: weather_datasource is " | ||
1159 | 1027 | "Weather.com, checking temp and humidity") | ||
1160 | 1028 | if self.__report['units']['temperature'] == "C": | ||
1161 | 1029 | units = 'metric' | ||
1162 | 1030 | elif self.__report['units']['temperature'] == "F": # else here? | ||
1163 | 1031 | units = 'imperial' | ||
1164 | 1032 | T = float(self.__report['current_conditions']['temperature']) | ||
1165 | 1033 | R = float(self.__report['current_conditions']['humidity']) | ||
1166 | 1034 | _value = pywapi.heat_index(T, R, units) | ||
1167 | 1035 | |||
1168 | 1036 | # Heat Index is only valid for temp >= 80°F and humidity >= 40%) | ||
1169 | 1037 | if _value is None: | ||
1170 | 1038 | return (_value, "") | ||
1171 | 1039 | if units == 'metric': | ||
1172 | 1040 | #return (u"%s: %s°C" % (_("Heat Index"), NumberFormatter.format_float(heat_index, 1))).replace(".0", "") | ||
1173 | 1041 | #return (NumberFormatter.format_float(_value, 1).replace(".0", ""), u"°C") | ||
1174 | 1042 | return (int(round(_value)), u"°C") | ||
1175 | 1043 | |||
1176 | 1044 | elif units == 'imperial': # else here? | ||
1177 | 1045 | #return (u"%s: %s°F" % (_("Heat Index"), NumberFormatter.format_float(heat_index, 1))).replace(".0", "") | ||
1178 | 1046 | #return (NumberFormatter.format_float(_value, 1).replace(".0", ""), u"°F") | ||
1179 | 1047 | return (int(round(_value)), u"°F") | ||
1180 | 1048 | |||
1181 | 1049 | def get_wind_chill(self): | ||
1182 | 1050 | """ Calculate wind chill index and get text string for label | ||
1183 | 1051 | |||
1184 | 1052 | The standard Wind Chill formula used by Environment Canada, | ||
1185 | 1053 | the 2001 JAG/TI Wind Chill Equivalent Temperature Index, is: | ||
1186 | 1054 | |||
1187 | 1055 | T_wc = 13.12 + 0.6215 * T_a - | ||
1188 | 1056 | 11.37 * V^0.16 + | ||
1189 | 1057 | 0.3965 * T_a * V^0.16 | ||
1190 | 1058 | where: | ||
1191 | 1059 | T_wc is the wind chill index based on Celsius | ||
1192 | 1060 | T_a is the air temperature in °C | ||
1193 | 1061 | V is the wind speed in km/h, at 10 m (standard anemometer height) | ||
1194 | 1062 | |||
1195 | 1063 | The equivalent formula in US customary units is: | ||
1196 | 1064 | |||
1197 | 1065 | T_wc = 35.74 + 0.6215 * T_a - | ||
1198 | 1066 | 35.75 * V^0.16 + | ||
1199 | 1067 | 0.4275 * T_a * V^0.16 | ||
1200 | 1068 | |||
1201 | 1069 | where: | ||
1202 | 1070 | T_wc is the wind chill index based on Fahrenheit | ||
1203 | 1071 | T_a is the air temperature °F | ||
1204 | 1072 | V is the wind speed in mph | ||
1205 | 1073 | |||
1206 | 1074 | Windchill temperature is defined only for temperatures at or | ||
1207 | 1075 | below 10 °C (50 °F) and wind speeds above 4.8 kilometres per | ||
1208 | 1076 | hour (3.0 mph). | ||
1209 | 1077 | |||
1210 | 1078 | """ | ||
1211 | 1079 | #TODO: Update with NOAA data | ||
1212 | 1080 | _value = None | ||
1213 | 1081 | |||
1214 | 1082 | if self.__report['units']['temperature'] == "C": | ||
1215 | 1083 | units = 'metric' | ||
1216 | 1084 | elif self.__report['units']['temperature'] == "F": # else here? | ||
1217 | 1085 | units = 'imperial' | ||
1218 | 1086 | |||
1219 | 1087 | if self.__weather_datasource == WeatherDataSource.YAHOO: | ||
1220 | 1088 | log.debug("Weather: get_wind_chill: weather_datasource is " | ||
1221 | 1089 | "Yahoo, checking temp and humidity") | ||
1222 | 1090 | T_a = float(self.__report['condition']['temp']) | ||
1223 | 1091 | V = float(self.__report['wind']['speed']) | ||
1224 | 1092 | |||
1225 | 1093 | if self.__weather_datasource == WeatherDataSource.WEATHER_COM: | ||
1226 | 1094 | log.debug("Weather: get_wind_chill: weather_datasource is " | ||
1227 | 1095 | "Weather.com, checking temp and humidity") | ||
1228 | 1096 | T_a = float(self.__report['current_conditions']['temperature']) | ||
1229 | 1097 | wind_speed = self.__report['current_conditions']['wind']['speed'] | ||
1230 | 1098 | V = (0.0 if wind_speed == 'calm' else float(wind_speed)) | ||
1231 | 1099 | |||
1232 | 1100 | # move below to pywapi | ||
1233 | 1101 | if units == 'metric': | ||
1234 | 1102 | _value = 13.12 + 0.6215 * T_a - 11.37 * pow(V, 0.16) + 0.3965 * T_a * pow(V, 0.16) | ||
1235 | 1103 | return (int(round(_value)), u"°C") | ||
1236 | 1104 | elif units == 'imperial': | ||
1237 | 1105 | _value = 35.74 + 0.6215 * T_a - 35.75 * pow(V, 0.16) + 0.4275 * T_a * pow(V, 0.16) | ||
1238 | 1106 | return (int(round(_value)), u"°F") | ||
1239 | 1107 | |||
1240 | 1108 | if _value is None: | ||
1241 | 1109 | return (_value, "") | ||
1242 | 1110 | |||
1243 | 1111 | def get_apparent_temp(self): | ||
1244 | 1112 | """ Calculate Australian apparent temperature and get text string for label | ||
1245 | 1113 | |||
1246 | 1114 | The standard formula for cooler temperatures used by the Australian | ||
1247 | 1115 | Bureau of Meteorology, the Australian Apparent Temperature, is: | ||
1248 | 1116 | |||
1249 | 1117 | AT = T_a + 0.33e - 0.70ws - 4.00 | ||
1250 | 1118 | |||
1251 | 1119 | Where: | ||
1252 | 1120 | T_a = Dry bulb temperature (°C) | ||
1253 | 1121 | e = Water vapour pressure (hPa) | ||
1254 | 1122 | ws = Wind speed (m/s) at an elevation of 10 meters | ||
1255 | 1123 | |||
1256 | 1124 | The vapour pressure can be calculated from the temperature and | ||
1257 | 1125 | relative humidity using the equation: | ||
1258 | 1126 | |||
1259 | 1127 | e = (rh / 100) * 6.105 * exp^[(17.27 * T_a) / (237.7 + T_a)] | ||
1260 | 1128 | |||
1261 | 1129 | Where: | ||
1262 | 1130 | T_a = Dry bulb temperature (°C) | ||
1263 | 1131 | rh = Relative humidity [%] | ||
1264 | 1132 | exp^ represents the exponential function | ||
1265 | 1133 | |||
1266 | 1134 | The Australian chill formula is only defined for temperatures | ||
1267 | 1135 | at or below 20°C (68°F) and wind speeds above 4.8 km/h (3.0 mph). | ||
1268 | 1136 | |||
1269 | 1137 | """ | ||
1270 | 1138 | #TODO: Update with NOAA data | ||
1271 | 1139 | _value = None | ||
1272 | 1140 | |||
1273 | 1141 | if self.__report['units']['temperature'] == "C": | ||
1274 | 1142 | units = 'metric' | ||
1275 | 1143 | elif self.__report['units']['temperature'] == "F": # else here? | ||
1276 | 1144 | units = 'imperial' | ||
1277 | 1145 | |||
1278 | 1146 | if self.__weather_datasource == WeatherDataSource.YAHOO: | ||
1279 | 1147 | log.debug("Weather: get_wind_chill: weather_datasource is " | ||
1280 | 1148 | "Yahoo, checking temp and humidity") | ||
1281 | 1149 | T_a = float(self.__report['condition']['temp']) | ||
1282 | 1150 | rh = float(self.__report['atmosphere']['humidity']) | ||
1283 | 1151 | ws = float(self.__report['wind']['speed']) | ||
1284 | 1152 | if self.__weather_datasource == WeatherDataSource.WEATHER_COM: | ||
1285 | 1153 | log.debug("Weather: get_wind_chill: weather_datasource is " | ||
1286 | 1154 | "Weather.com, checking temp and humidity") | ||
1287 | 1155 | T_a = float(self.__report['current_conditions']['temperature']) | ||
1288 | 1156 | rh = float(self.__report['current_conditions']['humidity']) | ||
1289 | 1157 | ws = float(self.__report['current_conditions']['wind']['speed']) | ||
1290 | 1158 | |||
1291 | 1159 | # calculated in °C, so need to convert from °F | ||
1292 | 1160 | if units == 'imperial': | ||
1293 | 1161 | T_a = ((T_a - 32.0) * 5.0/9.0) | ||
1294 | 1162 | |||
1295 | 1163 | e = (rh / 100) * 6.105 * exp((17.27 * T_a) / (237.7 + T_a)) | ||
1296 | 1164 | _value = T_a + 0.33 * e - 0.70 * ws - 4.00 | ||
1297 | 1165 | |||
1298 | 1166 | # Now convert back to °F | ||
1299 | 1167 | if units == 'imperial': | ||
1300 | 1168 | _value = (_value*9.0/5.0) + 32.0 | ||
1301 | 1169 | return (int(round(_value)), u"°F") | ||
1302 | 1170 | if units == 'metric': | ||
1303 | 1171 | return (int(round(_value)), u"°C") | ||
1304 | 1172 | |||
1305 | 1173 | if _value is None: | ||
1306 | 1174 | return (_value, "") | ||
1307 | 1175 | |||
1308 | 855 | def get_wind_label(self): | 1176 | def get_wind_label(self): |
1319 | 856 | if self.__weather_datasource == WeatherDataSource.GOOGLE: | 1177 | """ Get text string for current wind speed and direction """ |
1320 | 857 | # Convert units picked up from Google and replace units with currently configured | 1178 | if self.__weather_datasource == WeatherDataSource.WEATHER_COM: |
1321 | 858 | if 'wind_condition' in self.__localized_report['current_conditions'].keys(): | 1179 | # Create a wind_info structure from Weather.com data |
1322 | 859 | localized_wind_info = self.__localized_report['current_conditions']['wind_condition'].split(' ') | 1180 | wind_direction = u"%s (%s°)" % (self.__report['current_conditions']['wind']['text'], |
1323 | 860 | wind_direction = localized_wind_info[1] | 1181 | self.__report['current_conditions']['wind']['direction']) |
1324 | 861 | wind_info = self.__report['current_conditions']['wind_condition'].split(' ') | 1182 | wind_speed = self.__report['current_conditions']['wind']['speed'] |
1325 | 862 | wind_speed = wind_info[3] | 1183 | wind_units = self.__report['units']['speed'] |
1326 | 863 | else: | 1184 | if wind_speed == "calm": |
1327 | 864 | return _("Unknown") | 1185 | wind_speed = 0 |
1328 | 865 | 1186 | ##wind_direction = wind_direction.replace("CALM","Calm") | |
1329 | 1187 | wind_info = [_("Wind") + ":", wind_direction, wind_speed, wind_units] | ||
1330 | 866 | if self.__weather_datasource == WeatherDataSource.YAHOO: | 1188 | if self.__weather_datasource == WeatherDataSource.YAHOO: |
1337 | 867 | # Create a similar to Google wind_info structure from Yahoo data | 1189 | # Create a wind_info structure from Yahoo data |
1338 | 868 | wind_direction = "%s (%s˚)" % (self.get_wind_direction(self.__localized_report['wind']['direction']), self.__localized_report['wind']['direction']) | 1190 | wind_direction = u"%s (%s°)" % (_(pywapi.get_wind_direction(self.__report['wind']['direction'])), self.__report['wind']['direction']) |
1339 | 869 | wind_speed = self.__localized_report['wind']['speed'] | 1191 | wind_speed = self.__report['wind']['speed'] |
1340 | 870 | wind_units = self.__localized_report['units']['speed'] | 1192 | wind_units = self.__report['units']['speed'] |
1341 | 871 | localized_wind_info = [_("Wind") + ":", wind_direction, wind_speed, wind_units] | 1193 | wind_info = [_("Wind") + ":", wind_direction, wind_speed, wind_units] |
1336 | 872 | |||
1342 | 873 | 1194 | ||
1343 | 874 | try: | 1195 | try: |
1344 | 875 | _value = float(wind_speed) | 1196 | _value = float(wind_speed) |
1345 | 876 | except ValueError as e: | 1197 | except ValueError as e: |
1346 | 877 | log.error("Could not parse '%s' as wind speed." % str(wind_speed)) | 1198 | log.error("Could not parse '%s' as wind speed." % str(wind_speed)) |
1347 | 878 | _value = -1.0 | 1199 | _value = -1.0 |
1349 | 879 | 1200 | ||
1350 | 880 | # Parse Wind_direction - convert to selected scale | 1201 | # Parse Wind_direction - convert to selected scale |
1367 | 881 | if (self._wind_unit == WindUnits.MPH): | 1202 | if wind_units == "mph": |
1368 | 882 | _unit = __("mph", "mph", _value) | 1203 | if (self._wind_unit == WindUnits.MPH): |
1369 | 883 | if (self._wind_unit == WindUnits.MPS): | 1204 | _unit = __("mph", "mph", _value) |
1370 | 884 | _value *= 0.44704 | 1205 | if (self._wind_unit == WindUnits.MPS): |
1371 | 885 | _unit = __("m/s", "m/s", _value) | 1206 | _value *= 0.44704 |
1372 | 886 | if (self._wind_unit == WindUnits.BEAUFORT): | 1207 | _unit = __("m/s", "m/s", _value) |
1373 | 887 | if _value >= 0.0: | 1208 | if (self._wind_unit == WindUnits.BEAUFORT): |
1374 | 888 | _value = self.get_beaufort_from_mph(_value) | 1209 | if _value >= 0.0: |
1375 | 889 | _unit = "" | 1210 | _value = pywapi.wind_beaufort_scale(_value, WindUnits.MPH) |
1376 | 890 | if (self._wind_unit == WindUnits.KPH): | 1211 | _unit = "" |
1377 | 891 | _value *= 1.609344 | 1212 | if (self._wind_unit == WindUnits.KPH): |
1378 | 892 | _unit = __("km/h", "km/h", _value) | 1213 | _value *= 1.609344 |
1379 | 893 | if (self._wind_unit == WindUnits.KNOTS): | 1214 | _unit = __("km/h", "km/h", _value) |
1380 | 894 | _value *= 0.868976241900648 | 1215 | if (self._wind_unit == WindUnits.KNOTS): |
1381 | 895 | _unit = __("knot", "knots", _value) | 1216 | _value *= 0.868976241900648 |
1382 | 896 | 1217 | _unit = __("knot", "knots", _value) | |
1383 | 1218 | elif wind_units == "km/h": | ||
1384 | 1219 | if (self._wind_unit == WindUnits.MPH): | ||
1385 | 1220 | _value *= 0.621371 | ||
1386 | 1221 | _unit = __("mph", "mph", _value) | ||
1387 | 1222 | if (self._wind_unit == WindUnits.MPS): | ||
1388 | 1223 | _value *= 0.277778 | ||
1389 | 1224 | _unit = __("m/s", "m/s", _value) | ||
1390 | 1225 | if (self._wind_unit == WindUnits.BEAUFORT): | ||
1391 | 1226 | if _value >= 0.0: | ||
1392 | 1227 | _value = pywapi.wind_beaufort_scale(_value, WindUnits.KPH) | ||
1393 | 1228 | _unit = "" | ||
1394 | 1229 | if (self._wind_unit == WindUnits.KPH): | ||
1395 | 1230 | _unit = __("km/h", "km/h", _value) | ||
1396 | 1231 | if (self._wind_unit == WindUnits.KNOTS): | ||
1397 | 1232 | _value *= 0.539957 | ||
1398 | 1233 | _unit = __("knot", "knots", _value) | ||
1399 | 1234 | else: | ||
1400 | 1235 | log.error("Could not parse '%s' as wind units." % wind_units) | ||
1401 | 1236 | _value = -1.0 | ||
1402 | 1237 | |||
1403 | 897 | # Join wind_info data in a label | 1238 | # Join wind_info data in a label |
1406 | 898 | localized_wind_info[len(localized_wind_info)-1] = _unit | 1239 | wind_info[len(wind_info)-1] = _unit |
1407 | 899 | localized_wind_info[len(localized_wind_info)-2] = \ | 1240 | wind_info[len(wind_info)-2] = \ |
1408 | 900 | NumberFormatter.format_float(_value, 1) | 1241 | NumberFormatter.format_float(_value, 1) |
1409 | 901 | if _value < 0.0: | 1242 | if _value < 0.0: |
1413 | 902 | localized_wind_info[1:] = ["", "N\A", ""] | 1243 | wind_info[1:] = ["", "N\A", ""] |
1414 | 903 | return "%s %s %s %s" % (localized_wind_info[0], localized_wind_info[1], \ | 1244 | if _value == 0.0: |
1415 | 904 | localized_wind_info[2], localized_wind_info[3]) | 1245 | wind_info[1:] = [_("Calm"), "", ""] |
1416 | 1246 | return "%s %s %s %s" % (wind_info[0], wind_info[1], \ | ||
1417 | 1247 | wind_info[2], wind_info[3]) | ||
1418 | 905 | 1248 | ||
1419 | 906 | # Get sunrise label | ||
1420 | 907 | def get_sunrise_label(self): | 1249 | def get_sunrise_label(self): |
1421 | 1250 | """ Get text string for sunrise time """ | ||
1422 | 908 | return "%s: %s" % (_("Sunrise"), TimeFormatter.format_time(self.__sunrise_t)) | 1251 | return "%s: %s" % (_("Sunrise"), TimeFormatter.format_time(self.__sunrise_t)) |
1423 | 909 | 1252 | ||
1424 | 910 | # Get sunset label | ||
1425 | 911 | def get_sunset_label(self): | 1253 | def get_sunset_label(self): |
1426 | 1254 | """ Get text string for sunset time """ | ||
1427 | 912 | return "%s: %s" % (_("Sunset"), TimeFormatter.format_time(self.__sunset_t)) | 1255 | return "%s: %s" % (_("Sunset"), TimeFormatter.format_time(self.__sunset_t)) |
1428 | 913 | 1256 | ||
1429 | 914 | 1257 | ||
1430 | 915 | # Additional functions | ||
1431 | 916 | # Convert wind direction from degrees to localized direction | ||
1432 | 917 | def get_wind_direction(self, degrees): | ||
1433 | 918 | try: | ||
1434 | 919 | degrees = int(degrees) | ||
1435 | 920 | except ValueError: | ||
1436 | 921 | return '' | ||
1437 | 922 | |||
1438 | 923 | if degrees < 23 or degrees >= 338: | ||
1439 | 924 | #Short wind direction - north | ||
1440 | 925 | return _('N') | ||
1441 | 926 | elif degrees < 68: | ||
1442 | 927 | return _('NE') | ||
1443 | 928 | elif degrees < 113: | ||
1444 | 929 | return _('E') | ||
1445 | 930 | elif degrees < 158: | ||
1446 | 931 | return _('SE') | ||
1447 | 932 | elif degrees < 203: | ||
1448 | 933 | return _('S') | ||
1449 | 934 | elif degrees < 248: | ||
1450 | 935 | return _('SW') | ||
1451 | 936 | elif degrees < 293: | ||
1452 | 937 | return _('W') | ||
1453 | 938 | elif degrees < 338: | ||
1454 | 939 | return _('NW') | ||
1455 | 940 | |||
1456 | 941 | # Convert mph to Beufort scale | ||
1457 | 942 | def get_beaufort_from_mph(self, value): | ||
1458 | 943 | if value < 1: | ||
1459 | 944 | return 0 | ||
1460 | 945 | elif value < 4: | ||
1461 | 946 | return 1 | ||
1462 | 947 | elif value < 8: | ||
1463 | 948 | return 2 | ||
1464 | 949 | elif value < 13: | ||
1465 | 950 | return 3 | ||
1466 | 951 | elif value < 18: | ||
1467 | 952 | return 4 | ||
1468 | 953 | elif value < 25: | ||
1469 | 954 | return 5 | ||
1470 | 955 | elif value < 27: | ||
1471 | 956 | return 6 | ||
1472 | 957 | elif value < 39: | ||
1473 | 958 | return 7 | ||
1474 | 959 | elif value < 47: | ||
1475 | 960 | return 8 | ||
1476 | 961 | elif value < 89: | ||
1477 | 962 | return 9 | ||
1478 | 963 | elif value < 64: | ||
1479 | 964 | return 10 | ||
1480 | 965 | elif value < 73: | ||
1481 | 966 | return 11 | ||
1482 | 967 | elif value >= 73: | ||
1483 | 968 | return 12 | ||
1484 | 969 | |||
1485 | 970 | class indicator_weather(threading.Thread): | 1258 | class indicator_weather(threading.Thread): |
1486 | 971 | """ Indicator class """ | 1259 | """ Indicator class """ |
1487 | 972 | last_update_time = None | 1260 | last_update_time = None |
1488 | 973 | 1261 | ||
1489 | 974 | # Settings values | 1262 | # Settings values |
1490 | 975 | # Formats: setting value, object name (for preferences dialog), value assigned (optional) | 1263 | # Formats: setting value, object name (for preferences dialog), value assigned (optional) |
1493 | 976 | metric_systems = { 'S': ('si', MetricSystem.SI), | 1264 | metric_systems = { 'S': ('si', UnitSystem.SI), |
1494 | 977 | 'I': ('imperial', MetricSystem.IMPERIAL)} | 1265 | 'I': ('imperial', UnitSystem.IMPERIAL)} |
1495 | 978 | 1266 | ||
1498 | 979 | weather_sources = { 'G': ('google', WeatherDataSource.GOOGLE), | 1267 | weather_sources = { 'Y': ('yahoo', WeatherDataSource.YAHOO), |
1499 | 980 | 'Y': ('yahoo', WeatherDataSource.YAHOO)} | 1268 | 'W': ('weather-com', WeatherDataSource.WEATHER_COM)} |
1500 | 981 | 1269 | ||
1501 | 982 | notifications = {'N': 'nonotif', | 1270 | notifications = {'N': 'nonotif', |
1502 | 983 | 'O': 'notifsevere', | 1271 | 'O': 'notifsevere', |
1503 | @@ -989,17 +1277,31 @@ | |||
1504 | 989 | 'beaufort': ("beaufort", WindUnits.BEAUFORT), | 1277 | 'beaufort': ("beaufort", WindUnits.BEAUFORT), |
1505 | 990 | 'knots': ("knots", WindUnits.KNOTS)} | 1278 | 'knots': ("knots", WindUnits.KNOTS)} |
1506 | 991 | 1279 | ||
1508 | 992 | # Initializing and reading settings | 1280 | heat_estimates = {'heatindex': ("heatindex", RelativeFormula.HEATINDEX), |
1509 | 1281 | 'humidex': ("humidex", RelativeFormula.HUMIDEX)} | ||
1510 | 1282 | |||
1511 | 1283 | chill_estimates = {'windchill': ("wctindex", RelativeFormula.WINDCHILL), | ||
1512 | 1284 | 'apparent': ("aatindex", RelativeFormula.APPARENT)} | ||
1513 | 1285 | |||
1514 | 993 | def __init__(self): | 1286 | def __init__(self): |
1515 | 1287 | """ Initializing and reading previously-saved settings """ | ||
1516 | 994 | log.debug("Indicator: creating") | 1288 | log.debug("Indicator: creating") |
1517 | 995 | threading.Thread.__init__(self) | 1289 | threading.Thread.__init__(self) |
1518 | 996 | self.main_icon = os.path.join | 1290 | self.main_icon = os.path.join |
1523 | 997 | self.winder = appindicator.Indicator ("indicator-weather", "weather-indicator", appindicator.CATEGORY_OTHER) | 1291 | self.winder = AppIndicator.Indicator.new("indicator-weather", "weather-indicator", AppIndicator.IndicatorCategory.OTHER) |
1524 | 998 | self.winder.set_status (appindicator.STATUS_ACTIVE) | 1292 | |
1525 | 999 | self.winder.set_attention_icon ("weather-indicator-error") | 1293 | self.queue = Queue.Queue() |
1526 | 1000 | 1294 | ||
1527 | 1001 | self.menu_update_lock = threading.Lock() | 1295 | self.menu_update_lock = threading.Lock() |
1528 | 1296 | self.status_update_lock = threading.Lock() | ||
1529 | 1297 | |||
1530 | 1298 | self.status_update_lock.acquire(True) | ||
1531 | 1299 | self.winder.set_status(AppIndicator.IndicatorStatus.ACTIVE) | ||
1532 | 1300 | self.winder.set_attention_icon("weather-indicator-error") | ||
1533 | 1301 | self.status_update_lock.release() | ||
1534 | 1302 | |||
1535 | 1002 | self.refreshed_minutes_ago = -1 | 1303 | self.refreshed_minutes_ago = -1 |
1536 | 1304 | self.places_changed = False | ||
1537 | 1003 | monitor_upower(self.on_system_sleep, self.on_system_resume, log) | 1305 | monitor_upower(self.on_system_sleep, self.on_system_resume, log) |
1538 | 1004 | 1306 | ||
1539 | 1005 | log.debug("Indicator: reading settings") | 1307 | log.debug("Indicator: reading settings") |
1540 | @@ -1010,27 +1312,37 @@ | |||
1541 | 1010 | self.unit = self.settings.get_value("unit") | 1312 | self.unit = self.settings.get_value("unit") |
1542 | 1011 | self.notif = self.settings.get_value("notif") | 1313 | self.notif = self.settings.get_value("notif") |
1543 | 1012 | self.wind = self.settings.get_value("wind") | 1314 | self.wind = self.settings.get_value("wind") |
1544 | 1315 | self.heat = self.settings.get_value("heat") | ||
1545 | 1316 | self.chill = self.settings.get_value("chill") | ||
1546 | 1013 | self.source = self.settings.get_value("data_source") | 1317 | self.source = self.settings.get_value("data_source") |
1547 | 1014 | self.placechosen = self.settings.get_value("placechosen") | 1318 | self.placechosen = self.settings.get_value("placechosen") |
1548 | 1015 | self.places = str(self.settings.get_value("places")) | 1319 | self.places = str(self.settings.get_value("places")) |
1549 | 1016 | self.show_label = self.settings.get_value("show_label") | 1320 | self.show_label = self.settings.get_value("show_label") |
1553 | 1017 | 1321 | self.show_relative = self.settings.get_value("show_relative") | |
1554 | 1018 | log.debug("Preferences: got settings: rate=%s, unit=%s, notif=%s, wind=%s, placechosen=%s, places=%s" % | 1322 | self.show_wind = self.settings.get_value("show_wind") |
1555 | 1019 | (self.rate, self.unit, self.notif, self.wind, self.placechosen, self.places)) | 1323 | self.show_suntimes = self.settings.get_value("show_suntimes") |
1556 | 1324 | |||
1557 | 1325 | log.debug("Preferences: got settings: rate=%s, unit=%s, notif=%s, " | ||
1558 | 1326 | "wind=%s, placechosen=%s, places=%s, heat=%s, chill=%s" % | ||
1559 | 1327 | (self.rate, self.unit, self.notif, self.wind, | ||
1560 | 1328 | self.placechosen, self.places, self.heat, self.chill)) | ||
1561 | 1020 | 1329 | ||
1562 | 1021 | #Setting default values | 1330 | #Setting default values |
1564 | 1022 | self.metric_system = MetricSystem.SI | 1331 | self.metric_system = UnitSystem.SI |
1565 | 1023 | self.wind_unit = WindUnits.MPH | 1332 | self.wind_unit = WindUnits.MPH |
1566 | 1024 | self.place = None | 1333 | self.place = None |
1567 | 1025 | self.menu = None | 1334 | self.menu = None |
1568 | 1026 | self.condition = None | 1335 | self.condition = None |
1569 | 1027 | self.icon = None | 1336 | self.icon = None |
1571 | 1028 | 1337 | self.heat_index = RelativeFormula.HUMIDEX | |
1572 | 1338 | self.chill_index = RelativeFormula.WINDCHILL | ||
1573 | 1339 | |||
1574 | 1029 | #Parsing settings | 1340 | #Parsing settings |
1575 | 1030 | # Metric system | 1341 | # Metric system |
1576 | 1031 | if self.unit in (False, None): | 1342 | if self.unit in (False, None): |
1577 | 1032 | default_value = 'S' | 1343 | default_value = 'S' |
1579 | 1033 | log.debug("Indicator: could not parse unit, setting to %s" % default_value) | 1344 | log.debug("Indicator: could not parse unit, " |
1580 | 1345 | "setting to %s" % default_value) | ||
1581 | 1034 | self.settings.set_value("unit", default_value) | 1346 | self.settings.set_value("unit", default_value) |
1582 | 1035 | self.unit = default_value | 1347 | self.unit = default_value |
1583 | 1036 | self.metric_system = self.metric_systems[self.unit][1] | 1348 | self.metric_system = self.metric_systems[self.unit][1] |
1584 | @@ -1038,25 +1350,70 @@ | |||
1585 | 1038 | # Notification | 1350 | # Notification |
1586 | 1039 | if self.notif in (False, None): | 1351 | if self.notif in (False, None): |
1587 | 1040 | default_value = 'N' | 1352 | default_value = 'N' |
1589 | 1041 | log.debug("Indicator: could not parse notif, setting to %s" % default_value) | 1353 | log.debug("Indicator: could not parse notif, " |
1590 | 1354 | "setting to %s" % default_value) | ||
1591 | 1042 | self.settings.set_value("notif", default_value) | 1355 | self.settings.set_value("notif", default_value) |
1592 | 1043 | self.notif = default_value | 1356 | self.notif = default_value |
1593 | 1357 | Notify.init("weather-indicator") | ||
1594 | 1044 | 1358 | ||
1595 | 1045 | # Wind units | 1359 | # Wind units |
1596 | 1046 | if self.wind in (False, None): | 1360 | if self.wind in (False, None): |
1597 | 1047 | default_value = 'mph' | 1361 | default_value = 'mph' |
1599 | 1048 | log.debug("Indicator: could not parse wind, setting to %s" % default_value) | 1362 | log.debug("Indicator: could not parse wind, " |
1600 | 1363 | "setting to %s" % default_value) | ||
1601 | 1049 | self.settings.set_value("wind", default_value) | 1364 | self.settings.set_value("wind", default_value) |
1602 | 1050 | self.wind = default_value | 1365 | self.wind = default_value |
1603 | 1051 | self.wind_unit = self.wind_systems[self.wind][1] | 1366 | self.wind_unit = self.wind_systems[self.wind][1] |
1604 | 1052 | 1367 | ||
1605 | 1368 | # Heat estimate formula | ||
1606 | 1369 | if self.heat in (False, None): | ||
1607 | 1370 | default_value = 'humidex' | ||
1608 | 1371 | log.debug("Indicator: could not parse heat, " | ||
1609 | 1372 | "setting to %s" % default_value) | ||
1610 | 1373 | self.settings.set_value("heat", default_value) | ||
1611 | 1374 | self.heat = default_value | ||
1612 | 1375 | self.heat_index = self.heat_estimates[self.heat][1] | ||
1613 | 1376 | |||
1614 | 1377 | # Chill estimate formula | ||
1615 | 1378 | if self.chill in (False, None): | ||
1616 | 1379 | default_value = 'windchill' | ||
1617 | 1380 | log.debug("Indicator: could not parse chill, " | ||
1618 | 1381 | "setting to %s" % default_value) | ||
1619 | 1382 | self.settings.set_value("chill", default_value) | ||
1620 | 1383 | self.chill = default_value | ||
1621 | 1384 | self.chill_index = self.chill_estimates[self.chill][1] | ||
1622 | 1385 | |||
1623 | 1053 | # Show label in indicator? | 1386 | # Show label in indicator? |
1625 | 1054 | self.show_label = True if self.show_label == 1 else False | 1387 | if self.show_label == 1: |
1626 | 1388 | self.show_label = True | ||
1627 | 1389 | self.label_guide = "100 ËšC" # Guide for width of label | ||
1628 | 1390 | else: | ||
1629 | 1391 | self.show_label = False | ||
1630 | 1392 | self.label_guide = " " | ||
1631 | 1055 | 1393 | ||
1632 | 1394 | # Show relative temperature in dropdown? | ||
1633 | 1395 | if self.show_relative == 1: | ||
1634 | 1396 | self.show_relative = True | ||
1635 | 1397 | else: | ||
1636 | 1398 | self.show_relative = False | ||
1637 | 1399 | |||
1638 | 1400 | # Show windspeed & direction in dropdown? | ||
1639 | 1401 | if self.show_wind == 1: | ||
1640 | 1402 | self.show_wind = True | ||
1641 | 1403 | else: | ||
1642 | 1404 | self.show_wind = False | ||
1643 | 1405 | |||
1644 | 1406 | # Show sunrise & sunset times in dropdown? | ||
1645 | 1407 | if self.show_suntimes == 1: | ||
1646 | 1408 | self.show_suntimes = True | ||
1647 | 1409 | else: | ||
1648 | 1410 | self.show_suntimes = False | ||
1649 | 1411 | |||
1650 | 1056 | # Weather source | 1412 | # Weather source |
1652 | 1057 | if self.source in (False, None): | 1413 | if self.source in (False, None, 'G'): # If set to Google, reset it |
1653 | 1058 | default_value = 'Y' | 1414 | default_value = 'Y' |
1655 | 1059 | log.debug("Indicator: could not parse data source, setting to %s" % default_value) | 1415 | log.debug("Indicator: could not parse data source, " |
1656 | 1416 | "setting to %s" % default_value) | ||
1657 | 1060 | self.settings.set_value("data_source", default_value) | 1417 | self.settings.set_value("data_source", default_value) |
1658 | 1061 | self.source = default_value | 1418 | self.source = default_value |
1659 | 1062 | self.weather_source = self.weather_sources[self.source][1] | 1419 | self.weather_source = self.weather_sources[self.source][1] |
1660 | @@ -1064,7 +1421,8 @@ | |||
1661 | 1064 | # Rate | 1421 | # Rate |
1662 | 1065 | if self.rate in (False, None): | 1422 | if self.rate in (False, None): |
1663 | 1066 | default_value = 15 | 1423 | default_value = 15 |
1665 | 1067 | log.debug("Indicator: could not parse rate, setting to %s" % str(default_value)) | 1424 | log.debug("Indicator: could not parse rate, " |
1666 | 1425 | "setting to %s" % str(default_value)) | ||
1667 | 1068 | self.settings.set_value("refresh_rate", default_value) | 1426 | self.settings.set_value("refresh_rate", default_value) |
1668 | 1069 | self.rate = default_value | 1427 | self.rate = default_value |
1669 | 1070 | 1428 | ||
1670 | @@ -1077,9 +1435,11 @@ | |||
1671 | 1077 | self.placechosen = int(self.placechosen) | 1435 | self.placechosen = int(self.placechosen) |
1672 | 1078 | 1436 | ||
1673 | 1079 | # Places list | 1437 | # Places list |
1674 | 1438 | self.menu_update_lock.acquire(True) | ||
1675 | 1080 | if self.places in (False, None, '', '[]', "['']"): | 1439 | if self.places in (False, None, '', '[]', "['']"): |
1676 | 1081 | log.debug("Indicator: could not parse places") | 1440 | log.debug("Indicator: could not parse places") |
1677 | 1082 | self.menu_noplace() | 1441 | self.menu_noplace() |
1678 | 1442 | self.menu_update_lock.release() | ||
1679 | 1083 | else: | 1443 | else: |
1680 | 1084 | self.places = eval(self.places) | 1444 | self.places = eval(self.places) |
1681 | 1085 | if self.placechosen >= len(self.places): | 1445 | if self.placechosen >= len(self.places): |
1682 | @@ -1089,89 +1449,96 @@ | |||
1683 | 1089 | if self.location_details in (False, None, '', '[]', "['']"): | 1449 | if self.location_details in (False, None, '', '[]', "['']"): |
1684 | 1090 | log.debug("Indicator: could not parse current location details") | 1450 | log.debug("Indicator: could not parse current location details") |
1685 | 1091 | self.menu_noplace() | 1451 | self.menu_noplace() |
1686 | 1452 | self.menu_update_lock.release() | ||
1687 | 1092 | else: | 1453 | else: |
1688 | 1093 | self.location_details = eval(self.location_details) | 1454 | self.location_details = eval(self.location_details) |
1690 | 1094 | self.menu_normal() | 1455 | ## self.menu_normal() |
1691 | 1456 | self.menu_update_lock.release() | ||
1692 | 1095 | self.update_weather() | 1457 | self.update_weather() |
1693 | 1096 | 1458 | ||
1694 | 1097 | # Set a label of indicator | ||
1695 | 1098 | def update_label(self, label): | 1459 | def update_label(self, label): |
1696 | 1460 | """ Set the label of the indicator """ | ||
1697 | 1099 | if (hasattr(self.winder, 'set_label')): | 1461 | if (hasattr(self.winder, 'set_label')): |
1698 | 1100 | log.debug("Indicator: update_label: setting label to '%s'" % label) | 1462 | log.debug("Indicator: update_label: setting label to '%s'" % label) |
1699 | 1101 | self.previous_label_value = label | 1463 | self.previous_label_value = label |
1703 | 1102 | self.winder.set_label(label) if self.show_label else self.winder.set_label(" ") | 1464 | self.status_update_lock.acquire(True) |
1704 | 1103 | self.winder.set_status(appindicator.STATUS_ATTENTION) | 1465 | self.winder.set_label(label, self.label_guide) if self.show_label else self.winder.set_label(" ", " ") |
1705 | 1104 | self.winder.set_status(appindicator.STATUS_ACTIVE) | 1466 | self.winder.set_status(AppIndicator.IndicatorStatus.ATTENTION) |
1706 | 1467 | self.winder.set_status(AppIndicator.IndicatorStatus.ACTIVE) | ||
1707 | 1468 | self.status_update_lock.release() | ||
1708 | 1105 | 1469 | ||
1709 | 1106 | # Show a menu if no places specified | ||
1710 | 1107 | def menu_noplace(self): | 1470 | def menu_noplace(self): |
1711 | 1471 | """ Show a menu if no places specified """ | ||
1712 | 1108 | log.debug("Indicator: making a menu for no places") | 1472 | log.debug("Indicator: making a menu for no places") |
1714 | 1109 | menu_noplace = gtk.Menu() | 1473 | menu_noplace = Gtk.Menu() |
1715 | 1110 | 1474 | ||
1717 | 1111 | setup = gtk.MenuItem(_("Set Up Weather...")) | 1475 | setup = Gtk.MenuItem(_("Set Up Weather...")) |
1718 | 1112 | setup.connect("activate", self.prefs) | 1476 | setup.connect("activate", self.prefs) |
1719 | 1113 | setup.show() | 1477 | setup.show() |
1720 | 1114 | menu_noplace.append(setup) | 1478 | menu_noplace.append(setup) |
1721 | 1115 | 1479 | ||
1723 | 1116 | quit = gtk.ImageMenuItem(gtk.STOCK_QUIT) | 1480 | quit = Gtk.ImageMenuItem.new_from_stock(Gtk.STOCK_QUIT, None) |
1724 | 1117 | quit.connect("activate", self.quit) | 1481 | quit.connect("activate", self.quit) |
1725 | 1118 | quit.show() | 1482 | quit.show() |
1726 | 1119 | menu_noplace.append(quit) | 1483 | menu_noplace.append(quit) |
1727 | 1120 | 1484 | ||
1728 | 1485 | self.status_update_lock.acquire(True) | ||
1729 | 1121 | self.winder.set_menu(menu_noplace) | 1486 | self.winder.set_menu(menu_noplace) |
1730 | 1122 | self.winder.set_icon(os.path.join(PROJECT_ROOT_DIRECTORY, "share/indicator-weather/media/icon.png")) | 1487 | self.winder.set_icon(os.path.join(PROJECT_ROOT_DIRECTORY, "share/indicator-weather/media/icon.png")) |
1735 | 1123 | self.winder.set_status(appindicator.STATUS_ATTENTION) | 1488 | self.winder.set_status(AppIndicator.IndicatorStatus.ATTENTION) |
1736 | 1124 | self.winder.set_status(appindicator.STATUS_ACTIVE) | 1489 | self.winder.set_status(AppIndicator.IndicatorStatus.ACTIVE) |
1737 | 1125 | 1490 | self.status_update_lock.release() | |
1738 | 1126 | # Show menu with data | 1491 | |
1739 | 1127 | def menu_normal(self): | 1492 | def menu_normal(self): |
1740 | 1493 | """ Show a menu with weather and location data """ | ||
1741 | 1128 | log.debug("Indicator: menu_normal: filling in a menu for found places") | 1494 | log.debug("Indicator: menu_normal: filling in a menu for found places") |
1743 | 1129 | self.menu = gtk.Menu() | 1495 | |
1744 | 1496 | self.menu = Gtk.Menu() | ||
1745 | 1130 | 1497 | ||
1746 | 1131 | ##City | 1498 | ##City |
1748 | 1132 | self.city_show = gtk.MenuItem() | 1499 | self.city_show = Gtk.MenuItem() |
1749 | 1133 | self.city_show.set_sensitive(True) | 1500 | self.city_show.set_sensitive(True) |
1750 | 1134 | self.menu.append(self.city_show) | 1501 | self.menu.append(self.city_show) |
1751 | 1135 | self.city_show.show() | 1502 | self.city_show.show() |
1752 | 1136 | 1503 | ||
1753 | 1137 | ##Condition | 1504 | ##Condition |
1755 | 1138 | self.cond_show = gtk.MenuItem() | 1505 | self.cond_show = Gtk.MenuItem() |
1756 | 1139 | self.cond_show.set_sensitive(True) | 1506 | self.cond_show.set_sensitive(True) |
1757 | 1140 | self.cond_show.show() | 1507 | self.cond_show.show() |
1758 | 1141 | self.menu.append(self.cond_show) | 1508 | self.menu.append(self.cond_show) |
1759 | 1142 | 1509 | ||
1760 | 1143 | ##Temperature | 1510 | ##Temperature |
1762 | 1144 | self.temp_show = gtk.MenuItem() | 1511 | self.temp_show = Gtk.MenuItem() |
1763 | 1145 | self.temp_show.set_sensitive(True) | 1512 | self.temp_show.set_sensitive(True) |
1764 | 1146 | self.temp_show.show() | 1513 | self.temp_show.show() |
1765 | 1147 | self.menu.append(self.temp_show) | 1514 | self.menu.append(self.temp_show) |
1766 | 1148 | 1515 | ||
1772 | 1149 | ##Humidex | 1516 | ##Relative Temperature |
1773 | 1150 | self.humidex_show = gtk.MenuItem() | 1517 | self.relative_show = Gtk.MenuItem() |
1774 | 1151 | self.humidex_show.set_sensitive(True) | 1518 | self.relative_show.set_sensitive(True) |
1775 | 1152 | self.humidex_show.show() | 1519 | self.relative_show.show() |
1776 | 1153 | self.menu.append(self.humidex_show) | 1520 | self.menu.append(self.relative_show) |
1777 | 1154 | 1521 | ||
1778 | 1155 | ##Humidity | 1522 | ##Humidity |
1780 | 1156 | self.humid_show = gtk.MenuItem() | 1523 | self.humid_show = Gtk.MenuItem() |
1781 | 1157 | self.humid_show.set_sensitive(True) | 1524 | self.humid_show.set_sensitive(True) |
1782 | 1158 | self.humid_show.show() | 1525 | self.humid_show.show() |
1783 | 1159 | self.menu.append(self.humid_show) | 1526 | self.menu.append(self.humid_show) |
1784 | 1160 | 1527 | ||
1785 | 1161 | ##Wind | 1528 | ##Wind |
1787 | 1162 | self.wind_show = gtk.MenuItem() | 1529 | self.wind_show = Gtk.MenuItem() |
1788 | 1163 | self.wind_show.set_sensitive(True) | 1530 | self.wind_show.set_sensitive(True) |
1789 | 1164 | self.wind_show.show() | 1531 | self.wind_show.show() |
1790 | 1165 | self.menu.append(self.wind_show) | 1532 | self.menu.append(self.wind_show) |
1791 | 1166 | 1533 | ||
1792 | 1167 | ##Sunrise | 1534 | ##Sunrise |
1794 | 1168 | self.sunrise_show = gtk.MenuItem() | 1535 | self.sunrise_show = Gtk.MenuItem() |
1795 | 1169 | self.sunrise_show.set_sensitive(True) | 1536 | self.sunrise_show.set_sensitive(True) |
1796 | 1170 | self.sunrise_show.show() | 1537 | self.sunrise_show.show() |
1797 | 1171 | self.menu.append(self.sunrise_show) | 1538 | self.menu.append(self.sunrise_show) |
1798 | 1172 | 1539 | ||
1799 | 1173 | ##Sunset | 1540 | ##Sunset |
1801 | 1174 | self.sunset_show = gtk.MenuItem() | 1541 | self.sunset_show = Gtk.MenuItem() |
1802 | 1175 | self.sunset_show.set_sensitive(True) | 1542 | self.sunset_show.set_sensitive(True) |
1803 | 1176 | self.sunset_show.show() | 1543 | self.sunset_show.show() |
1804 | 1177 | self.menu.append(self.sunset_show) | 1544 | self.menu.append(self.sunset_show) |
1805 | @@ -1179,65 +1546,68 @@ | |||
1806 | 1179 | ##Cities | 1546 | ##Cities |
1807 | 1180 | if len(self.places) != 1: | 1547 | if len(self.places) != 1: |
1808 | 1181 | ##Breaker | 1548 | ##Breaker |
1810 | 1182 | breaker = gtk.SeparatorMenuItem() | 1549 | breaker = Gtk.SeparatorMenuItem() |
1811 | 1183 | breaker.show() | 1550 | breaker.show() |
1812 | 1184 | self.menu.append(breaker) | 1551 | self.menu.append(breaker) |
1813 | 1185 | 1552 | ||
1814 | 1186 | log.debug("Indicator: menu_normal: adding first location menu item '%s'" % self.places[0][1]) | 1553 | log.debug("Indicator: menu_normal: adding first location menu item '%s'" % self.places[0][1]) |
1816 | 1187 | loco1 = gtk.RadioMenuItem(None, self.places[0][1]) | 1554 | loco1 = Gtk.RadioMenuItem.new_with_label([], self.places[0][1]) |
1817 | 1188 | if self.placechosen == 0: | 1555 | if self.placechosen == 0: |
1818 | 1189 | loco1.set_active(True) | 1556 | loco1.set_active(True) |
1819 | 1190 | loco1.connect("toggled", self.on_city_changed) | 1557 | loco1.connect("toggled", self.on_city_changed) |
1820 | 1191 | loco1.show() | 1558 | loco1.show() |
1821 | 1192 | self.menu.append(loco1) | 1559 | self.menu.append(loco1) |
1822 | 1560 | group = loco1.get_group() | ||
1823 | 1193 | for place in self.places[1:]: | 1561 | for place in self.places[1:]: |
1824 | 1194 | log.debug("Indicator: menu_normal: adding location menu item '%s'" % place[1]) | 1562 | log.debug("Indicator: menu_normal: adding location menu item '%s'" % place[1]) |
1826 | 1195 | loco = gtk.RadioMenuItem(loco1, place[1]) | 1563 | loco = Gtk.RadioMenuItem.new_with_label(group, place[1]) |
1827 | 1196 | if self.places.index(place) == self.placechosen: | 1564 | if self.places.index(place) == self.placechosen: |
1828 | 1197 | loco.set_active(True) | 1565 | loco.set_active(True) |
1829 | 1198 | loco.connect("toggled", self.on_city_changed) | 1566 | loco.connect("toggled", self.on_city_changed) |
1830 | 1199 | loco.show() | 1567 | loco.show() |
1831 | 1200 | self.menu.append(loco) | 1568 | self.menu.append(loco) |
1832 | 1569 | group = loco.get_group() | ||
1833 | 1201 | 1570 | ||
1834 | 1202 | ##Breaker | 1571 | ##Breaker |
1836 | 1203 | breaker = gtk.SeparatorMenuItem() | 1572 | breaker = Gtk.SeparatorMenuItem() |
1837 | 1204 | breaker.show() | 1573 | breaker.show() |
1838 | 1205 | self.menu.append(breaker) | 1574 | self.menu.append(breaker) |
1839 | 1206 | 1575 | ||
1841 | 1207 | self.refresh_show = gtk.MenuItem() | 1576 | self.refresh_show = Gtk.MenuItem() |
1842 | 1208 | #label will be set later | 1577 | #label will be set later |
1843 | 1209 | self.refresh_show.connect("activate", self.update_weather) | 1578 | self.refresh_show.connect("activate", self.update_weather) |
1844 | 1210 | self.refresh_show.show() | 1579 | self.refresh_show.show() |
1845 | 1211 | self.menu.append(self.refresh_show) | 1580 | self.menu.append(self.refresh_show) |
1846 | 1212 | 1581 | ||
1848 | 1213 | ext_show = gtk.MenuItem(_("Forecast")) | 1582 | ext_show = Gtk.MenuItem(_("Forecast")) |
1849 | 1214 | ext_show.connect("activate", self.extforecast) | 1583 | ext_show.connect("activate", self.extforecast) |
1850 | 1215 | ext_show.show() | 1584 | ext_show.show() |
1851 | 1216 | self.menu.append(ext_show) | 1585 | self.menu.append(ext_show) |
1852 | 1217 | 1586 | ||
1853 | 1218 | ##Preferences | 1587 | ##Preferences |
1855 | 1219 | prefs_show = gtk.MenuItem(_("Preferences...")) | 1588 | prefs_show = Gtk.MenuItem(_("Preferences...")) |
1856 | 1220 | prefs_show.connect("activate", self.prefs) | 1589 | prefs_show.connect("activate", self.prefs) |
1857 | 1221 | prefs_show.show() | 1590 | prefs_show.show() |
1858 | 1222 | self.menu.append(prefs_show) | 1591 | self.menu.append(prefs_show) |
1859 | 1223 | 1592 | ||
1860 | 1224 | ##About | 1593 | ##About |
1862 | 1225 | about_show = gtk.MenuItem(_("About...")) | 1594 | about_show = Gtk.MenuItem(_("About...")) |
1863 | 1226 | about_show.connect("activate", self.about) | 1595 | about_show.connect("activate", self.about) |
1864 | 1227 | about_show.show() | 1596 | about_show.show() |
1865 | 1228 | self.menu.append(about_show) | 1597 | self.menu.append(about_show) |
1866 | 1229 | 1598 | ||
1867 | 1230 | ##Quit | 1599 | ##Quit |
1869 | 1231 | quit = gtk.ImageMenuItem(gtk.STOCK_QUIT) | 1600 | quit = Gtk.ImageMenuItem.new_from_stock(Gtk.STOCK_QUIT, None) |
1870 | 1232 | quit.connect("activate", self.quit) | 1601 | quit.connect("activate", self.quit) |
1871 | 1233 | quit.show() | 1602 | quit.show() |
1872 | 1234 | self.menu.append(quit) | 1603 | self.menu.append(quit) |
1873 | 1235 | 1604 | ||
1874 | 1236 | self.winder.set_menu(self.menu) | 1605 | self.winder.set_menu(self.menu) |
1875 | 1237 | self.update_label(" ") | 1606 | self.update_label(" ") |
1876 | 1607 | |||
1877 | 1238 | 1608 | ||
1878 | 1239 | # Another city has been selected from radiobutton | ||
1879 | 1240 | def on_city_changed(self,widget): | 1609 | def on_city_changed(self,widget): |
1880 | 1610 | """ Another city has been selected from radiobutton """ | ||
1881 | 1241 | if widget.get_active(): | 1611 | if widget.get_active(): |
1882 | 1242 | for place in self.places: | 1612 | for place in self.places: |
1883 | 1243 | if (place[1] == widget.get_label()): | 1613 | if (place[1] == widget.get_label()): |
1884 | @@ -1251,28 +1621,30 @@ | |||
1885 | 1251 | self.location_details = self.settings.get_location_details(self.place[0]) | 1621 | self.location_details = self.settings.get_location_details(self.place[0]) |
1886 | 1252 | if self.location_details in (False, None, '', '[]', "['']"): | 1622 | if self.location_details in (False, None, '', '[]', "['']"): |
1887 | 1253 | log.debug("Indicator: could not parse location details for placechosen='%s'" % self.placechosen) | 1623 | log.debug("Indicator: could not parse location details for placechosen='%s'" % self.placechosen) |
1888 | 1624 | self.menu_update_lock.acquire(True) | ||
1889 | 1254 | self.menu_noplace() | 1625 | self.menu_noplace() |
1890 | 1626 | self.menu_update_lock.release() | ||
1891 | 1255 | else: | 1627 | else: |
1892 | 1256 | self.location_details = eval(self.location_details) | 1628 | self.location_details = eval(self.location_details) |
1893 | 1257 | self.settings.set_value("placechosen", self.placechosen) | 1629 | self.settings.set_value("placechosen", self.placechosen) |
1894 | 1258 | self.update_weather(False) | 1630 | self.update_weather(False) |
1895 | 1259 | 1631 | ||
1896 | 1260 | def on_system_sleep(self): | 1632 | def on_system_sleep(self): |
1899 | 1261 | """ | 1633 | """Callback from UPower that system suspends/hibernates |
1900 | 1262 | Callback from UPower that system suspends/hibernates | 1634 | |
1901 | 1263 | """ | 1635 | """ |
1902 | 1264 | # store time | 1636 | # store time |
1903 | 1265 | self.sleep_time = datetime.datetime.now() | 1637 | self.sleep_time = datetime.datetime.now() |
1904 | 1266 | log.debug("Indicator: system goes to sleep at %s" % self.sleep_time) | 1638 | log.debug("Indicator: system goes to sleep at %s" % self.sleep_time) |
1905 | 1267 | # remove gobject timeouts | 1639 | # remove gobject timeouts |
1906 | 1268 | if hasattr(self, "refresh_id"): | 1640 | if hasattr(self, "refresh_id"): |
1908 | 1269 | gobject.source_remove(self.refresh_id) | 1641 | GObject.source_remove(self.refresh_id) |
1909 | 1270 | if hasattr(self, "rate_id"): | 1642 | if hasattr(self, "rate_id"): |
1911 | 1271 | gobject.source_remove(self.rate_id) | 1643 | GObject.source_remove(self.rate_id) |
1912 | 1272 | 1644 | ||
1913 | 1273 | def on_system_resume(self): | 1645 | def on_system_resume(self): |
1916 | 1274 | """ | 1646 | """Callback from UPower that system resumes |
1917 | 1275 | Callback from UPower that system resumes | 1647 | |
1918 | 1276 | """ | 1648 | """ |
1919 | 1277 | now = datetime.datetime.now() | 1649 | now = datetime.datetime.now() |
1920 | 1278 | log.debug("Indicator: system resumes at %s" % now) | 1650 | log.debug("Indicator: system resumes at %s" % now) |
1921 | @@ -1291,25 +1663,26 @@ | |||
1922 | 1291 | else: | 1663 | else: |
1923 | 1292 | self.update_weather() | 1664 | self.update_weather() |
1924 | 1293 | 1665 | ||
1925 | 1294 | # Schedule weather update | ||
1926 | 1295 | def schedule_weather_update(self, rate_override = None): | 1666 | def schedule_weather_update(self, rate_override = None): |
1927 | 1667 | """ Schedule the next weather update """ | ||
1928 | 1296 | if hasattr(self, "rate_id"): | 1668 | if hasattr(self, "rate_id"): |
1930 | 1297 | gobject.source_remove(self.rate_id) | 1669 | GObject.source_remove(self.rate_id) |
1931 | 1298 | if rate_override: | 1670 | if rate_override: |
1934 | 1299 | self.rate_id = gobject.timeout_add( | 1671 | self.rate_id = GObject.timeout_add( |
1935 | 1300 | int(rate_override) * 60000, self.update_weather) | 1672 | ## int(rate_override) * 60000, self.update_weather) |
1936 | 1673 | int(rate_override * 60000), self.update_weather) | ||
1937 | 1301 | else: | 1674 | else: |
1939 | 1302 | self.rate_id = gobject.timeout_add( | 1675 | self.rate_id = GObject.timeout_add( |
1940 | 1303 | int(self.rate) * 60000, self.update_weather) | 1676 | int(self.rate) * 60000, self.update_weather) |
1941 | 1304 | 1677 | ||
1942 | 1305 | # Schedule weather update | ||
1943 | 1306 | def schedule_refresh_label_update(self): | 1678 | def schedule_refresh_label_update(self): |
1944 | 1679 | """ Schedule the next 'Refresh' label update """ | ||
1945 | 1307 | if hasattr(self, "refresh_id"): | 1680 | if hasattr(self, "refresh_id"): |
1948 | 1308 | gobject.source_remove(self.refresh_id) | 1681 | GObject.source_remove(self.refresh_id) |
1949 | 1309 | self.refresh_id = gobject.timeout_add(60000, self.update_refresh_label) | 1682 | self.refresh_id = GObject.timeout_add(60000, self.update_refresh_label) |
1950 | 1310 | 1683 | ||
1951 | 1311 | # Update 'Refresh' label with time since last successful data refresh | ||
1952 | 1312 | def update_refresh_label(self, reset_minutes = None): | 1684 | def update_refresh_label(self, reset_minutes = None): |
1953 | 1685 | """ Update 'Refresh' label with time since last successful data refresh """ | ||
1954 | 1313 | if reset_minutes is not None: | 1686 | if reset_minutes is not None: |
1955 | 1314 | self.refreshed_minutes_ago = reset_minutes | 1687 | self.refreshed_minutes_ago = reset_minutes |
1956 | 1315 | else: | 1688 | else: |
1957 | @@ -1319,6 +1692,7 @@ | |||
1958 | 1319 | return False | 1692 | return False |
1959 | 1320 | 1693 | ||
1960 | 1321 | def set_refresh_label(self, refreshing=False): | 1694 | def set_refresh_label(self, refreshing=False): |
1961 | 1695 | """ Update the 'Refresh' label text """ | ||
1962 | 1322 | if refreshing: | 1696 | if refreshing: |
1963 | 1323 | refresh_label=_("Refreshing, please wait") | 1697 | refresh_label=_("Refreshing, please wait") |
1964 | 1324 | elif self.refreshed_minutes_ago < 0: | 1698 | elif self.refreshed_minutes_ago < 0: |
1965 | @@ -1329,68 +1703,86 @@ | |||
1966 | 1329 | refresh_label = "%s (%s)" % (_("Refresh"), _("%d min. ago") % self.refreshed_minutes_ago) | 1703 | refresh_label = "%s (%s)" % (_("Refresh"), _("%d min. ago") % self.refreshed_minutes_ago) |
1967 | 1330 | self.refresh_show.set_label(refresh_label) | 1704 | self.refresh_show.set_label(refresh_label) |
1968 | 1331 | 1705 | ||
1971 | 1332 | # Load weather data from cache and display its values | 1706 | def get_cached_weather(self, queue): |
1972 | 1333 | def show_cached_weather(self): | 1707 | """ Load weather data from cache and put it onto the queue """ |
1973 | 1334 | try: | 1708 | try: |
1975 | 1335 | self.menu_update_lock.acquire(True) | 1709 | log.debug("Indicator: show_cached_weather: setting " |
1976 | 1710 | "previous_condition to None") | ||
1977 | 1336 | self.previous_condition = None | 1711 | self.previous_condition = None |
1978 | 1337 | cached_weather = self.settings.get_weather(self.places[self.placechosen][0]) | 1712 | cached_weather = self.settings.get_weather(self.places[self.placechosen][0]) |
1979 | 1338 | if cached_weather is not None: | 1713 | if cached_weather is not None: |
1980 | 1339 | cached_weather = eval(cached_weather) | 1714 | cached_weather = eval(cached_weather) |
1989 | 1340 | log.debug("Indicator: loading weather from cache for %s" % self.places[self.placechosen]) | 1715 | log.debug("Indicator: loading weather from cache " |
1990 | 1341 | self.menu_normal() | 1716 | "for %s" % self.places[self.placechosen]) |
1991 | 1342 | self.set_refresh_label(True) | 1717 | # Put the cached weather onto to the Queue |
1992 | 1343 | self.icon = cached_weather['icon'] | 1718 | queue.put({'cached_weather': cached_weather}) |
1993 | 1344 | if (self.icon == False): | 1719 | except Exception, e: |
1994 | 1345 | self.winder.set_icon(os.path.join(PROJECT_ROOT_DIRECTORY, "share/indicator-weather/media/icon_unknown_condition.png")) | 1720 | log.error(e) |
1995 | 1346 | else: | 1721 | log.debug(traceback.format_exc(e)) |
1988 | 1347 | self.winder.set_icon(self.icon) | ||
1996 | 1348 | 1722 | ||
2006 | 1349 | self.city_show.set_label(self.places[self.placechosen][1]) | 1723 | def show_cached_weather(self, cached_weather): |
2007 | 1350 | self.previous_condition = cached_weather['condition'] | 1724 | """ Update the indicator icon, label and menu with cached weather data """ |
2008 | 1351 | self.cond_show.set_label(cached_weather['condition']) | 1725 | try: |
2009 | 1352 | self.temp_show.set_label(cached_weather['temper']) | 1726 | self.menu_normal() |
2010 | 1353 | if cached_weather['humidex'] != None: | 1727 | self.set_refresh_label(True) |
2011 | 1354 | self.humidex_show.set_label(cached_weather['humidex']) | 1728 | self.icon = cached_weather['icon'] |
2012 | 1355 | else: | 1729 | if (self.icon == False): |
2013 | 1356 | self.humidex_show.destroy() | 1730 | self.winder.set_icon( |
2014 | 1357 | self.humid_show.set_label(cached_weather['humidity']) | 1731 | os.path.join(PROJECT_ROOT_DIRECTORY, |
2015 | 1732 | "share/indicator-weather/media/icon_unknown_condition.png") | ||
2016 | 1733 | ) | ||
2017 | 1734 | else: | ||
2018 | 1735 | self.winder.set_icon(self.icon) | ||
2019 | 1736 | |||
2020 | 1737 | self.city_show.set_label(self.places[self.placechosen][1]) | ||
2021 | 1738 | self.previous_condition = cached_weather['condition'] | ||
2022 | 1739 | self.cond_show.set_label(cached_weather['condition']) | ||
2023 | 1740 | self.temp_show.set_label(cached_weather['temper']) | ||
2024 | 1741 | if (self.show_relative and cached_weather['feelslike'] != None): | ||
2025 | 1742 | self.relative_show.set_visible(True) | ||
2026 | 1743 | self.relative_show.set_label(cached_weather['feelslike']) | ||
2027 | 1744 | else: | ||
2028 | 1745 | self.relative_show.set_visible(False) | ||
2029 | 1746 | self.humid_show.set_label(cached_weather['humidity']) | ||
2030 | 1747 | if self.show_wind: | ||
2031 | 1748 | self.wind_show.set_visible(True) | ||
2032 | 1358 | self.wind_show.set_label(cached_weather['wind']) | 1749 | self.wind_show.set_label(cached_weather['wind']) |
2033 | 1750 | else: | ||
2034 | 1751 | self.wind_show.set_visible(False) | ||
2035 | 1752 | if self.show_suntimes: | ||
2036 | 1753 | self.sunrise_show.set_visible(True) | ||
2037 | 1359 | self.sunrise_show.set_label(cached_weather['sunrise']) | 1754 | self.sunrise_show.set_label(cached_weather['sunrise']) |
2038 | 1755 | self.sunset_show.set_visible(True) | ||
2039 | 1360 | self.sunset_show.set_label(cached_weather['sunset']) | 1756 | self.sunset_show.set_label(cached_weather['sunset']) |
2043 | 1361 | self.update_label(cached_weather['label']) | 1757 | else: |
2044 | 1362 | self.winder.set_status(appindicator.STATUS_ATTENTION) | 1758 | self.sunrise_show.set_visible(False) |
2045 | 1363 | self.winder.set_status(appindicator.STATUS_ACTIVE) | 1759 | self.sunset_show.set_visible(False) |
2046 | 1364 | 1760 | ||
2047 | 1761 | self.update_label(cached_weather['label']) | ||
2048 | 1762 | |||
2049 | 1365 | except Exception, e: | 1763 | except Exception, e: |
2050 | 1366 | log.error(e) | 1764 | log.error(e) |
2051 | 1367 | log.debug(traceback.format_exc(e)) | 1765 | log.debug(traceback.format_exc(e)) |
2052 | 1368 | 1766 | ||
2058 | 1369 | self.menu_update_lock.release() | 1767 | def get_new_weather_data(self, notif, queue): |
2059 | 1370 | 1768 | """ Get fresh weather data from source and put it onto the queue """ | |
2055 | 1371 | # Get fresh weather data | ||
2056 | 1372 | def get_new_weather_data(self, notif = True): | ||
2057 | 1373 | |||
2060 | 1374 | # get weather and catch any exception | 1769 | # get weather and catch any exception |
2061 | 1375 | weather = None | 1770 | weather = None |
2062 | 1376 | try: | 1771 | try: |
2063 | 1377 | weather = self.get_weather() | 1772 | weather = self.get_weather() |
2064 | 1378 | |||
2065 | 1379 | except urllib2.URLError, e: | 1773 | except urllib2.URLError, e: |
2066 | 1380 | weather = None | 1774 | weather = None |
2067 | 1381 | log.error("Indicator: networking error: %s" % e) | 1775 | log.error("Indicator: networking error: %s" % e) |
2068 | 1382 | |||
2069 | 1383 | except Exception, e: | 1776 | except Exception, e: |
2070 | 1384 | weather = None | 1777 | weather = None |
2071 | 1385 | log.error(e) | 1778 | log.error(e) |
2072 | 1386 | log.debug(traceback.format_exc(e)) | 1779 | log.debug(traceback.format_exc(e)) |
2073 | 1780 | # Put the new weather data onto the Queue | ||
2074 | 1781 | queue.put({'weather': weather}) | ||
2075 | 1387 | 1782 | ||
2076 | 1783 | def show_new_weather_data(self, weather): | ||
2077 | 1784 | """ Update the indicator icon, label and menu with new weather data """ | ||
2078 | 1388 | try: | 1785 | try: |
2079 | 1389 | # wait until cacher finishes | ||
2080 | 1390 | log.debug("Indicator: updateWeather: waiting for 'Cacher' thread to terminate") | ||
2081 | 1391 | self.menu_update_lock.acquire(True) | ||
2082 | 1392 | self.menu_update_lock.release() | ||
2083 | 1393 | |||
2084 | 1394 | if weather is None: | 1786 | if weather is None: |
2085 | 1395 | # remove the "Refreshing" status | 1787 | # remove the "Refreshing" status |
2086 | 1396 | self.set_refresh_label() | 1788 | self.set_refresh_label() |
2087 | @@ -1399,35 +1791,59 @@ | |||
2088 | 1399 | # Repeat an attempt in one minute | 1791 | # Repeat an attempt in one minute |
2089 | 1400 | self.schedule_weather_update(1) | 1792 | self.schedule_weather_update(1) |
2090 | 1401 | return | 1793 | return |
2092 | 1402 | 1794 | ||
2093 | 1403 | # Fill in menu with data | 1795 | # Fill in menu with data |
2094 | 1404 | log.debug("Indicator: updateWeather: got condition '%s', icon '%s'" % (self.condition, self.icon)) | 1796 | log.debug("Indicator: updateWeather: got condition '%s', icon '%s'" % (self.condition, self.icon)) |
2095 | 1405 | self.condition = weather.get_condition_label() | 1797 | self.condition = weather.get_condition_label() |
2096 | 1406 | self.icon = weather.get_icon_name() | 1798 | self.icon = weather.get_icon_name() |
2099 | 1407 | log.debug("Indicator: fill in menu with params: city='%s', temp='%s', humid='%s', wind='%s', sunrise='%s', sunset='%s', puretemp=%s" % (self.places[self.placechosen][1], weather.get_temperature_label(), weather.get_humidity_label(), weather.get_wind_label(), weather.get_sunrise_label(), weather.get_sunset_label(), weather.get_temperature())) | 1799 | log.debug("Indicator: fill in menu with params: " \ |
2100 | 1408 | 1800 | "city='%s', temp='%s', humid='%s', " \ | |
2101 | 1801 | "wind='%s', sunrise='%s', sunset='%s', " \ | ||
2102 | 1802 | "puretemp=%s" % (self.places[self.placechosen][1], | ||
2103 | 1803 | weather.get_temperature_label(), | ||
2104 | 1804 | weather.get_humidity_label(), | ||
2105 | 1805 | weather.get_wind_label(), | ||
2106 | 1806 | weather.get_sunrise_label(), | ||
2107 | 1807 | weather.get_sunset_label(), | ||
2108 | 1808 | weather.get_temperature_string())) | ||
2109 | 1409 | self.menu_normal() | 1809 | self.menu_normal() |
2110 | 1410 | self.update_refresh_label(0) | 1810 | self.update_refresh_label(0) |
2111 | 1411 | self.city_show.set_label(self.places[self.placechosen][1]) | 1811 | self.city_show.set_label(self.places[self.placechosen][1]) |
2112 | 1412 | self.cond_show.set_label(self.condition) | 1812 | self.cond_show.set_label(self.condition) |
2113 | 1413 | self.temp_show.set_label(weather.get_temperature_label()) | 1813 | self.temp_show.set_label(weather.get_temperature_label()) |
2116 | 1414 | if (weather.get_humidex_label() != None): | 1814 | _relative_label = weather.get_relative_label() |
2117 | 1415 | self.humidex_show.set_label(weather.get_humidex_label()) | 1815 | if (self.show_relative and "---" not in _relative_label): |
2118 | 1816 | self.relative_show.set_visible(True) | ||
2119 | 1817 | self.relative_show.set_label(_relative_label) | ||
2120 | 1416 | else: | 1818 | else: |
2122 | 1417 | self.humidex_show.destroy() | 1819 | self.relative_show.set_visible(False) |
2123 | 1418 | self.humid_show.set_label(weather.get_humidity_label()) | 1820 | self.humid_show.set_label(weather.get_humidity_label()) |
2129 | 1419 | self.wind_show.set_label(weather.get_wind_label()) | 1821 | if self.show_wind: |
2130 | 1420 | self.sunrise_show.set_label(weather.get_sunrise_label()) | 1822 | self.wind_show.set_visible(True) |
2131 | 1421 | self.sunset_show.set_label(weather.get_sunset_label()) | 1823 | self.wind_show.set_label(weather.get_wind_label()) |
2132 | 1422 | 1824 | else: | |
2133 | 1423 | # Saving cached data, unless correct icon is supplied | 1825 | self.wind_show.set_visible(False) |
2134 | 1826 | if self.show_suntimes: | ||
2135 | 1827 | self.sunrise_show.set_visible(True) | ||
2136 | 1828 | self.sunrise_show.set_label(weather.get_sunrise_label()) | ||
2137 | 1829 | self.sunset_show.set_visible(True) | ||
2138 | 1830 | self.sunset_show.set_label(weather.get_sunset_label()) | ||
2139 | 1831 | else: | ||
2140 | 1832 | self.sunrise_show.set_visible(False) | ||
2141 | 1833 | self.sunset_show.set_visible(False) | ||
2142 | 1834 | |||
2143 | 1835 | # Save cached data if correct icon is supplied | ||
2144 | 1424 | if (self.icon == False): | 1836 | if (self.icon == False): |
2146 | 1425 | self.winder.set_icon(os.path.join(PROJECT_ROOT_DIRECTORY, "share/indicator-weather/media/icon_unknown_condition.png")) | 1837 | self.winder.set_icon( |
2147 | 1838 | os.path.join(PROJECT_ROOT_DIRECTORY, | ||
2148 | 1839 | "share/indicator-weather/media/icon_unknown_condition.png") | ||
2149 | 1840 | ) | ||
2150 | 1426 | else: | 1841 | else: |
2151 | 1427 | self.winder.set_icon(self.icon) | 1842 | self.winder.set_icon(self.icon) |
2152 | 1428 | self.settings.save_weather(weather, self.places[self.placechosen][0]) | 1843 | self.settings.save_weather(weather, self.places[self.placechosen][0]) |
2155 | 1429 | self.update_label(weather.get_temperature(needs_rounding=True)) | 1844 | # Update the indicator label |
2156 | 1430 | 1845 | self.update_label(weather.get_temperature_string()) | |
2157 | 1846 | |||
2158 | 1431 | # Notify user, if notifications are enabled | 1847 | # Notify user, if notifications are enabled |
2159 | 1432 | if self.condition != self.previous_condition and self.notif == 'U': | 1848 | if self.condition != self.previous_condition and self.notif == 'U': |
2160 | 1433 | # Weather condition has changed | 1849 | # Weather condition has changed |
2161 | @@ -1437,106 +1853,135 @@ | |||
2162 | 1437 | # Severe weather condition notification | 1853 | # Severe weather condition notification |
2163 | 1438 | log.debug("Indicator: updateWeather: severe condition notification") | 1854 | log.debug("Indicator: updateWeather: severe condition notification") |
2164 | 1439 | self.notify(self.condition, self.icon, severe=True) | 1855 | self.notify(self.condition, self.icon, severe=True) |
2166 | 1440 | 1856 | # Save the current condition to track changes for notifications | |
2167 | 1441 | self.previous_condition = self.condition | 1857 | self.previous_condition = self.condition |
2168 | 1442 | |||
2169 | 1443 | except Exception, e: | 1858 | except Exception, e: |
2170 | 1444 | log.error(e) | 1859 | log.error(e) |
2171 | 1445 | log.debug(traceback.format_exc(e)) | 1860 | log.debug(traceback.format_exc(e)) |
2172 | 1446 | 1861 | ||
2173 | 1862 | # Schedule the next weather fetch | ||
2174 | 1447 | self.schedule_weather_update() | 1863 | self.schedule_weather_update() |
2177 | 1448 | 1864 | ||
2176 | 1449 | # Update weather | ||
2178 | 1450 | def update_weather(self, notif=True, widget=None): | 1865 | def update_weather(self, notif=True, widget=None): |
2180 | 1451 | log.debug("Indicator: updateWeather: updating weather for %s" % self.places[self.placechosen]) | 1866 | """ Update the displayed weather data from cache and fetch new data """ |
2181 | 1867 | log.debug("Indicator: updateWeather: updating weather for %s" % | ||
2182 | 1868 | self.places[self.placechosen]) | ||
2183 | 1452 | # First, display cached data | 1869 | # First, display cached data |
2185 | 1453 | threading.Thread(target=self.show_cached_weather, name='Cache').start() | 1870 | cache_thread = threading.Thread(target=self.get_cached_weather, |
2186 | 1871 | name='Cache', args=(self.queue,)) | ||
2187 | 1872 | cache_thread.start() | ||
2188 | 1873 | |||
2189 | 1454 | # Then, start a new thread with real data pickup | 1874 | # Then, start a new thread with real data pickup |
2193 | 1455 | threading.Thread(target=self.get_new_weather_data, name='Fetcher').start() | 1875 | fetcher_thread = threading.Thread(target=self.get_new_weather_data, |
2194 | 1456 | 1876 | name='Fetcher', | |
2195 | 1457 | # Get current weather for selected location | 1877 | args=(self.notif, self.queue)) |
2196 | 1878 | fetcher_thread.start() | ||
2197 | 1879 | |||
2198 | 1880 | # Update the menu with the cached weather | ||
2199 | 1881 | cache_thread.join() | ||
2200 | 1882 | cached_weather = self.queue.get() | ||
2201 | 1883 | if cached_weather is not None and cached_weather.has_key('cached_weather'): | ||
2202 | 1884 | self.show_cached_weather(cached_weather['cached_weather']) | ||
2203 | 1885 | |||
2204 | 1886 | # Update the menu with the new weather | ||
2205 | 1887 | fetcher_thread.join() | ||
2206 | 1888 | weather = self.queue.get() | ||
2207 | 1889 | if weather is not None and weather.has_key('weather'): | ||
2208 | 1890 | self.show_new_weather_data(weather['weather']) | ||
2209 | 1891 | |||
2210 | 1458 | def get_weather(self): | 1892 | def get_weather(self): |
2213 | 1459 | log.debug("Indicator: getWeather for location '%s'" % self.location_details['full name']) | 1893 | """ Get current weather for selected location """ |
2214 | 1460 | self.current_location = Location(self.metric_system, self.wind_unit, self.location_details) | 1894 | log.debug("Indicator: getWeather for location '%s'" % |
2215 | 1895 | self.location_details['full name']) | ||
2216 | 1896 | self.current_location = Location(self.metric_system, self.wind_unit, | ||
2217 | 1897 | self.heat_index, self.chill_index, | ||
2218 | 1898 | self.location_details) | ||
2219 | 1461 | log.debug("Indicator: getWeather: updating weather report") | 1899 | log.debug("Indicator: getWeather: updating weather report") |
2220 | 1462 | self.current_location.update_weather_data(self.weather_source) | 1900 | self.current_location.update_weather_data(self.weather_source) |
2221 | 1463 | return self.current_location.weather | 1901 | return self.current_location.weather |
2222 | 1464 | 1902 | ||
2226 | 1465 | # Show notification to user | 1903 | def notify(self,condition,icon,severe=False): |
2227 | 1466 | def notify(self,conditon,icon,severe=False): | 1904 | """ Show notification to user according to preferences """ |
2228 | 1467 | log.debug("Indicator: Notify on weather condition, severe=%s, condition=%s, icon=%s" % (severe, self.condition, icon)) | 1905 | log.debug("Indicator: Notify on weather condition, severe=%s, " |
2229 | 1906 | "condition=%s, icon=%s" % (severe, condition, icon)) | ||
2230 | 1468 | if severe: | 1907 | if severe: |
2234 | 1469 | n = pynotify.Notification (_("Severe weather alert"), | 1908 | n = Notify.Notification (_("Severe weather alert"), |
2235 | 1470 | self.condition, | 1909 | condition, |
2236 | 1471 | icon) | 1910 | icon) |
2237 | 1472 | else: | 1911 | else: |
2239 | 1473 | n = pynotify.Notification (self.condition, "", icon) | 1912 | n = Notify.Notification (condition, "", icon) |
2240 | 1474 | n.show () | 1913 | n.show () |
2241 | 1475 | 1914 | ||
2242 | 1476 | # Menu callbacks | ||
2243 | 1477 | # Open Preferences dialog | ||
2244 | 1478 | def prefs(self, widget): | 1915 | def prefs(self, widget): |
2245 | 1916 | """ Menu callback to open Preferences dialog """ | ||
2246 | 1479 | log.debug("Indicator: open Preferences") | 1917 | log.debug("Indicator: open Preferences") |
2247 | 1480 | if ((not hasattr(self, 'prefswindow')) or (not self.prefswindow.get_visible())): | 1918 | if ((not hasattr(self, 'prefswindow')) or (not self.prefswindow.get_visible())): |
2248 | 1481 | self.prefswindow = PreferencesDialog() | 1919 | self.prefswindow = PreferencesDialog() |
2249 | 1482 | self.prefswindow.show() | 1920 | self.prefswindow.show() |
2251 | 1483 | 1921 | ||
2252 | 1484 | def about(self, widget): | 1922 | def about(self, widget): |
2253 | 1923 | """ Menu callback to open About dialog """ | ||
2254 | 1485 | log.debug("Indicator: open About dialog") | 1924 | log.debug("Indicator: open About dialog") |
2256 | 1486 | self.aboutdialog = gtk.AboutDialog() | 1925 | self.aboutdialog = Gtk.AboutDialog() |
2257 | 1487 | self.aboutdialog.set_name(_("Weather Indicator")) | 1926 | self.aboutdialog.set_name(_("Weather Indicator")) |
2258 | 1488 | self.aboutdialog.set_version(VERSION) | 1927 | self.aboutdialog.set_version(VERSION) |
2259 | 1489 | 1928 | ||
2261 | 1490 | ifile = open(os.path.join(PROJECT_ROOT_DIRECTORY, "share/doc/indicator-weather/AUTHORS"), "r") | 1929 | ifile = open(os.path.join(PROJECT_ROOT_DIRECTORY, |
2262 | 1930 | "share/doc/indicator-weather/AUTHORS"), "r") | ||
2263 | 1491 | self.aboutdialog.set_copyright(ifile.read().replace('\x0c', '')) | 1931 | self.aboutdialog.set_copyright(ifile.read().replace('\x0c', '')) |
2264 | 1492 | ifile.close() | 1932 | ifile.close() |
2265 | 1493 | 1933 | ||
2267 | 1494 | ifile = open(os.path.join(PROJECT_ROOT_DIRECTORY, "share/common-licenses/GPL-3"), "r") | 1934 | ifile = open(os.path.join(PROJECT_ROOT_DIRECTORY, |
2268 | 1935 | "share/common-licenses/GPL-3"), "r") | ||
2269 | 1495 | self.aboutdialog.set_license(ifile.read().replace('\x0c', '')) | 1936 | self.aboutdialog.set_license(ifile.read().replace('\x0c', '')) |
2270 | 1496 | ifile.close() | 1937 | ifile.close() |
2271 | 1497 | 1938 | ||
2272 | 1498 | self.aboutdialog.set_website("https://launchpad.net/weather-indicator") | 1939 | self.aboutdialog.set_website("https://launchpad.net/weather-indicator") |
2273 | 1499 | self.aboutdialog.set_translator_credits(_("translator-credits")) | 1940 | self.aboutdialog.set_translator_credits(_("translator-credits")) |
2277 | 1500 | logo_path = os.path.join(PROJECT_ROOT_DIRECTORY, "share/indicator-weather/media/icon.png") | 1941 | logo_path = os.path.join(PROJECT_ROOT_DIRECTORY, |
2278 | 1501 | self.aboutdialog.set_logo(gtk.gdk.pixbuf_new_from_file(logo_path)) | 1942 | "share/indicator-weather/media/icon.png") |
2279 | 1502 | 1943 | self.aboutdialog.set_logo(GdkPixbuf.Pixbuf.new_from_file(logo_path)) | |
2280 | 1503 | 1944 | ||
2281 | 1504 | self.aboutdialog.connect("response", self.about_close) | 1945 | self.aboutdialog.connect("response", self.about_close) |
2282 | 1505 | self.aboutdialog.show() | 1946 | self.aboutdialog.show() |
2283 | 1506 | 1947 | ||
2284 | 1507 | def about_close(self, widget, event=None): | 1948 | def about_close(self, widget, event=None): |
2285 | 1949 | """ Menu callback to close About dialog """ | ||
2286 | 1508 | log.debug("Indicator: closing About dialog") | 1950 | log.debug("Indicator: closing About dialog") |
2287 | 1509 | self.aboutdialog.destroy() | 1951 | self.aboutdialog.destroy() |
2288 | 1510 | 1952 | ||
2289 | 1511 | # Open Extended forecast window | ||
2290 | 1512 | def extforecast(self, widget): | 1953 | def extforecast(self, widget): |
2291 | 1954 | """ Menu callback to open Extended forecast window """ | ||
2292 | 1513 | log.debug("Indicator: open Forecast") | 1955 | log.debug("Indicator: open Forecast") |
2296 | 1514 | if ((not hasattr(self, 'forecastwd')) or (not self.forecastwd.get_visible())): | 1956 | if ((not hasattr(self, 'forecastwd')) or \ |
2297 | 1515 | self.forecastwd = ExtendedForecast() | 1957 | (not self.forecastwd.get_visible())): |
2298 | 1516 | self.forecastwd.show() | 1958 | self.forecastwd = ExtendedForecast() |
2299 | 1959 | self.forecastwd.show() | ||
2300 | 1517 | 1960 | ||
2301 | 1518 | # Quit the applet | ||
2302 | 1519 | def quit(self, widget, data=None): | 1961 | def quit(self, widget, data=None): |
2303 | 1962 | """ Menu callback to quit the indicator applet """ | ||
2304 | 1520 | log.debug("Indicator: Quitting") | 1963 | log.debug("Indicator: Quitting") |
2306 | 1521 | gtk.main_quit() | 1964 | Gtk.main_quit() |
2307 | 1522 | 1965 | ||
2309 | 1523 | class PreferencesDialog(gtk.Dialog): | 1966 | class PreferencesDialog(Gtk.Dialog): |
2310 | 1524 | """ Class for preferences dialog """ | 1967 | """ Class for preferences dialog """ |
2311 | 1525 | __gtype_name__ = "PreferencesDialog" | 1968 | __gtype_name__ = "PreferencesDialog" |
2312 | 1526 | 1969 | ||
2313 | 1527 | # Creating a new preferences dialog | ||
2314 | 1528 | def __new__(cls): | 1970 | def __new__(cls): |
2315 | 1971 | """ Creating a new preferences dialog """ | ||
2316 | 1529 | log.debug("Preferences: creating") | 1972 | log.debug("Preferences: creating") |
2317 | 1530 | builder = get_builder('PreferencesDialog') | 1973 | builder = get_builder('PreferencesDialog') |
2318 | 1531 | new_object = builder.get_object("preferences_dialog") | 1974 | new_object = builder.get_object("preferences_dialog") |
2319 | 1532 | new_object.finish_initializing(builder) | 1975 | new_object.finish_initializing(builder) |
2320 | 1533 | return new_object | 1976 | return new_object |
2321 | 1534 | 1977 | ||
2322 | 1535 | # Fill in preferences dialog with currect data | ||
2323 | 1536 | def finish_initializing(self, builder): | 1978 | def finish_initializing(self, builder): |
2324 | 1979 | """ Fill in preferences dialog with correct data """ | ||
2325 | 1537 | log.debug("Preferences: finishing initialization") | 1980 | log.debug("Preferences: finishing initialization") |
2328 | 1538 | log.debug("Preferences: got settings: unit=%s, notif=%s, wind=%s, rate=%s, source=%s" % | 1981 | log.debug("Preferences: got settings: unit=%s, notif=%s, wind=%s, " |
2329 | 1539 | (wi.unit, wi.notif, wi.wind, wi.rate, wi.source)) | 1982 | "rate=%s, source=%s, heat=%s, chill=%s" % |
2330 | 1983 | (wi.unit, wi.notif, wi.wind, wi.rate, wi.source, | ||
2331 | 1984 | wi.heat, wi.chill)) | ||
2332 | 1540 | self.builder = builder | 1985 | self.builder = builder |
2333 | 1541 | 1986 | ||
2334 | 1542 | # Set correct wind_unit using dictionary of wind value and object name | 1987 | # Set correct wind_unit using dictionary of wind value and object name |
2335 | @@ -1547,11 +1992,16 @@ | |||
2336 | 1547 | self.builder.get_object('show_label').set_active(wi.show_label) | 1992 | self.builder.get_object('show_label').set_active(wi.show_label) |
2337 | 1548 | self.builder.get_object('show_label').set_visible(hasattr(wi.winder, 'set_label')) | 1993 | self.builder.get_object('show_label').set_visible(hasattr(wi.winder, 'set_label')) |
2338 | 1549 | self.builder.get_object('rate').set_value(float(wi.rate)) | 1994 | self.builder.get_object('rate').set_value(float(wi.rate)) |
2339 | 1995 | self.builder.get_object(wi.heat_estimates[wi.heat][0]).set_active(True) | ||
2340 | 1996 | self.builder.get_object(wi.chill_estimates[wi.chill][0]).set_active(True) | ||
2341 | 1997 | self.builder.get_object('show_relative').set_active(wi.show_relative) | ||
2342 | 1998 | self.builder.get_object('show_wind').set_active(wi.show_wind) | ||
2343 | 1999 | self.builder.get_object('show_suntimes').set_active(wi.show_suntimes) | ||
2344 | 1550 | 2000 | ||
2345 | 1551 | log.debug("Preferences: Loading places") | 2001 | log.debug("Preferences: Loading places") |
2346 | 1552 | if wi.places != None: | 2002 | if wi.places != None: |
2347 | 1553 | for place in wi.places: | 2003 | for place in wi.places: |
2349 | 1554 | if len(place)>1: | 2004 | if len(place)>1 and place[0] is not None: |
2350 | 1555 | log.debug("Preferences: Places: got (%s, %s)" % (place[1], place[0])) | 2005 | log.debug("Preferences: Places: got (%s, %s)" % (place[1], place[0])) |
2351 | 1556 | newplace = list() | 2006 | newplace = list() |
2352 | 1557 | newplace.append(place[1]) | 2007 | newplace.append(place[1]) |
2353 | @@ -1563,32 +2013,45 @@ | |||
2354 | 1563 | 2013 | ||
2355 | 1564 | self.builder.connect_signals(self) | 2014 | self.builder.connect_signals(self) |
2356 | 1565 | 2015 | ||
2357 | 1566 | # 'Remove' clicked - remove location from list | ||
2358 | 1567 | #TODO: Update settings object | ||
2359 | 1568 | def on_remove_location(self, widget): | 2016 | def on_remove_location(self, widget): |
2360 | 2017 | """ 'Remove' clicked - remove location from list """ | ||
2361 | 1569 | selection = self.builder.get_object('location_list').get_selection() | 2018 | selection = self.builder.get_object('location_list').get_selection() |
2362 | 1570 | model, iter = selection.get_selected() | 2019 | model, iter = selection.get_selected() |
2363 | 1571 | if iter != None: | 2020 | if iter != None: |
2365 | 1572 | log.debug("Preferences: Removing location %s (code %s)" % (model[iter][0], model[iter][1])) | 2021 | log.debug("Preferences: Removing location %s (code %s)" % |
2366 | 2022 | (model[iter][0], model[iter][1])) | ||
2367 | 2023 | newplaces = [] | ||
2368 | 2024 | for place in wi.places: | ||
2369 | 2025 | if place[1] != model[iter][0] and \ | ||
2370 | 2026 | place[0] != model[iter][1]: | ||
2371 | 2027 | newplaces.append(place) | ||
2372 | 2028 | if newplaces != wi.places: | ||
2373 | 2029 | wi.places = newplaces | ||
2374 | 2030 | log.debug("Preferences: update settings object") | ||
2375 | 2031 | wi.settings.set_value("places", str(wi.places)) | ||
2376 | 2032 | |||
2377 | 1573 | model.remove(iter) | 2033 | model.remove(iter) |
2379 | 1574 | 2034 | wi.places_changed = True | |
2380 | 2035 | |||
2381 | 1575 | if (self.builder.get_object('citieslist').get_iter_first() == None): | 2036 | if (self.builder.get_object('citieslist').get_iter_first() == None): |
2382 | 1576 | self.builder.get_object('ok_button').set_sensitive(False) | 2037 | self.builder.get_object('ok_button').set_sensitive(False) |
2385 | 1577 | 2038 | ||
2384 | 1578 | # 'Add' clicked - create a new Assistant | ||
2386 | 1579 | def on_add_location(self, widget): | 2039 | def on_add_location(self, widget): |
2387 | 2040 | """ 'Add' clicked - create a new Assistant """ | ||
2388 | 1580 | log.debug("Preferences: Add location clicked") | 2041 | log.debug("Preferences: Add location clicked") |
2389 | 1581 | if ((not hasattr(self, 'assistant')) or (not self.assistant.get_visible())): | 2042 | if ((not hasattr(self, 'assistant')) or (not self.assistant.get_visible())): |
2390 | 1582 | self.assistant = Assistant() | 2043 | self.assistant = Assistant() |
2391 | 1583 | self.assistant.show() | 2044 | self.assistant.show() |
2392 | 1584 | 2045 | ||
2393 | 1585 | # 'OK' clicked - save settings | ||
2394 | 1586 | def ok(self, widget, data=None): | 2046 | def ok(self, widget, data=None): |
2395 | 2047 | """ 'OK' clicked - save settings """ | ||
2396 | 2048 | #TODO: rewrite this - for better response to user clicks, | ||
2397 | 2049 | # it should first copy values to a queue, then destroy the window | ||
2398 | 1587 | log.debug("Preferences: Saving settings") | 2050 | log.debug("Preferences: Saving settings") |
2399 | 1588 | need_to_update_weather = False | 2051 | need_to_update_weather = False |
2400 | 1589 | need_to_update_indicator = False | 2052 | need_to_update_indicator = False |
2401 | 1590 | 2053 | ||
2403 | 1591 | #Show label near icon | 2054 | # Show label near icon |
2404 | 1592 | new_show_label = self.builder.get_object('show_label').get_active() | 2055 | new_show_label = self.builder.get_object('show_label').get_active() |
2405 | 1593 | if (wi.show_label != new_show_label): | 2056 | if (wi.show_label != new_show_label): |
2406 | 1594 | wi.show_label = new_show_label | 2057 | wi.show_label = new_show_label |
2407 | @@ -1597,6 +2060,30 @@ | |||
2408 | 1597 | need_to_update_indicator = True | 2060 | need_to_update_indicator = True |
2409 | 1598 | log.debug("Preferences: Show Label changed to '%s'" % wi.show_label) | 2061 | log.debug("Preferences: Show Label changed to '%s'" % wi.show_label) |
2410 | 1599 | 2062 | ||
2411 | 2063 | # Show relative temperature | ||
2412 | 2064 | new_show_relative = self.builder.get_object('show_relative').get_active() | ||
2413 | 2065 | if (wi.show_relative != new_show_relative): | ||
2414 | 2066 | wi.show_relative = new_show_relative | ||
2415 | 2067 | wi.settings.set_value("show_relative", new_show_relative) | ||
2416 | 2068 | need_to_update_weather = True | ||
2417 | 2069 | log.debug("PreferencesDialog: Show Relative Temp changed to %s" % wi.show_relative) | ||
2418 | 2070 | |||
2419 | 2071 | # Show wind speed & direction | ||
2420 | 2072 | new_show_wind = self.builder.get_object('show_wind').get_active() | ||
2421 | 2073 | if (wi.show_wind != new_show_wind): | ||
2422 | 2074 | wi.show_wind = new_show_wind | ||
2423 | 2075 | wi.settings.set_value("show_relative", new_show_wind) | ||
2424 | 2076 | need_to_update_weather = True | ||
2425 | 2077 | log.debug("PreferencesDialog: Show Wind Data changed to %s" % wi.show_wind) | ||
2426 | 2078 | |||
2427 | 2079 | # Show sunrise & sunset times | ||
2428 | 2080 | new_show_suntimes = self.builder.get_object('show_suntimes').get_active() | ||
2429 | 2081 | if (wi.show_suntimes != new_show_suntimes): | ||
2430 | 2082 | wi.show_suntimes = new_show_suntimes | ||
2431 | 2083 | wi.settings.set_value("show_suntimes", new_show_suntimes) | ||
2432 | 2084 | need_to_update_weather = True | ||
2433 | 2085 | log.debug("PreferencesDialog: Show Sunrise/Sunset Times changed to %s" % wi.show_suntimes) | ||
2434 | 2086 | |||
2435 | 1600 | # Metric systems | 2087 | # Metric systems |
2436 | 1601 | for k in wi.metric_systems.keys(): | 2088 | for k in wi.metric_systems.keys(): |
2437 | 1602 | if self.builder.get_object(wi.metric_systems[k][0]).get_active(): | 2089 | if self.builder.get_object(wi.metric_systems[k][0]).get_active(): |
2438 | @@ -1634,6 +2121,32 @@ | |||
2439 | 1634 | need_to_update_weather = True | 2121 | need_to_update_weather = True |
2440 | 1635 | log.debug("Preferences: Wind Unit changed to '%s'" % wi.wind) | 2122 | log.debug("Preferences: Wind Unit changed to '%s'" % wi.wind) |
2441 | 1636 | 2123 | ||
2442 | 2124 | # Heat estimate formula | ||
2443 | 2125 | for k in wi.heat_estimates.keys(): | ||
2444 | 2126 | if self.builder.get_object(wi.heat_estimates[k][0]).get_active(): | ||
2445 | 2127 | new_heat_index = k | ||
2446 | 2128 | new_heat_estimate = wi.heat_estimates[k][1] | ||
2447 | 2129 | |||
2448 | 2130 | if (wi.heat != new_heat_index): | ||
2449 | 2131 | wi.heat = new_heat_index | ||
2450 | 2132 | wi.heat_index = new_heat_estimate | ||
2451 | 2133 | wi.settings.set_value("heat", wi.heat) | ||
2452 | 2134 | need_to_update_weather = True | ||
2453 | 2135 | log.debug("Preferences: Heat Estimate changed to '%s'" % wi.heat) | ||
2454 | 2136 | |||
2455 | 2137 | # Chill estimate formula | ||
2456 | 2138 | for k in wi.chill_estimates.keys(): | ||
2457 | 2139 | if self.builder.get_object(wi.chill_estimates[k][0]).get_active(): | ||
2458 | 2140 | new_chill_index = k | ||
2459 | 2141 | new_chill_estimate = wi.chill_estimates[k][1] | ||
2460 | 2142 | |||
2461 | 2143 | if (wi.chill != new_chill_index): | ||
2462 | 2144 | wi.chill = new_chill_index | ||
2463 | 2145 | wi.chill_index = new_chill_estimate | ||
2464 | 2146 | wi.settings.set_value("chill", wi.chill) | ||
2465 | 2147 | need_to_update_weather = True | ||
2466 | 2148 | log.debug("Preferences: Chill Estimate changed to '%s'" % wi.chill) | ||
2467 | 2149 | |||
2468 | 1637 | # Weather source | 2150 | # Weather source |
2469 | 1638 | for k in wi.weather_sources.keys(): | 2151 | for k in wi.weather_sources.keys(): |
2470 | 1639 | if self.builder.get_object(wi.weather_sources[k][0]).get_active(): | 2152 | if self.builder.get_object(wi.weather_sources[k][0]).get_active(): |
2471 | @@ -1655,18 +2168,19 @@ | |||
2472 | 1655 | wi.schedule_weather_update() | 2168 | wi.schedule_weather_update() |
2473 | 1656 | 2169 | ||
2474 | 1657 | # Get places from location list | 2170 | # Get places from location list |
2483 | 1658 | newplaces = list() | 2171 | ## newplaces = list() |
2484 | 1659 | item = self.builder.get_object('citieslist').get_iter_first() | 2172 | ## item = self.builder.get_object('citieslist').get_iter_first() |
2485 | 1660 | while (item != None): | 2173 | ## while (item != None): |
2486 | 1661 | newplace = list() | 2174 | ## newplace = list() |
2487 | 1662 | newplace.append(self.builder.get_object('citieslist').get_value (item, 1)) | 2175 | ## newplace.append(self.builder.get_object('citieslist').get_value (item, 1)) |
2488 | 1663 | newplace.append(self.builder.get_object('citieslist').get_value (item, 0)) | 2176 | ## newplace.append(self.builder.get_object('citieslist').get_value (item, 0)) |
2489 | 1664 | newplaces.append(newplace) | 2177 | ## newplaces.append(newplace) |
2490 | 1665 | item = self.builder.get_object('citieslist').iter_next(item) | 2178 | ## item = self.builder.get_object('citieslist').iter_next(item) |
2491 | 1666 | 2179 | ||
2492 | 1667 | # If places have changed - update weather data | 2180 | # If places have changed - update weather data |
2495 | 1668 | if newplaces != wi.places: | 2181 | ## if newplaces != wi.places: |
2496 | 1669 | wi.places = newplaces | 2182 | ## wi.places = newplaces |
2497 | 2183 | if wi.places_changed: | ||
2498 | 1670 | log.debug("Preferences: Places changed to '%s'" % str(wi.places)) | 2184 | log.debug("Preferences: Places changed to '%s'" % str(wi.places)) |
2499 | 1671 | wi.settings.set_value("places", str(wi.places)) | 2185 | wi.settings.set_value("places", str(wi.places)) |
2500 | 1672 | if (type(wi.place) != None) and (wi.place in wi.places): | 2186 | if (type(wi.place) != None) and (wi.place in wi.places): |
2501 | @@ -1677,60 +2191,68 @@ | |||
2502 | 1677 | log.debug("Preferences: Place Chosen changed to '%s'" % wi.placechosen) | 2191 | log.debug("Preferences: Place Chosen changed to '%s'" % wi.placechosen) |
2503 | 1678 | wi.settings.set_value("placechosen", wi.placechosen) | 2192 | wi.settings.set_value("placechosen", wi.placechosen) |
2504 | 1679 | wi.location_details = eval(wi.settings.get_location_details(wi.place[0])) | 2193 | wi.location_details = eval(wi.settings.get_location_details(wi.place[0])) |
2507 | 1680 | wi.menu_normal() | 2194 | ## wi.menu_normal() |
2508 | 1681 | wi.set_refresh_label() | 2195 | ## wi.set_refresh_label() |
2509 | 1682 | need_to_update_weather = True | 2196 | need_to_update_weather = True |
2510 | 2197 | wi.places_changed = False | ||
2511 | 1683 | 2198 | ||
2512 | 1684 | if need_to_update_weather: | 2199 | if need_to_update_weather: |
2514 | 1685 | wi.update_weather(False) | 2200 | #### wi.update_weather(False) |
2515 | 2201 | wi.schedule_weather_update(0.003) | ||
2516 | 1686 | 2202 | ||
2517 | 1687 | if need_to_update_indicator: | 2203 | if need_to_update_indicator: |
2518 | 1688 | wi.update_label(wi.previous_label_value) | 2204 | wi.update_label(wi.previous_label_value) |
2519 | 1689 | 2205 | ||
2520 | 1690 | self.destroy() | 2206 | self.destroy() |
2521 | 1691 | 2207 | ||
2522 | 1692 | # 'Cancel' click - forget all changes | ||
2523 | 1693 | def cancel(self, widget, data=None): | 2208 | def cancel(self, widget, data=None): |
2524 | 2209 | """ 'Cancel' clicked - forget all changes """ | ||
2525 | 1694 | log.debug("Preferences: Cancelling") | 2210 | log.debug("Preferences: Cancelling") |
2526 | 1695 | self.destroy() | 2211 | self.destroy() |
2527 | 1696 | 2212 | ||
2529 | 1697 | class ExtendedForecast(gtk.Window): | 2213 | class ExtendedForecast(Gtk.Window): |
2530 | 1698 | """ Class for forecast window """ | 2214 | """ Class for forecast window """ |
2531 | 1699 | __gtype_name__ = "ExtendedForecast" | 2215 | __gtype_name__ = "ExtendedForecast" |
2532 | 1700 | 2216 | ||
2533 | 1701 | # Create forecast | ||
2534 | 1702 | def __new__(cls): | 2217 | def __new__(cls): |
2535 | 2218 | """ Create forecast """ | ||
2536 | 1703 | log.debug("ExtendedForecast: creating") | 2219 | log.debug("ExtendedForecast: creating") |
2537 | 1704 | builder = get_builder('ExtendedForecast') | 2220 | builder = get_builder('ExtendedForecast') |
2538 | 1705 | new_object = builder.get_object("extended_forecast") | 2221 | new_object = builder.get_object("extended_forecast") |
2539 | 1706 | new_object.finish_initializing(builder) | 2222 | new_object.finish_initializing(builder) |
2540 | 1707 | return new_object | 2223 | return new_object |
2541 | 1708 | 2224 | ||
2542 | 1709 | # Fill in forecast parameters | ||
2543 | 1710 | def finish_initializing(self, builder): | 2225 | def finish_initializing(self, builder): |
2544 | 2226 | """ Fill in forecast parameters """ | ||
2545 | 1711 | log.debug("ExtendedForecast: finishing initialization") | 2227 | log.debug("ExtendedForecast: finishing initialization") |
2546 | 1712 | self.builder = builder | 2228 | self.builder = builder |
2547 | 1713 | self.builder.connect_signals(self) | 2229 | self.builder.connect_signals(self) |
2548 | 1714 | 2230 | ||
2549 | 1715 | # Get forecast data using Forecast object | 2231 | # Get forecast data using Forecast object |
2552 | 1716 | log.debug("ExtendedForecast: chosen place: %s (code %s)" % (wi.places[wi.placechosen][1], wi.places[wi.placechosen][0])) | 2232 | log.debug("ExtendedForecast: chosen place: %s (code %s)" % |
2553 | 1717 | self.builder.get_object('extended_forecast').set_title("%s %s" % (_('Weather Forecast for '), wi.places[wi.placechosen][1])) | 2233 | (wi.places[wi.placechosen][1], wi.places[wi.placechosen][0])) |
2554 | 2234 | self.builder.get_object('extended_forecast').set_title("%s %s" % | ||
2555 | 2235 | (_('Weather Forecast for'), wi.places[wi.placechosen][1])) | ||
2556 | 1718 | log.debug("ExtendedForecast: getting forecast data") | 2236 | log.debug("ExtendedForecast: getting forecast data") |
2558 | 1719 | forecast = Forecast(wi.metric_system, wi.current_location.location_details['latitude'], wi.current_location.location_details['longitude'], locale_name) | 2237 | forecast = Forecast(wi.metric_system, |
2559 | 2238 | wi.current_location.location_details['yahoo id'], | ||
2560 | 2239 | locale_name) | ||
2561 | 1720 | forecast.prepare_forecast_data() | 2240 | forecast.prepare_forecast_data() |
2562 | 1721 | if forecast.error_message != None: | 2241 | if forecast.error_message != None: |
2563 | 1722 | #Error occurred while getting forecast data | 2242 | #Error occurred while getting forecast data |
2565 | 1723 | self.builder.get_object('connection_error').set_text("%s" % forecast.error_message) | 2243 | self.builder.get_object('connection_error').set_text("%s" % |
2566 | 2244 | forecast.error_message) | ||
2567 | 1724 | self.builder.get_object('connection_error').set_visible(True) | 2245 | self.builder.get_object('connection_error').set_visible(True) |
2568 | 1725 | self.builder.get_object('hbox1').set_visible(False) | 2246 | self.builder.get_object('hbox1').set_visible(False) |
2569 | 1726 | else: | 2247 | else: |
2570 | 1727 | daysofweek = forecast.get_forecast_daysofweek() | 2248 | daysofweek = forecast.get_forecast_daysofweek() |
2571 | 1728 | forecast_data = forecast.get_forecast_data() | 2249 | forecast_data = forecast.get_forecast_data() |
2572 | 1729 | if forecast_data == None: | 2250 | if forecast_data == None: |
2577 | 1730 | # Forecast data unavailable - hide elements and show 'connection_error' label | 2251 | # Forecast data unavailable - hide elements |
2578 | 1731 | self.builder.get_object('connection_error').set_visible(True); | 2252 | # and show 'connection_error' label |
2579 | 1732 | self.builder.get_object('hbox1').set_visible(False); | 2253 | self.builder.get_object('connection_error').set_visible(True) |
2580 | 1733 | self.builder.get_object('hseparator1').set_visible(False); | 2254 | self.builder.get_object('hbox1').set_visible(False) |
2581 | 2255 | self.builder.get_object('hseparator1').set_visible(False) | ||
2582 | 1734 | return | 2256 | return |
2583 | 1735 | (highdata, lowdata) = forecast_data | 2257 | (highdata, lowdata) = forecast_data |
2584 | 1736 | icons = forecast.get_forecast_icons() | 2258 | icons = forecast.get_forecast_icons() |
2585 | @@ -1738,68 +2260,81 @@ | |||
2586 | 1738 | 2260 | ||
2587 | 1739 | log.debug("ExtendedForecast: parsing forecast data") | 2261 | log.debug("ExtendedForecast: parsing forecast data") |
2588 | 1740 | # Create labels for each weekday | 2262 | # Create labels for each weekday |
2594 | 1741 | self.builder.get_object('day1lbl').set_label('<big>%s</big>' % daysofweek[0].capitalize()) | 2263 | for i in xrange(1,5): |
2595 | 1742 | self.builder.get_object('day2lbl').set_label('<big>%s</big>' % daysofweek[1].capitalize()) | 2264 | try: |
2596 | 1743 | self.builder.get_object('day3lbl').set_label('<big>%s</big>' % daysofweek[2].capitalize()) | 2265 | lbl_name = 'day%slbl' % (i) |
2597 | 1744 | self.builder.get_object('day4lbl').set_label('<big>%s</big>' % daysofweek[3].capitalize()) | 2266 | self.builder.get_object(lbl_name).set_label('<big>%s</big>' % |
2598 | 1745 | 2267 | daysofweek[i].capitalize()) | |
2599 | 2268 | except IndexError: | ||
2600 | 2269 | log.error("ExtendedForecast: Yahoo didn't return " | ||
2601 | 2270 | "forecast for %s days" % i) | ||
2602 | 2271 | log.error(forecast.forecast) | ||
2603 | 2272 | |||
2604 | 1746 | # Fill in icons | 2273 | # Fill in icons |
2605 | 1747 | for i in xrange(1,5): | 2274 | for i in xrange(1,5): |
2607 | 1748 | # Get icon name from dictionary in Weather object for Google icons | 2275 | # Get icon name from dictionary in Weather object |
2608 | 2276 | # for Yahoo condition codes | ||
2609 | 1749 | try: | 2277 | try: |
2611 | 1750 | conds = Weather._GoogleConditions.get(icons[i-1]) | 2278 | conds = Weather._YahooConditions.get(icons[i]) |
2612 | 1751 | if conds != None: | 2279 | if conds != None: |
2614 | 1752 | google_icon = conds[0] | 2280 | yahoo_icon = conds[0] |
2615 | 1753 | else: | 2281 | else: |
2617 | 1754 | log.error("ExtendedForecast: unknown Google weather condition '%s'" % icons[i-1]) | 2282 | log.error("ExtendedForecast: unknown Yahoo weather " |
2618 | 2283 | "condition code '%s'" % icons[i]) | ||
2619 | 1755 | log.error(forecast.forecast) | 2284 | log.error(forecast.forecast) |
2622 | 1756 | google_icon = 'weather-indicator-unknown' | 2285 | yahoo_icon = 'weather-indicator-unknown' |
2623 | 1757 | self.builder.get_object('day%simage' % str(i)).set_from_icon_name(google_icon,gtk.ICON_SIZE_BUTTON) | 2286 | self.builder.get_object('day%simage' % |
2624 | 2287 | str(i)).set_from_icon_name(yahoo_icon, | ||
2625 | 2288 | Gtk.IconSize.BUTTON) | ||
2626 | 1758 | except IndexError: | 2289 | except IndexError: |
2629 | 1759 | log.error("ExtendedForecast: Google didn't return condition for %s days" % i-1) | 2290 | log.error("ExtendedForecast: Yahoo didn't return " |
2630 | 1760 | log.error(forecast.forecast) | 2291 | "condition for %s days" % i) |
2631 | 2292 | log.error(forecast.forecast) | ||
2632 | 1761 | 2293 | ||
2633 | 1762 | # Fill in condition labels | 2294 | # Fill in condition labels |
2634 | 1763 | for i in xrange(1,5): | 2295 | for i in xrange(1,5): |
2637 | 1764 | if conditions[i-1] != '': | 2296 | if conditions[i] != '': |
2638 | 1765 | condition = conditions[i-1] | 2297 | condition = conditions[i] |
2639 | 1766 | else: | 2298 | else: |
2640 | 1767 | condition = _("Unknown condition") | 2299 | condition = _("Unknown condition") |
2642 | 1768 | self.builder.get_object('day%scond' % str(i)).set_label(condition) | 2300 | self.builder.get_object('day%scond' % |
2643 | 2301 | str(i)).set_label(condition) | ||
2644 | 1769 | 2302 | ||
2645 | 1770 | # Fill in High and Low temperatures | 2303 | # Fill in High and Low temperatures |
2648 | 1771 | if wi.metric_system == MetricSystem.SI: | 2304 | if wi.metric_system == UnitSystem.SI: |
2649 | 1772 | tempunit = '°C' | 2305 | tempunit = u"°C" |
2650 | 1773 | else: | 2306 | else: |
2652 | 1774 | tempunit = '°F' | 2307 | tempunit = u"°F" |
2653 | 1775 | for i in xrange(1,5): | 2308 | for i in xrange(1,5): |
2658 | 1776 | label = "%s: %s%s" % (_('High'), highdata[i-1],tempunit) | 2309 | label = "%s: %s%s" % (_('High'), highdata[i],tempunit) |
2659 | 1777 | self.builder.get_object('day%stemphigh' % str(i)).set_label(label) | 2310 | self.builder.get_object('day%stemphigh' % |
2660 | 1778 | label = "%s: %s%s" % (_('Low'), lowdata[i-1],tempunit) | 2311 | str(i)).set_label(label) |
2661 | 1779 | self.builder.get_object('day%stemplow' % str(i)).set_label(label) | 2312 | label = "%s: %s%s" % (_('Low'), lowdata[i],tempunit) |
2662 | 2313 | self.builder.get_object('day%stemplow' % | ||
2663 | 2314 | str(i)).set_label(label) | ||
2664 | 1780 | 2315 | ||
2665 | 1781 | # Closing forecast window | ||
2666 | 1782 | def close(self, widget, data=None): | 2316 | def close(self, widget, data=None): |
2667 | 2317 | """ 'Close' clicked - close forecast window """ | ||
2668 | 1783 | log.debug("ExtendedForecast: closing window") | 2318 | log.debug("ExtendedForecast: closing window") |
2669 | 1784 | self.destroy() | 2319 | self.destroy() |
2670 | 1785 | 2320 | ||
2671 | 1786 | def on_destroy(self, widget): | 2321 | def on_destroy(self, widget): |
2672 | 1787 | pass | 2322 | pass |
2673 | 1788 | 2323 | ||
2675 | 1789 | class Assistant(gtk.Assistant): | 2324 | class Assistant(Gtk.Assistant): |
2676 | 1790 | """ Class for a wizard, which helps to add a new location in location list """ | 2325 | """ Class for a wizard, which helps to add a new location in location list """ |
2677 | 1791 | __gtype_name__ = "Assistant" | 2326 | __gtype_name__ = "Assistant" |
2678 | 1792 | 2327 | ||
2679 | 1793 | # Create new object | ||
2680 | 1794 | def __new__(cls): | 2328 | def __new__(cls): |
2681 | 2329 | """ Create new object """ | ||
2682 | 1795 | log.debug("Assistant: creating new Assistance instance") | 2330 | log.debug("Assistant: creating new Assistance instance") |
2683 | 1796 | builder = get_builder('Assistant') | 2331 | builder = get_builder('Assistant') |
2684 | 1797 | new_object = builder.get_object("assistant") | 2332 | new_object = builder.get_object("assistant") |
2685 | 1798 | new_object.finish_initializing(builder) | 2333 | new_object.finish_initializing(builder) |
2686 | 1799 | return new_object | 2334 | return new_object |
2687 | 1800 | 2335 | ||
2688 | 1801 | # Finish UI initialization - prepare combobox | ||
2689 | 1802 | def finish_initializing(self, builder): | 2336 | def finish_initializing(self, builder): |
2690 | 2337 | """ Finish UI initialization - prepare combobox """ | ||
2691 | 1803 | log.debug("Assistant: finishing initialization") | 2338 | log.debug("Assistant: finishing initialization") |
2692 | 1804 | self.builder = builder | 2339 | self.builder = builder |
2693 | 1805 | self.builder.connect_signals(self) | 2340 | self.builder.connect_signals(self) |
2694 | @@ -1809,18 +2344,18 @@ | |||
2695 | 1809 | 2344 | ||
2696 | 1810 | # Set up combobox | 2345 | # Set up combobox |
2697 | 1811 | log.debug("Assistant: setting up location combobox") | 2346 | log.debug("Assistant: setting up location combobox") |
2699 | 1812 | self.store = gtk.ListStore(str, str, str, str, str) | 2347 | self.store = Gtk.ListStore(str, str, str, str, str) |
2700 | 1813 | self.location_input_combo = self.builder.get_object("combolocations") | 2348 | self.location_input_combo = self.builder.get_object("combolocations") |
2701 | 1814 | self.location_input_combo.set_model(self.store) | 2349 | self.location_input_combo.set_model(self.store) |
2703 | 1815 | self.location_input_combo.set_text_column(0) | 2350 | self.location_input_combo.set_entry_text_column(0) |
2704 | 1816 | self.location_entry = self.builder.get_object("entrylocation") | 2351 | self.location_entry = self.builder.get_object("entrylocation") |
2705 | 1817 | self.place_selected = None | 2352 | self.place_selected = None |
2706 | 1818 | self.location = None | 2353 | self.location = None |
2707 | 1819 | 2354 | ||
2709 | 1820 | self.assistant.set_forward_page_func(self.next_page) | 2355 | self.assistant.set_forward_page_func(self.next_page, None) |
2710 | 1821 | 2356 | ||
2711 | 1822 | # 'Get cities' button clicked - get suggested cities list | ||
2712 | 1823 | def on_get_city_names(self, widget): | 2357 | def on_get_city_names(self, widget): |
2713 | 2358 | """ 'Get cities' button clicked - get suggested cities list """ | ||
2714 | 1824 | new_text = self.location_entry.get_text() | 2359 | new_text = self.location_entry.get_text() |
2715 | 1825 | log.debug("Assistant: looking for location '%s'" % new_text) | 2360 | log.debug("Assistant: looking for location '%s'" % new_text) |
2716 | 1826 | try: | 2361 | try: |
2717 | @@ -1833,18 +2368,26 @@ | |||
2718 | 1833 | for city in cities['geonames']: | 2368 | for city in cities['geonames']: |
2719 | 1834 | # Create a full city name, consisting of city name, administrative areas names and country name | 2369 | # Create a full city name, consisting of city name, administrative areas names and country name |
2720 | 1835 | if 'adminName2' in city: | 2370 | if 'adminName2' in city: |
2722 | 1836 | displayed_city_name = "%s, %s, %s, %s" % (city['name'], city['adminName1'], city['adminName1'], city['countryName']) | 2371 | displayed_city_name = "%s, %s, %s, %s" % ( |
2723 | 2372 | city['name'], city['adminName1'], | ||
2724 | 2373 | city['adminName1'], city['countryName'] | ||
2725 | 2374 | ) | ||
2726 | 1837 | elif 'adminName1' in city: | 2375 | elif 'adminName1' in city: |
2728 | 1838 | displayed_city_name = "%s, %s, %s" % (city['name'], city['adminName1'], city['countryName']) | 2376 | displayed_city_name = "%s, %s, %s" % ( |
2729 | 2377 | city['name'], city['adminName1'], city['countryName'] | ||
2730 | 2378 | ) | ||
2731 | 1839 | else: | 2379 | else: |
2734 | 1840 | displayed_city_name = "%s, %s" % (city['name'], city['countryName']) | 2380 | displayed_city_name = "%s, %s" % (city['name'], |
2735 | 1841 | self.store.append([displayed_city_name, str(city['geonameId']), str(city['lat']), str(city['lng']), str(city['name'])]) | 2381 | city['countryName']) |
2736 | 2382 | self.store.append([displayed_city_name, | ||
2737 | 2383 | str(city['geonameId']), str(city['lat']), | ||
2738 | 2384 | str(city['lng']), str(city['name'])]) | ||
2739 | 1842 | self.location_input_combo.popup() | 2385 | self.location_input_combo.popup() |
2740 | 1843 | except urllib2.URLError: | 2386 | except urllib2.URLError: |
2741 | 1844 | log.error("Assistant: error reaching url '%s'" % url) | 2387 | log.error("Assistant: error reaching url '%s'" % url) |
2742 | 1845 | 2388 | ||
2743 | 1846 | # A city is selected from suggested list | ||
2744 | 1847 | def on_select_city(self, entry): | 2389 | def on_select_city(self, entry): |
2745 | 2390 | """ A city is selected from suggested list """ | ||
2746 | 1848 | if self.location_input_combo.get_active() != -1: | 2391 | if self.location_input_combo.get_active() != -1: |
2747 | 1849 | self.place_selected = self.store[self.location_input_combo.get_active()] | 2392 | self.place_selected = self.store[self.location_input_combo.get_active()] |
2748 | 1850 | self.assistant.set_page_complete(self.builder.get_object("placeinput"),True) | 2393 | self.assistant.set_page_complete(self.builder.get_object("placeinput"),True) |
2749 | @@ -1853,50 +2396,74 @@ | |||
2750 | 1853 | self.location = None | 2396 | self.location = None |
2751 | 1854 | self.assistant.set_page_complete(self.builder.get_object("placeinput"), False) | 2397 | self.assistant.set_page_complete(self.builder.get_object("placeinput"), False) |
2752 | 1855 | 2398 | ||
2755 | 1856 | # Create a location object out of a selected location | 2399 | def next_page(self, current_page, data): |
2756 | 1857 | def next_page(self, current_page): | 2400 | """ Create a location object out of a selected location """ |
2757 | 1858 | log.debug("Assistant: moved to page %s" % current_page) | 2401 | log.debug("Assistant: moved to page %s" % current_page) |
2759 | 1859 | if (self.assistant.get_current_page() == 0) and not self.location and self.place_selected: | 2402 | if (self.assistant.get_current_page() == 0) and \ |
2760 | 2403 | not self.location and self.place_selected: | ||
2761 | 1860 | # Label input page | 2404 | # Label input page |
2764 | 1861 | log.debug("Assistant: Page %s: got location with code %s" % (current_page, self.place_selected[1])) | 2405 | log.debug("Assistant: Page %s: got location with code %s" % |
2765 | 1862 | self.location = Location(wi.metric_system, wi.wind_unit) | 2406 | (current_page, self.place_selected[1])) |
2766 | 2407 | self.location = Location(wi.metric_system, wi.wind_unit, | ||
2767 | 2408 | wi.heat_index, wi.chill_index) | ||
2768 | 1863 | if self.location.prepare_location(self.place_selected): | 2409 | if self.location.prepare_location(self.place_selected): |
2770 | 1864 | log.debug("Assistant: Page %s: City %s found" % (current_page, self.place_selected[0])) | 2410 | log.debug("Assistant: Page %s: City %s found" % |
2771 | 2411 | (current_page, self.place_selected[0])) | ||
2772 | 1865 | # Set a short city name as default label | 2412 | # Set a short city name as default label |
2773 | 1866 | self.builder.get_object("entrylbl").set_text(self.place_selected[4]) | 2413 | self.builder.get_object("entrylbl").set_text(self.place_selected[4]) |
2774 | 1867 | else: | 2414 | else: |
2776 | 1868 | log.error("Assistant: Page %s: City with code %s was NOT found" % (current_page, self.place_selected[0])) | 2415 | log.error("Assistant: Page %s: City with code %s was NOT " |
2777 | 2416 | "found" % (current_page, self.place_selected[0])) | ||
2778 | 1869 | return 3 | 2417 | return 3 |
2779 | 1870 | elif self.assistant.get_current_page() == 1: | 2418 | elif self.assistant.get_current_page() == 1: |
2780 | 1871 | # Confirmation page | 2419 | # Confirmation page |
2781 | 1872 | lbl = self.builder.get_object("entrylbl").get_text() | 2420 | lbl = self.builder.get_object("entrylbl").get_text() |
2783 | 1873 | log.debug("Assistant: Page %s: City label is %s" % (current_page, lbl)) | 2421 | log.debug("Assistant: Page %s: City label is %s" % |
2784 | 2422 | (current_page, lbl)) | ||
2785 | 1874 | # If empty label was input, set label to short city name | 2423 | # If empty label was input, set label to short city name |
2786 | 1875 | if lbl == '': | 2424 | if lbl == '': |
2788 | 1876 | log.debug("Assistant: Page %s: Empty label found, setting lbl to short name - %s" % (current_page, self.place_selected[4])) | 2425 | log.debug("Assistant: Page %s: Empty label found, setting " |
2789 | 2426 | "lbl to short name - %s" % | ||
2790 | 2427 | (current_page, self.place_selected[4])) | ||
2791 | 1877 | lbl = self.place_selected[4] | 2428 | lbl = self.place_selected[4] |
2792 | 1878 | self.location.location_details['label'] = lbl | 2429 | self.location.location_details['label'] = lbl |
2793 | 1879 | self.builder.get_object("lbl3").set_label(_('Label:')) | 2430 | self.builder.get_object("lbl3").set_label(_('Label:')) |
2794 | 1880 | self.builder.get_object("labellbl").set_label('<b>%s</b>' % lbl) | 2431 | self.builder.get_object("labellbl").set_label('<b>%s</b>' % lbl) |
2796 | 1881 | self.builder.get_object("placelbl").set_label('<b>%s</b>' % self.place_selected[0]) | 2432 | self.builder.get_object("placelbl").set_label( |
2797 | 2433 | '<b>%s</b>' % self.place_selected[0]) | ||
2798 | 1882 | 2434 | ||
2799 | 1883 | return self.assistant.get_current_page() + 1 | 2435 | return self.assistant.get_current_page() + 1 |
2800 | 1884 | 2436 | ||
2801 | 1885 | # 'Cancel' clicked | ||
2802 | 1886 | def on_cancel(self,widget): | 2437 | def on_cancel(self,widget): |
2803 | 2438 | """ 'Cancel' clicked """ | ||
2804 | 1887 | log.debug("Assistant: Cancelled") | 2439 | log.debug("Assistant: Cancelled") |
2805 | 1888 | self.destroy() | 2440 | self.destroy() |
2806 | 1889 | 2441 | ||
2807 | 1890 | # 'Apply' clicked - save location details, add an entry in a location list | ||
2808 | 1891 | def on_apply(self,widget): | 2442 | def on_apply(self,widget): |
2809 | 2443 | """ 'Apply' clicked - save location details, add an entry in a location list """ | ||
2810 | 1892 | (location_code, location_details) = self.location.export_location_details() | 2444 | (location_code, location_details) = self.location.export_location_details() |
2812 | 1893 | log.debug("Assistant: Apply: adding location ('%s', '%s')" % (self.location.location_details['label'], location_code)) | 2445 | log.debug("Assistant: Apply: adding location ('%s', '%s')" % |
2813 | 2446 | (self.location.location_details['label'], location_code)) | ||
2814 | 1894 | newplace = list() | 2447 | newplace = list() |
2815 | 1895 | newplace.append(self.location.location_details['label']) | 2448 | newplace.append(self.location.location_details['label']) |
2816 | 1896 | newplace.append(str(location_code)) | 2449 | newplace.append(str(location_code)) |
2817 | 1897 | newplace.append(str(location_details)) | 2450 | newplace.append(str(location_details)) |
2819 | 1898 | wi.settings.save_location_details(eval(str(location_details)), str(location_code)) | 2451 | wi.settings.save_location_details( |
2820 | 2452 | eval(str(location_details)), str(location_code) | ||
2821 | 2453 | ) | ||
2822 | 1899 | wi.prefswindow.builder.get_object('citieslist').append(newplace) | 2454 | wi.prefswindow.builder.get_object('citieslist').append(newplace) |
2823 | 2455 | |||
2824 | 2456 | newplaces = list() | ||
2825 | 2457 | item = wi.prefswindow.builder.get_object('citieslist').get_iter_first() | ||
2826 | 2458 | while (item != None): | ||
2827 | 2459 | newplace = list() | ||
2828 | 2460 | newplace.append(wi.prefswindow.builder.get_object('citieslist').get_value(item, 1)) | ||
2829 | 2461 | newplace.append(wi.prefswindow.builder.get_object('citieslist').get_value(item, 0)) | ||
2830 | 2462 | newplaces.append(newplace) | ||
2831 | 2463 | item = wi.prefswindow.builder.get_object('citieslist').iter_next(item) | ||
2832 | 2464 | wi.places = newplaces | ||
2833 | 2465 | wi.places_changed = True | ||
2834 | 2466 | |||
2835 | 1900 | # Enable 'OK' button in Preferences | 2467 | # Enable 'OK' button in Preferences |
2836 | 1901 | wi.prefswindow.builder.get_object('ok_button').set_sensitive(True) | 2468 | wi.prefswindow.builder.get_object('ok_button').set_sensitive(True) |
2837 | 1902 | self.hide() | 2469 | self.hide() |
2838 | @@ -1904,8 +2471,8 @@ | |||
2839 | 1904 | class SingleInstance(object): | 2471 | class SingleInstance(object): |
2840 | 1905 | """ Class to ensure, that single instance of the applet is run for each user """ | 2472 | """ Class to ensure, that single instance of the applet is run for each user """ |
2841 | 1906 | 2473 | ||
2842 | 1907 | # Initialize, specifying a path to store pids | ||
2843 | 1908 | def __init__(self, pidPath): | 2474 | def __init__(self, pidPath): |
2844 | 2475 | """ Initialize, specifying a path to store pids """ | ||
2845 | 1909 | self.pidPath=pidPath | 2476 | self.pidPath=pidPath |
2846 | 1910 | # See if pidFile exists | 2477 | # See if pidFile exists |
2847 | 1911 | if os.path.exists(pidPath): | 2478 | if os.path.exists(pidPath): |
2848 | @@ -1928,7 +2495,8 @@ | |||
2849 | 1928 | shutil.copy(temp_path, pidPath) | 2495 | shutil.copy(temp_path, pidPath) |
2850 | 1929 | os.unlink(temp_path) | 2496 | os.unlink(temp_path) |
2851 | 1930 | except Exception as e: | 2497 | except Exception as e: |
2853 | 1931 | log.error("SingleInstance: exception while renaming '%s' to '%s':\n %s" % (temp_path, pidPath, str(e))) | 2498 | log.error("SingleInstance: exception while renaming '%s' " |
2854 | 2499 | "to '%s':\n %s" % (temp_path, pidPath, str(e))) | ||
2855 | 1932 | 2500 | ||
2856 | 1933 | def is_already_running(self): | 2501 | def is_already_running(self): |
2857 | 1934 | return self.lasterror | 2502 | return self.lasterror |
2858 | @@ -1939,7 +2507,8 @@ | |||
2859 | 1939 | os.unlink(self.pidPath) | 2507 | os.unlink(self.pidPath) |
2860 | 1940 | 2508 | ||
2861 | 1941 | def main(): | 2509 | def main(): |
2863 | 1942 | gtk.main() | 2510 | Gtk.main() |
2864 | 2511 | |||
2865 | 1943 | return 0 | 2512 | return 0 |
2866 | 1944 | 2513 | ||
2867 | 1945 | if __name__ == "__main__": | 2514 | if __name__ == "__main__": |
2868 | @@ -1952,8 +2521,10 @@ | |||
2869 | 1952 | log = logging.getLogger('IndicatorWeather') | 2521 | log = logging.getLogger('IndicatorWeather') |
2870 | 1953 | log.propagate = False | 2522 | log.propagate = False |
2871 | 1954 | log.setLevel(logging.DEBUG) | 2523 | log.setLevel(logging.DEBUG) |
2874 | 1955 | log_handler = logging.handlers.RotatingFileHandler(log_filename, maxBytes=1024*1024, backupCount=5) | 2524 | log_handler = logging.handlers.RotatingFileHandler( |
2875 | 1956 | log_formatter = logging.Formatter("[%(threadName)s] %(asctime)s - %(levelname)s - %(message)s") | 2525 | log_filename, maxBytes=1024*1024, backupCount=5) |
2876 | 2526 | log_formatter = logging.Formatter("[%(threadName)s] %(asctime)s - " | ||
2877 | 2527 | "%(levelname)s - %(message)s") | ||
2878 | 1957 | log_handler.setFormatter(log_formatter) | 2528 | log_handler.setFormatter(log_formatter) |
2879 | 1958 | log.addHandler(log_handler) | 2529 | log.addHandler(log_handler) |
2880 | 1959 | 2530 | ||
2881 | @@ -1974,8 +2545,7 @@ | |||
2882 | 1974 | TimeFormatter.monitor_indicator_datetime(log) | 2545 | TimeFormatter.monitor_indicator_datetime(log) |
2883 | 1975 | 2546 | ||
2884 | 1976 | # not running, safe to continue... | 2547 | # not running, safe to continue... |
2887 | 1977 | gtk.gdk.threads_init() | 2548 | |
2886 | 1978 | gtk.gdk.threads_enter() | ||
2888 | 1979 | # Remember locale name | 2549 | # Remember locale name |
2889 | 1980 | global locale_name | 2550 | global locale_name |
2890 | 1981 | locale_name = locale.getlocale()[0] | 2551 | locale_name = locale.getlocale()[0] |
2891 | @@ -1984,6 +2554,20 @@ | |||
2892 | 1984 | else: | 2554 | else: |
2893 | 1985 | locale.setlocale(locale.LC_ALL, 'C') # use default (C) locale | 2555 | locale.setlocale(locale.LC_ALL, 'C') # use default (C) locale |
2894 | 1986 | locale_name = "en" | 2556 | locale_name = "en" |
2895 | 2557 | |||
2896 | 2558 | # init GLib/GObject | ||
2897 | 2559 | GObject.threads_init() | ||
2898 | 2560 | |||
2899 | 2561 | # init Gdk threads and get Gdk lock | ||
2900 | 2562 | Gdk.threads_init() | ||
2901 | 2563 | Gdk.threads_enter() | ||
2902 | 2564 | |||
2903 | 2565 | # init Gtk | ||
2904 | 2566 | Gtk.init(None) | ||
2905 | 2567 | |||
2906 | 2568 | # create main thread and enter main loop | ||
2907 | 1987 | wi = indicator_weather() | 2569 | wi = indicator_weather() |
2908 | 1988 | main() | 2570 | main() |
2910 | 1989 | gtk.gdk.threads_leave() | 2571 | |
2911 | 2572 | # release Gdk lock | ||
2912 | 2573 | Gdk.threads_leave() | ||
2913 | 1990 | \ No newline at end of file | 2574 | \ No newline at end of file |
2914 | 1991 | 2575 | ||
2915 | === modified file 'data/indicator-weather.gschema.xml' | |||
2916 | --- data/indicator-weather.gschema.xml 2011-05-31 09:49:23 +0000 | |||
2917 | +++ data/indicator-weather.gschema.xml 2013-05-22 05:08:27 +0000 | |||
2918 | @@ -6,6 +6,21 @@ | |||
2919 | 6 | <summary>Display icon/label in the indicator</summary> | 6 | <summary>Display icon/label in the indicator</summary> |
2920 | 7 | <description>0 - display icon only, 1 - display label only, 2 - display both icon and text</description> | 7 | <description>0 - display icon only, 1 - display label only, 2 - display both icon and text</description> |
2921 | 8 | </key> | 8 | </key> |
2922 | 9 | <key type="b" name="relative-display"> | ||
2923 | 10 | <default>false</default> | ||
2924 | 11 | <summary>Display relative temperature</summary> | ||
2925 | 12 | <description>Display relative temperature</description> | ||
2926 | 13 | </key> | ||
2927 | 14 | <key type="b" name="wind-display"> | ||
2928 | 15 | <default>true</default> | ||
2929 | 16 | <summary>Display wind speed and direction</summary> | ||
2930 | 17 | <description>Display wind speed and direction</description> | ||
2931 | 18 | </key> | ||
2932 | 19 | <key type="b" name="suntimes-display"> | ||
2933 | 20 | <default>true</default> | ||
2934 | 21 | <summary>Display sunrise and sunset times</summary> | ||
2935 | 22 | <description>Display sunrise and sunset times</description> | ||
2936 | 23 | </key> | ||
2937 | 9 | <key type="s" name="notifications"> | 24 | <key type="s" name="notifications"> |
2938 | 10 | <default>'N'</default> | 25 | <default>'N'</default> |
2939 | 11 | <summary>Notifications</summary> | 26 | <summary>Notifications</summary> |
2940 | @@ -36,6 +51,16 @@ | |||
2941 | 36 | <summary>wind unit</summary> | 51 | <summary>wind unit</summary> |
2942 | 37 | <description>wind unit</description> | 52 | <description>wind unit</description> |
2943 | 38 | </key> | 53 | </key> |
2944 | 54 | <key type="s" name="heat-estimate"> | ||
2945 | 55 | <default>'humidex'</default> | ||
2946 | 56 | <summary>heat estimate formula</summary> | ||
2947 | 57 | <description>heat estimate formula</description> | ||
2948 | 58 | </key> | ||
2949 | 59 | <key type="s" name="chill-estimate"> | ||
2950 | 60 | <default>'windchill'</default> | ||
2951 | 61 | <summary>chill estimate formula</summary> | ||
2952 | 62 | <description>chill estimate formula</description> | ||
2953 | 63 | </key> | ||
2954 | 39 | <key type="b" name="show-forecast"> | 64 | <key type="b" name="show-forecast"> |
2955 | 40 | <default>true</default> | 65 | <default>true</default> |
2956 | 41 | <summary>show forecast</summary> | 66 | <summary>show forecast</summary> |
2957 | 42 | 67 | ||
2958 | === modified file 'data/ui/Assistant.ui' | |||
2959 | --- data/ui/Assistant.ui 2011-04-03 05:00:19 +0000 | |||
2960 | +++ data/ui/Assistant.ui 2013-05-22 05:08:27 +0000 | |||
2961 | @@ -1,29 +1,28 @@ | |||
2962 | 1 | <?xml version="1.0" encoding="UTF-8"?> | 1 | <?xml version="1.0" encoding="UTF-8"?> |
2963 | 2 | <interface> | 2 | <interface> |
2965 | 3 | <requires lib="gtk+" version="2.16"/> | 3 | <!-- interface-requires gtk+ 3.0 --> |
2966 | 4 | <!-- interface-requires assistant 1.0 --> | 4 | <!-- interface-requires assistant 1.0 --> |
2967 | 5 | <!-- interface-naming-policy project-wide --> | ||
2968 | 6 | <!-- interface-local-resource-path ../media --> | 5 | <!-- interface-local-resource-path ../media --> |
2969 | 7 | <object class="Assistant" id="assistant"> | 6 | <object class="Assistant" id="assistant"> |
2970 | 7 | <property name="can_focus">False</property> | ||
2971 | 8 | <property name="border_width">12</property> | 8 | <property name="border_width">12</property> |
2972 | 9 | <property name="title" translatable="yes">Add a location</property> | 9 | <property name="title" translatable="yes">Add a location</property> |
2973 | 10 | <property name="resizable">False</property> | ||
2974 | 10 | <property name="window_position">mouse</property> | 11 | <property name="window_position">mouse</property> |
2975 | 11 | <property name="default_width">400</property> | 12 | <property name="default_width">400</property> |
2976 | 12 | <property name="default_height">200</property> | 13 | <property name="default_height">200</property> |
2983 | 13 | <property name="resizable">False</property> | 14 | <signal name="apply" handler="on_apply" swapped="no"/> |
2984 | 14 | <signal name="apply" handler="on_apply"/> | 15 | <signal name="cancel" handler="on_cancel" swapped="no"/> |
2979 | 15 | <signal name="cancel" handler="on_cancel"/> | ||
2980 | 16 | <!--<child> | ||
2981 | 17 | <placeholder/> | ||
2982 | 18 | </child> --> | ||
2985 | 19 | <child> | 16 | <child> |
2986 | 20 | <object class="GtkVBox" id="placeinput"> | 17 | <object class="GtkVBox" id="placeinput"> |
2987 | 21 | <property name="visible">True</property> | 18 | <property name="visible">True</property> |
2988 | 19 | <property name="can_focus">False</property> | ||
2989 | 22 | <property name="border_width">12</property> | 20 | <property name="border_width">12</property> |
2990 | 23 | <property name="spacing">6</property> | 21 | <property name="spacing">6</property> |
2991 | 24 | <child> | 22 | <child> |
2992 | 25 | <object class="GtkLabel" id="lblplaceinput"> | 23 | <object class="GtkLabel" id="lblplaceinput"> |
2993 | 26 | <property name="visible">True</property> | 24 | <property name="visible">True</property> |
2994 | 25 | <property name="can_focus">False</property> | ||
2995 | 27 | <property name="xalign">0</property> | 26 | <property name="xalign">0</property> |
2996 | 28 | <property name="yalign">0</property> | 27 | <property name="yalign">0</property> |
2997 | 29 | <property name="ypad">6</property> | 28 | <property name="ypad">6</property> |
2998 | @@ -32,43 +31,56 @@ | |||
2999 | 32 | <property name="wrap_mode">word-char</property> | 31 | <property name="wrap_mode">word-char</property> |
3000 | 33 | </object> | 32 | </object> |
3001 | 34 | <packing> | 33 | <packing> |
3002 | 34 | <property name="expand">True</property> | ||
3003 | 35 | <property name="fill">True</property> | ||
3004 | 35 | <property name="position">0</property> | 36 | <property name="position">0</property> |
3005 | 36 | </packing> | 37 | </packing> |
3006 | 37 | </child> | 38 | </child> |
3007 | 38 | <child> | 39 | <child> |
3039 | 39 | <object class="GtkHBox" id="city_input_vbox"> | 40 | <object class="GtkHBox" id="city_input_vbox"> |
3040 | 40 | <property name="visible">True</property> | 41 | <property name="visible">True</property> |
3041 | 41 | <property name="border_width">12</property> | 42 | <property name="can_focus">False</property> |
3042 | 42 | <property name="spacing">6</property> | 43 | <property name="border_width">12</property> |
3043 | 43 | <child> | 44 | <property name="spacing">6</property> |
3044 | 44 | <object class="GtkComboBoxEntry" id="combolocations"> | 45 | <child> |
3045 | 45 | <property name="visible">True</property> | 46 | <object class="GtkComboBox" id="combolocations"> |
3046 | 46 | <signal name="changed" handler="on_select_city"/> | 47 | <property name="visible">True</property> |
3047 | 47 | <child internal-child="entry"> | 48 | <property name="can_focus">False</property> |
3048 | 48 | <object class="GtkEntry" id="entrylocation"> | 49 | <property name="has_entry">True</property> |
3049 | 49 | <property name="visible">True</property> | 50 | <signal name="changed" handler="on_select_city" swapped="no"/> |
3050 | 50 | <property name="can_focus">True</property> | 51 | <child internal-child="entry"> |
3051 | 51 | </object> | 52 | <object class="GtkEntry" id="entrylocation"> |
3052 | 52 | </child> | 53 | <property name="visible">True</property> |
3053 | 53 | </object> | 54 | <property name="can_focus">True</property> |
3054 | 54 | <packing> | 55 | </object> |
3055 | 55 | <property name="position">0</property> | 56 | </child> |
3056 | 56 | </packing> | 57 | </object> |
3057 | 57 | </child> | 58 | <packing> |
3058 | 58 | <child> | 59 | <property name="expand">True</property> |
3059 | 59 | <object class="GtkButton" id="getcities"> | 60 | <property name="fill">True</property> |
3060 | 60 | <property name="visible">True</property> | 61 | <property name="position">0</property> |
3061 | 61 | <property name="label" translatable="yes">Search</property> | 62 | </packing> |
3062 | 62 | <signal name="clicked" handler="on_get_city_names"/> | 63 | </child> |
3063 | 63 | </object> | 64 | <child> |
3064 | 64 | <packing> | 65 | <object class="GtkButton" id="getcities"> |
3065 | 65 | <property name="position">1</property> | 66 | <property name="label" translatable="yes">Search</property> |
3066 | 66 | </packing> | 67 | <property name="visible">True</property> |
3067 | 67 | </child> | 68 | <property name="can_focus">False</property> |
3068 | 68 | </object> | 69 | <property name="receives_default">False</property> |
3069 | 69 | <packing> | 70 | <signal name="clicked" handler="on_get_city_names" swapped="no"/> |
3070 | 71 | </object> | ||
3071 | 72 | <packing> | ||
3072 | 73 | <property name="expand">True</property> | ||
3073 | 74 | <property name="fill">True</property> | ||
3074 | 70 | <property name="position">1</property> | 75 | <property name="position">1</property> |
3076 | 71 | </packing> | 76 | </packing> |
3077 | 77 | </child> | ||
3078 | 78 | </object> | ||
3079 | 79 | <packing> | ||
3080 | 80 | <property name="expand">True</property> | ||
3081 | 81 | <property name="fill">True</property> | ||
3082 | 82 | <property name="position">1</property> | ||
3083 | 83 | </packing> | ||
3084 | 72 | </child> | 84 | </child> |
3085 | 73 | </object> | 85 | </object> |
3086 | 74 | <packing> | 86 | <packing> |
3087 | @@ -78,16 +90,19 @@ | |||
3088 | 78 | <child> | 90 | <child> |
3089 | 79 | <object class="GtkVBox" id="label"> | 91 | <object class="GtkVBox" id="label"> |
3090 | 80 | <property name="visible">True</property> | 92 | <property name="visible">True</property> |
3091 | 93 | <property name="can_focus">False</property> | ||
3092 | 81 | <property name="border_width">12</property> | 94 | <property name="border_width">12</property> |
3093 | 82 | <property name="spacing">6</property> | 95 | <property name="spacing">6</property> |
3094 | 83 | <child> | 96 | <child> |
3095 | 84 | <object class="GtkLabel" id="lblwould"> | 97 | <object class="GtkLabel" id="lblwould"> |
3096 | 85 | <property name="visible">True</property> | 98 | <property name="visible">True</property> |
3097 | 99 | <property name="can_focus">False</property> | ||
3098 | 86 | <property name="xalign">0</property> | 100 | <property name="xalign">0</property> |
3099 | 87 | <property name="label" translatable="yes">Please enter a name for this location:</property> | 101 | <property name="label" translatable="yes">Please enter a name for this location:</property> |
3100 | 88 | </object> | 102 | </object> |
3101 | 89 | <packing> | 103 | <packing> |
3102 | 90 | <property name="expand">False</property> | 104 | <property name="expand">False</property> |
3103 | 105 | <property name="fill">True</property> | ||
3104 | 91 | <property name="position">0</property> | 106 | <property name="position">0</property> |
3105 | 92 | </packing> | 107 | </packing> |
3106 | 93 | </child> | 108 | </child> |
3107 | @@ -99,6 +114,7 @@ | |||
3108 | 99 | </object> | 114 | </object> |
3109 | 100 | <packing> | 115 | <packing> |
3110 | 101 | <property name="expand">False</property> | 116 | <property name="expand">False</property> |
3111 | 117 | <property name="fill">True</property> | ||
3112 | 102 | <property name="position">1</property> | 118 | <property name="position">1</property> |
3113 | 103 | </packing> | 119 | </packing> |
3114 | 104 | </child> | 120 | </child> |
3115 | @@ -110,10 +126,12 @@ | |||
3116 | 110 | <child> | 126 | <child> |
3117 | 111 | <object class="GtkVBox" id="review"> | 127 | <object class="GtkVBox" id="review"> |
3118 | 112 | <property name="visible">True</property> | 128 | <property name="visible">True</property> |
3119 | 129 | <property name="can_focus">False</property> | ||
3120 | 113 | <property name="border_width">12</property> | 130 | <property name="border_width">12</property> |
3121 | 114 | <child> | 131 | <child> |
3122 | 115 | <object class="GtkLabel" id="lblreview"> | 132 | <object class="GtkLabel" id="lblreview"> |
3123 | 116 | <property name="visible">True</property> | 133 | <property name="visible">True</property> |
3124 | 134 | <property name="can_focus">False</property> | ||
3125 | 117 | <property name="xalign">0</property> | 135 | <property name="xalign">0</property> |
3126 | 118 | <property name="ypad">6</property> | 136 | <property name="ypad">6</property> |
3127 | 119 | <property name="label" translatable="yes">Please review the choices below. If anything is not correct, please go back and select the correct options.</property> | 137 | <property name="label" translatable="yes">Please review the choices below. If anything is not correct, please go back and select the correct options.</property> |
3128 | @@ -122,99 +140,120 @@ | |||
3129 | 122 | </object> | 140 | </object> |
3130 | 123 | <packing> | 141 | <packing> |
3131 | 124 | <property name="expand">False</property> | 142 | <property name="expand">False</property> |
3132 | 143 | <property name="fill">True</property> | ||
3133 | 125 | <property name="position">0</property> | 144 | <property name="position">0</property> |
3134 | 126 | </packing> | 145 | </packing> |
3135 | 127 | </child> | 146 | </child> |
3136 | 128 | <child> | 147 | <child> |
3137 | 129 | <object class="GtkAlignment" id="alignment1"> | 148 | <object class="GtkAlignment" id="alignment1"> |
3138 | 130 | <property name="visible">True</property> | 149 | <property name="visible">True</property> |
3139 | 150 | <property name="can_focus">False</property> | ||
3140 | 131 | <property name="left_padding">12</property> | 151 | <property name="left_padding">12</property> |
3141 | 132 | <child> | 152 | <child> |
3142 | 133 | <object class="GtkVBox" id="vbox1"> | 153 | <object class="GtkVBox" id="vbox1"> |
3143 | 134 | <property name="visible">True</property> | 154 | <property name="visible">True</property> |
3144 | 155 | <property name="can_focus">False</property> | ||
3145 | 135 | <child> | 156 | <child> |
3146 | 136 | <object class="GtkHBox" id="revlabel"> | 157 | <object class="GtkHBox" id="revlabel"> |
3147 | 137 | <property name="visible">True</property> | 158 | <property name="visible">True</property> |
3148 | 159 | <property name="can_focus">False</property> | ||
3149 | 138 | <property name="spacing">5</property> | 160 | <property name="spacing">5</property> |
3150 | 139 | <child> | 161 | <child> |
3151 | 140 | <object class="GtkArrow" id="arrow3"> | 162 | <object class="GtkArrow" id="arrow3"> |
3152 | 141 | <property name="visible">True</property> | 163 | <property name="visible">True</property> |
3153 | 142 | <property name="sensitive">False</property> | 164 | <property name="sensitive">False</property> |
3154 | 165 | <property name="can_focus">False</property> | ||
3155 | 143 | </object> | 166 | </object> |
3156 | 144 | <packing> | 167 | <packing> |
3157 | 145 | <property name="expand">False</property> | 168 | <property name="expand">False</property> |
3158 | 169 | <property name="fill">True</property> | ||
3159 | 146 | <property name="position">0</property> | 170 | <property name="position">0</property> |
3160 | 147 | </packing> | 171 | </packing> |
3161 | 148 | </child> | 172 | </child> |
3162 | 149 | <child> | 173 | <child> |
3163 | 150 | <object class="GtkLabel" id="lbl3"> | 174 | <object class="GtkLabel" id="lbl3"> |
3164 | 151 | <property name="visible">True</property> | 175 | <property name="visible">True</property> |
3165 | 176 | <property name="can_focus">False</property> | ||
3166 | 152 | <property name="xalign">0</property> | 177 | <property name="xalign">0</property> |
3167 | 153 | <property name="label" translatable="yes">Label:</property> | 178 | <property name="label" translatable="yes">Label:</property> |
3168 | 154 | <property name="use_markup">True</property> | 179 | <property name="use_markup">True</property> |
3169 | 155 | </object> | 180 | </object> |
3170 | 156 | <packing> | 181 | <packing> |
3171 | 157 | <property name="expand">False</property> | 182 | <property name="expand">False</property> |
3172 | 183 | <property name="fill">True</property> | ||
3173 | 158 | <property name="position">1</property> | 184 | <property name="position">1</property> |
3174 | 159 | </packing> | 185 | </packing> |
3175 | 160 | </child> | 186 | </child> |
3176 | 161 | <child> | 187 | <child> |
3177 | 162 | <object class="GtkLabel" id="labellbl"> | 188 | <object class="GtkLabel" id="labellbl"> |
3178 | 163 | <property name="visible">True</property> | 189 | <property name="visible">True</property> |
3179 | 190 | <property name="can_focus">False</property> | ||
3180 | 164 | <property name="xalign">0</property> | 191 | <property name="xalign">0</property> |
3181 | 165 | <property name="label" translatable="yes"><b>Home</b></property> | 192 | <property name="label" translatable="yes"><b>Home</b></property> |
3182 | 166 | <property name="use_markup">True</property> | 193 | <property name="use_markup">True</property> |
3183 | 167 | </object> | 194 | </object> |
3184 | 168 | <packing> | 195 | <packing> |
3185 | 196 | <property name="expand">True</property> | ||
3186 | 197 | <property name="fill">True</property> | ||
3187 | 169 | <property name="position">2</property> | 198 | <property name="position">2</property> |
3188 | 170 | </packing> | 199 | </packing> |
3189 | 171 | </child> | 200 | </child> |
3190 | 172 | </object> | 201 | </object> |
3191 | 173 | <packing> | 202 | <packing> |
3192 | 174 | <property name="expand">False</property> | 203 | <property name="expand">False</property> |
3193 | 204 | <property name="fill">True</property> | ||
3194 | 175 | <property name="position">0</property> | 205 | <property name="position">0</property> |
3195 | 176 | </packing> | 206 | </packing> |
3196 | 177 | </child> | 207 | </child> |
3197 | 178 | <child> | 208 | <child> |
3198 | 179 | <object class="GtkHBox" id="revplace"> | 209 | <object class="GtkHBox" id="revplace"> |
3199 | 180 | <property name="visible">True</property> | 210 | <property name="visible">True</property> |
3200 | 211 | <property name="can_focus">False</property> | ||
3201 | 181 | <property name="spacing">5</property> | 212 | <property name="spacing">5</property> |
3202 | 182 | <child> | 213 | <child> |
3203 | 183 | <object class="GtkArrow" id="arrow2"> | 214 | <object class="GtkArrow" id="arrow2"> |
3204 | 184 | <property name="visible">True</property> | 215 | <property name="visible">True</property> |
3205 | 185 | <property name="sensitive">False</property> | 216 | <property name="sensitive">False</property> |
3206 | 217 | <property name="can_focus">False</property> | ||
3207 | 186 | </object> | 218 | </object> |
3208 | 187 | <packing> | 219 | <packing> |
3209 | 188 | <property name="expand">False</property> | 220 | <property name="expand">False</property> |
3210 | 221 | <property name="fill">True</property> | ||
3211 | 189 | <property name="position">0</property> | 222 | <property name="position">0</property> |
3212 | 190 | </packing> | 223 | </packing> |
3213 | 191 | </child> | 224 | </child> |
3214 | 192 | <child> | 225 | <child> |
3215 | 193 | <object class="GtkLabel" id="lbl2"> | 226 | <object class="GtkLabel" id="lbl2"> |
3216 | 194 | <property name="visible">True</property> | 227 | <property name="visible">True</property> |
3217 | 228 | <property name="can_focus">False</property> | ||
3218 | 195 | <property name="xalign">0</property> | 229 | <property name="xalign">0</property> |
3219 | 196 | <property name="label" translatable="yes">Location:</property> | 230 | <property name="label" translatable="yes">Location:</property> |
3220 | 197 | <property name="use_markup">True</property> | 231 | <property name="use_markup">True</property> |
3221 | 198 | </object> | 232 | </object> |
3222 | 199 | <packing> | 233 | <packing> |
3223 | 200 | <property name="expand">False</property> | 234 | <property name="expand">False</property> |
3224 | 235 | <property name="fill">True</property> | ||
3225 | 201 | <property name="position">1</property> | 236 | <property name="position">1</property> |
3226 | 202 | </packing> | 237 | </packing> |
3227 | 203 | </child> | 238 | </child> |
3228 | 204 | <child> | 239 | <child> |
3229 | 205 | <object class="GtkLabel" id="placelbl"> | 240 | <object class="GtkLabel" id="placelbl"> |
3230 | 206 | <property name="visible">True</property> | 241 | <property name="visible">True</property> |
3231 | 242 | <property name="can_focus">False</property> | ||
3232 | 207 | <property name="xalign">0</property> | 243 | <property name="xalign">0</property> |
3233 | 208 | <property name="label" translatable="yes"><b>Orange, Texas</b></property> | 244 | <property name="label" translatable="yes"><b>Orange, Texas</b></property> |
3234 | 209 | <property name="use_markup">True</property> | 245 | <property name="use_markup">True</property> |
3235 | 210 | </object> | 246 | </object> |
3236 | 211 | <packing> | 247 | <packing> |
3237 | 248 | <property name="expand">True</property> | ||
3238 | 249 | <property name="fill">True</property> | ||
3239 | 212 | <property name="position">2</property> | 250 | <property name="position">2</property> |
3240 | 213 | </packing> | 251 | </packing> |
3241 | 214 | </child> | 252 | </child> |
3242 | 215 | </object> | 253 | </object> |
3243 | 216 | <packing> | 254 | <packing> |
3244 | 217 | <property name="expand">False</property> | 255 | <property name="expand">False</property> |
3245 | 256 | <property name="fill">True</property> | ||
3246 | 218 | <property name="position">1</property> | 257 | <property name="position">1</property> |
3247 | 219 | </packing> | 258 | </packing> |
3248 | 220 | </child> | 259 | </child> |
3249 | @@ -223,6 +262,7 @@ | |||
3250 | 223 | </object> | 262 | </object> |
3251 | 224 | <packing> | 263 | <packing> |
3252 | 225 | <property name="expand">False</property> | 264 | <property name="expand">False</property> |
3253 | 265 | <property name="fill">True</property> | ||
3254 | 226 | <property name="position">1</property> | 266 | <property name="position">1</property> |
3255 | 227 | </packing> | 267 | </packing> |
3256 | 228 | </child> | 268 | </child> |
3257 | @@ -235,5 +275,10 @@ | |||
3258 | 235 | <property name="title" translatable="yes">Review choices</property> | 275 | <property name="title" translatable="yes">Review choices</property> |
3259 | 236 | </packing> | 276 | </packing> |
3260 | 237 | </child> | 277 | </child> |
3261 | 278 | <child internal-child="action_area"> | ||
3262 | 279 | <object class="GtkBox" id="Assistant-action_area1"> | ||
3263 | 280 | <property name="can_focus">False</property> | ||
3264 | 281 | </object> | ||
3265 | 282 | </child> | ||
3266 | 238 | </object> | 283 | </object> |
3267 | 239 | </interface> | 284 | </interface> |
3268 | 240 | 285 | ||
3269 | === modified file 'data/ui/ExtendedForecast.ui' | |||
3270 | --- data/ui/ExtendedForecast.ui 2011-11-27 07:38:08 +0000 | |||
3271 | +++ data/ui/ExtendedForecast.ui 2013-05-22 05:08:27 +0000 | |||
3272 | @@ -1,64 +1,76 @@ | |||
3273 | 1 | <?xml version="1.0" encoding="UTF-8"?> | 1 | <?xml version="1.0" encoding="UTF-8"?> |
3274 | 2 | <interface> | 2 | <interface> |
3276 | 3 | <requires lib="gtk+" version="2.16"/> | 3 | <!-- interface-requires gtk+ 3.0 --> |
3277 | 4 | <!-- interface-requires extended_forecast 1.0 --> | 4 | <!-- interface-requires extended_forecast 1.0 --> |
3278 | 5 | <!-- interface-naming-policy project-wide --> | ||
3279 | 6 | <!-- interface-local-resource-path ../media --> | 5 | <!-- interface-local-resource-path ../media --> |
3280 | 7 | <object class="ExtendedForecast" id="extended_forecast"> | 6 | <object class="ExtendedForecast" id="extended_forecast"> |
3281 | 7 | <property name="can_focus">False</property> | ||
3282 | 8 | <property name="border_width">12</property> | 8 | <property name="border_width">12</property> |
3283 | 9 | <property name="title" translatable="yes">Extended Forecast</property> | 9 | <property name="title" translatable="yes">Extended Forecast</property> |
3284 | 10 | <property name="resizable">False</property> | 10 | <property name="resizable">False</property> |
3285 | 11 | <property name="window_position">mouse</property> | 11 | <property name="window_position">mouse</property> |
3286 | 12 | <property name="icon">../media/icon.png</property> | 12 | <property name="icon">../media/icon.png</property> |
3288 | 13 | <signal name="destroy" handler="on_destroy"/> | 13 | <signal name="destroy" handler="on_destroy" swapped="no"/> |
3289 | 14 | <child> | 14 | <child> |
3290 | 15 | <object class="GtkVBox" id="mainvbox"> | 15 | <object class="GtkVBox" id="mainvbox"> |
3291 | 16 | <property name="visible">True</property> | 16 | <property name="visible">True</property> |
3292 | 17 | <property name="can_focus">False</property> | ||
3293 | 17 | <child> | 18 | <child> |
3304 | 18 | <object class="GtkLabel" id="connection_error"> | 19 | <object class="GtkLabel" id="connection_error"> |
3305 | 19 | <property name="visible">False</property> | 20 | <property name="can_focus">False</property> |
3306 | 20 | <property name="ypad">10</property> | 21 | <property name="ypad">10</property> |
3307 | 21 | <property name="label"><big>Forecast information cannot be fetched. Connection cannot be established.</big></property> | 22 | <property name="label"><big>Forecast information cannot be fetched. Connection cannot be established.</big></property> |
3308 | 22 | <property name="use_markup">True</property> | 23 | <property name="use_markup">True</property> |
3309 | 23 | <property name="wrap">False</property> | 24 | </object> |
3310 | 24 | </object> | 25 | <packing> |
3311 | 25 | <packing> | 26 | <property name="expand">True</property> |
3312 | 26 | <property name="position">0</property> | 27 | <property name="fill">True</property> |
3313 | 27 | </packing> | 28 | <property name="position">0</property> |
3314 | 29 | </packing> | ||
3315 | 28 | </child> | 30 | </child> |
3316 | 29 | <child> | 31 | <child> |
3317 | 30 | <object class="GtkHBox" id="hbox1"> | 32 | <object class="GtkHBox" id="hbox1"> |
3318 | 31 | <property name="visible">True</property> | 33 | <property name="visible">True</property> |
3319 | 34 | <property name="can_focus">False</property> | ||
3320 | 32 | <property name="spacing">5</property> | 35 | <property name="spacing">5</property> |
3321 | 33 | <property name="homogeneous">True</property> | 36 | <property name="homogeneous">True</property> |
3322 | 34 | <child> | 37 | <child> |
3323 | 35 | <object class="GtkHBox" id="hbox2"> | 38 | <object class="GtkHBox" id="hbox2"> |
3324 | 36 | <property name="visible">True</property> | 39 | <property name="visible">True</property> |
3325 | 40 | <property name="can_focus">False</property> | ||
3326 | 37 | <child> | 41 | <child> |
3327 | 38 | <object class="GtkAlignment" id="alignment3"> | 42 | <object class="GtkAlignment" id="alignment3"> |
3328 | 39 | <property name="visible">True</property> | 43 | <property name="visible">True</property> |
3329 | 44 | <property name="can_focus">False</property> | ||
3330 | 40 | <property name="right_padding">6</property> | 45 | <property name="right_padding">6</property> |
3331 | 41 | <child> | 46 | <child> |
3332 | 42 | <object class="GtkVBox" id="day1vbox"> | 47 | <object class="GtkVBox" id="day1vbox"> |
3333 | 43 | <property name="visible">True</property> | 48 | <property name="visible">True</property> |
3334 | 49 | <property name="can_focus">False</property> | ||
3335 | 44 | <child> | 50 | <child> |
3336 | 45 | <object class="GtkLabel" id="day1lbl"> | 51 | <object class="GtkLabel" id="day1lbl"> |
3337 | 46 | <property name="visible">True</property> | 52 | <property name="visible">True</property> |
3338 | 53 | <property name="can_focus">False</property> | ||
3339 | 47 | <property name="ypad">10</property> | 54 | <property name="ypad">10</property> |
3340 | 48 | <property name="label"><big>Today (fri.)</big></property> | 55 | <property name="label"><big>Today (fri.)</big></property> |
3341 | 49 | <property name="use_markup">True</property> | 56 | <property name="use_markup">True</property> |
3342 | 50 | </object> | 57 | </object> |
3343 | 51 | <packing> | 58 | <packing> |
3344 | 59 | <property name="expand">True</property> | ||
3345 | 60 | <property name="fill">True</property> | ||
3346 | 52 | <property name="position">0</property> | 61 | <property name="position">0</property> |
3347 | 53 | </packing> | 62 | </packing> |
3348 | 54 | </child> | 63 | </child> |
3349 | 55 | <child> | 64 | <child> |
3350 | 56 | <object class="GtkImage" id="day1image"> | 65 | <object class="GtkImage" id="day1image"> |
3351 | 57 | <property name="visible">True</property> | 66 | <property name="visible">True</property> |
3352 | 67 | <property name="can_focus">False</property> | ||
3353 | 58 | <property name="pixel_size">50</property> | 68 | <property name="pixel_size">50</property> |
3354 | 59 | <property name="icon_name">weather-showers</property> | 69 | <property name="icon_name">weather-showers</property> |
3355 | 60 | </object> | 70 | </object> |
3356 | 61 | <packing> | 71 | <packing> |
3357 | 72 | <property name="expand">True</property> | ||
3358 | 73 | <property name="fill">True</property> | ||
3359 | 62 | <property name="position">1</property> | 74 | <property name="position">1</property> |
3360 | 63 | </packing> | 75 | </packing> |
3361 | 64 | </child> | 76 | </child> |
3362 | @@ -66,6 +78,7 @@ | |||
3363 | 66 | <object class="GtkLabel" id="day1cond"> | 78 | <object class="GtkLabel" id="day1cond"> |
3364 | 67 | <property name="height_request">80</property> | 79 | <property name="height_request">80</property> |
3365 | 68 | <property name="visible">True</property> | 80 | <property name="visible">True</property> |
3366 | 81 | <property name="can_focus">False</property> | ||
3367 | 69 | <property name="label">Partially cloudy</property> | 82 | <property name="label">Partially cloudy</property> |
3368 | 70 | <property name="justify">center</property> | 83 | <property name="justify">center</property> |
3369 | 71 | <property name="wrap">True</property> | 84 | <property name="wrap">True</property> |
3370 | @@ -73,33 +86,44 @@ | |||
3371 | 73 | <property name="width_chars">15</property> | 86 | <property name="width_chars">15</property> |
3372 | 74 | </object> | 87 | </object> |
3373 | 75 | <packing> | 88 | <packing> |
3374 | 89 | <property name="expand">True</property> | ||
3375 | 90 | <property name="fill">True</property> | ||
3376 | 76 | <property name="position">2</property> | 91 | <property name="position">2</property> |
3377 | 77 | </packing> | 92 | </packing> |
3378 | 78 | </child> | 93 | </child> |
3379 | 79 | <child> | 94 | <child> |
3380 | 80 | <object class="GtkVBox" id="vbox1"> | 95 | <object class="GtkVBox" id="vbox1"> |
3381 | 81 | <property name="visible">True</property> | 96 | <property name="visible">True</property> |
3382 | 97 | <property name="can_focus">False</property> | ||
3383 | 82 | <property name="homogeneous">True</property> | 98 | <property name="homogeneous">True</property> |
3384 | 83 | <child> | 99 | <child> |
3385 | 84 | <object class="GtkLabel" id="day1temphigh"> | 100 | <object class="GtkLabel" id="day1temphigh"> |
3386 | 85 | <property name="visible">True</property> | 101 | <property name="visible">True</property> |
3387 | 102 | <property name="can_focus">False</property> | ||
3388 | 86 | <property name="label">High : 23°C</property> | 103 | <property name="label">High : 23°C</property> |
3389 | 87 | </object> | 104 | </object> |
3390 | 88 | <packing> | 105 | <packing> |
3391 | 106 | <property name="expand">True</property> | ||
3392 | 107 | <property name="fill">True</property> | ||
3393 | 89 | <property name="position">0</property> | 108 | <property name="position">0</property> |
3394 | 90 | </packing> | 109 | </packing> |
3395 | 91 | </child> | 110 | </child> |
3396 | 92 | <child> | 111 | <child> |
3397 | 93 | <object class="GtkLabel" id="day1templow"> | 112 | <object class="GtkLabel" id="day1templow"> |
3398 | 94 | <property name="visible">True</property> | 113 | <property name="visible">True</property> |
3399 | 114 | <property name="can_focus">False</property> | ||
3400 | 95 | <property name="label">Low : 19°C</property> | 115 | <property name="label">Low : 19°C</property> |
3401 | 96 | </object> | 116 | </object> |
3402 | 97 | <packing> | 117 | <packing> |
3403 | 118 | <property name="expand">True</property> | ||
3404 | 119 | <property name="fill">True</property> | ||
3405 | 98 | <property name="position">1</property> | 120 | <property name="position">1</property> |
3406 | 99 | </packing> | 121 | </packing> |
3407 | 100 | </child> | 122 | </child> |
3408 | 101 | </object> | 123 | </object> |
3409 | 102 | <packing> | 124 | <packing> |
3410 | 125 | <property name="expand">True</property> | ||
3411 | 126 | <property name="fill">True</property> | ||
3412 | 103 | <property name="position">3</property> | 127 | <property name="position">3</property> |
3413 | 104 | </packing> | 128 | </packing> |
3414 | 105 | </child> | 129 | </child> |
3415 | @@ -107,6 +131,8 @@ | |||
3416 | 107 | </child> | 131 | </child> |
3417 | 108 | </object> | 132 | </object> |
3418 | 109 | <packing> | 133 | <packing> |
3419 | 134 | <property name="expand">True</property> | ||
3420 | 135 | <property name="fill">True</property> | ||
3421 | 110 | <property name="position">0</property> | 136 | <property name="position">0</property> |
3422 | 111 | </packing> | 137 | </packing> |
3423 | 112 | </child> | 138 | </child> |
3424 | @@ -114,45 +140,58 @@ | |||
3425 | 114 | <object class="GtkVSeparator" id="vseparator1"> | 140 | <object class="GtkVSeparator" id="vseparator1"> |
3426 | 115 | <property name="width_request">2</property> | 141 | <property name="width_request">2</property> |
3427 | 116 | <property name="visible">True</property> | 142 | <property name="visible">True</property> |
3428 | 143 | <property name="can_focus">False</property> | ||
3429 | 117 | </object> | 144 | </object> |
3430 | 118 | <packing> | 145 | <packing> |
3431 | 119 | <property name="expand">False</property> | 146 | <property name="expand">False</property> |
3432 | 147 | <property name="fill">True</property> | ||
3433 | 120 | <property name="position">1</property> | 148 | <property name="position">1</property> |
3434 | 121 | </packing> | 149 | </packing> |
3435 | 122 | </child> | 150 | </child> |
3436 | 123 | </object> | 151 | </object> |
3437 | 124 | <packing> | 152 | <packing> |
3438 | 153 | <property name="expand">True</property> | ||
3439 | 154 | <property name="fill">True</property> | ||
3440 | 125 | <property name="position">0</property> | 155 | <property name="position">0</property> |
3441 | 126 | </packing> | 156 | </packing> |
3442 | 127 | </child> | 157 | </child> |
3443 | 128 | <child> | 158 | <child> |
3444 | 129 | <object class="GtkHBox" id="hbox3"> | 159 | <object class="GtkHBox" id="hbox3"> |
3445 | 130 | <property name="visible">True</property> | 160 | <property name="visible">True</property> |
3446 | 161 | <property name="can_focus">False</property> | ||
3447 | 131 | <child> | 162 | <child> |
3448 | 132 | <object class="GtkAlignment" id="alignment2"> | 163 | <object class="GtkAlignment" id="alignment2"> |
3449 | 133 | <property name="visible">True</property> | 164 | <property name="visible">True</property> |
3450 | 165 | <property name="can_focus">False</property> | ||
3451 | 134 | <property name="right_padding">6</property> | 166 | <property name="right_padding">6</property> |
3452 | 135 | <child> | 167 | <child> |
3453 | 136 | <object class="GtkVBox" id="day2vbox"> | 168 | <object class="GtkVBox" id="day2vbox"> |
3454 | 137 | <property name="visible">True</property> | 169 | <property name="visible">True</property> |
3455 | 170 | <property name="can_focus">False</property> | ||
3456 | 138 | <child> | 171 | <child> |
3457 | 139 | <object class="GtkLabel" id="day2lbl"> | 172 | <object class="GtkLabel" id="day2lbl"> |
3458 | 140 | <property name="visible">True</property> | 173 | <property name="visible">True</property> |
3459 | 174 | <property name="can_focus">False</property> | ||
3460 | 141 | <property name="ypad">10</property> | 175 | <property name="ypad">10</property> |
3461 | 142 | <property name="label"><big>Tomorrow (sat.)</big></property> | 176 | <property name="label"><big>Tomorrow (sat.)</big></property> |
3462 | 143 | <property name="use_markup">True</property> | 177 | <property name="use_markup">True</property> |
3463 | 144 | </object> | 178 | </object> |
3464 | 145 | <packing> | 179 | <packing> |
3465 | 180 | <property name="expand">True</property> | ||
3466 | 181 | <property name="fill">True</property> | ||
3467 | 146 | <property name="position">0</property> | 182 | <property name="position">0</property> |
3468 | 147 | </packing> | 183 | </packing> |
3469 | 148 | </child> | 184 | </child> |
3470 | 149 | <child> | 185 | <child> |
3471 | 150 | <object class="GtkImage" id="day2image"> | 186 | <object class="GtkImage" id="day2image"> |
3472 | 151 | <property name="visible">True</property> | 187 | <property name="visible">True</property> |
3473 | 188 | <property name="can_focus">False</property> | ||
3474 | 152 | <property name="pixel_size">50</property> | 189 | <property name="pixel_size">50</property> |
3475 | 153 | <property name="icon_name">weather-storm</property> | 190 | <property name="icon_name">weather-storm</property> |
3476 | 154 | </object> | 191 | </object> |
3477 | 155 | <packing> | 192 | <packing> |
3478 | 193 | <property name="expand">True</property> | ||
3479 | 194 | <property name="fill">True</property> | ||
3480 | 156 | <property name="position">1</property> | 195 | <property name="position">1</property> |
3481 | 157 | </packing> | 196 | </packing> |
3482 | 158 | </child> | 197 | </child> |
3483 | @@ -160,6 +199,7 @@ | |||
3484 | 160 | <object class="GtkLabel" id="day2cond"> | 199 | <object class="GtkLabel" id="day2cond"> |
3485 | 161 | <property name="height_request">80</property> | 200 | <property name="height_request">80</property> |
3486 | 162 | <property name="visible">True</property> | 201 | <property name="visible">True</property> |
3487 | 202 | <property name="can_focus">False</property> | ||
3488 | 163 | <property name="label">Couverture nuageuse partielle</property> | 203 | <property name="label">Couverture nuageuse partielle</property> |
3489 | 164 | <property name="justify">center</property> | 204 | <property name="justify">center</property> |
3490 | 165 | <property name="wrap">True</property> | 205 | <property name="wrap">True</property> |
3491 | @@ -167,33 +207,44 @@ | |||
3492 | 167 | <property name="width_chars">15</property> | 207 | <property name="width_chars">15</property> |
3493 | 168 | </object> | 208 | </object> |
3494 | 169 | <packing> | 209 | <packing> |
3495 | 210 | <property name="expand">True</property> | ||
3496 | 211 | <property name="fill">True</property> | ||
3497 | 170 | <property name="position">2</property> | 212 | <property name="position">2</property> |
3498 | 171 | </packing> | 213 | </packing> |
3499 | 172 | </child> | 214 | </child> |
3500 | 173 | <child> | 215 | <child> |
3501 | 174 | <object class="GtkVBox" id="vbox2"> | 216 | <object class="GtkVBox" id="vbox2"> |
3502 | 175 | <property name="visible">True</property> | 217 | <property name="visible">True</property> |
3503 | 218 | <property name="can_focus">False</property> | ||
3504 | 176 | <property name="homogeneous">True</property> | 219 | <property name="homogeneous">True</property> |
3505 | 177 | <child> | 220 | <child> |
3506 | 178 | <object class="GtkLabel" id="day2temphigh"> | 221 | <object class="GtkLabel" id="day2temphigh"> |
3507 | 179 | <property name="visible">True</property> | 222 | <property name="visible">True</property> |
3508 | 223 | <property name="can_focus">False</property> | ||
3509 | 180 | <property name="label">High : 26°C</property> | 224 | <property name="label">High : 26°C</property> |
3510 | 181 | </object> | 225 | </object> |
3511 | 182 | <packing> | 226 | <packing> |
3512 | 227 | <property name="expand">True</property> | ||
3513 | 228 | <property name="fill">True</property> | ||
3514 | 183 | <property name="position">0</property> | 229 | <property name="position">0</property> |
3515 | 184 | </packing> | 230 | </packing> |
3516 | 185 | </child> | 231 | </child> |
3517 | 186 | <child> | 232 | <child> |
3518 | 187 | <object class="GtkLabel" id="day2templow"> | 233 | <object class="GtkLabel" id="day2templow"> |
3519 | 188 | <property name="visible">True</property> | 234 | <property name="visible">True</property> |
3520 | 235 | <property name="can_focus">False</property> | ||
3521 | 189 | <property name="label">Low : 16°C</property> | 236 | <property name="label">Low : 16°C</property> |
3522 | 190 | </object> | 237 | </object> |
3523 | 191 | <packing> | 238 | <packing> |
3524 | 239 | <property name="expand">True</property> | ||
3525 | 240 | <property name="fill">True</property> | ||
3526 | 192 | <property name="position">1</property> | 241 | <property name="position">1</property> |
3527 | 193 | </packing> | 242 | </packing> |
3528 | 194 | </child> | 243 | </child> |
3529 | 195 | </object> | 244 | </object> |
3530 | 196 | <packing> | 245 | <packing> |
3531 | 246 | <property name="expand">True</property> | ||
3532 | 247 | <property name="fill">True</property> | ||
3533 | 197 | <property name="position">3</property> | 248 | <property name="position">3</property> |
3534 | 198 | </packing> | 249 | </packing> |
3535 | 199 | </child> | 250 | </child> |
3536 | @@ -201,6 +252,8 @@ | |||
3537 | 201 | </child> | 252 | </child> |
3538 | 202 | </object> | 253 | </object> |
3539 | 203 | <packing> | 254 | <packing> |
3540 | 255 | <property name="expand">True</property> | ||
3541 | 256 | <property name="fill">True</property> | ||
3542 | 204 | <property name="position">0</property> | 257 | <property name="position">0</property> |
3543 | 205 | </packing> | 258 | </packing> |
3544 | 206 | </child> | 259 | </child> |
3545 | @@ -208,47 +261,58 @@ | |||
3546 | 208 | <object class="GtkVSeparator" id="vseparator2"> | 261 | <object class="GtkVSeparator" id="vseparator2"> |
3547 | 209 | <property name="width_request">2</property> | 262 | <property name="width_request">2</property> |
3548 | 210 | <property name="visible">True</property> | 263 | <property name="visible">True</property> |
3549 | 264 | <property name="can_focus">False</property> | ||
3550 | 211 | </object> | 265 | </object> |
3551 | 212 | <packing> | 266 | <packing> |
3552 | 213 | <property name="expand">False</property> | 267 | <property name="expand">False</property> |
3553 | 268 | <property name="fill">True</property> | ||
3554 | 214 | <property name="position">1</property> | 269 | <property name="position">1</property> |
3555 | 215 | </packing> | 270 | </packing> |
3556 | 216 | </child> | 271 | </child> |
3557 | 217 | </object> | 272 | </object> |
3558 | 218 | <packing> | 273 | <packing> |
3559 | 274 | <property name="expand">True</property> | ||
3560 | 275 | <property name="fill">True</property> | ||
3561 | 219 | <property name="position">1</property> | 276 | <property name="position">1</property> |
3562 | 220 | </packing> | 277 | </packing> |
3563 | 221 | </child> | 278 | </child> |
3564 | 222 | <child> | 279 | <child> |
3565 | 223 | <object class="GtkHBox" id="hbox4"> | 280 | <object class="GtkHBox" id="hbox4"> |
3566 | 224 | <property name="visible">True</property> | 281 | <property name="visible">True</property> |
3567 | 282 | <property name="can_focus">False</property> | ||
3568 | 225 | <child> | 283 | <child> |
3569 | 226 | <object class="GtkAlignment" id="alignment4"> | 284 | <object class="GtkAlignment" id="alignment4"> |
3570 | 227 | <property name="visible">True</property> | 285 | <property name="visible">True</property> |
3571 | 286 | <property name="can_focus">False</property> | ||
3572 | 228 | <property name="right_padding">6</property> | 287 | <property name="right_padding">6</property> |
3573 | 229 | <child> | 288 | <child> |
3574 | 230 | <object class="GtkVBox" id="day3vbox"> | 289 | <object class="GtkVBox" id="day3vbox"> |
3575 | 231 | <property name="visible">True</property> | 290 | <property name="visible">True</property> |
3576 | 291 | <property name="can_focus">False</property> | ||
3577 | 232 | <child> | 292 | <child> |
3578 | 233 | <object class="GtkLabel" id="day3lbl"> | 293 | <object class="GtkLabel" id="day3lbl"> |
3579 | 234 | <property name="visible">True</property> | 294 | <property name="visible">True</property> |
3580 | 295 | <property name="can_focus">False</property> | ||
3581 | 235 | <property name="ypad">10</property> | 296 | <property name="ypad">10</property> |
3582 | 236 | <property name="label"><big>Sunday</big></property> | 297 | <property name="label"><big>Sunday</big></property> |
3583 | 237 | <property name="use_markup">True</property> | 298 | <property name="use_markup">True</property> |
3584 | 238 | </object> | 299 | </object> |
3585 | 239 | <packing> | 300 | <packing> |
3586 | 240 | <property name="expand">False</property> | 301 | <property name="expand">False</property> |
3587 | 302 | <property name="fill">True</property> | ||
3588 | 241 | <property name="position">0</property> | 303 | <property name="position">0</property> |
3589 | 242 | </packing> | 304 | </packing> |
3590 | 243 | </child> | 305 | </child> |
3591 | 244 | <child> | 306 | <child> |
3592 | 245 | <object class="GtkImage" id="day3image"> | 307 | <object class="GtkImage" id="day3image"> |
3593 | 246 | <property name="visible">True</property> | 308 | <property name="visible">True</property> |
3594 | 309 | <property name="can_focus">False</property> | ||
3595 | 247 | <property name="pixel_size">50</property> | 310 | <property name="pixel_size">50</property> |
3596 | 248 | <property name="icon_name">weather-fog</property> | 311 | <property name="icon_name">weather-fog</property> |
3597 | 249 | </object> | 312 | </object> |
3598 | 250 | <packing> | 313 | <packing> |
3599 | 251 | <property name="expand">False</property> | 314 | <property name="expand">False</property> |
3600 | 315 | <property name="fill">True</property> | ||
3601 | 252 | <property name="position">1</property> | 316 | <property name="position">1</property> |
3602 | 253 | </packing> | 317 | </packing> |
3603 | 254 | </child> | 318 | </child> |
3604 | @@ -256,6 +320,7 @@ | |||
3605 | 256 | <object class="GtkLabel" id="day3cond"> | 320 | <object class="GtkLabel" id="day3cond"> |
3606 | 257 | <property name="height_request">80</property> | 321 | <property name="height_request">80</property> |
3607 | 258 | <property name="visible">True</property> | 322 | <property name="visible">True</property> |
3608 | 323 | <property name="can_focus">False</property> | ||
3609 | 259 | <property name="label">Fogs</property> | 324 | <property name="label">Fogs</property> |
3610 | 260 | <property name="justify">center</property> | 325 | <property name="justify">center</property> |
3611 | 261 | <property name="wrap">True</property> | 326 | <property name="wrap">True</property> |
3612 | @@ -263,32 +328,43 @@ | |||
3613 | 263 | <property name="width_chars">15</property> | 328 | <property name="width_chars">15</property> |
3614 | 264 | </object> | 329 | </object> |
3615 | 265 | <packing> | 330 | <packing> |
3616 | 331 | <property name="expand">True</property> | ||
3617 | 332 | <property name="fill">True</property> | ||
3618 | 266 | <property name="position">2</property> | 333 | <property name="position">2</property> |
3619 | 267 | </packing> | 334 | </packing> |
3620 | 268 | </child> | 335 | </child> |
3621 | 269 | <child> | 336 | <child> |
3622 | 270 | <object class="GtkVBox" id="vbox3"> | 337 | <object class="GtkVBox" id="vbox3"> |
3623 | 271 | <property name="visible">True</property> | 338 | <property name="visible">True</property> |
3624 | 339 | <property name="can_focus">False</property> | ||
3625 | 272 | <child> | 340 | <child> |
3626 | 273 | <object class="GtkLabel" id="day3temphigh"> | 341 | <object class="GtkLabel" id="day3temphigh"> |
3627 | 274 | <property name="visible">True</property> | 342 | <property name="visible">True</property> |
3628 | 343 | <property name="can_focus">False</property> | ||
3629 | 275 | <property name="label">High : 28°C</property> | 344 | <property name="label">High : 28°C</property> |
3630 | 276 | </object> | 345 | </object> |
3631 | 277 | <packing> | 346 | <packing> |
3632 | 347 | <property name="expand">True</property> | ||
3633 | 348 | <property name="fill">True</property> | ||
3634 | 278 | <property name="position">0</property> | 349 | <property name="position">0</property> |
3635 | 279 | </packing> | 350 | </packing> |
3636 | 280 | </child> | 351 | </child> |
3637 | 281 | <child> | 352 | <child> |
3638 | 282 | <object class="GtkLabel" id="day3templow"> | 353 | <object class="GtkLabel" id="day3templow"> |
3639 | 283 | <property name="visible">True</property> | 354 | <property name="visible">True</property> |
3640 | 355 | <property name="can_focus">False</property> | ||
3641 | 284 | <property name="label">Low : 16°C</property> | 356 | <property name="label">Low : 16°C</property> |
3642 | 285 | </object> | 357 | </object> |
3643 | 286 | <packing> | 358 | <packing> |
3644 | 359 | <property name="expand">True</property> | ||
3645 | 360 | <property name="fill">True</property> | ||
3646 | 287 | <property name="position">1</property> | 361 | <property name="position">1</property> |
3647 | 288 | </packing> | 362 | </packing> |
3648 | 289 | </child> | 363 | </child> |
3649 | 290 | </object> | 364 | </object> |
3650 | 291 | <packing> | 365 | <packing> |
3651 | 366 | <property name="expand">True</property> | ||
3652 | 367 | <property name="fill">True</property> | ||
3653 | 292 | <property name="position">3</property> | 368 | <property name="position">3</property> |
3654 | 293 | </packing> | 369 | </packing> |
3655 | 294 | </child> | 370 | </child> |
3656 | @@ -296,50 +372,65 @@ | |||
3657 | 296 | </child> | 372 | </child> |
3658 | 297 | </object> | 373 | </object> |
3659 | 298 | <packing> | 374 | <packing> |
3660 | 375 | <property name="expand">True</property> | ||
3661 | 376 | <property name="fill">True</property> | ||
3662 | 299 | <property name="position">0</property> | 377 | <property name="position">0</property> |
3663 | 300 | </packing> | 378 | </packing> |
3664 | 301 | </child> | 379 | </child> |
3665 | 302 | <child> | 380 | <child> |
3666 | 303 | <object class="GtkVSeparator" id="vseparator3"> | 381 | <object class="GtkVSeparator" id="vseparator3"> |
3667 | 304 | <property name="visible">True</property> | 382 | <property name="visible">True</property> |
3668 | 383 | <property name="can_focus">False</property> | ||
3669 | 305 | </object> | 384 | </object> |
3670 | 306 | <packing> | 385 | <packing> |
3671 | 307 | <property name="expand">False</property> | 386 | <property name="expand">False</property> |
3672 | 387 | <property name="fill">True</property> | ||
3673 | 308 | <property name="position">1</property> | 388 | <property name="position">1</property> |
3674 | 309 | </packing> | 389 | </packing> |
3675 | 310 | </child> | 390 | </child> |
3676 | 311 | </object> | 391 | </object> |
3677 | 312 | <packing> | 392 | <packing> |
3678 | 393 | <property name="expand">True</property> | ||
3679 | 394 | <property name="fill">True</property> | ||
3680 | 313 | <property name="position">2</property> | 395 | <property name="position">2</property> |
3681 | 314 | </packing> | 396 | </packing> |
3682 | 315 | </child> | 397 | </child> |
3683 | 316 | <child> | 398 | <child> |
3684 | 317 | <object class="GtkHBox" id="hbox5"> | 399 | <object class="GtkHBox" id="hbox5"> |
3685 | 318 | <property name="visible">True</property> | 400 | <property name="visible">True</property> |
3686 | 401 | <property name="can_focus">False</property> | ||
3687 | 319 | <child> | 402 | <child> |
3688 | 320 | <object class="GtkAlignment" id="alignment5"> | 403 | <object class="GtkAlignment" id="alignment5"> |
3689 | 321 | <property name="visible">True</property> | 404 | <property name="visible">True</property> |
3690 | 405 | <property name="can_focus">False</property> | ||
3691 | 322 | <child> | 406 | <child> |
3692 | 323 | <object class="GtkVBox" id="day4vbox"> | 407 | <object class="GtkVBox" id="day4vbox"> |
3693 | 324 | <property name="visible">True</property> | 408 | <property name="visible">True</property> |
3694 | 409 | <property name="can_focus">False</property> | ||
3695 | 325 | <child> | 410 | <child> |
3696 | 326 | <object class="GtkLabel" id="day4lbl"> | 411 | <object class="GtkLabel" id="day4lbl"> |
3697 | 327 | <property name="visible">True</property> | 412 | <property name="visible">True</property> |
3698 | 413 | <property name="can_focus">False</property> | ||
3699 | 328 | <property name="ypad">10</property> | 414 | <property name="ypad">10</property> |
3700 | 329 | <property name="label"><big>Monday</big></property> | 415 | <property name="label"><big>Monday</big></property> |
3701 | 330 | <property name="use_markup">True</property> | 416 | <property name="use_markup">True</property> |
3702 | 331 | </object> | 417 | </object> |
3703 | 332 | <packing> | 418 | <packing> |
3704 | 419 | <property name="expand">True</property> | ||
3705 | 420 | <property name="fill">True</property> | ||
3706 | 333 | <property name="position">0</property> | 421 | <property name="position">0</property> |
3707 | 334 | </packing> | 422 | </packing> |
3708 | 335 | </child> | 423 | </child> |
3709 | 336 | <child> | 424 | <child> |
3710 | 337 | <object class="GtkImage" id="day4image"> | 425 | <object class="GtkImage" id="day4image"> |
3711 | 338 | <property name="visible">True</property> | 426 | <property name="visible">True</property> |
3712 | 427 | <property name="can_focus">False</property> | ||
3713 | 339 | <property name="pixel_size">50</property> | 428 | <property name="pixel_size">50</property> |
3714 | 340 | <property name="icon_name">weather-clear</property> | 429 | <property name="icon_name">weather-clear</property> |
3715 | 341 | </object> | 430 | </object> |
3716 | 342 | <packing> | 431 | <packing> |
3717 | 432 | <property name="expand">True</property> | ||
3718 | 433 | <property name="fill">True</property> | ||
3719 | 343 | <property name="position">1</property> | 434 | <property name="position">1</property> |
3720 | 344 | </packing> | 435 | </packing> |
3721 | 345 | </child> | 436 | </child> |
3722 | @@ -347,6 +438,7 @@ | |||
3723 | 347 | <object class="GtkLabel" id="day4cond"> | 438 | <object class="GtkLabel" id="day4cond"> |
3724 | 348 | <property name="height_request">80</property> | 439 | <property name="height_request">80</property> |
3725 | 349 | <property name="visible">True</property> | 440 | <property name="visible">True</property> |
3726 | 441 | <property name="can_focus">False</property> | ||
3727 | 350 | <property name="label">Clear</property> | 442 | <property name="label">Clear</property> |
3728 | 351 | <property name="justify">center</property> | 443 | <property name="justify">center</property> |
3729 | 352 | <property name="wrap">True</property> | 444 | <property name="wrap">True</property> |
3730 | @@ -354,32 +446,43 @@ | |||
3731 | 354 | <property name="width_chars">15</property> | 446 | <property name="width_chars">15</property> |
3732 | 355 | </object> | 447 | </object> |
3733 | 356 | <packing> | 448 | <packing> |
3734 | 449 | <property name="expand">True</property> | ||
3735 | 450 | <property name="fill">True</property> | ||
3736 | 357 | <property name="position">2</property> | 451 | <property name="position">2</property> |
3737 | 358 | </packing> | 452 | </packing> |
3738 | 359 | </child> | 453 | </child> |
3739 | 360 | <child> | 454 | <child> |
3740 | 361 | <object class="GtkVBox" id="vbox4"> | 455 | <object class="GtkVBox" id="vbox4"> |
3741 | 362 | <property name="visible">True</property> | 456 | <property name="visible">True</property> |
3742 | 457 | <property name="can_focus">False</property> | ||
3743 | 363 | <child> | 458 | <child> |
3744 | 364 | <object class="GtkLabel" id="day4temphigh"> | 459 | <object class="GtkLabel" id="day4temphigh"> |
3745 | 365 | <property name="visible">True</property> | 460 | <property name="visible">True</property> |
3746 | 461 | <property name="can_focus">False</property> | ||
3747 | 366 | <property name="label">High : 26°C</property> | 462 | <property name="label">High : 26°C</property> |
3748 | 367 | </object> | 463 | </object> |
3749 | 368 | <packing> | 464 | <packing> |
3750 | 465 | <property name="expand">True</property> | ||
3751 | 466 | <property name="fill">True</property> | ||
3752 | 369 | <property name="position">0</property> | 467 | <property name="position">0</property> |
3753 | 370 | </packing> | 468 | </packing> |
3754 | 371 | </child> | 469 | </child> |
3755 | 372 | <child> | 470 | <child> |
3756 | 373 | <object class="GtkLabel" id="day4templow"> | 471 | <object class="GtkLabel" id="day4templow"> |
3757 | 374 | <property name="visible">True</property> | 472 | <property name="visible">True</property> |
3758 | 473 | <property name="can_focus">False</property> | ||
3759 | 375 | <property name="label">Low : 14°C</property> | 474 | <property name="label">Low : 14°C</property> |
3760 | 376 | </object> | 475 | </object> |
3761 | 377 | <packing> | 476 | <packing> |
3762 | 477 | <property name="expand">True</property> | ||
3763 | 478 | <property name="fill">True</property> | ||
3764 | 378 | <property name="position">1</property> | 479 | <property name="position">1</property> |
3765 | 379 | </packing> | 480 | </packing> |
3766 | 380 | </child> | 481 | </child> |
3767 | 381 | </object> | 482 | </object> |
3768 | 382 | <packing> | 483 | <packing> |
3769 | 484 | <property name="expand">True</property> | ||
3770 | 485 | <property name="fill">True</property> | ||
3771 | 383 | <property name="position">3</property> | 486 | <property name="position">3</property> |
3772 | 384 | </packing> | 487 | </packing> |
3773 | 385 | </child> | 488 | </child> |
3774 | @@ -387,16 +490,21 @@ | |||
3775 | 387 | </child> | 490 | </child> |
3776 | 388 | </object> | 491 | </object> |
3777 | 389 | <packing> | 492 | <packing> |
3778 | 493 | <property name="expand">True</property> | ||
3779 | 494 | <property name="fill">True</property> | ||
3780 | 390 | <property name="position">0</property> | 495 | <property name="position">0</property> |
3781 | 391 | </packing> | 496 | </packing> |
3782 | 392 | </child> | 497 | </child> |
3783 | 393 | </object> | 498 | </object> |
3784 | 394 | <packing> | 499 | <packing> |
3785 | 500 | <property name="expand">True</property> | ||
3786 | 501 | <property name="fill">True</property> | ||
3787 | 395 | <property name="position">3</property> | 502 | <property name="position">3</property> |
3788 | 396 | </packing> | 503 | </packing> |
3789 | 397 | </child> | 504 | </child> |
3790 | 398 | </object> | 505 | </object> |
3791 | 399 | <packing> | 506 | <packing> |
3792 | 507 | <property name="expand">True</property> | ||
3793 | 400 | <property name="fill">False</property> | 508 | <property name="fill">False</property> |
3794 | 401 | <property name="position">1</property> | 509 | <property name="position">1</property> |
3795 | 402 | </packing> | 510 | </packing> |
3796 | @@ -404,26 +512,31 @@ | |||
3797 | 404 | <child> | 512 | <child> |
3798 | 405 | <object class="GtkHSeparator" id="hseparator1"> | 513 | <object class="GtkHSeparator" id="hseparator1"> |
3799 | 406 | <property name="visible">True</property> | 514 | <property name="visible">True</property> |
3800 | 515 | <property name="can_focus">False</property> | ||
3801 | 407 | </object> | 516 | </object> |
3802 | 408 | <packing> | 517 | <packing> |
3803 | 409 | <property name="expand">False</property> | 518 | <property name="expand">False</property> |
3804 | 519 | <property name="fill">True</property> | ||
3805 | 410 | <property name="position">2</property> | 520 | <property name="position">2</property> |
3806 | 411 | </packing> | 521 | </packing> |
3807 | 412 | </child> | 522 | </child> |
3808 | 413 | <child> | 523 | <child> |
3809 | 414 | <object class="GtkAlignment" id="alignment1"> | 524 | <object class="GtkAlignment" id="alignment1"> |
3810 | 415 | <property name="visible">True</property> | 525 | <property name="visible">True</property> |
3811 | 526 | <property name="can_focus">False</property> | ||
3812 | 416 | <property name="xalign">1</property> | 527 | <property name="xalign">1</property> |
3813 | 417 | <child> | 528 | <child> |
3814 | 418 | <object class="GtkVButtonBox" id="hbuttonbox1"> | 529 | <object class="GtkVButtonBox" id="hbuttonbox1"> |
3815 | 419 | <property name="visible">True</property> | 530 | <property name="visible">True</property> |
3816 | 531 | <property name="can_focus">False</property> | ||
3817 | 420 | <child> | 532 | <child> |
3818 | 421 | <object class="GtkButton" id="closebtn"> | 533 | <object class="GtkButton" id="closebtn"> |
3819 | 422 | <property name="label">gtk-close</property> | 534 | <property name="label">gtk-close</property> |
3820 | 423 | <property name="visible">True</property> | 535 | <property name="visible">True</property> |
3821 | 536 | <property name="can_focus">False</property> | ||
3822 | 424 | <property name="receives_default">True</property> | 537 | <property name="receives_default">True</property> |
3823 | 425 | <property name="use_stock">True</property> | 538 | <property name="use_stock">True</property> |
3825 | 426 | <signal name="clicked" handler="close"/> | 539 | <signal name="clicked" handler="close" swapped="no"/> |
3826 | 427 | </object> | 540 | </object> |
3827 | 428 | <packing> | 541 | <packing> |
3828 | 429 | <property name="expand">False</property> | 542 | <property name="expand">False</property> |
3829 | @@ -435,6 +548,8 @@ | |||
3830 | 435 | </child> | 548 | </child> |
3831 | 436 | </object> | 549 | </object> |
3832 | 437 | <packing> | 550 | <packing> |
3833 | 551 | <property name="expand">True</property> | ||
3834 | 552 | <property name="fill">True</property> | ||
3835 | 438 | <property name="position">3</property> | 553 | <property name="position">3</property> |
3836 | 439 | </packing> | 554 | </packing> |
3837 | 440 | </child> | 555 | </child> |
3838 | 441 | 556 | ||
3839 | === modified file 'data/ui/PreferencesDialog.ui' | |||
3840 | --- data/ui/PreferencesDialog.ui 2012-03-12 04:53:24 +0000 | |||
3841 | +++ data/ui/PreferencesDialog.ui 2013-05-22 05:08:27 +0000 | |||
3842 | @@ -1,19 +1,25 @@ | |||
3843 | 1 | <?xml version="1.0" encoding="UTF-8"?> | 1 | <?xml version="1.0" encoding="UTF-8"?> |
3844 | 2 | <interface> | 2 | <interface> |
3846 | 3 | <requires lib="gtk+" version="2.16"/> | 3 | <!-- interface-requires gtk+ 3.0 --> |
3847 | 4 | <!-- interface-requires preferences_dialog 1.0 --> | 4 | <!-- interface-requires preferences_dialog 1.0 --> |
3848 | 5 | <!-- interface-naming-policy project-wide --> | ||
3849 | 6 | <object class="GtkListStore" id="citieslist"> | 5 | <object class="GtkListStore" id="citieslist"> |
3850 | 7 | <columns> | 6 | <columns> |
3851 | 8 | <!-- column-name Label --> | 7 | <!-- column-name Label --> |
3852 | 9 | <column type="gchararray"/> | 8 | <column type="gchararray"/> |
3853 | 10 | <!-- column-name City --> | 9 | <!-- column-name City --> |
3854 | 11 | <column type="gchararray"/> | 10 | <column type="gchararray"/> |
3856 | 12 | <!-- column-name Location Details --> | 11 | <!-- column-name Location --> |
3857 | 13 | <column type="gchararray"/> | 12 | <column type="gchararray"/> |
3858 | 14 | </columns> | 13 | </columns> |
3859 | 15 | </object> | 14 | </object> |
3860 | 15 | <object class="GtkAdjustment" id="rate"> | ||
3861 | 16 | <property name="lower">1</property> | ||
3862 | 17 | <property name="upper">30</property> | ||
3863 | 18 | <property name="step_increment">1</property> | ||
3864 | 19 | <property name="page_increment">10</property> | ||
3865 | 20 | </object> | ||
3866 | 16 | <object class="PreferencesDialog" id="preferences_dialog"> | 21 | <object class="PreferencesDialog" id="preferences_dialog"> |
3867 | 22 | <property name="can_focus">False</property> | ||
3868 | 17 | <property name="border_width">12</property> | 23 | <property name="border_width">12</property> |
3869 | 18 | <property name="title" translatable="yes">Weather Indicator Preferences</property> | 24 | <property name="title" translatable="yes">Weather Indicator Preferences</property> |
3870 | 19 | <property name="window_position">mouse</property> | 25 | <property name="window_position">mouse</property> |
3871 | @@ -22,62 +28,118 @@ | |||
3872 | 22 | <property name="icon">../media/icon.png</property> | 28 | <property name="icon">../media/icon.png</property> |
3873 | 23 | <property name="type_hint">normal</property> | 29 | <property name="type_hint">normal</property> |
3874 | 24 | <child internal-child="vbox"> | 30 | <child internal-child="vbox"> |
3876 | 25 | <object class="GtkVBox" id="dialog-vbox1"> | 31 | <object class="GtkBox" id="dialog-vbox1"> |
3877 | 26 | <property name="visible">True</property> | 32 | <property name="visible">True</property> |
3878 | 33 | <property name="can_focus">False</property> | ||
3879 | 34 | <property name="orientation">vertical</property> | ||
3880 | 27 | <property name="spacing">6</property> | 35 | <property name="spacing">6</property> |
3881 | 36 | <child internal-child="action_area"> | ||
3882 | 37 | <object class="GtkButtonBox" id="dialog-action_area1"> | ||
3883 | 38 | <property name="visible">True</property> | ||
3884 | 39 | <property name="can_focus">False</property> | ||
3885 | 40 | <property name="layout_style">end</property> | ||
3886 | 41 | <child> | ||
3887 | 42 | <object class="GtkButton" id="cancel_button"> | ||
3888 | 43 | <property name="label">gtk-cancel</property> | ||
3889 | 44 | <property name="visible">True</property> | ||
3890 | 45 | <property name="can_focus">False</property> | ||
3891 | 46 | <property name="receives_default">True</property> | ||
3892 | 47 | <property name="use_stock">True</property> | ||
3893 | 48 | <signal name="clicked" handler="cancel" swapped="no"/> | ||
3894 | 49 | </object> | ||
3895 | 50 | <packing> | ||
3896 | 51 | <property name="expand">False</property> | ||
3897 | 52 | <property name="fill">False</property> | ||
3898 | 53 | <property name="position">0</property> | ||
3899 | 54 | </packing> | ||
3900 | 55 | </child> | ||
3901 | 56 | <child> | ||
3902 | 57 | <object class="GtkButton" id="ok_button"> | ||
3903 | 58 | <property name="label">gtk-ok</property> | ||
3904 | 59 | <property name="visible">True</property> | ||
3905 | 60 | <property name="sensitive">False</property> | ||
3906 | 61 | <property name="can_focus">False</property> | ||
3907 | 62 | <property name="receives_default">True</property> | ||
3908 | 63 | <property name="use_stock">True</property> | ||
3909 | 64 | <signal name="clicked" handler="ok" swapped="no"/> | ||
3910 | 65 | </object> | ||
3911 | 66 | <packing> | ||
3912 | 67 | <property name="expand">False</property> | ||
3913 | 68 | <property name="fill">False</property> | ||
3914 | 69 | <property name="position">1</property> | ||
3915 | 70 | </packing> | ||
3916 | 71 | </child> | ||
3917 | 72 | </object> | ||
3918 | 73 | <packing> | ||
3919 | 74 | <property name="expand">False</property> | ||
3920 | 75 | <property name="fill">False</property> | ||
3921 | 76 | <property name="pack_type">end</property> | ||
3922 | 77 | <property name="position">0</property> | ||
3923 | 78 | </packing> | ||
3924 | 79 | </child> | ||
3925 | 28 | <child> | 80 | <child> |
3926 | 29 | <object class="GtkNotebook" id="notebook1"> | 81 | <object class="GtkNotebook" id="notebook1"> |
3927 | 30 | <property name="visible">True</property> | 82 | <property name="visible">True</property> |
3928 | 31 | <property name="can_focus">True</property> | 83 | <property name="can_focus">True</property> |
3929 | 32 | <child> | 84 | <child> |
3931 | 33 | <object class="GtkVBox" id="vboxpreferences"> | 85 | <object class="GtkBox" id="vboxpreferences"> |
3932 | 34 | <property name="visible">True</property> | 86 | <property name="visible">True</property> |
3933 | 87 | <property name="can_focus">False</property> | ||
3934 | 35 | <property name="border_width">12</property> | 88 | <property name="border_width">12</property> |
3935 | 89 | <property name="orientation">vertical</property> | ||
3936 | 36 | <property name="spacing">12</property> | 90 | <property name="spacing">12</property> |
3937 | 37 | <child> | 91 | <child> |
3939 | 38 | <object class="GtkVBox" id="vbox10"> | 92 | <object class="GtkBox" id="vbox10"> |
3940 | 39 | <property name="visible">True</property> | 93 | <property name="visible">True</property> |
3941 | 94 | <property name="can_focus">False</property> | ||
3942 | 95 | <property name="orientation">vertical</property> | ||
3943 | 40 | <property name="homogeneous">True</property> | 96 | <property name="homogeneous">True</property> |
3944 | 41 | <child> | 97 | <child> |
3945 | 42 | <object class="GtkCheckButton" id="enableindicator"> | 98 | <object class="GtkCheckButton" id="enableindicator"> |
3946 | 43 | <property name="label" translatable="yes">Enable the Weather Indicator Applet</property> | 99 | <property name="label" translatable="yes">Enable the Weather Indicator Applet</property> |
3947 | 44 | <property name="can_focus">True</property> | 100 | <property name="can_focus">True</property> |
3948 | 45 | <property name="receives_default">False</property> | 101 | <property name="receives_default">False</property> |
3950 | 46 | <property name="xalign">0.02</property> | 102 | <property name="xalign">0.019999999552965164</property> |
3951 | 47 | <property name="active">True</property> | 103 | <property name="active">True</property> |
3952 | 48 | <property name="draw_indicator">True</property> | 104 | <property name="draw_indicator">True</property> |
3953 | 49 | </object> | 105 | </object> |
3954 | 50 | <packing> | 106 | <packing> |
3955 | 51 | <property name="expand">False</property> | 107 | <property name="expand">False</property> |
3956 | 108 | <property name="fill">True</property> | ||
3957 | 52 | <property name="position">0</property> | 109 | <property name="position">0</property> |
3958 | 53 | </packing> | 110 | </packing> |
3959 | 54 | </child> | 111 | </child> |
3960 | 55 | <child> | 112 | <child> |
3961 | 56 | <object class="GtkCheckButton" id="show_label"> | 113 | <object class="GtkCheckButton" id="show_label"> |
3962 | 57 | <property name="visible">True</property> | ||
3963 | 58 | <property name="label" translatable="yes">Show temperature near indicator</property> | 114 | <property name="label" translatable="yes">Show temperature near indicator</property> |
3964 | 115 | <property name="visible">True</property> | ||
3965 | 59 | <property name="can_focus">True</property> | 116 | <property name="can_focus">True</property> |
3966 | 60 | <property name="receives_default">False</property> | 117 | <property name="receives_default">False</property> |
3967 | 118 | <property name="xalign">0</property> | ||
3968 | 61 | <property name="draw_indicator">True</property> | 119 | <property name="draw_indicator">True</property> |
3969 | 62 | </object> | 120 | </object> |
3970 | 63 | <packing> | 121 | <packing> |
3971 | 64 | <property name="expand">False</property> | 122 | <property name="expand">False</property> |
3972 | 123 | <property name="fill">True</property> | ||
3973 | 65 | <property name="position">1</property> | 124 | <property name="position">1</property> |
3974 | 66 | </packing> | 125 | </packing> |
3975 | 67 | </child> | 126 | </child> |
3976 | 68 | <child> | 127 | <child> |
3978 | 69 | <object class="GtkHBox" id="hbox_updateevery"> | 128 | <object class="GtkBox" id="hbox_updateevery"> |
3979 | 70 | <property name="visible">True</property> | 129 | <property name="visible">True</property> |
3980 | 130 | <property name="can_focus">False</property> | ||
3981 | 71 | <property name="spacing">6</property> | 131 | <property name="spacing">6</property> |
3982 | 72 | <child> | 132 | <child> |
3983 | 73 | <object class="GtkLabel" id="updateevery"> | 133 | <object class="GtkLabel" id="updateevery"> |
3984 | 74 | <property name="visible">True</property> | 134 | <property name="visible">True</property> |
3985 | 135 | <property name="can_focus">False</property> | ||
3986 | 75 | <property name="xalign">1</property> | 136 | <property name="xalign">1</property> |
3987 | 76 | <property name="label" translatable="yes">Update every</property> | 137 | <property name="label" translatable="yes">Update every</property> |
3988 | 77 | <property name="use_markup">True</property> | 138 | <property name="use_markup">True</property> |
3989 | 78 | </object> | 139 | </object> |
3990 | 79 | <packing> | 140 | <packing> |
3991 | 80 | <property name="expand">False</property> | 141 | <property name="expand">False</property> |
3992 | 142 | <property name="fill">True</property> | ||
3993 | 81 | <property name="position">0</property> | 143 | <property name="position">0</property> |
3994 | 82 | </packing> | 144 | </packing> |
3995 | 83 | </child> | 145 | </child> |
3996 | @@ -86,6 +148,7 @@ | |||
3997 | 86 | <property name="visible">True</property> | 148 | <property name="visible">True</property> |
3998 | 87 | <property name="can_focus">True</property> | 149 | <property name="can_focus">True</property> |
3999 | 88 | <property name="invisible_char">•</property> | 150 | <property name="invisible_char">•</property> |
4000 | 151 | <property name="invisible_char_set">True</property> | ||
4001 | 89 | <property name="adjustment">rate</property> | 152 | <property name="adjustment">rate</property> |
4002 | 90 | </object> | 153 | </object> |
4003 | 91 | <packing> | 154 | <packing> |
4004 | @@ -97,31 +160,39 @@ | |||
4005 | 97 | <child> | 160 | <child> |
4006 | 98 | <object class="GtkLabel" id="label4"> | 161 | <object class="GtkLabel" id="label4"> |
4007 | 99 | <property name="visible">True</property> | 162 | <property name="visible">True</property> |
4008 | 163 | <property name="can_focus">False</property> | ||
4009 | 100 | <property name="xalign">0</property> | 164 | <property name="xalign">0</property> |
4010 | 101 | <property name="label" translatable="yes">minutes</property> | 165 | <property name="label" translatable="yes">minutes</property> |
4011 | 102 | </object> | 166 | </object> |
4012 | 103 | <packing> | 167 | <packing> |
4013 | 104 | <property name="expand">False</property> | 168 | <property name="expand">False</property> |
4014 | 169 | <property name="fill">True</property> | ||
4015 | 105 | <property name="position">2</property> | 170 | <property name="position">2</property> |
4016 | 106 | </packing> | 171 | </packing> |
4017 | 107 | </child> | 172 | </child> |
4018 | 108 | </object> | 173 | </object> |
4019 | 109 | <packing> | 174 | <packing> |
4020 | 175 | <property name="expand">True</property> | ||
4021 | 176 | <property name="fill">True</property> | ||
4022 | 110 | <property name="position">2</property> | 177 | <property name="position">2</property> |
4023 | 111 | </packing> | 178 | </packing> |
4024 | 112 | </child> | 179 | </child> |
4025 | 113 | </object> | 180 | </object> |
4026 | 114 | <packing> | 181 | <packing> |
4027 | 115 | <property name="expand">False</property> | 182 | <property name="expand">False</property> |
4028 | 183 | <property name="fill">True</property> | ||
4029 | 116 | <property name="position">0</property> | 184 | <property name="position">0</property> |
4030 | 117 | </packing> | 185 | </packing> |
4031 | 118 | </child> | 186 | </child> |
4032 | 119 | <child> | 187 | <child> |
4034 | 120 | <object class="GtkVBox" id="vbox1"> | 188 | <object class="GtkBox" id="vbox1"> |
4035 | 121 | <property name="visible">True</property> | 189 | <property name="visible">True</property> |
4036 | 190 | <property name="can_focus">False</property> | ||
4037 | 191 | <property name="orientation">vertical</property> | ||
4038 | 122 | <child> | 192 | <child> |
4039 | 123 | <object class="GtkLabel" id="notificationslabel"> | 193 | <object class="GtkLabel" id="notificationslabel"> |
4040 | 124 | <property name="visible">True</property> | 194 | <property name="visible">True</property> |
4041 | 195 | <property name="can_focus">False</property> | ||
4042 | 125 | <property name="xalign">0</property> | 196 | <property name="xalign">0</property> |
4043 | 126 | <property name="ypad">3</property> | 197 | <property name="ypad">3</property> |
4044 | 127 | <property name="label" translatable="yes"><b>Notifications</b></property> | 198 | <property name="label" translatable="yes"><b>Notifications</b></property> |
4045 | @@ -129,16 +200,20 @@ | |||
4046 | 129 | </object> | 200 | </object> |
4047 | 130 | <packing> | 201 | <packing> |
4048 | 131 | <property name="expand">False</property> | 202 | <property name="expand">False</property> |
4049 | 203 | <property name="fill">True</property> | ||
4050 | 132 | <property name="position">0</property> | 204 | <property name="position">0</property> |
4051 | 133 | </packing> | 205 | </packing> |
4052 | 134 | </child> | 206 | </child> |
4053 | 135 | <child> | 207 | <child> |
4054 | 136 | <object class="GtkAlignment" id="alignment1"> | 208 | <object class="GtkAlignment" id="alignment1"> |
4055 | 137 | <property name="visible">True</property> | 209 | <property name="visible">True</property> |
4056 | 210 | <property name="can_focus">False</property> | ||
4057 | 138 | <property name="left_padding">12</property> | 211 | <property name="left_padding">12</property> |
4058 | 139 | <child> | 212 | <child> |
4060 | 140 | <object class="GtkVBox" id="vbox4"> | 213 | <object class="GtkBox" id="vbox4"> |
4061 | 141 | <property name="visible">True</property> | 214 | <property name="visible">True</property> |
4062 | 215 | <property name="can_focus">False</property> | ||
4063 | 216 | <property name="orientation">vertical</property> | ||
4064 | 142 | <property name="homogeneous">True</property> | 217 | <property name="homogeneous">True</property> |
4065 | 143 | <child> | 218 | <child> |
4066 | 144 | <object class="GtkRadioButton" id="nonotif"> | 219 | <object class="GtkRadioButton" id="nonotif"> |
4067 | @@ -146,6 +221,7 @@ | |||
4068 | 146 | <property name="visible">True</property> | 221 | <property name="visible">True</property> |
4069 | 147 | <property name="can_focus">True</property> | 222 | <property name="can_focus">True</property> |
4070 | 148 | <property name="receives_default">False</property> | 223 | <property name="receives_default">False</property> |
4071 | 224 | <property name="xalign">0.5</property> | ||
4072 | 149 | <property name="active">True</property> | 225 | <property name="active">True</property> |
4073 | 150 | <property name="draw_indicator">True</property> | 226 | <property name="draw_indicator">True</property> |
4074 | 151 | </object> | 227 | </object> |
4075 | @@ -161,6 +237,7 @@ | |||
4076 | 161 | <property name="visible">True</property> | 237 | <property name="visible">True</property> |
4077 | 162 | <property name="can_focus">True</property> | 238 | <property name="can_focus">True</property> |
4078 | 163 | <property name="receives_default">False</property> | 239 | <property name="receives_default">False</property> |
4079 | 240 | <property name="xalign">0.5</property> | ||
4080 | 164 | <property name="draw_indicator">True</property> | 241 | <property name="draw_indicator">True</property> |
4081 | 165 | <property name="group">nonotif</property> | 242 | <property name="group">nonotif</property> |
4082 | 166 | </object> | 243 | </object> |
4083 | @@ -176,6 +253,7 @@ | |||
4084 | 176 | <property name="visible">True</property> | 253 | <property name="visible">True</property> |
4085 | 177 | <property name="can_focus">True</property> | 254 | <property name="can_focus">True</property> |
4086 | 178 | <property name="receives_default">False</property> | 255 | <property name="receives_default">False</property> |
4087 | 256 | <property name="xalign">0.5</property> | ||
4088 | 179 | <property name="draw_indicator">True</property> | 257 | <property name="draw_indicator">True</property> |
4089 | 180 | <property name="group">nonotif</property> | 258 | <property name="group">nonotif</property> |
4090 | 181 | </object> | 259 | </object> |
4091 | @@ -189,12 +267,15 @@ | |||
4092 | 189 | </child> | 267 | </child> |
4093 | 190 | </object> | 268 | </object> |
4094 | 191 | <packing> | 269 | <packing> |
4095 | 270 | <property name="expand">True</property> | ||
4096 | 271 | <property name="fill">True</property> | ||
4097 | 192 | <property name="position">1</property> | 272 | <property name="position">1</property> |
4098 | 193 | </packing> | 273 | </packing> |
4099 | 194 | </child> | 274 | </child> |
4100 | 195 | <child> | 275 | <child> |
4101 | 196 | <object class="GtkLabel" id="weathersourcelabel"> | 276 | <object class="GtkLabel" id="weathersourcelabel"> |
4102 | 197 | <property name="visible">True</property> | 277 | <property name="visible">True</property> |
4103 | 278 | <property name="can_focus">False</property> | ||
4104 | 198 | <property name="xalign">0</property> | 279 | <property name="xalign">0</property> |
4105 | 199 | <property name="ypad">3</property> | 280 | <property name="ypad">3</property> |
4106 | 200 | <property name="label" translatable="yes"><b>Weather Data Source</b></property> | 281 | <property name="label" translatable="yes"><b>Weather Data Source</b></property> |
4107 | @@ -202,40 +283,46 @@ | |||
4108 | 202 | </object> | 283 | </object> |
4109 | 203 | <packing> | 284 | <packing> |
4110 | 204 | <property name="expand">False</property> | 285 | <property name="expand">False</property> |
4111 | 286 | <property name="fill">True</property> | ||
4112 | 205 | <property name="position">2</property> | 287 | <property name="position">2</property> |
4113 | 206 | </packing> | 288 | </packing> |
4114 | 207 | </child> | 289 | </child> |
4115 | 208 | <child> | 290 | <child> |
4116 | 209 | <object class="GtkAlignment" id="alignment2"> | 291 | <object class="GtkAlignment" id="alignment2"> |
4117 | 210 | <property name="visible">True</property> | 292 | <property name="visible">True</property> |
4118 | 293 | <property name="can_focus">False</property> | ||
4119 | 211 | <property name="left_padding">12</property> | 294 | <property name="left_padding">12</property> |
4120 | 212 | <child> | 295 | <child> |
4122 | 213 | <object class="GtkVBox" id="vbox5"> | 296 | <object class="GtkBox" id="vbox5"> |
4123 | 214 | <property name="visible">True</property> | 297 | <property name="visible">True</property> |
4124 | 298 | <property name="can_focus">False</property> | ||
4125 | 299 | <property name="orientation">vertical</property> | ||
4126 | 215 | <property name="homogeneous">True</property> | 300 | <property name="homogeneous">True</property> |
4127 | 216 | <child> | 301 | <child> |
4128 | 217 | <object class="GtkRadioButton" id="google"> | ||
4129 | 218 | <property name="label" translatable="yes">Google</property> | ||
4130 | 219 | <property name="visible">True</property> | ||
4131 | 220 | <property name="can_focus">True</property> | ||
4132 | 221 | <property name="receives_default">False</property> | ||
4133 | 222 | <property name="active">True</property> | ||
4134 | 223 | <property name="draw_indicator">True</property> | ||
4135 | 224 | </object> | ||
4136 | 225 | <packing> | ||
4137 | 226 | <property name="expand">False</property> | ||
4138 | 227 | <property name="fill">False</property> | ||
4139 | 228 | <property name="position">0</property> | ||
4140 | 229 | </packing> | ||
4141 | 230 | </child> | ||
4142 | 231 | <child> | ||
4143 | 232 | <object class="GtkRadioButton" id="yahoo"> | 302 | <object class="GtkRadioButton" id="yahoo"> |
4144 | 233 | <property name="label" translatable="yes">Yahoo!</property> | 303 | <property name="label" translatable="yes">Yahoo!</property> |
4145 | 234 | <property name="visible">True</property> | 304 | <property name="visible">True</property> |
4146 | 235 | <property name="can_focus">True</property> | 305 | <property name="can_focus">True</property> |
4147 | 236 | <property name="receives_default">False</property> | 306 | <property name="receives_default">False</property> |
4150 | 237 | <property name="draw_indicator">True</property> | 307 | <property name="xalign">0.5</property> |
4151 | 238 | <property name="group">google</property> | 308 | <property name="draw_indicator">True</property> |
4152 | 309 | </object> | ||
4153 | 310 | <packing> | ||
4154 | 311 | <property name="expand">False</property> | ||
4155 | 312 | <property name="fill">False</property> | ||
4156 | 313 | <property name="position">0</property> | ||
4157 | 314 | </packing> | ||
4158 | 315 | </child> | ||
4159 | 316 | <child> | ||
4160 | 317 | <object class="GtkRadioButton" id="weather-com"> | ||
4161 | 318 | <property name="label" translatable="yes">Weather.com</property> | ||
4162 | 319 | <property name="visible">True</property> | ||
4163 | 320 | <property name="can_focus">True</property> | ||
4164 | 321 | <property name="receives_default">False</property> | ||
4165 | 322 | <property name="xalign">0.5</property> | ||
4166 | 323 | <property name="active">True</property> | ||
4167 | 324 | <property name="draw_indicator">True</property> | ||
4168 | 325 | <property name="group">yahoo</property> | ||
4169 | 239 | </object> | 326 | </object> |
4170 | 240 | <packing> | 327 | <packing> |
4171 | 241 | <property name="expand">False</property> | 328 | <property name="expand">False</property> |
4172 | @@ -247,12 +334,15 @@ | |||
4173 | 247 | </child> | 334 | </child> |
4174 | 248 | </object> | 335 | </object> |
4175 | 249 | <packing> | 336 | <packing> |
4176 | 337 | <property name="expand">True</property> | ||
4177 | 338 | <property name="fill">True</property> | ||
4178 | 250 | <property name="position">3</property> | 339 | <property name="position">3</property> |
4179 | 251 | </packing> | 340 | </packing> |
4180 | 252 | </child> | 341 | </child> |
4181 | 253 | </object> | 342 | </object> |
4182 | 254 | <packing> | 343 | <packing> |
4183 | 255 | <property name="expand">False</property> | 344 | <property name="expand">False</property> |
4184 | 345 | <property name="fill">True</property> | ||
4185 | 256 | <property name="position">1</property> | 346 | <property name="position">1</property> |
4186 | 257 | </packing> | 347 | </packing> |
4187 | 258 | </child> | 348 | </child> |
4188 | @@ -261,6 +351,7 @@ | |||
4189 | 261 | <child type="tab"> | 351 | <child type="tab"> |
4190 | 262 | <object class="GtkLabel" id="label1"> | 352 | <object class="GtkLabel" id="label1"> |
4191 | 263 | <property name="visible">True</property> | 353 | <property name="visible">True</property> |
4192 | 354 | <property name="can_focus">False</property> | ||
4193 | 264 | <property name="label" translatable="yes">General</property> | 355 | <property name="label" translatable="yes">General</property> |
4194 | 265 | </object> | 356 | </object> |
4195 | 266 | <packing> | 357 | <packing> |
4196 | @@ -268,16 +359,296 @@ | |||
4197 | 268 | </packing> | 359 | </packing> |
4198 | 269 | </child> | 360 | </child> |
4199 | 270 | <child> | 361 | <child> |
4207 | 271 | <object class="GtkVBox" id="vbox9"> | 362 | <object class="GtkBox" id="boxdisplay"> |
4208 | 272 | <property name="visible">True</property> | 363 | <property name="visible">True</property> |
4209 | 273 | <property name="border_width">12</property> | 364 | <property name="can_focus">False</property> |
4210 | 274 | <property name="spacing">12</property> | 365 | <property name="border_width">12</property> |
4211 | 275 | <child> | 366 | <property name="orientation">vertical</property> |
4212 | 276 | <object class="GtkVBox" id="vbox2"> | 367 | <property name="spacing">12</property> |
4213 | 277 | <property name="visible">True</property> | 368 | <child> |
4214 | 369 | <object class="GtkBox" id="box1"> | ||
4215 | 370 | <property name="visible">True</property> | ||
4216 | 371 | <property name="can_focus">False</property> | ||
4217 | 372 | <property name="orientation">vertical</property> | ||
4218 | 373 | <child> | ||
4219 | 374 | <object class="GtkLabel" id="conditionslabel"> | ||
4220 | 375 | <property name="visible">True</property> | ||
4221 | 376 | <property name="can_focus">False</property> | ||
4222 | 377 | <property name="xalign">0</property> | ||
4223 | 378 | <property name="ypad">3</property> | ||
4224 | 379 | <property name="label" translatable="yes"><b>Weather Conditions</b></property> | ||
4225 | 380 | <property name="use_markup">True</property> | ||
4226 | 381 | </object> | ||
4227 | 382 | <packing> | ||
4228 | 383 | <property name="expand">False</property> | ||
4229 | 384 | <property name="fill">True</property> | ||
4230 | 385 | <property name="position">0</property> | ||
4231 | 386 | </packing> | ||
4232 | 387 | </child> | ||
4233 | 388 | <child> | ||
4234 | 389 | <object class="GtkAlignment" id="alignment5"> | ||
4235 | 390 | <property name="visible">True</property> | ||
4236 | 391 | <property name="can_focus">False</property> | ||
4237 | 392 | <property name="left_padding">12</property> | ||
4238 | 393 | <child> | ||
4239 | 394 | <object class="GtkBox" id="box3"> | ||
4240 | 395 | <property name="visible">True</property> | ||
4241 | 396 | <property name="can_focus">False</property> | ||
4242 | 397 | <property name="orientation">vertical</property> | ||
4243 | 398 | <property name="homogeneous">True</property> | ||
4244 | 399 | <child> | ||
4245 | 400 | <object class="GtkCheckButton" id="show_relative"> | ||
4246 | 401 | <property name="label" translatable="yes">Relative temperature ("Feels like")</property> | ||
4247 | 402 | <property name="visible">True</property> | ||
4248 | 403 | <property name="can_focus">True</property> | ||
4249 | 404 | <property name="receives_default">False</property> | ||
4250 | 405 | <property name="xalign">0</property> | ||
4251 | 406 | <property name="draw_indicator">True</property> | ||
4252 | 407 | </object> | ||
4253 | 408 | <packing> | ||
4254 | 409 | <property name="expand">False</property> | ||
4255 | 410 | <property name="fill">False</property> | ||
4256 | 411 | <property name="position">0</property> | ||
4257 | 412 | </packing> | ||
4258 | 413 | </child> | ||
4259 | 414 | <child> | ||
4260 | 415 | <object class="GtkCheckButton" id="show_wind"> | ||
4261 | 416 | <property name="label" translatable="yes">Wind speed and direction</property> | ||
4262 | 417 | <property name="visible">True</property> | ||
4263 | 418 | <property name="can_focus">True</property> | ||
4264 | 419 | <property name="receives_default">False</property> | ||
4265 | 420 | <property name="xalign">0</property> | ||
4266 | 421 | <property name="active">True</property> | ||
4267 | 422 | <property name="draw_indicator">True</property> | ||
4268 | 423 | </object> | ||
4269 | 424 | <packing> | ||
4270 | 425 | <property name="expand">False</property> | ||
4271 | 426 | <property name="fill">False</property> | ||
4272 | 427 | <property name="position">1</property> | ||
4273 | 428 | </packing> | ||
4274 | 429 | </child> | ||
4275 | 430 | <child> | ||
4276 | 431 | <object class="GtkCheckButton" id="show_suntimes"> | ||
4277 | 432 | <property name="label" translatable="yes">Sunrise and sunset times</property> | ||
4278 | 433 | <property name="visible">True</property> | ||
4279 | 434 | <property name="can_focus">True</property> | ||
4280 | 435 | <property name="receives_default">False</property> | ||
4281 | 436 | <property name="xalign">0</property> | ||
4282 | 437 | <property name="active">True</property> | ||
4283 | 438 | <property name="draw_indicator">True</property> | ||
4284 | 439 | </object> | ||
4285 | 440 | <packing> | ||
4286 | 441 | <property name="expand">False</property> | ||
4287 | 442 | <property name="fill">False</property> | ||
4288 | 443 | <property name="position">2</property> | ||
4289 | 444 | </packing> | ||
4290 | 445 | </child> | ||
4291 | 446 | </object> | ||
4292 | 447 | </child> | ||
4293 | 448 | </object> | ||
4294 | 449 | <packing> | ||
4295 | 450 | <property name="expand">True</property> | ||
4296 | 451 | <property name="fill">True</property> | ||
4297 | 452 | <property name="position">1</property> | ||
4298 | 453 | </packing> | ||
4299 | 454 | </child> | ||
4300 | 455 | </object> | ||
4301 | 456 | <packing> | ||
4302 | 457 | <property name="expand">False</property> | ||
4303 | 458 | <property name="fill">True</property> | ||
4304 | 459 | <property name="position">0</property> | ||
4305 | 460 | </packing> | ||
4306 | 461 | </child> | ||
4307 | 462 | <child> | ||
4308 | 463 | <object class="GtkBox" id="box6"> | ||
4309 | 464 | <property name="visible">True</property> | ||
4310 | 465 | <property name="can_focus">False</property> | ||
4311 | 466 | <property name="orientation">vertical</property> | ||
4312 | 467 | <child> | ||
4313 | 468 | <object class="GtkLabel" id="heatlabel"> | ||
4314 | 469 | <property name="visible">True</property> | ||
4315 | 470 | <property name="can_focus">False</property> | ||
4316 | 471 | <property name="xalign">0</property> | ||
4317 | 472 | <property name="ypad">3</property> | ||
4318 | 473 | <property name="label" translatable="yes"><b>Relative Heat Formula</b></property> | ||
4319 | 474 | <property name="use_markup">True</property> | ||
4320 | 475 | </object> | ||
4321 | 476 | <packing> | ||
4322 | 477 | <property name="expand">False</property> | ||
4323 | 478 | <property name="fill">True</property> | ||
4324 | 479 | <property name="position">0</property> | ||
4325 | 480 | </packing> | ||
4326 | 481 | </child> | ||
4327 | 482 | <child> | ||
4328 | 483 | <object class="GtkAlignment" id="alignment6"> | ||
4329 | 484 | <property name="visible">True</property> | ||
4330 | 485 | <property name="can_focus">False</property> | ||
4331 | 486 | <property name="left_padding">12</property> | ||
4332 | 487 | <child> | ||
4333 | 488 | <object class="GtkBox" id="box4"> | ||
4334 | 489 | <property name="visible">True</property> | ||
4335 | 490 | <property name="can_focus">False</property> | ||
4336 | 491 | <property name="orientation">vertical</property> | ||
4337 | 492 | <property name="homogeneous">True</property> | ||
4338 | 493 | <child> | ||
4339 | 494 | <object class="GtkRadioButton" id="heatindex"> | ||
4340 | 495 | <property name="label" translatable="yes">Heat Index (US)</property> | ||
4341 | 496 | <property name="visible">True</property> | ||
4342 | 497 | <property name="can_focus">True</property> | ||
4343 | 498 | <property name="receives_default">False</property> | ||
4344 | 499 | <property name="xalign">0</property> | ||
4345 | 500 | <property name="active">True</property> | ||
4346 | 501 | <property name="draw_indicator">True</property> | ||
4347 | 502 | </object> | ||
4348 | 503 | <packing> | ||
4349 | 504 | <property name="expand">False</property> | ||
4350 | 505 | <property name="fill">False</property> | ||
4351 | 506 | <property name="position">0</property> | ||
4352 | 507 | </packing> | ||
4353 | 508 | </child> | ||
4354 | 509 | <child> | ||
4355 | 510 | <object class="GtkRadioButton" id="humidex"> | ||
4356 | 511 | <property name="label" translatable="yes">Humidex (Canada)</property> | ||
4357 | 512 | <property name="visible">True</property> | ||
4358 | 513 | <property name="can_focus">True</property> | ||
4359 | 514 | <property name="receives_default">False</property> | ||
4360 | 515 | <property name="xalign">0</property> | ||
4361 | 516 | <property name="draw_indicator">True</property> | ||
4362 | 517 | <property name="group">heatindex</property> | ||
4363 | 518 | </object> | ||
4364 | 519 | <packing> | ||
4365 | 520 | <property name="expand">False</property> | ||
4366 | 521 | <property name="fill">False</property> | ||
4367 | 522 | <property name="position">1</property> | ||
4368 | 523 | </packing> | ||
4369 | 524 | </child> | ||
4370 | 525 | </object> | ||
4371 | 526 | </child> | ||
4372 | 527 | </object> | ||
4373 | 528 | <packing> | ||
4374 | 529 | <property name="expand">False</property> | ||
4375 | 530 | <property name="fill">True</property> | ||
4376 | 531 | <property name="position">1</property> | ||
4377 | 532 | </packing> | ||
4378 | 533 | </child> | ||
4379 | 534 | </object> | ||
4380 | 535 | <packing> | ||
4381 | 536 | <property name="expand">False</property> | ||
4382 | 537 | <property name="fill">True</property> | ||
4383 | 538 | <property name="position">1</property> | ||
4384 | 539 | </packing> | ||
4385 | 540 | </child> | ||
4386 | 541 | <child> | ||
4387 | 542 | <object class="GtkBox" id="box2"> | ||
4388 | 543 | <property name="visible">True</property> | ||
4389 | 544 | <property name="can_focus">False</property> | ||
4390 | 545 | <property name="orientation">vertical</property> | ||
4391 | 546 | <child> | ||
4392 | 547 | <object class="GtkLabel" id="chilllabel"> | ||
4393 | 548 | <property name="visible">True</property> | ||
4394 | 549 | <property name="can_focus">False</property> | ||
4395 | 550 | <property name="xalign">0</property> | ||
4396 | 551 | <property name="ypad">3</property> | ||
4397 | 552 | <property name="label" translatable="yes"><b>Wind Chill Formula</b></property> | ||
4398 | 553 | <property name="use_markup">True</property> | ||
4399 | 554 | </object> | ||
4400 | 555 | <packing> | ||
4401 | 556 | <property name="expand">False</property> | ||
4402 | 557 | <property name="fill">True</property> | ||
4403 | 558 | <property name="position">0</property> | ||
4404 | 559 | </packing> | ||
4405 | 560 | </child> | ||
4406 | 561 | <child> | ||
4407 | 562 | <object class="GtkAlignment" id="alignment7"> | ||
4408 | 563 | <property name="visible">True</property> | ||
4409 | 564 | <property name="can_focus">False</property> | ||
4410 | 565 | <property name="left_padding">12</property> | ||
4411 | 566 | <child> | ||
4412 | 567 | <object class="GtkBox" id="box7"> | ||
4413 | 568 | <property name="visible">True</property> | ||
4414 | 569 | <property name="can_focus">False</property> | ||
4415 | 570 | <property name="orientation">vertical</property> | ||
4416 | 571 | <property name="homogeneous">True</property> | ||
4417 | 572 | <child> | ||
4418 | 573 | <object class="GtkRadioButton" id="wctindex"> | ||
4419 | 574 | <property name="label" translatable="yes">JAG/TI Wind Chill Index (US/UK/Canada)</property> | ||
4420 | 575 | <property name="visible">True</property> | ||
4421 | 576 | <property name="can_focus">True</property> | ||
4422 | 577 | <property name="receives_default">False</property> | ||
4423 | 578 | <property name="xalign">0</property> | ||
4424 | 579 | <property name="active">True</property> | ||
4425 | 580 | <property name="draw_indicator">True</property> | ||
4426 | 581 | </object> | ||
4427 | 582 | <packing> | ||
4428 | 583 | <property name="expand">False</property> | ||
4429 | 584 | <property name="fill">False</property> | ||
4430 | 585 | <property name="position">0</property> | ||
4431 | 586 | </packing> | ||
4432 | 587 | </child> | ||
4433 | 588 | <child> | ||
4434 | 589 | <object class="GtkRadioButton" id="aatindex"> | ||
4435 | 590 | <property name="label" translatable="yes">Apparent Temperature (Australia)</property> | ||
4436 | 591 | <property name="visible">True</property> | ||
4437 | 592 | <property name="can_focus">True</property> | ||
4438 | 593 | <property name="receives_default">False</property> | ||
4439 | 594 | <property name="xalign">0</property> | ||
4440 | 595 | <property name="draw_indicator">True</property> | ||
4441 | 596 | <property name="group">wctindex</property> | ||
4442 | 597 | </object> | ||
4443 | 598 | <packing> | ||
4444 | 599 | <property name="expand">False</property> | ||
4445 | 600 | <property name="fill">False</property> | ||
4446 | 601 | <property name="position">1</property> | ||
4447 | 602 | </packing> | ||
4448 | 603 | </child> | ||
4449 | 604 | </object> | ||
4450 | 605 | </child> | ||
4451 | 606 | </object> | ||
4452 | 607 | <packing> | ||
4453 | 608 | <property name="expand">False</property> | ||
4454 | 609 | <property name="fill">True</property> | ||
4455 | 610 | <property name="position">1</property> | ||
4456 | 611 | </packing> | ||
4457 | 612 | </child> | ||
4458 | 613 | </object> | ||
4459 | 614 | <packing> | ||
4460 | 615 | <property name="expand">False</property> | ||
4461 | 616 | <property name="fill">True</property> | ||
4462 | 617 | <property name="position">2</property> | ||
4463 | 618 | </packing> | ||
4464 | 619 | </child> | ||
4465 | 620 | </object> | ||
4466 | 621 | <packing> | ||
4467 | 622 | <property name="position">1</property> | ||
4468 | 623 | </packing> | ||
4469 | 624 | </child> | ||
4470 | 625 | <child type="tab"> | ||
4471 | 626 | <object class="GtkLabel" id="label5"> | ||
4472 | 627 | <property name="visible">True</property> | ||
4473 | 628 | <property name="can_focus">False</property> | ||
4474 | 629 | <property name="label" translatable="yes">Conditions</property> | ||
4475 | 630 | </object> | ||
4476 | 631 | <packing> | ||
4477 | 632 | <property name="position">1</property> | ||
4478 | 633 | <property name="tab_fill">False</property> | ||
4479 | 634 | </packing> | ||
4480 | 635 | </child> | ||
4481 | 636 | <child> | ||
4482 | 637 | <object class="GtkBox" id="vbox9"> | ||
4483 | 638 | <property name="visible">True</property> | ||
4484 | 639 | <property name="can_focus">False</property> | ||
4485 | 640 | <property name="border_width">12</property> | ||
4486 | 641 | <property name="orientation">vertical</property> | ||
4487 | 642 | <property name="spacing">12</property> | ||
4488 | 643 | <child> | ||
4489 | 644 | <object class="GtkBox" id="vbox2"> | ||
4490 | 645 | <property name="visible">True</property> | ||
4491 | 646 | <property name="can_focus">False</property> | ||
4492 | 647 | <property name="orientation">vertical</property> | ||
4493 | 278 | <child> | 648 | <child> |
4494 | 279 | <object class="GtkLabel" id="Metric System Unit"> | 649 | <object class="GtkLabel" id="Metric System Unit"> |
4495 | 280 | <property name="visible">True</property> | 650 | <property name="visible">True</property> |
4496 | 651 | <property name="can_focus">False</property> | ||
4497 | 281 | <property name="xalign">0</property> | 652 | <property name="xalign">0</property> |
4498 | 282 | <property name="ypad">3</property> | 653 | <property name="ypad">3</property> |
4499 | 283 | <property name="label" translatable="yes"><b>Temperature Scale</b></property> | 654 | <property name="label" translatable="yes"><b>Temperature Scale</b></property> |
4500 | @@ -285,16 +656,20 @@ | |||
4501 | 285 | </object> | 656 | </object> |
4502 | 286 | <packing> | 657 | <packing> |
4503 | 287 | <property name="expand">False</property> | 658 | <property name="expand">False</property> |
4504 | 659 | <property name="fill">True</property> | ||
4505 | 288 | <property name="position">0</property> | 660 | <property name="position">0</property> |
4506 | 289 | </packing> | 661 | </packing> |
4507 | 290 | </child> | 662 | </child> |
4508 | 291 | <child> | 663 | <child> |
4509 | 292 | <object class="GtkAlignment" id="alignment3"> | 664 | <object class="GtkAlignment" id="alignment3"> |
4510 | 293 | <property name="visible">True</property> | 665 | <property name="visible">True</property> |
4511 | 666 | <property name="can_focus">False</property> | ||
4512 | 294 | <property name="left_padding">12</property> | 667 | <property name="left_padding">12</property> |
4513 | 295 | <child> | 668 | <child> |
4515 | 296 | <object class="GtkVBox" id="vbox6"> | 669 | <object class="GtkBox" id="box5"> |
4516 | 297 | <property name="visible">True</property> | 670 | <property name="visible">True</property> |
4517 | 671 | <property name="can_focus">False</property> | ||
4518 | 672 | <property name="orientation">vertical</property> | ||
4519 | 298 | <property name="homogeneous">True</property> | 673 | <property name="homogeneous">True</property> |
4520 | 299 | <child> | 674 | <child> |
4521 | 300 | <object class="GtkRadioButton" id="imperial"> | 675 | <object class="GtkRadioButton" id="imperial"> |
4522 | @@ -302,6 +677,7 @@ | |||
4523 | 302 | <property name="visible">True</property> | 677 | <property name="visible">True</property> |
4524 | 303 | <property name="can_focus">True</property> | 678 | <property name="can_focus">True</property> |
4525 | 304 | <property name="receives_default">False</property> | 679 | <property name="receives_default">False</property> |
4526 | 680 | <property name="xalign">0</property> | ||
4527 | 305 | <property name="active">True</property> | 681 | <property name="active">True</property> |
4528 | 306 | <property name="draw_indicator">True</property> | 682 | <property name="draw_indicator">True</property> |
4529 | 307 | </object> | 683 | </object> |
4530 | @@ -317,6 +693,7 @@ | |||
4531 | 317 | <property name="visible">True</property> | 693 | <property name="visible">True</property> |
4532 | 318 | <property name="can_focus">True</property> | 694 | <property name="can_focus">True</property> |
4533 | 319 | <property name="receives_default">False</property> | 695 | <property name="receives_default">False</property> |
4534 | 696 | <property name="xalign">0</property> | ||
4535 | 320 | <property name="draw_indicator">True</property> | 697 | <property name="draw_indicator">True</property> |
4536 | 321 | <property name="group">imperial</property> | 698 | <property name="group">imperial</property> |
4537 | 322 | </object> | 699 | </object> |
4538 | @@ -331,21 +708,26 @@ | |||
4539 | 331 | </object> | 708 | </object> |
4540 | 332 | <packing> | 709 | <packing> |
4541 | 333 | <property name="expand">False</property> | 710 | <property name="expand">False</property> |
4542 | 711 | <property name="fill">True</property> | ||
4543 | 334 | <property name="position">1</property> | 712 | <property name="position">1</property> |
4544 | 335 | </packing> | 713 | </packing> |
4545 | 336 | </child> | 714 | </child> |
4546 | 337 | </object> | 715 | </object> |
4547 | 338 | <packing> | 716 | <packing> |
4548 | 339 | <property name="expand">False</property> | 717 | <property name="expand">False</property> |
4549 | 718 | <property name="fill">True</property> | ||
4550 | 340 | <property name="position">0</property> | 719 | <property name="position">0</property> |
4551 | 341 | </packing> | 720 | </packing> |
4552 | 342 | </child> | 721 | </child> |
4553 | 343 | <child> | 722 | <child> |
4555 | 344 | <object class="GtkVBox" id="vbox3"> | 723 | <object class="GtkBox" id="vbox3"> |
4556 | 345 | <property name="visible">True</property> | 724 | <property name="visible">True</property> |
4557 | 725 | <property name="can_focus">False</property> | ||
4558 | 726 | <property name="orientation">vertical</property> | ||
4559 | 346 | <child> | 727 | <child> |
4560 | 347 | <object class="GtkLabel" id="Wind Speed Unit"> | 728 | <object class="GtkLabel" id="Wind Speed Unit"> |
4561 | 348 | <property name="visible">True</property> | 729 | <property name="visible">True</property> |
4562 | 730 | <property name="can_focus">False</property> | ||
4563 | 349 | <property name="xalign">0</property> | 731 | <property name="xalign">0</property> |
4564 | 350 | <property name="ypad">3</property> | 732 | <property name="ypad">3</property> |
4565 | 351 | <property name="label" translatable="yes"><b>Wind Speed Unit</b></property> | 733 | <property name="label" translatable="yes"><b>Wind Speed Unit</b></property> |
4566 | @@ -353,23 +735,28 @@ | |||
4567 | 353 | </object> | 735 | </object> |
4568 | 354 | <packing> | 736 | <packing> |
4569 | 355 | <property name="expand">False</property> | 737 | <property name="expand">False</property> |
4570 | 738 | <property name="fill">True</property> | ||
4571 | 356 | <property name="position">0</property> | 739 | <property name="position">0</property> |
4572 | 357 | </packing> | 740 | </packing> |
4573 | 358 | </child> | 741 | </child> |
4574 | 359 | <child> | 742 | <child> |
4575 | 360 | <object class="GtkAlignment" id="alignment4"> | 743 | <object class="GtkAlignment" id="alignment4"> |
4576 | 361 | <property name="visible">True</property> | 744 | <property name="visible">True</property> |
4577 | 745 | <property name="can_focus">False</property> | ||
4578 | 362 | <property name="left_padding">12</property> | 746 | <property name="left_padding">12</property> |
4579 | 363 | <child> | 747 | <child> |
4581 | 364 | <object class="GtkVBox" id="vbox7"> | 748 | <object class="GtkBox" id="vbox7"> |
4582 | 365 | <property name="visible">True</property> | 749 | <property name="visible">True</property> |
4583 | 750 | <property name="can_focus">False</property> | ||
4584 | 751 | <property name="orientation">vertical</property> | ||
4585 | 366 | <property name="homogeneous">True</property> | 752 | <property name="homogeneous">True</property> |
4586 | 367 | <child> | 753 | <child> |
4587 | 368 | <object class="GtkRadioButton" id="mps"> | 754 | <object class="GtkRadioButton" id="mps"> |
4589 | 369 | <property name="label" translatable="yes">Meter per second (m/s)</property> | 755 | <property name="label" translatable="yes">Meters per second (m/s)</property> |
4590 | 370 | <property name="visible">True</property> | 756 | <property name="visible">True</property> |
4591 | 371 | <property name="can_focus">True</property> | 757 | <property name="can_focus">True</property> |
4592 | 372 | <property name="receives_default">False</property> | 758 | <property name="receives_default">False</property> |
4593 | 759 | <property name="xalign">0.5</property> | ||
4594 | 373 | <property name="active">True</property> | 760 | <property name="active">True</property> |
4595 | 374 | <property name="draw_indicator">True</property> | 761 | <property name="draw_indicator">True</property> |
4596 | 375 | </object> | 762 | </object> |
4597 | @@ -385,6 +772,7 @@ | |||
4598 | 385 | <property name="visible">True</property> | 772 | <property name="visible">True</property> |
4599 | 386 | <property name="can_focus">True</property> | 773 | <property name="can_focus">True</property> |
4600 | 387 | <property name="receives_default">False</property> | 774 | <property name="receives_default">False</property> |
4601 | 775 | <property name="xalign">0.5</property> | ||
4602 | 388 | <property name="draw_indicator">True</property> | 776 | <property name="draw_indicator">True</property> |
4603 | 389 | <property name="group">mps</property> | 777 | <property name="group">mps</property> |
4604 | 390 | </object> | 778 | </object> |
4605 | @@ -400,6 +788,7 @@ | |||
4606 | 400 | <property name="visible">True</property> | 788 | <property name="visible">True</property> |
4607 | 401 | <property name="can_focus">True</property> | 789 | <property name="can_focus">True</property> |
4608 | 402 | <property name="receives_default">False</property> | 790 | <property name="receives_default">False</property> |
4609 | 791 | <property name="xalign">0.5</property> | ||
4610 | 403 | <property name="draw_indicator">True</property> | 792 | <property name="draw_indicator">True</property> |
4611 | 404 | <property name="group">mps</property> | 793 | <property name="group">mps</property> |
4612 | 405 | </object> | 794 | </object> |
4613 | @@ -411,10 +800,11 @@ | |||
4614 | 411 | </child> | 800 | </child> |
4615 | 412 | <child> | 801 | <child> |
4616 | 413 | <object class="GtkRadioButton" id="beaufort"> | 802 | <object class="GtkRadioButton" id="beaufort"> |
4618 | 414 | <property name="label" translatable="yes">Beaufort</property> | 803 | <property name="label" translatable="yes">Beaufort number</property> |
4619 | 415 | <property name="visible">True</property> | 804 | <property name="visible">True</property> |
4620 | 416 | <property name="can_focus">True</property> | 805 | <property name="can_focus">True</property> |
4621 | 417 | <property name="receives_default">False</property> | 806 | <property name="receives_default">False</property> |
4622 | 807 | <property name="xalign">0.5</property> | ||
4623 | 418 | <property name="draw_indicator">True</property> | 808 | <property name="draw_indicator">True</property> |
4624 | 419 | <property name="group">mps</property> | 809 | <property name="group">mps</property> |
4625 | 420 | </object> | 810 | </object> |
4626 | @@ -430,6 +820,7 @@ | |||
4627 | 430 | <property name="visible">True</property> | 820 | <property name="visible">True</property> |
4628 | 431 | <property name="can_focus">True</property> | 821 | <property name="can_focus">True</property> |
4629 | 432 | <property name="receives_default">False</property> | 822 | <property name="receives_default">False</property> |
4630 | 823 | <property name="xalign">0.5</property> | ||
4631 | 433 | <property name="draw_indicator">True</property> | 824 | <property name="draw_indicator">True</property> |
4632 | 434 | <property name="group">mps</property> | 825 | <property name="group">mps</property> |
4633 | 435 | </object> | 826 | </object> |
4634 | @@ -444,41 +835,44 @@ | |||
4635 | 444 | </object> | 835 | </object> |
4636 | 445 | <packing> | 836 | <packing> |
4637 | 446 | <property name="expand">False</property> | 837 | <property name="expand">False</property> |
4638 | 838 | <property name="fill">True</property> | ||
4639 | 447 | <property name="position">1</property> | 839 | <property name="position">1</property> |
4640 | 448 | </packing> | 840 | </packing> |
4641 | 449 | </child> | 841 | </child> |
4642 | 450 | </object> | 842 | </object> |
4643 | 451 | <packing> | 843 | <packing> |
4644 | 452 | <property name="expand">False</property> | 844 | <property name="expand">False</property> |
4645 | 845 | <property name="fill">True</property> | ||
4646 | 453 | <property name="position">1</property> | 846 | <property name="position">1</property> |
4647 | 454 | </packing> | 847 | </packing> |
4648 | 455 | </child> | 848 | </child> |
4649 | 456 | </object> | 849 | </object> |
4650 | 457 | <packing> | 850 | <packing> |
4652 | 458 | <property name="position">1</property> | 851 | <property name="position">2</property> |
4653 | 459 | </packing> | 852 | </packing> |
4654 | 460 | </child> | 853 | </child> |
4655 | 461 | <child type="tab"> | 854 | <child type="tab"> |
4656 | 462 | <object class="GtkLabel" id="label2"> | 855 | <object class="GtkLabel" id="label2"> |
4657 | 463 | <property name="visible">True</property> | 856 | <property name="visible">True</property> |
4658 | 857 | <property name="can_focus">False</property> | ||
4659 | 464 | <property name="label" translatable="yes">Units</property> | 858 | <property name="label" translatable="yes">Units</property> |
4660 | 465 | </object> | 859 | </object> |
4661 | 466 | <packing> | 860 | <packing> |
4663 | 467 | <property name="position">1</property> | 861 | <property name="position">2</property> |
4664 | 468 | <property name="tab_fill">False</property> | 862 | <property name="tab_fill">False</property> |
4665 | 469 | </packing> | 863 | </packing> |
4666 | 470 | </child> | 864 | </child> |
4667 | 471 | <child> | 865 | <child> |
4669 | 472 | <object class="GtkVBox" id="vbox8"> | 866 | <object class="GtkBox" id="vbox8"> |
4670 | 473 | <property name="visible">True</property> | 867 | <property name="visible">True</property> |
4671 | 868 | <property name="can_focus">False</property> | ||
4672 | 474 | <property name="border_width">12</property> | 869 | <property name="border_width">12</property> |
4673 | 870 | <property name="orientation">vertical</property> | ||
4674 | 475 | <property name="spacing">6</property> | 871 | <property name="spacing">6</property> |
4675 | 476 | <child> | 872 | <child> |
4676 | 477 | <object class="GtkScrolledWindow" id="scrolledwindow1"> | 873 | <object class="GtkScrolledWindow" id="scrolledwindow1"> |
4677 | 478 | <property name="visible">True</property> | 874 | <property name="visible">True</property> |
4678 | 479 | <property name="can_focus">True</property> | 875 | <property name="can_focus">True</property> |
4679 | 480 | <property name="hscrollbar_policy">automatic</property> | ||
4680 | 481 | <property name="vscrollbar_policy">automatic</property> | ||
4681 | 482 | <property name="window_placement_set">True</property> | 876 | <property name="window_placement_set">True</property> |
4682 | 483 | <property name="shadow_type">in</property> | 877 | <property name="shadow_type">in</property> |
4683 | 484 | <child> | 878 | <child> |
4684 | @@ -490,6 +884,9 @@ | |||
4685 | 490 | <property name="headers_clickable">False</property> | 884 | <property name="headers_clickable">False</property> |
4686 | 491 | <property name="reorderable">True</property> | 885 | <property name="reorderable">True</property> |
4687 | 492 | <property name="search_column">0</property> | 886 | <property name="search_column">0</property> |
4688 | 887 | <child internal-child="selection"> | ||
4689 | 888 | <object class="GtkTreeSelection" id="treeview-selection1"/> | ||
4690 | 889 | </child> | ||
4691 | 493 | <child> | 890 | <child> |
4692 | 494 | <object class="GtkTreeViewColumn" id="City"> | 891 | <object class="GtkTreeViewColumn" id="City"> |
4693 | 495 | <property name="title">City</property> | 892 | <property name="title">City</property> |
4694 | @@ -506,12 +903,15 @@ | |||
4695 | 506 | </child> | 903 | </child> |
4696 | 507 | </object> | 904 | </object> |
4697 | 508 | <packing> | 905 | <packing> |
4698 | 906 | <property name="expand">True</property> | ||
4699 | 907 | <property name="fill">True</property> | ||
4700 | 509 | <property name="position">0</property> | 908 | <property name="position">0</property> |
4701 | 510 | </packing> | 909 | </packing> |
4702 | 511 | </child> | 910 | </child> |
4703 | 512 | <child> | 911 | <child> |
4704 | 513 | <object class="GtkHButtonBox" id="hbuttonbox1"> | 912 | <object class="GtkHButtonBox" id="hbuttonbox1"> |
4705 | 514 | <property name="visible">True</property> | 913 | <property name="visible">True</property> |
4706 | 914 | <property name="can_focus">False</property> | ||
4707 | 515 | <property name="spacing">6</property> | 915 | <property name="spacing">6</property> |
4708 | 516 | <property name="layout_style">start</property> | 916 | <property name="layout_style">start</property> |
4709 | 517 | <child> | 917 | <child> |
4710 | @@ -521,7 +921,7 @@ | |||
4711 | 521 | <property name="can_focus">True</property> | 921 | <property name="can_focus">True</property> |
4712 | 522 | <property name="receives_default">True</property> | 922 | <property name="receives_default">True</property> |
4713 | 523 | <property name="use_stock">True</property> | 923 | <property name="use_stock">True</property> |
4715 | 524 | <signal name="clicked" handler="on_add_location"/> | 924 | <signal name="clicked" handler="on_add_location" swapped="no"/> |
4716 | 525 | </object> | 925 | </object> |
4717 | 526 | <packing> | 926 | <packing> |
4718 | 527 | <property name="expand">False</property> | 927 | <property name="expand">False</property> |
4719 | @@ -536,7 +936,7 @@ | |||
4720 | 536 | <property name="can_focus">True</property> | 936 | <property name="can_focus">True</property> |
4721 | 537 | <property name="receives_default">True</property> | 937 | <property name="receives_default">True</property> |
4722 | 538 | <property name="use_stock">True</property> | 938 | <property name="use_stock">True</property> |
4724 | 539 | <signal name="clicked" handler="on_remove_location"/> | 939 | <signal name="clicked" handler="on_remove_location" swapped="no"/> |
4725 | 540 | </object> | 940 | </object> |
4726 | 541 | <packing> | 941 | <packing> |
4727 | 542 | <property name="expand">False</property> | 942 | <property name="expand">False</property> |
4728 | @@ -547,70 +947,33 @@ | |||
4729 | 547 | </object> | 947 | </object> |
4730 | 548 | <packing> | 948 | <packing> |
4731 | 549 | <property name="expand">False</property> | 949 | <property name="expand">False</property> |
4732 | 950 | <property name="fill">True</property> | ||
4733 | 550 | <property name="position">1</property> | 951 | <property name="position">1</property> |
4734 | 551 | </packing> | 952 | </packing> |
4735 | 552 | </child> | 953 | </child> |
4736 | 553 | </object> | 954 | </object> |
4737 | 554 | <packing> | 955 | <packing> |
4739 | 555 | <property name="position">2</property> | 956 | <property name="position">3</property> |
4740 | 556 | </packing> | 957 | </packing> |
4741 | 557 | </child> | 958 | </child> |
4742 | 558 | <child type="tab"> | 959 | <child type="tab"> |
4743 | 559 | <object class="GtkLabel" id="label3"> | 960 | <object class="GtkLabel" id="label3"> |
4744 | 560 | <property name="visible">True</property> | 961 | <property name="visible">True</property> |
4745 | 962 | <property name="can_focus">False</property> | ||
4746 | 561 | <property name="label" translatable="yes">Locations</property> | 963 | <property name="label" translatable="yes">Locations</property> |
4747 | 562 | </object> | 964 | </object> |
4748 | 563 | <packing> | 965 | <packing> |
4750 | 564 | <property name="position">2</property> | 966 | <property name="position">3</property> |
4751 | 565 | <property name="tab_fill">False</property> | 967 | <property name="tab_fill">False</property> |
4752 | 566 | </packing> | 968 | </packing> |
4753 | 567 | </child> | 969 | </child> |
4754 | 568 | </object> | 970 | </object> |
4755 | 569 | <packing> | 971 | <packing> |
4756 | 972 | <property name="expand">False</property> | ||
4757 | 973 | <property name="fill">True</property> | ||
4758 | 570 | <property name="position">1</property> | 974 | <property name="position">1</property> |
4759 | 571 | </packing> | 975 | </packing> |
4760 | 572 | </child> | 976 | </child> |
4761 | 573 | <child internal-child="action_area"> | ||
4762 | 574 | <object class="GtkHButtonBox" id="dialog-action_area1"> | ||
4763 | 575 | <property name="visible">True</property> | ||
4764 | 576 | <property name="layout_style">end</property> | ||
4765 | 577 | <child> | ||
4766 | 578 | <object class="GtkButton" id="cancel_button"> | ||
4767 | 579 | <property name="label">gtk-cancel</property> | ||
4768 | 580 | <property name="visible">True</property> | ||
4769 | 581 | <property name="receives_default">True</property> | ||
4770 | 582 | <property name="use_stock">True</property> | ||
4771 | 583 | <signal name="clicked" handler="cancel"/> | ||
4772 | 584 | </object> | ||
4773 | 585 | <packing> | ||
4774 | 586 | <property name="expand">False</property> | ||
4775 | 587 | <property name="fill">False</property> | ||
4776 | 588 | <property name="position">0</property> | ||
4777 | 589 | </packing> | ||
4778 | 590 | </child> | ||
4779 | 591 | <child> | ||
4780 | 592 | <object class="GtkButton" id="ok_button"> | ||
4781 | 593 | <property name="label">gtk-ok</property> | ||
4782 | 594 | <property name="visible">True</property> | ||
4783 | 595 | <property name="sensitive">False</property> | ||
4784 | 596 | <property name="receives_default">True</property> | ||
4785 | 597 | <property name="use_stock">True</property> | ||
4786 | 598 | <signal name="clicked" handler="ok"/> | ||
4787 | 599 | </object> | ||
4788 | 600 | <packing> | ||
4789 | 601 | <property name="expand">False</property> | ||
4790 | 602 | <property name="fill">False</property> | ||
4791 | 603 | <property name="position">1</property> | ||
4792 | 604 | </packing> | ||
4793 | 605 | </child> | ||
4794 | 606 | </object> | ||
4795 | 607 | <packing> | ||
4796 | 608 | <property name="expand">False</property> | ||
4797 | 609 | <property name="fill">False</property> | ||
4798 | 610 | <property name="pack_type">end</property> | ||
4799 | 611 | <property name="position">0</property> | ||
4800 | 612 | </packing> | ||
4801 | 613 | </child> | ||
4802 | 614 | </object> | 977 | </object> |
4803 | 615 | </child> | 978 | </child> |
4804 | 616 | <action-widgets> | 979 | <action-widgets> |
4805 | @@ -618,10 +981,4 @@ | |||
4806 | 618 | <action-widget response="-5">ok_button</action-widget> | 981 | <action-widget response="-5">ok_button</action-widget> |
4807 | 619 | </action-widgets> | 982 | </action-widgets> |
4808 | 620 | </object> | 983 | </object> |
4809 | 621 | <object class="GtkAdjustment" id="rate"> | ||
4810 | 622 | <property name="lower">1</property> | ||
4811 | 623 | <property name="upper">30</property> | ||
4812 | 624 | <property name="step_increment">1</property> | ||
4813 | 625 | <property name="page_increment">10</property> | ||
4814 | 626 | </object> | ||
4815 | 627 | </interface> | 984 | </interface> |
4816 | 628 | 985 | ||
4817 | === modified file 'debian/changelog' | |||
4818 | --- debian/changelog 2012-07-30 04:02:24 +0000 | |||
4819 | +++ debian/changelog 2013-05-22 05:08:27 +0000 | |||
4820 | @@ -1,3 +1,38 @@ | |||
4821 | 1 | indicator-weather (13.05.17-quantal2) quantal; urgency=low | ||
4822 | 2 | |||
4823 | 3 | * Fix for 4-day Forecast display (LP: #1182324) | ||
4824 | 4 | * 'OK' button in Preferences Dialog is now more responsive | ||
4825 | 5 | |||
4826 | 6 | -- Joshua Tasker <jtasker@gmail.com> Wed, 22 May 2013 00:32:54 +0500 | ||
4827 | 7 | |||
4828 | 8 | indicator-weather (13.05.17~quantal1) quantal; urgency=low | ||
4829 | 9 | |||
4830 | 10 | * Ported to GTK3 and GObject from PyGTK | ||
4831 | 11 | * Rewrite threading code to avoid dbus-related crashes (LP: #743541) | ||
4832 | 12 | * Added "feels like" temperature (humidex/heat index/wind chill) | ||
4833 | 13 | * New "Conditions" tab in Preferences dialog, choose temperature formulas, toggle display of conditions | ||
4834 | 14 | * Bumped version number to reflect massive changes | ||
4835 | 15 | |||
4836 | 16 | -- Joshua Tasker <jtasker@gmail.com> Sat, 18 May 2013 12:59:03 +0500 | ||
4837 | 17 | |||
4838 | 18 | indicator-weather (12.07.30~quantal2) quantal; urgency=low | ||
4839 | 19 | |||
4840 | 20 | * Don't crash if Yahoo doesn't return conditions | ||
4841 | 21 | * Fixed a crash when reading saved Places with no location IDs | ||
4842 | 22 | * Fix units in Forecast when metric is selected | ||
4843 | 23 | * One-line fix for outdated data sources | ||
4844 | 24 | |||
4845 | 25 | -- Joshua Tasker <jtasker@gmail.com> Sat, 04 May 2013 01:20:38 +0500 | ||
4846 | 26 | |||
4847 | 27 | indicator-weather (12.07.30~quantal1) quantal; urgency=low | ||
4848 | 28 | |||
4849 | 29 | * Fix adding location, now uses Yahoo's YQL service | ||
4850 | 30 | * Fix for "Forecast", now uses Yahoo instead of Google | ||
4851 | 31 | * Bump dependency for python-pywapi to 0.3 | ||
4852 | 32 | * Hide Google radio button on Preferences UI | ||
4853 | 33 | |||
4854 | 34 | -- Joshua Tasker <jtasker@gmail.com> Tue, 09 Apr 2013 02:27:04 +0500 | ||
4855 | 35 | |||
4856 | 1 | indicator-weather (12.07.30~precise1) precise; urgency=low | 36 | indicator-weather (12.07.30~precise1) precise; urgency=low |
4857 | 2 | * Skip sunset and sunrise check as Earthtools.org is down (LP: #964365) | 37 | * Skip sunset and sunrise check as Earthtools.org is down (LP: #964365) |
4858 | 3 | 38 | ||
4859 | 4 | 39 | ||
4860 | === modified file 'debian/control' | |||
4861 | --- debian/control 2011-06-22 09:52:46 +0000 | |||
4862 | +++ debian/control 2013-05-22 05:08:27 +0000 | |||
4863 | @@ -1,26 +1,33 @@ | |||
4864 | 1 | Source: indicator-weather | 1 | Source: indicator-weather |
4865 | 2 | Section: python | 2 | Section: python |
4866 | 3 | Priority: extra | 3 | Priority: extra |
4874 | 4 | Build-Depends: cdbs (>= 0.4.90-1~), | 4 | Build-Depends: debhelper (>= 7.0.50~), |
4875 | 5 | debhelper (>= 6), | 5 | gobject-introspection, |
4876 | 6 | python (>= 2.6.6-3~), | 6 | python (>= 2.6.6-3~), |
4877 | 7 | gobject-introspection, | 7 | python-distutils-extra (>= 2.10) |
4878 | 8 | python-distutils-extra (>= 2.10) | 8 | X-Python-Version: >= 2.6 |
4879 | 9 | Maintainer: Vadim Rutkovsky <roignac@gmail.com> | 9 | Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com> |
4880 | 10 | Standards-Version: 3.8.3 | 10 | Standards-Version: 3.9.3 |
4881 | 11 | Homepage: https://launchpad.net/weather-indicator | ||
4882 | 11 | 12 | ||
4883 | 12 | Package: indicator-weather | 13 | Package: indicator-weather |
4884 | 13 | Architecture: all | 14 | Architecture: all |
4894 | 14 | Depends: ${misc:Depends}, | 15 | Depends: gir1.2-glib-2.0, |
4895 | 15 | ${python:Depends}, | 16 | gir1.2-gtk-3.0, |
4896 | 16 | libglib2.0-bin, | 17 | gir1.2-appindicator3-0.1, |
4897 | 17 | python-appindicator, | 18 | gnome-icon-theme, |
4898 | 18 | python-notify, | 19 | libglib2.0-bin, |
4899 | 19 | python-gobject, | 20 | libgtk-3-bin, |
4900 | 20 | python-gtk2, | 21 | python-gconf, |
4901 | 21 | python-gconf, | 22 | python-gi, |
4902 | 22 | python-pywapi | 23 | python-pywapi (>= 0.3.2 |
4903 | 24 | xdg-utils, | ||
4904 | 25 | ${misc:Depends}, | ||
4905 | 26 | ${python:Depends} | ||
4906 | 23 | Recommends: python-apport | 27 | Recommends: python-apport |
4910 | 24 | Description: A weather indicator for Ubuntu's Indicator Applet | 28 | Description: indicator that displays weather information |
4911 | 25 | A weather indicator that displays information for one or multiple places | 29 | Indicator-Weather displays information for one or multiple places |
4912 | 26 | in the world | 30 | in the world. Current weather status is displayed directly on your |
4913 | 31 | panel and detailed forecasts are no more than a click away. | ||
4914 | 32 | . | ||
4915 | 33 | It is implemented using the Indicator Applet API. | ||
4916 | 27 | 34 | ||
4917 | === modified file 'debian/copyright' | |||
4918 | --- debian/copyright 2011-06-22 09:52:46 +0000 | |||
4919 | +++ debian/copyright 2013-05-22 05:08:27 +0000 | |||
4920 | @@ -1,12 +1,31 @@ | |||
4925 | 1 | Format-Specification: http://wiki.debian.org/Proposals/CopyrightFormat | 1 | Format: http://dep.debian.net/deps/dep5 |
4926 | 2 | Upstream-Name: indicator-weather | 2 | Upstream-Name: Indicator-Weather |
4927 | 3 | Upstream-Maintainer: Vadim Rutkovsky <roignac@gmail.com> | 3 | Upstream-Contact: Vadim Rutkovsky <roignac@gmail.com> |
4928 | 4 | Upstream-Source: https://launchpad.net/weather-indicator | 4 | Source: https://launchpad.net/weather-indicator/+download |
4929 | 5 | 5 | ||
4930 | 6 | Files: * | 6 | Files: * |
4937 | 7 | Copyright: (C) 2010 Mehdi Rejraji mehd36@gmail.com | 7 | Copyright: 2010, Mehdi Rejraji <mehd36@gmail.com> |
4938 | 8 | Copyright: (C) 2010 Sebastian MacDonald Sebas310@gmail.com | 8 | 2010, Sebastian MacDonald <Sebas310@gmail.com> |
4939 | 9 | Copyright: (C) 2011 Vadim Rutkovsky <roignac@gmail.com> | 9 | 2011, Vadim Rutkovsky <roignac@gmail.com> |
4940 | 10 | License: GPL-3 | 10 | 2013, Joshua Tasker <jtasker@gmail.com> |
4941 | 11 | The full text of the GPL is distributed in | 11 | License: GPL-3 |
4942 | 12 | /usr/share/common-licenses/GPL-3 on Debian systems. | 12 | |
4943 | 13 | Files: debian/* | ||
4944 | 14 | Copyright: 2011, Andrew Starr-Bochicchio <a.starr.b@gmail.com> | ||
4945 | 15 | License: GPL-3 | ||
4946 | 16 | |||
4947 | 17 | License: GPL-3 | ||
4948 | 18 | This package is free software; you can redistribute it and/or modify | ||
4949 | 19 | it under the terms of the GNU General Public License as published by | ||
4950 | 20 | the Free Software Foundation; version 3 of the License. | ||
4951 | 21 | . | ||
4952 | 22 | This package is distributed in the hope that it will be useful, | ||
4953 | 23 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
4954 | 24 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
4955 | 25 | GNU General Public License for more details. | ||
4956 | 26 | . | ||
4957 | 27 | You should have received a copy of the GNU General Public License | ||
4958 | 28 | along with this package; if not, write to the Free Software | ||
4959 | 29 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
4960 | 30 | . | ||
4961 | 31 | On Debian systems, see `/usr/share/common-licenses/GPL-3' | ||
4962 | 13 | 32 | ||
4963 | === modified file 'debian/indicator-weather.install' | |||
4964 | --- debian/indicator-weather.install 2011-01-23 14:08:21 +0000 | |||
4965 | +++ debian/indicator-weather.install 2013-05-22 05:08:27 +0000 | |||
4966 | @@ -1,1 +1,2 @@ | |||
4967 | 1 | AUTHORS /usr/share/doc/indicator-weather | ||
4968 | 1 | debian/source_indicator-weather.py usr/share/apport/package-hooks | 2 | debian/source_indicator-weather.py usr/share/apport/package-hooks |
4969 | 2 | 3 | ||
4970 | === modified file 'debian/postinst' | |||
4971 | --- debian/postinst 2011-11-02 15:34:54 +0000 | |||
4972 | +++ debian/postinst 2013-05-22 05:08:27 +0000 | |||
4973 | @@ -1,19 +1,18 @@ | |||
4974 | 1 | #!/bin/sh | 1 | #!/bin/sh |
4976 | 2 | 2 | ||
4977 | 3 | set -e | ||
4978 | 4 | |||
4979 | 3 | #DEBHELPER# | 5 | #DEBHELPER# |
4980 | 6 | |||
4981 | 4 | echo "Installing indicator-specific icons..." | 7 | echo "Installing indicator-specific icons..." |
4982 | 5 | xdg-icon-resource install --theme hicolor --novendor --size 22 /usr/share/indicator-weather/media/icon.png weather-indicator | 8 | xdg-icon-resource install --theme hicolor --novendor --size 22 /usr/share/indicator-weather/media/icon.png weather-indicator |
4983 | 6 | xdg-icon-resource install --theme hicolor --novendor --size 22 /usr/share/indicator-weather/media/icon_unknown_condition.png weather-indicator-unknown | 9 | xdg-icon-resource install --theme hicolor --novendor --size 22 /usr/share/indicator-weather/media/icon_unknown_condition.png weather-indicator-unknown |
4984 | 7 | xdg-icon-resource install --theme hicolor --novendor --size 22 /usr/share/indicator-weather/media/icon_connection_error.png weather-indicator-error | 10 | xdg-icon-resource install --theme hicolor --novendor --size 22 /usr/share/indicator-weather/media/icon_connection_error.png weather-indicator-error |
4985 | 8 | 11 | ||
4986 | 9 | #installing dconf schema | ||
4987 | 10 | echo "Installing indicator dconf schema..." | ||
4988 | 11 | cp /usr/share/indicator-weather/indicator-weather.gschema.xml /usr/share/glib-2.0/schemas | ||
4989 | 12 | glib-compile-schemas /usr/share/glib-2.0/schemas | ||
4990 | 13 | |||
4991 | 14 | #quick fix for incomplete icon themes | 12 | #quick fix for incomplete icon themes |
4992 | 15 | echo "Fixing incomplete weather icons..." | 13 | echo "Fixing incomplete weather icons..." |
4994 | 16 | if [ ! -e "/usr/share/icons/gnome/22x22/status/weather-clouds.png" ]; then | 14 | if [ ! -e "/usr/share/icons/gnome/22x22/status/weather-clouds.png" ] && \ |
4995 | 15 | [ ! -L "/usr/share/icons/gnome/22x22/status/weather-clouds.png" ]; then | ||
4996 | 17 | ln -s /usr/share/icons/gnome/22x22/status/weather-few-clouds.png /usr/share/icons/gnome/22x22/status/weather-clouds.png | 16 | ln -s /usr/share/icons/gnome/22x22/status/weather-few-clouds.png /usr/share/icons/gnome/22x22/status/weather-clouds.png |
4997 | 18 | ln -s /usr/share/icons/gnome/22x22/status/weather-clouds-night.png /usr/share/icons/gnome/22x22/status/weather-clouds-night.png | 17 | ln -s /usr/share/icons/gnome/22x22/status/weather-clouds-night.png /usr/share/icons/gnome/22x22/status/weather-clouds-night.png |
4998 | 19 | 18 | ||
4999 | 20 | 19 | ||
5000 | === modified file 'debian/rules' |
The dbus-related bug I am talking about is this one: https:/ /bugs.launchpad .net/ubuntu/ +source/ indicator- weather/ +bug/743541