From fe8aea1c3b5348347633da18a02b0bffd3b266a1 Mon Sep 17 00:00:00 2001 From: Perberos Date: Thu, 1 Dec 2011 21:42:39 -0300 Subject: moving from https://github.com/perberos/mate-desktop-environment --- libmateweather/timezone-menu.c | 415 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 415 insertions(+) create mode 100644 libmateweather/timezone-menu.c (limited to 'libmateweather/timezone-menu.c') diff --git a/libmateweather/timezone-menu.c b/libmateweather/timezone-menu.c new file mode 100644 index 0000000..eb34931 --- /dev/null +++ b/libmateweather/timezone-menu.c @@ -0,0 +1,415 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* timezone-menu.c - Timezone-selecting menu + * + * Copyright 2008, Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see + * . + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE +#include "timezone-menu.h" +#include "weather-priv.h" + +#include + +/** + * MateWeatherTimezoneMenu: + * + * A #GtkComboBox subclass for choosing a #MateWeatherTimezone + **/ + +G_DEFINE_TYPE (MateWeatherTimezoneMenu, mateweather_timezone_menu, GTK_TYPE_COMBO_BOX) + +enum { + PROP_0, + + PROP_TOP, + PROP_TZID, + + LAST_PROP +}; + +static void set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec); +static void get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec); + +static void changed (GtkComboBox *combo); + +static GtkTreeModel *mateweather_timezone_model_new (MateWeatherLocation *top); +static gboolean row_separator_func (GtkTreeModel *model, GtkTreeIter *iter, + gpointer data); +static void is_sensitive (GtkCellLayout *cell_layout, GtkCellRenderer *cell, + GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data); + +static void +mateweather_timezone_menu_init (MateWeatherTimezoneMenu *menu) +{ + GtkCellRenderer *renderer; + + gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (menu), + row_separator_func, NULL, NULL); + + renderer = gtk_cell_renderer_text_new (); + gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (menu), renderer, TRUE); + gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (menu), renderer, + "markup", 0, + NULL); + gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (menu), + renderer, is_sensitive, NULL, NULL); +} + +static void +finalize (GObject *object) +{ + MateWeatherTimezoneMenu *menu = MATEWEATHER_TIMEZONE_MENU (object); + + if (menu->zone) + mateweather_timezone_unref (menu->zone); + + G_OBJECT_CLASS (mateweather_timezone_menu_parent_class)->finalize (object); +} + +static void +mateweather_timezone_menu_class_init (MateWeatherTimezoneMenuClass *timezone_menu_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (timezone_menu_class); + GtkComboBoxClass *combo_class = GTK_COMBO_BOX_CLASS (timezone_menu_class); + + object_class->finalize = finalize; + object_class->set_property = set_property; + object_class->get_property = get_property; + + combo_class->changed = changed; + + /* properties */ + g_object_class_install_property ( + object_class, PROP_TOP, + g_param_spec_pointer ("top", + "Top Location", + "The MateWeatherLocation whose children will be used to fill in the menu", + G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); + g_object_class_install_property ( + object_class, PROP_TZID, + g_param_spec_string ("tzid", + "TZID", + "The selected TZID", + NULL, + G_PARAM_READWRITE)); +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + GtkTreeModel *model; + + switch (prop_id) { + case PROP_TOP: + model = mateweather_timezone_model_new (g_value_get_pointer (value)); + gtk_combo_box_set_model (GTK_COMBO_BOX (object), model); + g_object_unref (model); + gtk_combo_box_set_active (GTK_COMBO_BOX (object), 0); + break; + + case PROP_TZID: + mateweather_timezone_menu_set_tzid (MATEWEATHER_TIMEZONE_MENU (object), + g_value_get_string (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + MateWeatherTimezoneMenu *menu = MATEWEATHER_TIMEZONE_MENU (object); + + switch (prop_id) { + case PROP_TZID: + g_value_set_string (value, mateweather_timezone_menu_get_tzid (menu)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +enum { + MATEWEATHER_TIMEZONE_MENU_NAME, + MATEWEATHER_TIMEZONE_MENU_ZONE +}; + +static void +changed (GtkComboBox *combo) +{ + MateWeatherTimezoneMenu *menu = MATEWEATHER_TIMEZONE_MENU (combo); + GtkTreeIter iter; + + if (menu->zone) + mateweather_timezone_unref (menu->zone); + + gtk_combo_box_get_active_iter (combo, &iter); + gtk_tree_model_get (gtk_combo_box_get_model (combo), &iter, + MATEWEATHER_TIMEZONE_MENU_ZONE, &menu->zone, + -1); + + if (menu->zone) + mateweather_timezone_ref (menu->zone); + + g_object_notify (G_OBJECT (combo), "tzid"); +} + +static void +append_offset (GString *desc, int offset) +{ + int hours, minutes; + + hours = offset / 60; + minutes = (offset > 0) ? offset % 60 : -offset % 60; + + if (minutes) + g_string_append_printf (desc, "GMT%+d:%02d", hours, minutes); + else if (hours) + g_string_append_printf (desc, "GMT%+d", hours); + else + g_string_append (desc, "GMT"); +} + +static char * +get_offset (MateWeatherTimezone *zone) +{ + GString *desc; + + desc = g_string_new (NULL); + append_offset (desc, mateweather_timezone_get_offset (zone)); + if (mateweather_timezone_has_dst (zone)) { + g_string_append (desc, " / "); + append_offset (desc, mateweather_timezone_get_dst_offset (zone)); + } + return g_string_free (desc, FALSE); +} + +static void +insert_location (GtkTreeStore *store, MateWeatherTimezone *zone, const char *loc_name, GtkTreeIter *parent) +{ + GtkTreeIter iter; + char *name, *offset; + + offset = get_offset (zone); + name = g_strdup_printf ("%s (%s)", + loc_name ? loc_name : mateweather_timezone_get_name (zone), + offset); + gtk_tree_store_append (store, &iter, parent); + gtk_tree_store_set (store, &iter, + MATEWEATHER_TIMEZONE_MENU_NAME, name, + MATEWEATHER_TIMEZONE_MENU_ZONE, mateweather_timezone_ref (zone), + -1); + g_free (name); + g_free (offset); +} + +static void +insert_locations (GtkTreeStore *store, MateWeatherLocation *loc) +{ + int i; + + if (mateweather_location_get_level (loc) < MATEWEATHER_LOCATION_COUNTRY) { + MateWeatherLocation **children; + + children = mateweather_location_get_children (loc); + for (i = 0; children[i]; i++) + insert_locations (store, children[i]); + mateweather_location_free_children (loc, children); + } else { + MateWeatherTimezone **zones; + GtkTreeIter iter; + + zones = mateweather_location_get_timezones (loc); + if (zones[1]) { + gtk_tree_store_append (store, &iter, NULL); + gtk_tree_store_set (store, &iter, + MATEWEATHER_TIMEZONE_MENU_NAME, mateweather_location_get_name (loc), + -1); + + for (i = 0; zones[i]; i++) { + insert_location (store, zones[i], NULL, &iter); + } + } else if (zones[0]) { + insert_location (store, zones[0], mateweather_location_get_name (loc), NULL); + } + + mateweather_location_free_timezones (loc, zones); + } +} + +static GtkTreeModel * +mateweather_timezone_model_new (MateWeatherLocation *top) +{ + GtkTreeStore *store; + GtkTreeModel *model; + GtkTreeIter iter; + char *unknown; + MateWeatherTimezone *utc; + + store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_POINTER); + model = GTK_TREE_MODEL (store); + + unknown = g_markup_printf_escaped ("%s", C_("timezone", "Unknown")); + + gtk_tree_store_append (store, &iter, NULL); + gtk_tree_store_set (store, &iter, + MATEWEATHER_TIMEZONE_MENU_NAME, unknown, + MATEWEATHER_TIMEZONE_MENU_ZONE, NULL, + -1); + + utc = mateweather_timezone_get_utc (); + if (utc) { + insert_location (store, utc, NULL, NULL); + mateweather_timezone_unref (utc); + } + + gtk_tree_store_append (store, &iter, NULL); + + g_free (unknown); + + insert_locations (store, top); + + return model; +} + +static gboolean +row_separator_func (GtkTreeModel *model, GtkTreeIter *iter, gpointer data) +{ + char *name; + + gtk_tree_model_get (model, iter, + MATEWEATHER_TIMEZONE_MENU_NAME, &name, + -1); + if (name) { + g_free (name); + return FALSE; + } else + return TRUE; +} + +static void +is_sensitive (GtkCellLayout *cell_layout, GtkCellRenderer *cell, + GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data) +{ + gboolean sensitive; + + sensitive = !gtk_tree_model_iter_has_child (tree_model, iter); + g_object_set (cell, "sensitive", sensitive, NULL); +} + +/** + * mateweather_timezone_menu_new: + * @top: the top-level location for the menu. + * + * Creates a new #MateWeatherTimezoneMenu. + * + * @top will normally be a location returned from + * mateweather_location_new_world(), but you can create a menu that + * contains the timezones from a smaller set of locations if you want. + * + * Return value: the new #MateWeatherTimezoneMenu + **/ +GtkWidget * +mateweather_timezone_menu_new (MateWeatherLocation *top) +{ + return g_object_new (MATEWEATHER_TYPE_TIMEZONE_MENU, + "top", top, + NULL); +} + +typedef struct { + GtkComboBox *combo; + const char *tzid; +} SetTimezoneData; + +static gboolean +check_tzid (GtkTreeModel *model, GtkTreePath *path, + GtkTreeIter *iter, gpointer data) +{ + SetTimezoneData *tzd = data; + MateWeatherTimezone *zone; + + gtk_tree_model_get (model, iter, + MATEWEATHER_TIMEZONE_MENU_ZONE, &zone, + -1); + if (!zone) + return FALSE; + + if (!strcmp (mateweather_timezone_get_tzid (zone), tzd->tzid)) { + gtk_combo_box_set_active_iter (tzd->combo, iter); + return TRUE; + } else + return FALSE; +} + +/** + * mateweather_timezone_menu_set_tzid: + * @menu: a #MateWeatherTimezoneMenu + * @tzid: (allow-none): a tzdata id (eg, "America/New_York") + * + * Sets @menu to the given @tzid. If @tzid is %NULL, sets @menu to + * "Unknown". + **/ +void +mateweather_timezone_menu_set_tzid (MateWeatherTimezoneMenu *menu, + const char *tzid) +{ + SetTimezoneData tzd; + + g_return_if_fail (MATEWEATHER_IS_TIMEZONE_MENU (menu)); + + if (!tzid) { + gtk_combo_box_set_active (GTK_COMBO_BOX (menu), 0); + return; + } + + tzd.combo = GTK_COMBO_BOX (menu); + tzd.tzid = tzid; + gtk_tree_model_foreach (gtk_combo_box_get_model (tzd.combo), + check_tzid, &tzd); +} + +/** + * mateweather_timezone_menu_get_tzid: + * @menu: a #MateWeatherTimezoneMenu + * + * Gets @menu's timezone id. + * + * Return value: (allow-none): @menu's tzid, or %NULL if no timezone + * is selected. + **/ +const char * +mateweather_timezone_menu_get_tzid (MateWeatherTimezoneMenu *menu) +{ + g_return_val_if_fail (MATEWEATHER_IS_TIMEZONE_MENU (menu), NULL); + + if (!menu->zone) + return NULL; + return mateweather_timezone_get_tzid (menu->zone); +} + -- cgit v1.2.1