[gnome-calendar] window: a load more weather changes



commit b8f51e1d3d5447bbdad8610a2f576eed34f86727
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date:   Sun Dec 17 11:35:19 2017 -0200

    window: a load more weather changes

 data/ui/menus.ui           | 152 ----------
 data/ui/window.ui          | 128 ++++++++
 src/gcal-utils.h           |   2 +
 src/gcal-weather-service.c |  86 +++---
 src/gcal-window.c          | 737 ++++++++++++++-------------------------------
 5 files changed, 397 insertions(+), 708 deletions(-)
---
diff --git a/data/ui/menus.ui b/data/ui/menus.ui
index a41d49fe..7c9f167e 100644
--- a/data/ui/menus.ui
+++ b/data/ui/menus.ui
@@ -30,158 +30,6 @@
       </item>
     </section>
   </menu>
-  <object class="GtkPopoverMenu" id="win-menu">
-    <child>
-      <object class="GtkStack" id="win-menu-stack">
-        <property name="visible">True</property>
-        <property name="can_focus">False</property>
-        <property name="vhomogeneous">False</property>
-        <child>
-          <!-- Initial user menu: -->
-          <object class="GtkBox">
-            <property name="margin">12</property>
-            <property name="visible">True</property>
-            <property name="orientation">vertical</property>
-            <child>
-              <object class="GtkModelButton">
-                <property name="text" translatable="yes">Add Eve_nt</property>
-                <property name="action-name">app.new</property>
-                <property name="visible">True</property>
-              </object>
-            </child>
-            <child>
-              <object class="GtkModelButton">
-                <property name="text" translatable="yes">_Synchronize</property>
-                <property name="action-name">app.sync</property>
-                <property name="visible">True</property>
-              </object>
-            </child>
-            <child>
-              <object class="GtkModelButton" id="win-menu-open-weather">
-                <property name="text" translatable="yes">_Weather</property>
-                <property name="menu-name" translatable="yes">win-menu-weather</property>
-                <property name="visible">True</property>
-              </object>
-            </child>
-          </object>
-          <packing>
-            <property name="name">win-menu-main</property>
-          </packing>
-        </child>
-        <child>
-          <!-- Weather Box: -> name this weather-settings -->
-          <object class="GtkBox">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="orientation">vertical</property>
-            <property name="margin">12</property>
-            <property name="spacing">5</property> <!-- TODO: check HIG for right value -->
-            <child>
-              <object class="GtkModelButton" id="win-menu-close-weather">
-                <property name="text" translatable="yes">_Weather</property>
-                <property name="menu-name" translatable="yes">win-menu-main</property>
-                <property name="inverted">True</property>
-                <property name="centered">True</property>
-                <property name="visible">True</property>
-              </object>
-              <packing>
-                <property name="position">0</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkBox">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="spacing">5</property> <!-- TODO: check HIG for right value -->
-                <child>
-                  <object class="GtkLabel">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="halign">start</property>
-                    <property name="label" translatable="yes">Show Weather</property>
-                  </object>
-                  <packing>
-                    <property name="expand">True</property>
-                    <property name="fill">True</property>
-                    <property name="position">0</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkSwitch" id="show-weather-switch">
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">True</property>
-                    <property name="position">1</property>
-                  </packing>
-                </child>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
-                <property name="position">1</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkBox" id="auto-location-box">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="spacing">5</property> <!-- TODO: check HIG for right value -->
-                <child>
-                  <object class="GtkLabel">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="halign">start</property>
-                    <property name="label" translatable="yes">Automatic Location</property>
-                  </object>
-                  <packing>
-                    <property name="expand">True</property>
-                    <property name="fill">True</property>
-                    <property name="position">0</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkSwitch" id="auto-location-switch">
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">True</property>
-                    <property name="position">1</property>
-                  </packing>
-                </child>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
-                <property name="position">2</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GWeatherLocationEntry" id="fixed-weather-location">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="primary_icon_name">edit-find-symbolic</property>
-                <property name="primary_icon_activatable">False</property>
-                <property name="primary_icon_sensitive">False</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
-                <property name="position">3</property>
-              </packing>
-            </child>
-          </object>
-          <packing>
-            <property name="name">win-menu-weather</property>
-          </packing>
-        </child>
-      </object>
-    </child>
-  </object>
   <menu id="add-source-menu">
     <section>
       <item>
diff --git a/data/ui/window.ui b/data/ui/window.ui
index 7afb0dc1..920fc068 100644
--- a/data/ui/window.ui
+++ b/data/ui/window.ui
@@ -249,6 +249,7 @@
           <object class="GtkMenuButton" id="menu_button">
             <property name="visible">True</property>
             <property name="can_focus">True</property>
+            <property name="popover">win_menu</property>
             <property name="receives_default">True</property>
             <child>
               <object class="GtkImage" id="menu_image">
@@ -369,4 +370,131 @@
     <signal name="response" handler="edit_dialog_closed" object="GcalWindow" swapped="no"/>
     <signal name="delete-event" handler="gtk_widget_hide_on_delete" object="GcalWindow" swapped="no"/>
   </object>
+  <object class="GtkPopoverMenu" id="win_menu">
+    <signal name="notify::visible" handler="on_popover_menu_visible_cb" object="GcalWindow" swapped="no" />
+    <child>
+      <object class="GtkStack" id="win_menu_stack">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="vhomogeneous">False</property>
+        <property name="transition_type">slide-left-right</property>
+        <property name="interpolate-size">True</property>
+        <child>
+
+          <!-- New Event -->
+          <object class="GtkBox">
+            <property name="margin">12</property>
+            <property name="visible">True</property>
+            <property name="orientation">vertical</property>
+            <child>
+              <object class="GtkModelButton">
+                <property name="text" translatable="yes">Add Eve_nt</property>
+                <property name="action-name">app.new</property>
+                <property name="visible">True</property>
+              </object>
+            </child>
+
+            <!-- Synchronize -->
+            <child>
+              <object class="GtkModelButton">
+                <property name="text" translatable="yes">_Synchronize</property>
+                <property name="action-name">app.sync</property>
+                <property name="visible">True</property>
+              </object>
+            </child>
+            <child>
+              <object class="GtkModelButton" id="win-menu-open-weather">
+                <property name="text" translatable="yes">_Weather</property>
+                <property name="menu-name" translatable="yes">weather-menu</property>
+                <property name="visible">True</property>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="name">main-menu</property>
+          </packing>
+        </child>
+
+        <!-- Weather -->
+        <child>
+          <object class="GtkBox">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="orientation">vertical</property>
+            <property name="margin">12</property>
+            <property name="spacing">6</property>
+            <child>
+              <object class="GtkModelButton">
+                <property name="text" translatable="yes">_Weather</property>
+                <property name="menu-name" translatable="yes">main-menu</property>
+                <property name="inverted">True</property>
+                <property name="centered">True</property>
+                <property name="visible">True</property>
+              </object>
+            </child>
+            <child>
+              <object class="GtkBox">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="spacing">18</property>
+                <child>
+                  <object class="GtkLabel">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="hexpand">True</property>
+                    <property name="xalign">0.0</property>
+                    <property name="label" translatable="yes">Show Weather</property>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkSwitch" id="show_weather_switch">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <signal name="notify::active" handler="on_show_weather_changed_cb" object="GcalWindow" 
swapped="no" />
+                  </object>
+                </child>
+              </object>
+            </child>
+            <child>
+              <object class="GtkBox" id="weather_auto_location_box">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="spacing">18</property>
+                <child>
+                  <object class="GtkLabel">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="hexpand">True</property>
+                    <property name="xalign">0.0</property>
+                    <property name="label" translatable="yes">Automatic Location</property>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkSwitch" id="weather_auto_location_switch">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <signal name="notify::active" handler="on_weather_auto_location_changed_cb" 
object="GcalWindow" swapped="no" />
+                  </object>
+                </child>
+              </object>
+            </child>
+            <child>
+              <object class="GWeatherLocationEntry" id="weather_location_entry">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="primary_icon_name">edit-find-symbolic</property>
+                <property name="primary_icon_activatable">False</property>
+                <property name="primary_icon_sensitive">False</property>
+                <signal name="changed" handler="on_weather_location_searchbox_changed_cb" 
object="GcalWindow" swapped="no" />
+                <signal name="activate" handler="on_weather_location_searchbox_changed_cb" 
object="GcalWindow" swapped="no" />
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="name">weather-menu</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+  </object>
 </interface>
diff --git a/src/gcal-utils.h b/src/gcal-utils.h
index a7b19561..cc9fea66 100644
--- a/src/gcal-utils.h
+++ b/src/gcal-utils.h
@@ -23,6 +23,7 @@
 #include "gcal-manager.h"
 #include <gtk/gtk.h>
 #include <libecal/libecal.h>
+#include <libgweather/gweather.h>
 #include <libical/icaltime.h>
 
 #define ICAL_TIME_TYPE (icaltime_get_type ())
@@ -36,6 +37,7 @@
 
 /* Add autoptr support for libecal */
 G_DEFINE_AUTOPTR_CLEANUP_FUNC (ESource, g_object_unref)
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (GWeatherLocation, gweather_location_unref)
 
 /**
  * GcalWindowViewType:
diff --git a/src/gcal-weather-service.c b/src/gcal-weather-service.c
index bbf91b06..3ebc9c1b 100644
--- a/src/gcal-weather-service.c
+++ b/src/gcal-weather-service.c
@@ -25,8 +25,9 @@
 #include <string.h>
 #include <math.h>
 
-#include "gcal-weather-service.h"
+#include "gcal-debug.h"
 #include "gcal-timer.h"
+#include "gcal-weather-service.h"
 
 
 #define DAY_SECONDS (24 * 60 * 60)
@@ -234,9 +235,10 @@ schedule_midnight (GcalWeatherService  *self)
 static void
 start_timer (GcalWeatherService  *self)
 {
-  GNetworkMonitor *monitor; /* unowned */
+  GNetworkMonitor *monitor;
 
   monitor = g_network_monitor_get_default ();
+
   if (g_network_monitor_get_network_available (monitor))
     {
       update_timeout_interval (self);
@@ -303,14 +305,8 @@ static gint
 get_icon_name_sortkey (const gchar *icon_name,
                        gboolean    *supports_night_icon)
 {
-  /* Note that we can't use gweathers condition
-   * field as it is not necessarily holds valid values.
-   * libgweather uses its own heuristic to determine
-   * the icon to use. String matching is still better
-   * than copying their algorithm, I guess.
-   */
-
   gssize normalized_name_len;
+  guint i;
 
   const GcalWeatherIconInfo icons[] =
     { {"weather-clear",             TRUE},
@@ -332,7 +328,7 @@ get_icon_name_sortkey (const gchar *icon_name,
   normalized_name_len = get_normalized_icon_name_len (icon_name);
   g_return_val_if_fail (normalized_name_len >= 0, -1);
 
-  for (int i = 0; i < G_N_ELEMENTS (icons); i++)
+  for (i = 0; i < G_N_ELEMENTS (icons); i++)
     {
       if (icons[i].name[normalized_name_len] == '\0' && strncmp (icon_name, icons[i].name, 
normalized_name_len) == 0)
         {
@@ -429,7 +425,8 @@ compute_weather_info_data (GSList    *samples,
   phenomenon_val = -1;
   phenomenon_supports_night_icon = FALSE;
 
-  /* Note: I checked three different gweather consumers
+  /*
+   * Note: I checked three different gweather consumers
    *   and they all pick different values. So here is my
    *   take: I pick up the worst weather for icons and
    *   the highest temperature. I basically want to know
@@ -441,8 +438,8 @@ compute_weather_info_data (GSList    *samples,
 
   for (iter = samples; iter; iter = iter->next)
     {
-      GWeatherInfo  *gwi;       /* unowned */
-      const gchar   *icon_name; /* unowned */
+      GWeatherInfo  *gwi;
+      const gchar *icon_name;
       gboolean supports_night_icon;
       gboolean valid_temp;
       gdouble temp;
@@ -478,6 +475,7 @@ compute_weather_info_data (GSList    *samples,
     {
       *icon_name = get_normalized_icon_name (phenomenon_gwi, is_today && !has_daytime && 
phenomenon_supports_night_icon);
       *temperature = gweather_info_get_temp (temp_gwi);
+
       return TRUE;
     }
   else
@@ -485,11 +483,11 @@ compute_weather_info_data (GSList    *samples,
       /* empty list */
       *icon_name = NULL;
       *temperature = NULL;
+
       return FALSE;
     }
 }
 
-
 static void
 update_location (GcalWeatherService  *self,
                  GWeatherLocation    *location)
@@ -571,8 +569,10 @@ preprocess_gweather_reports (GcalWeatherService *self,
   glong first_tomorrow_dtime = -1;
   glong today_unix;
   glong unix_now;
+  guint i;
 
-  /* This function basically separates samples by date and calls compute_weather_info_data
+  /*
+   * This function basically separates samples by date and calls compute_weather_info_data
    * for every bucket to build weather infos. Each bucket represents a single day.
    *
    * All gweather consumers I reviewed presume sorted samples. However, there is no documented
@@ -641,7 +641,7 @@ preprocess_gweather_reports (GcalWeatherService *self,
     }
 
   /* Produce GcalWeatherInfo for each bucket: */
-  for (int i = 0; i < self->max_days; i++)
+  for (i = 0; i < self->max_days; i++)
     {
       g_autofree gchar *icon_name;
       g_autofree gchar *temperature;
@@ -653,7 +653,7 @@ preprocess_gweather_reports (GcalWeatherService *self,
     }
 
   /* Cleanup */
-  for (int i = 0; i < self->max_days; i++)
+  for (i = 0; i < self->max_days; i++)
     g_slist_free (days[i]);
   g_free (days);
 
@@ -676,7 +676,7 @@ on_network_changed_cb (GNetworkMonitor    *monitor,
 
   if (available && !is_running)
     {
-      if (self->gweather_info != NULL)
+      if (self->gweather_info)
         gweather_info_update (self->gweather_info);
 
       start_timer (self);
@@ -712,6 +712,8 @@ on_gclue_simple_creation_cb (GClueSimple        *_source,
   GClueSimple *location_service;
   GClueClient *client;
 
+  GCAL_ENTRY;
+
   /*
    * Make sure we do not touch self->location_service
    * if the current operation was cancelled.
@@ -727,8 +729,7 @@ on_gclue_simple_creation_cb (GClueSimple        *_source,
       else
         g_warning ("Could not create GCLueSimple: %s", error->message);
 
-      g_object_unref (self);
-      return;
+      GCAL_RETURN ();
     }
 
   self->location_service = g_steal_pointer (&location_service);
@@ -740,29 +741,20 @@ on_gclue_simple_creation_cb (GClueSimple        *_source,
     {
       update_gclue_location (self, location);
 
-      g_signal_connect_object (location,
-                               "notify::location",
-                               G_CALLBACK (on_gclue_location_changed_cb),
-                               self,
-                               0);
+      g_signal_connect (location,
+                        "notify::location",
+                        G_CALLBACK (on_gclue_location_changed_cb),
+                        self);
     }
 
-  g_signal_connect_object (client,
-                           "notify::active",
-                           G_CALLBACK (on_gclue_client_activity_changed_cb),
-                           self,
-                           0);
+  g_signal_connect (client,
+                    "notify::active",
+                    G_CALLBACK (on_gclue_client_activity_changed_cb),
+                    self);
 
-  g_object_unref (self);
+  GCAL_EXIT;
 }
 
-/* on_gclue_client_stop:
- * @source_object: A #GClueClient.
- * @res:           Result of gclue_client_call_stop().
- * @simple:        (transfer full): A #GClueSimple.
- *
- * Helper-callback used in gcal_weather_service_stop().
- */
 static void
 on_gclue_client_stop (GClueClient  *client,
                       GAsyncResult *res,
@@ -789,11 +781,6 @@ on_gweather_update_cb (GWeatherInfo       *info,
   update_weather (self, info, TRUE);
 }
 
-/* on_duration_timer_timeout
- * @self: A #GcalWeatherService.
- *
- * Handles scheduled weather report updates.
- */
 static void
 on_duration_timer_timeout (GcalTimer          *timer,
                            GcalWeatherService *self)
@@ -802,11 +789,6 @@ on_duration_timer_timeout (GcalTimer          *timer,
     gweather_info_update (self->gweather_info);
 }
 
-/* on_midnight_timer_timeout
- * @self: A #GcalWeatherService.
- *
- * Handles scheduled weather report updates.
- */
 static void
 on_midnight_timer_timeout (GcalTimer          *timer,
                            GcalWeatherService *self)
@@ -1391,12 +1373,14 @@ gcal_weather_service_run (GcalWeatherService *self,
 void
 gcal_weather_service_stop (GcalWeatherService *self)
 {
+  GCAL_ENTRY;
+
   g_return_if_fail (GCAL_IS_WEATHER_SERVICE (self));
 
   g_debug ("Stop weather service");
 
   if (!self->location_service_running && !self->weather_service_running)
-    return ;
+    GCAL_RETURN ();
 
   self->location_service_running = FALSE;
   self->weather_service_running = FALSE;
@@ -1412,8 +1396,10 @@ gcal_weather_service_stop (GcalWeatherService *self)
   else
     {
       gclue_client_call_stop (gclue_simple_get_client (self->location_service),
-                              NULL,
+                              self->location_cancellable,
                               (GAsyncReadyCallback) on_gclue_client_stop,
                               g_steal_pointer (&self->location_service));
     }
+
+  GCAL_EXIT;
 }
diff --git a/src/gcal-window.c b/src/gcal-window.c
index 5fb6e9ad..f272369b 100644
--- a/src/gcal-window.c
+++ b/src/gcal-window.c
@@ -96,21 +96,6 @@ typedef struct
   gchar              *uuid;
 } OpenEditDialogData;
 
-/* WeatherSigs:
- * @instance: (transfer none) Instance this signal is connected to.
- * @sig_id: Signal uid
- *
- * Describes a signal used in weather-menu that triggers
- * weather service or weather menu changes.
- *
- * Used to block signals when loading settings.
- */
-typedef struct
-{
-  GObject            *obj; /* unowned */
-  gulong              id;
-} WeatherSigs;
-
 struct _GcalWindow
 {
   GtkApplicationWindow parent;
@@ -142,6 +127,7 @@ struct _GcalWindow
   GtkWidget          *today_button;
   GtkWidget          *forward_button;
   GtkWidget          *views_switcher;
+  GtkWidget          *win_menu_stack;
 
   /* new event popover widgets */
   GtkWidget          *quick_add_popover;
@@ -177,12 +163,11 @@ struct _GcalWindow
   gint                open_edit_dialog_timeout_id;
 
   /* weather management */
-  GcalWeatherService *weather_service;   /* owned */
-  GtkSwitch          *weather;           /* unowned */
-  GtkSwitch          *auto_location;     /* unowned */
-  GtkBox             *auto_location_box; /* unowned */
-  GWeatherLocationEntry *location_entry;    /* unowned */
-  WeatherSigs         weather_cb_ids[5];
+  GcalWeatherService *weather_service;
+  GtkSwitch          *show_weather_switch;
+  GtkSwitch          *weather_auto_location_switch;
+  GtkBox             *weather_auto_location_box;
+  GtkWidget          *weather_location_entry;
 
   /* temp to keep event_creation */
   gboolean            open_edit_dialog;
@@ -226,53 +211,25 @@ static void          on_view_action_activated                    (GSimpleAction
                                                                   GVariant           *param,
                                                                   gpointer            user_data);
 
-static void          on_menu_button_clicked                      (GtkMenuButton      *menu,
-                                                                  GtkStack           *stack);
-
 static void          on_toggle_search_bar_activated              (GSimpleAction      *action,
                                                                   GVariant           *param,
                                                                   gpointer            user_data);
 
-static void          on_view_menu_open_sub                       (GtkModelButton     *button,
-                                                                  GtkStack           *stack);
-
-static void          on_view_menu_open_parent                    (GtkModelButton     *button,
-                                                                  GtkStack           *stack);
-
-static void          on_weather_location_searchbox_change        (GWeatherLocationEntry *entry,
+static void          on_weather_location_searchbox_changed_cb    (GWeatherLocationEntry *entry,
                                                                   GcalWindow            *self);
 
-static void          on_show_weather_change                      (GtkSwitch          *wswitch,
+static void          on_show_weather_changed_cb                  (GtkSwitch          *wswitch,
                                                                   GParamSpec         *pspec,
                                                                   GcalWindow         *self);
 
-static void          on_auto_location_change                     (GtkSwitch          *lswitch,
+static void          on_weather_auto_location_changed_cb         (GtkSwitch          *lswitch,
                                                                   GParamSpec         *pspec,
                                                                   GcalWindow         *self);
 
-static gboolean      on_weather_location_searchbox_match_selected (GtkEntryCompletion *sender,
-                                                                   GtkTreeModel       *model,
-                                                                   GtkTreeIter        *iter,
-                                                                   GcalWindow         *self);
-
-static void          set_model_button_animation                  (GtkBuilder         *builder,
-                                                                  GtkStack           *stack,
-                                                                  const char         *id,
-                                                                  gboolean            go_back);
-
 static void          update_menu_weather_sensitivity             (GcalWindow         *self);
 
-
-static void          close_menu                                  (GcalWindow         *self);
-
-static void          safe_weather_settings                       (GcalWindow         *self);
-
 static void          load_weather_settings                       (GcalWindow         *self);
 
-static void          manage_weather_service                      (GcalWindow         *self);
-
-static GWeatherLocation* get_checked_fixed_location              (GcalWindow         *self);
-
 G_DEFINE_TYPE (GcalWindow, gcal_window, GTK_TYPE_APPLICATION_WINDOW)
 
 static const GActionEntry actions[] = {
@@ -292,10 +249,10 @@ hide_search_view_on_click_outside (GcalWindow     *window,
 {
   GdkWindow *search_view_window;
 
-  search_view_window = gtk_widget_get_window (GTK_WIDGET (popover)); 
+  search_view_window = gtk_widget_get_window (GTK_WIDGET (popover));
 
   /* If the event is not produced in the search view widget, we hide the search_bar */
-  if (event->window != search_view_window) 
+  if (event->window != search_view_window)
     {
       gtk_popover_popdown (popover);
       gtk_search_bar_set_search_mode (GTK_SEARCH_BAR (window->search_bar), FALSE);
@@ -304,6 +261,138 @@ hide_search_view_on_click_outside (GcalWindow     *window,
   return GDK_EVENT_PROPAGATE;
 }
 
+static GWeatherLocation*
+get_checked_fixed_location (GcalWindow *self)
+{
+  g_autoptr (GWeatherLocation) location;
+
+  location = gweather_location_entry_get_location (GWEATHER_LOCATION_ENTRY (self->weather_location_entry));
+
+  /*
+   * NOTE: This check feels shabby. However, I couldn't find a better
+   * one without iterating the model. has-custom-text does not work
+   * properly. Lets go with it for now.
+   */
+  if (location && gweather_location_get_name (location))
+    return g_steal_pointer (&location);
+
+  return NULL;
+}
+
+static void
+load_weather_settings (GcalWindow *self)
+{
+  g_autoptr (GVariant) location = NULL;
+  g_autoptr (GVariant) value = NULL;
+  g_autofree gchar *location_name = NULL;
+  GSettings *settings;
+  gboolean show_weather;
+  gboolean auto_location;
+
+  settings = gcal_manager_get_settings (self->manager);
+  value = g_settings_get_value (settings, "weather-settings");
+
+  g_variant_get (value, "(bbsmv)",
+                 &show_weather,
+                 &auto_location,
+                 &location_name,
+                 &location);
+
+  g_signal_handlers_block_by_func (self->show_weather_switch, on_show_weather_changed_cb, self);
+  g_signal_handlers_block_by_func (self->weather_auto_location_switch, on_weather_auto_location_changed_cb, 
self);
+  g_signal_handlers_block_by_func (self->weather_location_entry, on_weather_location_searchbox_changed_cb, 
self);
+
+  gtk_switch_set_active (self->show_weather_switch, show_weather);
+  gtk_switch_set_active (self->weather_auto_location_switch, auto_location);
+
+  if (!location && !auto_location)
+    {
+      GtkStyleContext *context;
+
+      context = gtk_widget_get_style_context (GTK_WIDGET (self->weather_location_entry));
+      gtk_entry_set_text (GTK_ENTRY (self->weather_location_entry), location_name);
+      gtk_style_context_add_class (context, "error");
+    }
+  else
+    {
+      g_autoptr (GWeatherLocation) weather_location;
+      GWeatherLocation *world;
+
+      world = gweather_location_get_world ();
+      weather_location = gweather_location_deserialize (world, location);
+
+      gweather_location_entry_set_location (GWEATHER_LOCATION_ENTRY (self->weather_location_entry), 
weather_location);
+    }
+
+  g_signal_handlers_unblock_by_func (self->show_weather_switch, on_show_weather_changed_cb, self);
+  g_signal_handlers_unblock_by_func (self->weather_auto_location_switch, 
on_weather_auto_location_changed_cb, self);
+  g_signal_handlers_unblock_by_func (self->weather_location_entry, on_weather_location_searchbox_changed_cb, 
self);
+}
+
+static void
+manage_weather_service (GcalWindow *self)
+{
+  g_autoptr (GWeatherLocation) location = NULL;
+
+  gcal_weather_service_stop (self->weather_service);
+
+  if (!gtk_switch_get_active (self->show_weather_switch))
+    return;
+
+  if (gtk_switch_get_active (self->weather_auto_location_switch))
+    {
+      gcal_weather_service_run (self->weather_service, NULL);
+      return;
+    }
+
+  location = get_checked_fixed_location (self);
+  if (!location)
+    {
+      /* TODO: this one should get reported to users */
+      g_warning ("Unknown location '%s' selected", gtk_entry_get_text (GTK_ENTRY 
(self->weather_location_entry)));
+      return;
+    }
+
+  gcal_weather_service_run (self->weather_service, location);
+}
+
+static void
+save_weather_settings (GcalWindow *self)
+{
+  g_autoptr (GWeatherLocation) location;
+  GSettings *settings;
+  GVariant *value;
+  GVariant *vlocation;
+  gboolean res;
+
+  location = gweather_location_entry_get_location (GWEATHER_LOCATION_ENTRY (self->weather_location_entry));
+  vlocation = location ? gweather_location_serialize (location) : NULL;
+
+  settings = gcal_manager_get_settings (self->manager);
+  value = g_variant_new ("(bbsmv)",
+                         gtk_switch_get_active (self->show_weather_switch),
+                         gtk_switch_get_active (self->weather_auto_location_switch),
+                         gtk_entry_get_text (GTK_ENTRY (self->weather_location_entry)),
+                         vlocation);
+
+  res = g_settings_set_value (settings, "weather-settings", value);
+
+  if (!res)
+    g_warning ("Could not persist weather settings");
+}
+
+static void
+update_menu_weather_sensitivity (GcalWindow *self)
+{
+  gboolean weather_enabled;
+  gboolean autoloc_enabled;
+
+  weather_enabled = gtk_switch_get_active (self->show_weather_switch);
+  autoloc_enabled = gtk_switch_get_active (self->weather_auto_location_switch);
+
+  gtk_widget_set_sensitive (GTK_WIDGET (self->weather_auto_location_switch), weather_enabled);
+  gtk_widget_set_sensitive (GTK_WIDGET (self->weather_location_entry), weather_enabled && !autoloc_enabled);
+}
 
 static void
 update_today_button_sensitive (GcalWindow *window)
@@ -1020,6 +1109,70 @@ window_state_changed (GtkWidget *widget,
 }
 
 static void
+on_show_weather_changed_cb (GtkSwitch  *wswitch,
+                            GParamSpec *pspec,
+                            GcalWindow *self)
+{
+  save_weather_settings (self);
+
+  if (!gtk_switch_get_active (wswitch))
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (self->menu_button), FALSE);
+
+  update_menu_weather_sensitivity (self);
+  manage_weather_service (self);
+}
+
+static void
+on_popover_menu_visible_cb (GtkWidget  *widget,
+                            GParamSpec *pspec,
+                            GcalWindow *self)
+{
+  gtk_stack_set_visible_child_name (GTK_STACK (self->win_menu_stack), "main-menu");
+}
+
+static void
+on_weather_auto_location_changed_cb (GtkSwitch  *lswitch,
+                                     GParamSpec *pspec,
+                                     GcalWindow *self)
+{
+  save_weather_settings (self);
+
+  if (gtk_switch_get_active (lswitch))
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (self->menu_button), FALSE);
+
+  update_menu_weather_sensitivity (self);
+  manage_weather_service (self);
+}
+
+static void
+on_weather_location_searchbox_changed_cb (GWeatherLocationEntry *entry,
+                                          GcalWindow            *self)
+{
+  GtkStyleContext  *context;
+  GWeatherLocation *location;
+  gboolean auto_location;
+
+  save_weather_settings (self);
+
+  context = gtk_widget_get_style_context (self->weather_location_entry);
+  auto_location = gtk_switch_get_active (self->weather_auto_location_switch);
+  location = get_checked_fixed_location (self);
+
+  if (!location && !auto_location)
+    {
+      gtk_style_context_add_class (context, "error");
+    }
+  else
+    {
+      gtk_style_context_remove_class (context, "error");
+
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (self->menu_button), FALSE);
+      manage_weather_service (self);
+      gweather_location_unref (location);
+    }
+}
+
+static void
 edit_event (GcalQuickAddPopover *popover,
             GcalEvent           *event,
             GcalWindow          *window)
@@ -1512,28 +1665,33 @@ gcal_window_class_init (GcalWindowClass *klass)
   gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/calendar/window.ui");
 
   /* widgets */
+  gtk_widget_class_bind_template_child (widget_class, GcalWindow, back_button);
+  gtk_widget_class_bind_template_child (widget_class, GcalWindow, calendars_button);
+  gtk_widget_class_bind_template_child (widget_class, GcalWindow, calendar_listbox);
+  gtk_widget_class_bind_template_child (widget_class, GcalWindow, calendar_popover);
   gtk_widget_class_bind_template_child (widget_class, GcalWindow, edit_dialog);
+  gtk_widget_class_bind_template_child (widget_class, GcalWindow, forward_button);
   gtk_widget_class_bind_template_child (widget_class, GcalWindow, header_bar);
   gtk_widget_class_bind_template_child (widget_class, GcalWindow, main_box);
   gtk_widget_class_bind_template_child (widget_class, GcalWindow, menu_button);
+  gtk_widget_class_bind_template_child (widget_class, GcalWindow, month_view);
+  gtk_widget_class_bind_template_child (widget_class, GcalWindow, quick_add_popover);
   gtk_widget_class_bind_template_child (widget_class, GcalWindow, search_bar);
   gtk_widget_class_bind_template_child (widget_class, GcalWindow, search_button);
-  gtk_widget_class_bind_template_child (widget_class, GcalWindow, calendars_button);
-  gtk_widget_class_bind_template_child (widget_class, GcalWindow, calendar_listbox);
-  gtk_widget_class_bind_template_child (widget_class, GcalWindow, calendar_popover);
   gtk_widget_class_bind_template_child (widget_class, GcalWindow, source_dialog);
   gtk_widget_class_bind_template_child (widget_class, GcalWindow, search_entry);
-  gtk_widget_class_bind_template_child (widget_class, GcalWindow, back_button);
+  gtk_widget_class_bind_template_child (widget_class, GcalWindow, search_view);
+  gtk_widget_class_bind_template_child (widget_class, GcalWindow, show_weather_switch);
   gtk_widget_class_bind_template_child (widget_class, GcalWindow, today_button);
-  gtk_widget_class_bind_template_child (widget_class, GcalWindow, forward_button);
   gtk_widget_class_bind_template_child (widget_class, GcalWindow, views_overlay);
   gtk_widget_class_bind_template_child (widget_class, GcalWindow, views_stack);
+  gtk_widget_class_bind_template_child (widget_class, GcalWindow, views_switcher);
+  gtk_widget_class_bind_template_child (widget_class, GcalWindow, weather_auto_location_box);
+  gtk_widget_class_bind_template_child (widget_class, GcalWindow, weather_auto_location_switch);
+  gtk_widget_class_bind_template_child (widget_class, GcalWindow, weather_location_entry);
+  gtk_widget_class_bind_template_child (widget_class, GcalWindow, win_menu_stack);
   gtk_widget_class_bind_template_child (widget_class, GcalWindow, week_view);
-  gtk_widget_class_bind_template_child (widget_class, GcalWindow, month_view);
   gtk_widget_class_bind_template_child (widget_class, GcalWindow, year_view);
-  gtk_widget_class_bind_template_child (widget_class, GcalWindow, views_switcher);
-  gtk_widget_class_bind_template_child (widget_class, GcalWindow, quick_add_popover);
-  gtk_widget_class_bind_template_child (widget_class, GcalWindow, search_view);
 
   gtk_widget_class_bind_template_child (widget_class, GcalWindow, notification);
   gtk_widget_class_bind_template_child (widget_class, GcalWindow, notification_label);
@@ -1548,6 +1706,11 @@ gcal_window_class_init (GcalWindowClass *klass)
   gtk_widget_class_bind_template_callback (widget_class, view_changed);
   gtk_widget_class_bind_template_callback (widget_class, date_updated);
 
+  gtk_widget_class_bind_template_callback (widget_class, on_popover_menu_visible_cb);
+  gtk_widget_class_bind_template_callback (widget_class, on_show_weather_changed_cb);
+  gtk_widget_class_bind_template_callback (widget_class, on_weather_auto_location_changed_cb);
+  gtk_widget_class_bind_template_callback (widget_class, on_weather_location_searchbox_changed_cb);
+
   /* Event removal related */
   gtk_widget_class_bind_template_callback (widget_class, hide_notification);
   gtk_widget_class_bind_template_callback (widget_class, remove_event);
@@ -1574,10 +1737,6 @@ static void
 gcal_window_init (GcalWindow *self)
 {
   GApplication *app;
-  GtkBuilder *builder;
-  GtkPopoverMenu *winmenu; /* unowned */
-  GtkStack *winmenustack;  /* unowned */
-  GtkEntryCompletion *location_completion; /* unowned */
   GSettings *helper_settings;
   gchar *clock_format;
   gboolean use_24h_format;
@@ -1600,42 +1759,6 @@ gcal_window_init (GcalWindow *self)
   g_free (clock_format);
   g_object_unref (helper_settings);
 
-  /* header_bar: menu */
-  builder = gtk_builder_new ();
-  gtk_builder_add_from_resource (builder,
-                                 "/org/gnome/calendar/gtk/menus.ui",
-                                 NULL);
-
-  winmenu = (GtkPopoverMenu *)gtk_builder_get_object (builder, "win-menu");
-  gtk_menu_button_set_popover (GTK_MENU_BUTTON (self->menu_button),
-                               GTK_WIDGET (winmenu));
-  /* Set-up menu animations: */
-  winmenustack = GTK_STACK (gtk_builder_get_object (builder, "win-menu-stack"));
-  g_signal_connect (GTK_BUTTON (self->menu_button), "clicked", (GCallback) on_menu_button_clicked, 
winmenustack);
-  set_model_button_animation (builder, winmenustack, "win-menu-open-weather", TRUE);
-  set_model_button_animation (builder, winmenustack, "win-menu-close-weather", FALSE);
-
-  /* Weather menu: */
-  self->weather_service = NULL;
-  self->weather = GTK_SWITCH(gtk_builder_get_object (builder, "show-weather-switch"));
-  self->auto_location_box = GTK_BOX (gtk_builder_get_object (builder, "auto-location-box"));
-  self->auto_location = GTK_SWITCH(gtk_builder_get_object (builder, "auto-location-switch"));
-  self->location_entry = GWEATHER_LOCATION_ENTRY (gtk_builder_get_object (builder, 
"fixed-weather-location"));
-  location_completion = gtk_entry_get_completion (GTK_ENTRY (self->location_entry));
-  /* Store signals that need to be blocked when loading weather information */
-  self->weather_cb_ids[0].id = g_signal_connect (self->location_entry, "changed", (GCallback) 
on_weather_location_searchbox_change, self);
-  self->weather_cb_ids[0].obj = G_OBJECT (self->location_entry);
-  self->weather_cb_ids[1].id = g_signal_connect (self->location_entry, "activate", (GCallback) 
on_weather_location_searchbox_change, self);
-  self->weather_cb_ids[1].obj = G_OBJECT (self->location_entry);
-  self->weather_cb_ids[2].id = g_signal_connect (location_completion, "match-selected", (GCallback) 
on_weather_location_searchbox_match_selected, self);
-  self->weather_cb_ids[2].obj = G_OBJECT (location_completion);
-  self->weather_cb_ids[3].id = g_signal_connect (self->weather, "notify::active", (GCallback) 
on_show_weather_change, self);
-  self->weather_cb_ids[3].obj = G_OBJECT (self->weather);
-  self->weather_cb_ids[4].id = g_signal_connect (self->auto_location, "notify::active", (GCallback) 
on_auto_location_change, self);
-  self->weather_cb_ids[4].obj = G_OBJECT (self->auto_location);
-
-  g_object_unref (builder);
-
   self->views[GCAL_WINDOW_VIEW_WEEK] = self->week_view;
   self->views[GCAL_WINDOW_VIEW_MONTH] = self->month_view;
   self->views[GCAL_WINDOW_VIEW_YEAR] = self->year_view;
@@ -1691,406 +1814,6 @@ gcal_window_init (GcalWindow *self)
   gcal_window_add_accelerator (app, "win.toggle-search-bar", "<Ctrl>f");
 }
 
-
-/* set_model_button_animation:
- * @builder: Builder including menu buttons
- * @id: name of the menu button to modify
- * @go_back: Whether this button jumps back to a parent menu
- *
- * Used to set right stack animations for hand-written menus.
- */
-static void
-set_model_button_animation (GtkBuilder *builder,
-                            GtkStack   *stack,
-                            const char *button_id,
-                            gboolean    go_back)
-{
-  g_return_if_fail (GTK_IS_BUILDER (builder));
-  g_return_if_fail (GTK_IS_STACK (stack));
-  g_return_if_fail (button_id != NULL);
-
-  GtkMenuButton *mbutton; /* unowned */
-
-  mbutton = GTK_MENU_BUTTON (gtk_builder_get_object (builder, button_id));
-  g_return_if_fail (mbutton != NULL);
-
-  if (go_back)
-    g_signal_connect (mbutton, "clicked", (GCallback) on_view_menu_open_parent, stack);
-  else
-    g_signal_connect (mbutton, "clicked", (GCallback) on_view_menu_open_sub, stack);
-}
-
-/* on_menu_button_clicked:
- * @menu: primary menu button
- * @stack: main menu popover stack
- *
- * Resets menu stack state before opening menu-popovers.
- */
-static void
-on_menu_button_clicked (GtkMenuButton *menu,
-                        GtkStack      *stack)
-{
-  g_return_if_fail (GTK_IS_MENU_BUTTON (menu));
-  g_return_if_fail (GTK_IS_STACK (stack));
-
-  gtk_stack_set_visible_child_name (stack, "win-menu-main");
-  gtk_stack_set_transition_type (stack, GTK_STACK_TRANSITION_TYPE_SLIDE_LEFT);
-}
-
-/* on_view_menu_open_sub:
- * @button: clicked menu entry
- * @stack: main menu popover stack
- *
- * Callback used to set right stack animations for sub-menus.
- */
-static void
-on_view_menu_open_sub (GtkModelButton *button,
-                       GtkStack       *stack)
-{
-  g_return_if_fail (GTK_IS_MODEL_BUTTON (button));
-  g_return_if_fail (GTK_IS_STACK (stack));
-
-  gtk_stack_set_transition_type (stack, GTK_STACK_TRANSITION_TYPE_SLIDE_LEFT);
-}
-
-/* on_view_menu_open_sub:
- * @button: clicked menu entry
- * @stack: Main menu popover stack
- *
- * Callback used to select right stack animation when jumping back to a parent menu.
- */
-static void
-on_view_menu_open_parent (GtkModelButton *button,
-                          GtkStack       *stack)
-{
-  g_return_if_fail (GTK_IS_MODEL_BUTTON (button));
-  g_return_if_fail (GTK_IS_STACK (stack));
-
-  gtk_stack_set_transition_type (stack, GTK_STACK_TRANSITION_TYPE_SLIDE_RIGHT);
-}
-
-/* on_show_weather_change:
- * @lswitch: The "show-weather" switch owned by @self
- * @pspec: spec of changed property.
- * @self: The #GcalWindow
- *
- * Handles show-weather on/off switch changes.
- */
-static void
-on_show_weather_change (GtkSwitch  *wswitch,
-                        GParamSpec *pspec,
-                        GcalWindow *self)
-{
-  g_return_if_fail (GTK_IS_SWITCH (wswitch));
-  g_return_if_fail (pspec != NULL);
-  g_return_if_fail (GCAL_IS_WINDOW (self));
-
-  safe_weather_settings (self);
-
-  if (!gtk_switch_get_active (wswitch))
-    close_menu (self);
-
-  update_menu_weather_sensitivity (self);
-  manage_weather_service (self);
-}
-
-/* on_auto_location_change:
- * @lswitch: The "auto-location" switch owned by @self
- * @pspec: spec of changed property.
- * @self: The #GcalWindow
- *
- * Handles auto-location on/off switch changes.
- */
-static void
-on_auto_location_change (GtkSwitch  *lswitch,
-                         GParamSpec *pspec,
-                         GcalWindow *self)
-{
-  g_return_if_fail (GTK_IS_SWITCH (lswitch));
-  g_return_if_fail (pspec != NULL);
-  g_return_if_fail (GCAL_IS_WINDOW (self));
-
-  safe_weather_settings (self);
-
-  if (gtk_switch_get_active (lswitch))
-    close_menu (self);
-
-  update_menu_weather_sensitivity (self);
-  manage_weather_service (self);
-}
-
-/* on_weather_location_searchbox_change:
- * @entry: the #GweatherLocationEntry owned by @self
- * @self: a #GcalWindow.
- *
- * Handles location search-box changes.
- */
-static void
-on_weather_location_searchbox_change (GWeatherLocationEntry *entry,
-                                      GcalWindow            *self)
-{
-  GtkStyleContext  *context;  /* unowned */
-  GWeatherLocation *location; /* owned */
-
-  g_return_if_fail (GWEATHER_IS_LOCATION_ENTRY (entry));
-  g_return_if_fail (GCAL_IS_WINDOW (self));
-
-  safe_weather_settings (self);
-
-  context = gtk_widget_get_style_context (GTK_WIDGET (self->location_entry));
-  location = get_checked_fixed_location (self);
-  if (location == NULL)
-    {
-      gtk_style_context_add_class (context, "error");
-    }
-  else
-    {
-      gtk_style_context_remove_class (context, "error");
-
-      close_menu (self);
-      manage_weather_service (self);
-      gweather_location_unref (location);
-    }
-}
-
-/* on_weather_location_searchbox_match_selected:
- * @sender: the #GWeatherLocationEntry of @self.
- * @model: underlining location model
- * @iter: current position
- * @self: a #GcalWindow as user data.
- *
- * Wrapper around on_weather_location_searchbox_change().
- *
- * Returns: %FALSE
- */
-static gboolean
-on_weather_location_searchbox_match_selected (GtkEntryCompletion *sender,
-                                              GtkTreeModel       *model,
-                                              GtkTreeIter        *iter,
-                                              GcalWindow         *self)
-{
-  g_return_val_if_fail (GTK_IS_ENTRY_COMPLETION (sender), FALSE);
-  g_return_val_if_fail (GTK_IS_TREE_MODEL (model), FALSE);
-  g_return_val_if_fail (iter != NULL, FALSE);
-  g_return_val_if_fail (GCAL_IS_WINDOW (self), FALSE);
-
-  GWeatherLocationEntry *entry; /* unowned */
-
-  entry = GWEATHER_LOCATION_ENTRY (gtk_entry_completion_get_entry (sender));
-
-  on_weather_location_searchbox_change (entry, self);
-  return FALSE;
-}
-
-/* update_menu_weather_sensitivity:
- * @self: A #GcalWindow
- *
- * Greys-out weather settings based on active settings.
- */
-static void
-update_menu_weather_sensitivity (GcalWindow *self)
-{
-  g_return_if_fail (GCAL_IS_WINDOW (self));
-
-  gboolean weather_enabled;
-  gboolean autoloc_enabled;
-
-  weather_enabled = gtk_switch_get_active (self->weather);
-  autoloc_enabled = gtk_switch_get_active (self->auto_location);
-
-  gtk_widget_set_sensitive (GTK_WIDGET (self->auto_location_box), weather_enabled);
-  gtk_widget_set_sensitive (GTK_WIDGET (self->location_entry), weather_enabled && !autoloc_enabled);
-}
-
-/* close_menu:
- * @self: A #GcalWindow
- *
- * Closes the main menu ("burger") if open.
- */
-static void
-close_menu (GcalWindow *self)
-{
-  g_return_if_fail (GCAL_IS_WINDOW (self));
-
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (self->menu_button), FALSE);
-}
-
-/* safe_weather_settings.
- * @self: A #GcalWindow
- *
- * Stores current weather settings. This
- * includes invalid states.
- */
-static void
-safe_weather_settings (GcalWindow *self)
-{
-  g_return_if_fail (GCAL_IS_WINDOW (self));
-
-  GSettings *settings;        /* unowned */
-  GVariant *value = NULL;     /* floating */
-  GVariant *vlocation = NULL; /* floating */
-  GWeatherLocation *location; /* owned */
-  gboolean res;
-
-  location = gweather_location_entry_get_location (self->location_entry);
-  if (location != NULL)
-    {
-      vlocation = gweather_location_serialize (location);
-      gweather_location_unref (location);
-      location = NULL;
-    }
-
-  settings = gcal_manager_get_settings (self->manager);
-  value = g_variant_new ("(bbsmv)",
-                         gtk_switch_get_active (self->weather),
-                         gtk_switch_get_active (self->auto_location),
-                         gtk_entry_get_text (GTK_ENTRY (self->location_entry)),
-                         vlocation);
-
-  res = g_settings_set_value (settings, "weather-settings", value);
-
-  if (!res)
-    g_warning ("Could not persist weather settings");
-}
-
-/* load_weather_settings:
- * @self: A #GcalWindow.
- *
- * Loads registered user settings.
- *
- * Does not start weather-services on its own.
- */
-static void
-load_weather_settings (GcalWindow *self)
-{
-  g_return_if_fail (GCAL_IS_WINDOW (self));
-
-  GSettings *settings; /* unowned */
-  g_autoptr (GVariant) value = NULL;
-  gboolean show_weather;
-  gboolean auto_location;
-  g_autoptr (GVariant) location = NULL;
-  g_autofree gchar *location_name = NULL;
-
-  settings = gcal_manager_get_settings (self->manager);
-  value = g_settings_get_value (settings, "weather-settings");
-
-  g_variant_get (value,
-                 "(bbsmv)",
-                 &show_weather,
-                 &auto_location,
-                 &location_name,
-                 &location);
-
-
-  for (int i = 0; i < G_N_ELEMENTS (self->weather_cb_ids); i++)
-    {
-      g_assert (self->weather_cb_ids[i].obj != NULL);
-      g_assert (self->weather_cb_ids[i].id > 0);
-
-      g_signal_handler_block (self->weather_cb_ids[i].obj, self->weather_cb_ids[i].id);
-    }
-
-  gtk_switch_set_active (self->weather, show_weather);
-  gtk_switch_set_active (self->auto_location, auto_location);
-  if (location == NULL)
-    {
-      GtkStyleContext *context; /* unowned */
-
-      context = gtk_widget_get_style_context (GTK_WIDGET (self->location_entry));
-      gtk_entry_set_text (GTK_ENTRY (self->location_entry), location_name);
-      gtk_style_context_add_class (context, "error");
-    }
-  else
-    {
-      GWeatherLocation *world; /* unowned */
-      GWeatherLocation *loc;   /* owned */
-
-      world = gweather_location_get_world ();
-      loc = gweather_location_deserialize (world, location);
-      gweather_location_entry_set_location (self->location_entry, loc);
-      gweather_location_unref (loc);
-    }
-
-  for (int i = 0; i < G_N_ELEMENTS (self->weather_cb_ids); i++)
-     g_signal_handler_unblock (self->weather_cb_ids[i].obj, self->weather_cb_ids[i].id);
-}
-
-/* manage_weather_service:
- * @self: A #GcalWindow
- *
- * Starts or stops weather service based on current
- * settings.
- */
-static void
-manage_weather_service (GcalWindow *self)
-{
-  g_return_if_fail (GCAL_IS_WINDOW (self));
-
-  gboolean show_weather;
-  gboolean auto_location;
-  GWeatherLocation* location; /* owned */
-
-  gcal_weather_service_stop (self->weather_service);
-
-  show_weather = gtk_switch_get_active (self->weather);
-  if (!show_weather)
-    return;
-
-  auto_location = gtk_switch_get_active (self->auto_location);
-  if (auto_location)
-    {
-      gcal_weather_service_run (self->weather_service, NULL);
-      return;
-    }
-
-  location = get_checked_fixed_location (self);
-  if (location == NULL)
-    {
-      /* TODO: this one should get reported to users */
-      g_warning ("Unknown location '%s' selected",
-                 gtk_entry_get_text (GTK_ENTRY (self->location_entry)));
-    }
-  else
-    {
-      gcal_weather_service_run (self->weather_service, location);
-      gweather_location_unref (location);
-    }
-}
-
-/* get_checked_fixed_location:
- * @self: A #GcalWindow
- *
- * Returns user defined location or %NULL
- * for invalid entries.
- *
- * Returns: (transfer full) (nullable): A #GweatherLocation.
- */
-static GWeatherLocation*
-get_checked_fixed_location (GcalWindow *self)
-{
-  g_return_val_if_fail (GCAL_IS_WINDOW (self), NULL);
-
-  GWeatherLocation *location; /* owned */
-
-  location = gweather_location_entry_get_location (self->location_entry);
-
-  /* NOTE: This check feels shabby. However,
-   * I couldn't find a better one without iterating
-   * the model. has-custom-text does not work properly.
-   * Lets go with it for now.
-   */
-  if (location != NULL && gweather_location_get_name (location) != NULL)
-    return location;
-
-  if (location != NULL)
-    gweather_location_unref (location);
-
-  return NULL;
-}
-
-
-/* Public API */
 /**
  * gcal_window_new_with_date:
  * @app: a #GcalApplication
@@ -2104,9 +1827,9 @@ GtkWidget*
 gcal_window_new_with_date (GcalApplication *app,
                            icaltimetype    *date)
 {
-  GcalWeatherService *weather_service; /* unowned */
-  GcalManager *manager; /* unowned */
-  GcalWindow *win;      /* owned */
+  GcalWeatherService *weather_service;
+  GcalManager *manager;
+  GcalWindow *win;
 
   weather_service = gcal_application_get_weather_service (GCAL_APPLICATION (app));
   manager = gcal_application_get_manager (GCAL_APPLICATION (app));
@@ -2152,10 +1875,12 @@ gcal_window_new_event (GcalWindow *self)
     case GCAL_WINDOW_VIEW_WEEK:
       end_date = g_date_time_add_hours (start_date, 1);
       break;
+
     case GCAL_WINDOW_VIEW_MONTH:
     case GCAL_WINDOW_VIEW_YEAR:
       end_date = g_date_time_add_days (start_date, 1);
       break;
+
     case GCAL_WINDOW_VIEW_LIST:
     case GCAL_WINDOW_VIEW_SEARCH:
     default:


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