[gnome-clocks/wip/cityimages] Initial city images support



commit 4bfa2dc9851e033e6a5f6fc2b716ebda689d47c5
Author: Evgeny Bobkin <evgen ibqn gmail com>
Date:   Thu Sep 12 14:10:40 2013 +0200

    Initial city images support

 Makefile.am               |    1 +
 data/css/gnome-clocks.css |   13 ++++-
 data/ui/world.ui          |    8 +---
 src/providers.vala        |  127 +++++++++++++++++++++++++++++++++++++++++++++
 src/world.vala            |   78 +++++++++++++++++++++++----
 5 files changed, 206 insertions(+), 21 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index e939fbc..b27d647 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -111,6 +111,7 @@ VALA_SOURCES = \
        src/window.vala \
        src/clock.vala \
        src/world.vala \
+       src/providers.vala \
        src/alarm.vala \
        src/stopwatch.vala \
        src/timer.vala \
diff --git a/data/css/gnome-clocks.css b/data/css/gnome-clocks.css
index ccaf01c..9d5a214 100644
--- a/data/css/gnome-clocks.css
+++ b/data/css/gnome-clocks.css
@@ -93,13 +93,22 @@
     background-image: none;
 }
 
-.clocks-standalone-label,
 .clocks-ringing-label {
     font-size: 64px;
 }
 
+.clocks-standalone-label {
+    font-size: 64px;
+    font-weight: bold;
+    text-shadow: inset 1px 1px 3px black;
+    color: white;
+}
+
 .clocks-secondary-standalone-label {
-    font-size: 18px;
+    font-size: 24px;
+    font-weight: bold;
+    text-shadow: inset 1px 1px 3px black;
+    color: white;
 }
 
 .clocks-button {
diff --git a/data/ui/world.ui b/data/ui/world.ui
index b05dd78..a829c70 100644
--- a/data/ui/world.ui
+++ b/data/ui/world.ui
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <interface>
-  <!-- interface-requires gtk+ 3.0 -->
+  <!-- interface-requires gtk+ 3.10 -->
   <object class="GtkGrid" id="empty_panel">
     <property name="visible">True</property>
     <property name="can_focus">False</property>
@@ -120,9 +120,6 @@
             <property name="visible">True</property>
             <property name="can_focus">False</property>
             <property name="label" translatable="yes">Sunrise</property>
-            <style>
-              <class name="dim-label"/>
-            </style>
           </object>
           <packing>
             <property name="left_attach">0</property>
@@ -136,9 +133,6 @@
             <property name="visible">True</property>
             <property name="can_focus">False</property>
             <property name="label" translatable="yes">Sunset</property>
-            <style>
-              <class name="dim-label"/>
-            </style>
           </object>
           <packing>
             <property name="left_attach">0</property>
diff --git a/src/providers.vala b/src/providers.vala
new file mode 100644
index 0000000..29ae6ae
--- /dev/null
+++ b/src/providers.vala
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2013  Evgeny Bobkin <evgen ibqn gmail com>
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+namespace Clocks {
+namespace World {
+
+public interface ImageProvider : GLib.Object {
+    public virtual Gdk.Pixbuf? get_image (string name) {
+        return null;
+    }
+
+    public signal void image_updated ();
+}
+
+// This is the default fallback provider
+public class DefaultProvider : GLib.Object, ImageProvider {
+    private static Gdk.Pixbuf? day_image;
+    private static Gdk.Pixbuf? night_image;
+
+       public virtual Gdk.Pixbuf? get_image (string name) {
+        if (name.has_suffix ("-day")) {
+            return day_image;
+        } else if (name.has_suffix ("-night")) {
+            return night_image;
+        }
+        return null;
+    }
+
+    public DefaultProvider () {
+        day_image = Utils.load_image ("day.png");
+        night_image =  Utils.load_image ("night.png");
+    }
+}
+
+public class LocalImageProvider : GLib.Object, ImageProvider {
+    private string folder_path;
+    private FileMonitor monitor;
+
+    public LocalImageProvider () {
+        folder_path = GLib.Path.build_path (GLib.Path.DIR_SEPARATOR_S,
+                                            GLib.Environment.get_user_data_dir (),
+                                            "gnome-clocks", "city-images");
+
+        File folder = File.new_for_path (folder_path);
+
+        try {
+            monitor = folder.monitor_directory (FileMonitorFlags.NONE, null);
+            stdout.printf ("Monitoring: %s\n", folder.get_path ());
+
+            monitor.changed.connect ((src, dest, event) => {
+                if (dest != null) {
+                    stdout.printf ("%s: %s, %s\n", event.to_string (),
+                                   src.get_path (), dest.get_path ());
+                } else {
+                    stdout.printf ("%s: %s\n", event.to_string (), src.get_path ());
+                }
+
+                image_updated ();
+            });
+        } catch (Error err) {
+            warning ("Monitoring image files: %s\n", err.message);
+        }
+    }
+
+    public Gdk.Pixbuf? get_image (string name) {
+        Gdk.Pixbuf? image = null;
+
+        try {
+            var path = GLib.Path.build_path (GLib.Path.DIR_SEPARATOR_S, folder_path, name + ".jpg");
+
+            image = new Gdk.Pixbuf.from_file (path);
+               } catch (Error e) {
+            warning ("Loading image file: %s", e.message);
+        }
+
+        return image;
+    }
+}
+
+public class AutomaticImageProvider : GLib.Object, ImageProvider {
+       private List<ImageProvider> providers;
+
+    public AutomaticImageProvider () {
+               providers = new List<ImageProvider> ();
+
+               providers.prepend (new DefaultProvider ());
+               providers.prepend (new LocalImageProvider ());
+
+        foreach (var provider in providers) {
+            provider.image_updated.connect (() => {
+                image_updated ();
+            });
+        }
+       }
+
+       public virtual Gdk.Pixbuf? get_image (string name) {
+               Gdk.Pixbuf? image = null;
+
+               foreach (ImageProvider provider in providers) {
+                       image = provider.get_image (name);
+
+                       if (image != null) {
+                               break;
+                       }
+               }
+
+               return image;
+    }
+}
+
+} // namespace World
+} // namespace Clocks
diff --git a/src/world.vala b/src/world.vala
index c7e708f..5745949 100644
--- a/src/world.vala
+++ b/src/world.vala
@@ -19,10 +19,9 @@
 namespace Clocks {
 namespace World {
 
-private class Item : Object, ContentItem {
-    private static Gdk.Pixbuf? day_pixbuf = Utils.load_image ("day.png");
-    private static Gdk.Pixbuf? night_pixbuf = Utils.load_image ("night.png");
+private static AutomaticImageProvider image_provider;
 
+private class Item : Object, ContentItem {
     public GWeather.Location location { get; set; }
 
     public bool automatic { get; set; default = false; }
@@ -119,21 +118,50 @@ private class Item : Object, ContentItem {
         }
     }
 
+    public Gdk.Pixbuf? day_pixbuf { get; private set; }
+    public Gdk.Pixbuf? night_pixbuf { get; private set; }
+
     private string _name;
     private GLib.TimeZone time_zone;
     private GLib.DateTime local_time;
     private GLib.DateTime date_time;
     private GWeather.Info weather_info;
+    private Gdk.Pixbuf? scaled_day_pixbuf;
+    private Gdk.Pixbuf? scaled_night_pixbuf;
+    private string file_name;
 
     public Item (GWeather.Location location) {
         Object (location: location);
 
         var weather_time_zone = location.get_timezone ();
-        time_zone = new GLib.TimeZone (weather_time_zone.get_tzid());
+        time_zone = new GLib.TimeZone (weather_time_zone.get_tzid ());
+        
+        string old_loc = Intl.setlocale (LocaleCategory.MESSAGES, null);
+        Intl.setlocale (LocaleCategory.MESSAGES, "en_US.UTF-8");
+
+        if (nation_name != null) {
+            file_name = "%s-%s".printf (city_name, nation_name);
+        } else {
+            file_name = city_name;
+        }
+        file_name = file_name.down ();
+        Intl.setlocale (LocaleCategory.MESSAGES, old_loc);
+
+        image_provider.image_updated.connect (update_images);
+
+        update_images ();
 
         tick ();
     }
 
+    public void update_images () {
+        day_pixbuf = image_provider.get_image (file_name + "-day");
+        scaled_day_pixbuf = day_pixbuf.scale_simple (256, 256, Gdk.InterpType.BILINEAR);
+
+        night_pixbuf = image_provider.get_image (file_name + "-night");
+        scaled_night_pixbuf = night_pixbuf.scale_simple (256, 256, Gdk.InterpType.BILINEAR);
+    }
+
     public void tick () {
         var wallclock = Utils.WallClock.get_default ();
         local_time = wallclock.date_time;
@@ -147,10 +175,10 @@ private class Item : Object, ContentItem {
         text = time_label;
         subtext = day_label;
         if (is_daytime) {
-            pixbuf = day_pixbuf;
+            pixbuf = scaled_day_pixbuf;
             css_class = "light";
         } else {
-            pixbuf = night_pixbuf;
+            pixbuf = scaled_night_pixbuf;
             css_class = "dark";
         }
     }
@@ -225,6 +253,9 @@ private class StandalonePanel : Gtk.EventBox {
     private Gtk.Label day_label;
     private Gtk.Label sunrise_label;
     private Gtk.Label sunset_label;
+    private Gtk.Image city_image;
+    private Gdk.Pixbuf? day_pixbuf;
+    private Gdk.Pixbuf? night_pixbuf;
 
     public StandalonePanel () {
         get_style_context ().add_class ("view");
@@ -238,7 +269,16 @@ private class StandalonePanel : Gtk.EventBox {
         sunrise_label = builder.get_object ("sunrise_label") as Gtk.Label;
         sunset_label = builder.get_object ("sunset_label") as Gtk.Label;
 
-        add (grid);
+        var overlay = new Gtk.Overlay ();
+        city_image = new Gtk.Image ();
+        city_image.halign = Gtk.Align.FILL;
+        city_image.valign = Gtk.Align.FILL;
+        overlay.add (city_image);
+        overlay.add_overlay (grid);
+
+        city_image.size_allocate.connect (on_size_allocate);
+
+        add (overlay);
     }
 
     public void update () {
@@ -247,6 +287,23 @@ private class StandalonePanel : Gtk.EventBox {
             day_label.label = location.day_label;
             sunrise_label.label = location.sunrise_label;
             sunset_label.label = location.sunset_label;
+
+            if (location.is_daytime) {
+                city_image.set_from_pixbuf (day_pixbuf);
+            } else {
+                city_image.set_from_pixbuf (night_pixbuf);
+            }
+        }
+    }
+
+    public void on_size_allocate (Gtk.Allocation rectangle) {
+        day_pixbuf = location.day_pixbuf.scale_simple (rectangle.width, rectangle.height, 
Gdk.InterpType.BILINEAR);
+        night_pixbuf = location.night_pixbuf.scale_simple (rectangle.width, rectangle.height, 
Gdk.InterpType.BILINEAR);
+
+        if (location.is_daytime) {
+            city_image.set_from_pixbuf (day_pixbuf);
+        } else {
+            city_image.set_from_pixbuf (night_pixbuf);
         }
     }
 }
@@ -260,20 +317,17 @@ public class MainPanel : Gtk.Stack, Clocks.Clock {
     private GLib.Settings settings;
     private Gtk.Button new_button;
     private Gtk.Button back_button;
-    private Gdk.Pixbuf? day_pixbuf;
-    private Gdk.Pixbuf? night_pixbuf;
     private ContentView content_view;
     private StandalonePanel standalone;
 
     public MainPanel (HeaderBar header_bar) {
         Object (label: _("World"), header_bar: header_bar, transition_type: 
Gtk.StackTransitionType.CROSSFADE, panel_id: PanelId.WORLD);
 
+        image_provider = new AutomaticImageProvider ();
+
         locations = new List<Item> ();
         settings = new GLib.Settings ("org.gnome.clocks");
 
-        day_pixbuf = Utils.load_image ("day.png");
-        night_pixbuf = Utils.load_image ("night.png");
-
         // Translators: "New" refers to a world clock
         new_button = new Gtk.Button.with_label (_("New"));
         new_button.valign = Gtk.Align.CENTER;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]