/* jshint esnext:true */
/ *
*
* 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 - 2013
* 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 > ,
* Jens Lody < jens @ jenslody . de >
* Copyright ( C ) 2014 - 2015
* Jens Lody < jens @ jenslody . de > ,
*
*
* This file is part of gnome - shell - extension - openweather .
*
* gnome - shell - extension - openweather 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 - openweather 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 - openweather . If not , see < http : //www.gnu.org/licenses/>.
*
* /
const ExtensionUtils = imports . misc . extensionUtils ;
const Me = ExtensionUtils . getCurrentExtension ( ) ;
const Config = imports . misc . config ;
const Convenience = Me . imports . convenience ;
const ForecastIo = Me . imports . forecast _io ;
const OpenweathermapOrg = Me . imports . openweathermap _org ;
const Clutter = imports . gi . Clutter ;
const Gettext = imports . gettext . domain ( 'gnome-shell-extension-openweather' ) ;
const Gio = imports . gi . Gio ;
const Gtk = imports . gi . Gtk ;
const GLib = imports . gi . GLib ;
const Lang = imports . lang ;
const Mainloop = imports . mainloop ;
const Soup = imports . gi . Soup ;
const St = imports . gi . St ;
const GnomeSession = imports . misc . gnomeSession ;
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 OPENWEATHER _SETTINGS _SCHEMA = 'org.gnome.shell.extensions.openweather' ;
const OPENWEATHER _DESKTOP _INTERFACE = 'org.gnome.desktop.interface' ;
const OPENWEATHER _PROVIDER _KEY = 'weather-provider' ;
const OPENWEATHER _UNIT _KEY = 'unit' ;
const OPENWEATHER _WIND _SPEED _UNIT _KEY = 'wind-speed-unit' ;
const OPENWEATHER _WIND _DIRECTION _KEY = 'wind-direction' ;
const OPENWEATHER _PRESSURE _UNIT _KEY = 'pressure-unit' ;
const OPENWEATHER _CITY _KEY = 'city' ;
const OPENWEATHER _ACTUAL _CITY _KEY = 'actual-city' ;
const OPENWEATHER _TRANSLATE _CONDITION _KEY = 'translate-condition' ;
const OPENWEATHER _USE _SYMBOLIC _ICONS _KEY = 'use-symbolic-icons' ;
const OPENWEATHER _USE _TEXT _ON _BUTTONS _KEY = 'use-text-on-buttons' ;
const OPENWEATHER _SHOW _TEXT _IN _PANEL _KEY = 'show-text-in-panel' ;
const OPENWEATHER _POSITION _IN _PANEL _KEY = 'position-in-panel' ;
const OPENWEATHER _SHOW _COMMENT _IN _PANEL _KEY = 'show-comment-in-panel' ;
const OPENWEATHER _SHOW _COMMENT _IN _FORECAST _KEY = 'show-comment-in-forecast' ;
const OPENWEATHER _REFRESH _INTERVAL _CURRENT = 'refresh-interval-current' ;
const OPENWEATHER _REFRESH _INTERVAL _FORECAST = 'refresh-interval-forecast' ;
const OPENWEATHER _CENTER _FORECAST _KEY = 'center-forecast' ;
const OPENWEATHER _DAYS _FORECAST = 'days-forecast' ;
const OPENWEATHER _DECIMAL _PLACES = 'decimal-places' ;
const OPENWEATHER _USE _DEFAULT _OWM _API _KEY = 'use-default-owm-key' ;
const OPENWEATHER _OWM _API _KEY = 'appid' ;
const OPENWEATHER _OWM _DEFAULT _API _KEY = 'c93b4a667c8c9d1d1eb941621f899bb8' ;
const OPENWEATHER _FC _API _KEY = 'appid-fc' ;
// Keep enums in sync with GSettings schemas
const WeatherProvider = {
DEFAULT : - 1 ,
OPENWEATHERMAP : 0 ,
FORECAST _IO : 1
} ;
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 ,
MMHG : 9
} ;
const WeatherPosition = {
CENTER : 0 ,
RIGHT : 1 ,
LEFT : 2
} ;
const OPENWEATHER _CONV _MPS _IN _MPH = 2.23693629 ;
const OPENWEATHER _CONV _MPS _IN _KPH = 3.6 ;
const OPENWEATHER _CONV _MPS _IN _KNOTS = 1.94384449 ;
const OPENWEATHER _CONV _MPS _IN _FPS = 3.2808399 ;
let _httpSession ;
let _currentWeatherCache , _forecastWeatherCache ;
let _timeCacheCurrentWeather , _timeCacheForecastWeather ;
const OpenweatherMenuButton = new Lang . Class ( {
Name : 'OpenweatherMenuButton' ,
Extends : PanelMenu . Button ,
_init : function ( ) {
this . owmCityId = 0 ;
// Create user-agent string from uuid and (if present) the version
this . user _agent = Me . metadata . uuid ;
if ( Me . metadata . version !== undefined && Me . metadata . version . toString ( ) . trim ( ) !== '' ) {
this . user _agent += '/' ;
this . user _agent += Me . metadata . version . toString ( ) ;
}
// add trailing space, so libsoup adds its own user-agent
this . user _agent += ' ' ;
this . oldProvider = this . _weather _provider ;
this . oldUseDefaultOwmKey = this . _use _default _owm _key ;
this . oldTranslateCondition = this . _translate _condition ;
this . switchProvider ( ) ;
// Load settings
this . loadConfig ( ) ;
// Label
this . _weatherInfo = new St . Label ( {
y _align : Clutter . ActorAlign . CENTER ,
text : _ ( '...' )
} ) ;
this . _weatherIcon = new St . Icon ( {
icon _name : 'view-refresh' + this . getIconType ( ) ,
style _class : 'system-status-icon openweather-icon'
} ) ;
// 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 ) ;
// 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 ( Main . panel . _menus === undefined )
Main . panel . menuManager . addMenu ( this . menu ) ;
else
Main . panel . _menus . addMenu ( this . menu ) ;
this . _session = new GnomeSession . SessionManager ( ) ;
this . _old _position _in _panel = this . _position _in _panel ;
// Current weather
this . _currentWeather = new St . Bin ( ) ;
// Future weather
this . _futureWeather = new St . Bin ( ) ;
// Putting the popup item together
let _itemCurrent = new PopupMenu . PopupBaseMenuItem ( {
reactive : false
} ) ;
let _itemFuture = new PopupMenu . PopupBaseMenuItem ( {
reactive : false
} ) ;
_itemCurrent . actor . add _actor ( this . _currentWeather ) ;
_itemFuture . actor . add _actor ( this . _futureWeather ) ;
this . menu . addMenuItem ( _itemCurrent ) ;
this . _separatorItem = new PopupMenu . PopupSeparatorMenuItem ( ) ;
this . menu . addMenuItem ( this . _separatorItem ) ;
this . menu . addMenuItem ( _itemFuture ) ;
let item = new PopupMenu . PopupSeparatorMenuItem ( ) ;
this . menu . addMenuItem ( item ) ;
this . _selectCity = new PopupMenu . PopupSubMenuMenuItem ( "" ) ;
this . _selectCity . actor . set _height ( 0 ) ;
this . _selectCity . _triangle . set _height ( 0 ) ;
this . _buttonMenu = new PopupMenu . PopupBaseMenuItem ( {
reactive : false ,
style _class : 'openweather-menu-button-container'
} ) ;
this . rebuildButtonMenu ( ) ;
this . menu . addMenuItem ( this . _buttonMenu ) ;
this . menu . addMenuItem ( this . _selectCity ) ;
this . rebuildSelectCityItem ( ) ;
this . _selectCity . menu . connect ( 'open-state-changed' , Lang . bind ( this , function ( ) {
this . _selectCity . actor . remove _style _pseudo _class ( 'open' ) ;
} ) ) ;
this . rebuildCurrentWeatherUi ( ) ;
this . rebuildFutureWeatherUi ( ) ;
this . _idle = false ;
this . _connected = false ;
this . _network _monitor = Gio . network _monitor _get _default ( ) ;
this . _presence = new GnomeSession . Presence ( Lang . bind ( this , function ( proxy , error ) {
this . _onStatusChanged ( proxy . status ) ;
} ) ) ;
this . _presence _connection = this . _presence . connectSignal ( 'StatusChanged' , Lang . bind ( this , function ( proxy , senderName , [ status ] ) {
this . _onStatusChanged ( status ) ;
} ) ) ;
this . currentWeatherCache = _currentWeatherCache ;
this . forecastWeatherCache = _forecastWeatherCache ;
if ( _timeCacheForecastWeather !== undefined ) {
let diff = Math . floor ( new Date ( new Date ( ) - _timeCacheForecastWeather ) . getTime ( ) / 1000 ) ;
if ( diff < this . _refresh _interval _forecast )
this . reloadWeatherForecast ( this . _refresh _interval _forecast - diff ) ;
}
if ( _timeCacheCurrentWeather !== undefined ) {
let diff = Math . floor ( new Date ( new Date ( ) - _timeCacheCurrentWeather ) . getTime ( ) / 1000 ) ;
if ( diff < this . _refresh _interval _current )
this . reloadWeatherCurrent ( this . _refresh _interval _current - diff ) ;
}
this . _network _monitor _connection = this . _network _monitor . connect ( 'network-changed' , Lang . bind ( this , this . _onNetworkStateChanged ) ) ;
this . _checkConnectionState ( ) ;
this . menu . connect ( 'open-state-changed' , Lang . bind ( this , this . recalcLayout ) ) ;
} ,
_onStatusChanged : function ( status ) {
this . _idle = false ;
if ( status == GnomeSession . PresenceStatus . IDLE ) {
this . _idle = true ;
}
} ,
stop : function ( ) {
_forecastWeatherCache = this . forecastWeatherCache ;
_currentWeatherCache = this . currentWeatherCache ;
if ( _httpSession !== undefined )
_httpSession . abort ( ) ;
_httpSession = undefined ;
if ( this . _timeoutCurrent )
Mainloop . source _remove ( this . _timeoutCurrent ) ;
this . _timeoutCurrent = undefined ;
if ( this . _timeoutForecast )
Mainloop . source _remove ( this . _timeoutForecast ) ;
this . _timeoutForecast = undefined ;
if ( this . _presence _connection ) {
this . _presence . disconnect ( this . _presence _connection ) ;
this . _presence _connection = undefined ;
}
if ( this . _network _monitor _connection ) {
this . _network _monitor . disconnect ( this . _network _monitor _connection ) ;
this . _network _monitor _connection = undefined ;
}
if ( this . _settingsC ) {
this . _settings . disconnect ( this . _settingsC ) ;
this . _settingsC = undefined ;
}
if ( this . _settingsInterfaceC ) {
this . _settingsInterface . disconnect ( this . _settingsInterfaceC ) ;
this . _settingsInterfaceC = undefined ;
}
if ( this . _globalThemeChangedId ) {
let context = St . ThemeContext . get _for _stage ( global . stage ) ;
context . disconnect ( this . _globalThemeChangedId ) ;
this . _globalThemeChangedId = undefined ;
}
} ,
switchProvider : function ( ) {
if ( this . _weather _provider == WeatherProvider . FORECAST _IO )
this . useForecastIo ( ) ;
else
this . useOpenweathermapOrg ( ) ;
} ,
useOpenweathermapOrg : function ( ) {
this . parseWeatherForecast = OpenweathermapOrg . parseWeatherForecast ;
this . parseWeatherCurrent = OpenweathermapOrg . parseWeatherCurrent ;
this . getWeatherIcon = OpenweathermapOrg . getWeatherIcon ;
this . refreshWeatherCurrent = OpenweathermapOrg . refreshWeatherCurrent ;
this . refreshWeatherForecast = OpenweathermapOrg . refreshWeatherForecast ;
this . weatherProvider = "https://openweathermap.org/" ;
if ( this . _appid . toString ( ) . trim ( ) === '' )
Main . notify ( "Openweather" , _ ( "Openweathermap.org does not work without an api-key.\nEither set the switch to use the extensions default key in the preferences dialog to on or register at http://openweathermap.org/appid and paste your personal key into the preferences dialog." ) ) ;
} ,
useForecastIo : function ( ) {
this . parseWeatherCurrent = ForecastIo . parseWeatherCurrent ;
this . parseWeatherForecast = ForecastIo . parseWeatherForecast ;
this . getWeatherIcon = ForecastIo . getWeatherIcon ;
this . refreshWeatherCurrent = ForecastIo . refreshWeatherCurrent ;
this . refreshWeatherForecast = function ( ) { } ;
this . weatherProvider = "https://forecast.io/" ;
this . fc _locale = 'en' ;
if ( this . _translate _condition ) {
let fc _locales = [
'ar' ,
'bs' ,
'de' ,
'el' ,
'en' ,
'es' ,
'fr' ,
'hr' ,
'it' ,
'nl' ,
'pl' ,
'pt' ,
'ru' ,
'sk' ,
'sv' ,
'tet' ,
'tr' ,
'uk' ,
'x-pig-latin' ,
'zh' ,
'zh-tw'
] ;
let locale = GLib . get _language _names ( ) [ 0 ] ;
if ( locale . indexOf ( '_' ) != - 1 )
locale = locale . split ( "_" ) [ 0 ] ;
if ( fc _locales . indexOf ( locale ) != - 1 )
this . fc _locale = locale ;
}
if ( this . _appid _fc . toString ( ) . trim ( ) === '' )
Main . notify ( "Openweather" , _ ( "Forecast.io does not work without an api-key.\nPlease register at https://developer.forecast.io/register and paste your personal key into the preferences dialog." ) ) ;
} ,
getWeatherProviderURL : function ( ) {
let url = "" ;
if ( this . _weather _provider == WeatherProvider . FORECAST _IO ) {
url = "https://forecast.io/#/f/" ;
url += this . extractCoord ( this . _city ) ;
} else {
url = "https://openweathermap.org" ;
url += "/city/" + this . owmCityId ;
if ( this . _appid )
url += "?APPID=" + this . _appid ;
}
return url ;
} ,
loadConfig : function ( ) {
this . _settings = Convenience . getSettings ( OPENWEATHER _SETTINGS _SCHEMA ) ;
if ( this . _cities . length === 0 )
this . _cities = "-8.5211767,179.1976747>Vaiaku, Tuvalu>-1" ;
this . _settingsC = this . _settings . connect ( "changed" , Lang . bind ( this , function ( ) {
if ( this . _cities . length === 0 )
this . _cities = "-8.5211767,179.1976747>Vaiaku, Tuvalu>-1" ;
this . rebuildCurrentWeatherUi ( ) ;
this . rebuildFutureWeatherUi ( ) ;
if ( this . providerChanged ( ) ) {
this . switchProvider ( ) ;
this . currentWeatherCache = undefined ;
this . forecastWeatherCache = undefined ;
}
if ( this . locationChanged ( ) ) {
this . currentWeatherCache = undefined ;
this . forecastWeatherCache = undefined ;
}
this . rebuildButtonMenu ( ) ;
this . parseWeatherCurrent ( ) ;
} ) ) ;
} ,
loadConfigInterface : function ( ) {
this . _settingsInterface = Convenience . getSettings ( OPENWEATHER _DESKTOP _INTERFACE ) ;
this . _settingsInterfaceC = this . _settingsInterface . connect ( "changed" , Lang . bind ( this , function ( ) {
this . rebuildCurrentWeatherUi ( ) ;
this . rebuildFutureWeatherUi ( ) ;
if ( this . providerChanged ( ) ) {
this . switchProvider ( ) ;
this . currentWeatherCache = undefined ;
this . forecastWeatherCache = undefined ;
}
if ( this . locationChanged ( ) ) {
this . currentWeatherCache = undefined ;
this . forecastWeatherCache = undefined ;
}
this . parseWeatherCurrent ( ) ;
} ) ) ;
} ,
_onNetworkStateChanged : function ( ) {
this . _checkConnectionState ( ) ;
} ,
_checkConnectionState : function ( ) {
let url = this . getWeatherProviderURL ( ) ;
let address = Gio . NetworkAddress . parse _uri ( url , 80 ) ;
let cancellable = Gio . Cancellable . new ( ) ;
this . _oldConnected = this . _connected ;
this . _connected = false ;
try {
this . _network _monitor . can _reach _async ( address , cancellable , Lang . bind ( this , this . _asyncReadyCallback ) ) ;
} catch ( err ) {
let title = _ ( "Can not connect to %s" ) . format ( url ) ;
log ( title + '\n' + err . message ) ;
}
} ,
_asyncReadyCallback : function ( nm , res ) {
this . _connected = this . _network _monitor . can _reach _finish ( res ) ;
if ( ! this . _oldConnected && this . _connected ) {
let now = new Date ( ) ;
if ( _timeCacheCurrentWeather &&
( Math . floor ( new Date ( now - _timeCacheCurrentWeather ) . getTime ( ) / 1000 ) > this . _refresh _interval _current ) )
this . currentWeatherCache = undefined ;
if ( _timeCacheForecastWeather &&
( Math . floor ( new Date ( now - _timeCacheForecastWeather ) . getTime ( ) / 1000 ) > this . _refresh _interval _forecast ) )
this . forecastWeatherCache = undefined ;
this . parseWeatherCurrent ( ) ;
}
} ,
locationChanged : function ( ) {
let location = this . extractCoord ( this . _city ) ;
if ( this . oldLocation != location ) {
return true ;
}
return false ;
} ,
providerChanged : function ( ) {
let provider = this . _weather _provider ;
if ( this . oldProvider != provider ) {
this . oldProvider = provider ;
return true ;
}
if ( provider == WeatherProvider . OPENWEATHERMAP ) {
let useDefaultOwmKey = this . _use _default _owm _key ;
if ( this . oldUseDefaultOwmKey != useDefaultOwmKey ) {
this . oldUseDefaultOwmKey = useDefaultOwmKey ;
return true ;
}
}
if ( provider == WeatherProvider . FORECAST _IO ) {
let translateCondition = this . _translate _condition ;
if ( this . oldTranslateCondition != translateCondition ) {
this . oldTranslateCondition = translateCondition ;
return true ;
}
}
return false ;
} ,
get _clockFormat ( ) {
if ( ! this . _settingsInterface )
this . loadConfigInterface ( ) ;
return this . _settingsInterface . get _string ( "clock-format" ) ;
} ,
get _weather _provider ( ) {
if ( ! this . _settings )
this . loadConfig ( ) ;
let provider = this . extractProvider ( this . _city ) ;
if ( provider == WeatherProvider . DEFAULT )
provider = this . _settings . get _enum ( OPENWEATHER _PROVIDER _KEY ) ;
return provider ;
} ,
get _units ( ) {
if ( ! this . _settings )
this . loadConfig ( ) ;
return this . _settings . get _enum ( OPENWEATHER _UNIT _KEY ) ;
} ,
get _wind _speed _units ( ) {
if ( ! this . _settings )
this . loadConfig ( ) ;
return this . _settings . get _enum ( OPENWEATHER _WIND _SPEED _UNIT _KEY ) ;
} ,
get _wind _direction ( ) {
if ( ! this . _settings )
this . loadConfig ( ) ;
return this . _settings . get _boolean ( OPENWEATHER _WIND _DIRECTION _KEY ) ;
} ,
get _pressure _units ( ) {
if ( ! this . _settings )
this . loadConfig ( ) ;
return this . _settings . get _enum ( OPENWEATHER _PRESSURE _UNIT _KEY ) ;
} ,
get _cities ( ) {
if ( ! this . _settings )
this . loadConfig ( ) ;
return this . _settings . get _string ( OPENWEATHER _CITY _KEY ) ;
} ,
set _cities ( v ) {
if ( ! this . _settings )
this . loadConfig ( ) ;
return this . _settings . set _string ( OPENWEATHER _CITY _KEY , v ) ;
} ,
get _actual _city ( ) {
if ( ! this . _settings )
this . loadConfig ( ) ;
var a = this . _settings . get _int ( OPENWEATHER _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 ( OPENWEATHER _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 ;
} ,
get _translate _condition ( ) {
if ( ! this . _settings )
this . loadConfig ( ) ;
return this . _settings . get _boolean ( OPENWEATHER _TRANSLATE _CONDITION _KEY ) ;
} ,
get _getIconType ( ) {
if ( ! this . _settings )
this . loadConfig ( ) ;
return this . _settings . get _boolean ( OPENWEATHER _USE _SYMBOLIC _ICONS _KEY ) ? 1 : 0 ;
} ,
get _use _text _on _buttons ( ) {
if ( ! this . _settings )
this . loadConfig ( ) ;
return this . _settings . get _boolean ( OPENWEATHER _USE _TEXT _ON _BUTTONS _KEY ) ? 1 : 0 ;
} ,
get _text _in _panel ( ) {
if ( ! this . _settings )
this . loadConfig ( ) ;
return this . _settings . get _boolean ( OPENWEATHER _SHOW _TEXT _IN _PANEL _KEY ) ;
} ,
get _position _in _panel ( ) {
if ( ! this . _settings )
this . loadConfig ( ) ;
return this . _settings . get _enum ( OPENWEATHER _POSITION _IN _PANEL _KEY ) ;
} ,
get _comment _in _panel ( ) {
if ( ! this . _settings )
this . loadConfig ( ) ;
return this . _settings . get _boolean ( OPENWEATHER _SHOW _COMMENT _IN _PANEL _KEY ) ;
} ,
get _comment _in _forecast ( ) {
if ( ! this . _settings )
this . loadConfig ( ) ;
return this . _settings . get _boolean ( OPENWEATHER _SHOW _COMMENT _IN _FORECAST _KEY ) ;
} ,
get _refresh _interval _current ( ) {
if ( ! this . _settings )
this . loadConfig ( ) ;
let v = this . _settings . get _int ( OPENWEATHER _REFRESH _INTERVAL _CURRENT ) ;
return ( ( v >= 600 ) ? v : 600 ) ;
} ,
get _refresh _interval _forecast ( ) {
if ( ! this . _settings )
this . loadConfig ( ) ;
let v = this . _settings . get _int ( OPENWEATHER _REFRESH _INTERVAL _FORECAST ) ;
return ( ( v >= 600 ) ? v : 600 ) ;
} ,
get _center _forecast ( ) {
if ( ! this . _settings )
this . loadConfig ( ) ;
return this . _settings . get _boolean ( OPENWEATHER _CENTER _FORECAST _KEY ) ;
} ,
get _days _forecast ( ) {
if ( ! this . _settings )
this . loadConfig ( ) ;
return this . _settings . get _int ( OPENWEATHER _DAYS _FORECAST ) ;
} ,
get _decimal _places ( ) {
if ( ! this . _settings )
this . loadConfig ( ) ;
return this . _settings . get _int ( OPENWEATHER _DECIMAL _PLACES ) ;
} ,
get _appid ( ) {
if ( ! this . _settings )
this . loadConfig ( ) ;
let key = '' ;
if ( this . _use _default _owm _key )
key = OPENWEATHER _OWM _DEFAULT _API _KEY ;
else
key = this . _settings . get _string ( OPENWEATHER _OWM _API _KEY ) ;
return ( key . length == 32 ) ? key : '' ;
} ,
get _use _default _owm _key ( ) {
if ( ! this . _settings )
this . loadConfig ( ) ;
return this . _settings . get _boolean ( OPENWEATHER _USE _DEFAULT _OWM _API _KEY ) ;
} ,
get _appid _fc ( ) {
if ( ! this . _settings )
this . loadConfig ( ) ;
let key = this . _settings . get _string ( OPENWEATHER _FC _API _KEY ) ;
return ( key . length == 32 ) ? key : '' ;
} ,
rebuildButtonMenu : function ( ) {
if ( this . _buttonBox ) {
if ( this . _buttonBox1 ) {
this . _buttonBox1 . destroy ( ) ;
this . _buttonBox1 = undefined ;
}
if ( this . _buttonBox2 ) {
this . _buttonBox2 . destroy ( ) ;
this . _buttonBox2 = undefined ;
}
this . _buttonMenu . removeActor ( this . _buttonBox ) ;
this . _buttonBox . destroy ( ) ;
this . _buttonBox = undefined ;
}
if ( this . _buttonBox1 ) {
this . _buttonBox1 . destroy ( ) ;
this . _buttonBox1 = undefined ;
}
if ( this . _buttonBox2 ) {
this . _buttonBox2 . destroy ( ) ;
this . _buttonBox2 = undefined ;
}
this . _locationButton = Main . panel . statusArea . aggregateMenu . _system . _createActionButton ( 'find-location-symbolic' , _ ( "Locations" ) ) ;
if ( this . _use _text _on _buttons )
this . _locationButton . set _label ( this . _locationButton . get _accessible _name ( ) ) ;
this . _locationButton . connect ( 'clicked' , Lang . bind ( this , function ( ) {
this . _selectCity . _setOpenState ( ! this . _selectCity . _getOpenState ( ) ) ;
} ) ) ;
this . _buttonBox1 = new St . BoxLayout ( {
style _class : 'openweather-button-box'
} ) ;
this . _buttonBox1 . add _actor ( this . _locationButton ) ;
this . _reloadButton = Main . panel . statusArea . aggregateMenu . _system . _createActionButton ( 'view-refresh-symbolic' , _ ( "Reload Weather Information" ) ) ;
if ( this . _use _text _on _buttons )
this . _reloadButton . set _label ( this . _reloadButton . get _accessible _name ( ) ) ;
this . _reloadButton . connect ( 'clicked' , Lang . bind ( this , function ( ) {
this . currentWeatherCache = undefined ;
this . forecastWeatherCache = undefined ;
this . parseWeatherCurrent ( ) ;
this . recalcLayout ( ) ;
} ) ) ;
this . _buttonBox1 . add _actor ( this . _reloadButton ) ;
this . _buttonBox2 = new St . BoxLayout ( {
style _class : 'openweather-button-box'
} ) ;
this . _urlButton = Main . panel . statusArea . aggregateMenu . _system . _createActionButton ( '' , _ ( "Weather data provided by:" ) + ( this . _use _text _on _buttons ? "\n" : " " ) + this . weatherProvider ) ;
this . _urlButton . set _label ( this . _urlButton . get _accessible _name ( ) ) ;
this . _urlButton . style _class += ' openweather-provider' ;
this . _urlButton . connect ( 'clicked' , Lang . bind ( this , function ( ) {
this . menu . actor . hide ( ) ;
let url = this . getWeatherProviderURL ( ) ;
try {
Gtk . show _uri ( null , url , global . get _current _time ( ) ) ;
} catch ( err ) {
let title = _ ( "Can not open %s" ) . format ( url ) ;
Main . notifyError ( title , err . message ) ;
}
} ) ) ;
this . _buttonBox2 . add _actor ( this . _urlButton ) ;
this . _prefsButton = Main . panel . statusArea . aggregateMenu . _system . _createActionButton ( 'preferences-system-symbolic' , _ ( "Weather Settings" ) ) ;
if ( this . _use _text _on _buttons )
this . _prefsButton . set _label ( this . _prefsButton . get _accessible _name ( ) ) ;
this . _prefsButton . connect ( 'clicked' , Lang . bind ( this , this . _onPreferencesActivate ) ) ;
this . _buttonBox2 . add _actor ( this . _prefsButton ) ;
this . _buttonMenu . actor . add _actor ( this . _buttonBox1 ) ;
this . _buttonMenu . actor . add _actor ( this . _buttonBox2 ) ;
this . _buttonBox1MinWidth = undefined ;
} ,
rebuildSelectCityItem : function ( ) {
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 ;
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 . setOrnament ( PopupMenu . Ornament . DOT ) ;
}
this . _selectCity . menu . addMenuItem ( item ) ;
// override the items default onActivate-handler, to keep the ui open while chosing the location
item . activate = this . _onActivate ;
}
if ( cities . length == 1 )
this . _selectCity . actor . hide ( ) ;
else
this . _selectCity . actor . show ( ) ;
} ,
_onActivate : function ( ) {
openweatherMenu . _actual _city = this . location ;
} ,
extractLocation : function ( ) {
if ( ! arguments [ 0 ] )
return "" ;
if ( arguments [ 0 ] . search ( ">" ) == - 1 )
return _ ( "Invalid city" ) ;
return arguments [ 0 ] . split ( ">" ) [ 1 ] ;
} ,
extractCoord : function ( ) {
let coords = 0 ;
if ( arguments [ 0 ] && ( arguments [ 0 ] . search ( ">" ) != - 1 ) )
coords = arguments [ 0 ] . split ( ">" ) [ 0 ] ;
if ( ( coords . search ( "," ) == - 1 ) || isNaN ( coords . split ( "," ) [ 0 ] ) || isNaN ( coords . split ( "," ) [ 1 ] ) ) {
Main . notify ( "Openweather" , _ ( "Invalid location! Please try to recreate it." ) ) ;
return 0 ;
}
return coords ;
} ,
extractProvider : function ( ) {
if ( ! arguments [ 0 ] )
return - 1 ;
if ( arguments [ 0 ] . split ( ">" ) [ 2 ] === undefined )
return - 1 ;
if ( isNaN ( parseInt ( arguments [ 0 ] . split ( ">" ) [ 2 ] ) ) )
return - 1 ;
return parseInt ( arguments [ 0 ] . split ( ">" ) [ 2 ] ) ;
} ,
_onPreferencesActivate : function ( ) {
this . menu . actor . hide ( ) ;
Util . spawn ( [ "gnome-shell-extension-prefs" , "openweather-extension@jenslody.de" ] ) ;
return 0 ;
} ,
recalcLayout : function ( ) {
if ( ! this . menu . isOpen )
return ;
if ( this . _buttonBox1MinWidth === undefined )
this . _buttonBox1MinWidth = this . _buttonBox1 . get _width ( ) ;
this . _buttonBox1 . set _width ( Math . max ( this . _buttonBox1MinWidth , this . _currentWeather . get _width ( ) - this . _buttonBox2 . get _width ( ) ) ) ;
if ( this . _forecastScrollBox !== undefined && this . _forecastBox !== undefined && this . _currentWeather !== undefined ) {
this . _forecastScrollBox . set _width ( Math . max ( this . _currentWeather . get _width ( ) , ( this . _buttonBox1 . get _width ( ) + this . _buttonBox2 . get _width ( ) ) ) ) ;
this . _forecastScrollBox . show ( ) ;
if ( this . _forecastBox . get _preferred _width ( this . _forecastBox . get _height ( ) ) [ 0 ] > this . _currentWeather . get _width ( ) ) {
this . _forecastScrollBox . hscroll . margin _top = 10 ;
this . _forecastScrollBox . hscroll . show ( ) ;
} else {
this . _forecastScrollBox . hscroll . margin _top = 0 ;
this . _forecastScrollBox . hscroll . hide ( ) ;
}
}
} ,
unit _to _unicode : function ( ) {
if ( this . _units == WeatherUnits . FAHRENHEIT )
return '\u00B0F' ;
else if ( this . _units == WeatherUnits . KELVIN )
return 'K' ;
else if ( this . _units == WeatherUnits . RANKINE )
return '\u00B0Ra' ;
else if ( this . _units == WeatherUnits . REAUMUR )
return '\u00B0R\u00E9' ;
else if ( this . _units == WeatherUnits . ROEMER )
return '\u00B0R\u00F8' ;
else if ( this . _units == WeatherUnits . DELISLE )
return '\u00B0De' ;
else if ( this . _units == WeatherUnits . NEWTON )
return '\u00B0N' ;
else
return '\u00B0C' ;
} ,
hasIcon : function ( icon ) {
return Gtk . IconTheme . get _default ( ) . has _icon ( icon + this . getIconType ( ) ) ;
} ,
toFahrenheit : function ( t ) {
return ( ( Number ( t ) * 1.8 ) + 32 ) . toFixed ( this . _decimal _places ) ;
} ,
toKelvin : function ( t ) {
return ( Number ( t ) + 273.15 ) . toFixed ( this . _decimal _places ) ;
} ,
toRankine : function ( t ) {
return ( ( Number ( t ) * 1.8 ) + 491.67 ) . toFixed ( this . _decimal _places ) ;
} ,
toReaumur : function ( t ) {
return ( Number ( t ) * 0.8 ) . toFixed ( this . _decimal _places ) ;
} ,
toRoemer : function ( t ) {
return ( ( Number ( t ) * 21 / 40 ) + 7.5 ) . toFixed ( this . _decimal _places ) ;
} ,
toDelisle : function ( t ) {
return ( ( 100 - Number ( t ) ) * 1.5 ) . toFixed ( this . _decimal _places ) ;
} ,
toNewton : function ( t ) {
return ( Number ( t ) - 0.33 ) . toFixed ( this . _decimal _places ) ;
} ,
toInHg : function ( p /*, t*/ ) {
return ( p / 33.86530749 ) . toFixed ( this . _decimal _places ) ;
} ,
toBeaufort : function ( w , t ) {
if ( w < 0.3 )
return ( ! t ) ? "0" : "(" + _ ( "Calm" ) + ")" ;
else if ( w >= 0.3 && w <= 1.5 )
return ( ! t ) ? "1" : "(" + _ ( "Light air" ) + ")" ;
else if ( w > 1.5 && w <= 3.4 )
return ( ! t ) ? "2" : "(" + _ ( "Light breeze" ) + ")" ;
else if ( w > 3.4 && w <= 5.4 )
return ( ! t ) ? "3" : "(" + _ ( "Gentle breeze" ) + ")" ;
else if ( w > 5 , 4 && w <= 7.9 )
return ( ! t ) ? "4" : "(" + _ ( "Moderate breeze" ) + ")" ;
else if ( w > 7.9 && w <= 10.7 )
return ( ! t ) ? "5" : "(" + _ ( "Fresh breeze" ) + ")" ;
else if ( w > 10.7 && w <= 13.8 )
return ( ! t ) ? "6" : "(" + _ ( "Strong breeze" ) + ")" ;
else if ( w > 13.8 && w <= 17.1 )
return ( ! t ) ? "7" : "(" + _ ( "Moderate gale" ) + ")" ;
else if ( w > 17.1 && w <= 20.7 )
return ( ! t ) ? "8" : "(" + _ ( "Fresh gale" ) + ")" ;
else if ( w > 20.7 && w <= 24.4 )
return ( ! t ) ? "9" : "(" + _ ( "Strong gale" ) + ")" ;
else if ( w > 24.4 && w <= 28.4 )
return ( ! t ) ? "10" : "(" + _ ( "Storm" ) + ")" ;
else if ( w > 28.4 && w <= 32.6 )
return ( ! t ) ? "11" : "(" + _ ( "Violent storm" ) + ")" ;
else
return ( ! t ) ? "12" : "(" + _ ( "Hurricane" ) + ")" ;
} ,
getLocaleDay : function ( abr ) {
let days = [ _ ( 'Sunday' ) , _ ( 'Monday' ) , _ ( 'Tuesday' ) , _ ( 'Wednesday' ) , _ ( 'Thursday' ) , _ ( 'Friday' ) , _ ( 'Saturday' ) ] ;
return days [ abr ] ;
} ,
getWindDirection : 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 ] ;
} ,
getIconType : function ( icon _name ) {
if ( ! icon _name )
if ( this . _getIconType )
return "-symbolic" ;
else
return "" ;
if ( this . _getIconType )
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 , params , fun ) {
if ( _httpSession === undefined ) {
_httpSession = new Soup . Session ( ) ;
_httpSession . user _agent = this . user _agent ;
} else {
// abort previous requests.
_httpSession . abort ( ) ;
}
let message = Soup . form _request _new _from _hash ( 'GET' , url , params ) ;
_httpSession . queue _message ( message , Lang . bind ( this , function ( _httpSession , message ) {
try {
if ( ! message . response _body . data ) {
fun . call ( this , 0 ) ;
return ;
}
let jp = JSON . parse ( message . response _body . data ) ;
fun . call ( this , jp ) ;
} catch ( e ) {
fun . call ( this , 0 ) ;
return ;
}
} ) ) ;
return ;
} ,
checkPositionInPanel : function ( ) {
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 ;
}
} ,
formatPressure : function ( pressure ) {
let pressure _unit = 'hPa' ;
switch ( this . _pressure _units ) {
case WeatherPressureUnits . INHG :
pressure = this . toInHg ( pressure ) ;
pressure _unit = "inHg" ;
break ;
case WeatherPressureUnits . HPA :
pressure = pressure . toFixed ( this . _decimal _places ) ;
pressure _unit = "hPa" ;
break ;
case WeatherPressureUnits . BAR :
pressure = ( pressure / 1000 ) . toFixed ( this . _decimal _places ) ;
pressure _unit = "bar" ;
break ;
case WeatherPressureUnits . PA :
pressure = ( pressure * 100 ) . toFixed ( this . _decimal _places ) ;
pressure _unit = "Pa" ;
break ;
case WeatherPressureUnits . KPA :
pressure = ( pressure / 10 ) . toFixed ( this . _decimal _places ) ;
pressure _unit = "kPa" ;
break ;
case WeatherPressureUnits . ATM :
pressure = ( pressure * 0.000986923267 ) . toFixed ( this . _decimal _places ) ;
pressure _unit = "atm" ;
break ;
case WeatherPressureUnits . AT :
pressure = ( pressure * 0.00101971621298 ) . toFixed ( this . _decimal _places ) ;
pressure _unit = "at" ;
break ;
case WeatherPressureUnits . TORR :
pressure = ( pressure * 0.750061683 ) . toFixed ( this . _decimal _places ) ;
pressure _unit = "Torr" ;
break ;
case WeatherPressureUnits . PSI :
pressure = ( pressure * 0.0145037738 ) . toFixed ( this . _decimal _places ) ;
pressure _unit = "psi" ;
break ;
case WeatherPressureUnits . MMHG :
pressure = ( pressure * 0.750061683 ) . toFixed ( this . _decimal _places ) ;
pressure _unit = "mmHg" ;
break ;
}
return parseFloat ( pressure ) . toLocaleString ( ) + ' ' + pressure _unit ;
} ,
formatTemperature : function ( temperature ) {
switch ( this . _units ) {
case WeatherUnits . FAHRENHEIT :
temperature = this . toFahrenheit ( temperature ) ;
break ;
case WeatherUnits . CELSIUS :
temperature = temperature . toFixed ( this . _decimal _places ) ;
break ;
case WeatherUnits . KELVIN :
temperature = this . toKelvin ( temperature ) ;
break ;
case WeatherUnits . RANKINE :
temperature = this . toRankine ( temperature ) ;
break ;
case WeatherUnits . REAUMUR :
temperature = this . toReaumur ( temperature ) ;
break ;
case WeatherUnits . ROEMER :
temperature = this . toRoemer ( temperature ) ;
break ;
case WeatherUnits . DELISLE :
temperature = this . toDelisle ( temperature ) ;
break ;
case WeatherUnits . NEWTON :
temperature = this . toNewton ( temperature ) ;
break ;
}
return parseFloat ( temperature ) . toLocaleString ( ) + ' ' + this . unit _to _unicode ( ) ;
} ,
formatWind : function ( speed , direction ) {
let unit = 'm/s' ;
switch ( this . _wind _speed _units ) {
case WeatherWindSpeedUnits . MPH :
speed = ( speed * OPENWEATHER _CONV _MPS _IN _MPH ) . toFixed ( this . _decimal _places ) ;
unit = 'mph' ;
break ;
case WeatherWindSpeedUnits . KPH :
speed = ( speed * OPENWEATHER _CONV _MPS _IN _KPH ) . toFixed ( this . _decimal _places ) ;
unit = 'km/h' ;
break ;
case WeatherWindSpeedUnits . MPS :
speed = speed . toFixed ( this . _decimal _places ) ;
break ;
case WeatherWindSpeedUnits . KNOTS :
speed = ( speed * OPENWEATHER _CONV _MPS _IN _KNOTS ) . toFixed ( this . _decimal _places ) ;
unit = 'kn' ;
break ;
case WeatherWindSpeedUnits . FPS :
speed = ( speed * OPENWEATHER _CONV _MPS _IN _FPS ) . toFixed ( this . _decimal _places ) ;
unit = 'ft/s' ;
break ;
case WeatherWindSpeedUnits . BEAUFORT :
speed = this . toBeaufort ( speed ) ;
unit = this . toBeaufort ( speed , true ) ;
break ;
}
if ( ! speed )
return '\u2013' ;
else if ( speed === 0 || ! direction )
return parseFloat ( speed ) . toLocaleString ( ) + ' ' + unit ;
else // i.e. speed > 0 && direction
return direction + ' ' + parseFloat ( speed ) . toLocaleString ( ) + ' ' + unit ;
} ,
reloadWeatherCurrent : function ( interval ) {
if ( this . _timeoutCurrent ) {
Mainloop . source _remove ( this . _timeoutCurrent ) ;
this . _timeoutCurrent = undefined ;
}
_timeCacheCurrentWeather = new Date ( ) ;
this . _timeoutCurrent = Mainloop . timeout _add _seconds ( interval , Lang . bind ( this , function ( ) {
// only invalidate cached data, if we can connect the weather-providers server
if ( this . _connected && ! this . _idle )
this . currentWeatherCache = undefined ;
this . parseWeatherCurrent ( ) ;
return true ;
} ) ) ;
} ,
reloadWeatherForecast : function ( interval ) {
if ( this . _timeoutForecast ) {
Mainloop . source _remove ( this . _timeoutForecast ) ;
this . _timeoutForecast = undefined ;
}
_timeCacheForecastWeather = new Date ( ) ;
this . _timeoutForecast = Mainloop . timeout _add _seconds ( interval , Lang . bind ( this , function ( ) {
// only invalidate cached data, if we can connect the weather-providers server
if ( this . _connected && ! this . _idle )
this . forecastWeatherCache = undefined ;
this . parseWeatherForecast ( ) ;
return true ;
} ) ) ;
} ,
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 ( ) ;
} ,
rebuildCurrentWeatherUi : function ( ) {
this . _weatherInfo . text = ( ' ' ) ;
this . _weatherIcon . icon _name = 'view-refresh' + this . getIconType ( ) ;
this . destroyCurrentWeather ( ) ;
// This will hold the icon for the current weather
this . _currentWeatherIcon = new St . Icon ( {
icon _size : 72 ,
icon _name : 'view-refresh' + this . getIconType ( ) ,
style _class : 'system-menu-action openweather-current-icon'
} ) ;
this . _sunriseIcon = new St . Icon ( {
icon _size : 15 ,
icon _name : 'weather-clear' + this . getIconType ( ) ,
style _class : 'openweather-sunrise-icon'
} ) ;
this . _sunsetIcon = new St . Icon ( {
icon _size : 15 ,
icon _name : 'weather-clear-night' + this . getIconType ( ) ,
style _class : 'openweather-sunset-icon'
} ) ;
this . _buildIcon = new St . Icon ( {
icon _size : 15 ,
icon _name : 'view-refresh' + this . getIconType ( ) ,
style _class : 'openweather-build-icon'
} ) ;
// The summary of the current weather
this . _currentWeatherSummary = new St . Label ( {
text : _ ( 'Loading ...' ) ,
style _class : 'openweather-current-summary'
} ) ;
this . _currentWeatherLocation = new St . Label ( {
text : _ ( 'Please wait' )
} ) ;
let bb = new St . BoxLayout ( {
vertical : true ,
style _class : 'system-menu-action openweather-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 : 'openweather-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 . _currentWeatherCloudiness = 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 : 'openweather-current-databox'
} ) ;
let rb _captions = new St . BoxLayout ( {
vertical : true ,
style _class : 'popup-menu-item popup-status-menu-item openweather-current-databox-captions'
} ) ;
let rb _values = new St . BoxLayout ( {
vertical : true ,
style _class : 'system-menu-action openweather-current-databox-values'
} ) ;
rb . add _actor ( rb _captions ) ;
rb . add _actor ( rb _values ) ;
rb _captions . add _actor ( new St . Label ( {
text : _ ( 'Cloudiness:' )
} ) ) ;
rb _values . add _actor ( this . _currentWeatherCloudiness ) ;
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 : 'openweather-current-iconbox'
} ) ;
box . add _actor ( this . _currentWeatherIcon ) ;
box . add _actor ( xb ) ;
this . _currentWeather . set _child ( box ) ;
} ,
scrollForecastBy : function ( delta ) {
if ( this . _forecastScrollBox === undefined )
return ;
this . _forecastScrollBox . hscroll . adjustment . value += delta ;
} ,
rebuildFutureWeatherUi : function ( cnt ) {
this . destroyFutureWeather ( ) ;
this . _forecast = [ ] ;
this . _forecastBox = new St . BoxLayout ( {
x _align : this . _center _forecast ? St . Align . END : St . Align . START ,
style _class : 'openweather-forecast-box'
} ) ;
this . _forecastScrollBox = new St . ScrollView ( {
style _class : 'openweather-forecasts'
} ) ;
let pan = new Clutter . PanAction ( {
interpolate : true
} ) ;
pan . connect ( 'pan' , Lang . bind ( this , function ( action ) {
let [ dist , dx , dy ] = action . get _motion _delta ( 0 ) ;
this . scrollForecastBy ( - 1 * ( dx / this . _forecastScrollBox . width ) * this . _forecastScrollBox . hscroll . adjustment . page _size ) ;
return false ;
} ) ) ;
this . _forecastScrollBox . add _action ( pan ) ;
this . _forecastScrollBox . connect ( 'scroll-event' , Lang . bind ( this , this . _onScroll ) ) ;
this . _forecastScrollBox . hscroll . connect ( 'scroll-event' , Lang . bind ( this , this . _onScroll ) ) ;
this . _forecastScrollBox . hscroll . margin _right = 25 ;
this . _forecastScrollBox . hscroll . margin _left = 25 ;
this . _forecastScrollBox . hscroll . hide ( ) ;
this . _forecastScrollBox . vscrollbar _policy = Gtk . PolicyType . NEVER ;
this . _forecastScrollBox . hscrollbar _policy = Gtk . PolicyType . AUTOMATIC ;
this . _forecastScrollBox . enable _mouse _scrolling = true ;
this . _forecastScrollBox . hide ( ) ;
this . _futureWeather . set _child ( this . _forecastScrollBox ) ;
if ( cnt === undefined )
cnt = this . _days _forecast ;
for ( let i = 0 ; i < cnt ; i ++ ) {
let forecastWeather = { } ;
forecastWeather . Icon = new St . Icon ( {
icon _size : 48 ,
icon _name : 'view-refresh' + this . getIconType ( ) ,
style _class : 'system-menu-action openweather-forecast-icon'
} ) ;
forecastWeather . Day = new St . Label ( {
style _class : 'popup-menu-item popup-status-menu-item openweather-forecast-day'
} ) ;
forecastWeather . Summary = new St . Label ( {
style _class : 'system-menu-action openweather-forecast-summary'
} ) ;
forecastWeather . Summary . clutter _text . line _wrap = true ;
forecastWeather . Temperature = new St . Label ( {
style _class : 'system-menu-action openweather-forecast-temperature'
} ) ;
let by = new St . BoxLayout ( {
vertical : true ,
style _class : 'openweather-forecast-databox'
} ) ;
by . add _actor ( forecastWeather . Day ) ;
if ( this . _comment _in _forecast )
by . add _actor ( forecastWeather . Summary ) ;
by . add _actor ( forecastWeather . Temperature ) ;
let bb = new St . BoxLayout ( {
style _class : 'openweather-forecast-iconbox'
} ) ;
bb . add _actor ( forecastWeather . Icon ) ;
bb . add _actor ( by ) ;
this . _forecast [ i ] = forecastWeather ;
this . _forecastBox . add _actor ( bb ) ;
}
this . _forecastScrollBox . add _actor ( this . _forecastBox ) ;
} ,
_onScroll : function ( actor , event ) {
let dx = 0 ;
let dy = 0 ;
switch ( event . get _scroll _direction ( ) ) {
case Clutter . ScrollDirection . UP :
dy = - 1 ;
break ;
case Clutter . ScrollDirection . DOWN :
dy = 1 ;
break ;
// horizontal scrolling will be handled by the control itself
default :
return true ;
}
this . scrollForecastBy ( dy * this . _forecastScrollBox . hscroll . adjustment . stepIncrement ) ;
return false ;
}
} ) ;
let openweatherMenu ;
function init ( ) {
Convenience . initTranslations ( 'gnome-shell-extension-openweather' ) ;
}
function enable ( ) {
openweatherMenu = new OpenweatherMenuButton ( ) ;
Main . panel . addToStatusArea ( 'openweatherMenu' , openweatherMenu ) ;
}
function disable ( ) {
openweatherMenu . stop ( ) ;
openweatherMenu . destroy ( ) ;
}