diff options
Diffstat (limited to 'mateweather/src')
-rw-r--r-- | mateweather/src/Makefile.am | 37 | ||||
-rw-r--r-- | mateweather/src/main.c | 58 | ||||
-rw-r--r-- | mateweather/src/mateweather-about.c | 64 | ||||
-rw-r--r-- | mateweather/src/mateweather-about.h | 27 | ||||
-rw-r--r-- | mateweather/src/mateweather-applet.c | 547 | ||||
-rw-r--r-- | mateweather/src/mateweather-applet.h | 30 | ||||
-rw-r--r-- | mateweather/src/mateweather-dialog.c | 368 | ||||
-rw-r--r-- | mateweather/src/mateweather-dialog.h | 34 | ||||
-rw-r--r-- | mateweather/src/mateweather-pref.c | 1240 | ||||
-rw-r--r-- | mateweather/src/mateweather-pref.h | 59 | ||||
-rw-r--r-- | mateweather/src/mateweather.h | 53 |
11 files changed, 2517 insertions, 0 deletions
diff --git a/mateweather/src/Makefile.am b/mateweather/src/Makefile.am new file mode 100644 index 00000000..b01bc226 --- /dev/null +++ b/mateweather/src/Makefile.am @@ -0,0 +1,37 @@ +AM_CPPFLAGS = \ + -I$(srcdir) \ + -I$(top_srcdir) \ + -DWEATHER_RESOURCE_PATH=\""/org/mate/mate-applets/mateweather/"\" \ + $(MATE_APPLETS4_CFLAGS) \ + $(LIBNOTIFY_CFLAGS) \ + $(LIBMATEWEATHER_CFLAGS) \ + ${WARN_CFLAGS} + +libexec_PROGRAMS = mateweather-applet + +BUILT_SOURCES = mateweather-resources.c mateweather-resources.h +nodist_mateweather_applet_SOURCES = $(BUILT_SOURCES) +mateweather_applet_SOURCES = \ + mateweather.h \ + main.c \ + mateweather-about.c mateweather-about.h \ + mateweather-pref.c mateweather-pref.h \ + mateweather-dialog.c mateweather-dialog.h \ + mateweather-applet.c mateweather-applet.h + +mateweather_applet_LDADD = \ + $(LIBNOTIFY_LIBS) \ + $(MATE_APPLETS4_LIBS) \ + $(MATE_LIBS2_LIBS) \ + $(LIBMATEWEATHER_LIBS) + +mateweather-resources.c: ../data/mateweather-resources.gresource.xml $(shell $(GLIB_COMPILE_RESOURCES) --sourcedir=$(srcdir)/../data/ --generate-dependencies $(srcdir)/../data/mateweather-resources.gresource.xml) + $(AM_V_GEN)$(GLIB_COMPILE_RESOURCES) --target=$@ --sourcedir=$(srcdir)/../data/ --generate --c-name mateweather $< + +mateweather-resources.h: ../data/mateweather-resources.gresource.xml $(shell $(GLIB_COMPILE_RESOURCES) --sourcedir=$(srcdir)/../data/ --generate-dependencies $(srcdir)/../data/mateweather-resources.gresource.xml) + $(AM_V_GEN)$(GLIB_COMPILE_RESOURCES) --target=$@ --sourcedir=$(srcdir)/../data/ --generate --c-name mateweather $< + +CLEANFILES = \ + $(BUILT_SOURCES) + +-include $(top_srcdir)/git.mk diff --git a/mateweather/src/main.c b/mateweather/src/main.c new file mode 100644 index 00000000..de8d8436 --- /dev/null +++ b/mateweather/src/main.c @@ -0,0 +1,58 @@ +/* $Id$ */ + +/* + * Papadimitriou Spiros <[email protected]> + * + * This code released under the GNU GPL. + * Read the file COPYING for more information. + * + * Main applet widget + * + */ + +#include <glib.h> +#include <config.h> +#include <gtk/gtk.h> +#include <gio/gio.h> +#include <mate-panel-applet.h> +#include <mate-panel-applet-gsettings.h> + +#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE + +#include <libmateweather/mateweather-prefs.h> + +#include "mateweather.h" +#include "mateweather-pref.h" +#include "mateweather-dialog.h" +#include "mateweather-applet.h" + + +static gboolean mateweather_applet_new(MatePanelApplet* applet, const gchar* iid, gpointer data) +{ + MateWeatherApplet* gw_applet; + + gw_applet = g_new0(MateWeatherApplet, 1); + + gw_applet->applet = applet; + gw_applet->mateweather_info = NULL; + gw_applet->settings = mate_panel_applet_settings_new (applet, "org.mate.weather"); + + mateweather_applet_create(gw_applet); + + mateweather_prefs_load(&gw_applet->mateweather_pref, gw_applet->settings); + + mateweather_update(gw_applet); + + return TRUE; +} + +static gboolean mateweather_applet_factory(MatePanelApplet* applet, const gchar* iid, gpointer data) +{ + gboolean retval = FALSE; + + retval = mateweather_applet_new(applet, iid, data); + + return retval; +} + +MATE_PANEL_APPLET_OUT_PROCESS_FACTORY("MateWeatherAppletFactory", PANEL_TYPE_APPLET, "mateweather", mateweather_applet_factory, NULL) diff --git a/mateweather/src/mateweather-about.c b/mateweather/src/mateweather-about.c new file mode 100644 index 00000000..5c1389f3 --- /dev/null +++ b/mateweather/src/mateweather-about.c @@ -0,0 +1,64 @@ +/* $Id$ */ + +/* + * Papadimitriou Spiros <[email protected]> + * + * This code released under the GNU GPL. + * Read the file COPYING for more information. + * + * About box + * + */ + +#ifdef HAVE_CONFIG_H + #include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <assert.h> + +#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE + +#include "mateweather.h" +#include "mateweather-about.h" + +void mateweather_about_run(MateWeatherApplet* gw_applet) +{ + static const gchar* authors[] = { + "Todd Kulesza <[email protected]>", + "Philip Langdale <[email protected]>", + "Ryan Lortie <[email protected]>", + "Davyd Madeley <[email protected]>", + "Spiros Papadimitriou <[email protected]>", + "Kevin Vandersloot <[email protected]>", + NULL + }; + + const gchar* documenters[] = { + "Dan Mueth <[email protected]>", + "Spiros Papadimitriou <[email protected]>", + N_("Sun GNOME Documentation Team <[email protected]>"), + "Davyd Madeley <[email protected]>", + N_("MATE Documentation Team"), + NULL + }; + +#ifdef ENABLE_NLS + const char **p; + for (p = documenters; *p; ++p) + *p = _(*p); +#endif + + gtk_show_about_dialog(NULL, + "title", _("About Weather Report"), + "version", VERSION, + "copyright", _("Copyright \xC2\xA9 1999-2005 by S. Papadimitriou and others\n" + "Copyright \xc2\xa9 2012-2020 MATE developers"), + "comments", _("A panel application for monitoring local weather conditions."), + "authors", authors, + "documenters", documenters, + "translator-credits", _("translator-credits"), + "logo-icon-name", "weather-storm", + NULL); +} diff --git a/mateweather/src/mateweather-about.h b/mateweather/src/mateweather-about.h new file mode 100644 index 00000000..6d5bed01 --- /dev/null +++ b/mateweather/src/mateweather-about.h @@ -0,0 +1,27 @@ +#ifndef __MATEWEATHER_ABOUT_H_ +#define __MATEWEATHER_ABOUT_H_ + +/* $Id$ */ + +/* + * Papadimitriou Spiros <[email protected]> + * + * This code released under the GNU GPL. + * Read the file COPYING for more information. + * + * About box + * + */ + +#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE + +#include "mateweather.h" + +G_BEGIN_DECLS + +extern void mateweather_about_run (MateWeatherApplet *gw_applet); + +G_END_DECLS + +#endif /* __MATEWEATHER_ABOUT_H_ */ + diff --git a/mateweather/src/mateweather-applet.c b/mateweather/src/mateweather-applet.c new file mode 100644 index 00000000..7785744f --- /dev/null +++ b/mateweather/src/mateweather-applet.c @@ -0,0 +1,547 @@ +/* $Id$ */ + +/* + * Papadimitriou Spiros <[email protected]> + * + * This code released under the GNU GPL. + * Read the file COPYING for more information. + * + * Main applet widget + * + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif /* HAVE_CONFIG_H */ + +#include <stdio.h> +#include <stdlib.h> +#include <assert.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <resolv.h> + +#include <gio/gio.h> +#include <mate-panel-applet.h> +#include <mate-panel-applet-gsettings.h> + +#include <gdk/gdkkeysyms.h> + +#ifdef HAVE_LIBNOTIFY +#include <libnotify/notify.h> +#endif + +#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE + +#include "mateweather.h" +#include "mateweather-about.h" +#include "mateweather-pref.h" +#include "mateweather-dialog.h" +#include "mateweather-applet.h" + +#define MAX_CONSECUTIVE_FAULTS (3) + +static void about_cb (GtkAction *action, + MateWeatherApplet *gw_applet) +{ + + mateweather_about_run (gw_applet); +} + +static void help_cb (GtkAction *action, + MateWeatherApplet *gw_applet) +{ + GError *error = NULL; + + gtk_show_uri_on_window (NULL, + "help:mateweather", + gtk_get_current_event_time (), + &error); + + if (error) { + GtkWidget *dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, + _("There was an error displaying help: %s"), error->message); + g_signal_connect (G_OBJECT (dialog), "response", G_CALLBACK (gtk_widget_destroy), NULL); + gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE); + gtk_window_set_screen (GTK_WINDOW (dialog), gtk_widget_get_screen (GTK_WIDGET (gw_applet->applet))); + gtk_widget_show (dialog); + g_error_free (error); + error = NULL; + } +} + +static void pref_cb (GtkAction *action, + MateWeatherApplet *gw_applet) +{ + if (gw_applet->pref_dialog) { + gtk_window_present (GTK_WINDOW (gw_applet->pref_dialog)); + } else { + gw_applet->pref_dialog = mateweather_pref_new(gw_applet); + g_object_add_weak_pointer(G_OBJECT(gw_applet->pref_dialog), + (gpointer *)&(gw_applet->pref_dialog)); + gtk_widget_show_all (gw_applet->pref_dialog); + } +} + +static void details_cb (GtkAction *action, + MateWeatherApplet *gw_applet) +{ + if (gw_applet->details_dialog) { + gtk_window_present (GTK_WINDOW (gw_applet->details_dialog)); + } else { + gw_applet->details_dialog = mateweather_dialog_new(gw_applet); + g_object_add_weak_pointer(G_OBJECT(gw_applet->details_dialog), + (gpointer *)&(gw_applet->details_dialog)); + mateweather_dialog_update (MATEWEATHER_DIALOG (gw_applet->details_dialog)); + gtk_widget_show (gw_applet->details_dialog); + } +} + +static void update_cb (GtkAction *action, + MateWeatherApplet *gw_applet) +{ + mateweather_update (gw_applet); +} + + +static const GtkActionEntry weather_applet_menu_actions [] = { + { "Details", NULL, N_("_Details"), + NULL, NULL, + G_CALLBACK (details_cb) }, + { "Update", "view-refresh", N_("_Update"), + NULL, NULL, + G_CALLBACK (update_cb) }, + { "Props", "document-properties", N_("_Preferences"), + NULL, NULL, + G_CALLBACK (pref_cb) }, + { "Help", "help-browser", N_("_Help"), + NULL, NULL, + G_CALLBACK (help_cb) }, + { "About", "help-about", N_("_About"), + NULL, NULL, + G_CALLBACK (about_cb) } +}; + +static void place_widgets (MateWeatherApplet *gw_applet) +{ + GtkRequisition req; + int total_size = 0; + gboolean horizontal = FALSE; + int panel_size = gw_applet->size; + const gchar *temp; + const gchar *icon_name; + + switch (gw_applet->orient) { + case MATE_PANEL_APPLET_ORIENT_LEFT: + case MATE_PANEL_APPLET_ORIENT_RIGHT: + horizontal = FALSE; + break; + case MATE_PANEL_APPLET_ORIENT_UP: + case MATE_PANEL_APPLET_ORIENT_DOWN: + horizontal = TRUE; + break; + } + + /* Create the weather icon */ + icon_name = weather_info_get_icon_name (gw_applet->mateweather_info); + gw_applet->image = gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_BUTTON); + + if (icon_name != NULL) { + gtk_widget_show (gw_applet->image); + gtk_widget_get_preferred_size (gw_applet->image, &req, NULL); + if (horizontal) + total_size += req.height; + else + total_size += req.width; + } + + /* Create the temperature label */ + gw_applet->label = gtk_label_new("0\302\260F"); + + /* Update temperature text */ + temp = weather_info_get_temp_summary(gw_applet->mateweather_info); + if (temp) + gtk_label_set_text(GTK_LABEL(gw_applet->label), temp); + + /* Check the label size to determine box layout */ + gtk_widget_show (gw_applet->label); + gtk_widget_get_preferred_size (gw_applet->label, &req, NULL); + if (horizontal) + total_size += req.height; + else + total_size += req.width; + + /* Pack the box */ + if (gw_applet->box) + gtk_widget_destroy (gw_applet->box); + + if (horizontal && (total_size <= panel_size)) + gw_applet->box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); + else if (horizontal && (total_size > panel_size)) + gw_applet->box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2); + else if (!horizontal && (total_size <= panel_size)) + gw_applet->box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2); + else + gw_applet->box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); + + /* better for vertical panels */ + if (horizontal) + gtk_widget_set_valign (gw_applet->box, GTK_ALIGN_CENTER); + else + gtk_widget_set_halign (gw_applet->box, GTK_ALIGN_CENTER); + + /* Rebuild the applet it's visual area */ + gtk_container_add (GTK_CONTAINER (gw_applet->applet), gw_applet->box); + gtk_box_pack_start (GTK_BOX (gw_applet->box), gw_applet->image, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (gw_applet->box), gw_applet->label, TRUE, TRUE, 0); + + gtk_widget_show_all (GTK_WIDGET (gw_applet->applet)); +} + +static void change_orient_cb (MatePanelApplet *w, MatePanelAppletOrient o, gpointer data) +{ + MateWeatherApplet *gw_applet = (MateWeatherApplet *)data; + + gw_applet->orient = o; + place_widgets(gw_applet); + return; +} + +static void size_allocate_cb(MatePanelApplet *w, GtkAllocation *allocation, gpointer data) +{ + MateWeatherApplet *gw_applet = (MateWeatherApplet *)data; + + if ((gw_applet->orient == MATE_PANEL_APPLET_ORIENT_LEFT) || (gw_applet->orient == MATE_PANEL_APPLET_ORIENT_RIGHT)) { + if (gw_applet->size == allocation->width) + return; + gw_applet->size = allocation->width; + } else { + if (gw_applet->size == allocation->height) + return; + gw_applet->size = allocation->height; + } + + place_widgets(gw_applet); + return; +} + +static gboolean clicked_cb (GtkWidget *widget, GdkEventButton *ev, gpointer data) +{ + MateWeatherApplet *gw_applet = data; + + if ((ev == NULL) || (ev->button != 1)) + return FALSE; + + if (ev->type == GDK_BUTTON_PRESS) { + if (!gw_applet->details_dialog) + details_cb (NULL, gw_applet); + else + gtk_widget_destroy (GTK_WIDGET (gw_applet->details_dialog)); + + return TRUE; + } + + return FALSE; +} + +static gboolean +key_press_cb (GtkWidget *widget, GdkEventKey *event, MateWeatherApplet *gw_applet) +{ + switch (event->keyval) { + case GDK_KEY_u: + if (event->state == GDK_CONTROL_MASK) { + mateweather_update (gw_applet); + return TRUE; + } + break; + case GDK_KEY_d: + if (event->state == GDK_CONTROL_MASK) { + details_cb (NULL, gw_applet); + return TRUE; + } + break; + case GDK_KEY_KP_Enter: + case GDK_KEY_ISO_Enter: + case GDK_KEY_3270_Enter: + case GDK_KEY_Return: + case GDK_KEY_space: + case GDK_KEY_KP_Space: + details_cb (NULL, gw_applet); + return TRUE; + default: + break; + } + + return FALSE; + +} + +static void +network_changed (GNetworkMonitor *monitor, gboolean available, MateWeatherApplet *gw_applet) +{ + if (available) { + mateweather_update (gw_applet); + } +} + +static void +applet_destroy (GtkWidget *widget, MateWeatherApplet *gw_applet) +{ + GNetworkMonitor *monitor; + + if (gw_applet->pref_dialog) + gtk_widget_destroy (gw_applet->pref_dialog); + + if (gw_applet->details_dialog) + gtk_widget_destroy (gw_applet->details_dialog); + + if (gw_applet->timeout_tag > 0) { + g_source_remove(gw_applet->timeout_tag); + gw_applet->timeout_tag = 0; + } + + if (gw_applet->suncalc_timeout_tag > 0) { + g_source_remove(gw_applet->suncalc_timeout_tag); + gw_applet->suncalc_timeout_tag = 0; + } + + if (gw_applet->settings) { + g_object_unref (gw_applet->settings); + gw_applet->settings = NULL; + } + + monitor = g_network_monitor_get_default (); + g_signal_handlers_disconnect_by_func (monitor, + G_CALLBACK (network_changed), + gw_applet); + + weather_info_abort (gw_applet->mateweather_info); +} + +void mateweather_applet_create (MateWeatherApplet *gw_applet) +{ + GtkActionGroup *action_group; + AtkObject *atk_obj; + GNetworkMonitor*monitor; + + gw_applet->mateweather_pref.location = NULL; + gw_applet->mateweather_pref.show_notifications = FALSE; + gw_applet->mateweather_pref.update_interval = 1800; + gw_applet->mateweather_pref.update_enabled = TRUE; + gw_applet->mateweather_pref.detailed = FALSE; + gw_applet->mateweather_pref.radar_enabled = TRUE; + gw_applet->mateweather_pref.temperature_unit = TEMP_UNIT_INVALID; + gw_applet->mateweather_pref.speed_unit = SPEED_UNIT_INVALID; + gw_applet->mateweather_pref.pressure_unit = PRESSURE_UNIT_INVALID; + gw_applet->mateweather_pref.distance_unit = DISTANCE_UNIT_INVALID; + + mate_panel_applet_set_flags (gw_applet->applet, MATE_PANEL_APPLET_EXPAND_MINOR); + + g_set_application_name (_("Weather Report")); + + gtk_window_set_default_icon_name ("weather-storm"); + + g_signal_connect (G_OBJECT(gw_applet->applet), "change_orient", + G_CALLBACK(change_orient_cb), gw_applet); + g_signal_connect (G_OBJECT(gw_applet->applet), "size_allocate", + G_CALLBACK(size_allocate_cb), gw_applet); + g_signal_connect (G_OBJECT(gw_applet->applet), "destroy", + G_CALLBACK (applet_destroy), gw_applet); + g_signal_connect (G_OBJECT(gw_applet->applet), "button_press_event", + G_CALLBACK(clicked_cb), gw_applet); + g_signal_connect (G_OBJECT(gw_applet->applet), "key_press_event", + G_CALLBACK(key_press_cb), gw_applet); + + gtk_widget_set_tooltip_text (GTK_WIDGET(gw_applet->applet), _("MATE Weather")); + + atk_obj = gtk_widget_get_accessible (GTK_WIDGET (gw_applet->applet)); + if (GTK_IS_ACCESSIBLE (atk_obj)) + atk_object_set_name (atk_obj, _("MATE Weather")); + + gw_applet->size = mate_panel_applet_get_size (gw_applet->applet); + + gw_applet->orient = mate_panel_applet_get_orient (gw_applet->applet); + + action_group = gtk_action_group_new ("MateWeather Applet Actions"); + gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE); + gtk_action_group_add_actions (action_group, + weather_applet_menu_actions, + G_N_ELEMENTS (weather_applet_menu_actions), + gw_applet); + mate_panel_applet_setup_menu_from_resource (gw_applet->applet, + WEATHER_RESOURCE_PATH "mateweather-applet-menu.xml", + action_group); + + if (mate_panel_applet_get_locked_down (gw_applet->applet)) { + GtkAction *action; + + action = gtk_action_group_get_action (action_group, "Props"); + gtk_action_set_visible (action, FALSE); + } + g_object_unref (action_group); + + place_widgets(gw_applet); + + monitor = g_network_monitor_get_default(); + g_signal_connect (monitor, "network-changed", + G_CALLBACK (network_changed), gw_applet);} + +gint timeout_cb (gpointer data) +{ + MateWeatherApplet *gw_applet = (MateWeatherApplet *)data; + + mateweather_update(gw_applet); + return 0; /* Do not repeat timeout (will be reset by mateweather_update) */ +} + +static void +update_finish (WeatherInfo *info, gpointer data) +{ + static int gw_fault_counter = 0; +#ifdef HAVE_LIBNOTIFY + char *message, *detail; +#endif + char *s; + MateWeatherApplet *gw_applet = (MateWeatherApplet *)data; + gint nxtSunEvent; + const gchar *icon_name; + + /* Update timer */ + if (gw_applet->timeout_tag > 0) + g_source_remove(gw_applet->timeout_tag); + if (gw_applet->mateweather_pref.update_enabled) + { + gw_applet->timeout_tag = + g_timeout_add_seconds ( + gw_applet->mateweather_pref.update_interval, + timeout_cb, gw_applet); + + nxtSunEvent = weather_info_next_sun_event(gw_applet->mateweather_info); + if (nxtSunEvent >= 0) + gw_applet->suncalc_timeout_tag = + g_timeout_add_seconds (nxtSunEvent, + suncalc_timeout_cb, gw_applet); + } + + if ((TRUE == weather_info_is_valid (info)) || + (gw_fault_counter >= MAX_CONSECUTIVE_FAULTS)) + { + gw_fault_counter = 0; + icon_name = weather_info_get_icon_name (gw_applet->mateweather_info); + gtk_image_set_from_icon_name (GTK_IMAGE(gw_applet->image), + icon_name, GTK_ICON_SIZE_BUTTON); + + gtk_label_set_text (GTK_LABEL (gw_applet->label), + weather_info_get_temp_summary( + gw_applet->mateweather_info)); + + s = weather_info_get_weather_summary (gw_applet->mateweather_info); + gtk_widget_set_tooltip_text (GTK_WIDGET (gw_applet->applet), s); + g_free (s); + + /* Update dialog -- if one is present */ + if (gw_applet->details_dialog) { + mateweather_dialog_update (MATEWEATHER_DIALOG (gw_applet->details_dialog)); + } + + /* update applet */ + place_widgets(gw_applet); + +#ifdef HAVE_LIBNOTIFY + if (gw_applet->mateweather_pref.show_notifications) + { + NotifyNotification *n; + + /* Show notifications if possible */ + if (!notify_is_initted ()) + notify_init (_("Weather Forecast")); + + if (notify_is_initted ()) + { + GError *error = NULL; + const char *icon; + + /* Show notification */ + message = g_strdup_printf ("%s: %s", + weather_info_get_location_name (info), + weather_info_get_sky (info)); + detail = g_strdup_printf ( + _("City: %s\nSky: %s\nTemperature: %s"), + weather_info_get_location_name (info), + weather_info_get_sky (info), + weather_info_get_temp_summary (info)); + + icon = weather_info_get_icon_name (gw_applet->mateweather_info); + if (icon == NULL) + icon = "stock-unknown"; + + n = notify_notification_new (message, detail, icon); + + notify_notification_show (n, &error); + if (error) + { + g_warning ("%s", error->message); + g_error_free (error); + } + + g_free (message); + g_free (detail); + } + } +#endif + } + else + { + /* there has been an error during retrival + * just update the fault counter + */ + gw_fault_counter++; + } +} + +gint suncalc_timeout_cb (gpointer data) +{ + WeatherInfo *info = ((MateWeatherApplet *)data)->mateweather_info; + update_finish(info, data); + return 0; /* Do not repeat timeout (will be reset by update_finish) */ +} + + +void mateweather_update (MateWeatherApplet *gw_applet) +{ + WeatherPrefs prefs; + const gchar *icon_name; + + icon_name = weather_info_get_icon_name(gw_applet->mateweather_info); + gtk_image_set_from_icon_name (GTK_IMAGE (gw_applet->image), + icon_name, GTK_ICON_SIZE_BUTTON); + gtk_widget_set_tooltip_text (GTK_WIDGET(gw_applet->applet), _("Updating...")); + + /* Set preferred forecast type */ + prefs.type = gw_applet->mateweather_pref.detailed ? FORECAST_ZONE : FORECAST_STATE; + + /* Set radar map retrieval option */ + prefs.radar = gw_applet->mateweather_pref.radar_enabled; + prefs.radar_custom_url = (gw_applet->mateweather_pref.use_custom_radar_url && + gw_applet->mateweather_pref.radar) ? + gw_applet->mateweather_pref.radar : NULL; + + /* Set the units */ + prefs.temperature_unit = gw_applet->mateweather_pref.temperature_unit; + prefs.speed_unit = gw_applet->mateweather_pref.speed_unit; + prefs.pressure_unit = gw_applet->mateweather_pref.pressure_unit; + prefs.distance_unit = gw_applet->mateweather_pref.distance_unit; + + /* Update current conditions */ + if (gw_applet->mateweather_info && + weather_location_equal(weather_info_get_location(gw_applet->mateweather_info), + gw_applet->mateweather_pref.location)) { + weather_info_update(gw_applet->mateweather_info, &prefs, + update_finish, gw_applet); + } else { + weather_info_free(gw_applet->mateweather_info); + gw_applet->mateweather_info = weather_info_new(gw_applet->mateweather_pref.location, + &prefs, + update_finish, gw_applet); + } +} diff --git a/mateweather/src/mateweather-applet.h b/mateweather/src/mateweather-applet.h new file mode 100644 index 00000000..eef4f8bb --- /dev/null +++ b/mateweather/src/mateweather-applet.h @@ -0,0 +1,30 @@ +#ifndef __MATEWEATHER_APPLET_H_ +#define __MATEWEATHER_APPLET_H_ + +/* $Id$ */ + +/* + * Papadimitriou Spiros <[email protected]> + * + * This code released under the GNU GPL. + * Read the file COPYING for more information. + * + * Main applet widget + * + */ + +#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE + +#include "mateweather.h" + +G_BEGIN_DECLS + +extern void mateweather_applet_create(MateWeatherApplet *gw_applet); +extern gint timeout_cb (gpointer data); +extern gint suncalc_timeout_cb (gpointer data); +extern void mateweather_update (MateWeatherApplet *applet); + +G_END_DECLS + +#endif /* __MATEWEATHER_APPLET_H_ */ + diff --git a/mateweather/src/mateweather-dialog.c b/mateweather/src/mateweather-dialog.c new file mode 100644 index 00000000..02ca824c --- /dev/null +++ b/mateweather/src/mateweather-dialog.c @@ -0,0 +1,368 @@ +/* $Id$ */ + +/* + * Papadimitriou Spiros <[email protected]> + * + * This code released under the GNU GPL. + * Read the file COPYING for more information. + * + * Main status dialog + * + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif /* HAVE_CONFIG_H */ + +#include <stdio.h> +#include <stdlib.h> +#include <assert.h> + +#include <gio/gio.h> + +#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE + +#include "mateweather.h" +#include "mateweather-applet.h" +#include "mateweather-pref.h" +#include "mateweather-dialog.h" + +struct _MateWeatherDialog { + GtkDialog parent; + + GtkWidget *weather_notebook; + GtkWidget *cond_location; + GtkWidget *cond_update; + GtkWidget *cond_cond; + GtkWidget *cond_sky; + GtkWidget *cond_temp; + GtkWidget *cond_dew; + GtkWidget *cond_humidity; + GtkWidget *cond_wind; + GtkWidget *cond_pressure; + GtkWidget *cond_vis; + GtkWidget *cond_apparent; + GtkWidget *cond_sunrise; + GtkWidget *cond_sunset; + GtkWidget *cond_image; + GtkWidget *forecast_text; + GtkWidget *radar_image; + + MateWeatherApplet *applet; +}; + +enum { + PROP_0, + PROP_MATEWEATHER_APPLET, +}; + +G_DEFINE_TYPE (MateWeatherDialog, mateweather_dialog, GTK_TYPE_DIALOG); + +#define MONOSPACE_FONT_SCHEMA "org.mate.interface" +#define MONOSPACE_FONT_KEY "monospace-font-name" + +static void +response_cb (MateWeatherDialog *dialog, + gint id, + gpointer data) +{ + if (id == GTK_RESPONSE_OK) { + mateweather_update (dialog->applet); + mateweather_dialog_update (dialog); + } else { + gtk_widget_destroy (GTK_WIDGET (dialog)); + } +} + +static void +link_cb (GtkButton *button, + gpointer data) +{ + gtk_show_uri_on_window (NULL, + "http://www.weather.com/", + gtk_get_current_event_time (), + NULL); +} + +static gchar* +replace_multiple_new_lines(gchar* s) +{ + gchar *prev_s = s; + gint count; + gint i; + + if (s == NULL) { + return s; + } + + for (;*s != '\0';s++) { + + count = 0; + + if (*s == '\n') { + s++; + while (*s == '\n' || *s == ' ') { + count++; + s++; + } + } + for (i = count; i > 1; i--) { + *(s - i) = ' '; + } + } + return prev_s; +} + +static PangoFontDescription* get_system_monospace_font(void) +{ + PangoFontDescription *desc = NULL; + GSettings *settings; + char *name; + + settings = g_settings_new (MONOSPACE_FONT_SCHEMA); + name = g_settings_get_string (settings, MONOSPACE_FONT_KEY); + + if (name) { + desc = pango_font_description_from_string (name); + g_free (name); + } + + g_object_unref (settings); + + return desc; +} + +static void +override_widget_font (GtkWidget *widget, + PangoFontDescription *font) +{ + static gboolean provider_added = FALSE; + static GtkCssProvider *provider; + gchar *css; + gchar *family; + gchar *weight; + const gchar *style; + gchar *size; + + family = g_strdup_printf ("font-family: %s;", pango_font_description_get_family (font)); + + weight = g_strdup_printf ("font-weight: %d;", pango_font_description_get_weight (font)); + + if (pango_font_description_get_style (font) == PANGO_STYLE_NORMAL) + style = "font-style: normal;"; + else if (pango_font_description_get_style (font) == PANGO_STYLE_ITALIC) + style = "font-style: italic;"; + else + style = "font-style: oblique;"; + + size = g_strdup_printf ("font-size: %d%s;", + pango_font_description_get_size (font) / PANGO_SCALE, + pango_font_description_get_size_is_absolute (font) ? "px" : "pt"); + if (!provider_added) + provider = gtk_css_provider_new (); + + gtk_widget_set_name(GTK_WIDGET(widget), "MateWeatherAppletTextView"); + css = g_strdup_printf ("#MateWeatherAppletTextView { %s %s %s %s }", family, weight, style, size); + gtk_css_provider_load_from_data (provider, css, -1, NULL); + + if (!provider_added) { + gtk_style_context_add_provider_for_screen (gtk_widget_get_screen (widget), + GTK_STYLE_PROVIDER (provider), + GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); + provider_added = TRUE; + } + + g_free (css); + g_free (family); + g_free (weight); + g_free (size); +} + +void +mateweather_dialog_update (MateWeatherDialog *dialog) +{ + WeatherInfo *info; + gchar *forecast; + GtkTextBuffer *buffer; + PangoFontDescription *font_desc; + const gchar *icon_name; + + /* Check for parallel network update in progress */ + if (dialog->applet->mateweather_info == NULL) + return; + + info = dialog->applet->mateweather_info; + + /* Update icon */ + icon_name = weather_info_get_icon_name (info); + gtk_image_set_from_icon_name (GTK_IMAGE (dialog->cond_image), + icon_name, GTK_ICON_SIZE_DIALOG); + + /* Update current condition fields and forecast */ + gtk_label_set_text (GTK_LABEL (dialog->cond_location), weather_info_get_location_name (info)); + gtk_label_set_text (GTK_LABEL (dialog->cond_update), weather_info_get_update (info)); + gtk_label_set_text (GTK_LABEL (dialog->cond_cond), weather_info_get_conditions (info)); + gtk_label_set_text (GTK_LABEL (dialog->cond_sky), weather_info_get_sky (info)); + gtk_label_set_text (GTK_LABEL (dialog->cond_temp), weather_info_get_temp (info)); + gtk_label_set_text (GTK_LABEL (dialog->cond_apparent), weather_info_get_apparent (info)); + gtk_label_set_text (GTK_LABEL (dialog->cond_dew), weather_info_get_dew (info)); + gtk_label_set_text (GTK_LABEL (dialog->cond_humidity), weather_info_get_humidity (info)); + gtk_label_set_text (GTK_LABEL (dialog->cond_wind), weather_info_get_wind (info)); + gtk_label_set_text (GTK_LABEL (dialog->cond_pressure), weather_info_get_pressure (info)); + gtk_label_set_text (GTK_LABEL (dialog->cond_vis), weather_info_get_visibility (info)); + gtk_label_set_text (GTK_LABEL (dialog->cond_sunrise), weather_info_get_sunrise (info)); + gtk_label_set_text (GTK_LABEL (dialog->cond_sunset), weather_info_get_sunset (info)); + + /* Update forecast */ + if (dialog->applet->mateweather_pref.location->zone_valid) { + font_desc = get_system_monospace_font (); + if (font_desc) { + override_widget_font (dialog->forecast_text, font_desc); + pango_font_description_free (font_desc); + } + + buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (dialog->forecast_text)); + forecast = g_strdup (weather_info_get_forecast (dialog->applet->mateweather_info)); + if (forecast) { + forecast = g_strstrip (replace_multiple_new_lines (forecast)); + gtk_text_buffer_set_text (buffer, forecast, -1); + g_free (forecast); + } else { + gtk_text_buffer_set_text (buffer, _("Forecast not currently available for this location."), -1); + } + gtk_widget_show (gtk_notebook_get_nth_page (GTK_NOTEBOOK (dialog->weather_notebook), 1)); + } else { + gtk_widget_hide (gtk_notebook_get_nth_page (GTK_NOTEBOOK (dialog->weather_notebook), 1)); + } + + /* Update radar map */ + if (dialog->applet->mateweather_pref.radar_enabled) { + GdkPixbufAnimation *radar; + + radar = weather_info_get_radar (info); + if (radar) { + gtk_image_set_from_animation (GTK_IMAGE (dialog->radar_image), radar); + } + gtk_widget_show (gtk_notebook_get_nth_page (GTK_NOTEBOOK (dialog->weather_notebook), 2)); + gtk_window_set_default_size (GTK_WINDOW (dialog), 570, 440); + } else { + gtk_widget_hide (gtk_notebook_get_nth_page (GTK_NOTEBOOK (dialog->weather_notebook), 2)); + gtk_window_set_default_size (GTK_WINDOW (dialog), 590, 340); + } +} + +static void +mateweather_dialog_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + MateWeatherDialog *dialog; + + dialog = MATEWEATHER_DIALOG (object); + + switch (prop_id) { + case PROP_MATEWEATHER_APPLET: + dialog->applet = g_value_get_pointer (value); + break; + default: + /* We don't have any other property... */ + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +mateweather_dialog_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + MateWeatherDialog *dialog; + + dialog = MATEWEATHER_DIALOG (object); + + switch (prop_id) { + case PROP_MATEWEATHER_APPLET: + g_value_set_pointer (value, dialog->applet); + break; + default: + /* We don't have any other property... */ + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +mateweather_dialog_init (MateWeatherDialog *dialog) +{ + gtk_widget_init_template (GTK_WIDGET (dialog)); +} + +static GObject* +mateweather_dialog_constructor (GType type, + guint n_construct_params, + GObjectConstructParam *construct_params) +{ + GObject *object; + MateWeatherDialog *self; + + object = G_OBJECT_CLASS (mateweather_dialog_parent_class)-> + constructor (type, n_construct_params, construct_params); + self = MATEWEATHER_DIALOG (object); + + mateweather_dialog_update (self); + + return object; +} + +GtkWidget* +mateweather_dialog_new (MateWeatherApplet *applet) +{ + return g_object_new(MATEWEATHER_TYPE_DIALOG, + "mateweather-applet", applet, + NULL); +} + +static void +mateweather_dialog_class_init (MateWeatherDialogClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + + object_class->set_property = mateweather_dialog_set_property; + object_class->get_property = mateweather_dialog_get_property; + object_class->constructor = mateweather_dialog_constructor; + + /* This becomes an OBJECT property when MateWeatherApplet is redone */ + g_object_class_install_property (object_class, + PROP_MATEWEATHER_APPLET, + g_param_spec_pointer ("mateweather-applet", + "MateWeather Applet", + "The MateWeather Applet", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + gtk_widget_class_set_template_from_resource (widget_class, + WEATHER_RESOURCE_PATH "mateweather-dialog.ui"); + + gtk_widget_class_bind_template_child (widget_class, MateWeatherDialog, weather_notebook); + gtk_widget_class_bind_template_child (widget_class, MateWeatherDialog, cond_location); + gtk_widget_class_bind_template_child (widget_class, MateWeatherDialog, cond_update); + gtk_widget_class_bind_template_child (widget_class, MateWeatherDialog, cond_cond); + gtk_widget_class_bind_template_child (widget_class, MateWeatherDialog, cond_sky); + gtk_widget_class_bind_template_child (widget_class, MateWeatherDialog, cond_temp); + gtk_widget_class_bind_template_child (widget_class, MateWeatherDialog, cond_dew); + gtk_widget_class_bind_template_child (widget_class, MateWeatherDialog, cond_humidity); + gtk_widget_class_bind_template_child (widget_class, MateWeatherDialog, cond_wind); + gtk_widget_class_bind_template_child (widget_class, MateWeatherDialog, cond_pressure); + gtk_widget_class_bind_template_child (widget_class, MateWeatherDialog, cond_vis); + gtk_widget_class_bind_template_child (widget_class, MateWeatherDialog, cond_apparent); + gtk_widget_class_bind_template_child (widget_class, MateWeatherDialog, cond_sunrise); + gtk_widget_class_bind_template_child (widget_class, MateWeatherDialog, cond_sunset); + gtk_widget_class_bind_template_child (widget_class, MateWeatherDialog, cond_image); + gtk_widget_class_bind_template_child (widget_class, MateWeatherDialog, forecast_text); + gtk_widget_class_bind_template_child (widget_class, MateWeatherDialog, radar_image); + + gtk_widget_class_bind_template_callback (widget_class, response_cb); + gtk_widget_class_bind_template_callback (widget_class, link_cb); +} diff --git a/mateweather/src/mateweather-dialog.h b/mateweather/src/mateweather-dialog.h new file mode 100644 index 00000000..0eaf0b50 --- /dev/null +++ b/mateweather/src/mateweather-dialog.h @@ -0,0 +1,34 @@ +#ifndef __MATEWEATHER_DIALOG_H_ +#define __MATEWEATHER_DIALOG_H_ + +/* $Id$ */ + +/* + * Papadimitriou Spiros <[email protected]> + * + * This code released under the GNU GPL. + * Read the file COPYING for more information. + * + * Main status dialog + * + */ + +#include <gtk/gtk.h> + +#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE + +#include "mateweather.h" + +G_BEGIN_DECLS + +#define MATEWEATHER_TYPE_DIALOG mateweather_dialog_get_type () +G_DECLARE_FINAL_TYPE (MateWeatherDialog, mateweather_dialog, + MATEWEATHER, DIALOG, GtkDialog) + +GtkWidget *mateweather_dialog_new (MateWeatherApplet *applet); +void mateweather_dialog_update (MateWeatherDialog *dialog); + +G_END_DECLS + +#endif /* __MATEWEATHER_DIALOG_H_ */ + diff --git a/mateweather/src/mateweather-pref.c b/mateweather/src/mateweather-pref.c new file mode 100644 index 00000000..ac41e149 --- /dev/null +++ b/mateweather/src/mateweather-pref.c @@ -0,0 +1,1240 @@ +/* $Id$ */ + +/* + * Papadimitriou Spiros <[email protected]> + * + * This code released under the GNU GPL. + * Read the file COPYING for more information. + * + * Preferences dialog + * + */ + +/* Radar map on by default. */ +#define RADARMAP + +#ifdef HAVE_CONFIG_H + #include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include <ctype.h> +#include <locale.h> + +#include <mate-panel-applet.h> +#include <gio/gio.h> + +#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE + +#include <libmateweather/mateweather-xml.h> +#include "mateweather.h" +#include "mateweather-pref.h" +#include "mateweather-applet.h" +#include "mateweather-dialog.h" + +#define NEVER_SENSITIVE "never_sensitive" + +struct _MateWeatherPrefPrivate { + GtkWidget* notebook; + + GtkWidget* basic_temp_combo; + GtkWidget* basic_speed_combo; + GtkWidget* basic_dist_combo; + GtkWidget* basic_pres_combo; + GtkWidget* find_entry; + GtkWidget* find_next_btn; + + #ifdef RADARMAP + GtkWidget* basic_radar_btn; + GtkWidget* basic_radar_url_btn; + GtkWidget* basic_radar_url_hbox; + GtkWidget* basic_radar_url_entry; + #endif /* RADARMAP */ + + #ifdef HAVE_LIBNOTIFY + GtkWidget* basic_show_notifications_btn; + #endif + + GtkWidget* basic_update_spin; + GtkWidget* basic_update_btn; + GtkWidget* tree; + + GtkTreeModel* model; + + MateWeatherApplet* applet; +}; + +enum { + PROP_0, + PROP_MATEWEATHER_APPLET, +}; + +G_DEFINE_TYPE_WITH_PRIVATE (MateWeatherPref, mateweather_pref, GTK_TYPE_DIALOG); + +/* set sensitive and setup NEVER_SENSITIVE appropriately */ +static void hard_set_sensitive(GtkWidget* w, gboolean sensitivity) +{ + gtk_widget_set_sensitive(w, sensitivity); + g_object_set_data(G_OBJECT(w), NEVER_SENSITIVE, GINT_TO_POINTER(!sensitivity)); +} + + +/* set sensitive, but always insensitive if NEVER_SENSITIVE is set */ +static void soft_set_sensitive(GtkWidget* w, gboolean sensitivity) +{ + if (g_object_get_data(G_OBJECT(w), NEVER_SENSITIVE)) + { + gtk_widget_set_sensitive(w, FALSE); + } + else + { + gtk_widget_set_sensitive(w, sensitivity); + } +} + +/* sets up ATK Relation between the widgets */ +static void add_atk_relation(GtkWidget* widget1, GtkWidget* widget2, AtkRelationType type) +{ + AtkObject* atk_obj1; + AtkObject* atk_obj2; + AtkRelationSet* relation_set; + AtkRelation* relation; + + atk_obj1 = gtk_widget_get_accessible(widget1); + + if (!GTK_IS_ACCESSIBLE(atk_obj1)) + { + return; + } + + atk_obj2 = gtk_widget_get_accessible(widget2); + + relation_set = atk_object_ref_relation_set(atk_obj1); + relation = atk_relation_new(&atk_obj2, 1, type); + atk_relation_set_add(relation_set, relation); + g_object_unref(G_OBJECT(relation)); +} + +/* sets accessible name and description */ +void set_access_namedesc(GtkWidget* widget, const gchar* name, const gchar* desc) +{ + AtkObject* obj = gtk_widget_get_accessible(widget); + + if (!GTK_IS_ACCESSIBLE(obj)) + { + return; + } + + if (desc) + { + atk_object_set_description(obj, desc); + } + + if (name) + { + atk_object_set_name(obj, name); + } +} + +/* sets accessible name, description, CONTROLLED_BY + * and CONTROLLER_FOR relations for the components + * in mateweather preference dialog. + */ +static void mateweather_pref_set_accessibility(MateWeatherPref* pref) +{ + /* Relation between components in General page */ + add_atk_relation(pref->priv->basic_update_btn, pref->priv->basic_update_spin, ATK_RELATION_CONTROLLER_FOR); + add_atk_relation(pref->priv->basic_radar_btn, pref->priv->basic_radar_url_btn, ATK_RELATION_CONTROLLER_FOR); + add_atk_relation(pref->priv->basic_radar_btn, pref->priv->basic_radar_url_entry, ATK_RELATION_CONTROLLER_FOR); + + add_atk_relation(pref->priv->basic_update_spin, pref->priv->basic_update_btn, ATK_RELATION_CONTROLLED_BY); + add_atk_relation(pref->priv->basic_radar_url_btn, pref->priv->basic_radar_btn, ATK_RELATION_CONTROLLED_BY); + add_atk_relation(pref->priv->basic_radar_url_entry, pref->priv->basic_radar_btn, ATK_RELATION_CONTROLLED_BY); + + /* Accessible Name and Description for the components in Preference Dialog */ + set_access_namedesc(pref->priv->tree, _("Location view"), _("Select Location from the list")); + set_access_namedesc(pref->priv->basic_update_spin, _("Update spin button"), _("Spinbutton for updating")); + set_access_namedesc(pref->priv->basic_radar_url_entry, _("Address Entry"), _("Enter the URL")); +} + + +/* Update pref dialog from mateweather_pref */ +static gboolean update_dialog(MateWeatherPref* pref) +{ + MateWeatherApplet* gw_applet = pref->priv->applet; + + g_return_val_if_fail(gw_applet->mateweather_pref.location != NULL, FALSE); + + gtk_spin_button_set_value(GTK_SPIN_BUTTON(pref->priv->basic_update_spin), gw_applet->mateweather_pref.update_interval / 60); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pref->priv->basic_update_btn), gw_applet->mateweather_pref.update_enabled); + soft_set_sensitive(pref->priv->basic_update_spin, gw_applet->mateweather_pref.update_enabled); + + gtk_combo_box_set_active(GTK_COMBO_BOX(pref->priv->basic_temp_combo), gw_applet->mateweather_pref.temperature_unit - 2); + + gtk_combo_box_set_active(GTK_COMBO_BOX(pref->priv->basic_speed_combo), gw_applet->mateweather_pref.speed_unit - 2); + + gtk_combo_box_set_active(GTK_COMBO_BOX(pref->priv->basic_pres_combo), gw_applet->mateweather_pref.pressure_unit - 2); + + gtk_combo_box_set_active(GTK_COMBO_BOX(pref->priv->basic_dist_combo), gw_applet->mateweather_pref.distance_unit - 2); + + #ifdef RADARMAP + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pref->priv->basic_radar_btn), gw_applet->mateweather_pref.radar_enabled); + + soft_set_sensitive(pref->priv->basic_radar_url_btn, gw_applet->mateweather_pref.radar_enabled); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pref->priv->basic_radar_url_btn), gw_applet->mateweather_pref.use_custom_radar_url); + soft_set_sensitive(pref->priv->basic_radar_url_hbox, gw_applet->mateweather_pref.radar_enabled); + + if (gw_applet->mateweather_pref.radar) + { + gtk_entry_set_text(GTK_ENTRY(pref->priv->basic_radar_url_entry), gw_applet->mateweather_pref.radar); + } + + #endif /* RADARMAP */ + + #ifdef HAVE_LIBNOTIFY + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pref->priv->basic_show_notifications_btn), gw_applet->mateweather_pref.show_notifications); + #endif + return TRUE; +} + +static void row_selected_cb(GtkTreeSelection* selection, MateWeatherPref* pref) +{ + MateWeatherApplet* gw_applet = pref->priv->applet; + GtkTreeModel* model; + WeatherLocation* loc = NULL; + GtkTreeIter iter; + + if (!gtk_tree_selection_get_selected(selection, &model, &iter)) + return; + + gtk_tree_model_get(model, &iter, MATEWEATHER_XML_COL_POINTER, &loc, -1); + + if (!loc) + { + return; + } + + g_settings_set_string (gw_applet->settings, "location1", loc->code); + g_settings_set_string (gw_applet->settings, "location2", loc->zone); + g_settings_set_string (gw_applet->settings, "location3", loc->radar); + g_settings_set_string (gw_applet->settings, "location4", loc->name); + g_settings_set_string (gw_applet->settings, "coordinates", loc->coordinates); + + if (gw_applet->mateweather_pref.location) + { + weather_location_free(gw_applet->mateweather_pref.location); + } + + gw_applet->mateweather_pref.location = + weather_location_new (loc->name, loc->code, loc->zone, loc->radar, loc->coordinates, + NULL, NULL); + + mateweather_update(gw_applet); +} + +static gboolean compare_location(GtkTreeModel* model, GtkTreePath* path, GtkTreeIter* iter, gpointer user_data) +{ + MateWeatherPref* pref = user_data; + WeatherLocation* loc; + GtkTreeView* view; + + gtk_tree_model_get(model, iter, MATEWEATHER_XML_COL_POINTER, &loc, -1); + + if (!loc) + { + return FALSE; + } + + if (!weather_location_equal(loc, pref->priv->applet->mateweather_pref.location)) + { + return FALSE; + } + + view = GTK_TREE_VIEW(pref->priv->tree); + gtk_tree_view_expand_to_path(view, path); + gtk_tree_view_set_cursor(view, path, NULL, FALSE); + gtk_tree_view_scroll_to_cell(view, path, NULL, TRUE, 0.5, 0.5); + + return TRUE; +} + +static void load_locations(MateWeatherPref* pref) +{ + GtkTreeView* tree = GTK_TREE_VIEW(pref->priv->tree); + GtkTreeViewColumn* column; + GtkCellRenderer* cell_renderer; + + /* Add a column for the locations */ + cell_renderer = gtk_cell_renderer_text_new(); + column = gtk_tree_view_column_new_with_attributes("not used", cell_renderer, "text", MATEWEATHER_XML_COL_LOC, NULL); + gtk_tree_view_append_column(tree, column); + gtk_tree_view_set_expander_column(GTK_TREE_VIEW(tree), column); + + /* load locations from xml file */ + pref->priv->model = mateweather_xml_load_locations(); + + if (!pref->priv->model) + { + GtkWidget* d = gtk_message_dialog_new(NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Failed to load the Locations XML database. Please report this as a bug.")); + gtk_dialog_run(GTK_DIALOG(d)); + gtk_widget_destroy(d); + } + + gtk_tree_view_set_model (tree, pref->priv->model); + + if (pref->priv->applet->mateweather_pref.location) + { + /* Select the current (default) location */ + gtk_tree_model_foreach(GTK_TREE_MODEL(pref->priv->model), compare_location, pref); + } +} + +static void show_notifications_toggled(GtkToggleButton* button, MateWeatherPref* pref) +{ + MateWeatherApplet* gw_applet = pref->priv->applet; + + gboolean toggled = gtk_toggle_button_get_active(button); + + if (toggled != gw_applet->mateweather_pref.show_notifications) + { + /* sync with mateweather_pref struct */ + gw_applet->mateweather_pref.show_notifications = toggled; + + /* sync with gsettings */ + g_settings_set_boolean (gw_applet->settings, "show-notifications", toggled); + } +} + +static void auto_update_toggled(GtkToggleButton* button, MateWeatherPref* pref) +{ + MateWeatherApplet* gw_applet = pref->priv->applet; + gboolean toggled; + gint nxtSunEvent; + + toggled = gtk_toggle_button_get_active(button); + gw_applet->mateweather_pref.update_enabled = toggled; + soft_set_sensitive(pref->priv->basic_update_spin, toggled); + g_settings_set_boolean (gw_applet->settings, "auto-update", toggled); + + if (gw_applet->timeout_tag > 0) + { + g_source_remove(gw_applet->timeout_tag); + } + + if (gw_applet->suncalc_timeout_tag > 0) + { + g_source_remove(gw_applet->suncalc_timeout_tag); + } + + if (gw_applet->mateweather_pref.update_enabled) + { + gw_applet->timeout_tag = g_timeout_add_seconds(gw_applet->mateweather_pref.update_interval, timeout_cb, gw_applet); + nxtSunEvent = weather_info_next_sun_event(gw_applet->mateweather_info); + + if (nxtSunEvent >= 0) + { + gw_applet->suncalc_timeout_tag = g_timeout_add_seconds(nxtSunEvent, suncalc_timeout_cb, gw_applet); + } + } +} + +static void temp_combo_changed_cb(GtkComboBox* combo, MateWeatherPref* pref) +{ + MateWeatherApplet* gw_applet = pref->priv->applet; + TempUnit new_unit, old_unit; + + g_return_if_fail(gw_applet != NULL); + + new_unit = gtk_combo_box_get_active(combo) + 2; + + old_unit = gw_applet->mateweather_pref.temperature_unit; + + if (new_unit == old_unit) + { + return; + } + + gw_applet->mateweather_pref.temperature_unit = new_unit; + + g_settings_set_enum (gw_applet->settings, "temperature-unit", new_unit); + + gtk_label_set_text(GTK_LABEL(gw_applet->label), weather_info_get_temp_summary(gw_applet->mateweather_info)); + + if (gw_applet->details_dialog) + { + mateweather_dialog_update(MATEWEATHER_DIALOG(gw_applet->details_dialog)); + } +} + +static void speed_combo_changed_cb(GtkComboBox* combo, MateWeatherPref* pref) +{ + MateWeatherApplet* gw_applet = pref->priv->applet; + SpeedUnit new_unit, old_unit; + + g_return_if_fail(gw_applet != NULL); + + new_unit = gtk_combo_box_get_active(combo) + 2; + + old_unit = gw_applet->mateweather_pref.speed_unit; + + if (new_unit == old_unit) + { + return; + } + + gw_applet->mateweather_pref.speed_unit = new_unit; + + g_settings_set_enum (gw_applet->settings, "speed-unit", new_unit); + + if (gw_applet->details_dialog) + { + mateweather_dialog_update(MATEWEATHER_DIALOG(gw_applet->details_dialog)); + } +} + +static void pres_combo_changed_cb(GtkComboBox* combo, MateWeatherPref* pref) +{ + MateWeatherApplet* gw_applet = pref->priv->applet; + PressureUnit new_unit, old_unit; + + g_return_if_fail(gw_applet != NULL); + + new_unit = gtk_combo_box_get_active(combo) + 2; + + old_unit = gw_applet->mateweather_pref.pressure_unit; + + if (new_unit == old_unit) + { + return; + } + + gw_applet->mateweather_pref.pressure_unit = new_unit; + + g_settings_set_enum (gw_applet->settings, "pressure-unit", new_unit); + + if (gw_applet->details_dialog) + { + mateweather_dialog_update(MATEWEATHER_DIALOG(gw_applet->details_dialog)); + } +} + +static void dist_combo_changed_cb(GtkComboBox* combo, MateWeatherPref* pref) +{ + MateWeatherApplet* gw_applet = pref->priv->applet; + DistanceUnit new_unit, old_unit; + + g_return_if_fail(gw_applet != NULL); + + new_unit = gtk_combo_box_get_active(combo) + 2; + + old_unit = gw_applet->mateweather_pref.distance_unit; + + if (new_unit == old_unit) + { + return; + } + + gw_applet->mateweather_pref.distance_unit = new_unit; + + g_settings_set_enum (gw_applet->settings, "distance-unit", new_unit); + + if (gw_applet->details_dialog) + { + mateweather_dialog_update(MATEWEATHER_DIALOG(gw_applet->details_dialog)); + } +} + +static void radar_toggled(GtkToggleButton* button, MateWeatherPref* pref) +{ + MateWeatherApplet* gw_applet = pref->priv->applet; + gboolean toggled; + + toggled = gtk_toggle_button_get_active(button); + gw_applet->mateweather_pref.radar_enabled = toggled; + g_settings_set_boolean (gw_applet->settings, "enable-radar-map", toggled); + soft_set_sensitive(pref->priv->basic_radar_url_btn, toggled); + + if (toggled == FALSE || gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (pref->priv->basic_radar_url_btn)) == TRUE) + { + soft_set_sensitive (pref->priv->basic_radar_url_hbox, toggled); + } +} + +static void use_radar_url_toggled(GtkToggleButton* button, MateWeatherPref* pref) +{ + MateWeatherApplet* gw_applet = pref->priv->applet; + gboolean toggled; + + toggled = gtk_toggle_button_get_active(button); + gw_applet->mateweather_pref.use_custom_radar_url = toggled; + g_settings_set_boolean (gw_applet->settings, "use-custom-radar-url", toggled); + soft_set_sensitive(pref->priv->basic_radar_url_hbox, toggled); +} + +static gboolean radar_url_changed(GtkWidget* widget, GdkEventFocus* event, MateWeatherPref* pref) +{ + MateWeatherApplet* gw_applet = pref->priv->applet; + gchar *text; + + text = gtk_editable_get_chars(GTK_EDITABLE(widget), 0, -1); + + if (gw_applet->mateweather_pref.radar) + { + g_free(gw_applet->mateweather_pref.radar); + } + + if (text) + { + gw_applet->mateweather_pref.radar = g_strdup(text); + g_free (text); + } + else + { + gw_applet->mateweather_pref.radar = NULL; + } + + g_settings_set_string (gw_applet->settings, "radar", gw_applet->mateweather_pref.radar); + + return FALSE; +} + +static void update_interval_changed(GtkSpinButton* button, MateWeatherPref* pref) +{ + MateWeatherApplet* gw_applet = pref->priv->applet; + + gw_applet->mateweather_pref.update_interval = gtk_spin_button_get_value_as_int(button)*60; + g_settings_set_int (gw_applet->settings, "auto-update-interval", gw_applet->mateweather_pref.update_interval); + + if (gw_applet->timeout_tag > 0) + { + g_source_remove(gw_applet->timeout_tag); + } + + if (gw_applet->mateweather_pref.update_enabled) + { + gw_applet->timeout_tag = g_timeout_add_seconds(gw_applet->mateweather_pref.update_interval, timeout_cb, gw_applet); + } +} + +static gboolean free_data(GtkTreeModel* model, GtkTreePath* path, GtkTreeIter* iter, gpointer data) +{ + WeatherLocation* location; + + gtk_tree_model_get(model, iter, MATEWEATHER_XML_COL_POINTER, &location, -1); + + if (!location) + { + return FALSE; + } + + weather_location_free(location); + + return FALSE; +} + + +static GtkWidget* create_hig_category(GtkWidget* main_box, gchar* title) +{ + GtkWidget* vbox; + GtkWidget* vbox2; + GtkWidget* hbox; + GtkWidget*label; + gchar* tmp; + + vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6); + gtk_box_pack_start (GTK_BOX (main_box), vbox, FALSE, FALSE, 0); + + tmp = g_strdup_printf ("<b>%s</b>", title); + label = gtk_label_new (NULL); + gtk_label_set_xalign (GTK_LABEL (label), 0.0); + gtk_label_set_markup (GTK_LABEL (label), tmp); + g_free (tmp); + gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, FALSE, 0); + + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); + gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); + + label = gtk_label_new (" "); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); + + vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6); + gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 0); + + return vbox2; +} + +static gboolean find_location(GtkTreeModel* model, GtkTreeIter* iter, const gchar* location, gboolean go_parent) +{ + GtkTreeIter iter_child; + GtkTreeIter iter_parent; + gchar* aux_loc; + gboolean valid; + int len; + + len = strlen (location); + + if (len <= 0) + { + return FALSE; + } + + do { + + gtk_tree_model_get (model, iter, MATEWEATHER_XML_COL_LOC, &aux_loc, -1); + + if (g_ascii_strncasecmp (aux_loc, location, len) == 0) + { + g_free (aux_loc); + return TRUE; + } + + if (gtk_tree_model_iter_has_child(model, iter)) + { + gtk_tree_model_iter_nth_child(model, &iter_child, iter, 0); + + if (find_location (model, &iter_child, location, FALSE)) + { + /* Manual copying of the iter */ + iter->stamp = iter_child.stamp; + iter->user_data = iter_child.user_data; + iter->user_data2 = iter_child.user_data2; + iter->user_data3 = iter_child.user_data3; + + g_free (aux_loc); + + return TRUE; + } + } + + g_free (aux_loc); + + valid = gtk_tree_model_iter_next(model, iter); + + } while (valid); + + if (go_parent) + { + iter_parent = *iter; + + while (gtk_tree_model_iter_parent (model, iter, &iter_parent)) + { + if (gtk_tree_model_iter_next (model, iter)) + { + return find_location (model, iter, location, TRUE); + } + + iter_parent = *iter; + } + } + + return FALSE; +} + +static void find_next_clicked(GtkButton* button, MateWeatherPref* pref) +{ + GtkTreeView *tree; + GtkTreeModel *model; + GtkEntry *entry; + GtkTreeSelection *selection; + GtkTreeIter iter; + GtkTreeIter iter_parent; + GtkTreePath *path; + const gchar *location; + + tree = GTK_TREE_VIEW (pref->priv->tree); + model = gtk_tree_view_get_model (tree); + entry = GTK_ENTRY (pref->priv->find_entry); + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree)); + + if (gtk_tree_selection_count_selected_rows (selection) >= 1) + { + gtk_tree_selection_get_selected (selection, &model, &iter); + /* Select next or select parent */ + if (!gtk_tree_model_iter_next (model, &iter)) + { + iter_parent = iter; + + if (!gtk_tree_model_iter_parent (model, &iter, &iter_parent) || !gtk_tree_model_iter_next (model, &iter)) + { + gtk_tree_model_get_iter_first (model, &iter); + } + } + + } + else + { + gtk_tree_model_get_iter_first (model, &iter); + } + + location = gtk_entry_get_text (entry); + + if (find_location (model, &iter, location, TRUE)) + { + gtk_widget_set_sensitive (pref->priv->find_next_btn, TRUE); + + path = gtk_tree_model_get_path (model, &iter); + gtk_tree_view_expand_to_path (tree, path); + gtk_tree_selection_select_path (selection, path); + gtk_tree_view_scroll_to_cell (tree, path, NULL, TRUE, 0.5, 0); + + gtk_tree_path_free (path); + } + else + { + gtk_widget_set_sensitive (pref->priv->find_next_btn, FALSE); + } +} + +static void find_entry_changed(GtkEditable* entry, MateWeatherPref* pref) +{ + GtkTreeView *tree; + GtkTreeModel *model; + GtkTreeSelection *selection; + GtkTreeIter iter; + GtkTreePath *path; + const gchar *location; + + tree = GTK_TREE_VIEW (pref->priv->tree); + model = gtk_tree_view_get_model (tree); + + g_return_if_fail (model != NULL); + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree)); + gtk_tree_model_get_iter_first (model, &iter); + + location = gtk_entry_get_text (GTK_ENTRY (entry)); + + if (find_location (model, &iter, location, TRUE)) + { + gtk_widget_set_sensitive (pref->priv->find_next_btn, TRUE); + + path = gtk_tree_model_get_path (model, &iter); + gtk_tree_view_expand_to_path (tree, path); + gtk_tree_selection_select_iter (selection, &iter); + gtk_tree_view_scroll_to_cell (tree, path, NULL, TRUE, 0.5, 0); + + gtk_tree_path_free (path); + } + else + { + gtk_widget_set_sensitive (pref->priv->find_next_btn, FALSE); + } +} + + +static void help_cb(GtkDialog* dialog, MateWeatherPref* pref) +{ + gint current_page; + gchar *uri; + GError* error = NULL; + + current_page = gtk_notebook_get_current_page (GTK_NOTEBOOK (pref->priv->notebook)); + uri = g_strdup_printf ("help:mateweather/mateweather-prefs#mateweather-%s", (current_page == 0) ? "metric" : "change-location"); + gtk_show_uri_on_window (GTK_WINDOW (dialog), + uri, + gtk_get_current_event_time (), + &error); + g_free (uri); + + if (error) + { + GtkWidget* error_dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, _("There was an error displaying help: %s"), error->message); + g_signal_connect (G_OBJECT (error_dialog), "response", G_CALLBACK (gtk_widget_destroy), NULL); + gtk_window_set_resizable (GTK_WINDOW (error_dialog), FALSE); + gtk_window_set_screen (GTK_WINDOW (error_dialog), gtk_widget_get_screen (GTK_WIDGET (dialog))); + gtk_widget_show (error_dialog); + g_error_free (error); + error = NULL; + } +} + + +static void response_cb(GtkDialog* dialog, gint id, MateWeatherPref* pref) +{ + if (id == GTK_RESPONSE_HELP) + { + help_cb(dialog, pref); + } + else + { + gtk_widget_destroy(GTK_WIDGET(dialog)); + } +} + + +static void mateweather_pref_create(MateWeatherPref* pref) +{ + GtkWidget* pref_vbox; + #ifdef RADARMAP + GtkWidget* radar_toggle_hbox; + #endif /* RADARMAP */ + GtkWidget* pref_basic_update_lbl; + GtkWidget* pref_basic_update_hbox; + GtkAdjustment* pref_basic_update_spin_adj; + GtkWidget* pref_basic_update_sec_lbl; + GtkWidget* pref_basic_note_lbl; + GtkWidget* pref_loc_hbox; + GtkWidget* pref_loc_note_lbl; + GtkWidget* scrolled_window; + GtkWidget* label; + GtkWidget* value_hbox; + GtkWidget* tree_label; + GtkTreeSelection *selection; + GtkWidget* pref_basic_vbox; + GtkWidget* vbox; + GtkWidget* frame; + GtkWidget* temp_label; + GtkWidget* temp_combo; + GtkWidget* speed_label; + GtkWidget* speed_combo; + GtkWidget* pres_label; + GtkWidget* pres_combo; + GtkWidget* dist_label; + GtkWidget* dist_combo; + GtkWidget* unit_grid; + GtkWidget* pref_find_label; + GtkWidget* pref_find_hbox; + GtkWidget* image; + + + g_object_set (pref, "destroy-with-parent", TRUE, NULL); + gtk_window_set_title (GTK_WINDOW (pref), _("Weather Preferences")); + gtk_dialog_add_buttons (GTK_DIALOG (pref), "gtk-close", GTK_RESPONSE_CLOSE, "gtk-help", GTK_RESPONSE_HELP, NULL); + gtk_dialog_set_default_response (GTK_DIALOG (pref), GTK_RESPONSE_CLOSE); + gtk_container_set_border_width (GTK_CONTAINER (pref), 5); + gtk_window_set_resizable (GTK_WINDOW (pref), TRUE); + gtk_window_set_screen (GTK_WINDOW (pref), gtk_widget_get_screen (GTK_WIDGET (pref->priv->applet->applet))); + + pref_vbox = gtk_dialog_get_content_area (GTK_DIALOG (pref)); + gtk_box_set_spacing (GTK_BOX (pref_vbox), 2); + gtk_widget_show (pref_vbox); + + pref->priv->notebook = gtk_notebook_new (); + gtk_container_set_border_width (GTK_CONTAINER (pref->priv->notebook), 5); + gtk_widget_show (pref->priv->notebook); + gtk_box_pack_start (GTK_BOX (pref_vbox), pref->priv->notebook, TRUE, TRUE, 0); + + /* + * General settings page. + */ + + pref_basic_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 18); + gtk_container_set_border_width (GTK_CONTAINER (pref_basic_vbox), 12); + gtk_container_add (GTK_CONTAINER (pref->priv->notebook), pref_basic_vbox); + + pref->priv->basic_update_btn = gtk_check_button_new_with_mnemonic (_("_Automatically update every:")); + gtk_widget_set_halign (pref->priv->basic_update_btn, GTK_ALIGN_START); + gtk_widget_set_vexpand (pref->priv->basic_update_btn, TRUE); + gtk_widget_show (pref->priv->basic_update_btn); + g_signal_connect (G_OBJECT (pref->priv->basic_update_btn), "toggled", G_CALLBACK (auto_update_toggled), pref); + + if (!g_settings_is_writable (pref->priv->applet->settings, "auto-update")) + { + hard_set_sensitive (pref->priv->basic_update_btn, FALSE); + } + + /* + * Units settings page. + */ + + /* Temperature Unit */ + temp_label = gtk_label_new_with_mnemonic (_("_Temperature unit:")); + gtk_label_set_use_markup (GTK_LABEL (temp_label), TRUE); + gtk_label_set_justify (GTK_LABEL (temp_label), GTK_JUSTIFY_LEFT); + gtk_label_set_xalign (GTK_LABEL (temp_label), 0.0); + gtk_widget_show (temp_label); + + temp_combo = gtk_combo_box_text_new (); + pref->priv->basic_temp_combo = temp_combo; + gtk_label_set_mnemonic_widget (GTK_LABEL (temp_label), temp_combo); + //gtk_combo_box_append_text (GTK_COMBO_BOX (temp_combo), _("Default")); + gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (temp_combo), _("Kelvin")); + /* TRANSLATORS: Celsius is sometimes referred Centigrade */ + gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (temp_combo), _("Celsius")); + gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (temp_combo), _("Fahrenheit")); + gtk_widget_show (temp_combo); + + if ( ! g_settings_is_writable (pref->priv->applet->settings, "temperature-unit")) + { + hard_set_sensitive (pref->priv->basic_temp_combo, FALSE); + } + + /* Speed Unit */ + speed_label = gtk_label_new_with_mnemonic (_("_Wind speed unit:")); + gtk_label_set_use_markup (GTK_LABEL (speed_label), TRUE); + gtk_label_set_justify (GTK_LABEL (speed_label), GTK_JUSTIFY_LEFT); + gtk_label_set_xalign (GTK_LABEL (speed_label), 0.0); + gtk_widget_show (speed_label); + + speed_combo = gtk_combo_box_text_new (); + pref->priv->basic_speed_combo = speed_combo; + gtk_label_set_mnemonic_widget (GTK_LABEL (speed_label), speed_combo); + //gtk_combo_box_append_text (GTK_COMBO_BOX (speed_combo), _("Default")); + /* TRANSLATOR: The wind speed unit "meters per second" */ + gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (speed_combo), _("m/s")); + /* TRANSLATOR: The wind speed unit "kilometers per hour" */ + gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (speed_combo), _("km/h")); + /* TRANSLATOR: The wind speed unit "miles per hour" */ + gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (speed_combo), _("mph")); + /* TRANSLATOR: The wind speed unit "knots" */ + gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (speed_combo), _("knots")); + gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (speed_combo), _("Beaufort scale")); + gtk_widget_show (speed_combo); + + if (!g_settings_is_writable (pref->priv->applet->settings, "speed-unit")) + { + hard_set_sensitive (pref->priv->basic_speed_combo, FALSE); + } + + /* Pressure Unit */ + pres_label = gtk_label_new_with_mnemonic (_("_Pressure unit:")); + gtk_label_set_use_markup (GTK_LABEL (pres_label), TRUE); + gtk_label_set_justify (GTK_LABEL (pres_label), GTK_JUSTIFY_LEFT); + gtk_label_set_xalign (GTK_LABEL (pres_label), 0.0); + gtk_widget_show (pres_label); + + pres_combo = gtk_combo_box_text_new (); + pref->priv->basic_pres_combo = pres_combo; + gtk_label_set_mnemonic_widget (GTK_LABEL (pres_label), pres_combo); + //gtk_combo_box_append_text (GTK_COMBO_BOX (pres_combo), _("Default")); + /* TRANSLATOR: The pressure unit "kiloPascals" */ + gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (pres_combo), _("kPa")); + /* TRANSLATOR: The pressure unit "hectoPascals" */ + gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (pres_combo), _("hPa")); + /* TRANSLATOR: The pressure unit "millibars" */ + gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (pres_combo), _("mb")); + /* TRANSLATOR: The pressure unit "millibars of mercury" */ + gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (pres_combo), _("mmHg")); + /* TRANSLATOR: The pressure unit "inches of mercury" */ + gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (pres_combo), _("inHg")); + /* TRANSLATOR: The pressure unit "atmospheres" */ + gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (pres_combo), _("atm")); + gtk_widget_show (pres_combo); + + if (!g_settings_is_writable(pref->priv->applet->settings, "pressure-unit")) + { + hard_set_sensitive(pref->priv->basic_pres_combo, FALSE); + } + + /* Distance Unit */ + dist_label = gtk_label_new_with_mnemonic (_("_Visibility unit:")); + gtk_label_set_use_markup (GTK_LABEL (dist_label), TRUE); + gtk_label_set_justify (GTK_LABEL (dist_label), GTK_JUSTIFY_LEFT); + gtk_label_set_xalign (GTK_LABEL (dist_label), 0.0); + gtk_widget_show (dist_label); + + dist_combo = gtk_combo_box_text_new (); + pref->priv->basic_dist_combo = dist_combo; + gtk_label_set_mnemonic_widget (GTK_LABEL (dist_label), dist_combo); + //gtk_combo_box_append_text (GTK_COMBO_BOX (dist_combo), _("Default")); + /* TRANSLATOR: The distance unit "meters" */ + gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (dist_combo), _("meters")); + /* TRANSLATOR: The distance unit "kilometers" */ + gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (dist_combo), _("km")); + /* TRANSLATOR: The distance unit "miles" */ + gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (dist_combo), _("miles")); + gtk_widget_show (dist_combo); + + if ( ! g_settings_is_writable (pref->priv->applet->settings, "distance-unit")) + hard_set_sensitive (pref->priv->basic_dist_combo, FALSE); + + unit_grid = gtk_grid_new (); + gtk_grid_set_row_spacing(GTK_GRID(unit_grid), 6); + gtk_grid_set_column_spacing(GTK_GRID(unit_grid), 12); + gtk_widget_set_halign (temp_label, GTK_ALIGN_START); + gtk_grid_attach(GTK_GRID(unit_grid), temp_label, 0, 0, 1, 1); + gtk_grid_attach(GTK_GRID(unit_grid), temp_combo, 1, 0, 1, 1); + gtk_widget_set_halign (speed_label, GTK_ALIGN_START); + gtk_grid_attach(GTK_GRID(unit_grid), speed_label, 0, 1, 1, 1); + gtk_grid_attach(GTK_GRID(unit_grid), speed_combo, 1, 1, 1, 1); + gtk_widget_set_halign (pres_label, GTK_ALIGN_START); + gtk_grid_attach(GTK_GRID(unit_grid), pres_label, 0, 2, 1, 1); + gtk_grid_attach(GTK_GRID(unit_grid), pres_combo, 1, 2, 1, 1); + gtk_widget_set_halign (dist_label, GTK_ALIGN_START); + gtk_grid_attach(GTK_GRID(unit_grid), dist_label, 0, 3, 1, 1); + gtk_grid_attach(GTK_GRID(unit_grid), dist_combo, 1, 3, 1, 1); + gtk_widget_show(unit_grid); + + g_signal_connect (temp_combo, "changed", G_CALLBACK (temp_combo_changed_cb), pref); + g_signal_connect (speed_combo, "changed", G_CALLBACK (speed_combo_changed_cb), pref); + g_signal_connect (dist_combo, "changed", G_CALLBACK (dist_combo_changed_cb), pref); + g_signal_connect (pres_combo, "changed", G_CALLBACK (pres_combo_changed_cb), pref); + + + #ifdef RADARMAP + pref->priv->basic_radar_btn = gtk_check_button_new_with_mnemonic (_("Enable _radar map")); + gtk_widget_show (pref->priv->basic_radar_btn); + g_signal_connect (G_OBJECT (pref->priv->basic_radar_btn), "toggled", G_CALLBACK (radar_toggled), pref); + + if (!g_settings_is_writable (pref->priv->applet->settings, "enable-radar-map")) + { + hard_set_sensitive(pref->priv->basic_radar_btn, FALSE); + } + + radar_toggle_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12); + gtk_widget_show(radar_toggle_hbox); + + label = gtk_label_new (" "); + gtk_widget_show (label); + gtk_box_pack_start (GTK_BOX (radar_toggle_hbox), label, FALSE, FALSE, 0); + + pref->priv->basic_radar_url_btn = gtk_check_button_new_with_mnemonic (_("Use _custom address for radar map")); + gtk_widget_show (pref->priv->basic_radar_url_btn); + gtk_box_pack_start (GTK_BOX (radar_toggle_hbox), pref->priv->basic_radar_url_btn, FALSE, FALSE, 0); + + g_signal_connect (G_OBJECT (pref->priv->basic_radar_url_btn), "toggled", G_CALLBACK (use_radar_url_toggled), pref); + + if ( ! g_settings_is_writable (pref->priv->applet->settings, "use-custom-radar-url")) + { + hard_set_sensitive (pref->priv->basic_radar_url_btn, FALSE); + } + + pref->priv->basic_radar_url_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12); + gtk_widget_show (pref->priv->basic_radar_url_hbox); + + label = gtk_label_new (" "); + gtk_widget_show (label); + gtk_box_pack_start (GTK_BOX (pref->priv->basic_radar_url_hbox), label, FALSE, FALSE, 0); + + label = gtk_label_new_with_mnemonic (_("A_ddress:")); + gtk_widget_show (label); + gtk_box_pack_start (GTK_BOX (pref->priv->basic_radar_url_hbox), label, FALSE, FALSE, 0); + pref->priv->basic_radar_url_entry = gtk_entry_new (); + gtk_widget_show (pref->priv->basic_radar_url_entry); + gtk_box_pack_start (GTK_BOX (pref->priv->basic_radar_url_hbox), pref->priv->basic_radar_url_entry, TRUE, TRUE, 0); + g_signal_connect (G_OBJECT (pref->priv->basic_radar_url_entry), "focus_out_event", G_CALLBACK (radar_url_changed), pref); + if ( ! g_settings_is_writable (pref->priv->applet->settings, "radar")) + { + hard_set_sensitive (pref->priv->basic_radar_url_entry, FALSE); + } + #endif /* RADARMAP */ + + #ifdef HAVE_LIBNOTIFY + /* setup show-notifications button */ + pref->priv->basic_show_notifications_btn = gtk_check_button_new_with_mnemonic (_("Show _notifications")); + + if (!g_settings_is_writable (pref->priv->applet->settings, "show-notifications")) + { + hard_set_sensitive (pref->priv->basic_show_notifications_btn, FALSE); + } + + g_signal_connect (G_OBJECT (pref->priv->basic_show_notifications_btn), "toggled", G_CALLBACK (show_notifications_toggled), pref); + #endif + + frame = create_hig_category (pref_basic_vbox, _("Update")); + + pref_basic_update_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12); + + pref_basic_update_lbl = gtk_label_new_with_mnemonic (_("_Automatically update every:")); + gtk_widget_show (pref_basic_update_lbl); + + gtk_widget_show (pref_basic_update_hbox); + + pref_basic_update_spin_adj = gtk_adjustment_new (30, 1, 3600, 5, 25, 1); + pref->priv->basic_update_spin = gtk_spin_button_new (pref_basic_update_spin_adj, 1, 0); + gtk_widget_show (pref->priv->basic_update_spin); + + gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (pref->priv->basic_update_spin), TRUE); + gtk_spin_button_set_update_policy (GTK_SPIN_BUTTON (pref->priv->basic_update_spin), GTK_UPDATE_IF_VALID); + g_signal_connect (G_OBJECT (pref->priv->basic_update_spin), "value_changed", G_CALLBACK (update_interval_changed), pref); + + pref_basic_update_sec_lbl = gtk_label_new (_("minutes")); + gtk_widget_show (pref_basic_update_sec_lbl); + + if ( ! g_settings_is_writable (pref->priv->applet->settings, "auto-update-interval")) + { + hard_set_sensitive (pref->priv->basic_update_spin, FALSE); + hard_set_sensitive (pref_basic_update_sec_lbl, FALSE); + } + + value_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); + + gtk_box_pack_start (GTK_BOX (pref_basic_update_hbox), pref->priv->basic_update_btn, FALSE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (pref_basic_update_hbox), value_hbox, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (value_hbox), pref->priv->basic_update_spin, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (value_hbox), pref_basic_update_sec_lbl, FALSE, FALSE, 0); + + gtk_container_add (GTK_CONTAINER (frame), pref_basic_update_hbox); + + frame = create_hig_category (pref_basic_vbox, _("Display")); + + vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6); + + gtk_box_pack_start (GTK_BOX (vbox), unit_grid, TRUE, TRUE, 0); + + #ifdef RADARMAP + gtk_box_pack_start (GTK_BOX (vbox), pref->priv->basic_radar_btn, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (vbox), radar_toggle_hbox, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (vbox), pref->priv->basic_radar_url_hbox, TRUE, TRUE, 0); + #endif /* RADARMAP */ + + #ifdef HAVE_LIBNOTIFY + /* add the show-notification toggle button to the vbox of the display section */ + gtk_box_pack_start (GTK_BOX (vbox), pref->priv->basic_show_notifications_btn, TRUE, TRUE, 0); + #endif + + gtk_container_add (GTK_CONTAINER (frame), vbox); + + pref_basic_note_lbl = gtk_label_new (_("General")); + gtk_widget_show (pref_basic_note_lbl); + gtk_notebook_set_tab_label (GTK_NOTEBOOK (pref->priv->notebook), gtk_notebook_get_nth_page (GTK_NOTEBOOK (pref->priv->notebook), 0), pref_basic_note_lbl); + + /* + * Location page. + */ + pref_loc_hbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6); + gtk_container_set_border_width (GTK_CONTAINER (pref_loc_hbox), 12); + gtk_container_add (GTK_CONTAINER (pref->priv->notebook), pref_loc_hbox); + + tree_label = gtk_label_new_with_mnemonic (_("_Select a location:")); + gtk_label_set_xalign (GTK_LABEL (tree_label), 0.0); + gtk_box_pack_start (GTK_BOX (pref_loc_hbox), tree_label, FALSE, FALSE, 0); + + scrolled_window = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window), GTK_SHADOW_IN); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + + pref->priv->tree = gtk_tree_view_new (); + gtk_label_set_mnemonic_widget (GTK_LABEL (tree_label), GTK_WIDGET (pref->priv->tree)); + gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (pref->priv->tree), FALSE); + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (pref->priv->tree)); + g_signal_connect (G_OBJECT (selection), "changed", G_CALLBACK (row_selected_cb), pref); + + gtk_container_add (GTK_CONTAINER (scrolled_window), pref->priv->tree); + gtk_widget_show (pref->priv->tree); + gtk_widget_show (scrolled_window); + gtk_box_pack_start (GTK_BOX (pref_loc_hbox), scrolled_window, TRUE, TRUE, 0); + load_locations(pref); + + pref_find_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); + pref_find_label = gtk_label_new (_("_Find:")); + gtk_label_set_use_underline (GTK_LABEL (pref_find_label), TRUE); + + pref->priv->find_entry = gtk_entry_new (); + gtk_label_set_mnemonic_widget (GTK_LABEL (pref_find_label), pref->priv->find_entry); + + pref->priv->find_next_btn = gtk_button_new_with_mnemonic (_("Find _Next")); + gtk_widget_set_sensitive (pref->priv->find_next_btn, FALSE); + + image = gtk_image_new_from_icon_name ("edit-find", GTK_ICON_SIZE_BUTTON); + gtk_button_set_image (GTK_BUTTON (pref->priv->find_next_btn), image); + + g_signal_connect (G_OBJECT (pref->priv->find_next_btn), "clicked", G_CALLBACK (find_next_clicked), pref); + g_signal_connect (G_OBJECT (pref->priv->find_entry), "changed", G_CALLBACK (find_entry_changed), pref); + + gtk_container_set_border_width (GTK_CONTAINER (pref_find_hbox), 0); + gtk_box_pack_start (GTK_BOX (pref_find_hbox), pref_find_label, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (pref_find_hbox), pref->priv->find_entry, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (pref_find_hbox), pref->priv->find_next_btn, FALSE, FALSE, 0); + + gtk_box_pack_start (GTK_BOX (pref_loc_hbox), pref_find_hbox, FALSE, FALSE, 0); + + if ( ! g_settings_is_writable (pref->priv->applet->settings, "location0")) + { + hard_set_sensitive (scrolled_window, FALSE); + } + + pref_loc_note_lbl = gtk_label_new (_("Location")); + gtk_widget_show (pref_loc_note_lbl); + gtk_notebook_set_tab_label (GTK_NOTEBOOK (pref->priv->notebook), gtk_notebook_get_nth_page (GTK_NOTEBOOK (pref->priv->notebook), 1), pref_loc_note_lbl); + + + g_signal_connect (G_OBJECT (pref), "response", G_CALLBACK (response_cb), pref); + + mateweather_pref_set_accessibility (pref); + gtk_label_set_mnemonic_widget (GTK_LABEL (pref_basic_update_sec_lbl), pref->priv->basic_update_spin); + gtk_label_set_mnemonic_widget (GTK_LABEL (label), pref->priv->basic_radar_url_entry); +} + + +static void mateweather_pref_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec *pspec) +{ + MateWeatherPref* pref = MATEWEATHER_PREF(object); + + switch (prop_id) { + case PROP_MATEWEATHER_APPLET: + pref->priv->applet = g_value_get_pointer(value); + break; + default: + /* We don't have any other property... */ + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + + +static void mateweather_pref_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) +{ + MateWeatherPref* pref = MATEWEATHER_PREF(object); + + switch (prop_id) { + case PROP_MATEWEATHER_APPLET: + g_value_set_pointer(value, pref->priv->applet); + break; + default: + /* We don't have any other property... */ + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + + +static void mateweather_pref_init(MateWeatherPref* self) +{ + self->priv = mateweather_pref_get_instance_private(self); +} + + +static GObject* mateweather_pref_constructor(GType type, guint n_construct_params, GObjectConstructParam* construct_params) +{ + GObject* object; + MateWeatherPref* self; + + object = G_OBJECT_CLASS(mateweather_pref_parent_class)->constructor(type, n_construct_params, construct_params); + self = MATEWEATHER_PREF(object); + + mateweather_pref_create(self); + update_dialog(self); + + return object; +} + + +GtkWidget* mateweather_pref_new(MateWeatherApplet* applet) +{ + return g_object_new(MATEWEATHER_TYPE_PREF, "mateweather-applet", applet, NULL); +} + + +static void mateweather_pref_finalize(GObject* object) +{ + MateWeatherPref* self = MATEWEATHER_PREF(object); + + gtk_tree_model_foreach(self->priv->model, free_data, NULL); + g_object_unref(G_OBJECT(self->priv->model)); + + G_OBJECT_CLASS(mateweather_pref_parent_class)->finalize(object); +} + + +static void mateweather_pref_class_init(MateWeatherPrefClass* klass) +{ + GObjectClass* object_class = G_OBJECT_CLASS(klass); + + mateweather_pref_parent_class = g_type_class_peek_parent(klass); + + object_class->set_property = mateweather_pref_set_property; + object_class->get_property = mateweather_pref_get_property; + object_class->constructor = mateweather_pref_constructor; + object_class->finalize = mateweather_pref_finalize; + + /* This becomes an OBJECT property when MateWeatherApplet is redone */ + g_object_class_install_property(object_class, PROP_MATEWEATHER_APPLET, g_param_spec_pointer("mateweather-applet", "MateWeather Applet", "The MateWeather Applet", G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); +} + + diff --git a/mateweather/src/mateweather-pref.h b/mateweather/src/mateweather-pref.h new file mode 100644 index 00000000..f3cc901b --- /dev/null +++ b/mateweather/src/mateweather-pref.h @@ -0,0 +1,59 @@ +/* $Id$ */ + +/* + * Papadimitriou Spiros <[email protected]> + * + * This code released under the GNU GPL. + * Read the file COPYING for more information. + * + * Preferences dialog + * + */ + +#ifndef __MATEWEATHER_PREF_H_ +#define __MATEWEATHER_PREF_H_ + +#include <gtk/gtk.h> + +#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE + +#include "mateweather.h" + +G_BEGIN_DECLS + +#define MATEWEATHER_TYPE_PREF (mateweather_pref_get_type ()) +#define MATEWEATHER_PREF(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MATEWEATHER_TYPE_PREF, MateWeatherPref)) +#define MATEWEATHER_PREF_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MATEWEATHER_TYPE_PREF, MateWeatherPrefClass)) +#define MATEWEATHER_IS_PREF(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MATEWEATHER_TYPE_PREF)) +#define MATEWEATHER_IS_PREF_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MATEWEATHER_TYPE_PREF)) +#define MATEWEATHER_PREF_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MATEWEATHER_TYPE_PREF, MateWeatherPrefClass)) + +typedef struct _MateWeatherPref MateWeatherPref; +typedef struct _MateWeatherPrefPrivate MateWeatherPrefPrivate; +typedef struct _MateWeatherPrefClass MateWeatherPrefClass; + +struct _MateWeatherPref +{ + GtkDialog parent; + + /* private */ + MateWeatherPrefPrivate *priv; +}; + + +struct _MateWeatherPrefClass +{ + GtkDialogClass parent_class; +}; + +GType mateweather_pref_get_type (void); +GtkWidget *mateweather_pref_new (MateWeatherApplet *applet); + + +void set_access_namedesc (GtkWidget *widget, const gchar *name, const gchar *desc); + + +G_END_DECLS + +#endif /* __MATEWEATHER_PREF_H */ + diff --git a/mateweather/src/mateweather.h b/mateweather/src/mateweather.h new file mode 100644 index 00000000..fa492849 --- /dev/null +++ b/mateweather/src/mateweather.h @@ -0,0 +1,53 @@ +#ifndef __MATEWEATHER_H__ +#define __MATEWEATHER_H__ + +/* + * todd kulesza <[email protected]> + * + * This code released under the GNU GPL. + * Read the file COPYING for more information. + * + * main header file + * + */ +#include <glib/gi18n.h> + +#include <gio/gio.h> + +#include <mate-panel-applet.h> + +#include <libmateweather/mateweather-prefs.h> + +/* Radar map on by default. */ +#define RADARMAP + +G_BEGIN_DECLS + +typedef struct _MateWeatherApplet { + MatePanelApplet* applet; + WeatherInfo* mateweather_info; + + GSettings* settings; + + GtkWidget* container; + GtkWidget* box; + GtkWidget* label; + GtkWidget* image; + + MatePanelAppletOrient orient; + gint size; + gint timeout_tag; + gint suncalc_timeout_tag; + + /* preferences */ + MateWeatherPrefs mateweather_pref; + + GtkWidget* pref_dialog; + + /* dialog stuff */ + GtkWidget* details_dialog; +} MateWeatherApplet; + +G_END_DECLS + +#endif |