You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1522 lines
44 KiB
1522 lines
44 KiB
/*
|
|
*
|
|
* Weather extension for GNOME Shell
|
|
* - Displays a small weather information on the top panel.
|
|
* - On click, gives a popup with details about the weather.
|
|
*
|
|
* Copyright (C) 2011 - 2012
|
|
* ecyrbe <ecyrbe+spam@gmail.com>,
|
|
* Timur Kristof <venemo@msn.com>,
|
|
* Elad Alfassa <elad@fedoraproject.org>,
|
|
* Simon Legner <Simon.Legner@gmail.com>,
|
|
* Christian METZLER <neroth@xeked.com>,
|
|
* Mark Benjamin weather.gnome.Markie1@dfgh.net,
|
|
* Mattia Meneguzzo odysseus@fedoraproject.org,
|
|
* Meng Zhuo <mengzhuo1203+spam@gmail.com>
|
|
*
|
|
*
|
|
* This file is part of gnome-shell-extension-weather.
|
|
*
|
|
* gnome-shell-extension-weather is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* gnome-shell-extension-weather is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with gnome-shell-extension-weather. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
const Cairo = imports.cairo;
|
|
const Clutter = imports.gi.Clutter;
|
|
const Gettext = imports.gettext.domain('gnome-shell-extension-weather');
|
|
const Gio = imports.gi.Gio;
|
|
const Gtk = imports.gi.Gtk;
|
|
const Lang = imports.lang;
|
|
const Mainloop = imports.mainloop;
|
|
const Soup = imports.gi.Soup;
|
|
const Shell = imports.gi.Shell;
|
|
const St = imports.gi.St;
|
|
const Util = imports.misc.util;
|
|
const _ = Gettext.gettext;
|
|
|
|
const Main = imports.ui.main;
|
|
const PanelMenu = imports.ui.panelMenu;
|
|
const PopupMenu = imports.ui.popupMenu;
|
|
|
|
// Settings
|
|
const WEATHER_SETTINGS_SCHEMA = 'org.gnome.shell.extensions.weather';
|
|
const WEATHER_UNIT_KEY = 'unit';
|
|
const WEATHER_WIND_SPEED_UNIT_KEY = 'wind-speed-unit';
|
|
const WEATHER_WIND_DIRECTION_KEY = 'wind-direction';
|
|
const WEATHER_PRESSURE_UNIT_KEY = 'pressure-unit';
|
|
const WEATHER_CITY_KEY = 'city';
|
|
const WEATHER_ACTUAL_CITY_KEY = 'actual-city';
|
|
const WEATHER_TRANSLATE_CONDITION_KEY = 'translate-condition';
|
|
const WEATHER_USE_SYMBOLIC_ICONS_KEY = 'use-symbolic-icons';
|
|
const WEATHER_SHOW_TEXT_IN_PANEL_KEY = 'show-text-in-panel';
|
|
const WEATHER_POSITION_IN_PANEL_KEY = 'position-in-panel';
|
|
const WEATHER_SHOW_COMMENT_IN_PANEL_KEY = 'show-comment-in-panel';
|
|
const WEATHER_REFRESH_INTERVAL = 'refresh-interval';
|
|
|
|
// Keep enums in sync with GSettings schemas
|
|
const WeatherUnits = {
|
|
CELSIUS: 0,
|
|
FAHRENHEIT: 1,
|
|
KELVIN: 2,
|
|
RANKINE: 3,
|
|
REAUMUR: 4,
|
|
ROEMER: 5,
|
|
DELISLE: 6,
|
|
NEWTON: 7
|
|
}
|
|
|
|
const WeatherWindSpeedUnits = {
|
|
KPH: 0,
|
|
MPH: 1,
|
|
MPS: 2,
|
|
KNOTS: 3,
|
|
FPS: 4,
|
|
BEAUFORT: 5
|
|
}
|
|
|
|
const WeatherPressureUnits = {
|
|
hPa: 0,
|
|
inHg: 1,
|
|
bar: 2,
|
|
Pa: 3,
|
|
kPa: 4,
|
|
atm: 5,
|
|
at: 6,
|
|
Torr: 7,
|
|
psi: 8
|
|
}
|
|
|
|
const WeatherPosition = {
|
|
CENTER: 0,
|
|
RIGHT: 1,
|
|
LEFT: 2
|
|
}
|
|
|
|
const WEATHER_CONV_MPH_IN_MPS = 2.23693629;
|
|
const WEATHER_CONV_KPH_IN_MPS = 3.6;
|
|
const WEATHER_CONV_KNOTS_IN_MPS = 1.94384449;
|
|
const WEATHER_CONV_FPS_IN_MPS = 3.2808399;
|
|
|
|
// Soup session (see https://bugzilla.gnome.org/show_bug.cgi?id=661323#c64) (Simon Legner)
|
|
const _httpSession = new Soup.SessionAsync();
|
|
Soup.Session.prototype.add_feature.call(_httpSession, new Soup.ProxyResolverDefault());
|
|
|
|
const WeatherMenuButton = new Lang.Class({
|
|
Name: 'WeatherMenuButton',
|
|
|
|
Extends: PanelMenu.Button,
|
|
|
|
_init: function() {
|
|
// Load settings
|
|
this.loadConfig();
|
|
|
|
// Label
|
|
this._weatherInfo = new St.Label({ text: _('...') });
|
|
|
|
if(typeof St.TextDirection == "undefined")
|
|
{
|
|
// Panel icon
|
|
this._weatherIcon = new St.Icon({
|
|
icon_name: 'view-refresh'+this.icon_type(),
|
|
style_class: 'system-status-icon weather-icon' + (Main.panel.actor.get_text_direction() == Clutter.TextDirection.RTL ? '-rtl' : '')
|
|
});
|
|
|
|
// Panel menu item - the current class
|
|
let menuAlignment = 0.25;
|
|
if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL)
|
|
menuAlignment = 1.0 - menuAlignment;
|
|
this.parent(menuAlignment);
|
|
}
|
|
else
|
|
{
|
|
// Panel icon
|
|
this._weatherIcon = new St.Icon({
|
|
icon_name: 'view-refresh'+this.icon_type(),
|
|
style_class: 'system-status-icon weather-icon' + (Main.panel.actor.get_direction() == St.TextDirection.RTL ? '-rtl' : '')
|
|
});
|
|
|
|
// Panel menu item - the current class
|
|
let menuAlignment = 0.25;
|
|
if (St.Widget.get_default_direction() == St.TextDirection.RTL)
|
|
menuAlignment = 1.0 - menuAlignment;
|
|
PanelMenu.Button.prototype._init.call(this, menuAlignment);
|
|
}
|
|
|
|
// Putting the panel item together
|
|
let topBox = new St.BoxLayout();
|
|
topBox.add_actor(this._weatherIcon);
|
|
topBox.add_actor(this._weatherInfo);
|
|
this.actor.add_actor(topBox);
|
|
|
|
let dummyBox = new St.BoxLayout();
|
|
this.actor.reparent(dummyBox);
|
|
dummyBox.remove_actor(this.actor);
|
|
dummyBox.destroy();
|
|
|
|
let children = null;
|
|
switch (this._position_in_panel) {
|
|
case WeatherPosition.LEFT:
|
|
children = Main.panel._leftBox.get_children();
|
|
Main.panel._leftBox.insert_child_at_index(this.actor, children.length);
|
|
break;
|
|
case WeatherPosition.CENTER:
|
|
children = Main.panel._centerBox.get_children();
|
|
Main.panel._centerBox.insert_child_at_index(this.actor, children.length);
|
|
break;
|
|
case WeatherPosition.RIGHT:
|
|
children = Main.panel._rightBox.get_children();
|
|
Main.panel._rightBox.insert_child_at_index(this.actor, 0);
|
|
break;
|
|
}
|
|
if(typeof Main.panel._menus == "undefined")
|
|
Main.panel.menuManager.addMenu(this.menu);
|
|
else
|
|
Main.panel._menus.addMenu(this.menu);
|
|
|
|
this._old_position_in_panel = this._position_in_panel;
|
|
|
|
// Current weather
|
|
this._currentWeather = new St.Bin({ style_class: 'current' });
|
|
// Future weather
|
|
this._futureWeather = new St.Bin({ style_class: 'forecast'});
|
|
|
|
// Putting the popup item together
|
|
this.menu.addActor(this._currentWeather);
|
|
|
|
let item = new PopupMenu.PopupSeparatorMenuItem();
|
|
this.menu.addMenuItem(item);
|
|
|
|
this.menu.addActor(this._futureWeather);
|
|
|
|
let item = new PopupMenu.PopupSeparatorMenuItem();
|
|
this.menu.addMenuItem(item);
|
|
|
|
this._selectCity = new PopupMenu.PopupSubMenuMenuItem(_("Locations"));
|
|
this.menu.addMenuItem(this._selectCity);
|
|
this.rebuildSelectCityItem();
|
|
|
|
let item = new PopupMenu.PopupMenuItem(_("Reload Weather Information"));
|
|
item.connect('activate', Lang.bind(this, function(){this.refreshWeather(false);}));
|
|
this.menu.addMenuItem(item);
|
|
|
|
let item = new PopupMenu.PopupMenuItem(_("Weather Settings"));
|
|
item.connect('activate', Lang.bind(this, this._onPreferencesActivate));
|
|
this.menu.addMenuItem(item);
|
|
|
|
// Items
|
|
this.showLoadingUi();
|
|
|
|
this.rebuildCurrentWeatherUi();
|
|
this.rebuildFutureWeatherUi();
|
|
|
|
// Show weather
|
|
this.refreshWeather(true);
|
|
|
|
},
|
|
|
|
loadConfig : function()
|
|
{
|
|
var that = this;
|
|
var schema = WEATHER_SETTINGS_SCHEMA;
|
|
if (Gio.Settings.list_schemas().indexOf(schema) == -1)
|
|
throw _("Schema \"%s\" not found.").replace("%s",schema);
|
|
this._settings = new Gio.Settings({ schema: schema });
|
|
this._settings.connect("changed",function(){that.refreshWeather(false);});
|
|
},
|
|
|
|
loadConfigInterface : function()
|
|
{
|
|
var that = this;
|
|
var schemaInterface = "org.gnome.desktop.interface";
|
|
if (Gio.Settings.list_schemas().indexOf(schemaInterface) == -1)
|
|
throw _("Schema \"%s\" not found.").replace("%s",schemaInterface);
|
|
this._settingsInterface = new Gio.Settings({ schema: schemaInterface });
|
|
this._settingsInterface.connect("changed",function(){that.refreshWeather(false);});
|
|
},
|
|
|
|
get _clockFormat()
|
|
{
|
|
if(!this._settingsInterface)
|
|
this.loadConfigInterface();
|
|
return this._settingsInterface.get_string("clock-format");
|
|
},
|
|
|
|
get _units()
|
|
{
|
|
if(!this._settings)
|
|
this.loadConfig();
|
|
return this._settings.get_enum(WEATHER_UNIT_KEY);
|
|
},
|
|
|
|
set _units(v)
|
|
{
|
|
if(!this._settings)
|
|
this.loadConfig();
|
|
this._settings.set_enum(WEATHER_UNIT_KEY,v);
|
|
},
|
|
|
|
get _wind_speed_units()
|
|
{
|
|
if(!this._settings)
|
|
this.loadConfig();
|
|
return this._settings.get_enum(WEATHER_WIND_SPEED_UNIT_KEY);
|
|
},
|
|
|
|
set _wind_speed_units(v)
|
|
{
|
|
if(!this._settings)
|
|
this.loadConfig();
|
|
this._settings.set_enum(WEATHER_WIND_SPEED_UNIT_KEY,v);
|
|
},
|
|
|
|
get _wind_direction()
|
|
{
|
|
if(!this._settings)
|
|
this.loadConfig();
|
|
return this._settings.get_boolean(WEATHER_WIND_DIRECTION_KEY);
|
|
},
|
|
|
|
set _wind_direction(v)
|
|
{
|
|
if(!this._settings)
|
|
this.loadConfig();
|
|
return this._settings.set_boolean(WEATHER_WIND_DIRECTION_KEY,v);
|
|
},
|
|
|
|
get _pressure_units()
|
|
{
|
|
if(!this._settings)
|
|
this.loadConfig();
|
|
return this._settings.get_enum(WEATHER_PRESSURE_UNIT_KEY);
|
|
},
|
|
|
|
set _pressure_units(v)
|
|
{
|
|
if(!this._settings)
|
|
this.loadConfig();
|
|
this._settings.set_enum(WEATHER_PRESSURE_UNIT_KEY,v);
|
|
},
|
|
|
|
get _cities()
|
|
{
|
|
if(!this._settings)
|
|
this.loadConfig();
|
|
return this._settings.get_string(WEATHER_CITY_KEY);
|
|
},
|
|
|
|
set _cities(v)
|
|
{
|
|
if(!this._settings)
|
|
this.loadConfig();
|
|
this._settings.set_string(WEATHER_CITY_KEY,v);
|
|
},
|
|
|
|
get _actual_city()
|
|
{
|
|
if(!this._settings)
|
|
this.loadConfig();
|
|
var a = this._settings.get_int(WEATHER_ACTUAL_CITY_KEY);
|
|
var b = a;
|
|
var cities = this._cities.split(" && ");
|
|
|
|
if(typeof cities != "object")
|
|
cities = [cities];
|
|
|
|
var l = cities.length-1;
|
|
|
|
if(a < 0)
|
|
a = 0;
|
|
|
|
if(l < 0)
|
|
l = 0;
|
|
|
|
if(a > l)
|
|
a = l;
|
|
|
|
return a;
|
|
},
|
|
|
|
set _actual_city(a)
|
|
{
|
|
if(!this._settings)
|
|
this.loadConfig();
|
|
var cities = this._cities.split(" && ");
|
|
|
|
if(typeof cities != "object")
|
|
cities = [cities];
|
|
|
|
var l = cities.length-1;
|
|
|
|
if(a < 0)
|
|
a = 0;
|
|
|
|
if(l < 0)
|
|
l = 0;
|
|
|
|
if(a > l)
|
|
a = l;
|
|
|
|
this._settings.set_int(WEATHER_ACTUAL_CITY_KEY,a);
|
|
},
|
|
|
|
get _city()
|
|
{
|
|
let cities = this._cities;
|
|
let cities = cities.split(" && ");
|
|
if(cities && typeof cities == "string")
|
|
cities = [cities];
|
|
if(!cities[0])
|
|
return "";
|
|
cities = cities[this._actual_city];
|
|
return cities;
|
|
},
|
|
|
|
set _city(v)
|
|
{
|
|
let cities = this._cities;
|
|
cities = cities.split(" && ");
|
|
if(cities && typeof cities == "string")
|
|
cities = [cities];
|
|
if(!cities[0])
|
|
cities = [];
|
|
cities.splice(this.actual_city,1,v);
|
|
cities = cities.join(" && ");
|
|
if(typeof cities != "string")
|
|
cities = cities[0];
|
|
this._cities = cities;
|
|
},
|
|
|
|
get _translate_condition()
|
|
{
|
|
if(!this._settings)
|
|
this.loadConfig();
|
|
return this._settings.get_boolean(WEATHER_TRANSLATE_CONDITION_KEY);
|
|
},
|
|
|
|
set _translate_condition(v)
|
|
{
|
|
if(!this._settings)
|
|
this.loadConfig();
|
|
this._settings.set_boolean(WEATHER_TRANSLATE_CONDITION_KEY,v);
|
|
},
|
|
|
|
get _icon_type()
|
|
{
|
|
if(!this._settings)
|
|
this.loadConfig();
|
|
return this._settings.get_boolean(WEATHER_USE_SYMBOLIC_ICONS_KEY) ? 1 : 0;
|
|
},
|
|
|
|
set _icon_type(v)
|
|
{
|
|
if(!this._settings)
|
|
this.loadConfig();
|
|
this._settings.set_boolean(WEATHER_USE_SYMBOLIC_ICONS_KEY,v);
|
|
},
|
|
|
|
get _text_in_panel()
|
|
{
|
|
if(!this._settings)
|
|
this.loadConfig();
|
|
return this._settings.get_boolean(WEATHER_SHOW_TEXT_IN_PANEL_KEY);
|
|
},
|
|
|
|
set _text_in_panel(v)
|
|
{
|
|
if(!this._settings)
|
|
this.loadConfig();
|
|
this._settings.set_boolean(WEATHER_SHOW_TEXT_IN_PANEL_KEY,v);
|
|
},
|
|
|
|
get _position_in_panel()
|
|
{
|
|
if(!this._settings)
|
|
this.loadConfig();
|
|
return this._settings.get_enum(WEATHER_POSITION_IN_PANEL_KEY);
|
|
},
|
|
|
|
set _position_in_panel(v)
|
|
{
|
|
if(!this._settings)
|
|
this.loadConfig();
|
|
this._settings.set_enum(WEATHER_POSITION_IN_PANEL_KEY,v);
|
|
},
|
|
|
|
get _comment_in_panel()
|
|
{
|
|
if(!this._settings)
|
|
this.loadConfig();
|
|
return this._settings.get_boolean(WEATHER_SHOW_COMMENT_IN_PANEL_KEY);
|
|
},
|
|
|
|
set _comment_in_panel(v)
|
|
{
|
|
if(!this._settings)
|
|
this.loadConfig();
|
|
this._settings.set_boolean(WEATHER_SHOW_COMMENT_IN_PANEL_KEY,v);
|
|
},
|
|
|
|
get _refresh_interval()
|
|
{
|
|
if(!this._settings)
|
|
this.loadConfig();
|
|
return this._settings.get_int(WEATHER_REFRESH_INTERVAL);
|
|
},
|
|
|
|
set _refresh_interval(v)
|
|
{
|
|
if(!this._settings)
|
|
this.loadConfig();
|
|
this._settings.set_int(WEATHER_REFRESH_INTERVAL,v);
|
|
},
|
|
|
|
rebuildSelectCityItem : function()
|
|
{
|
|
let that = this;
|
|
this._selectCity.menu.removeAll();
|
|
let item = null;
|
|
|
|
let cities = this._cities;
|
|
cities = cities.split(" && ");
|
|
if(cities && typeof cities == "string")
|
|
cities = [cities];
|
|
if(!cities[0])
|
|
return 0;
|
|
|
|
for(let i = 0; cities.length > i; i++)
|
|
{
|
|
item = new PopupMenu.PopupMenuItem(this.extractLocation(cities[i]));
|
|
item.location = i;
|
|
if(i == this._actual_city)
|
|
item.setShowDot(true);
|
|
this._selectCity.menu.addMenuItem(item);
|
|
item.connect('activate', function(actor,event)
|
|
{
|
|
that._actual_city = actor.location;
|
|
});
|
|
}
|
|
|
|
if (cities.length == 1)
|
|
this._selectCity.actor.hide();
|
|
else
|
|
this._selectCity.actor.show();
|
|
|
|
return 0;
|
|
},
|
|
|
|
extractLocation : function()
|
|
{
|
|
if(!arguments[0])
|
|
return "";
|
|
|
|
if(arguments[0].search(">") == -1)
|
|
return _("Invalid city");
|
|
return arguments[0].split(">")[1];
|
|
},
|
|
|
|
extractWoeid : function()
|
|
{
|
|
if(!arguments[0])
|
|
return 0;
|
|
|
|
if(arguments[0].search(">") == -1)
|
|
return 0;
|
|
return arguments[0].split(">")[0];
|
|
},
|
|
|
|
updateCities : function()
|
|
{
|
|
let that = this;
|
|
let cities = this._cities;
|
|
|
|
cities = cities.split(" && ");
|
|
if(cities && typeof cities == "string")
|
|
cities = [cities];
|
|
if(!cities[0])
|
|
cities = [];
|
|
|
|
if(cities.length == 0)
|
|
{
|
|
this._cities = "2373572>Cambridge, Massachusetts (US)";
|
|
this.updateCities();
|
|
return 0;
|
|
}
|
|
|
|
for(let a in cities)
|
|
{
|
|
if(!this.extractWoeid(cities[a]))
|
|
{
|
|
this.load_json_async(encodeURI("http://query.yahooapis.com/v1/public/yql?format=json&q=select woeid,name,admin1,country from geo.places where text = '"+cities[a]+"' limit 1"),function()
|
|
{
|
|
let city = arguments[0].query;
|
|
if(typeof city == "object" && typeof city.results == "object")
|
|
city = city.results.place;
|
|
else
|
|
return 0;
|
|
let cityText = city.woeid+">"+city.name;
|
|
if(city.admin1)
|
|
cityText += ", "+city.admin1.content;
|
|
|
|
if(city.country)
|
|
cityText += " ("+city.country.code+")";
|
|
|
|
cities.splice(a,1,cityText);
|
|
cities = cities.join(" && ");
|
|
if(typeof cities != "string")
|
|
cities = cities[0];
|
|
that._cities = cities;
|
|
that.updateCities();
|
|
});
|
|
return 0;
|
|
}
|
|
else
|
|
continue;
|
|
}
|
|
this.refreshWeather();
|
|
return 0;
|
|
},
|
|
|
|
_onPreferencesActivate : function() {
|
|
let app = Shell.AppSystem.get_default().lookup_app('weather-settings.desktop');
|
|
app.activate();
|
|
return 0;
|
|
},
|
|
|
|
unit_to_unicode: function() {
|
|
if(this._units == WeatherUnits.FAHRENHEIT)
|
|
return '\u00B0\F';
|
|
else if(this._units == WeatherUnits.KELVIN)
|
|
return 'K';
|
|
else if(this._units == WeatherUnits.RANKINE)
|
|
return '\u00B0\Ra';
|
|
else if(this._units == WeatherUnits.REAUMUR)
|
|
return '\u00B0\R\u00E9';
|
|
else if(this._units == WeatherUnits.ROEMER)
|
|
return '\u00B0\R\u00F8';
|
|
else if(this._units == WeatherUnits.DELISLE)
|
|
return '\u00B0\De';
|
|
else if(this._units == WeatherUnits.NEWTON)
|
|
return '\u00B0\N';
|
|
else
|
|
return '\u00B0\C';
|
|
},
|
|
|
|
get_weather_url: function() {
|
|
return encodeURI('http://query.yahooapis.com/v1/public/yql?format=json&q=select * from weather.forecast where woeid = '+this.extractWoeid(this._city)+' and u="f"');
|
|
},
|
|
|
|
get_weather_icon: function(code) {
|
|
/* see http://developer.yahoo.com/weather/#codetable */
|
|
/* fallback icons are: weather-clear-night weather-clear weather-few-clouds-night weather-few-clouds weather-fog weather-overcast weather-severe-alert weather-showers weather-showers-scattered weather-snow weather-storm */
|
|
switch (parseInt(code, 10)) {
|
|
case 0:/* tornado */
|
|
return ['weather-severe-alert'];
|
|
case 1:/* tropical storm */
|
|
return ['weather-severe-alert'];
|
|
case 2:/* hurricane */
|
|
return ['weather-severe-alert'];
|
|
case 3:/* severe thunderstorms */
|
|
return ['weather-severe-alert'];
|
|
case 4:/* thunderstorms */
|
|
return ['weather-storm'];
|
|
case 5:/* mixed rain and snow */
|
|
return ['weather-snow-rain', 'weather-snow'];
|
|
case 6:/* mixed rain and sleet */
|
|
return ['weather-snow-rain', 'weather-snow'];
|
|
case 7:/* mixed snow and sleet */
|
|
return ['weather-snow'];
|
|
case 8:/* freezing drizzle */
|
|
return ['weather-freezing-rain', 'weather-showers'];
|
|
case 9:/* drizzle */
|
|
return ['weather-showers'];
|
|
case 10:/* freezing rain */
|
|
return ['weather-freezing-rain', 'weather-showers'];
|
|
case 11:/* showers */
|
|
return ['weather-showers'];
|
|
case 12:/* showers */
|
|
return ['weather-showers'];
|
|
case 13:/* snow flurries */
|
|
return ['weather-snow'];
|
|
case 14:/* light snow showers */
|
|
return ['weather-snow'];
|
|
case 15:/* blowing snow */
|
|
return ['weather-snow'];
|
|
case 16:/* snow */
|
|
return ['weather-snow'];
|
|
case 17:/* hail */
|
|
return ['weather-snow'];
|
|
case 18:/* sleet */
|
|
return ['weather-snow'];
|
|
case 19:/* dust */
|
|
return ['weather-fog'];
|
|
case 20:/* foggy */
|
|
return ['weather-fog'];
|
|
case 21:/* haze */
|
|
return ['weather-fog'];
|
|
case 22:/* smoky */
|
|
return ['weather-fog'];
|
|
case 23:/* blustery */
|
|
return ['weather-few-clouds'];
|
|
case 24:/* windy */
|
|
return ['weather-few-clouds'];
|
|
case 25:/* cold */
|
|
return ['weather-few-clouds'];
|
|
case 26:/* cloudy */
|
|
return ['weather-overcast'];
|
|
case 27:/* mostly cloudy (night) */
|
|
return ['weather-clouds-night', 'weather-few-clouds-night'];
|
|
case 28:/* mostly cloudy (day) */
|
|
return ['weather-clouds', 'weather-overcast'];
|
|
case 29:/* partly cloudy (night) */
|
|
return ['weather-few-clouds-night'];
|
|
case 30:/* partly cloudy (day) */
|
|
return ['weather-few-clouds'];
|
|
case 31:/* clear (night) */
|
|
return ['weather-clear-night'];
|
|
case 32:/* sunny */
|
|
return ['weather-clear'];
|
|
case 33:/* fair (night) */
|
|
return ['weather-clear-night'];
|
|
case 34:/* fair (day) */
|
|
return ['weather-clear'];
|
|
case 35:/* mixed rain and hail */
|
|
return ['weather-snow-rain', 'weather-showers'];
|
|
case 36:/* hot */
|
|
return ['weather-clear'];
|
|
case 37:/* isolated thunderstorms */
|
|
return ['weather-storm'];
|
|
case 38:/* scattered thunderstorms */
|
|
return ['weather-storm'];
|
|
case 39:/* http://developer.yahoo.com/forum/YDN-Documentation/Yahoo-Weather-API-Wrong-Condition-Code/1290534174000-1122fc3d-da6d-34a2-9fb9-d0863e6c5bc6 */
|
|
case 40:/* scattered showers */
|
|
return ['weather-showers-scattered', 'weather-showers'];
|
|
case 41:/* heavy snow */
|
|
return ['weather-snow'];
|
|
case 42:/* scattered snow showers */
|
|
return ['weather-snow'];
|
|
case 43:/* heavy snow */
|
|
return ['weather-snow'];
|
|
case 44:/* partly cloudy */
|
|
return ['weather-few-clouds'];
|
|
case 45:/* thundershowers */
|
|
return ['weather-storm'];
|
|
case 46:/* snow showers */
|
|
return ['weather-snow'];
|
|
case 47:/* isolated thundershowers */
|
|
return ['weather-storm'];
|
|
case 3200:/* not available */
|
|
default:
|
|
return ['weather-severe-alert'];
|
|
}
|
|
},
|
|
|
|
get_weather_icon_safely: function(code) {
|
|
let iconname = this.get_weather_icon(code);
|
|
for (let i = 0; i < iconname.length; i++) {
|
|
if (this.has_icon(iconname[i]))
|
|
return iconname[i]+this.icon_type();
|
|
}
|
|
return 'weather-severe-alert'+this.icon_type();
|
|
},
|
|
|
|
has_icon: function(icon) {
|
|
return Gtk.IconTheme.get_default().has_icon(icon+this.icon_type());
|
|
},
|
|
|
|
get_weather_condition: function(code) {
|
|
switch (parseInt(code, 10)){
|
|
case 0:/* tornado */
|
|
return _('Tornado');
|
|
case 1:/* tropical storm */
|
|
return _('Tropical storm');
|
|
case 2:/* hurricane */
|
|
return _('Hurricane');
|
|
case 3:/* severe thunderstorms */
|
|
return _('Severe thunderstorms');
|
|
case 4:/* thunderstorms */
|
|
return _('Thunderstorms');
|
|
case 5:/* mixed rain and snow */
|
|
return _('Mixed rain and snow');
|
|
case 6:/* mixed rain and sleet */
|
|
return _('Mixed rain and sleet');
|
|
case 7:/* mixed snow and sleet */
|
|
return _('Mixed snow and sleet');
|
|
case 8:/* freezing drizzle */
|
|
return _('Freezing drizzle');
|
|
case 9:/* drizzle */
|
|
return _('Drizzle');
|
|
case 10:/* freezing rain */
|
|
return _('Freezing rain');
|
|
case 11:/* showers */
|
|
return _('Showers');
|
|
case 12:/* showers */
|
|
return _('Showers');
|
|
case 13:/* snow flurries */
|
|
return _('Snow flurries');
|
|
case 14:/* light snow showers */
|
|
return _('Light snow showers');
|
|
case 15:/* blowing snow */
|
|
return _('Blowing snow');
|
|
case 16:/* snow */
|
|
return _('Snow');
|
|
case 17:/* hail */
|
|
return _('Hail');
|
|
case 18:/* sleet */
|
|
return _('Sleet');
|
|
case 19:/* dust */
|
|
return _('Dust');
|
|
case 20:/* foggy */
|
|
return _('Foggy');
|
|
case 21:/* haze */
|
|
return _('Haze');
|
|
case 22:/* smoky */
|
|
return _('Smoky');
|
|
case 23:/* blustery */
|
|
return _('Blustery');
|
|
case 24:/* windy */
|
|
return _('Windy');
|
|
case 25:/* cold */
|
|
return _('Cold');
|
|
case 26:/* cloudy */
|
|
return _('Cloudy');
|
|
case 27:/* mostly cloudy (night) */
|
|
case 28:/* mostly cloudy (day) */
|
|
return _('Mostly cloudy');
|
|
case 29:/* partly cloudy (night) */
|
|
case 30:/* partly cloudy (day) */
|
|
return _('Partly cloudy');
|
|
case 31:/* clear (night) */
|
|
return _('Clear');
|
|
case 32:/* sunny */
|
|
return _('Sunny');
|
|
case 33:/* fair (night) */
|
|
case 34:/* fair (day) */
|
|
return _('Fair');
|
|
case 35:/* mixed rain and hail */
|
|
return _('Mixed rain and hail');
|
|
case 36:/* hot */
|
|
return _('Hot');
|
|
case 37:/* isolated thunderstorms */
|
|
return _('Isolated thunderstorms');
|
|
case 38:/* scattered thunderstorms */
|
|
case 39:/* scattered thunderstorms */
|
|
return _('Scattered thunderstorms');
|
|
case 40:/* scattered showers */
|
|
return _('Scattered showers');
|
|
case 41:/* heavy snow */
|
|
return _('Heavy snow');
|
|
case 42:/* scattered snow showers */
|
|
return _('Scattered snow showers');
|
|
case 43:/* heavy snow */
|
|
return _('Heavy snow');
|
|
case 44:/* partly cloudy */
|
|
return _('Partly cloudy');
|
|
case 45:/* thundershowers */
|
|
return _('Thundershowers');
|
|
case 46:/* snow showers */
|
|
return _('Snow showers');
|
|
case 47:/* isolated thundershowers */
|
|
return _('Isolated thundershowers');
|
|
case 3200:/* not available */
|
|
default:
|
|
return _('Not available');
|
|
}
|
|
},
|
|
|
|
toCelsius: function(t)
|
|
{
|
|
return String(Math.round((Number(t)-32)*0.555556));
|
|
},
|
|
|
|
toKelvin: function(t)
|
|
{
|
|
return String(Math.round(((Number(t)+459.67)/1.8)*100)/100);
|
|
},
|
|
|
|
toRankine: function(t)
|
|
{
|
|
return String(Math.round((Number(t)+459.67)*100)/100);
|
|
},
|
|
|
|
toReaumur: function(t)
|
|
{
|
|
return String(Math.round((Number(t)-32)/2.25));
|
|
},
|
|
|
|
toRoemer: function(t)
|
|
{
|
|
return String(Math.round((((Number(t)-32)*7)/24)+7.5));
|
|
},
|
|
|
|
toDelisle: function(t)
|
|
{
|
|
return String(Math.round(((212-Number(t))*5)/6));
|
|
},
|
|
|
|
toNewton: function(t)
|
|
{
|
|
return String(Math.round((((Number(t)-32)*11)/60)*10)/10);
|
|
},
|
|
|
|
toPascal: function(p,t)
|
|
{
|
|
return Math.round((p * (3386.39-((t-32)*0.003407143))));
|
|
},
|
|
|
|
toBeaufort: function(w,t)
|
|
{
|
|
if(w < 1)
|
|
return (!t)?"0":"("+_("Calm")+")";
|
|
else if(w >= 1 && w <= 3)
|
|
return (!t)?"1":"("+_("Light air")+")";
|
|
else if(w >= 4 && w <= 7)
|
|
return (!t)?"2":"("+_("Light breeze")+")";
|
|
else if(w >= 8 && w <= 12)
|
|
return (!t)?"3":"("+_("Gentle breeze")+")";
|
|
else if(w >= 13 && w <= 17)
|
|
return (!t)?"4":"("+_("Moderate breeze")+")";
|
|
else if(w >= 18 && w <= 24)
|
|
return (!t)?"5":"("+_("Fresh breeze")+")";
|
|
else if(w >= 25 && w <= 30)
|
|
return (!t)?"6":"("+_("Strong breeze")+")";
|
|
else if(w >= 31 && w <= 38)
|
|
return (!t)?"7":"("+_("Moderate gale")+")";
|
|
else if(w >= 39 && w <= 46)
|
|
return (!t)?"8":"("+_("Fresh gale")+")";
|
|
else if(w >= 47 && w <= 54)
|
|
return (!t)?"9":"("+_("Strong gale")+")";
|
|
else if(w >= 55 && w <= 63)
|
|
return (!t)?"10":"("+_("Storm")+")";
|
|
else if(w >= 64 && w <= 73)
|
|
return (!t)?"11":"("+_("Violent storm")+")";
|
|
else
|
|
return (!t)?"12":"("+_("Hurricane")+")";
|
|
},
|
|
|
|
get_locale_day: function(abr)
|
|
{
|
|
let days = [_('Sunday'),_('Monday'), _('Tuesday'), _('Wednesday'), _('Thursday'), _('Friday'), _('Saturday')];
|
|
return days[abr];
|
|
},
|
|
|
|
get_wind_direction : function(deg)
|
|
{
|
|
let arrows = ["\u2193", "\u2199", "\u2190", "\u2196", "\u2191", "\u2197", "\u2192", "\u2198"];
|
|
let letters = [_('N'), _('NE'), _('E'), _('SE'), _('S'), _('SW'), _('W'), _('NW')];
|
|
let idx = Math.round(deg / 45) % arrows.length;
|
|
return (this._wind_direction)?arrows[idx]:letters[idx];
|
|
},
|
|
|
|
get_pressure_state : function(state)
|
|
{
|
|
switch(parseInt(state, 3))
|
|
{
|
|
case 0:
|
|
return '';
|
|
break;
|
|
|
|
case 1:
|
|
return '\u2934';
|
|
break;
|
|
|
|
case 2:
|
|
return '\u2935';
|
|
break;
|
|
}
|
|
return 0;
|
|
},
|
|
|
|
icon_type : function(icon_name)
|
|
{
|
|
if(!icon_name)
|
|
if(this._icon_type)
|
|
return "-symbolic";
|
|
else
|
|
return "";
|
|
|
|
if(this._icon_type)
|
|
if(String(icon_name).search("-symbolic") != -1)
|
|
return icon_name;
|
|
else
|
|
return icon_name+"-symbolic";
|
|
else
|
|
if(String(icon_name).search("-symbolic") != -1)
|
|
return String(icon_name).replace("-symbolic","");
|
|
else
|
|
return icon_name;
|
|
},
|
|
|
|
load_json_async: function(url, fun) {
|
|
let here = this;
|
|
|
|
let message = Soup.Message.new('GET', url);
|
|
|
|
_httpSession.queue_message(message, function(_httpSession, message) {
|
|
if(!message.response_body.data)
|
|
{
|
|
fun.call(here,0);
|
|
return 0;
|
|
}
|
|
|
|
try
|
|
{
|
|
let jp = JSON.parse(message.response_body.data);
|
|
fun.call(here, jp);
|
|
}
|
|
catch(e)
|
|
{
|
|
fun.call(here,0);
|
|
return 0;
|
|
}
|
|
});
|
|
return 0;
|
|
},
|
|
|
|
refreshWeather: function(recurse)
|
|
{
|
|
if(!this.extractWoeid(this._city))
|
|
{
|
|
this.updateCities();
|
|
return 0;
|
|
}
|
|
this.load_json_async(this.get_weather_url(), function(json)
|
|
{
|
|
if(!json)
|
|
return 0;
|
|
let weather = json.query.results.channel;
|
|
let many = 0;
|
|
if(typeof weather[0] != "undefined")
|
|
{
|
|
weather = weather[0];
|
|
many = 1;
|
|
}
|
|
let weather_c = weather.item.condition;
|
|
|
|
this.rebuildSelectCityItem();
|
|
|
|
this._weatherIcon.icon_name = this.icon_type(this._weatherIcon.icon_name);
|
|
this._currentWeatherIcon.icon_name = this.icon_type(this._currentWeatherIcon.icon_name);
|
|
this._forecast[0].Icon.icon_name = this.icon_type(this._forecast[0].Icon.icon_name);
|
|
this._forecast[1].Icon.icon_name = this.icon_type(this._forecast[1].Icon.icon_name);
|
|
this._sunriseIcon.icon_name = this.icon_type(this._sunriseIcon.icon_name);
|
|
this._sunsetIcon.icon_name = this.icon_type(this._sunsetIcon.icon_name);
|
|
this._buildIcon.icon_name = this.icon_type(this._buildIcon.icon_name);
|
|
|
|
if(typeof St.IconType != "undefined")
|
|
{
|
|
this._weatherIcon.icon_type = (this._icon_type) ? St.IconType.SYMBOLIC : St.IconType.FULLCOLOR;
|
|
this._currentWeatherIcon.icon_type = (this._icon_type) ? St.IconType.SYMBOLIC : St.IconType.FULLCOLOR;
|
|
this._forecast[0].Icon.icon_type = (this._icon_type) ? St.IconType.SYMBOLIC : St.IconType.FULLCOLOR;
|
|
this._forecast[1].Icon.icon_type = (this._icon_type) ? St.IconType.SYMBOLIC : St.IconType.FULLCOLOR;
|
|
this._sunriseIcon.icon_type = (this._icon_type) ? St.IconType.SYMBOLIC : St.IconType.FULLCOLOR;
|
|
this._sunsetIcon.icon_type = (this._icon_type) ? St.IconType.SYMBOLIC : St.IconType.FULLCOLOR;
|
|
this._buildIcon.icon_type = (this._icon_type) ? St.IconType.SYMBOLIC : St.IconType.FULLCOLOR;
|
|
}
|
|
|
|
if(this._old_position_in_panel != this._position_in_panel)
|
|
{
|
|
switch (this._old_position_in_panel) {
|
|
case WeatherPosition.LEFT:
|
|
Main.panel._leftBox.remove_actor(this.actor);
|
|
break;
|
|
case WeatherPosition.CENTER:
|
|
Main.panel._centerBox.remove_actor(this.actor);
|
|
break;
|
|
case WeatherPosition.RIGHT:
|
|
Main.panel._rightBox.remove_actor(this.actor);
|
|
break;
|
|
}
|
|
|
|
let children = null;
|
|
switch (this._position_in_panel) {
|
|
case WeatherPosition.LEFT:
|
|
children = Main.panel._leftBox.get_children();
|
|
Main.panel._leftBox.insert_child_at_index(this.actor, children.length);
|
|
break;
|
|
case WeatherPosition.CENTER:
|
|
children = Main.panel._centerBox.get_children();
|
|
Main.panel._centerBox.insert_child_at_index(this.actor, children.length);
|
|
break;
|
|
case WeatherPosition.RIGHT:
|
|
children = Main.panel._rightBox.get_children();
|
|
Main.panel._rightBox.insert_child_at_index(this.actor, 0);
|
|
break;
|
|
}
|
|
this._old_position_in_panel = this._position_in_panel;
|
|
}
|
|
|
|
let forecast = weather.item.forecast;
|
|
let location = this.extractLocation(this._city);
|
|
|
|
// Refresh current weather
|
|
let comment = weather_c.text;
|
|
if (this._translate_condition)
|
|
comment = this.get_weather_condition(weather_c.code);
|
|
|
|
let temperature = weather_c.temp;
|
|
let chill = weather.wind.chill;
|
|
let humidity = weather.atmosphere.humidity + ' %';
|
|
let pressure = weather.atmosphere.pressure;
|
|
let pressure_unit = weather.units.pressure;
|
|
let pressure_state = weather.atmosphere.rising;
|
|
let wind_direction = this.get_wind_direction(weather.wind.direction);
|
|
let wind = weather.wind.speed;
|
|
let wind_unit = weather.units.speed;
|
|
let iconname = this.get_weather_icon_safely(weather_c.code);
|
|
let sunrise = weather.astronomy.sunrise;
|
|
let sunset = weather.astronomy.sunset;
|
|
|
|
if(typeof this.lastBuildId == "undefined")
|
|
this.lastBuildId = 0;
|
|
|
|
if(typeof this.lastBuildDate == "undefined")
|
|
this.lastBuildDate = 0;
|
|
|
|
if(this.lastBuildId != weather_c.date || !this.lastBuildDate)
|
|
{
|
|
this.lastBuildId = weather_c.date;
|
|
this.lastBuildDate = new Date();
|
|
}
|
|
|
|
let actualDate = new Date();
|
|
let d = Math.floor((actualDate.getTime()-this.lastBuildDate.getTime())/86400000);
|
|
|
|
switch(this._pressure_units)
|
|
{
|
|
case WeatherPressureUnits.inHg:
|
|
pressure_unit = "inHg";
|
|
break;
|
|
|
|
case WeatherPressureUnits.hPa:
|
|
pressure = Math.round(this.toPascal(pressure,temperature)/100);
|
|
pressure_unit = "hPa";
|
|
break;
|
|
|
|
case WeatherPressureUnits.bar:
|
|
pressure = this.toPascal(pressure,temperature)/100000;
|
|
pressure_unit = "bar";
|
|
break;
|
|
|
|
case WeatherPressureUnits.Pa:
|
|
pressure = this.toPascal(pressure,temperature);
|
|
pressure_unit = "Pa";
|
|
break;
|
|
|
|
case WeatherPressureUnits.kPa:
|
|
pressure = Math.round(this.toPascal(pressure,temperature)/100)/10;
|
|
pressure_unit = "kPa";
|
|
break;
|
|
|
|
case WeatherPressureUnits.atm:
|
|
pressure = Math.round((this.toPascal(pressure,temperature)*0.00000986923267)*100000)/100000;
|
|
pressure_unit = "atm";
|
|
break;
|
|
|
|
case WeatherPressureUnits.at:
|
|
pressure = Math.round((this.toPascal(pressure,temperature)*0.0000101971621298)*100000)/100000;
|
|
pressure_unit = "at";
|
|
break;
|
|
|
|
case WeatherPressureUnits.Torr:
|
|
pressure = Math.round((this.toPascal(pressure,temperature)*0.00750061683)*100)/100;
|
|
pressure_unit = "Torr";
|
|
break;
|
|
|
|
case WeatherPressureUnits.psi:
|
|
pressure = Math.round((this.toPascal(pressure,temperature)*0.000145037738)*100)/100;
|
|
pressure_unit = "psi";
|
|
break;
|
|
}
|
|
|
|
switch(this._units)
|
|
{
|
|
case WeatherUnits.FAHRENHEIT:
|
|
break;
|
|
|
|
case WeatherUnits.CELSIUS:
|
|
temperature = this.toCelsius(temperature);
|
|
chill = this.toCelsius(chill);
|
|
break;
|
|
|
|
case WeatherUnits.KELVIN:
|
|
temperature = this.toKelvin(temperature);
|
|
chill = this.toKelvin(chill);
|
|
break;
|
|
|
|
case WeatherUnits.RANKINE:
|
|
temperature = this.toRankine(temperature);
|
|
chill = this.toRankine(chill);
|
|
break;
|
|
|
|
case WeatherUnits.REAUMUR:
|
|
temperature = this.toReaumur(temperature);
|
|
chill = this.toReaumur(chill);
|
|
break;
|
|
|
|
case WeatherUnits.ROEMER:
|
|
temperature = this.toRoemer(temperature);
|
|
chill = this.toRoemer(chill);
|
|
break;
|
|
|
|
case WeatherUnits.DELISLE:
|
|
temperature = this.toDelisle(temperature);
|
|
chill = this.toDelisle(chill);
|
|
break;
|
|
|
|
case WeatherUnits.NEWTON:
|
|
temperature = this.toNewton(temperature);
|
|
chill = this.toNewton(chill);
|
|
break;
|
|
}
|
|
|
|
let lastBuild = (this.lastBuildDate.getHours()%12)+":"+((this.lastBuildDate.getMinutes()<10)?"0":"")+this.lastBuildDate.getMinutes()+" "+((this.lastBuildDate.getHours() >= 12)?"pm":"am");
|
|
|
|
if(this._clockFormat == "24h")
|
|
{
|
|
sunrise = new Date("3 Mar 1999 "+sunrise);
|
|
sunrise = sunrise.getHours()+":"+((sunrise.getMinutes()<10)?"0":"")+sunrise.getMinutes();
|
|
sunset = new Date("3 Mar 1999 "+sunset);
|
|
sunset = sunset.getHours()+":"+((sunset.getMinutes()<10)?"0":"")+sunset.getMinutes();
|
|
lastBuild = this.lastBuildDate.getHours()+":"+((this.lastBuildDate.getMinutes()<10)?"0":"")+this.lastBuildDate.getMinutes();
|
|
}
|
|
|
|
if(d >= 1)
|
|
{
|
|
lastBuild = _("Yesterday");
|
|
if(d > 1)
|
|
lastBuild = _("%s days ago").replace("%s",d);
|
|
}
|
|
|
|
this._currentWeatherIcon.icon_name = this._weatherIcon.icon_name = iconname;
|
|
|
|
let weatherInfoC = "";
|
|
let weatherInfoT = "";
|
|
|
|
if (this._comment_in_panel)
|
|
weatherInfoC = comment;
|
|
|
|
if (this._text_in_panel)
|
|
weatherInfoT = parseFloat(temperature).toLocaleString() + ' ' + this.unit_to_unicode();
|
|
|
|
this._weatherInfo.text = weatherInfoC + ((weatherInfoC && weatherInfoT) ? ", " : "") + weatherInfoT;
|
|
|
|
this._currentWeatherSummary.text = comment + ", " + parseFloat(temperature).toLocaleString() + ' ' + this.unit_to_unicode();
|
|
this._currentWeatherLocation.text = location;
|
|
this._currentWeatherTemperature.text = parseFloat(chill).toLocaleString() + ' ' + this.unit_to_unicode();
|
|
this._currentWeatherHumidity.text = parseFloat(humidity).toLocaleString() + ' %';
|
|
this._currentWeatherPressure.text = parseFloat(pressure).toLocaleString() + ' ' + pressure_unit + ((pressure_state)?" ":"") + this.get_pressure_state(pressure_state);
|
|
this._currentWeatherSunrise.text = sunrise;
|
|
this._currentWeatherSunset.text = sunset;
|
|
this._currentWeatherBuild.text = lastBuild;
|
|
|
|
// Override wind units with our preference
|
|
// Need to consider what units the Yahoo API has returned it in
|
|
switch (this._wind_speed_units)
|
|
{
|
|
case WeatherWindSpeedUnits.MPH:
|
|
break;
|
|
|
|
case WeatherWindSpeedUnits.KPH:
|
|
wind = Math.round (wind / WEATHER_CONV_MPH_IN_MPS * WEATHER_CONV_KPH_IN_MPS);
|
|
wind_unit = 'km/h';
|
|
break;
|
|
|
|
case WeatherWindSpeedUnits.MPS:
|
|
wind = Math.round ((wind / WEATHER_CONV_MPH_IN_MPS) * 10)/ 10;
|
|
wind_unit = 'm/s';
|
|
break;
|
|
|
|
case WeatherWindSpeedUnits.KNOTS:
|
|
wind = Math.round (wind / WEATHER_CONV_MPH_IN_MPS * WEATHER_CONV_KNOTS_IN_MPS);
|
|
wind_unit = 'kn';
|
|
break;
|
|
|
|
case WeatherWindSpeedUnits.FPS:
|
|
wind = Math.round (wind / WEATHER_CONV_MPH_IN_MPS * WEATHER_CONV_FPS_IN_MPS);
|
|
wind_unit = 'ft/s';
|
|
break;
|
|
|
|
case WeatherWindSpeedUnits.BEAUFORT:
|
|
wind_unit = this.toBeaufort(wind,true);
|
|
wind = this.toBeaufort(wind);
|
|
}
|
|
|
|
if (!wind)
|
|
this._currentWeatherWind.text = '\u2013';
|
|
else if (wind == 0 || !wind_direction)
|
|
this._currentWeatherWind.text = parseFloat(wind).toLocaleString() + ' ' + wind_unit;
|
|
else // i.e. wind > 0 && wind_direction
|
|
this._currentWeatherWind.text = wind_direction + ' ' + parseFloat(wind).toLocaleString() + ' ' + wind_unit;
|
|
|
|
// Refresh forecast
|
|
for (let i = 0; i <= 1; i++) {
|
|
let forecastUi = this._forecast[i];
|
|
let forecastData = forecast[i];
|
|
|
|
let code = forecastData.code;
|
|
let t_low = forecastData.low;
|
|
let t_high = forecastData.high;
|
|
|
|
switch(this._units)
|
|
{
|
|
case WeatherUnits.FAHRENHEIT:
|
|
break;
|
|
|
|
case WeatherUnits.CELSIUS:
|
|
t_low = this.toCelsius(t_low);
|
|
t_high = this.toCelsius(t_high);
|
|
break;
|
|
|
|
case WeatherUnits.KELVIN:
|
|
t_low = this.toKelvin(t_low);
|
|
t_high = this.toKelvin(t_high);
|
|
break;
|
|
|
|
case WeatherUnits.RANKINE:
|
|
t_low = this.toRankine(t_low);
|
|
t_high = this.toRankine(t_high);
|
|
break;
|
|
|
|
case WeatherUnits.REAUMUR:
|
|
t_low = this.toReaumur(t_low);
|
|
t_high = this.toReaumur(t_high);
|
|
break;
|
|
|
|
case WeatherUnits.ROEMER:
|
|
t_low = this.toRoemer(t_low);
|
|
t_high = this.toRoemer(t_high);
|
|
break;
|
|
|
|
case WeatherUnits.DELISLE:
|
|
t_low = this.toDelisle(t_low);
|
|
t_high = this.toDelisle(t_high);
|
|
break;
|
|
|
|
case WeatherUnits.NEWTON:
|
|
t_low = this.toNewton(t_low);
|
|
t_high = this.toNewton(t_high);
|
|
break;
|
|
}
|
|
|
|
let comment = forecastData.text;
|
|
if (this._translate_condition)
|
|
comment = this.get_weather_condition(code);
|
|
|
|
let forecastDate = new Date(forecastData.date);
|
|
let dayLeft = Math.floor((actualDate.getTime()-forecastDate.getTime())/1000/60/60/24);
|
|
|
|
let date_string = _("Today");
|
|
if(dayLeft == -1)
|
|
date_string = _("Tomorrow");
|
|
else if(dayLeft < -1)
|
|
date_string = _("In %s days").replace("%s",-1*dayLeft);
|
|
else if(dayLeft == 1)
|
|
date_string = _("Yesterday");
|
|
else if(dayLeft > 1)
|
|
date_string = _("%s days ago").replace("%s",dayLeft);
|
|
|
|
forecastUi.Day.text = date_string + ' (' + this.get_locale_day(forecastDate.getDay()) + ')';
|
|
forecastUi.Temperature.text = '\u2193 ' + parseFloat(t_low).toLocaleString() + ' ' + this.unit_to_unicode() + ' \u2191 ' + parseFloat(t_high).toLocaleString() + ' ' + this.unit_to_unicode();
|
|
forecastUi.Summary.text = comment;
|
|
forecastUi.Icon.icon_name = this.get_weather_icon_safely(code);
|
|
}
|
|
return 0;
|
|
});
|
|
|
|
// Repeatedly refresh weather if recurse is set
|
|
if (recurse) {
|
|
Mainloop.timeout_add_seconds(this._refresh_interval, Lang.bind(this, function() {
|
|
this.refreshWeather(true);
|
|
}));
|
|
}
|
|
return 0;
|
|
},
|
|
|
|
destroyCurrentWeather: function() {
|
|
if (this._currentWeather.get_child() != null)
|
|
this._currentWeather.get_child().destroy();
|
|
},
|
|
|
|
destroyFutureWeather: function() {
|
|
if (this._futureWeather.get_child() != null)
|
|
this._futureWeather.get_child().destroy();
|
|
},
|
|
|
|
showLoadingUi: function() {
|
|
this.destroyCurrentWeather();
|
|
this.destroyFutureWeather();
|
|
this._currentWeather.set_child(new St.Label({ text: _('Loading current weather ...') }));
|
|
this._futureWeather.set_child(new St.Label({ text: _('Loading future weather ...') }));
|
|
},
|
|
|
|
rebuildCurrentWeatherUi: function() {
|
|
this.destroyCurrentWeather();
|
|
|
|
// This will hold the icon for the current weather
|
|
this._currentWeatherIcon = new St.Icon({
|
|
icon_size: 72,
|
|
icon_name: 'view-refresh'+this.icon_type(),
|
|
style_class: 'weather-current-icon'
|
|
});
|
|
|
|
this._sunriseIcon = new St.Icon({
|
|
icon_size: 15,
|
|
icon_name: 'weather-clear'+this.icon_type(),
|
|
style_class: 'weather-sunrise-icon'
|
|
});
|
|
|
|
this._sunsetIcon = new St.Icon({
|
|
icon_size: 15,
|
|
icon_name: 'weather-clear-night'+this.icon_type(),
|
|
style_class: 'weather-sunset-icon'
|
|
});
|
|
|
|
this._buildIcon = new St.Icon({
|
|
icon_size: 15,
|
|
icon_name: 'view-refresh'+this.icon_type(),
|
|
style_class: 'weather-build-icon'
|
|
});
|
|
|
|
// The summary of the current weather
|
|
this._currentWeatherSummary = new St.Label({
|
|
text: _('Loading ...'),
|
|
style_class: 'weather-current-summary'
|
|
});
|
|
this._currentWeatherLocation = new St.Label({ text: _('Please wait') });
|
|
|
|
let bb = new St.BoxLayout({
|
|
vertical: true,
|
|
style_class: 'weather-current-summarybox'
|
|
});
|
|
bb.add_actor(this._currentWeatherLocation);
|
|
bb.add_actor(this._currentWeatherSummary);
|
|
|
|
this._currentWeatherSunrise = new St.Label({ text: '-' });
|
|
this._currentWeatherSunset = new St.Label({ text: '-' });
|
|
this._currentWeatherBuild = new St.Label({ text: '-' });
|
|
|
|
let ab = new St.BoxLayout({
|
|
style_class: 'weather-current-infobox'
|
|
});
|
|
|
|
ab.add_actor(this._sunriseIcon);
|
|
ab.add_actor(this._currentWeatherSunrise);
|
|
ab.add_actor(this._sunsetIcon);
|
|
ab.add_actor(this._currentWeatherSunset);
|
|
ab.add_actor(this._buildIcon);
|
|
ab.add_actor(this._currentWeatherBuild);
|
|
bb.add_actor(ab);
|
|
|
|
// Other labels
|
|
this._currentWeatherTemperature = new St.Label({ text: '...' });
|
|
this._currentWeatherHumidity = new St.Label({ text: '...' });
|
|
this._currentWeatherPressure = new St.Label({ text: '...' });
|
|
this._currentWeatherWind = new St.Label({ text: '...' });
|
|
|
|
let rb = new St.BoxLayout({
|
|
style_class: 'weather-current-databox'
|
|
});
|
|
let rb_captions = new St.BoxLayout({
|
|
vertical: true,
|
|
style_class: 'weather-current-databox-captions'
|
|
});
|
|
let rb_values = new St.BoxLayout({
|
|
vertical: true,
|
|
style_class: 'weather-current-databox-values'
|
|
});
|
|
rb.add_actor(rb_captions);
|
|
rb.add_actor(rb_values);
|
|
|
|
rb_captions.add_actor(new St.Label({text: _('Feel like:')}));
|
|
rb_values.add_actor(this._currentWeatherTemperature);
|
|
rb_captions.add_actor(new St.Label({text: _('Humidity:')}));
|
|
rb_values.add_actor(this._currentWeatherHumidity);
|
|
rb_captions.add_actor(new St.Label({text: _('Pressure:')}));
|
|
rb_values.add_actor(this._currentWeatherPressure);
|
|
rb_captions.add_actor(new St.Label({text: _('Wind:')}));
|
|
rb_values.add_actor(this._currentWeatherWind);
|
|
|
|
let xb = new St.BoxLayout();
|
|
xb.add_actor(bb);
|
|
xb.add_actor(rb);
|
|
|
|
let box = new St.BoxLayout({
|
|
style_class: 'weather-current-iconbox'
|
|
});
|
|
box.add_actor(this._currentWeatherIcon);
|
|
box.add_actor(xb);
|
|
this._currentWeather.set_child(box);
|
|
|
|
},
|
|
|
|
rebuildFutureWeatherUi: function() {
|
|
this.destroyFutureWeather();
|
|
|
|
this._forecast = [];
|
|
this._forecastBox = new St.BoxLayout();
|
|
this._futureWeather.set_child(this._forecastBox);
|
|
|
|
for (let i = 0; i <= 1; i++) {
|
|
let forecastWeather = {};
|
|
|
|
forecastWeather.Icon = new St.Icon({
|
|
icon_size: 48,
|
|
icon_name: 'view-refresh'+this.icon_type(),
|
|
style_class: 'weather-forecast-icon'
|
|
});
|
|
forecastWeather.Day = new St.Label({
|
|
style_class: 'weather-forecast-day'
|
|
});
|
|
forecastWeather.Summary = new St.Label({
|
|
style_class: 'weather-forecast-summary'
|
|
});
|
|
forecastWeather.Temperature = new St.Label({
|
|
style_class: 'weather-forecast-temperature'
|
|
});
|
|
|
|
let by = new St.BoxLayout({
|
|
vertical: true,
|
|
style_class: 'weather-forecast-databox'
|
|
});
|
|
by.add_actor(forecastWeather.Day);
|
|
by.add_actor(forecastWeather.Summary);
|
|
by.add_actor(forecastWeather.Temperature);
|
|
|
|
let bb = new St.BoxLayout({
|
|
style_class: 'weather-forecast-box'
|
|
});
|
|
bb.add_actor(forecastWeather.Icon);
|
|
bb.add_actor(by);
|
|
|
|
this._forecast[i] = forecastWeather;
|
|
this._forecastBox.add_actor(bb);
|
|
|
|
}
|
|
|
|
}
|
|
});
|
|
|
|
let weatherMenu;
|
|
|
|
function init() {
|
|
}
|
|
|
|
function enable() {
|
|
weatherMenu = new WeatherMenuButton();
|
|
Main.panel.addToStatusArea('weatherMenu', weatherMenu);
|
|
}
|
|
|
|
function disable() {
|
|
weatherMenu.destroy();
|
|
}
|
|
|