[gnome-color-manager] Ignore duplicate profiles by the MD5 checksum and add self test code to test this



commit 8ff51a149c69065162e645ca80f7a47fa0d8dede
Author: Richard Hughes <richard hughsie com>
Date:   Tue Jun 1 11:23:20 2010 +0100

    Ignore duplicate profiles by the MD5 checksum and add self test code to test this

 src/gcm-prefs.c         |    3 +
 src/gcm-profile-store.c |  179 +++++++++++++++++++++++++++++++++++++----------
 src/gcm-profile-store.h |    5 ++
 src/gcm-self-test.c     |   43 +++++++++++
 4 files changed, 192 insertions(+), 38 deletions(-)
---
diff --git a/src/gcm-prefs.c b/src/gcm-prefs.c
index c6d09fc..48e4bdb 100644
--- a/src/gcm-prefs.c
+++ b/src/gcm-prefs.c
@@ -2860,6 +2860,9 @@ gcm_prefs_startup_phase1_idle_cb (gpointer user_data)
 	gchar *intent_display;
 	gchar *intent_softproof;
 
+	/* search the disk for profiles */
+	gcm_profile_store_search_default (profile_store);
+
 	/* setup RGB combobox */
 	widget = GTK_WIDGET (gtk_builder_get_object (builder, "combobox_space_rgb"));
 	colorspace_rgb = g_settings_get_string (settings, GCM_SETTINGS_COLORSPACE_RGB);
diff --git a/src/gcm-profile-store.c b/src/gcm-profile-store.c
index 882fc53..7d45b52 100644
--- a/src/gcm-profile-store.c
+++ b/src/gcm-profile-store.c
@@ -41,9 +41,6 @@ static void     gcm_profile_store_finalize	(GObject     *object);
 
 #define GCM_PROFILE_STORE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GCM_TYPE_PROFILE_STORE, GcmProfileStorePrivate))
 
-static gboolean	gcm_profile_store_add_profiles_for_path	(GcmProfileStore *profile_store, const gchar *path);
-static void	gcm_profile_store_add_profiles		(GcmProfileStore *profile_store);
-
 /**
  * GcmProfileStorePrivate:
  *
@@ -138,22 +135,71 @@ out:
 }
 
 /**
- * gcm_profile_store_notify_filename_cb:
+ * gcm_profile_store_get_by_checksum:
+ *
+ * @profile_store: a valid %GcmProfileStore instance
+ * @checksum: the profile checksum
+ *
+ * Gets a profile.
+ *
+ * Return value: a valid %GcmProfile or %NULL. Free with g_object_unref()
  **/
-static void
-gcm_profile_store_notify_filename_cb (GcmProfile *profile, GParamSpec *pspec, GcmProfileStore *profile_store)
+GcmProfile *
+gcm_profile_store_get_by_checksum (GcmProfileStore *profile_store, const gchar *checksum)
 {
-	const gchar *description;
+	guint i;
+	GcmProfile *profile = NULL;
+	GcmProfile *profile_tmp;
+	const gchar *checksum_tmp;
+	GcmProfileStorePrivate *priv = profile_store->priv;
+
+	g_return_val_if_fail (GCM_IS_PROFILE_STORE (profile_store), NULL);
+	g_return_val_if_fail (checksum != NULL, NULL);
+
+	/* find profile */
+	for (i=0; i<priv->profile_array->len; i++) {
+		profile_tmp = g_ptr_array_index (priv->profile_array, i);
+		checksum_tmp = gcm_profile_get_checksum (profile_tmp);
+		if (g_strcmp0 (checksum, checksum_tmp) == 0) {
+			profile = g_object_ref (profile_tmp);
+			goto out;
+		}
+	}
+out:
+	return profile;
+}
+
+/**
+ * gcm_profile_store_remove_profile:
+ **/
+static gboolean
+gcm_profile_store_remove_profile (GcmProfileStore *profile_store, GcmProfile *profile)
+{
+	gboolean ret;
 	GcmProfileStorePrivate *priv = profile_store->priv;
 
 	/* remove from list */
-	g_ptr_array_remove (priv->profile_array, profile);
+	ret = g_ptr_array_remove (priv->profile_array, profile);
+	if (!ret) {
+		egg_warning ("failed to remove %s", gcm_profile_get_filename (profile));
+		goto out;
+	}
 
 	/* emit a signal */
-	description = gcm_profile_get_description (profile);
-	egg_debug ("emit removed (and changed): %s", description);
+	egg_debug ("emit removed (and changed): %s", gcm_profile_get_filename (profile));
 	g_signal_emit (profile_store, signals[SIGNAL_REMOVED], 0, profile);
 	g_signal_emit (profile_store, signals[SIGNAL_CHANGED], 0);
+out:
+	return ret;
+}
+
+/**
+ * gcm_profile_store_notify_filename_cb:
+ **/
+static void
+gcm_profile_store_notify_filename_cb (GcmProfile *profile, GParamSpec *pspec, GcmProfileStore *profile_store)
+{
+	gcm_profile_store_remove_profile (profile_store, profile);
 }
 
 /**
@@ -164,8 +210,10 @@ gcm_profile_store_add_profile (GcmProfileStore *profile_store, GFile *file)
 {
 	gboolean ret = FALSE;
 	GcmProfile *profile = NULL;
+	GcmProfile *profile_tmp = NULL;
 	GError *error = NULL;
 	gchar *filename = NULL;
+	const gchar *checksum;
 	GcmProfileStorePrivate *priv = profile_store->priv;
 
 	/* already added? */
@@ -183,6 +231,22 @@ gcm_profile_store_add_profile (GcmProfileStore *profile_store, GFile *file)
 		goto out;		
 	}
 
+	/* check the profile has not been added already */
+	checksum = gcm_profile_get_checksum (profile);
+	profile_tmp = gcm_profile_store_get_by_checksum (profile_store, checksum);
+	if (profile_tmp != NULL) {
+
+		/* we value a local file higher than the shared file */
+		if (gcm_profile_get_can_delete (profile_tmp)) {
+			egg_debug ("already added a deletable profile %s, cannot add %s",
+				   gcm_profile_get_filename (profile_tmp), filename);
+			goto out;
+		}
+
+		/* remove the old profile in favour of the new one */
+		gcm_profile_store_remove_profile (profile_store, profile_tmp);
+	}
+
 	/* add to array */
 	egg_debug ("parsed new profile '%s'", filename);
 	g_ptr_array_add (priv->profile_array, g_object_ref (profile));
@@ -194,6 +258,8 @@ gcm_profile_store_add_profile (GcmProfileStore *profile_store, GFile *file)
 	g_signal_emit (profile_store, signals[SIGNAL_CHANGED], 0);
 out:
 	g_free (filename);
+	if (profile_tmp != NULL)
+		g_object_unref (profile_tmp);
 	if (profile != NULL)
 		g_object_unref (profile);
 	return ret;
@@ -218,20 +284,23 @@ gcm_profile_store_file_monitor_changed_cb (GFileMonitor *monitor, GFile *file, G
 		goto out;
 	}
 	egg_debug ("%s was added, rescanning everything", path);
-	gcm_profile_store_add_profiles (profile_store);
+	gcm_profile_store_search_default (profile_store);
 out:
 	g_free (path);
 }
 
 /**
- * gcm_profile_store_add_profiles_for_path:
+ * gcm_profile_store_search_by_path:
+ *
+ * Return value: if any profile were added
  **/
-static gboolean
-gcm_profile_store_add_profiles_for_path (GcmProfileStore *profile_store, const gchar *path)
+gboolean
+gcm_profile_store_search_by_path (GcmProfileStore *profile_store, const gchar *path)
 {
 	GDir *dir = NULL;
 	GError *error = NULL;
-	gboolean ret = TRUE;
+	gboolean ret;
+	gboolean success = FALSE;
 	const gchar *name;
 	gchar *full_path;
 	GcmProfileStorePrivate *priv = profile_store->priv;
@@ -245,7 +314,7 @@ gcm_profile_store_add_profiles_for_path (GcmProfileStore *profile_store, const g
 		file = g_file_new_for_path (path);
 		ret = gcm_utils_is_icc_profile (file);
 		if (ret) {
-			gcm_profile_store_add_profile (profile_store, file);
+			success = gcm_profile_store_add_profile (profile_store, file);
 			goto out;
 		}
 
@@ -289,7 +358,9 @@ gcm_profile_store_add_profiles_for_path (GcmProfileStore *profile_store, const g
 
 		/* make the compete path */
 		full_path = g_build_filename (path, name, NULL);
-		gcm_profile_store_add_profiles_for_path (profile_store, full_path);
+		ret = gcm_profile_store_search_by_path (profile_store, full_path);
+		if (ret)
+			success = TRUE;
 		g_free (full_path);
 	} while (TRUE);
 out:
@@ -299,13 +370,13 @@ out:
 		g_object_unref (file);
 	if (dir != NULL)
 		g_dir_close (dir);
-	return ret;
+	return success;
 }
 
 /**
  * gcm_profile_store_add_profiles_from_mounted_volume:
  **/
-static void
+static gboolean
 gcm_profile_store_add_profiles_from_mounted_volume (GcmProfileStore *profile_store, GMount *mount)
 {
 	GFile *root;
@@ -314,6 +385,8 @@ gcm_profile_store_add_profiles_from_mounted_volume (GcmProfileStore *profile_sto
 	const gchar *type;
 	GFileInfo *info;
 	GError *error = NULL;
+	gboolean ret;
+	gboolean success = FALSE;
 
 	/* get the mount root */
 	root = g_mount_get_root (mount);
@@ -334,7 +407,9 @@ gcm_profile_store_add_profiles_from_mounted_volume (GcmProfileStore *profile_sto
 	/* only scan hfs volumes for OSX */
 	if (g_strcmp0 (type, "hfs") == 0) {
 		path = g_build_filename (path_root, "Library", "ColorSync", "Profiles", "Displays", NULL);
-		gcm_profile_store_add_profiles_for_path (profile_store, path);
+		ret = gcm_profile_store_search_by_path (profile_store, path);
+		if (ret)
+			success = TRUE;
 		g_free (path);
 
 		/* no more matching */
@@ -346,17 +421,23 @@ gcm_profile_store_add_profiles_from_mounted_volume (GcmProfileStore *profile_sto
 
 		/* Windows XP */
 		path = g_build_filename (path_root, "Windows", "system32", "spool", "drivers", "color", NULL);
-		gcm_profile_store_add_profiles_for_path (profile_store, path);
+		ret = gcm_profile_store_search_by_path (profile_store, path);
+		if (ret)
+			success = TRUE;
 		g_free (path);
 
 		/* Windows 2000 */
 		path = g_build_filename (path_root, "Winnt", "system32", "spool", "drivers", "color", NULL);
-		gcm_profile_store_add_profiles_for_path (profile_store, path);
+		ret = gcm_profile_store_search_by_path (profile_store, path);
+		if (ret)
+			success = TRUE;
 		g_free (path);
 
 		/* Windows 98 and ME */
 		path = g_build_filename (path_root, "Windows", "System", "Color", NULL);
-		gcm_profile_store_add_profiles_for_path (profile_store, path);
+		ret = gcm_profile_store_search_by_path (profile_store, path);
+		if (ret)
+			success = TRUE;
 		g_free (path);
 
 		/* no more matching */
@@ -365,14 +446,17 @@ gcm_profile_store_add_profiles_from_mounted_volume (GcmProfileStore *profile_sto
 out:
 	g_free (path_root);
 	g_object_unref (root);
+	return success;
 }
 
 /**
  * gcm_profile_store_add_profiles_from_mounted_volumes:
  **/
-static void
+static gboolean
 gcm_profile_store_add_profiles_from_mounted_volumes (GcmProfileStore *profile_store)
 {
+	gboolean ret;
+	gboolean success = FALSE;
 	GList *mounts, *l;
 	GMount *mount;
 	GcmProfileStorePrivate *priv = profile_store->priv;
@@ -381,32 +465,47 @@ gcm_profile_store_add_profiles_from_mounted_volumes (GcmProfileStore *profile_st
 	mounts = g_volume_monitor_get_mounts (priv->volume_monitor);
 	for (l = mounts; l != NULL; l = l->next) {
 		mount = l->data;
-		gcm_profile_store_add_profiles_from_mounted_volume (profile_store, mount);
+		ret = gcm_profile_store_add_profiles_from_mounted_volume (profile_store, mount);
+		if (ret)
+			success = TRUE;
 		g_object_unref (mount);
 	}
 	g_list_free (mounts);
+	return success;
 }
 
 /**
  * gcm_profile_store_add_profiles:
+ *
+ * Return value: if any profile were added
  **/
-static void
-gcm_profile_store_add_profiles (GcmProfileStore *profile_store)
+gboolean
+gcm_profile_store_search_default (GcmProfileStore *profile_store)
 {
 	gchar *path;
 	gboolean ret;
+	gboolean success = FALSE;
 	GError *error;
 	GcmProfileStorePrivate *priv = profile_store->priv;
 
 	/* get OSX and Linux system-wide profiles */
-	gcm_profile_store_add_profiles_for_path (profile_store, "/usr/share/color/icc");
-	gcm_profile_store_add_profiles_for_path (profile_store, "/usr/local/share/color/icc");
-	gcm_profile_store_add_profiles_for_path (profile_store, "/Library/ColorSync/Profiles/Displays");
+	ret = gcm_profile_store_search_by_path (profile_store, "/usr/share/color/icc");
+	if (ret)
+		success = TRUE;
+	ret = gcm_profile_store_search_by_path (profile_store, "/usr/local/share/color/icc");
+	if (ret)
+		success = TRUE;
+	ret = gcm_profile_store_search_by_path (profile_store, "/Library/ColorSync/Profiles/Displays");
+	if (ret)
+		success = TRUE;
 
 	/* get OSX and Windows system-wide profiles when using Linux */
 	ret = g_settings_get_boolean (priv->settings, GCM_SETTINGS_USE_PROFILES_FROM_VOLUMES);
-	if (ret)
-		gcm_profile_store_add_profiles_from_mounted_volumes (profile_store);
+	if (ret) {
+		ret = gcm_profile_store_add_profiles_from_mounted_volumes (profile_store);
+		if (ret)
+			success = TRUE;
+	}
 
 	/* get Linux per-user profiles */
 	path = g_build_filename (g_get_user_data_dir (), "icc", NULL);
@@ -415,19 +514,26 @@ gcm_profile_store_add_profiles (GcmProfileStore *profile_store)
 		egg_error ("failed to create directory on startup: %s", error->message);
 		g_error_free (error);
 	} else {
-		gcm_profile_store_add_profiles_for_path (profile_store, path);
+		ret = gcm_profile_store_search_by_path (profile_store, path);
+		if (ret)
+			success = TRUE;
 	}
 	g_free (path);
 
 	/* get per-user profiles from obsolete location */
 	path = g_build_filename (g_get_home_dir (), ".color", "icc", NULL);
-	gcm_profile_store_add_profiles_for_path (profile_store, path);
+	ret = gcm_profile_store_search_by_path (profile_store, path);
+	if (ret)
+		success = TRUE;
 	g_free (path);
 
 	/* get OSX per-user profiles */
 	path = g_build_filename (g_get_home_dir (), "Library", "ColorSync", "Profiles", NULL);
-	gcm_profile_store_add_profiles_for_path (profile_store, path);
+	ret = gcm_profile_store_search_by_path (profile_store, path);
+	if (ret)
+		success = TRUE;
 	g_free (path);
+	return success;
 }
 
 /**
@@ -497,9 +603,6 @@ gcm_profile_store_init (GcmProfileStore *profile_store)
 			  "mount-added",
 			  G_CALLBACK(gcm_profile_store_volume_monitor_mount_added_cb),
 			  profile_store);
-
-	/* get profiles */
-	gcm_profile_store_add_profiles (profile_store);
 }
 
 /**
diff --git a/src/gcm-profile-store.h b/src/gcm-profile-store.h
index ec593dd..7546ae3 100644
--- a/src/gcm-profile-store.h
+++ b/src/gcm-profile-store.h
@@ -64,7 +64,12 @@ GcmProfileStore	*gcm_profile_store_new			(void);
 
 GcmProfile	*gcm_profile_store_get_by_filename	(GcmProfileStore	*profile_store,
 							 const gchar		*filename);
+GcmProfile	*gcm_profile_store_get_by_checksum	(GcmProfileStore	*profile_store,
+							 const gchar		*checksum);
 GPtrArray	*gcm_profile_store_get_array		(GcmProfileStore	*profile_store);
+gboolean	 gcm_profile_store_search_default	(GcmProfileStore	*profile_store);
+gboolean	 gcm_profile_store_search_by_path	(GcmProfileStore	*profile_store,
+							 const gchar		*path);
 
 G_END_DECLS
 
diff --git a/src/gcm-self-test.c b/src/gcm-self-test.c
index 69328f6..a4ac4a7 100644
--- a/src/gcm-self-test.c
+++ b/src/gcm-self-test.c
@@ -40,6 +40,7 @@
 #include "gcm-image.h"
 #include "gcm-print.h"
 #include "gcm-profile.h"
+#include "gcm-profile-store.h"
 #include "gcm-profile-lcms1.h"
 #include "gcm-tables.h"
 #include "gcm-trc-widget.h"
@@ -816,6 +817,7 @@ typedef struct {
 	GcmProfileKind kind;
 	GcmColorspace colorspace;
 	gfloat luminance;
+	gboolean has_vcgt;
 } GcmProfileTestData;
 
 static void
@@ -849,6 +851,7 @@ gcm_test_profile_test_parse_file (const gchar *datafile, GcmProfileTestData *tes
 	g_assert_cmpstr (gcm_profile_get_checksum (profile_lcms1), ==, test_data->checksum);
 	g_assert_cmpint (gcm_profile_get_kind (profile_lcms1), ==, test_data->kind);
 	g_assert_cmpint (gcm_profile_get_colorspace (profile_lcms1), ==, test_data->colorspace);
+	g_assert_cmpint (gcm_profile_get_has_vcgt (profile_lcms1), ==, test_data->has_vcgt);
 
 	g_object_get (profile_lcms1,
 		      "red", &xyz,
@@ -876,6 +879,7 @@ gcm_test_profile_func (void)
 	test_data.luminance = 0.648454;
 	test_data.datetime = "February  9 1998, 06:49:00 AM";
 	test_data.checksum = "8e2aed5dac6f8b5d8da75610a65b7f27";
+	test_data.has_vcgt = TRUE;
 	gcm_test_profile_test_parse_file ("bluish.icc", &test_data);
 
 	/* Adobe test */
@@ -888,10 +892,48 @@ gcm_test_profile_func (void)
 	test_data.luminance = 0.648446;
 	test_data.datetime = "August 16 2005, 09:49:54 PM";
 	test_data.checksum = "bd847723f676e2b846daaf6759330624";
+	test_data.has_vcgt = TRUE;
 	gcm_test_profile_test_parse_file ("AdobeGammaTest.icm", &test_data);
 }
 
 static void
+gcm_test_profile_store_func (void)
+{
+	GcmProfileStore *store;
+	GPtrArray *array;
+	GcmProfile *profile;
+	gboolean ret;
+	gchar *filename;
+
+	store = gcm_profile_store_new ();
+	g_assert (store != NULL);
+
+	/* add test files */
+	filename = gcm_test_get_data_file (".");
+	ret = gcm_profile_store_search_by_path (store, filename);
+	g_assert (ret);
+	g_free (filename);
+
+	/* profile does not exist */
+	profile = gcm_profile_store_get_by_filename (store, "xxxxxxxxx");
+	g_assert (profile == NULL);
+
+	/* profile does exist */
+	profile = gcm_profile_store_get_by_checksum (store, "8e2aed5dac6f8b5d8da75610a65b7f27");
+	g_assert (profile != NULL);
+	g_assert_cmpstr (gcm_profile_get_checksum (profile), ==, "8e2aed5dac6f8b5d8da75610a65b7f27");
+	g_object_unref (profile);
+
+	/* get array of profiles */
+	array = gcm_profile_store_get_array (store);
+	g_assert (array != NULL);
+	g_assert_cmpint (array->len, ==, 3);
+	g_ptr_array_unref (array);
+
+	g_object_unref (store);
+}
+
+static void
 gcm_test_tables_func (void)
 {
 	GcmTables *tables;
@@ -1197,6 +1239,7 @@ main (int argc, char **argv)
 	g_test_add_func ("/color/utils", gcm_test_utils_func);
 	g_test_add_func ("/color/device", gcm_test_device_func);
 	g_test_add_func ("/color/profile", gcm_test_profile_func);
+	g_test_add_func ("/color/profile_store", gcm_test_profile_store_func);
 	g_test_add_func ("/color/clut", gcm_test_clut_func);
 	g_test_add_func ("/color/xyz", gcm_test_xyz_func);
 	g_test_add_func ("/color/calibrate_dialog", gcm_test_calibrate_dialog_func);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]