1. Improve gnome-clocks world view (pictures, geolocation)
1.1. Abstract
The use of new GNOME 3 design pattern has already been proven to turn the user experience into a pleasure. Working in a close collaboration with the GNOME Design Team the main goal of this project is on one side to improve gnome-clocks world view by implementing the support for custom city images as well as the integration with geolocation and on the another side to use a framework of gnome-clocks App to test and to implement new design ideas. The wip/geoclue branch contains a port of the same code to the geoclue service.
1.2. Design Ideas
The tentative geolocation design with the discussion of the implementation ideas and issues can be found here: GeolocationIntegration.
1.2.1. Geolocation support
On the wip/geolocation branch there is a working implementation of the design that directly queries the http provider, this was done to not block the implementation on the ongoing changes to the geoclue module.
The work on geolocation support took place in the wip/geolocation and wip/geoinfo branches. Afterwards It was pushed to the master branch. Thank to my mentor, this featute, therefore, will be part of the 3.10 release. \o/ Feel free to try it out!
1.2.2. City Images Support
The following Figure shows a screenshot of the city images support in Clocks. The city image changes dynamically corresponding to the day and night time, respectively.
Once, you one of the cities is selected you are forwarded to the standalone mode, in which the image of the city is shown in the background, as illustrated in the picture below:
Flickr group has been created for sharing city images between users. The corresponding code is developed in the wip/cityimages branch. Currently only three experimental provider were implemented: Default fallback provider, Local image provider and the Flickr group provider, respectively. They are all inherited from the following interface:
- The default fallback provider is only capable to provide two statically stored image for a day and night as illustrated in the first screenshot with the shown geolocation support.
- The Local image provider transmits the images saved in the directory:
~/.local/share/gnome-clocks/city-images
The file names should follow the name convention: <city name>-<country name>-<{day|night}>.jpg (everything in lower case), like for example:
berlin-germany-day.jpg tokyo-japan-night.jpg london-united kingdom-day.jpg
The Flickr group provider is responsible for downloading of images from the gnome-clocks group and save them in ~/.local/share/gnome-clocks/city-images/flickr directory. For the testing phase it only contains images of the following cities: tokyo, berlin, moscow, rome.
1.3. How to test
Here, below you can find some code snippets, which I was using during the geolocation test phase. Therefore I heve ported a small class to Vala, which is able to obtain and parse the geolocation related data from services like: http://freegeoip.net/json/. The output is a Json string:
{"ip":"78.52.9.161","country_code":"DE","country_name":"Germany","region_code":"16","region_name":"Berlin","city":"Berlin","zipcode":"","latitude":52.5167,"longitude":13.4,"metro_code":"","areacode":""}
1 MainLoop main_loop;
2
3 public static void main () {
4 var monitor = new GeoInfo.LocationLookUp ();
5 monitor.server = "https://geoip.fedoraproject.org/city";
6 monitor.search.begin ((obj, res) => {
7 GeoInfo.LocationInfo? location = monitor.search.end (res);
8
9 if (location != null ) {
10 stdout.printf ("Latitude: %lf\nLongitude: %lf\n",
11 location.latitude,
12 location.longitude);
13
14 string? str = location.country_name;
15 if (str != null) {
16 stdout.printf ("Country name: %s\n", str);
17 }
18
19 str = location.country_code;
20 if (str != null) {
21 stdout.printf ("Country code: %s\n", str);
22 }
23
24 str = location.time_zone;
25 if (str != null) {
26 stdout.printf ("Time zone: %s\n", str);
27 }
28 }
29
30 main_loop.quit ();
31 });
32
33 main_loop = new MainLoop ();
34 main_loop.run ();
35 }
I was using the latest libsoup Vala binding for the asynchronous calls, so better to be on the safe side try it out under the jhbuild with the latest corresponding libraries and Vala versions installed.
$ jhbuild shell $ make valac --thread --enable-experimental --pkg libsoup-2.4 location-lookup.vala location-info.vala main.vala --target-glib=2.38 --pkg gio-2.0 --pkg json-glib-1.0 $ ./location-lookup Latitude: 52.516701 Longitude: 13.400000 Country name: Germany Country code: DE Timezone: Europe/Berlin
The source code of this sample can be found here: location-lookup.tar.gz.
1.3.1. Helper Tools
To find matches in the libgweather database between the city names and the corresponding timezone on one side with the longitude and latitude data on the other side the following helper tool was written:
It's source code can be found here: helper-tool.tar.gz.
1.4. External libraries in Clocks
1.4.1. Libgweather
The full source code can be found here libgweather-vala.tar.gz
1.4.2. Geoclue
1 [DBus (name = "org.freedesktop.GeoClue2.Manager")]
2 interface Manager : Object {
3 public abstract async void get_client (out string client_path) throws IOError;
4 }
5
6 [DBus (name = "org.freedesktop.GeoClue2.Client")]
7 interface Client : Object {
8 public abstract string location { owned get; }
9 public abstract uint distance_threshold { get; set; }
10 public abstract async void start () throws IOError;
11 public abstract async void stop () throws IOError;
12 public signal void location_updated (string old_path, string new_path);
13 }
14
15 [DBus (name = "org.freedesktop.GeoClue2.Location")]
16 interface Location : Object {
17 public abstract double latitude { get; }
18 public abstract double longitude { get; }
19 public abstract double accuracy { get; }
20 public abstract string description { owned get; }
21 }
22
23 class FindLocation : Object {
24 public static MainLoop main_loop = new MainLoop ();
25
26 public FindLocation () {
27 Environment.set_application_name ("Find Location");
28 }
29
30 public async void seek () {
31 Manager manager;
32 Client client;
33
34 string? client_path = null;
35
36 try {
37 manager = yield Bus.get_proxy (GLib.BusType.SYSTEM,
38 "org.freedesktop.GeoClue2",
39 "/org/freedesktop/GeoClue2/Manager");
40 } catch (IOError e) {
41 error ("Failed to connect to GeoClue2 Manager service: %s", e.message);
42 }
43
44 try {
45 yield manager.get_client (out client_path);
46 } catch (IOError e) {
47 error ("Failed to connect to GeoClue2 Manager service: %s", e.message);
48 }
49
50 if (client_path == null) {
51 error ("The client path is not set");
52 }
53
54 stdout.printf ("Client object: %s\n", client_path);
55
56 try {
57 client = yield Bus.get_proxy (GLib.BusType.SYSTEM,
58 "org.freedesktop.GeoClue2",
59 client_path);
60 } catch (IOError e) {
61 error ("Failed to connect to GeoClue2 Client service: %s", e.message);
62 }
63
64 client.location_updated.connect (on_location_updated);
65
66 try {
67 yield client.start ();
68 } catch (IOError e) {
69 error ("Failed to start client: %s", e.message);
70 }
71 }
72
73 public async void on_location_updated (string old_path, string new_path) {
74 Location location;
75 try {
76 location = yield Bus.get_proxy (GLib.BusType.SYSTEM,
77 "org.freedesktop.GeoClue2",
78 new_path);
79 } catch (Error e) {
80 error ("Failed to connect to GeoClue2 Location service: %s", e.message);
81 }
82
83 stdout.printf ("Latitude: %lf\nLongitude: %lf\nAccuracy (in meters): %lf\n",
84 location.latitude,
85 location.longitude,
86 location.accuracy);
87
88 string desc = location.description;
89 if (desc != null)
90 stdout.printf ("Description: %s\n", desc);
91
92 main_loop.quit ();
93 }
94
95 public static void main () {
96 var fl = new FindLocation ();
97 fl.seek.begin ();
98
99 main_loop.run ();
100 }
101 }
$ jhbuild shell under jhbuild $ make valac find-location.vala --target-glib=2.38 --pkg gio-2.0 $ ./find-location Client object: /org/freedesktop/GeoClue2/Client/1 Latitude: 52.516700 Longitude: 13.400000 Accuracy (in meters): 15000.000000 Description: Berlin, Berlin, Germany
1.4.3. GeocodeGlib
1 void main () {
2 var main_loop = new MainLoop ();
3
4 var location = new Geocode.Location (46.2000, 10.1330, Geocode.LOCATION_ACCURACY_UNKNOWN);
5 var reverse = new Geocode.Reverse.for_location (location);
6
7 reverse.resolve_async.begin (null, (obj, res) => {
8 try {
9 Geocode.Place place = reverse.resolve_async.end (res);
10
11 stdout.printf ("country code: %s\n", place.get_country_code ());
12 } catch (Error e) {
13 error ("Failed to reverse location");
14 }
15 main_loop.quit ();
16 });
17
18 main_loop.run ();
19 }
$ jhbuild shell under jhbuild $ make valac --target-glib=2.38 reverse.vala --pkg geocode-glib-1.0 $ ./reverse country code: it
1.5. GUADEC
Within the frame of the GSOC 2013 project I have participated in the GUADEC conference, which took place in Brno, Czech Republic.
Picture is take from aakash's blog post.
My travel to the conference was sponsored by the GNOME Foundation.