#! /usr/bin/env seed
/ *
*
* Weather Settings for GNOME Shell Extension Weather
*
* Copyright ( C ) 2012
* Christian METZLER < neroth @ xeked . 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 Gtk = imports . gi . Gtk ;
const GObject = imports . gi . GObject ;
const GtkBuilder = imports . gtkbuilder ;
const Gio = imports . gi . Gio ;
const Gettext = imports . gettext ;
const _ = Gettext . gettext ;
const Soup = imports . gi . Soup ;
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 _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' ;
// 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 ( ) ) ;
var WeatherSetting = function ( )
{
Gettext . textdomain ( "gnome-shell-extension-weather" ) ;
Gtk . init ( Seed . argv ) ;
this . initWindow ( ) ;
this . refreshUI ( ) ;
this . showWindow ( ) ;
Gtk . main ( ) ;
} ;
WeatherSetting . prototype =
{
addCity : function ( )
{
var that = this ;
var textDialog = _ ( "Name of the city" ) ;
var dialog = new Gtk . Dialog ( { title : "" } ) ;
var entry = new Gtk . Entry ( ) ;
var completion = new Gtk . EntryCompletion ( ) ;
entry . set _completion ( completion ) ;
var completionModel = new Gtk . ListStore . c _new ( 1 , [ GObject . TYPE _STRING ] ) ;
completion . set _model ( completionModel ) ;
completion . set _text _column ( 0 ) ;
completion . set _match _func ( function ( completion , key , iter )
{
if ( iter )
if ( completionModel . get _value ( iter , 0 ) . value . get _string ( ) )
return true ;
return false ;
} ) ;
entry . margin _top = 12 ;
entry . margin _bottom = 12 ;
var label = new Gtk . Label ( { label : textDialog } ) ;
dialog . set _border _width ( 12 ) ;
dialog . set _modal ( 1 ) ;
dialog . set _resizable ( 0 ) ;
dialog . set _transient _for ( this . Window . get _object ( "main-window" ) ) ;
dialog . add _button ( Gtk . STOCK _CANCEL , 0 ) ;
var d = dialog . add _button ( Gtk . STOCK _OK , 1 ) ;
d . set _can _default ( true ) ;
d . sensitive = 0 ;
dialog . set _default ( d ) ;
entry . activates _default = true ;
var testLocation = function ( location )
{
that . loadJsonAsync ( encodeURI ( 'http://query.yahooapis.com/v1/public/yql?format=json&q=select woeid from geo.places where text = "' + location + '" limit 1' ) , function ( )
{
d . sensitive = 0 ;
var city = arguments [ 0 ] . query ;
if ( Number ( city . count ) == 0 )
return 0 ;
d . sensitive = 1 ;
} ) ;
} ;
entry . signal . changed . connect ( function ( )
{
var location = entry . get _text ( ) ;
testLocation ( location ) ;
that . loadJsonAsync ( encodeURI ( 'http://query.yahooapis.com/v1/public/yql?q=select woeid,name,admin1,country from geo.places where text = "*' + location + '*" or text = "' + location + '" limit 10&format=json' ) , function ( )
{
if ( ! arguments [ 0 ] )
return 0 ;
var city = arguments [ 0 ] . query ;
var n = Number ( city . count ) ;
if ( n > 0 )
city = city . results . place ;
else
return 0 ;
var iter = that . iter ;
completionModel . clear ( ) ;
if ( n > 1 )
{
for ( var i in city )
{
if ( typeof m == "undefined" )
var m = { } ;
var current = completionModel . append ( iter ) . iter ;
var cityText = city [ i ] . name ;
if ( city [ i ] . admin1 )
cityText += ", " + city [ i ] . admin1 . content ;
if ( city [ i ] . country )
cityText += ", " + city [ i ] . country . code ;
if ( m [ cityText ] )
continue ;
else
m [ cityText ] = 1 ;
completionModel . set _value ( current , 0 , cityText ) ;
completion . complete ( ) ;
}
}
else
{
var current = completionModel . append ( iter ) . iter ;
var cityText = city . name ;
if ( city . admin1 )
cityText += ", " + city . admin1 . content ;
if ( city . country )
cityText += ", " + city . country . code ;
completionModel . set _value ( current , 0 , cityText ) ;
completion . complete ( ) ;
}
testLocation ( location ) ;
} ) ;
return 0 ;
} ) ;
var dialog _area = dialog . get _content _area ( ) ;
dialog _area . pack _start ( label ) ;
dialog _area . pack _start ( entry ) ;
dialog . signal . response . connect ( function ( w , response _id ) {
if ( response _id )
{
that . loadJsonAsync ( encodeURI ( 'http://query.yahooapis.com/v1/public/yql?format=json&q=select woeid,name,admin1,country from geo.places where text = "' + entry . get _text ( ) + '" limit 1' ) , function ( )
{
var city = arguments [ 0 ] . query ;
if ( Number ( city . count ) > 0 )
city = city . results . place ;
else
return 0 ;
var cityText = city . name ;
if ( city . admin1 )
cityText += ", " + city . admin1 . content ;
if ( city . country )
cityText += ", " + city . country . code ;
if ( that . city )
that . city = that . city + " && " + city . woeid + ">" + cityText ;
else
that . city = city . woeid + ">" + cityText ;
} ) ;
}
dialog . hide ( ) ;
} ) ;
dialog . show _all ( ) ;
} ,
removeCity : function ( )
{
var that = this ;
var city = this . city . split ( " && " ) ;
if ( ! city . length )
return 0 ;
var ac = this . actual _city ;
var textDialog = _ ( "Remove %s ?" ) . replace ( "%s" , this . extractLocation ( city [ ac ] ) ) ;
var dialog = new Gtk . Dialog ( { title : "" } ) ;
var label = new Gtk . Label ( { label : textDialog } ) ;
label . margin _bottom = 12 ;
dialog . set _border _width ( 12 ) ;
dialog . set _modal ( 1 ) ;
dialog . set _resizable ( 0 ) ;
dialog . set _transient _for ( this . Window . get _object ( "main-window" ) ) ;
dialog . add _button ( Gtk . STOCK _NO , 0 ) ;
var d = dialog . add _button ( Gtk . STOCK _YES , 1 ) ;
d . set _can _default ( true ) ;
dialog . set _default ( d ) ;
var dialog _area = dialog . get _content _area ( ) ;
dialog _area . pack _start ( label ) ;
dialog . signal . response . connect ( function ( w , response _id )
{
if ( response _id )
{
if ( city . length == 0 )
city = [ ] ;
if ( city . length > 0 && typeof city != "object" )
city = [ city ] ;
if ( city . length > 0 )
city . splice ( ac , 1 ) ;
if ( city . length > 1 )
that . city = city . join ( " && " ) ;
else if ( city [ 0 ] )
that . city = city [ 0 ] ;
else
that . city = "" ;
}
dialog . hide ( ) ;
} ) ;
dialog . show _all ( ) ;
} ,
changeSelection : function ( )
{
var path = this . actual _city ;
if ( arguments [ 0 ] )
path = arguments [ 0 ] ;
path = new Gtk . TreePath . from _string ( path ) ;
this . treeview . get _selection ( ) . select _path ( path ) ;
} ,
loadJsonAsync : function ( url , fun )
{
var here = this ;
var message = new Soup . Message . c _new ( 'GET' , url ) ;
_httpSession . queue _message ( message , function ( _httpSession , message ) {
if ( ! message . response _body . data )
{
fun . call ( here , 0 ) ;
return 0 ;
}
try
{
var jp = JSON . parse ( message . response _body . data ) ;
fun . call ( here , jp ) ;
}
catch ( e )
{
fun . call ( here , 0 ) ;
return 0 ;
}
} ) ;
} ,
loadConfig : function ( )
{
var that = this ;
var schema = WEATHER _SETTINGS _SCHEMA ;
if ( Gio . Settings . list _schemas ( ) . indexOf ( schema ) == - 1 )
throw _ ( "Schema \"%s\" not found." ) . format ( schema ) ;
this . Settings = new Gio . Settings ( { schema : schema } ) ;
this . Settings . signal . connect ( "changed" , function ( ) { that . refreshUI ( ) ; } ) ;
} ,
get units ( )
{
if ( ! this . Settings )
this . loadConfig ( ) ;
return this . Settings . get _enum ( WEATHER _UNIT _KEY ) ;
} ,
set units ( )
{
if ( ! this . Settings )
this . loadConfig ( ) ;
this . Settings . set _enum ( WEATHER _UNIT _KEY , arguments [ 0 ] ) ;
} ,
get wind _speed _unit ( )
{
if ( ! this . Settings )
this . loadConfig ( ) ;
return this . Settings . get _enum ( WEATHER _WIND _SPEED _UNIT _KEY ) ;
} ,
set wind _speed _unit ( )
{
if ( ! this . Settings )
this . loadConfig ( ) ;
this . Settings . set _enum ( WEATHER _WIND _SPEED _UNIT _KEY , arguments [ 0 ] ) ;
} ,
get wind _direction ( )
{
if ( ! this . Settings )
this . loadConfig ( ) ;
return this . Settings . get _boolean ( WEATHER _WIND _DIRECTION _KEY ) ;
} ,
set wind _direction ( )
{
if ( ! this . Settings )
this . loadConfig ( ) ;
return this . Settings . set _boolean ( WEATHER _WIND _DIRECTION _KEY , arguments [ 0 ] ) ;
} ,
get city ( )
{
if ( ! this . Settings )
this . loadConfig ( ) ;
return this . Settings . get _string ( WEATHER _CITY _KEY ) ;
} ,
set city ( )
{
if ( ! this . Settings )
this . loadConfig ( ) ;
this . Settings . set _string ( WEATHER _CITY _KEY , arguments [ 0 ] ) ;
} ,
get actual _city ( )
{
if ( ! this . Settings )
this . loadConfig ( ) ;
var a = this . Settings . get _int ( WEATHER _ACTUAL _CITY _KEY ) ;
var citys = this . city . split ( " && " ) ;
if ( citys && typeof citys == "string" )
citys = [ citys ] ;
var l = citys . length - 1 ;
if ( a < 0 )
a = 0 ;
if ( l < 0 )
l = 0 ;
if ( a > l )
a = l ;
return a ;
} ,
set actual _city ( )
{
if ( ! this . Settings )
this . loadConfig ( ) ;
var a = arguments [ 0 ] ;
var citys = this . city . split ( " && " ) ;
if ( citys && typeof citys == "string" )
citys = [ citys ] ;
var l = citys . 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 translate _condition ( )
{
if ( ! this . Settings )
this . loadConfig ( ) ;
return this . Settings . get _boolean ( WEATHER _TRANSLATE _CONDITION _KEY ) ;
} ,
set translate _condition ( )
{
if ( ! this . Settings )
this . loadConfig ( ) ;
this . Settings . set _boolean ( WEATHER _TRANSLATE _CONDITION _KEY , arguments [ 0 ] ) ;
} ,
get icon _type ( )
{
if ( ! this . Settings )
this . loadConfig ( ) ;
return this . Settings . get _boolean ( WEATHER _USE _SYMBOLIC _ICONS _KEY ) ;
} ,
set icon _type ( )
{
if ( ! this . Settings )
this . loadConfig ( ) ;
this . Settings . set _boolean ( WEATHER _USE _SYMBOLIC _ICONS _KEY , arguments [ 0 ] ) ;
} ,
get text _in _panel ( )
{
if ( ! this . Settings )
this . loadConfig ( ) ;
return this . Settings . get _boolean ( WEATHER _SHOW _TEXT _IN _PANEL _KEY ) ;
} ,
set text _in _panel ( )
{
if ( ! this . Settings )
this . loadConfig ( ) ;
this . Settings . set _boolean ( WEATHER _SHOW _TEXT _IN _PANEL _KEY , arguments [ 0 ] ) ;
} ,
get position _in _panel ( )
{
if ( ! this . Settings )
this . loadConfig ( ) ;
return this . Settings . get _enum ( WEATHER _POSITION _IN _PANEL _KEY ) ;
} ,
set position _in _panel ( )
{
if ( ! this . Settings )
this . loadConfig ( ) ;
this . Settings . set _enum ( WEATHER _POSITION _IN _PANEL _KEY , arguments [ 0 ] ) ;
} ,
get comment _in _panel ( )
{
if ( ! this . Settings )
this . loadConfig ( ) ;
return this . Settings . get _boolean ( WEATHER _SHOW _COMMENT _IN _PANEL _KEY ) ;
} ,
set comment _in _panel ( )
{
if ( ! this . Settings )
this . loadConfig ( ) ;
this . Settings . set _boolean ( WEATHER _SHOW _COMMENT _IN _PANEL _KEY , arguments [ 0 ] ) ;
} ,
get refresh _interval ( )
{
if ( ! this . Settings )
this . loadConfig ( ) ;
return this . Settings . get _int ( WEATHER _REFRESH _INTERVAL ) ;
} ,
set refresh _interval ( )
{
if ( ! this . Settings )
this . loadConfig ( ) ;
this . Settings . set _int ( WEATHER _REFRESH _INTERVAL , arguments [ 0 ] ) ;
} ,
extractLocation : function ( )
{
if ( arguments [ 0 ] . search ( ">" ) == - 1 )
return _ ( "Invalid city" ) ;
return arguments [ 0 ] . split ( ">" ) [ 1 ] ;
} ,
extractWoeid : function ( )
{
if ( arguments [ 0 ] . search ( ">" ) == - 1 )
return 0 ;
return arguments [ 0 ] . split ( ">" ) [ 0 ] ;
} ,
refreshUI : function ( )
{
this . Window . get _object ( "tree-toolbutton-remove" ) . sensitive = Boolean ( this . city . length ) ;
if ( this . mCities != this . city )
{
if ( typeof this . liststore != "undefined" )
this . liststore . clear ( ) ;
if ( this . city . length > 0 )
{
var city = String ( this . city ) . split ( " && " ) ;
if ( city && typeof city == "string" )
city = [ city ] ;
var iter = this . iter ;
for ( var i in city )
{
var a = this . liststore . append ( iter ) ;
var current = a . iter ;
this . liststore . set _value ( current , 0 , this . extractLocation ( city [ i ] ) ) ;
}
}
this . mCities = this . city ;
}
this . changeSelection ( ) ;
var config = this . configWidgets ;
for ( var i in config )
if ( config [ i ] [ 0 ] . active != this [ config [ i ] [ 1 ] ] )
config [ i ] [ 0 ] . active = this [ config [ i ] [ 1 ] ] ;
} ,
initConfigWidget : function ( )
{
var a = this . Window . get _object ( "right-widget-table" ) ;
a . visible = 1 ;
a . can _focus = 0 ;
this . widget = a ;
} ,
x : [ 0 , 1 ] ,
y : [ 0 , 1 ] ,
configWidgets : [ ] ,
inc : function ( )
{
if ( this . x [ 0 ] == 1 )
{
this . x [ 0 ] = 0 ;
this . x [ 1 ] = 1 ;
this . y [ 0 ] += 1 ;
this . y [ 1 ] += 1 ;
}
else
{
this . x [ 0 ] += 1 ;
this . x [ 1 ] += 1 ;
}
} ,
addLabel : function ( text )
{
var l = new Gtk . Label ( { label : text , xalign : 0 } ) ;
l . visible = 1 ;
l . can _focus = 0 ;
this . widget . attach ( l , this . x [ 0 ] , this . x [ 1 ] , this . y [ 0 ] , this . y [ 1 ] ) ;
this . inc ( ) ;
} ,
addComboBox : function ( a , b )
{
var that = this ;
var cf = new Gtk . ComboBoxText ( ) ;
this . configWidgets . push ( [ cf , b ] ) ;
cf . visible = 1 ;
cf . can _focus = 0 ;
cf . width _request = 75 ;
for ( var i in a )
cf . append _text ( a [ i ] ) ;
cf . active = this [ b ] ;
cf . signal . changed . connect ( function ( ) { that [ b ] = arguments [ 0 ] . active ; } ) ;
this . widget . attach ( cf , this . x [ 0 ] , this . x [ 1 ] , this . y [ 0 ] , this . y [ 1 ] ) ;
this . inc ( ) ;
} ,
addSwitch : function ( a )
{
var that = this ;
var sw = new Gtk . Switch ( ) ;
this . configWidgets . push ( [ sw , a ] ) ;
sw . visible = 1 ;
sw . can _focus = 0 ;
sw . active = this [ a ] ;
sw . signal . connect ( "notify::active" , function ( ) { that [ a ] = arguments [ 0 ] . active ; } ) ;
this . widget . attach ( sw , this . x [ 0 ] , this . x [ 1 ] , this . y [ 0 ] , this . y [ 1 ] ) ;
this . inc ( ) ;
} ,
initWindow : function ( )
{
var that = this ;
this . Window = new Gtk . Builder ( ) ;
this . Window . add _from _file ( "@EXTENSIONDIR@/weather-settings.ui" ) ;
this . Window . get _object ( "main-window" ) . title = _ ( "Weather Settings" ) ;
this . Window . connect _signals (
{
add _button _clicked : function ( button )
{
that . addCity ( ) ;
} ,
remove _button _clicked : function ( button )
{
that . removeCity ( ) ;
} ,
selection _changed : function ( selection )
{
that . selectionChanged ( selection ) ;
}
} ) ;
this . treeview = this . Window . get _object ( "tree-treeview" ) ;
this . iter = new Gtk . TreeIter ( ) ;
this . liststore = new Gtk . ListStore . c _new ( 1 , [ GObject . TYPE _STRING ] ) ;
this . treeview . set _model ( this . liststore ) ;
var column = new Gtk . TreeViewColumn ( )
this . treeview . append _column ( column ) ;
renderer = new Gtk . CellRendererText ( ) ;
column . pack _start ( renderer ) ;
column . set _cell _data _func ( renderer , function ( )
{
arguments [ 1 ] . markup = arguments [ 2 ] . get _value ( arguments [ 3 ] , 0 ) . value . get _string ( ) ;
} ) ;
this . initConfigWidget ( ) ;
this . addLabel ( _ ( "Temperature Unit" ) ) ;
this . addComboBox ( [ "°C" , "°F" , "K" ] , "units" ) ;
this . addLabel ( _ ( "Wind Speed Unit" ) ) ;
this . addComboBox ( [ "km/h" , "mph" , "m/s" , "knots" ] , "wind_speed_unit" ) ;
this . addLabel ( _ ( "Position in Panel" ) ) ;
this . addComboBox ( [ _ ( "Center" ) , _ ( "Right" ) , _ ( "Left" ) ] , "position_in_panel" ) ;
this . addLabel ( _ ( "Wind Direction by Arrows" ) ) ;
this . addSwitch ( "wind_direction" ) ;
this . addLabel ( _ ( "Translate Conditions" ) ) ;
this . addSwitch ( "translate_condition" ) ;
this . addLabel ( _ ( "Symbolic Icons" ) ) ;
this . addSwitch ( "icon_type" ) ;
this . addLabel ( _ ( "Temperature in Panel" ) ) ;
this . addSwitch ( "text_in_panel" ) ;
this . addLabel ( _ ( "Conditions in Panel" ) ) ;
this . addSwitch ( "comment_in_panel" ) ;
} ,
showWindow : function ( )
{
this . Window . get _object ( "main-window" ) . signal . hide . connect ( Gtk . main _quit ) ;
this . Window . get _object ( "main-window" ) . show _all ( ) ;
} ,
selectionChanged : function ( select )
{
if ( typeof select . get _selected _rows ( this . treestore ) [ 0 ] == "object" )
{
var a = select . get _selected _rows ( this . treestore ) [ 0 ] . to _string ( ) ;
if ( this . actual _city != parseInt ( a ) )
this . actual _city = parseInt ( a ) ;
}
}
} ;
new WeatherSetting ( ) ;