[gthumb/ext: 5/20] allow to reorder the metadata in the thumbnail caption
- From: Paolo Bacchilega <paobac src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gthumb/ext: 5/20] allow to reorder the metadata in the thumbnail caption
- Date: Wed, 25 Nov 2009 17:13:15 +0000 (UTC)
commit 3794bbc29b0b6e12b0556b638e65c44477f95683
Author: Paolo Bacchilega <paobac src gnome org>
Date: Sat Nov 21 00:16:04 2009 +0100
allow to reorder the metadata in the thumbnail caption
data/ui/preferences.ui | 158 ++++++++-----
gthumb/Makefile.am | 2 +
gthumb/dlg-preferences.c | 185 ++-------------
gthumb/gth-metadata-chooser.c | 521 +++++++++++++++++++++++++++++++++++++++++
gthumb/gth-metadata-chooser.h | 63 +++++
gthumb/gth-uri-list.c | 4 +-
6 files changed, 708 insertions(+), 225 deletions(-)
---
diff --git a/data/ui/preferences.ui b/data/ui/preferences.ui
index 37bfe3d..bdf5c5e 100644
--- a/data/ui/preferences.ui
+++ b/data/ui/preferences.ui
@@ -35,8 +35,10 @@
<child>
<object class="GtkLabel" id="label156">
<property name="visible">True</property>
- <property name="label" translatable="yes"><b>Interface</b></property>
- <property name="use_markup">True</property>
+ <property name="label" translatable="yes">Appearance</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
</object>
<packing>
<property name="expand">False</property>
@@ -106,9 +108,11 @@
<child>
<object class="GtkLabel" id="label86">
<property name="visible">True</property>
- <property name="label" translatable="yes"><b>On startup:</b></property>
- <property name="use_markup">True</property>
+ <property name="label" translatable="yes">On startup:</property>
<property name="justify">center</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
</object>
<packing>
<property name="expand">False</property>
@@ -185,8 +189,8 @@
<child>
<object class="GtkFileChooserButton" id="startup_dir_filechooserbutton">
<property name="visible">True</property>
- <property name="local_only">False</property>
<property name="action">select-folder</property>
+ <property name="local_only">False</property>
<property name="title" translatable="yes">Choose startup folder</property>
</object>
<packing>
@@ -249,9 +253,11 @@
<child>
<object class="GtkLabel" id="label183">
<property name="visible">True</property>
- <property name="label" translatable="yes"><b>Other</b></property>
- <property name="use_markup">True</property>
+ <property name="label" translatable="yes">Other</property>
<property name="justify">center</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
</object>
<packing>
<property name="expand">False</property>
@@ -336,38 +342,95 @@
<property name="orientation">vertical</property>
<property name="spacing">12</property>
<child>
- <object class="GtkVBox" id="vbox30">
+ <object class="GtkVBox" id="vbox5">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
- <object class="GtkCheckButton" id="slow_mime_type_checkbutton">
- <property name="label" translatable="yes">D_etermine image type from content (slower)</property>
+ <object class="GtkHBox" id="hbox2">
<property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="use_underline">True</property>
- <property name="draw_indicator">True</property>
+ <property name="spacing">5</property>
+ <child>
+ <object class="GtkLabel" id="label4">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Caption</property>
+ <property name="justify">center</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
</object>
<packing>
+ <property name="expand">False</property>
<property name="position">0</property>
</packing>
</child>
+ <child>
+ <object class="GtkAlignment" id="alignment7">
+ <property name="visible">True</property>
+ <property name="left_padding">12</property>
+ <child>
+ <object class="GtkScrolledWindow" id="caption_scrolledwindow">
+ <property name="height_request">150</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">automatic</property>
+ <property name="vscrollbar_policy">automatic</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
</object>
<packing>
- <property name="expand">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
- <object class="GtkFrame" id="frame1">
+ <object class="GtkVBox" id="vbox2">
<property name="visible">True</property>
- <property name="label_xalign">0</property>
- <property name="shadow_type">none</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
<child>
- <object class="GtkAlignment" id="alignment1">
+ <object class="GtkHBox" id="hbox1">
+ <property name="visible">True</property>
+ <property name="spacing">5</property>
+ <child>
+ <object class="GtkLabel" id="label3">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Other</property>
+ <property name="justify">center</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkAlignment" id="alignment6">
<property name="visible">True</property>
- <property name="top_padding">6</property>
<property name="left_padding">12</property>
<child>
<object class="GtkVBox" id="vbox1">
@@ -375,14 +438,14 @@
<property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
- <object class="GtkHBox" id="hbox1">
+ <object class="GtkHBox" id="hbox3">
<property name="visible">True</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel" id="size_label">
<property name="visible">True</property>
<property name="xalign">0</property>
- <property name="label" translatable="yes">_Size:</property>
+ <property name="label" translatable="yes">Thumbnail _size:</property>
<property name="use_underline">True</property>
<property name="justify">center</property>
</object>
@@ -405,42 +468,17 @@
</child>
</object>
<packing>
- <property name="expand">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
- <object class="GtkVBox" id="vbox2">
+ <object class="GtkCheckButton" id="slow_mime_type_checkbutton">
+ <property name="label" translatable="yes">D_etermine image type from content (slower)</property>
<property name="visible">True</property>
- <property name="orientation">vertical</property>
- <child>
- <object class="GtkLabel" id="caption_label">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">C_aption:</property>
- <property name="use_underline">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkScrolledWindow" id="caption_scrolledwindow">
- <property name="height_request">150</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="hscrollbar_policy">automatic</property>
- <property name="vscrollbar_policy">automatic</property>
- <property name="shadow_type">in</property>
- <child>
- <placeholder/>
- </child>
- </object>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
</object>
<packing>
<property name="position">1</property>
@@ -449,19 +487,13 @@
</object>
</child>
</object>
- </child>
- <child type="label">
- <object class="GtkLabel" id="label2">
- <property name="visible">True</property>
- <property name="label" translatable="yes">Thumbnail</property>
- <property name="use_markup">True</property>
- <attributes>
- <attribute name="weight" value="bold"/>
- </attributes>
- </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
</child>
</object>
<packing>
+ <property name="expand">False</property>
<property name="position">1</property>
</packing>
</child>
diff --git a/gthumb/Makefile.am b/gthumb/Makefile.am
index d9ab7d7..91d0b70 100644
--- a/gthumb/Makefile.am
+++ b/gthumb/Makefile.am
@@ -71,6 +71,7 @@ PUBLIC_HEADER_FILES = \
gth-location-chooser.h \
gth-main.h \
gth-metadata.h \
+ gth-metadata-chooser.h \
gth-metadata-provider.h \
gth-monitor.h \
gth-multipage.h \
@@ -188,6 +189,7 @@ gthumb_SOURCES = \
gth-main-default-tests.c \
gth-main-default-types.c \
gth-metadata.c \
+ gth-metadata-chooser.c \
gth-metadata-provider.c \
gth-metadata-provider-file.c \
gth-monitor.c \
diff --git a/gthumb/dlg-preferences.c b/gthumb/dlg-preferences.c
index c2c850c..406f4d5 100644
--- a/gthumb/dlg-preferences.c
+++ b/gthumb/dlg-preferences.c
@@ -28,6 +28,7 @@
#include "gth-enum-types.h"
#include "gth-file-source-vfs.h"
#include "gth-main.h"
+#include "gth-metadata-chooser.h"
#include "gth-preferences.h"
#include "gtk-utils.h"
#include "glib-utils.h"
@@ -36,12 +37,6 @@
#define GET_WIDGET(name) _gtk_builder_get_widget (data->builder, (name))
-enum {
- CAPTION_COLUMN_NAME,
- CAPTION_COLUMN_ID,
- CAPTION_COLUMN_USED,
- CAPTION_COLUMNS
-};
typedef struct {
GthBrowser *browser;
@@ -49,7 +44,7 @@ typedef struct {
GtkWidget *dialog;
GtkWidget *toolbar_style_combobox;
GtkWidget *thumbnail_size_combobox;
- GtkWidget *thumbnail_caption_list_view;
+ GtkWidget *thumbnail_caption_chooser;
} DialogData;
static int thumb_size[] = { 48, 64, 85, 95, 112, 128, 164, 200, 256 };
@@ -78,10 +73,8 @@ destroy_cb (GtkWidget *widget,
}
-/* called when the "apply" button is clicked. */
static void
-apply_cb (GtkWidget *widget,
- DialogData *data)
+apply_changes (DialogData *data)
{
/* Startup dir. */
@@ -101,20 +94,18 @@ apply_cb (GtkWidget *widget,
}
-/* called when the "close" button is clicked. */
static void
-close_cb (GtkWidget *widget,
- DialogData *data)
+close_button_clicked_cb (GtkWidget *widget,
+ DialogData *data)
{
- apply_cb (widget, data);
+ apply_changes (data);
gtk_widget_destroy (data->dialog);
}
-/* called when the "help" button is clicked. */
static void
-help_cb (GtkWidget *widget,
- DialogData *data)
+help_button_clicked_cb (GtkWidget *widget,
+ DialogData *data)
{
show_help_dialog (GTK_WINDOW (data->dialog), "preferences");
}
@@ -184,107 +175,15 @@ fast_file_type_toggled_cb (GtkToggleButton *button,
static void
-update_caption_from_list_view (DialogData *data)
-{
- GtkTreeModel *tree_model;
- GtkTreeIter iter;
- GString *attributes;
-
- attributes = g_string_new ("");
- tree_model = gtk_tree_view_get_model (GTK_TREE_VIEW (data->thumbnail_caption_list_view));
- if (gtk_tree_model_get_iter_first (tree_model, &iter)) {
- do {
- gboolean used;
- char *attribute_id;
-
- gtk_tree_model_get (tree_model, &iter,
- CAPTION_COLUMN_ID, &attribute_id,
- CAPTION_COLUMN_USED, &used,
- -1);
-
- if (used) {
- if (attributes->len > 0)
- g_string_append (attributes, ",");
- g_string_append (attributes, attribute_id);
- }
-
- g_free (attribute_id);
- }
- while (gtk_tree_model_iter_next (tree_model, &iter));
- }
-
- if (attributes->len > 0)
- eel_gconf_set_string (PREF_THUMBNAIL_CAPTION, attributes->str);
- else
- eel_gconf_set_string (PREF_THUMBNAIL_CAPTION, "none");
-
- g_string_free (attributes, TRUE);
-}
-
-
-static void
-cell_renderer_toggle_toggled_cb (GtkCellRendererToggle *cell_renderer,
- char *path,
- gpointer user_data)
-{
- DialogData *data = user_data;
- GtkTreePath *tpath;
- GtkTreeModel *tree_model;
- GtkTreeIter iter;
-
- tpath = gtk_tree_path_new_from_string (path);
- if (tpath == NULL)
- return;
-
- tree_model = gtk_tree_view_get_model (GTK_TREE_VIEW (data->thumbnail_caption_list_view));
- if (gtk_tree_model_get_iter (tree_model, &iter, tpath)) {
- gboolean used;
-
- gtk_tree_model_get (tree_model, &iter,
- CAPTION_COLUMN_USED, &used,
- -1);
- gtk_list_store_set (GTK_LIST_STORE (tree_model), &iter,
- CAPTION_COLUMN_USED, ! used,
- -1);
- }
-
- update_caption_from_list_view (data);
-
- gtk_tree_path_free (tpath);
-}
-
-
-static void
-caption_list_view_add_columns (GtkTreeView *treeview,
- DialogData *data)
+thumbnail_caption_chooser_changed_cb (GthMetadataChooser *chooser,
+ DialogData *data)
{
- GtkTreeViewColumn *column;
- GtkCellRenderer *renderer;
+ char *attributes;
- /* the checkbox column */
+ attributes = gth_metadata_chooser_get_selection (chooser);
+ eel_gconf_set_string (PREF_THUMBNAIL_CAPTION, attributes);
- column = gtk_tree_view_column_new ();
- renderer = gtk_cell_renderer_toggle_new ();
- g_signal_connect (renderer,
- "toggled",
- G_CALLBACK (cell_renderer_toggle_toggled_cb),
- data);
- gtk_tree_view_column_pack_start (column, renderer, FALSE);
- gtk_tree_view_column_set_attributes (column, renderer,
- "active", CAPTION_COLUMN_USED,
- NULL);
- gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
-
- /* the name column. */
-
- column = gtk_tree_view_column_new ();
- renderer = gtk_cell_renderer_text_new ();
- gtk_tree_view_column_pack_start (column, renderer, TRUE);
- gtk_tree_view_column_set_attributes (column, renderer,
- "text", CAPTION_COLUMN_NAME,
- NULL);
- gtk_tree_view_column_set_expand (column, TRUE);
- gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+ g_free (attributes);
}
@@ -294,12 +193,7 @@ dlg_preferences (GthBrowser *browser)
DialogData *data;
char *startup_location;
GthFileSource *file_source;
- GtkListStore *caption_store;
- GtkTreeIter iter;
char *current_caption;
- char **attributes_v;
- char **active_attributes_v;
- int i;
if (gth_browser_get_dialog (browser, "preferences") != NULL) {
gtk_window_present (GTK_WINDOW (gth_browser_get_dialog (browser, "preferences")));
@@ -321,46 +215,14 @@ dlg_preferences (GthBrowser *browser)
data->toolbar_style_combobox = _gtk_combo_box_new_with_texts (_("System settings"), _("Text below icons"), _("Text beside icons"), _("Icons only"), _("Text only"), NULL);
data->thumbnail_size_combobox = _gtk_combo_box_new_with_texts (_("48"), _("64"), _("85"), _("95"), _("112"), _("128"), _("164"), _("200"), _("256"), NULL);
- caption_store = gtk_list_store_new (CAPTION_COLUMNS, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN);
- data->thumbnail_caption_list_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (caption_store));
- g_object_unref (caption_store);
-
- gtk_tree_view_set_reorderable (GTK_TREE_VIEW (data->thumbnail_caption_list_view), FALSE);
- gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (data->thumbnail_caption_list_view), FALSE);
-
- caption_list_view_add_columns (GTK_TREE_VIEW (data->thumbnail_caption_list_view), data);
-
- gtk_widget_show (data->thumbnail_caption_list_view);
- gtk_container_add (GTK_CONTAINER (GET_WIDGET ("caption_scrolledwindow")), data->thumbnail_caption_list_view);
-
/* caption list */
+ data->thumbnail_caption_chooser = gth_metadata_chooser_new (GTH_METADATA_ALLOW_IN_FILE_LIST);
+ gtk_widget_show (data->thumbnail_caption_chooser);
+ gtk_container_add (GTK_CONTAINER (GET_WIDGET ("caption_scrolledwindow")), data->thumbnail_caption_chooser);
+
current_caption = eel_gconf_get_string (PREF_THUMBNAIL_CAPTION, DEFAULT_THUMBNAIL_CAPTION);
- active_attributes_v = g_strsplit (current_caption, ",", -1);
- attributes_v = gth_main_get_metadata_attributes ("*");
- for (i = 0; attributes_v[i] != NULL; i++) {
- GthMetadataInfo *info;
- const char *name;
- gboolean used;
-
- info = gth_main_get_metadata_info (attributes_v[i]);
- if ((info == NULL) || ((info->flags & GTH_METADATA_ALLOW_IN_FILE_LIST) == 0))
- continue;
-
- gtk_list_store_append (caption_store, &iter);
-
- name = info->display_name;
- if (name == NULL)
- name = info->id;
- used = _g_strv_find (active_attributes_v, info->id) != -1;
- gtk_list_store_set (caption_store, &iter,
- CAPTION_COLUMN_NAME, name,
- CAPTION_COLUMN_ID, info->id,
- CAPTION_COLUMN_USED, used,
- -1);
- }
- g_strfreev (attributes_v);
- g_strfreev (active_attributes_v);
+ gth_metadata_chooser_set_selection (GTH_METADATA_CHOOSER (data->thumbnail_caption_chooser), current_caption);
g_free (current_caption);
gtk_widget_show (data->toolbar_style_combobox);
@@ -369,7 +231,6 @@ dlg_preferences (GthBrowser *browser)
gtk_box_pack_start (GTK_BOX (GET_WIDGET ("toolbar_style_combobox_box")), data->toolbar_style_combobox, FALSE, FALSE, 0);
gtk_box_pack_start (GTK_BOX (GET_WIDGET ("thumbnail_size_box")), data->thumbnail_size_combobox, FALSE, FALSE, 0);
- gtk_label_set_mnemonic_widget (GTK_LABEL (GET_WIDGET ("caption_label")), data->thumbnail_caption_list_view);
gtk_label_set_mnemonic_widget (GTK_LABEL (GET_WIDGET ("size_label")), data->thumbnail_size_combobox);
/* * general */
@@ -423,11 +284,11 @@ dlg_preferences (GthBrowser *browser)
data);
g_signal_connect (G_OBJECT (GET_WIDGET ("close_button")),
"clicked",
- G_CALLBACK (close_cb),
+ G_CALLBACK (close_button_clicked_cb),
data);
g_signal_connect (G_OBJECT (GET_WIDGET ("help_button")),
"clicked",
- G_CALLBACK (help_cb),
+ G_CALLBACK (help_button_clicked_cb),
data);
/* general */
@@ -459,6 +320,10 @@ dlg_preferences (GthBrowser *browser)
"toggled",
G_CALLBACK (fast_file_type_toggled_cb),
data);
+ g_signal_connect (G_OBJECT (data->thumbnail_caption_chooser),
+ "changed",
+ G_CALLBACK (thumbnail_caption_chooser_changed_cb),
+ data);
/* run dialog. */
diff --git a/gthumb/gth-metadata-chooser.c b/gthumb/gth-metadata-chooser.c
new file mode 100644
index 0000000..f650432
--- /dev/null
+++ b/gthumb/gth-metadata-chooser.c
@@ -0,0 +1,521 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * GThumb
+ *
+ * Copyright (C) 2009 The Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include <glib/gi18n.h>
+#include "glib-utils.h"
+#include "gth-main.h"
+#include "gth-metadata-chooser.h"
+
+
+#define ORDER_CHANGED_DELAY 250
+
+
+enum {
+ NAME_COLUMN,
+ ID_COLUMN,
+ USED_COLUMN,
+ SEPARATOR_COLUMN,
+ N_COLUMNS
+};
+
+
+/* Signals */
+enum {
+ CHANGED,
+ LAST_SIGNAL
+};
+
+
+struct _GthMetadataChooserPrivate {
+ GthMetadataFlags allowed_flags;
+ gulong row_inserted_event;
+ gulong row_deleted_event;
+ guint changed_id;
+};
+
+
+static gpointer parent_class = NULL;
+static guint gth_metadata_chooser_signals[LAST_SIGNAL] = { 0 };
+
+
+static void
+gth_metadata_chooser_finalize (GObject *obj)
+{
+/* GthMetadataChooser *self;
+
+ self = GTH_METADATA_CHOOSER (obj); FIXME: delete if not needed */
+
+ G_OBJECT_CLASS (parent_class)->finalize (obj);
+}
+
+
+static void
+gth_metadata_chooser_class_init (GthMetadataChooserClass *klass)
+{
+ GObjectClass *object_class;
+
+ parent_class = g_type_class_peek_parent (klass);
+ g_type_class_add_private (klass, sizeof (GthMetadataChooserPrivate));
+
+ object_class = (GObjectClass*) (klass);
+ object_class->finalize = gth_metadata_chooser_finalize;
+
+ /* signals */
+
+ gth_metadata_chooser_signals[CHANGED] =
+ g_signal_new ("changed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GthMetadataChooserClass, changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+}
+
+
+/* -- gth_metadata_chooser_reorder_list -- */
+
+
+typedef struct {
+ int pos;
+ char *name;
+ char *id;
+ gboolean used;
+ gboolean separator;
+} ItemData;
+
+
+static void
+item_data_free (ItemData *item_data)
+{
+ g_free (item_data->name);
+ g_free (item_data->id);
+ g_free (item_data);
+}
+
+
+static int
+item_data_compare_func (gconstpointer a,
+ gconstpointer b)
+{
+ ItemData *item_a = (ItemData *) a;
+ ItemData *item_b = (ItemData *) b;
+
+ if (item_a->separator) {
+ if (item_b->used)
+ return 1;
+ else
+ return -1;
+ }
+
+ if (item_b->separator) {
+ if (item_a->used)
+ return -1;
+ else
+ return 1;
+ }
+
+ if (item_a->used == item_b->used) {
+ if (item_a->used) {
+ /* keep the user defined order for the used items */
+ if (item_a->pos < item_b->pos)
+ return -1;
+ else if (item_a->pos > item_b->pos)
+ return 1;
+ else
+ return 0;
+ }
+ else {
+ /* sort by name for the unused items */
+ return g_utf8_collate (item_a->name, item_b->name);
+ }
+ }
+ else if (item_a->used)
+ return -1;
+ else
+ return 1;
+}
+
+
+static gboolean
+gth_metadata_chooser_reorder_list (GthMetadataChooser *self)
+{
+ gboolean changed = FALSE;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ GList *list;
+ int pos;
+ int *new_order;
+ GList *scan;
+
+ model = gtk_tree_view_get_model (GTK_TREE_VIEW (self));
+ if (! gtk_tree_model_get_iter_first (model, &iter))
+ return FALSE;
+
+ list = NULL;
+ pos = 0;
+ do {
+ ItemData *item_data;
+
+ item_data = g_new0 (ItemData, 1);
+ item_data->pos = pos;
+ gtk_tree_model_get (model, &iter,
+ NAME_COLUMN, &item_data->name,
+ ID_COLUMN, &item_data->id,
+ USED_COLUMN, &item_data->used,
+ SEPARATOR_COLUMN, &item_data->separator,
+ -1);
+ list = g_list_prepend (list, item_data);
+ pos++;
+ }
+ while (gtk_tree_model_iter_next (model, &iter));
+
+ list = g_list_sort (list, item_data_compare_func);
+ new_order = g_new (int, g_list_length (list));
+ for (pos = 0, scan = list; scan; pos++, scan = scan->next) {
+ ItemData *item_data = scan->data;
+
+ if (pos != item_data->pos)
+ changed = TRUE;
+ new_order[pos] = item_data->pos;
+ }
+ gtk_list_store_reorder (GTK_LIST_STORE (model), new_order);
+
+ g_free (new_order);
+ g_list_foreach (list, (GFunc) item_data_free, NULL);
+ g_list_free (list);
+
+ return changed;
+}
+
+
+static void
+cell_renderer_toggle_toggled_cb (GtkCellRendererToggle *cell_renderer,
+ char *path,
+ gpointer user_data)
+{
+ GthMetadataChooser *self = user_data;
+ GtkTreePath *tree_path;
+ GtkTreeModel *tree_model;
+ GtkTreeIter iter;
+
+ tree_path = gtk_tree_path_new_from_string (path);
+ if (tree_path == NULL)
+ return;
+
+ tree_model = gtk_tree_view_get_model (GTK_TREE_VIEW (self));
+ if (gtk_tree_model_get_iter (tree_model, &iter, tree_path)) {
+ gboolean used;
+
+ gtk_tree_model_get (tree_model, &iter,
+ USED_COLUMN, &used,
+ -1);
+ gtk_list_store_set (GTK_LIST_STORE (tree_model), &iter,
+ USED_COLUMN, ! used,
+ -1);
+ gth_metadata_chooser_reorder_list (self);
+ g_signal_emit (self, gth_metadata_chooser_signals[CHANGED], 0);
+ }
+
+ gtk_tree_path_free (tree_path);
+}
+
+
+static gboolean
+row_separator_func (GtkTreeModel *model,
+ GtkTreeIter *iter,
+ gpointer data)
+{
+ gboolean separator;
+
+ gtk_tree_model_get (model, iter, SEPARATOR_COLUMN, &separator, -1);
+
+ return separator;
+}
+
+
+
+static gboolean
+order_changed (gpointer user_data)
+{
+ GthMetadataChooser *self = user_data;
+
+ if (self->priv->changed_id != 0)
+ g_source_remove (self->priv->changed_id);
+ self->priv->changed_id = 0;
+
+ gth_metadata_chooser_reorder_list (self);
+ g_signal_emit (self, gth_metadata_chooser_signals[CHANGED], 0);
+
+ return FALSE;
+}
+
+
+static void
+row_deleted_cb (GtkTreeModel *tree_model,
+ GtkTreePath *path,
+ gpointer user_data)
+{
+ GthMetadataChooser *self = user_data;
+
+ if (self->priv->changed_id != 0)
+ g_source_remove (self->priv->changed_id);
+ self->priv->changed_id = gdk_threads_add_timeout (ORDER_CHANGED_DELAY, order_changed, self);
+}
+
+
+static void
+row_inserted_cb (GtkTreeModel *tree_model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gpointer user_data)
+{
+ GthMetadataChooser *self = user_data;
+
+ if (self->priv->changed_id != 0)
+ g_source_remove (self->priv->changed_id);
+ self->priv->changed_id = gdk_threads_add_timeout (ORDER_CHANGED_DELAY, order_changed, self);
+}
+
+
+static void
+gth_metadata_chooser_instance_init (GthMetadataChooser *self)
+{
+ GtkListStore *store;
+ GtkTreeViewColumn *column;
+ GtkCellRenderer *renderer;
+
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GTH_TYPE_METADATA_CHOOSER, GthMetadataChooserPrivate);
+
+ /* the list view */
+
+ store = gtk_list_store_new (N_COLUMNS,
+ G_TYPE_STRING,
+ G_TYPE_STRING,
+ G_TYPE_BOOLEAN,
+ G_TYPE_BOOLEAN);
+ gtk_tree_view_set_model (GTK_TREE_VIEW (self), GTK_TREE_MODEL (store));
+ g_object_unref (store);
+ gtk_tree_view_set_reorderable (GTK_TREE_VIEW (self), TRUE);
+ gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (self), FALSE);
+ gtk_tree_view_set_row_separator_func (GTK_TREE_VIEW (self),
+ row_separator_func,
+ self,
+ NULL);
+
+ self->priv->row_inserted_event = g_signal_connect (store,
+ "row-inserted",
+ G_CALLBACK (row_inserted_cb),
+ self);
+ self->priv->row_deleted_event = g_signal_connect (store,
+ "row-deleted",
+ G_CALLBACK (row_deleted_cb),
+ self);
+
+ /* the checkbox column */
+
+ column = gtk_tree_view_column_new ();
+ renderer = gtk_cell_renderer_toggle_new ();
+ g_signal_connect (renderer,
+ "toggled",
+ G_CALLBACK (cell_renderer_toggle_toggled_cb),
+ self);
+ gtk_tree_view_column_pack_start (column, renderer, FALSE);
+ gtk_tree_view_column_set_attributes (column, renderer,
+ "active", USED_COLUMN,
+ NULL);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (self), column);
+
+ /* the name column. */
+
+ column = gtk_tree_view_column_new ();
+ renderer = gtk_cell_renderer_text_new ();
+ gtk_tree_view_column_pack_start (column, renderer, TRUE);
+ gtk_tree_view_column_set_attributes (column, renderer,
+ "text", NAME_COLUMN,
+ NULL);
+ gtk_tree_view_column_set_expand (column, TRUE);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (self), column);
+}
+
+
+GType
+gth_metadata_chooser_get_type (void)
+{
+ static GType type = 0;
+
+ if (type == 0) {
+ static const GTypeInfo g_define_type_info = {
+ sizeof (GthMetadataChooserClass),
+ NULL,
+ NULL,
+ (GClassInitFunc) gth_metadata_chooser_class_init,
+ NULL,
+ NULL,
+ sizeof (GthMetadataChooser),
+ 0,
+ (GInstanceInitFunc) gth_metadata_chooser_instance_init,
+ NULL
+ };
+ type = g_type_register_static (GTK_TYPE_TREE_VIEW,
+ "GthMetadataChooser",
+ &g_define_type_info,
+ 0);
+ }
+
+ return type;
+}
+
+
+GtkWidget *
+gth_metadata_chooser_new (GthMetadataFlags allowed_flags)
+{
+ GthMetadataChooser *self;
+
+ self = g_object_new (GTH_TYPE_METADATA_CHOOSER, NULL);
+ self->priv->allowed_flags = allowed_flags;
+ gth_metadata_chooser_set_selection (self, "");
+
+ return (GtkWidget *) self;
+}
+
+
+void
+gth_metadata_chooser_set_selection (GthMetadataChooser *self,
+ char *ids)
+{
+ GtkListStore *store;
+ char **attributes_v;
+ char **ids_v;
+ int i;
+ GtkTreeIter iter;
+
+ store = (GtkListStore *) gtk_tree_view_get_model (GTK_TREE_VIEW (self));
+
+ g_signal_handler_block (store, self->priv->row_inserted_event);
+ g_signal_handler_block (store, self->priv->row_deleted_event);
+
+ gtk_list_store_clear (store);
+
+ attributes_v = gth_main_get_metadata_attributes ("*");
+ ids_v = g_strsplit (ids, ",", -1);
+ for (i = 0; ids_v[i] != NULL; i++) {
+ int idx;
+ GthMetadataInfo *info;
+ const char *name;
+
+ idx = _g_strv_find (attributes_v, ids_v[i]);
+ if (idx < 0)
+ continue;
+
+ info = gth_main_get_metadata_info (attributes_v[idx]);
+ if ((info == NULL) || ((info->flags & self->priv->allowed_flags) == 0))
+ continue;
+
+ name = info->display_name;
+ if (name == NULL)
+ name = info->id;
+
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter,
+ NAME_COLUMN, name,
+ ID_COLUMN, info->id,
+ USED_COLUMN, TRUE,
+ SEPARATOR_COLUMN, FALSE,
+ -1);
+ }
+
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter,
+ SEPARATOR_COLUMN, TRUE,
+ -1);
+
+ for (i = 0; attributes_v[i] != NULL; i++) {
+ GtkTreeIter iter;
+ GthMetadataInfo *info;
+ const char *name;
+
+ if (_g_strv_find (ids_v, attributes_v[i]) >= 0)
+ continue;
+
+ info = gth_main_get_metadata_info (attributes_v[i]);
+ if ((info == NULL) || ((info->flags & self->priv->allowed_flags) == 0))
+ continue;
+
+ name = info->display_name;
+ if (name == NULL)
+ name = info->id;
+
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter,
+ NAME_COLUMN, name,
+ ID_COLUMN, info->id,
+ USED_COLUMN, FALSE,
+ SEPARATOR_COLUMN, FALSE,
+ -1);
+ }
+
+ g_signal_handler_unblock (store, self->priv->row_inserted_event);
+ g_signal_handler_unblock (store, self->priv->row_deleted_event);
+
+ g_strfreev (attributes_v);
+ g_strfreev (ids_v);
+}
+
+
+char *
+gth_metadata_chooser_get_selection (GthMetadataChooser *self)
+{
+ GString *selection;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+
+ selection = g_string_new ("");
+ model = gtk_tree_view_get_model (GTK_TREE_VIEW (self));
+ if (gtk_tree_model_get_iter_first (model, &iter)) {
+ do {
+ gboolean used;
+ char *id;
+
+ gtk_tree_model_get (model, &iter,
+ ID_COLUMN, &id,
+ USED_COLUMN, &used,
+ -1);
+
+ if (used) {
+ if (selection->len > 0)
+ g_string_append (selection, ",");
+ g_string_append (selection, id);
+ }
+
+ g_free (id);
+ }
+ while (gtk_tree_model_iter_next (model, &iter));
+ }
+
+ if (selection->len == 0)
+ g_string_append (selection, "none");
+
+ return g_string_free (selection, FALSE);
+}
diff --git a/gthumb/gth-metadata-chooser.h b/gthumb/gth-metadata-chooser.h
new file mode 100644
index 0000000..e51d1e1
--- /dev/null
+++ b/gthumb/gth-metadata-chooser.h
@@ -0,0 +1,63 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * GThumb
+ *
+ * Copyright (C) 2009 The Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef GTH_METADATA_CHOOSER_H
+#define GTH_METADATA_CHOOSER_H
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GTH_TYPE_METADATA_CHOOSER (gth_metadata_chooser_get_type ())
+#define GTH_METADATA_CHOOSER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTH_TYPE_METADATA_CHOOSER, GthMetadataChooser))
+#define GTH_METADATA_CHOOSER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTH_TYPE_METADATA_CHOOSER, GthMetadataChooserClass))
+#define GTH_IS_METADATA_CHOOSER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTH_TYPE_METADATA_CHOOSER))
+#define GTH_IS_METADATA_CHOOSER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTH_TYPE_METADATA_CHOOSER))
+#define GTH_METADATA_CHOOSER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTH_TYPE_METADATA_CHOOSER, GthMetadataChooserClass))
+
+typedef struct _GthMetadataChooser GthMetadataChooser;
+typedef struct _GthMetadataChooserClass GthMetadataChooserClass;
+typedef struct _GthMetadataChooserPrivate GthMetadataChooserPrivate;
+
+struct _GthMetadataChooser {
+ GtkTreeView parent_instance;
+ GthMetadataChooserPrivate *priv;
+};
+
+struct _GthMetadataChooserClass {
+ GtkTreeViewClass parent_class;
+
+ /*< signals >*/
+
+ void (*changed) (GthMetadataChooser *self);
+};
+
+GType gth_metadata_chooser_get_type (void);
+GtkWidget * gth_metadata_chooser_new (GthMetadataFlags allowed_flags);
+void gth_metadata_chooser_set_selection (GthMetadataChooser *self,
+ char *ids);
+char * gth_metadata_chooser_get_selection (GthMetadataChooser *self);
+
+G_END_DECLS
+
+#endif /* GTH_METADATA_CHOOSER_H */
+
diff --git a/gthumb/gth-uri-list.c b/gthumb/gth-uri-list.c
index 97c80cb..c33cae0 100644
--- a/gthumb/gth-uri-list.c
+++ b/gthumb/gth-uri-list.c
@@ -111,7 +111,7 @@ row_deleted_cb (GtkTreeModel *tree_model,
if (uri_list->priv->changed_id != 0)
g_source_remove (uri_list->priv->changed_id);
- uri_list->priv->changed_id = g_timeout_add (ORDER_CHANGED_DELAY, order_changed, uri_list);
+ uri_list->priv->changed_id = gdk_threads_add_timeout (ORDER_CHANGED_DELAY, order_changed, uri_list);
}
@@ -125,7 +125,7 @@ row_inserted_cb (GtkTreeModel *tree_model,
if (uri_list->priv->changed_id != 0)
g_source_remove (uri_list->priv->changed_id);
- uri_list->priv->changed_id = g_timeout_add (ORDER_CHANGED_DELAY, order_changed, uri_list);
+ uri_list->priv->changed_id = gdk_threads_add_timeout (ORDER_CHANGED_DELAY, order_changed, uri_list);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]