weather: Integrate weather into our main windows.
This commit is contained in:
committed by
Georges Basile Stavracas Neto
parent
950a2cda8f
commit
1f3173823b
@@ -21,5 +21,10 @@
|
||||
<summary>Type of the active view</summary>
|
||||
<description>Type of the active window view, default value is: monthly view</description>
|
||||
</key>
|
||||
<key name="weather-settings" type="(bbsmv)">
|
||||
<default>(true, true, '', nothing)</default>
|
||||
<summary>Weather Service Configuration</summary>
|
||||
<description>Whether weather reports are shown, automatic locations are used and a location-name</description>
|
||||
</key>
|
||||
</schema>
|
||||
</schemalist>
|
||||
|
||||
+152
-13
@@ -30,19 +30,158 @@
|
||||
</item>
|
||||
</section>
|
||||
</menu>
|
||||
<menu id="win-menu">
|
||||
<section>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">Add Eve_nt…</attribute>
|
||||
<attribute name="action">app.new</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">_Synchronize</attribute>
|
||||
<attribute name="action">app.sync</attribute>
|
||||
<attribute name="accel">F5</attribute>
|
||||
</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">
|
||||
<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>
|
||||
|
||||
+523
-8
@@ -33,9 +33,10 @@
|
||||
#include "gcal-week-view.h"
|
||||
#include "gcal-window.h"
|
||||
#include "gcal-year-view.h"
|
||||
#include "gcal-weather-service.h"
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
#include <libgweather/gweather.h>
|
||||
#include <libecal/libecal.h>
|
||||
#include <libical/icaltime.h>
|
||||
|
||||
@@ -95,6 +96,21 @@ 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;
|
||||
@@ -160,6 +176,13 @@ struct _GcalWindow
|
||||
gint refresh_timeout_id;
|
||||
gint open_edit_dialog_timeout_id;
|
||||
|
||||
/* weather management */
|
||||
GcalWeatherService *weather_service; /* owned */
|
||||
GtkSwitch *weather; /* unowned */
|
||||
GtkSwitch *auto_location; /* unowned */
|
||||
GWeatherLocationEntry *location_entry; /* unowned */
|
||||
WeatherSigs weather_cb_ids[5];
|
||||
|
||||
/* temp to keep event_creation */
|
||||
gboolean open_edit_dialog;
|
||||
|
||||
@@ -179,6 +202,7 @@ enum
|
||||
PROP_0,
|
||||
PROP_ACTIVE_VIEW,
|
||||
PROP_MANAGER,
|
||||
PROP_WEATHER_SERVICE,
|
||||
PROP_ACTIVE_DATE,
|
||||
PROP_NEW_EVENT_MODE
|
||||
};
|
||||
@@ -205,6 +229,49 @@ static void on_toggle_search_bar_activated (GSimpleAction *a
|
||||
GVariant *param,
|
||||
gpointer user_data);
|
||||
|
||||
static void on_menu_button_clicked (GtkMenuButton *menu,
|
||||
GtkStack *stack);
|
||||
|
||||
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,
|
||||
GcalWindow *self);
|
||||
|
||||
static void on_show_weather_change (GtkSwitch *wswitch,
|
||||
GParamSpec *pspec,
|
||||
GcalWindow *self);
|
||||
|
||||
static void on_auto_location_change (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[] = {
|
||||
@@ -1234,9 +1301,11 @@ gcal_window_finalize (GObject *object)
|
||||
g_clear_object (&window->views_switcher);
|
||||
|
||||
g_clear_pointer (&window->active_date, g_free);
|
||||
|
||||
G_OBJECT_CLASS (gcal_window_parent_class)->finalize (object);
|
||||
|
||||
gcal_weather_service_stop (window->weather_service);
|
||||
g_clear_object (&window->weather_service);
|
||||
|
||||
GCAL_EXIT;
|
||||
}
|
||||
|
||||
@@ -1299,6 +1368,19 @@ gcal_window_set_property (GObject *object,
|
||||
}
|
||||
return;
|
||||
|
||||
case PROP_WEATHER_SERVICE:
|
||||
{
|
||||
GcalWeatherService *service; /* unowned */
|
||||
|
||||
service = GCAL_WEATHER_SERVICE (g_value_get_object (value));
|
||||
g_return_if_fail (service != NULL);
|
||||
|
||||
g_return_if_fail (self->weather_service == NULL);
|
||||
self->weather_service = (GcalWeatherService*) g_object_ref (service);
|
||||
g_object_notify (object, "weather-service");
|
||||
return ;
|
||||
}
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
}
|
||||
@@ -1324,6 +1406,10 @@ gcal_window_get_property (GObject *object,
|
||||
g_value_set_object (value, self->manager);
|
||||
return;
|
||||
|
||||
case PROP_WEATHER_SERVICE:
|
||||
g_value_set_object (value, self->weather_service);
|
||||
return;
|
||||
|
||||
case PROP_ACTIVE_DATE:
|
||||
g_value_set_boxed (value, self->active_date);
|
||||
return;
|
||||
@@ -1395,6 +1481,15 @@ gcal_window_class_init (GcalWindowClass *klass)
|
||||
GCAL_TYPE_MANAGER,
|
||||
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
|
||||
|
||||
g_object_class_install_property (
|
||||
object_class,
|
||||
PROP_WEATHER_SERVICE,
|
||||
g_param_spec_object ("weather-service",
|
||||
"The weather service object",
|
||||
"The weather service object",
|
||||
GCAL_TYPE_WEATHER_SERVICE,
|
||||
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
|
||||
|
||||
g_object_class_install_property (
|
||||
object_class,
|
||||
PROP_ACTIVE_DATE,
|
||||
@@ -1479,7 +1574,9 @@ gcal_window_init (GcalWindow *self)
|
||||
{
|
||||
GApplication *app;
|
||||
GtkBuilder *builder;
|
||||
GMenuModel *winmenu;
|
||||
GtkPopoverMenu *winmenu; /* unowned */
|
||||
GtkStack *winmenustack; /* unowned */
|
||||
GtkEntryCompletion *location_completion; /* unowned */
|
||||
GSettings *helper_settings;
|
||||
gchar *clock_format;
|
||||
gboolean use_24h_format;
|
||||
@@ -1508,9 +1605,32 @@ gcal_window_init (GcalWindow *self)
|
||||
"/org/gnome/calendar/gtk/menus.ui",
|
||||
NULL);
|
||||
|
||||
winmenu = (GMenuModel *)gtk_builder_get_object (builder, "win-menu");
|
||||
gtk_menu_button_set_menu_model (GTK_MENU_BUTTON (self->menu_button),
|
||||
winmenu);
|
||||
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 = 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);
|
||||
|
||||
@@ -1548,6 +1668,7 @@ gcal_window_init (GcalWindow *self)
|
||||
* FIXME: this is a hack around the issue that happens when trying to bind
|
||||
* there properties using the GtkBuilder .ui file.
|
||||
*/
|
||||
g_object_bind_property (self, "weather-service", self->week_view, "weather-service", G_BINDING_DEFAULT);
|
||||
g_object_bind_property (self, "manager", self->edit_dialog, "manager", G_BINDING_DEFAULT);
|
||||
g_object_bind_property (self, "manager", self->source_dialog, "manager", G_BINDING_DEFAULT);
|
||||
g_object_bind_property (self, "manager", self->week_view, "manager", G_BINDING_DEFAULT);
|
||||
@@ -1566,6 +1687,392 @@ 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)
|
||||
{
|
||||
GWeatherLocation *location; /* owned */
|
||||
|
||||
g_return_if_fail (GWEATHER_IS_LOCATION_ENTRY (entry));
|
||||
g_return_if_fail (GCAL_IS_WINDOW (self));
|
||||
|
||||
safe_weather_settings (self);
|
||||
|
||||
location = get_checked_fixed_location (self);
|
||||
if (location != NULL)
|
||||
{
|
||||
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), 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)
|
||||
{
|
||||
gtk_entry_set_text (GTK_ENTRY (self->location_entry), location_name);
|
||||
}
|
||||
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:
|
||||
@@ -1580,12 +2087,15 @@ GtkWidget*
|
||||
gcal_window_new_with_date (GcalApplication *app,
|
||||
icaltimetype *date)
|
||||
{
|
||||
GcalManager *manager;
|
||||
GcalWindow *win;
|
||||
GcalWeatherService *weather_service; /* unowned */
|
||||
GcalManager *manager; /* unowned */
|
||||
GcalWindow *win; /* owned */
|
||||
|
||||
weather_service = gcal_application_get_weather_service (GCAL_APPLICATION (app));
|
||||
manager = gcal_application_get_manager (GCAL_APPLICATION (app));
|
||||
win = g_object_new (GCAL_TYPE_WINDOW,
|
||||
"application", GTK_APPLICATION (app),
|
||||
"weather-service", weather_service,
|
||||
"manager", manager,
|
||||
"active-date", date,
|
||||
NULL);
|
||||
@@ -1593,6 +2103,11 @@ gcal_window_new_with_date (GcalApplication *app,
|
||||
/* loading size */
|
||||
load_geometry (win);
|
||||
|
||||
/* Recover weather settings */
|
||||
load_weather_settings (win);
|
||||
update_menu_weather_sensitivity (win);
|
||||
manage_weather_service (win);
|
||||
|
||||
return GTK_WIDGET (win);
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "gcal-week-header.h"
|
||||
#include "gcal-week-grid.h"
|
||||
#include "gcal-week-view.h"
|
||||
#include "gcal-weather-service.h"
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
@@ -61,8 +62,9 @@ struct _GcalWeekView
|
||||
gboolean use_24h_format;
|
||||
|
||||
/* property */
|
||||
icaltimetype *date;
|
||||
GcalManager *manager; /* owned */
|
||||
icaltimetype *date;
|
||||
GcalManager *manager; /* owned */
|
||||
GcalWeatherService *weather_service; /* owned */
|
||||
|
||||
guint scroll_grid_timeout_id;
|
||||
|
||||
@@ -86,6 +88,7 @@ enum
|
||||
PROP_0,
|
||||
PROP_DATE,
|
||||
PROP_MANAGER,
|
||||
PROP_WEATHER_SERVICE,
|
||||
NUM_PROPS
|
||||
};
|
||||
|
||||
@@ -522,6 +525,9 @@ gcal_week_view_finalize (GObject *object)
|
||||
|
||||
g_clear_object (&self->manager);
|
||||
|
||||
if (self->weather_service != NULL)
|
||||
g_clear_object (&self->weather_service);
|
||||
|
||||
/* Chain up to parent's finalize() method. */
|
||||
G_OBJECT_CLASS (gcal_week_view_parent_class)->finalize (object);
|
||||
}
|
||||
@@ -545,10 +551,28 @@ gcal_week_view_set_property (GObject *object,
|
||||
|
||||
gcal_week_grid_set_manager (GCAL_WEEK_GRID (self->week_grid), self->manager);
|
||||
gcal_week_header_set_manager (GCAL_WEEK_HEADER (self->header), self->manager);
|
||||
|
||||
g_object_notify (object, "manager");
|
||||
break;
|
||||
|
||||
case PROP_WEATHER_SERVICE:
|
||||
{
|
||||
GcalWeatherService* weather_service; /* unowned */
|
||||
weather_service = g_value_get_object (value);
|
||||
|
||||
g_return_if_fail (weather_service == NULL || GCAL_IS_WEATHER_SERVICE (weather_service));
|
||||
|
||||
if (self->weather_service != weather_service)
|
||||
{
|
||||
g_set_object (&self->weather_service, weather_service);
|
||||
|
||||
gcal_week_header_set_weather_service (GCAL_WEEK_HEADER (self->header),
|
||||
self->weather_service);
|
||||
|
||||
g_object_notify (object, "weather-service");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
@@ -576,6 +600,10 @@ gcal_week_view_get_property (GObject *object,
|
||||
g_value_set_object (value, self->manager);
|
||||
break;
|
||||
|
||||
case PROP_WEATHER_SERVICE:
|
||||
g_value_set_object (value, self->weather_service);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
@@ -598,6 +626,18 @@ gcal_week_view_class_init (GcalWeekViewClass *klass)
|
||||
g_object_class_override_property (object_class, PROP_DATE, "active-date");
|
||||
g_object_class_override_property (object_class, PROP_MANAGER, "manager");
|
||||
|
||||
/**
|
||||
* GcalWeekView:weather-service:
|
||||
*
|
||||
* Sets the weather service to use.
|
||||
*/
|
||||
g_object_class_install_property
|
||||
(object_class,
|
||||
PROP_WEATHER_SERVICE,
|
||||
g_param_spec_object ("weather-service", "weather-service", "weather-service",
|
||||
GCAL_TYPE_WEATHER_SERVICE,
|
||||
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE));
|
||||
|
||||
signals[EVENT_ACTIVATED] = g_signal_new ("event-activated",
|
||||
GCAL_TYPE_WEEK_VIEW,
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
@@ -625,6 +665,8 @@ gcal_week_view_init (GcalWeekView *self)
|
||||
gtk_widget_init_template (GTK_WIDGET (self));
|
||||
|
||||
update_hours_sidebar_size (self);
|
||||
|
||||
self->weather_service = NULL;
|
||||
}
|
||||
|
||||
/* Public API */
|
||||
|
||||
Reference in New Issue
Block a user