summaryrefslogtreecommitdiffstats
path: root/libgimpwidgets/gimpcolorprofilestore.c
diff options
context:
space:
mode:
Diffstat (limited to 'libgimpwidgets/gimpcolorprofilestore.c')
-rw-r--r--libgimpwidgets/gimpcolorprofilestore.c794
1 files changed, 794 insertions, 0 deletions
diff --git a/libgimpwidgets/gimpcolorprofilestore.c b/libgimpwidgets/gimpcolorprofilestore.c
new file mode 100644
index 0000000..324e4c6
--- /dev/null
+++ b/libgimpwidgets/gimpcolorprofilestore.c
@@ -0,0 +1,794 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
+ *
+ * gimpprofilestore.c
+ * Copyright (C) 2004-2008 Sven Neumann <sven@gimp.org>
+ *
+ * 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 3 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
+ * <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include <gtk/gtk.h>
+
+#include "libgimpbase/gimpbase.h"
+#include "libgimpconfig/gimpconfig.h"
+
+#include "gimpwidgetstypes.h"
+
+#include "gimpcolorprofilestore.h"
+#include "gimpcolorprofilestore-private.h"
+
+#include "libgimp/libgimp-intl.h"
+
+
+/**
+ * SECTION: gimpcolorprofilestore
+ * @title: GimpColorProfileStore
+ * @short_description: A #GtkListStore subclass that keep color profiles.
+ *
+ * A #GtkListStore subclass that keep color profiles.
+ **/
+
+
+#define HISTORY_SIZE 8
+
+enum
+{
+ PROP_0,
+ PROP_HISTORY
+};
+
+
+static void gimp_color_profile_store_constructed (GObject *object);
+static void gimp_color_profile_store_dispose (GObject *object);
+static void gimp_color_profile_store_finalize (GObject *object);
+static void gimp_color_profile_store_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void gimp_color_profile_store_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec);
+
+static gboolean gimp_color_profile_store_history_insert (GimpColorProfileStore *store,
+ GtkTreeIter *iter,
+ GFile *file,
+ const gchar *label,
+ gint index);
+static void gimp_color_profile_store_get_separator (GimpColorProfileStore *store,
+ GtkTreeIter *iter,
+ gboolean top);
+static gboolean gimp_color_profile_store_save (GimpColorProfileStore *store,
+ const gchar *filename,
+ GError **error);
+static gboolean gimp_color_profile_store_load (GimpColorProfileStore *store,
+ const gchar *filename,
+ GError **error);
+
+
+G_DEFINE_TYPE (GimpColorProfileStore,
+ gimp_color_profile_store, GTK_TYPE_LIST_STORE)
+
+#define parent_class gimp_color_profile_store_parent_class
+
+
+static void
+gimp_color_profile_store_class_init (GimpColorProfileStoreClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->constructed = gimp_color_profile_store_constructed;
+ object_class->dispose = gimp_color_profile_store_dispose;
+ object_class->finalize = gimp_color_profile_store_finalize;
+ object_class->set_property = gimp_color_profile_store_set_property;
+ object_class->get_property = gimp_color_profile_store_get_property;
+
+ /**
+ * GimpColorProfileStore:history:
+ *
+ * Filename of the color history used to populate the profile store.
+ *
+ * Since: 2.4
+ */
+ g_object_class_install_property (object_class,
+ PROP_HISTORY,
+ g_param_spec_string ("history",
+ "History",
+ "Filename of the color history used to populate the profile store",
+ NULL,
+ G_PARAM_CONSTRUCT_ONLY |
+ GIMP_PARAM_READWRITE));
+}
+
+static void
+gimp_color_profile_store_init (GimpColorProfileStore *store)
+{
+ GType types[] =
+ {
+ G_TYPE_INT, /* GIMP_COLOR_PROFILE_STORE_ITEM_TYPE */
+ G_TYPE_STRING, /* GIMP_COLOR_PROFILE_STORE_LABEL */
+ G_TYPE_FILE, /* GIMP_COLOR_PROFILE_STORE_FILE */
+ G_TYPE_INT /* GIMP_COLOR_PROFILE_STORE_INDEX */
+ };
+
+ gtk_list_store_set_column_types (GTK_LIST_STORE (store),
+ G_N_ELEMENTS (types), types);
+}
+
+static void
+gimp_color_profile_store_constructed (GObject *object)
+{
+ GimpColorProfileStore *store = GIMP_COLOR_PROFILE_STORE (object);
+ GtkTreeIter iter;
+
+ G_OBJECT_CLASS (parent_class)->constructed (object);
+
+ gtk_list_store_append (GTK_LIST_STORE (store), &iter);
+ gtk_list_store_set (GTK_LIST_STORE (store), &iter,
+ GIMP_COLOR_PROFILE_STORE_ITEM_TYPE,
+ GIMP_COLOR_PROFILE_STORE_ITEM_DIALOG,
+ GIMP_COLOR_PROFILE_STORE_LABEL,
+ _("Select color profile from disk..."),
+ -1);
+
+ if (store->history)
+ {
+ gimp_color_profile_store_load (store, store->history, NULL);
+ }
+}
+
+static void
+gimp_color_profile_store_dispose (GObject *object)
+{
+ GimpColorProfileStore *store = GIMP_COLOR_PROFILE_STORE (object);
+
+ if (store->history)
+ {
+ gimp_color_profile_store_save (store, store->history, NULL);
+ }
+
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+gimp_color_profile_store_finalize (GObject *object)
+{
+ GimpColorProfileStore *store = GIMP_COLOR_PROFILE_STORE (object);
+
+ g_clear_pointer (&store->history, g_free);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+gimp_color_profile_store_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GimpColorProfileStore *store = GIMP_COLOR_PROFILE_STORE (object);
+
+ switch (property_id)
+ {
+ case PROP_HISTORY:
+ g_return_if_fail (store->history == NULL);
+ store->history = g_value_dup_string (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+gimp_color_profile_store_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GimpColorProfileStore *store = GIMP_COLOR_PROFILE_STORE (object);
+
+ switch (property_id)
+ {
+ case PROP_HISTORY:
+ g_value_set_string (value, store->history);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+
+/**
+ * gimp_color_profile_store_new:
+ * @history: filename of the profilerc (or %NULL for no history)
+ *
+ * Creates a new #GimpColorProfileStore object and populates it with
+ * last used profiles read from the file @history. The updated history
+ * is written back to disk when the store is disposed.
+ *
+ * The filename passed as @history is typically created using the
+ * following code snippet:
+ * <informalexample><programlisting>
+ * gchar *history = gimp_personal_rc_file ("profilerc");
+ * </programlisting></informalexample>
+ *
+ * Return value: a new #GimpColorProfileStore
+ *
+ * Since: 2.4
+ **/
+GtkListStore *
+gimp_color_profile_store_new (const gchar *history)
+{
+ return g_object_new (GIMP_TYPE_COLOR_PROFILE_STORE,
+ "history", history,
+ NULL);
+}
+
+/**
+ * gimp_color_profile_store_add:
+ * @store: a #GimpColorProfileStore
+ * @filename: filename of the profile to add (or %NULL)
+ * @label: label to use for the profile
+ * (may only be %NULL if @filename is %NULL)
+ *
+ * Adds a color profile item to the #GimpColorProfileStore. Items
+ * added with this function will be kept at the top, separated from
+ * the history of last used color profiles.
+ *
+ * This function is often used to add a selectable item for the %NULL
+ * filename. If you pass %NULL for both @filename and @label, the
+ * @label will be set to the string "None" for you (and translated for
+ * the user).
+ *
+ * Deprecated: use gimp_color_profile_store_add_file() instead.
+ *
+ * Since: 2.4
+ **/
+void
+gimp_color_profile_store_add (GimpColorProfileStore *store,
+ const gchar *filename,
+ const gchar *label)
+{
+ GFile *file = NULL;
+
+ g_return_if_fail (GIMP_IS_COLOR_PROFILE_STORE (store));
+ g_return_if_fail (label != NULL || filename == NULL);
+
+ if (filename)
+ file = g_file_new_for_path (filename);
+
+ gimp_color_profile_store_add_file (store, file, label);
+
+ g_object_unref (file);
+}
+
+/**
+ * gimp_color_profile_store_add_file:
+ * @store: a #GimpColorProfileStore
+ * @file: file of the profile to add (or %NULL)
+ * @label: label to use for the profile
+ * (may only be %NULL if @filename is %NULL)
+ *
+ * Adds a color profile item to the #GimpColorProfileStore. Items
+ * added with this function will be kept at the top, separated from
+ * the history of last used color profiles.
+ *
+ * This function is often used to add a selectable item for the %NULL
+ * file. If you pass %NULL for both @file and @label, the @label will
+ * be set to the string "None" for you (and translated for the user).
+ *
+ * Since: 2.10
+ **/
+void
+gimp_color_profile_store_add_file (GimpColorProfileStore *store,
+ GFile *file,
+ const gchar *label)
+{
+ GtkTreeIter separator;
+ GtkTreeIter iter;
+
+ g_return_if_fail (GIMP_IS_COLOR_PROFILE_STORE (store));
+ g_return_if_fail (label != NULL || file == NULL);
+ g_return_if_fail (file == NULL || G_IS_FILE (file));
+
+ if (! file && ! label)
+ label = C_("profile", "None");
+
+ gimp_color_profile_store_get_separator (store, &separator, TRUE);
+
+ gtk_list_store_insert_before (GTK_LIST_STORE (store), &iter, &separator);
+ gtk_list_store_set (GTK_LIST_STORE (store), &iter,
+ GIMP_COLOR_PROFILE_STORE_ITEM_TYPE,
+ GIMP_COLOR_PROFILE_STORE_ITEM_FILE,
+ GIMP_COLOR_PROFILE_STORE_FILE, file,
+ GIMP_COLOR_PROFILE_STORE_LABEL, label,
+ GIMP_COLOR_PROFILE_STORE_INDEX, -1,
+ -1);
+}
+
+/**
+ * _gimp_color_profile_store_history_add:
+ * @store: a #GimpColorProfileStore
+ * @file: file of the profile to add (or %NULL)
+ * @label: label to use for the profile (or %NULL)
+ * @iter: a #GtkTreeIter
+ *
+ * Return value: %TRUE if the iter is valid and pointing to the item
+ *
+ * Since: 2.4
+ **/
+gboolean
+_gimp_color_profile_store_history_add (GimpColorProfileStore *store,
+ GFile *file,
+ const gchar *label,
+ GtkTreeIter *iter)
+{
+ GtkTreeModel *model;
+ gboolean iter_valid;
+ gint max = -1;
+
+ g_return_val_if_fail (GIMP_IS_COLOR_PROFILE_STORE (store), FALSE);
+ g_return_val_if_fail (iter != NULL, FALSE);
+
+ model = GTK_TREE_MODEL (store);
+
+ for (iter_valid = gtk_tree_model_get_iter_first (model, iter);
+ iter_valid;
+ iter_valid = gtk_tree_model_iter_next (model, iter))
+ {
+ gint type;
+ gint index;
+ GFile *this;
+
+ gtk_tree_model_get (model, iter,
+ GIMP_COLOR_PROFILE_STORE_ITEM_TYPE, &type,
+ GIMP_COLOR_PROFILE_STORE_INDEX, &index,
+ -1);
+
+ if (type != GIMP_COLOR_PROFILE_STORE_ITEM_FILE)
+ continue;
+
+ if (index > max)
+ max = index;
+
+ /* check if we found a filename match */
+ gtk_tree_model_get (model, iter,
+ GIMP_COLOR_PROFILE_STORE_FILE, &this,
+ -1);
+
+ if ((this && file && g_file_equal (this, file)) ||
+ (! this && ! file))
+ {
+ /* update the label */
+ if (label && *label)
+ gtk_list_store_set (GTK_LIST_STORE (store), iter,
+ GIMP_COLOR_PROFILE_STORE_LABEL, label,
+ -1);
+
+ if (this)
+ g_object_unref (this);
+
+ return TRUE;
+ }
+
+ if (this)
+ g_object_unref (this);
+ }
+
+ if (! file)
+ return FALSE;
+
+ if (label && *label)
+ {
+ iter_valid = gimp_color_profile_store_history_insert (store, iter,
+ file, label,
+ ++max);
+ }
+ else
+ {
+ const gchar *utf8 = gimp_file_get_utf8_name (file);
+ gchar *basename = g_path_get_basename (utf8);
+
+ iter_valid = gimp_color_profile_store_history_insert (store, iter,
+ file, basename,
+ ++max);
+ g_free (basename);
+ }
+
+ return iter_valid;
+}
+
+/**
+ * _gimp_color_profile_store_history_reorder
+ * @store: a #GimpColorProfileStore
+ * @iter: a #GtkTreeIter
+ *
+ * Moves the entry pointed to by @iter to the front of the MRU list.
+ *
+ * Since: 2.4
+ **/
+void
+_gimp_color_profile_store_history_reorder (GimpColorProfileStore *store,
+ GtkTreeIter *iter)
+{
+ GtkTreeModel *model;
+ gint index;
+ gboolean iter_valid;
+
+ g_return_if_fail (GIMP_IS_COLOR_PROFILE_STORE (store));
+ g_return_if_fail (iter != NULL);
+
+ model = GTK_TREE_MODEL (store);
+
+ gtk_tree_model_get (model, iter,
+ GIMP_COLOR_PROFILE_STORE_INDEX, &index,
+ -1);
+
+ if (index == 0)
+ return; /* already at the top */
+
+ for (iter_valid = gtk_tree_model_get_iter_first (model, iter);
+ iter_valid;
+ iter_valid = gtk_tree_model_iter_next (model, iter))
+ {
+ gint type;
+ gint this_index;
+
+ gtk_tree_model_get (model, iter,
+ GIMP_COLOR_PROFILE_STORE_ITEM_TYPE, &type,
+ GIMP_COLOR_PROFILE_STORE_INDEX, &this_index,
+ -1);
+
+ if (type == GIMP_COLOR_PROFILE_STORE_ITEM_FILE && this_index > -1)
+ {
+ if (this_index < index)
+ {
+ this_index++;
+ }
+ else if (this_index == index)
+ {
+ this_index = 0;
+ }
+
+ gtk_list_store_set (GTK_LIST_STORE (store), iter,
+ GIMP_COLOR_PROFILE_STORE_INDEX, this_index,
+ -1);
+ }
+ }
+}
+
+static gboolean
+gimp_color_profile_store_history_insert (GimpColorProfileStore *store,
+ GtkTreeIter *iter,
+ GFile *file,
+ const gchar *label,
+ gint index)
+{
+ GtkTreeModel *model = GTK_TREE_MODEL (store);
+ GtkTreeIter sibling;
+ gboolean iter_valid;
+
+ g_return_val_if_fail (G_IS_FILE (file), FALSE);
+ g_return_val_if_fail (label != NULL, FALSE);
+ g_return_val_if_fail (index > -1, FALSE);
+
+ gimp_color_profile_store_get_separator (store, iter, FALSE);
+
+ for (iter_valid = gtk_tree_model_get_iter_first (model, &sibling);
+ iter_valid;
+ iter_valid = gtk_tree_model_iter_next (model, &sibling))
+ {
+ gint type;
+ gint this_index;
+
+ gtk_tree_model_get (model, &sibling,
+ GIMP_COLOR_PROFILE_STORE_ITEM_TYPE, &type,
+ GIMP_COLOR_PROFILE_STORE_INDEX, &this_index,
+ -1);
+
+ if (type == GIMP_COLOR_PROFILE_STORE_ITEM_SEPARATOR_BOTTOM)
+ {
+ gtk_list_store_insert_before (GTK_LIST_STORE (store),
+ iter, &sibling);
+ break;
+ }
+
+ if (type == GIMP_COLOR_PROFILE_STORE_ITEM_FILE && this_index > -1)
+ {
+ gchar *this_label;
+
+ gtk_tree_model_get (model, &sibling,
+ GIMP_COLOR_PROFILE_STORE_LABEL, &this_label,
+ -1);
+
+ if (this_label && g_utf8_collate (label, this_label) < 0)
+ {
+ gtk_list_store_insert_before (GTK_LIST_STORE (store),
+ iter, &sibling);
+ g_free (this_label);
+ break;
+ }
+
+ g_free (this_label);
+ }
+ }
+
+ if (iter_valid)
+ gtk_list_store_set (GTK_LIST_STORE (store), iter,
+ GIMP_COLOR_PROFILE_STORE_ITEM_TYPE,
+ GIMP_COLOR_PROFILE_STORE_ITEM_FILE,
+ GIMP_COLOR_PROFILE_STORE_FILE, file,
+ GIMP_COLOR_PROFILE_STORE_LABEL, label,
+ GIMP_COLOR_PROFILE_STORE_INDEX, index,
+ -1);
+
+ return iter_valid;
+}
+
+static void
+gimp_color_profile_store_create_separator (GimpColorProfileStore *store,
+ GtkTreeIter *iter,
+ gboolean top)
+{
+ if (top)
+ {
+ gtk_list_store_prepend (GTK_LIST_STORE (store), iter);
+ }
+ else
+ {
+ GtkTreeModel *model = GTK_TREE_MODEL (store);
+ GtkTreeIter sibling;
+ gboolean iter_valid;
+
+ for (iter_valid = gtk_tree_model_get_iter_first (model, &sibling);
+ iter_valid;
+ iter_valid = gtk_tree_model_iter_next (model, &sibling))
+ {
+ gint type;
+
+ gtk_tree_model_get (model, &sibling,
+ GIMP_COLOR_PROFILE_STORE_ITEM_TYPE, &type,
+ -1);
+
+ if (type == GIMP_COLOR_PROFILE_STORE_ITEM_DIALOG)
+ break;
+ }
+
+ if (iter_valid)
+ gtk_list_store_insert_before (GTK_LIST_STORE (store), iter, &sibling);
+ }
+
+ gtk_list_store_set (GTK_LIST_STORE (store), iter,
+ GIMP_COLOR_PROFILE_STORE_ITEM_TYPE,
+ top ?
+ GIMP_COLOR_PROFILE_STORE_ITEM_SEPARATOR_TOP :
+ GIMP_COLOR_PROFILE_STORE_ITEM_SEPARATOR_BOTTOM,
+ GIMP_COLOR_PROFILE_STORE_INDEX, -1,
+ -1);
+}
+
+static void
+gimp_color_profile_store_get_separator (GimpColorProfileStore *store,
+ GtkTreeIter *iter,
+ gboolean top)
+{
+ GtkTreeModel *model = GTK_TREE_MODEL (store);
+ gboolean iter_valid;
+ gint needle;
+
+ needle = (top ?
+ GIMP_COLOR_PROFILE_STORE_ITEM_SEPARATOR_TOP :
+ GIMP_COLOR_PROFILE_STORE_ITEM_SEPARATOR_BOTTOM);
+
+ for (iter_valid = gtk_tree_model_get_iter_first (model, iter);
+ iter_valid;
+ iter_valid = gtk_tree_model_iter_next (model, iter))
+ {
+ gint type;
+
+ gtk_tree_model_get (model, iter,
+ GIMP_COLOR_PROFILE_STORE_ITEM_TYPE, &type,
+ -1);
+
+ if (type == needle)
+ return;
+ }
+
+ gimp_color_profile_store_create_separator (store, iter, top);
+}
+
+static GTokenType
+gimp_color_profile_store_load_profile (GimpColorProfileStore *store,
+ GScanner *scanner,
+ gint index)
+{
+ GtkTreeIter iter;
+ gchar *label = NULL;
+ gchar *path = NULL;
+
+ if (gimp_scanner_parse_string (scanner, &label) &&
+ gimp_scanner_parse_string (scanner, &path))
+ {
+ GFile *file = NULL;
+
+ if (g_str_has_prefix (path, "file://"))
+ {
+ file = g_file_new_for_uri (path);
+ }
+ else
+ {
+ file = gimp_file_new_for_config_path (path, NULL);
+ }
+
+ if (file)
+ {
+ if (g_file_query_file_type (file, 0, NULL) == G_FILE_TYPE_REGULAR)
+ {
+ gimp_color_profile_store_history_insert (store, &iter,
+ file, label, index);
+ }
+
+ g_object_unref (file);
+ }
+
+ g_free (label);
+ g_free (path);
+
+ return G_TOKEN_RIGHT_PAREN;
+ }
+
+ g_free (label);
+ g_free (path);
+
+ return G_TOKEN_STRING;
+}
+
+static gboolean
+gimp_color_profile_store_load (GimpColorProfileStore *store,
+ const gchar *filename,
+ GError **error)
+{
+ GScanner *scanner;
+ GTokenType token;
+ gint i = 0;
+
+ scanner = gimp_scanner_new_file (filename, error);
+ if (! scanner)
+ return FALSE;
+
+ g_scanner_scope_add_symbol (scanner, 0, "color-profile", NULL);
+
+ token = G_TOKEN_LEFT_PAREN;
+
+ while (g_scanner_peek_next_token (scanner) == token)
+ {
+ token = g_scanner_get_next_token (scanner);
+
+ switch (token)
+ {
+ case G_TOKEN_LEFT_PAREN:
+ token = G_TOKEN_SYMBOL;
+ break;
+
+ case G_TOKEN_SYMBOL:
+ token = gimp_color_profile_store_load_profile (store, scanner, i++);
+ break;
+
+ case G_TOKEN_RIGHT_PAREN:
+ token = G_TOKEN_LEFT_PAREN;
+ break;
+
+ default: /* do nothing */
+ break;
+ }
+ }
+
+ if (token != G_TOKEN_LEFT_PAREN)
+ {
+ g_scanner_get_next_token (scanner);
+ g_scanner_unexp_token (scanner, token, NULL, NULL, NULL,
+ _("fatal parse error"), TRUE);
+ }
+
+ gimp_scanner_destroy (scanner);
+
+ return TRUE;
+}
+
+static gboolean
+gimp_color_profile_store_save (GimpColorProfileStore *store,
+ const gchar *filename,
+ GError **error)
+{
+ GimpConfigWriter *writer;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ gchar *labels[HISTORY_SIZE] = { NULL, };
+ GFile *files[HISTORY_SIZE] = { NULL, };
+ gboolean iter_valid;
+ gint i;
+
+ writer = gimp_config_writer_new_file (filename,
+ TRUE,
+ "GIMP color profile history",
+ error);
+ if (! writer)
+ return FALSE;
+
+ model = GTK_TREE_MODEL (store);
+
+ for (iter_valid = gtk_tree_model_get_iter_first (model, &iter);
+ iter_valid;
+ iter_valid = gtk_tree_model_iter_next (model, &iter))
+ {
+ gint type;
+ gint index;
+
+ gtk_tree_model_get (model, &iter,
+ GIMP_COLOR_PROFILE_STORE_ITEM_TYPE, &type,
+ GIMP_COLOR_PROFILE_STORE_INDEX, &index,
+ -1);
+
+ if (type == GIMP_COLOR_PROFILE_STORE_ITEM_FILE &&
+ index >= 0 &&
+ index < HISTORY_SIZE)
+ {
+ if (labels[index] || files[index])
+ g_warning ("%s: double index %d", G_STRFUNC, index);
+
+ gtk_tree_model_get (model, &iter,
+ GIMP_COLOR_PROFILE_STORE_LABEL,
+ &labels[index],
+ GIMP_COLOR_PROFILE_STORE_FILE,
+ &files[index],
+ -1);
+ }
+ }
+
+
+ for (i = 0; i < HISTORY_SIZE; i++)
+ {
+ if (files[i] && labels[i])
+ {
+ gchar *path = gimp_file_get_config_path (files[i], NULL);
+
+ if (path)
+ {
+ gimp_config_writer_open (writer, "color-profile");
+ gimp_config_writer_string (writer, labels[i]);
+ gimp_config_writer_string (writer, path);
+ gimp_config_writer_close (writer);
+
+ g_free (path);
+ }
+ }
+
+ if (files[i])
+ g_object_unref (files[i]);
+
+ g_free (labels[i]);
+ }
+
+ return gimp_config_writer_finish (writer,
+ "end of color profile history", error);
+}