From bf65330d3ef0e57d0bf2d4c6171c77038695b771 Mon Sep 17 00:00:00 2001 From: "Javier S. Pedro" Date: Sat, 22 Jan 2011 04:03:32 +0100 Subject: lots of UI work --- presets.c | 187 ++++++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 110 insertions(+), 77 deletions(-) (limited to 'presets.c') diff --git a/presets.c b/presets.c index 2f1f37b..f9d5c85 100644 --- a/presets.c +++ b/presets.c @@ -20,61 +20,64 @@ struct _CFmPresetsPrivate { gchar *name; gchar *gconf_dir; guint gconf_notify; + GtkListStore *l; GHashTable *t; }; enum { - PROP_0, - PROP_NAME, - PROP_LAST + COL_INVALID = -1, + COL_FREQUENCY = 0, + COL_NAME }; enum { - SIGNAL_0, - SIGNAL_LAST + PROP_0, + PROP_NAME, + PROP_MODEL, + PROP_LAST }; static GParamSpec *properties[PROP_LAST]; -static guint signals[SIGNAL_LAST]; -static inline gfloat freq_to_float(gulong f) +static inline gulong round_freq(gulong freq) +{ + const gulong round_to = 100000; /* 0.1 MHz */ + return ((freq + round_to / 2) / round_to) * round_to; +} + +static inline gulong ffreq_to_freq(gfloat ffreq) { - return f / 1000000.0; + return round_freq(ffreq * 1000000.0f); } -static inline gulong float_to_freq(gfloat f) +static inline gfloat freq_to_ffreq(gulong freq) { - return f * 1000000.0; + return freq / 1000000.0f; } -static inline gfloat pointer_to_float(gpointer p) +static inline gpointer freq_to_pointer(gulong freq) { - union { - gfloat f; - gpointer p; - } u; - u.p = p; - return u.f; + return GUINT_TO_POINTER(freq); } -static inline gpointer float_to_pointer(gfloat f) +static inline gulong pointer_to_freq(gpointer ptr) { - union { - gfloat f; - gpointer p; - } u; - u.f = f; - return u.p; + return GPOINTER_TO_UINT(ptr); } -static inline gpointer freq_to_pointer(gulong f) +static inline gpointer ffreq_to_pointer(gfloat ffreq) { - return float_to_pointer(freq_to_float(f)); + return freq_to_pointer(ffreq_to_freq(ffreq)); } -static inline gulong pointer_to_freq(gpointer p) +static inline gfloat pointer_to_ffreq(gpointer ptr) { - return float_to_freq(pointer_to_float(p)); + return freq_to_ffreq(pointer_to_freq(ptr)); +} + +static void destroy_iter(gpointer data) +{ + g_slice_free(GtkTreeIter, data); } static void func_gconf_entry_free(gpointer data, gpointer user_data) @@ -83,6 +86,18 @@ static void func_gconf_entry_free(gpointer data, gpointer user_data) gconf_entry_free(entry); } +static gint compare_freq(GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, + gpointer user_data) +{ + gulong freq_a, freq_b; + gtk_tree_model_get(model, a, 0, &freq_a, -1); + gtk_tree_model_get(model, b, 0, &freq_b, -1); + + if (freq_a > freq_b) return 1; + else if (freq_a < freq_b) return -1; + else return 0; +} + static void cfm_presets_load(CFmPresets *self) { CFmPresetsPrivate *priv = self->priv; @@ -95,9 +110,16 @@ static void cfm_presets_load(CFmPresets *self) for (i = l; i; i = g_slist_next(i)) { GConfEntry *entry = (GConfEntry*) i->data; const gchar *basename = g_basename(gconf_entry_get_key(entry)); - gfloat freq = g_ascii_strtod(basename, NULL); + gfloat ffreq = g_ascii_strtod(basename, NULL); + gulong freq = ffreq_to_freq(ffreq); const gchar *name = gconf_value_get_string(gconf_entry_get_value(entry)); - g_hash_table_insert(priv->t, float_to_pointer(freq), g_strdup(name)); + GtkTreeIter *iter = g_slice_new(GtkTreeIter); + gtk_list_store_insert_with_values(priv->l, iter, 0, + COL_FREQUENCY, freq, + COL_NAME, name, + COL_INVALID + ); + g_hash_table_insert(priv->t, freq_to_pointer(freq), iter); } g_slist_foreach(l, func_gconf_entry_free, NULL); @@ -115,16 +137,37 @@ static void cfm_presets_gconf_notify(GConfClient *gconf, guint cnxn_id, } const gchar *basename = g_basename(gconf_entry_get_key(entry)); - gfloat freq = g_ascii_strtod(basename, NULL); + gfloat ffreq = g_ascii_strtod(basename, NULL); + gulong freq = ffreq_to_freq(ffreq); + gpointer t_data = g_hash_table_lookup(priv->t, freq_to_pointer(freq)); GConfValue *value = gconf_entry_get_value(entry); if (value) { const gchar *name = gconf_value_get_string(gconf_entry_get_value(entry)); - g_debug("Preset '%s' changed to '%s'\n", basename, name); - g_hash_table_insert(priv->t, float_to_pointer(freq), g_strdup(name)); + if (t_data) { + /* Modifying existing preset's name */ + GtkTreeIter *iter = (GtkTreeIter*)t_data; + g_debug("Preset '%s' changed to '%s'\n", basename, name); + gtk_list_store_set(priv->l, iter, COL_NAME, name, COL_INVALID); + } else { + GtkTreeIter *iter = g_slice_new(GtkTreeIter); + g_debug("Preset '%s' set to '%s'\n", basename, name); + gtk_list_store_insert_with_values(priv->l, iter, 0, + COL_FREQUENCY, freq, + COL_NAME, name, + COL_INVALID + ); + g_hash_table_insert(priv->t, freq_to_pointer(freq), iter); + } + } else { - g_debug("Preset '%s' removed\n", basename); - g_hash_table_remove(priv->t, float_to_pointer(freq)); + + if (t_data) { + GtkTreeIter *iter = (GtkTreeIter*)t_data; + g_debug("Preset '%s' removed\n", basename); + gtk_list_store_remove(priv->l, iter); + g_hash_table_remove(priv->t, freq_to_pointer(freq)); + } } } @@ -151,6 +194,9 @@ static void cfm_presets_get_property(GObject *object, guint property_id, case PROP_NAME: g_value_set_string(value, self->priv->name); break; + case PROP_MODEL: + g_value_set_object(value, self->priv->l); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); break; @@ -164,7 +210,8 @@ static void cfm_presets_init(CFmPresets *self) self->priv = priv = CFM_PRESETS_GET_PRIVATE(self); priv->gconf = gconf_client_get_default(); - priv->t = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_free); + priv->t = g_hash_table_new_full(g_direct_hash, g_direct_equal, + NULL, destroy_iter); } static GObject * cfm_presets_constructor(GType gtype, guint n_properties, @@ -182,6 +229,12 @@ static GObject * cfm_presets_constructor(GType gtype, guint n_properties, priv->gconf_notify = gconf_client_notify_add(priv->gconf, priv->gconf_dir, cfm_presets_gconf_notify, self, NULL, NULL); + priv->l = gtk_list_store_new(2, G_TYPE_ULONG, G_TYPE_STRING); + gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(priv->l), 0, compare_freq, + NULL, NULL); + gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(priv->l), 0, + GTK_SORT_ASCENDING); + cfm_presets_load(self); return object; @@ -206,6 +259,10 @@ static void cfm_presets_dispose(GObject *object) g_object_unref(priv->gconf); priv->gconf = NULL; } + if (priv->l) { + g_object_unref(priv->l); + priv->l = NULL; + } } static void cfm_presets_finalize(GObject *object) @@ -238,6 +295,13 @@ static void cfm_presets_class_init(CFmPresetsClass *klass) G_PARAM_STATIC_STRINGS); properties[PROP_NAME] = param_spec; g_object_class_install_property(gobject_class, PROP_NAME, param_spec); + param_spec = g_param_spec_object("model", + "Preset list model", + "A model containing this set of presets", + GTK_TYPE_TREE_MODEL, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + properties[PROP_MODEL] = param_spec; + g_object_class_install_property(gobject_class, PROP_MODEL, param_spec); } static gpointer cfm_presets_build_default(gpointer data) @@ -264,7 +328,7 @@ void cfm_presets_set_preset(CFmPresets *self, gulong freq, const gchar *name) GError *error = NULL; gchar buf[G_ASCII_DTOSTR_BUF_SIZE]; gchar *key = g_strdup_printf("%s/%s", priv->gconf_dir, - g_ascii_formatd(buf, sizeof(buf), "%.1f", freq_to_float(freq))); + g_ascii_formatd(buf, sizeof(buf), "%.1f", freq_to_ffreq(freq))); if (!gconf_client_set_string(priv->gconf, key, name, &error)) { g_warning("Failed to store preset '%s' ('%s'): %s\n", key, name, error->message); @@ -278,7 +342,7 @@ void cfm_presets_remove_preset(CFmPresets *self, gulong freq) GError *error = NULL; gchar buf[G_ASCII_DTOSTR_BUF_SIZE]; gchar *key = g_strdup_printf("%s/%s", priv->gconf_dir, - g_ascii_formatd(buf, sizeof(buf), "%.1f", freq_to_float(freq))); + g_ascii_formatd(buf, sizeof(buf), "%.1f", freq_to_ffreq(freq))); if (!gconf_client_unset(priv->gconf, key, &error)) { g_warning("Failed to remove preset '%s': %s\n", key, error->message); } @@ -292,13 +356,17 @@ gboolean cfm_presets_is_preset(CFmPresets *self, gulong freq) return g_hash_table_lookup(priv->t, freq_to_pointer(freq)) ? TRUE : FALSE; } -const gchar * cfm_presets_get_preset(CFmPresets *self, gulong freq) +gchar * cfm_presets_get_preset(CFmPresets *self, gulong freq) { CFmPresetsPrivate *priv = self->priv; - gpointer found = g_hash_table_lookup(priv->t, freq_to_pointer(freq)); - if (found) { - return (const gchar *) found; + gpointer t_data = g_hash_table_lookup(priv->t, freq_to_pointer(freq)); + if (t_data) { + GtkTreeIter *iter = (GtkTreeIter*) t_data; + gchar *name; + gtk_tree_model_get(GTK_TREE_MODEL(priv->l), iter, + COL_NAME, &name, COL_INVALID); + return name; } else { return NULL; } @@ -306,38 +374,3 @@ const gchar * cfm_presets_get_preset(CFmPresets *self, gulong freq) return NULL; } -static void preset_to_list_store(gpointer key, gpointer value, gpointer user_data) -{ - GtkListStore *l = GTK_LIST_STORE(user_data); - GtkTreeIter iter; - - gulong freq = pointer_to_freq(key); - gtk_list_store_insert_with_values(l, &iter, 0, 0, freq, 1, value, -1); -} - -static gint compare_freq(GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, - gpointer user_data) -{ - gulong freq_a, freq_b; - gtk_tree_model_get(model, a, 0, &freq_a, -1); - gtk_tree_model_get(model, b, 0, &freq_b, -1); - - if (freq_a > freq_b) return 1; - else if (freq_a < freq_b) return -1; - else return 0; -} - -GtkListStore* cfm_presets_get_all(CFmPresets *self) -{ - CFmPresetsPrivate *priv = self->priv; - GtkListStore *l = gtk_list_store_new(2, G_TYPE_ULONG, G_TYPE_STRING); - g_hash_table_foreach(priv->t, preset_to_list_store, l); - - gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(l), 0, compare_freq, - NULL, NULL); - gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(l), 0, - GTK_SORT_ASCENDING); - - return l; -} - -- cgit v1.2.3