[brasero] Add support for icons for data projects through autorun.inf file



commit bdde2bec642087968b642f886e0dac4153beb766
Author: Philippe Rouquier <bonfire-app wanadoo fr>
Date:   Sat May 23 15:38:35 2009 +0200

    Add support for icons for data projects through autorun.inf file
    Fix #438859 â?? Allow burned disk icon customization
    Also fixes a few memory leaks
---
 libbrasero-burn/brasero-burn-options.c    |    3 +-
 libbrasero-burn/brasero-data-project.c    |  516 +++++++++++++++++++------
 libbrasero-burn/brasero-data-project.h    |   14 +
 libbrasero-burn/brasero-data-tree-model.c |    9 +
 libbrasero-burn/brasero-data-vfs.c        |    1 -
 libbrasero-burn/brasero-file-node.c       |  154 ++++++--
 libbrasero-burn/brasero-file-node.h       |   35 +-
 libbrasero-burn/brasero-src-image.c       |    3 +-
 libbrasero-burn/brasero-track-data-cfg.c  |  601 ++++++++++++++++++++++++-----
 libbrasero-burn/brasero-track-data-cfg.h  |   18 +-
 libbrasero-burn/libbrasero-marshal.list   |    1 +
 src/brasero-data-disc.c                   |   81 ++++-
 src/brasero-data-disc.h                   |    7 +
 src/brasero-project-parse.c               |   17 +
 src/brasero-project-parse.h               |    1 +
 src/brasero-project.c                     |  153 ++++++++
 16 files changed, 1346 insertions(+), 268 deletions(-)

diff --git a/libbrasero-burn/brasero-burn-options.c b/libbrasero-burn/brasero-burn-options.c
index cb3d550..8a52682 100644
--- a/libbrasero-burn/brasero-burn-options.c
+++ b/libbrasero-burn/brasero-burn-options.c
@@ -427,7 +427,8 @@ brasero_burn_options_update_valid (BraseroBurnOptions *self)
 		if (priv->message_input) {
 			gtk_widget_show (priv->message_input);
 			message = brasero_notify_message_add (BRASERO_NOTIFY (priv->message_input),
-							      _("Please select another image."),
+							      /* Translators: this is a disc image not a picture */
+							      C_("disc", "Please select another image."),
 							      _("It doesn't appear to be a valid image or a valid cue file."),
 							      -1,
 							      BRASERO_NOTIFY_CONTEXT_SIZE);
diff --git a/libbrasero-burn/brasero-data-project.c b/libbrasero-burn/brasero-data-project.c
index 11473e1..6661b7c 100644
--- a/libbrasero-burn/brasero-data-project.c
+++ b/libbrasero-burn/brasero-data-project.c
@@ -111,6 +111,7 @@ enum {
 	DEEP_DIRECTORY_SIGNAL,
 	G2_FILE_SIGNAL,
 	PROJECT_LOADED_SIGNAL,
+	VIRTUAL_SIBLING_SIGNAL,
 	LAST_SIGNAL
 };
 
@@ -126,6 +127,90 @@ typedef gboolean	(*BraseroDataNodeAddedFunc)	(BraseroDataProject *project,
 							 BraseroFileNode *node,
 							 const gchar *uri);
 
+static void
+brasero_data_project_virtual_sibling (BraseroDataProject *self,
+				      BraseroFileNode *node,
+				      BraseroFileNode *sibling)
+{
+	BraseroDataProjectPrivate *priv;
+	BraseroFileTreeStats *stats;
+	BraseroFileNode *children;
+	BraseroFileNode *iter;
+
+	if (sibling == node)
+		return;
+
+	priv = BRASERO_DATA_PROJECT_PRIVATE (self);
+
+	g_signal_emit (self,
+		       brasero_data_project_signals [VIRTUAL_SIBLING_SIGNAL],
+		       0,
+		       node,
+		       sibling);
+
+	stats = brasero_file_node_get_tree_stats (priv->root, NULL);
+	if (node) {
+		/* we remove the virtual node, BUT, we keep its
+		 * virtual children that will be appended to the
+		 * node being moved in replacement. */
+		/* NOTE: children MUST all be virtual */
+		children = BRASERO_FILE_NODE_CHILDREN (sibling);
+		for (iter = children; iter; iter = iter->next)
+			brasero_file_node_add (node, iter, NULL);
+
+		sibling->union2.children = NULL;
+	}
+	else {
+		/* Remove the virtual node. This should never happens */
+		g_warning ("Virtual nodes could not be transfered");
+	}
+
+	/* Just destroy the node as it has no other 
+	 * existence nor goal in existence but to create
+	 * a collision. */
+	brasero_file_node_destroy (sibling, stats);
+}
+
+static gboolean
+brasero_data_project_node_signal (BraseroDataProject *self,
+				  guint signal,
+				  BraseroFileNode *node)
+{
+	GValue instance_and_params [2];
+	GValue return_value;
+	GValue *params;
+
+	/* object which signalled */
+	instance_and_params->g_type = 0;
+	g_value_init (instance_and_params, G_TYPE_FROM_INSTANCE (self));
+	g_value_set_instance (instance_and_params, self);
+
+	/* arguments of signal (name) */
+	params = instance_and_params + 1;
+	params->g_type = 0;
+	g_value_init (params, G_TYPE_POINTER);
+	g_value_set_pointer (params, node);
+
+	/* default to FALSE */
+	return_value.g_type = 0;
+	g_value_init (&return_value, G_TYPE_BOOLEAN);
+	g_value_set_boolean (&return_value, FALSE);
+
+	g_signal_emitv (instance_and_params,
+			brasero_data_project_signals [signal],
+			0,
+			&return_value);
+
+	g_value_unset (instance_and_params);
+	g_value_unset (params);
+
+	/* In this case always remove the sibling */
+	if (signal == NAME_COLLISION_SIGNAL && BRASERO_FILE_NODE_VIRTUAL (node))
+		return FALSE;
+
+	return g_value_get_boolean (&return_value);
+}
+
 static gboolean
 brasero_data_project_file_signal (BraseroDataProject *self,
 				  guint signal,
@@ -1300,6 +1385,53 @@ brasero_data_project_is_deep (BraseroDataProject *self,
 	return TRUE;
 }
 
+static void
+brasero_data_project_remove_sibling (BraseroDataProject *self,
+				     BraseroFileNode *sibling,
+				     BraseroFileNode *replacement)
+{
+	BraseroDataProjectPrivate *priv;
+
+	if (sibling != replacement)
+		return;
+
+	priv = BRASERO_DATA_PROJECT_PRIVATE (self);
+
+	if (BRASERO_FILE_NODE_VIRTUAL (sibling)) {
+		BraseroFileTreeStats *stats;
+		BraseroFileNode *children;
+		BraseroFileNode *iter;
+
+		stats = brasero_file_node_get_tree_stats (priv->root, NULL);
+		if (replacement) {
+			/* we remove the virtual node, BUT, we keep its
+			 * virtual children that will be appended to the
+			 * node being moved in replacement. */
+			/* NOTE: children MUST all be virtual */
+			children = BRASERO_FILE_NODE_CHILDREN (sibling);
+			for (iter = children; iter; iter = iter->next)
+				brasero_file_node_add (replacement, iter, NULL);
+
+			sibling->union2.children = NULL;
+		}
+		else {
+			/* Remove the virtual node. This should never happens */
+			g_warning ("Virtual nodes could not be transfered");
+		}
+
+		/* Just destroy the node as it has no other 
+		 * existence nor goal in existence but to create
+		 * a collision. */
+		brasero_file_node_destroy (sibling, stats);
+	}
+	else {
+		/* The node existed and the user wants the existing to 
+		 * be replaced, so we delete that node (since the new
+		 * one would have the old one's children otherwise). */
+		 brasero_data_project_remove_real (self, sibling);
+	 }
+}
+
 gboolean
 brasero_data_project_move_node (BraseroDataProject *self,
 				BraseroFileNode *node,
@@ -1336,9 +1468,14 @@ brasero_data_project_move_node (BraseroDataProject *self,
 	/* One case could make us fail: if there is the same name in
 	 * the directory: in that case return FALSE; check now. */
 	target_sibling = brasero_file_node_check_name_existence (parent, BRASERO_FILE_NODE_NAME (node));
-	if (target_sibling
-	&&  brasero_data_project_file_signal (self, NAME_COLLISION_SIGNAL, BRASERO_FILE_NODE_NAME (node)))
-		return FALSE;
+	if (target_sibling) {
+		if (BRASERO_FILE_NODE_VIRTUAL (target_sibling)) {
+			brasero_data_project_virtual_sibling (self, node, target_sibling);
+			target_sibling = NULL;
+		}
+		else if (brasero_data_project_node_signal (self, NAME_COLLISION_SIGNAL, target_sibling))
+			return FALSE;
+	}
 
 	/* If node was in the joliet incompatible table, remove it */
 	brasero_data_project_joliet_remove_node (self, node);
@@ -1383,12 +1520,10 @@ brasero_data_project_move_node (BraseroDataProject *self,
 	if (former_parent && klass->node_removed)
 		klass->node_removed (self, former_parent, former_position, node);
 
-	if (target_sibling) {
-		/* The node existed and the user wants the existing to 
-		 * be replaced, so we delete that node (since the new
-		 * one would have the old one's children otherwise). */
-		brasero_data_project_remove_real (self, target_sibling);
-	}
+	if (target_sibling)
+		brasero_data_project_remove_sibling (self,
+						     target_sibling,
+						     node);
 
 	brasero_file_node_move_to (node, parent, priv->sort_func);
 
@@ -1436,6 +1571,7 @@ brasero_data_project_rename_node (BraseroDataProject *self,
 				  BraseroFileNode *node,
 				  const gchar *name)
 {
+	BraseroFileNode *imported_sibling;
 	BraseroDataProjectPrivate *priv;
 	BraseroFileNode *sibling;
 
@@ -1445,11 +1581,16 @@ brasero_data_project_rename_node (BraseroDataProject *self,
 	 * simply not possible to rename. */
 	sibling = brasero_file_node_check_name_existence (node->parent, name);
 	if (sibling) {
-		if (brasero_data_project_file_signal (self, NAME_COLLISION_SIGNAL, name))
+		if (BRASERO_FILE_NODE_VIRTUAL (sibling))
+			brasero_data_project_virtual_sibling (self, node, sibling);
+		else if (brasero_data_project_node_signal (self, NAME_COLLISION_SIGNAL, sibling))
 			return FALSE;
-
-		if (sibling != node)
+		else if (sibling != node) {
+			/* The node existed and the user wants the existing to 
+			 * be replaced, so we delete that node (since the new
+			 * one would have the old one's children otherwise). */
 			brasero_data_project_remove_real (self, sibling);
+		}
 	}
 
 	/* If node was in the joliet incompatible table, remove it */
@@ -1457,7 +1598,7 @@ brasero_data_project_rename_node (BraseroDataProject *self,
 
 	/* see if this node didn't replace an imported one. If so the old 
 	 * imported node must re-appear in the tree. */
-	sibling = brasero_file_node_check_imported_sibling (node);
+	imported_sibling = brasero_file_node_check_imported_sibling (node);
 
 	if (!node->is_grafted) {
 		gchar *uri;
@@ -1495,14 +1636,14 @@ brasero_data_project_rename_node (BraseroDataProject *self,
 
 	brasero_data_project_node_changed (self, node);
 
-	if (sibling) {
+	if (imported_sibling) {
 		BraseroDataProjectClass *klass;
 
 		klass = BRASERO_DATA_PROJECT_GET_CLASS (self);
 
-		brasero_file_node_add (sibling->parent, sibling, priv->sort_func);
+		brasero_file_node_add (sibling->parent, imported_sibling, priv->sort_func);
 		if (klass->node_added)
-			brasero_data_project_add_node_and_children (self, sibling, klass->node_added);
+			brasero_data_project_add_node_and_children (self, imported_sibling, klass->node_added);
 	}
 
 	return TRUE;
@@ -1624,7 +1765,8 @@ brasero_data_project_restore_uri (BraseroDataProject *self,
 		if (brasero_file_node_check_name_existence (parent, name))
 			continue;
 
-		node = brasero_file_node_new_loading (name, parent, priv->sort_func);
+		node = brasero_file_node_new_loading (name);
+		brasero_file_node_add (parent, node, priv->sort_func);
 		brasero_data_project_add_node_real (self, node, graft, uri);
 	}
 	g_slist_free (nodes);
@@ -1660,6 +1802,7 @@ brasero_data_project_add_imported_session_file (BraseroDataProject *self,
 						BraseroFileNode *parent)
 {
 	BraseroFileNode *node;
+	BraseroFileNode *sibling;
 	BraseroDataProjectClass *klass;
 	BraseroDataProjectPrivate *priv;
 
@@ -1671,54 +1814,62 @@ brasero_data_project_add_imported_session_file (BraseroDataProject *self,
 	if (!parent)
 		parent = priv->root;
 
-	node = brasero_file_node_check_name_existence (parent, g_file_info_get_name (info));
-	if (node) {
+	sibling = brasero_file_node_check_name_existence (parent, g_file_info_get_name (info));
+	if (sibling) {
 		/* The node exists but it may be that we've loaded the project
 		 * before. Then the necessary directories to hold the grafted
 		 * files will have been created as fake directories. We need to
 		 * replace those whenever we run into one but not lose their 
 		 * children. */
-		if (node->is_fake && node->is_tmp_parent) {
+		if (BRASERO_FILE_NODE_VIRTUAL (sibling)) {
+			node = brasero_file_node_new_imported_session_file (info);
+			brasero_data_project_virtual_sibling (self, node, sibling);
+		}
+		else if (sibling->is_fake && sibling->is_tmp_parent) {
 			BraseroGraft *graft;
 			BraseroURINode *uri_node;
 
-			graft = BRASERO_FILE_NODE_GRAFT (node);
+			graft = BRASERO_FILE_NODE_GRAFT (sibling);
 			uri_node = graft->node;
 
 			/* NOTE after this function graft is invalid */
-			brasero_file_node_ungraft (node);
+			brasero_file_node_ungraft (sibling);
 
 			/* see if uri_node is still needed */
 			if (!uri_node->nodes
 			&&  !brasero_data_project_uri_has_parent (self, uri_node->uri))
 				brasero_data_project_uri_remove_graft (self, uri_node->uri);
 
-			if (node->is_file)
-				node->is_fake = FALSE;
+			if (sibling->is_file)
+				sibling->is_fake = FALSE;
 			else
-				node->union3.imported_address = g_file_info_get_attribute_int64 (info, BRASERO_IO_DIR_CONTENTS_ADDR);
+				sibling->union3.imported_address = g_file_info_get_attribute_int64 (info, BRASERO_IO_DIR_CONTENTS_ADDR);
 
-			node->is_imported = TRUE;
-			node->is_tmp_parent = FALSE;
+			sibling->is_imported = TRUE;
+			sibling->is_tmp_parent = FALSE;
 
 			/* Something has changed, tell the tree */
 			klass = BRASERO_DATA_PROJECT_GET_CLASS (self);
 			if (klass->node_changed)
-				klass->node_changed (self, node);
+				klass->node_changed (self, sibling);
 
-			return node;
+			return sibling;
 		}
-
-		if (brasero_data_project_file_signal (self, NAME_COLLISION_SIGNAL, BRASERO_FILE_NODE_NAME (node)))
+		else if (brasero_data_project_node_signal (self, NAME_COLLISION_SIGNAL, sibling))
 			return NULL;
-
-		/* The node existed and the user wants the existing to 
-		 * be replaced, so we delete that node (since the new
-		 * one would have the old one's children otherwise). */
-		brasero_data_project_remove_real (self, node);
+		else {
+			/* The node existed and the user wants the existing to 
+			 * be replaced, so we delete that node (since the new
+			 * one would have the old one's children otherwise). */
+			brasero_data_project_remove_real (self, sibling);
+			node = brasero_file_node_new_imported_session_file (info);
+		}
 	}
+	else
+		node = brasero_file_node_new_imported_session_file (info);
 
-	node = brasero_file_node_new_imported_session_file (info, parent, priv->sort_func);
+	/* Add it (we must add a graft) */
+	brasero_file_node_add (parent, node, priv->sort_func);
 
 	/* In this case, there can be no graft, and furthermore the
 	 * lengths of the names are not our problem. Just signal that
@@ -1737,6 +1888,7 @@ brasero_data_project_add_empty_directory (BraseroDataProject *self,
 {
 	BraseroFileNode *node;
 	BraseroURINode *graft;
+	BraseroFileNode *sibling;
 	BraseroDataProjectPrivate *priv;
 
 	g_return_val_if_fail (BRASERO_IS_DATA_PROJECT (self), NULL);
@@ -1751,18 +1903,26 @@ brasero_data_project_add_empty_directory (BraseroDataProject *self,
 	if (!brasero_data_project_is_deep (self, parent, name, FALSE))
 		return NULL;
 
-	node = brasero_file_node_check_name_existence (parent, name);
-	if (node) {
-		if (brasero_data_project_file_signal (self, NAME_COLLISION_SIGNAL, BRASERO_FILE_NODE_NAME (node)))
+	sibling = brasero_file_node_check_name_existence (parent, name);
+	if (sibling) {
+		if (BRASERO_FILE_NODE_VIRTUAL (sibling)) {
+			node = brasero_file_node_new_empty_folder (name);
+			brasero_data_project_virtual_sibling (self, node, sibling);
+		}
+		else if (brasero_data_project_node_signal (self, NAME_COLLISION_SIGNAL, sibling))
 			return NULL;
-
-		/* The node existed and the user wants the existing to 
-		 * be replaced, so we delete that node (since the new
-		 * one would have the old one's children otherwise). */
-		brasero_data_project_remove_real (self, node);
+		else {
+			/* The node existed and the user wants the existing to 
+			 * be replaced, so we delete that node (since the new
+			 * one would have the old one's children otherwise). */
+			brasero_data_project_remove_real (self, sibling);
+			node = brasero_file_node_new_empty_folder (name);
+		}
 	}
+	else
+		node = brasero_file_node_new_empty_folder (name);
 
-	node = brasero_file_node_new_empty_folder (name, parent, priv->sort_func);
+	brasero_file_node_add (parent, node, priv->sort_func);
 
 	/* Add it (we must add a graft) */
 	graft = g_hash_table_lookup (priv->grafts, NEW_FOLDER);
@@ -1998,52 +2158,87 @@ brasero_data_project_node_reloaded (BraseroDataProject *self,
 			       0);
 }
 
-BraseroFileNode *
-brasero_data_project_add_loading_node (BraseroDataProject *self,
-				       const gchar *uri,
-				       BraseroFileNode *parent)
+static BraseroFileNode *
+brasero_data_project_add_loading_node_real (BraseroDataProject *self,
+					    const gchar *uri,
+					    const gchar *name_arg,
+					    gboolean is_hidden,
+					    BraseroFileNode *parent)
 {
 	gchar *name;
 	BraseroFileNode *node;
 	BraseroURINode *graft;
+	BraseroFileNode *sibling;
 	BraseroDataProjectPrivate *priv;
 
-	g_return_val_if_fail (BRASERO_IS_DATA_PROJECT (self), NULL);
-	g_return_val_if_fail (uri != NULL, NULL);
-
 	priv = BRASERO_DATA_PROJECT_PRIVATE (self);
 
 	graft = g_hash_table_lookup (priv->grafts, uri);
 	if (!parent)
 		parent = priv->root;
 
-	/* NOTE: find the name of the node through the URI */
-	name = brasero_utils_get_uri_name (uri);
+	if (!name_arg) {
+		/* NOTE: find the name of the node through the URI */
+		name = brasero_utils_get_uri_name (uri);
+	}
+	else
+		name = g_strdup (name_arg);
 
 	/* make sure that name doesn't exist */
-	node = brasero_file_node_check_name_existence (parent, name);
-	if (node) {
-		if (brasero_data_project_file_signal (self,
-						      NAME_COLLISION_SIGNAL,
-						      BRASERO_FILE_NODE_NAME (node))) {
+	sibling = brasero_file_node_check_name_existence (parent, name);
+	if (sibling) {
+		if (BRASERO_FILE_NODE_VIRTUAL (sibling)) {
+			node = brasero_file_node_new_loading (name);
+			brasero_data_project_virtual_sibling (self, node, sibling);
+		}
+		else if (brasero_data_project_node_signal (self, NAME_COLLISION_SIGNAL, sibling)) {
 			g_free (name);
 			return NULL;
 		}
-
-		/* The node existed and the user wants the existing to 
-		 * be replaced, so we delete that node (since the new
-		 * one would have the old one's children otherwise). */
-		brasero_data_project_remove_real (self, node);
-		graft = g_hash_table_lookup (priv->grafts, uri);
+		else {
+			/* The node existed and the user wants the existing to 
+			 * be replaced, so we delete that node (since the new
+			 * one would have the old one's children otherwise). */
+			brasero_data_project_remove_real (self, sibling);
+			node = brasero_file_node_new_loading (name);
+			graft = g_hash_table_lookup (priv->grafts, uri);
+		}
 	}
+	else
+		node = brasero_file_node_new_loading (name);
 
-	node = brasero_file_node_new_loading (name, parent, priv->sort_func);
+	brasero_file_node_add (parent, node, priv->sort_func);
+
+	node->is_hidden = is_hidden;
 	brasero_data_project_add_node_real (self, node, graft, uri);
 	g_free (name);
 
 	return node;
 }
 
+BraseroFileNode *
+brasero_data_project_add_loading_node (BraseroDataProject *self,
+				       const gchar *uri,
+				       BraseroFileNode *parent)
+{
+	g_return_val_if_fail (BRASERO_IS_DATA_PROJECT (self), NULL);
+	g_return_val_if_fail (uri != NULL, NULL);
+
+	return brasero_data_project_add_loading_node_real (self, uri, NULL, FALSE, parent);
+}
+
+BraseroFileNode *
+brasero_data_project_add_hidden_node (BraseroDataProject *self,
+				      const gchar *uri,
+				      const gchar *name,
+				      BraseroFileNode *parent)
+{
+	g_return_val_if_fail (BRASERO_IS_DATA_PROJECT (self), NULL);
+	g_return_val_if_fail (uri != NULL, NULL);
+
+	return brasero_data_project_add_loading_node_real (self, uri, name, TRUE, parent);
+}
+
 /**
  * This function is only used by brasero-data-vfs.c to add the contents of a 
  * directory. That's why if a node with the same name is already grafted we 
@@ -2086,6 +2281,7 @@ brasero_data_project_add_node_from_info (BraseroDataProject *self,
 	const gchar *name;
 	BraseroFileNode *node;
 	BraseroURINode *graft;
+	BraseroFileNode *sibling;
 	BraseroDataProjectPrivate *priv;
 
 	g_return_val_if_fail (BRASERO_IS_DATA_PROJECT (self), NULL);
@@ -2124,20 +2320,9 @@ brasero_data_project_add_node_from_info (BraseroDataProject *self,
 	if (!parent)
 		parent = priv->root;
 
-	/* make sure that name doesn't exist */
 	name = g_file_info_get_name (info);
-	node = brasero_file_node_check_name_existence (parent, name);
-	if (node) {
-		if (brasero_data_project_file_signal (self, NAME_COLLISION_SIGNAL, BRASERO_FILE_NODE_NAME (node)))
-			return NULL;
-
-		/* The node existed and the user wants the existing to 
-		 * be replaced, so we delete that node (since the new
-		 * one would have the old one's children otherwise). */
-		brasero_data_project_remove_real (self, node);
-		graft = g_hash_table_lookup (priv->grafts, uri);
-	}
 
+	/* Run a few checks */
 	type = g_file_info_get_file_type (info);
 	if (type != G_FILE_TYPE_DIRECTORY) {
 		guint64 size;
@@ -2157,9 +2342,40 @@ brasero_data_project_add_node_from_info (BraseroDataProject *self,
 			return NULL;
 	} 
 
-	node = brasero_file_node_new_from_info (info,
-						parent,
-						priv->sort_func);
+	/* make sure that name doesn't exist */
+	sibling = brasero_file_node_check_name_existence (parent, name);
+	if (sibling) {
+		BraseroFileTreeStats *stats;
+
+		stats = brasero_file_node_get_tree_stats (priv->root, NULL);
+
+		if (BRASERO_FILE_NODE_VIRTUAL (sibling)) {
+			node = brasero_file_node_new (g_file_info_get_name (info));
+			brasero_file_node_set_from_info (node, stats, info);
+			brasero_data_project_virtual_sibling (self, node, sibling);
+		}
+		else if (brasero_data_project_node_signal (self, NAME_COLLISION_SIGNAL, sibling))
+			return NULL;
+		else {
+			/* The node existed and the user wants the existing to 
+			 * be replaced, so we delete that node (since the new
+			 * one would have the old one's children otherwise). */
+			node = brasero_file_node_new (g_file_info_get_name (info));
+			brasero_file_node_set_from_info (node, stats, info);
+
+			brasero_data_project_remove_real (self, sibling);
+			graft = g_hash_table_lookup (priv->grafts, uri);
+		}
+	}
+	else {
+		BraseroFileTreeStats *stats;
+
+		node = brasero_file_node_new (g_file_info_get_name (info));
+		stats = brasero_file_node_get_tree_stats (priv->root, NULL);
+		brasero_file_node_set_from_info (node, stats, info);
+	}
+
+	brasero_file_node_add (parent, node, priv->sort_func);
 
 	if (g_file_info_get_is_symlink (info)
 	&&  g_file_info_get_file_type (info) != G_FILE_TYPE_SYMBOLIC_LINK) {
@@ -2213,6 +2429,7 @@ brasero_data_project_add_node_from_info (BraseroDataProject *self,
  */
 struct _MakeTrackData {
 	gboolean append_slash;
+	gboolean hidden_nodes;
 
 	GSList *grafts;
 	GSList *excluded;
@@ -2221,7 +2438,7 @@ struct _MakeTrackData {
 };
 typedef struct _MakeTrackData MakeTrackData;
 
-static gchar *
+gchar *
 brasero_data_project_node_to_path (BraseroDataProject *self,
 				   BraseroFileNode *node)
 {
@@ -2274,18 +2491,7 @@ _foreach_grafts_make_list_cb (const gchar *uri,
 			      MakeTrackData *data)
 {
 	GSList *iter;
-
-	/* Each URI in this table must be excluded. Then each node in 
-	 * this list will be grafted. That way only those that we are
-	 * interested in will be in the tree. */
-
-	/* Add to the unreadable. This could be further improved by 
-	 * checking if there is a parent in the hash for this URI. If 
-	 * not that's no use adding this URI to unreadable. */
-	/* NOTE: if that the created directories URI, then there is no 
-	 * need to add it to excluded */
-	if (uri != NEW_FOLDER)
-		data->excluded = g_slist_prepend (data->excluded, g_strdup (uri));
+	gboolean add_to_excluded = FALSE;
 
 	/* add each node */
 	for (iter = uri_node->nodes; iter; iter = iter->next) {
@@ -2293,7 +2499,10 @@ _foreach_grafts_make_list_cb (const gchar *uri,
 		BraseroGraftPt *graft;
 
 		node = iter->data;
+		if (!data->hidden_nodes && node->is_hidden)
+			continue;
 
+		add_to_excluded = TRUE;
 		graft = g_new0 (BraseroGraftPt, 1);
 
 		/* if URI is a created directory set URI to NULL */
@@ -2315,6 +2524,18 @@ _foreach_grafts_make_list_cb (const gchar *uri,
 
 		data->grafts = g_slist_prepend (data->grafts, graft);
 	}
+
+	/* Each URI in this table must be excluded. Then each node in 
+	 * this list will be grafted. That way only those that we are
+	 * interested in will be in the tree. */
+
+	/* Add to the unreadable. This could be further improved by 
+	 * checking if there is a parent in the hash for this URI. If 
+	 * not that's no use adding this URI to unreadable. */
+	/* NOTE: if that the created directories URI, then there is no 
+	 * need to add it to excluded */
+	if (uri != NEW_FOLDER && add_to_excluded)
+		data->excluded = g_slist_prepend (data->excluded, g_strdup (uri));
 }
 
 static void
@@ -2362,6 +2583,7 @@ gboolean
 brasero_data_project_get_contents (BraseroDataProject *self,
 				   GSList **grafts,
 				   GSList **unreadable,
+				   gboolean hidden_nodes,
 				   gboolean joliet_compat,
 				   gboolean append_slash)
 {
@@ -2376,12 +2598,18 @@ brasero_data_project_get_contents (BraseroDataProject *self,
 	callback_data.project = self;
 	callback_data.grafts = NULL;
 	callback_data.excluded = NULL;
+	callback_data.hidden_nodes = hidden_nodes;
 	callback_data.append_slash = append_slash;
 
 	g_hash_table_foreach (priv->grafts,
 			      (GHFunc) _foreach_grafts_make_list_cb,
 			      &callback_data);
 
+	/* This is possible even if the GHashTable is empty since there could be
+	 * only excluded URI inside or hidden nodes like autorun.inf. */
+	if (!grafts)
+		return FALSE;
+
 	if (joliet_compat) {
 		/* Make sure that all nodes with incompatible joliet names are
 		 * added as graft points. */
@@ -2870,15 +3098,17 @@ brasero_data_project_create_path (BraseroDataProject *self,
 	end = g_utf8_strchr (path, -1, G_DIR_SEPARATOR);
 
 	while (end && end [1] != '\0') {
+		BraseroFileNode *node;
 		gchar *name;
 		gint len;
 
 		/* create the path */
 		len = end - path;
 		name = g_strndup (path, len);
-		parent = brasero_file_node_new_loading (name,
-							parent,
-							priv->sort_func);
+
+		node = brasero_file_node_new_loading (name);
+		brasero_file_node_add (parent, node, priv->sort_func);
+		parent = node;
 		g_free (name);
 
 		/* check joliet compatibility; do it after node was created. */
@@ -3031,9 +3261,11 @@ brasero_data_project_add_path (BraseroDataProject *self,
 		 * - we don't check for sibling
 		 * - we set right from the start the right name */
 		if (uri != NEW_FOLDER)
-			node = brasero_file_node_new_loading (path, parent, priv->sort_func);
+			node = brasero_file_node_new_loading (path);
 		else
-			node = brasero_file_node_new_empty_folder (path, parent, priv->sort_func);
+			node = brasero_file_node_new_empty_folder (path);
+
+		brasero_file_node_add (parent, node, priv->sort_func);
 
 		/* the following function checks for joliet, graft it */
 		brasero_data_project_add_node_real (self,
@@ -3422,6 +3654,47 @@ brasero_data_project_get_root (BraseroDataProject *self)
 	return priv->root;
 }
 
+/**
+ * This is to watch a still empty path and get a warning through the collision
+ * name signal when the node is created. If a node is already created for this
+ * path, then returns NULL.
+ */
+
+BraseroFileNode *
+brasero_data_project_watch_path (BraseroDataProject *project,
+				 const gchar *path)
+{
+	BraseroDataProjectPrivate *priv;
+	BraseroFileNode *parent;
+	gchar **array;
+	gchar **iter;
+
+	priv = BRASERO_DATA_PROJECT_PRIVATE (project);
+	parent = brasero_data_project_skip_existing (project, priv->root, &path);
+
+	if (!path || path [0] == '\0')
+		return NULL;
+
+	/* Now add the virtual node */
+	if (g_str_has_prefix (path, G_DIR_SEPARATOR_S))
+		array = g_strsplit (path + 1, G_DIR_SEPARATOR_S, 0);
+	else
+		array = g_strsplit (path, G_DIR_SEPARATOR_S, 0);
+
+	for (iter = array; iter && *iter && parent; iter ++) {
+		BraseroFileNode *node;
+
+		node = brasero_file_node_new_virtual (*iter);
+		brasero_file_node_add (parent, node, NULL);
+		parent = node;
+	}
+
+	g_strfreev (array);
+
+	/* This function shouldn't fail anyway */
+	return parent;
+}
+
 static gboolean
 brasero_data_project_clear_grafts_cb (gchar *key,
 				      BraseroURINode *graft,
@@ -3580,14 +3853,17 @@ brasero_data_project_file_added (BraseroFileMonitor *monitor,
 	g_free (escaped_name);
 	g_free (parent_uri);
 
-	if (sibling) {
-		/* There is no way we can add the node to tree; so exclude it */
-		brasero_data_project_exclude_uri (BRASERO_DATA_PROJECT (monitor), uri);
-	}
-	else
+	if (!sibling || BRASERO_FILE_NODE_VIRTUAL (sibling)) {
+		/* If there is a virtual node, get rid of it */
 		brasero_data_project_add_loading_node (BRASERO_DATA_PROJECT (monitor),
 						       uri,
 						       parent);
+	}
+	else {
+		/* There is no way we can add the node to tree; so exclude it */
+		brasero_data_project_exclude_uri (BRASERO_DATA_PROJECT (monitor), uri);
+	}
+
 	g_free (uri);
 }
 
@@ -3731,7 +4007,7 @@ brasero_data_project_file_renamed (BraseroFileMonitor *monitor,
 	 * simply not possible to rename. So if node is grafted it keeps its
 	 * name if not, it's grafted with the old name. */
 	sibling = brasero_file_node_check_name_existence (node->parent, new_name);
-	if (sibling) {
+	if (sibling && !BRASERO_FILE_NODE_VIRTUAL (sibling)) {
 		if (!node->is_grafted) {
 			brasero_data_project_file_graft (BRASERO_DATA_PROJECT (monitor), node, new_name);
 			return;
@@ -3748,6 +4024,11 @@ brasero_data_project_file_renamed (BraseroFileMonitor *monitor,
 		brasero_data_project_file_update_name (BRASERO_DATA_PROJECT (monitor), node, new_name);
 	}
 
+	if (sibling && BRASERO_FILE_NODE_VIRTUAL (sibling)) {
+		/* Signal collision and remove virtual node but ignore result */
+		brasero_data_project_virtual_sibling (BRASERO_DATA_PROJECT (monitor), node, sibling);
+	}
+
 	if (node->is_grafted) {
 		BraseroURINode *uri_node;
 		BraseroGraft *graft;
@@ -3829,11 +4110,16 @@ brasero_data_project_file_moved (BraseroFileMonitor *monitor,
 		 * that's simply not possible to rename. So if node is grafted
 		 * it keeps its name; if not, it's grafted with the old name. */
 		sibling = brasero_file_node_check_name_existence (parent, name_dest);
-		if (sibling) {
+		if (sibling && !BRASERO_FILE_NODE_VIRTUAL (sibling)) {
 			brasero_data_project_file_graft (BRASERO_DATA_PROJECT (monitor), node, name_dest);
 			return;
 		}
 
+		if (sibling && BRASERO_FILE_NODE_VIRTUAL (sibling)) {
+			/* Signal collision and remove virtual node but ignore result */
+			brasero_data_project_virtual_sibling (BRASERO_DATA_PROJECT (monitor), node, sibling);
+		}
+
 		/* If node was in the joliet incompatible table, remove it */
 		brasero_data_project_joliet_remove_node (BRASERO_DATA_PROJECT (monitor), node);
 
@@ -3976,10 +4262,10 @@ brasero_data_project_class_init (BraseroDataProjectClass *klass)
 			  G_SIGNAL_RUN_LAST|G_SIGNAL_NO_RECURSE,
 			  0,
 			  NULL, NULL,
-			  brasero_marshal_BOOLEAN__STRING,
+			  brasero_marshal_BOOLEAN__POINTER,
 			  G_TYPE_BOOLEAN,
 			  1,
-			  G_TYPE_STRING);
+			  G_TYPE_POINTER);
 	brasero_data_project_signals [SIZE_CHANGED_SIGNAL] = 
 	    g_signal_new ("size_changed",
 			  G_TYPE_FROM_CLASS (klass),
@@ -4021,6 +4307,18 @@ brasero_data_project_class_init (BraseroDataProjectClass *klass)
 			  1,
 			  G_TYPE_INT);
 
+	brasero_data_project_signals [VIRTUAL_SIBLING_SIGNAL] = 
+	    g_signal_new ("virtual-sibling",
+			  G_TYPE_FROM_CLASS (klass),
+			  G_SIGNAL_RUN_LAST|G_SIGNAL_NO_RECURSE,
+			  0,
+			  NULL, NULL,
+			  brasero_marshal_VOID__POINTER_POINTER,
+			  G_TYPE_NONE,
+			  2,
+			  G_TYPE_POINTER,
+			  G_TYPE_POINTER);
+
 #ifdef BUILD_INOTIFY
 
 	BraseroFileMonitorClass *monitor_class = BRASERO_FILE_MONITOR_CLASS (klass);
diff --git a/libbrasero-burn/brasero-data-project.h b/libbrasero-burn/brasero-data-project.h
index 873d969..2515633 100644
--- a/libbrasero-burn/brasero-data-project.h
+++ b/libbrasero-burn/brasero-data-project.h
@@ -133,6 +133,7 @@ gboolean
 brasero_data_project_get_contents (BraseroDataProject *project,
 				   GSList **grafts,
 				   GSList **unreadable,
+				   gboolean hidden_nodes,
 				   gboolean joliet_compat,
 				   gboolean append_slash);
 
@@ -154,6 +155,12 @@ brasero_data_project_load_contents (BraseroDataProject *project,
 				    GSList *excluded);
 
 BraseroFileNode *
+brasero_data_project_add_hidden_node (BraseroDataProject *project,
+				      const gchar *uri,
+				      const gchar *name,
+				      BraseroFileNode *parent);
+
+BraseroFileNode *
 brasero_data_project_add_loading_node (BraseroDataProject *project,
 				       const gchar *uri,
 				       BraseroFileNode *parent);
@@ -225,12 +232,19 @@ brasero_data_project_get_root (BraseroDataProject *project);
 gchar *
 brasero_data_project_node_to_uri (BraseroDataProject *project,
 				  BraseroFileNode *node);
+gchar *
+brasero_data_project_node_to_path (BraseroDataProject *self,
+				   BraseroFileNode *node);
 
 void
 brasero_data_project_set_sort_function (BraseroDataProject *project,
 					GtkSortType sort_type,
 					GCompareFunc sort_func);
 
+BraseroFileNode *
+brasero_data_project_watch_path (BraseroDataProject *project,
+				 const gchar *path);
+
 BraseroBurnResult
 brasero_data_project_span (BraseroDataProject *project,
 			   goffset max_sectors,
diff --git a/libbrasero-burn/brasero-data-tree-model.c b/libbrasero-burn/brasero-data-tree-model.c
index 6343625..5520c80 100644
--- a/libbrasero-burn/brasero-data-tree-model.c
+++ b/libbrasero-burn/brasero-data-tree-model.c
@@ -66,6 +66,9 @@ brasero_data_tree_model_node_added (BraseroDataProject *project,
 				    const gchar *uri)
 {
 	/* see if we really need to tell the treeview we changed */
+	if (node->is_hidden)
+		goto end;
+
 	if (node->parent
 	&& !node->parent->is_root
 	&& !node->parent->is_visible)
@@ -91,6 +94,9 @@ brasero_data_tree_model_node_removed (BraseroDataProject *project,
 				      BraseroFileNode *node)
 {
 	/* see if we really need to tell the treeview we changed */
+	if (node->is_hidden)
+		goto end;
+
 	if (!node->is_visible
 	&&   former_parent
 	&&  !former_parent->is_root
@@ -118,6 +124,9 @@ brasero_data_tree_model_node_changed (BraseroDataProject *project,
 				      BraseroFileNode *node)
 {
 	/* see if we really need to tell the treeview we changed */
+	if (node->is_hidden)
+		goto end;
+
 	if (node->parent
 	&& !node->parent->is_root
 	&& !node->parent->is_visible)
diff --git a/libbrasero-burn/brasero-data-vfs.c b/libbrasero-burn/brasero-data-vfs.c
index 87bc61b..e526887 100644
--- a/libbrasero-burn/brasero-data-vfs.c
+++ b/libbrasero-burn/brasero-data-vfs.c
@@ -436,7 +436,6 @@ brasero_data_vfs_directory_load_result (GObject *owner,
 		}
 	}
 
-
 	/* add node for all parents */
 	nodes = g_hash_table_lookup (priv->directories, parent_uri);
 	for (iter = nodes; iter; iter = iter->next) {
diff --git a/libbrasero-burn/brasero-file-node.c b/libbrasero-burn/brasero-file-node.c
index 0e91ade..3a7867d 100644
--- a/libbrasero-burn/brasero-file-node.c
+++ b/libbrasero-burn/brasero-file-node.c
@@ -196,6 +196,32 @@ brasero_file_node_insert (BraseroFileNode *head,
 		return node;
 	}
 
+	/* Set hidden nodes (whether virtual or not) always last */
+	if (head->is_hidden) {
+		node->next = head;
+		if (newpos)
+			*newpos = 0;
+
+		return node;
+	}
+
+	if (node->is_hidden) {
+		iter = head;
+		n = 1;
+		while (iter->next)  {
+			iter = iter->next;
+			n ++;
+		}
+
+		iter->next = node;
+
+		if (newpos)
+			*newpos = n;
+
+		return head;
+	}
+
+	/* regular node, regular head node */
 	if (sort_func (head, node) > 0) {
 		/* head is after node */
 		node->next = head;
@@ -242,6 +268,9 @@ brasero_file_node_need_resort (BraseroFileNode *node,
 	guint oldpos;
 	guint size;
 
+	if (node->is_hidden)
+		return NULL;
+
 	parent = node->parent;
 	head = BRASERO_FILE_NODE_CHILDREN (parent);
 
@@ -272,6 +301,7 @@ brasero_file_node_need_resort (BraseroFileNode *node,
 		parent->union2.children = head;
 
 		/* create an array to reflect the changes */
+		/* NOTE: hidden nodes are not taken into account. */
 		size = brasero_file_node_get_n_children (parent);
 		array = g_new0 (gint, size);
 
@@ -284,7 +314,8 @@ brasero_file_node_need_resort (BraseroFileNode *node,
 				array [i] = i;
 		}
 	}
-	else if (node->next && sort_func (node, node->next) > 0) {
+	/* Hidden nodes stay at the end, hence the !node->next->is_hidden */
+	else if (node->next && !node->next->is_hidden && sort_func (node, node->next) > 0) {
 		gint i;
 
 		/* move on the right */
@@ -302,7 +333,8 @@ brasero_file_node_need_resort (BraseroFileNode *node,
 		/* we started from oldpos so newpos needs updating */
 		newpos += oldpos;
 
-		/* create an array to reflect the changes */
+		/* create an array to reflect the changes. */
+		/* NOTE: hidden nodes are not taken into account. */
 		size = brasero_file_node_get_n_children (parent);
 		array = g_new0 (gint, size);
 
@@ -331,9 +363,11 @@ brasero_file_node_sort_children (BraseroFileNode *parent,
 	guint oldpos = 1;
 	guint newpos;
 
-	new_order = BRASERO_FILE_NODE_CHILDREN (parent);
-
 	/* check for some special cases */
+	if (parent->is_hidden)
+		return NULL;
+
+	new_order = BRASERO_FILE_NODE_CHILDREN (parent);
 	if (!new_order)
 		return NULL;
 
@@ -483,8 +517,11 @@ brasero_file_node_get_n_children (const BraseroFileNode *node)
 	if (!node)
 		return 0;
 
-	for (children = BRASERO_FILE_NODE_CHILDREN (node); children; children = children->next)
+	for (children = BRASERO_FILE_NODE_CHILDREN (node); children; children = children->next) {
+		if (children->is_hidden)
+			continue;
 		num ++;
+	}
 
 	return num;
 }
@@ -523,6 +560,24 @@ brasero_file_node_is_ancestor (BraseroFileNode *parent,
 }
 
 BraseroFileNode *
+brasero_file_node_check_name_existence_case (BraseroFileNode *parent,
+					     const gchar *name)
+{
+	BraseroFileNode *iter;
+
+	if (name && name [0] == '\0')
+		return NULL;
+
+	iter = BRASERO_FILE_NODE_CHILDREN (parent);
+	for (; iter; iter = iter->next) {
+		if (!strcasecmp (name, BRASERO_FILE_NODE_NAME (iter)))
+			return iter;
+	}
+
+	return NULL;
+}
+
+BraseroFileNode *
 brasero_file_node_check_name_existence (BraseroFileNode *parent,
 				        const gchar *name)
 {
@@ -541,6 +596,35 @@ brasero_file_node_check_name_existence (BraseroFileNode *parent,
 }
 
 BraseroFileNode *
+brasero_file_node_get_from_path (BraseroFileNode *root,
+				 const gchar *path)
+{
+	gchar **array;
+	gchar **iter;
+
+	if (!path)
+		return NULL;
+
+	/* If we don't do that array[0] == '\0' */
+	if (g_str_has_prefix (path, G_DIR_SEPARATOR_S))
+		array = g_strsplit (path + 1, G_DIR_SEPARATOR_S, 0);
+	else
+		array = g_strsplit (path, G_DIR_SEPARATOR_S, 0);
+
+	if (!array)
+		return NULL;
+
+	for (iter = array; iter && *iter; iter++) {
+		root = brasero_file_node_check_name_existence (root, *iter);
+		if (!root)
+			break;
+	}
+	g_strfreev (array);
+
+	return root;
+}
+
+BraseroFileNode *
 brasero_file_node_check_imported_sibling (BraseroFileNode *node)
 {
 	BraseroFileNode *parent;
@@ -683,6 +767,10 @@ brasero_file_node_add (BraseroFileNode *parent,
 							    sort_func,
 							    NULL);
 	node->parent = parent;
+
+	if (BRASERO_FILE_NODE_VIRTUAL (node))
+		return;
+
 	if (!node->is_imported) {
 		/* NOTE: parent will be changed afterwards !!! */
 		if (!node->is_grafted) {
@@ -695,7 +783,8 @@ brasero_file_node_add (BraseroFileNode *parent,
 		}
 	}
 
-	/* even imported should be included */
+	/* Even imported should be included. The only type of nodes that are not
+	 * heeded are the virtual nodes. */
 	stats = brasero_file_node_get_tree_stats (node->parent, &depth);
 	if (node->is_file) {
 		if (depth < 6)
@@ -727,7 +816,8 @@ brasero_file_node_set_from_info (BraseroFileNode *node,
 		stats->children ++;
 	}
 
-	if (!node->is_symlink && (g_file_info_get_file_type (info) == G_FILE_TYPE_SYMBOLIC_LINK)) {
+	if (!node->is_symlink
+	&& (g_file_info_get_file_type (info) == G_FILE_TYPE_SYMBOLIC_LINK)) {
 		/* only count files */
 		stats->num_sym ++;
 	}
@@ -810,9 +900,7 @@ brasero_file_node_get_uri_name (const gchar *uri)
 }
 
 BraseroFileNode *
-brasero_file_node_new_loading (const gchar *name,
-			       BraseroFileNode *parent,
-			       GCompareFunc sort_func)
+brasero_file_node_new_loading (const gchar *name)
 {
 	BraseroFileNode *node;
 
@@ -820,35 +908,39 @@ brasero_file_node_new_loading (const gchar *name,
 	node->union1.name = g_strdup (name);
 	node->is_loading = TRUE;
 
-	brasero_file_node_add (parent, node, sort_func);
-
 	return node;
 }
 
 BraseroFileNode *
-brasero_file_node_new_from_info (GFileInfo *info,
-				 BraseroFileNode *parent,
-				 GCompareFunc sort_func)
+brasero_file_node_new_virtual (const gchar *name)
 {
 	BraseroFileNode *node;
-	BraseroFileTreeStats *stats;
 
+	/* virtual nodes are nodes that "don't exist". They appear as temporary
+	 * parents (and therefore replacable) and hidden (not displayed in the
+	 * GtkTreeModel). They are used as 'placeholders' to trigger
+	 * name-collision signal. */
 	node = g_new0 (BraseroFileNode, 1);
-	node->union1.name = g_strdup (g_file_info_get_name (info));
+	node->union1.name = g_strdup (name);
+	node->is_fake = TRUE;
+	node->is_hidden = TRUE;
 
-	stats = brasero_file_node_get_tree_stats (parent, NULL);
-	brasero_file_node_set_from_info (node, stats, info);
+	return node;
+}
 
-	/* This must be done after above function */
-	brasero_file_node_add (parent, node, sort_func);
+BraseroFileNode *
+brasero_file_node_new (const gchar *name)
+{
+	BraseroFileNode *node;
+
+	node = g_new0 (BraseroFileNode, 1);
+	node->union1.name = g_strdup (name);
 
 	return node;
 }
 
 BraseroFileNode *
-brasero_file_node_new_imported_session_file (GFileInfo *info,
-					     BraseroFileNode *parent,
-					     GCompareFunc sort_func)
+brasero_file_node_new_imported_session_file (GFileInfo *info)
 {
 	BraseroFileNode *node;
 
@@ -865,15 +957,11 @@ brasero_file_node_new_imported_session_file (GFileInfo *info,
 	else
 		node->union3.sectors = BRASERO_BYTES_TO_SECTORS (g_file_info_get_size (info), 2048);
 
-	/* Add it (we must add a graft) */
-	brasero_file_node_add (parent, node, sort_func);
 	return node;
 }
 
 BraseroFileNode *
-brasero_file_node_new_empty_folder (const gchar *name,
-				    BraseroFileNode *parent,
-				    GCompareFunc sort_func)
+brasero_file_node_new_empty_folder (const gchar *name)
 {
 	BraseroFileNode *node;
 
@@ -882,8 +970,6 @@ brasero_file_node_new_empty_folder (const gchar *name,
 	node->union1.name = g_strdup (name);
 	node->is_fake = TRUE;
 
-	/* Add it (we must add a graft) */
-	brasero_file_node_add (parent, node, sort_func);
 	return node;
 }
 
@@ -899,7 +985,9 @@ brasero_file_node_unlink (BraseroFileNode *node)
 	iter = BRASERO_FILE_NODE_CHILDREN (node->parent);
 
 	/* handle the size change for previous parent */
-	if (!node->is_grafted && !node->is_imported) {
+	if (!node->is_grafted
+	&&  !node->is_imported
+	&&  !BRASERO_FILE_NODE_VIRTUAL (node)) {
 		BraseroFileNode *parent;
 
 		/* handle the size change if it wasn't grafted */
@@ -1028,7 +1116,7 @@ brasero_file_node_destroy_with_children (BraseroFileNode *node,
 	}
 
 	/* update all statistics on tree if any */
-	if (stats) {
+	if (!BRASERO_FILE_NODE_VIRTUAL (node) && stats) {
 		/* check if that's a 2 GiB file */
 		if (node->is_2GiB)
 			stats->num_2GiB --;
diff --git a/libbrasero-burn/brasero-file-node.h b/libbrasero-burn/brasero-file-node.h
index fc216b0..685b4d2 100644
--- a/libbrasero-burn/brasero-file-node.h
+++ b/libbrasero-burn/brasero-file-node.h
@@ -147,8 +147,8 @@ struct _BraseroFileNode {
 	 * parent with the same name*/
 	guint is_tmp_parent:1;
 
-	/* this should be set by BraseroDataDisc */
-	guint is_selected:1; /* Used to determne if the name is editable */
+	/* Used to determine if is should be shown */
+	guint is_hidden:1;
 
 	/* Used by the model */
 	/* This is a workaround for a warning in gailtreeview.c line 2946 where
@@ -187,6 +187,9 @@ struct _BraseroFileNode {
 #define BRASERO_FILE_NODE_STATS(MACRO_root)					\
 	((MACRO_root)->is_root?(MACRO_root)->union3.stats:NULL)
 
+#define BRASERO_FILE_NODE_VIRTUAL(MACRO_node)					\
+	((MACRO_node)->is_hidden && (MACRO_node)->is_fake)
+
 #define BRASERO_FILE_NODE_IMPORTED_ADDRESS(MACRO_node)				\
 	((MACRO_node) && (MACRO_node)->is_imported && (MACRO_node)->is_fake?(MACRO_node)->union3.imported_address:-1)
 
@@ -223,9 +226,15 @@ gboolean
 brasero_file_node_is_ancestor (BraseroFileNode *parent,
 			       BraseroFileNode *node);
 BraseroFileNode *
+brasero_file_node_get_from_path (BraseroFileNode *root,
+				 const gchar *path);
+BraseroFileNode *
 brasero_file_node_check_name_existence (BraseroFileNode *parent,
 				        const gchar *name);
 BraseroFileNode *
+brasero_file_node_check_name_existence_case (BraseroFileNode *parent,
+					     const gchar *name);
+BraseroFileNode *
 brasero_file_node_check_imported_sibling (BraseroFileNode *node);
 
 /**
@@ -238,21 +247,19 @@ brasero_file_node_add (BraseroFileNode *parent,
 		       GCompareFunc sort_func);
 
 BraseroFileNode *
-brasero_file_node_new_loading (const gchar *name,
-			       BraseroFileNode *parent,
-			       GCompareFunc sort_func);
+brasero_file_node_new (const gchar *name);
+
 BraseroFileNode *
-brasero_file_node_new_from_info (GFileInfo *info,
-				 BraseroFileNode *parent,
-				 GCompareFunc sort_func);
+brasero_file_node_new_virtual (const gchar *name);
+
 BraseroFileNode *
-brasero_file_node_new_empty_folder (const gchar *name,
-				    BraseroFileNode *parent,
-				    GCompareFunc sort_func);
+brasero_file_node_new_loading (const gchar *name);
+
+BraseroFileNode *
+brasero_file_node_new_empty_folder (const gchar *name);
+
 BraseroFileNode *
-brasero_file_node_new_imported_session_file (GFileInfo *info,
-					     BraseroFileNode *parent,
-					     GCompareFunc sort_func);
+brasero_file_node_new_imported_session_file (GFileInfo *info);
 
 /**
  * If there are any change in the order it cannot be handled in these functions
diff --git a/libbrasero-burn/brasero-src-image.c b/libbrasero-burn/brasero-src-image.c
index d0e001a..bd49515 100644
--- a/libbrasero-burn/brasero-src-image.c
+++ b/libbrasero-burn/brasero-src-image.c
@@ -162,7 +162,8 @@ brasero_src_image_error (BraseroSrcImage *self,
 		return;
 
 	brasero_utils_message_dialog (toplevel,
-				      _("Please select another image."),
+				      /* Translators: this is a disc image, not a picture */
+				      C_("disc", "Please select another image."),
 				      error->message,
 				      GTK_MESSAGE_ERROR);
 }
diff --git a/libbrasero-burn/brasero-track-data-cfg.c b/libbrasero-burn/brasero-track-data-cfg.c
index dad9514..c4d4030 100644
--- a/libbrasero-burn/brasero-track-data-cfg.c
+++ b/libbrasero-burn/brasero-track-data-cfg.c
@@ -59,8 +59,9 @@ struct _BraseroTrackDataCfgPrivate
 	BraseroImageFS forced_fs;
 	BraseroImageFS banned_fs;
 
-	gchar *icon_path;
-	gchar *autorun_path;
+	BraseroFileNode *autorun;
+	BraseroFileNode *icon;
+	gchar *image_path;
 
 	BraseroDataTreeModel *tree;
 	guint stamp;
@@ -119,6 +120,7 @@ enum {
 	RECURSIVE,
 	UNKNOWN,
 	G2_FILE,
+	ICON_CHANGED,
 	NAME_COLLISION,
 	DEEP_DIRECTORY,
 	SOURCE_LOADED, 
@@ -133,9 +135,34 @@ static gulong brasero_track_data_cfg_signals [LAST_SIGNAL] = { 0 };
  * GtkTreeModel part
  */
 
+static guint
+brasero_track_data_cfg_get_pos_as_child (BraseroFileNode *node)
+{
+	BraseroFileNode *parent;
+	BraseroFileNode *peers;
+	guint pos = 0;
+
+	if (!node)
+		return 0;
+
+	parent = node->parent;
+	for (peers = BRASERO_FILE_NODE_CHILDREN (parent); peers; peers = peers->next) {
+		if (peers == node)
+			break;
+
+		/* Don't increment when is_hidden */
+		if (peers->is_hidden)
+			continue;
+
+		pos ++;
+	}
+
+	return pos;
+}
+
 static GtkTreePath *
 brasero_track_data_cfg_node_to_path (BraseroTrackDataCfg *self,
-				      BraseroFileNode *node)
+				     BraseroFileNode *node)
 {
 	BraseroTrackDataCfgPrivate *priv;
 	GtkTreePath *path;
@@ -146,7 +173,7 @@ brasero_track_data_cfg_node_to_path (BraseroTrackDataCfg *self,
 	for (; node->parent && !node->is_root; node = node->parent) {
 		guint nth;
 
-		nth = brasero_file_node_get_pos_as_child (node);
+		nth = brasero_track_data_cfg_get_pos_as_child (node);
 		gtk_tree_path_prepend_index (path, nth);
 	}
 
@@ -155,8 +182,8 @@ brasero_track_data_cfg_node_to_path (BraseroTrackDataCfg *self,
 
 static gboolean
 brasero_track_data_cfg_iter_parent (GtkTreeModel *model,
-				     GtkTreeIter *iter,
-				     GtkTreeIter *child)
+				    GtkTreeIter *iter,
+				    GtkTreeIter *child)
 {
 	BraseroTrackDataCfgPrivate *priv;
 	BraseroFileNode *node;
@@ -188,11 +215,36 @@ brasero_track_data_cfg_iter_parent (GtkTreeModel *model,
 	return TRUE;
 }
 
+static BraseroFileNode *
+brasero_track_data_cfg_nth_child (BraseroFileNode *parent,
+				  guint nth)
+{
+	BraseroFileNode *peers;
+	guint pos;
+
+	if (!parent)
+		return NULL;
+
+	peers = BRASERO_FILE_NODE_CHILDREN (parent);
+	while (peers && peers->is_hidden)
+		peers = peers->next;
+		
+	for (pos = 0; pos < nth && peers; pos ++) {
+		/* Don't include hidden */
+		if (peers->is_hidden)
+			pos --;
+
+		peers = peers->next;
+	}
+
+	return peers;
+}
+
 static gboolean
 brasero_track_data_cfg_iter_nth_child (GtkTreeModel *model,
-					GtkTreeIter *iter,
-					GtkTreeIter *parent,
-					gint n)
+				       GtkTreeIter *iter,
+				       GtkTreeIter *parent,
+				       gint n)
 {
 	BraseroTrackDataCfgPrivate *priv;
 	BraseroFileNode *node;
@@ -215,7 +267,7 @@ brasero_track_data_cfg_iter_nth_child (GtkTreeModel *model,
 	else
 		node = brasero_data_project_get_root (BRASERO_DATA_PROJECT (priv->tree));
 
-	iter->user_data = brasero_file_node_nth_child (node, n);
+	iter->user_data = brasero_track_data_cfg_nth_child (node, n);
 	if (!iter->user_data)
 		return FALSE;
 
@@ -224,6 +276,25 @@ brasero_track_data_cfg_iter_nth_child (GtkTreeModel *model,
 	return TRUE;
 }
 
+static guint
+brasero_track_data_cfg_get_n_children (const BraseroFileNode *node)
+{
+	BraseroFileNode *children;
+	guint num = 0;
+
+	if (!node)
+		return 0;
+
+	for (children = BRASERO_FILE_NODE_CHILDREN (node); children; children = children->next) {
+		if (children->is_hidden)
+			continue;
+
+		num ++;
+	}
+
+	return num;
+}
+
 static gint
 brasero_track_data_cfg_iter_n_children (GtkTreeModel *model,
 					 GtkTreeIter *iter)
@@ -236,7 +307,7 @@ brasero_track_data_cfg_iter_n_children (GtkTreeModel *model,
 	if (iter == NULL) {
 		/* special case */
 		node = brasero_data_project_get_root (BRASERO_DATA_PROJECT (priv->tree));
-		return brasero_file_node_get_n_children (node);
+		return brasero_track_data_cfg_get_n_children (node);
 	}
 
 	/* make sure that iter comes from us */
@@ -251,10 +322,10 @@ brasero_track_data_cfg_iter_n_children (GtkTreeModel *model,
 		return 0;
 
 	/* return at least one for the bogus row labelled "empty". */
-	if (!BRASERO_FILE_NODE_CHILDREN (node))
+	if (!brasero_track_data_cfg_get_n_children (node))
 		return 1;
 
-	return brasero_file_node_get_n_children (node);
+	return brasero_track_data_cfg_get_n_children (node);
 }
 
 static gboolean
@@ -309,7 +380,7 @@ brasero_track_data_cfg_iter_children (GtkTreeModel *model,
 
 		/* This is for the top directory */
 		root = brasero_data_project_get_root (BRASERO_DATA_PROJECT (priv->tree));
-		if (!root || !BRASERO_FILE_NODE_CHILDREN (root))
+		if (!root || !brasero_track_data_cfg_get_n_children (root))
 			return FALSE;
 
 		iter->stamp = priv->stamp;
@@ -334,7 +405,7 @@ brasero_track_data_cfg_iter_children (GtkTreeModel *model,
 	}
 
 	iter->stamp = priv->stamp;
-	if (!BRASERO_FILE_NODE_CHILDREN (node)) {
+	if (!brasero_track_data_cfg_get_n_children (node)) {
 		/* This is a directory but it hasn't got any child; yet
 		 * we show a row written empty for that. Set bogus in
 		 * user_data and put parent in user_data. */
@@ -371,7 +442,7 @@ brasero_track_data_cfg_iter_next (GtkTreeModel *model,
 
 	node = iter->user_data;
 	iter->user_data = node->next;
-	if (!node->next)
+	if (!node->next || node->next->is_hidden)
 		return FALSE;
 
 	return TRUE;
@@ -702,7 +773,7 @@ brasero_track_data_cfg_get_value (GtkTreeModel *model,
 				return;
 			}
 
-			nb_items = brasero_file_node_get_n_children (node);
+			nb_items = brasero_track_data_cfg_get_n_children (node);
 			if (!nb_items)
 				g_value_set_string (value, _("Empty"));
 			else {
@@ -803,7 +874,7 @@ brasero_track_data_cfg_get_value (GtkTreeModel *model,
 
 static GtkTreePath *
 brasero_track_data_cfg_get_path (GtkTreeModel *model,
-				  GtkTreeIter *iter)
+				 GtkTreeIter *iter)
 {
 	BraseroTrackDataCfgPrivate *priv;
 	BraseroFileNode *node;
@@ -847,7 +918,7 @@ brasero_track_data_cfg_path_to_node (BraseroTrackDataCfg *self,
 		BraseroFileNode *parent;
 
 		parent = node;
-		node = brasero_file_node_nth_child (parent, indices [i]);
+		node = brasero_track_data_cfg_nth_child (parent, indices [i]);
 		if (!node)
 			return NULL;
 	}
@@ -876,7 +947,7 @@ brasero_track_data_cfg_get_iter (GtkTreeModel *model,
 	if (!root)
 		return FALSE;
 		
-	node = brasero_file_node_nth_child (root, indices [0]);
+	node = brasero_track_data_cfg_nth_child (root, indices [0]);
 	if (!node)
 		return FALSE;
 
@@ -884,13 +955,13 @@ brasero_track_data_cfg_get_iter (GtkTreeModel *model,
 		BraseroFileNode *parent;
 
 		parent = node;
-		node = brasero_file_node_nth_child (parent, indices [i]);
+		node = brasero_track_data_cfg_nth_child (parent, indices [i]);
 		if (!node) {
 			/* There is one case where this can happen and
 			 * is allowed: that's when the parent is an
 			 * empty directory. Then index must be 0. */
 			if (!parent->is_file
-			&&  !BRASERO_FILE_NODE_CHILDREN (parent)
+			&&  !brasero_track_data_cfg_get_n_children (parent)
 			&&   indices [i] == 0) {
 				iter->stamp = priv->stamp;
 				iter->user_data = parent;
@@ -1198,8 +1269,8 @@ brasero_track_data_cfg_row_drop_possible (GtkTreeDragDest *drag_dest,
 
 static gboolean
 brasero_track_data_cfg_get_sort_column_id (GtkTreeSortable *sortable,
-					    gint *column,
-					    GtkSortType *type)
+					   gint *column,
+					   GtkSortType *type)
 {
 	BraseroTrackDataCfgPrivate *priv;
 
@@ -1216,8 +1287,8 @@ brasero_track_data_cfg_get_sort_column_id (GtkTreeSortable *sortable,
 
 static void
 brasero_track_data_cfg_set_sort_column_id (GtkTreeSortable *sortable,
-					    gint column,
-					    GtkSortType type)
+					   gint column,
+					   GtkSortType type)
 {
 	BraseroTrackDataCfgPrivate *priv;
 
@@ -1258,6 +1329,54 @@ brasero_track_data_cfg_has_default_sort_func (GtkTreeSortable *sortable)
 	return TRUE;
 }
 
+
+static BraseroFileNode *
+brasero_track_data_cfg_autorun_inf_parse (BraseroTrackDataCfg *track,
+					  const gchar *uri)
+{
+	BraseroTrackDataCfgPrivate *priv;
+	BraseroFileNode *root;
+	BraseroFileNode *node;
+	GKeyFile *key_file;
+	gchar *icon_path;
+	gchar *path;
+
+	priv = BRASERO_TRACK_DATA_CFG_PRIVATE (track);
+
+	path = g_filename_from_uri (uri, NULL, NULL);
+	key_file = g_key_file_new ();
+
+	if (!g_key_file_load_from_file (key_file, path, G_KEY_FILE_KEEP_COMMENTS|G_KEY_FILE_KEEP_TRANSLATIONS, NULL)) {
+		g_key_file_free (key_file);
+		g_free (path);
+		return NULL;
+	}
+	g_free (path);
+
+	/* NOTE: icon_path is the ON DISC path of the icon */
+	icon_path = g_key_file_get_value (key_file, "autorun", "icon", NULL);
+	g_key_file_free (key_file);
+
+	if (icon_path && icon_path [0] == '\0') {
+		g_free (icon_path);
+		return NULL;
+	}
+
+	/* Get the node (hope it already exists) */
+	root = brasero_data_project_get_root (BRASERO_DATA_PROJECT (priv->tree));
+	node = brasero_file_node_get_from_path (root, icon_path);
+	if (node) {
+		g_free (icon_path);
+		return node;
+	}
+
+	/* Add a virtual node to get warned when/if the icon is added to the tree */
+	node = brasero_data_project_watch_path (BRASERO_DATA_PROJECT (priv->tree), icon_path);
+	g_free (icon_path);
+
+	return node;
+}
+
 static void
 brasero_track_data_cfg_node_added (BraseroDataProject *project,
 				   BraseroFileNode *node,
@@ -1270,6 +1389,32 @@ brasero_track_data_cfg_node_added (BraseroDataProject *project,
 
 	priv = BRASERO_TRACK_DATA_CFG_PRIVATE (self);
 
+	if (priv->icon == node) {
+		/* Our icon node has showed up, signal that */
+		g_signal_emit (self,
+			       brasero_track_data_cfg_signals [ICON_CHANGED],
+			       0);
+	}
+
+	/* Check if the parent is root */
+	if (node->parent->is_root) {
+		if (!strcasecmp (BRASERO_FILE_NODE_NAME (node), "autorun.inf")) {
+			gchar *uri;
+
+			/* This has been added by the user or by a project so
+			 * we do display it; also we signal the change in icon.
+			 * NOTE: if we had our own autorun.inf it was wiped out
+			 * in the callback for "name-collision". */
+			uri = brasero_data_project_node_to_uri (BRASERO_DATA_PROJECT (priv->tree), node);
+			priv->icon = brasero_track_data_cfg_autorun_inf_parse (self, uri);
+			g_free (uri);
+
+			g_signal_emit (self,
+				       brasero_track_data_cfg_signals [ICON_CHANGED],
+				       0);
+		}
+	}
+
 	iter.stamp = priv->stamp;
 	iter.user_data = node;
 	iter.user_data2 = GINT_TO_POINTER (BRASERO_ROW_REGULAR);
@@ -1309,7 +1454,7 @@ brasero_track_data_cfg_node_added (BraseroDataProject *project,
 		/* Check if the parent of this node is empty if so remove the BOGUS row.
 		 * Do it afterwards to prevent the parent row to be collapsed if it was
 		 * previously expanded. */
-		if (parent && brasero_file_node_get_n_children (parent) == 1) {
+		if (parent && brasero_track_data_cfg_get_n_children (parent) == 1) {
 			gtk_tree_path_append_index (path, 1);
 			gtk_tree_model_row_deleted (GTK_TREE_MODEL (self), path);
 		}
@@ -1346,7 +1491,30 @@ brasero_track_data_cfg_node_removed (BraseroDataProject *project,
 	GtkTreePath *path;
 
 	priv = BRASERO_TRACK_DATA_CFG_PRIVATE (self);
-
+	/* NOTE: there is no special case of autorun.inf here when we created
+	 * it as a temprary file since it's hidden and BraseroDataTreeModel
+	 * won't emit a signal for removed file in this case.
+	 * On the other hand we check for a node at root of the CD called
+	 * "autorun.inf" just in case an autorun added by the user would be
+	 * removed. Do it also for the icon node. */
+	if (former_parent->is_root) {
+		if (!strcasecmp (BRASERO_FILE_NODE_NAME (node), "autorun.inf")) {
+			priv->icon = NULL;
+			g_signal_emit (self,
+				       brasero_track_data_cfg_signals [ICON_CHANGED],
+				       0);
+		}
+		else if (priv->icon == node
+		     || (priv->icon && !priv->autorun && brasero_file_node_is_ancestor (node, priv->icon))) {
+			/* This icon had been added by the user. Do nothing but
+			 * register that the icon is no more on the disc */
+			priv->icon = NULL;
+			g_signal_emit (self,
+				       brasero_track_data_cfg_signals [ICON_CHANGED],
+				       0);
+		}
+	}
+	
 	/* remove it from the shown list and all its children as well */
 	priv->shown = g_slist_remove (priv->shown, node);
 	for (iter = priv->shown; iter; iter = next) {
@@ -1362,7 +1530,7 @@ brasero_track_data_cfg_node_removed (BraseroDataProject *project,
 	 * add a bogus row. If it hasn't got children then it only remains our
 	 * node in the list.
 	 * NOTE: parent has to be a directory. */
-	if (!former_parent->is_root && !BRASERO_FILE_NODE_CHILDREN (former_parent)) {
+	if (!former_parent->is_root && !brasero_track_data_cfg_get_n_children (former_parent)) {
 		GtkTreeIter iter;
 
 		iter.stamp = priv->stamp;
@@ -1428,7 +1596,7 @@ brasero_track_data_cfg_node_changed (BraseroDataProject *project,
 								      NULL);
 
 		/* add the row */
-		if (!BRASERO_FILE_NODE_CHILDREN (node))  {
+		if (!brasero_track_data_cfg_get_n_children (node))  {
 			iter.user_data2 = GINT_TO_POINTER (BRASERO_ROW_BOGUS);
 			gtk_tree_path_append_index (path, 0);
 
@@ -1474,23 +1642,49 @@ brasero_track_data_cfg_node_reordered (BraseroDataProject *project,
 }
 
 static void
-brasero_track_data_cfg_finalize (GObject *object)
+brasero_track_data_clean_autorun (BraseroTrackDataCfg *track)
 {
+	gchar *uri;
+	gchar *path;
 	BraseroTrackDataCfgPrivate *priv;
 
-	priv = BRASERO_TRACK_DATA_CFG_PRIVATE (object);
+	priv = BRASERO_TRACK_DATA_CFG_PRIVATE (track);
 
-	if (priv->icon_path) {
-		g_remove (priv->icon_path);
-		g_free (priv->icon_path);
-		priv->icon_path = NULL;
+	if (priv->image_path) {
+		g_free (priv->image_path);
+		priv->image_path = NULL;
 	}
 
-	if (priv->autorun_path) {
-		g_remove (priv->autorun_path);
-		g_free (priv->autorun_path);
-		priv->autorun_path = NULL;
+	if (priv->autorun) {
+		/* ONLY remove icon if it's our own */
+		if (priv->icon) {
+			uri = brasero_data_project_node_to_uri (BRASERO_DATA_PROJECT (priv->tree), priv->icon);
+			path = g_filename_from_uri (uri, NULL, NULL);
+			g_free (uri);
+			g_remove (path);
+			g_free (path);
+			priv->icon = NULL;
+		}
+
+		uri = brasero_data_project_node_to_uri (BRASERO_DATA_PROJECT (priv->tree), priv->autorun);
+		path = g_filename_from_uri (uri, NULL, NULL);
+		g_free (uri);
+		g_remove (path);
+		g_free (path);
+		priv->autorun = NULL;
 	}
+	else
+		priv->icon = NULL;
+}
+
+static void
+brasero_track_data_cfg_finalize (GObject *object)
+{
+	BraseroTrackDataCfgPrivate *priv;
+
+	priv = BRASERO_TRACK_DATA_CFG_PRIVATE (object);
+
+	brasero_track_data_clean_autorun (BRASERO_TRACK_DATA_CFG (object));
 
 	if (priv->shown) {
 		g_slist_free (priv->shown);
@@ -1614,8 +1808,8 @@ brasero_track_data_cfg_add_empty_directory (BraseroTrackDataCfg *track,
 					    const gchar *name,
 					    GtkTreePath *parent)
 {
+	BraseroFileNode *parent_node = NULL;
 	BraseroTrackDataCfgPrivate *priv;
-	BraseroFileNode *parent_node;
 	gchar *default_name = NULL;
 	BraseroFileNode *node;
 
@@ -1630,7 +1824,8 @@ brasero_track_data_cfg_add_empty_directory (BraseroTrackDataCfg *track,
 		if (parent_node && (parent_node->is_file || parent_node->is_loading))
 			parent_node = parent_node->parent;
 	}
-	else
+
+	if (!parent_node)
 		parent_node = brasero_data_project_get_root (BRASERO_DATA_PROJECT (priv->tree));
 
 	if (!name) {
@@ -1704,8 +1899,11 @@ brasero_track_data_cfg_reset (BraseroTrackDataCfg *track)
 	if (priv->loading)
 		return FALSE;
 
+	/* Do it now */
+	brasero_track_data_clean_autorun (track);
+
 	root = brasero_data_project_get_root (BRASERO_DATA_PROJECT (priv->tree));
-	num = brasero_file_node_get_n_children (root);
+	num = brasero_track_data_cfg_get_n_children (root);
 
 	brasero_data_project_reset (BRASERO_DATA_PROJECT (priv->tree));
 
@@ -1717,18 +1915,6 @@ brasero_track_data_cfg_reset (BraseroTrackDataCfg *track)
 	g_slist_free (priv->shown);
 	priv->shown = NULL;
 
-	if (priv->icon_path) {
-		g_remove (priv->icon_path);
-		g_free (priv->icon_path);
-		priv->icon_path = NULL;
-	}
-
-	if (priv->autorun_path) {
-		g_remove (priv->autorun_path);
-		g_free (priv->autorun_path);
-		priv->autorun_path = NULL;
-	}
-
 	priv->G2_files = FALSE;
 	priv->deep_directory = FALSE;
 
@@ -1923,6 +2109,26 @@ brasero_track_data_cfg_get_fs (BraseroTrackData *track)
 	return fs_type;
 }
 
+gboolean
+brasero_track_data_cfg_get_contents (BraseroTrackData *track,
+				     GSList **grafts,
+				     GSList **excluded)
+{
+	BraseroTrackDataCfgPrivate *priv;
+
+	g_return_val_if_fail (BRASERO_IS_TRACK_DATA_CFG (track), FALSE);
+	priv = BRASERO_TRACK_DATA_CFG_PRIVATE (track);
+
+	/* append a slash for mkisofs */
+	brasero_data_project_get_contents (BRASERO_DATA_PROJECT (priv->tree),
+					   grafts,
+					   excluded,
+					   FALSE,	/* no hidden node */
+					   FALSE,	/* no grafts for joliet incompatible nodes */
+					   FALSE);	/* no final slash for names */
+	return TRUE;
+}
+
 static GSList *
 brasero_track_data_cfg_get_grafts (BraseroTrackData *track)
 {
@@ -1937,6 +2143,7 @@ brasero_track_data_cfg_get_grafts (BraseroTrackData *track)
 	brasero_data_project_get_contents (BRASERO_DATA_PROJECT (priv->tree),
 					   &grafts,
 					   NULL,
+					   TRUE, /* include hidden nodes */
 					   (fs_type & BRASERO_IMAGE_FS_JOLIET) != 0,
 					   TRUE);
 	return grafts;
@@ -1956,6 +2163,7 @@ brasero_track_data_cfg_get_excluded (BraseroTrackData *track)
 	brasero_data_project_get_contents (BRASERO_DATA_PROJECT (priv->tree),
 					   NULL,
 					   &unreadable,
+					   TRUE, /* include hidden nodes */
 					   (fs_type & BRASERO_IMAGE_FS_JOLIET) != 0,
 					   TRUE);
 	return unreadable;
@@ -2170,8 +2378,90 @@ brasero_track_data_cfg_unknown_uri_cb (BraseroDataVFS *vfs,
 }
 
 static gboolean
+brasero_track_data_cfg_autorun_inf_update (BraseroTrackDataCfg *self)
+{
+	BraseroTrackDataCfgPrivate *priv;
+	gchar *icon_path = NULL;
+	gsize data_size = 0;
+	GKeyFile *key_file;
+	gchar *data = NULL;
+	gchar *path = NULL;
+	gchar *uri;
+	int fd;
+
+	priv = BRASERO_TRACK_DATA_CFG_PRIVATE (self);
+
+	uri = brasero_data_project_node_to_uri (BRASERO_DATA_PROJECT (priv->tree), priv->autorun);
+	path = g_filename_from_uri (uri, NULL, NULL);
+	g_free (uri);
+
+	fd = open (path, O_WRONLY|O_TRUNC);
+	g_free (path);
+
+	if (fd == -1)
+		return FALSE;
+
+	icon_path = brasero_data_project_node_to_path (BRASERO_DATA_PROJECT (priv->tree), priv->icon);
+
+	/* Write the autorun.inf if we don't have one yet */
+	key_file = g_key_file_new ();
+	g_key_file_set_value (key_file, "autorun", "icon", icon_path);
+	g_free (icon_path);
+
+	data = g_key_file_to_data (key_file, &data_size, NULL);
+	g_key_file_free (key_file);
+
+	if (write (fd, data, data_size) == -1) {
+		g_free (data);
+		close (fd);
+		return FALSE;
+	}
+
+	g_free (data);
+	close (fd);
+	return TRUE;
+}
+
+static gchar *
+brasero_track_data_cfg_find_icon_name (BraseroTrackDataCfg *track)
+{
+	BraseroTrackDataCfgPrivate *priv;
+	BraseroFileNode *root;
+	gchar *name = NULL;
+	int i = 0;
+
+	priv = BRASERO_TRACK_DATA_CFG_PRIVATE (track);
+
+	root = brasero_data_project_get_root (BRASERO_DATA_PROJECT (priv->tree));
+	do {
+		g_free (name);
+		name = g_strdup_printf ("Autorun%i.ico", i);
+	} while (brasero_file_node_check_name_existence (root, name));
+
+	return name;
+}
+
+static void
+brasero_track_data_cfg_virtual_sibling_cb (BraseroDataProject *project,
+					   BraseroFileNode *node,
+					   BraseroFileNode *sibling,
+					   BraseroTrackDataCfg *self)
+{
+	BraseroTrackDataCfgPrivate *priv;
+
+	priv = BRASERO_TRACK_DATA_CFG_PRIVATE (self);
+	if (sibling == priv->icon) {
+		/* This is a warning that the icon has been added. Update our 
+		 * icon node and wait for it to appear in the callback for the
+		 * 'node-added' signal. Then we'll be able to fire the "icon-
+		 * changed" signal. */
+		priv->icon = node;
+	}
+}
+
+static gboolean
 brasero_track_data_cfg_name_collision_cb (BraseroDataProject *project,
-					  const gchar *name,
+					  BraseroFileNode *node,
 					  BraseroTrackDataCfg *self)
 {
 	BraseroTrackDataCfgPrivate *priv;
@@ -2179,6 +2469,51 @@ brasero_track_data_cfg_name_collision_cb (BraseroDataProject *project,
 
 	priv = BRASERO_TRACK_DATA_CFG_PRIVATE (self);
 
+	/* some names are interesting for us */
+	if (node == priv->autorun) {
+		BraseroFileNode *icon;
+
+		/* An autorun.inf has been added by the user. Whether or not we
+		 * are loading a project, if there is an autorun.inf file, then
+		 * wipe it, parse the new and signal */
+
+		/* Save icon node as we'll need it afterwards to remove it */
+		icon = priv->icon;
+
+		/* Do it now as this is the hidden temporarily created
+		 * graft point whose deletion won't be signalled by 
+		 * BraseroDataTreeModel */
+		brasero_track_data_clean_autorun (self);
+		brasero_data_project_remove_node (BRASERO_DATA_PROJECT (priv->tree), icon);
+
+		g_signal_emit (self,
+			       brasero_track_data_cfg_signals [ICON_CHANGED],
+			       0);
+
+		return FALSE;
+	}
+	else if (node == priv->icon) {
+		gchar *uri;
+		gchar *name = NULL;
+		BraseroFileNode *root;
+
+		/* we need to recreate another one with a different name */
+		uri = brasero_data_project_node_to_uri (BRASERO_DATA_PROJECT (priv->tree), node);
+		root = brasero_data_project_get_root (BRASERO_DATA_PROJECT (priv->tree));
+		name = brasero_track_data_cfg_find_icon_name (self);
+
+		priv->icon = brasero_data_project_add_hidden_node (BRASERO_DATA_PROJECT (priv->tree),
+								   uri,
+								   name,
+								   root);
+		g_free (name);
+		g_free (uri);
+
+		/* Update our autorun.inf */
+		brasero_track_data_cfg_autorun_inf_update (self);
+		return FALSE;
+	}
+
 	if (priv->loading) {
 		/* don't do anything accept replacement */
 		return FALSE;
@@ -2187,7 +2522,7 @@ brasero_track_data_cfg_name_collision_cb (BraseroDataProject *project,
 	g_signal_emit (self,
 		       brasero_track_data_cfg_signals [NAME_COLLISION],
 		       0,
-		       name,
+		       BRASERO_FILE_NODE_NAME (node),
 		       &result);
 	return result;
 }
@@ -2423,124 +2758,179 @@ brasero_track_data_cfg_span_stop (BraseroTrackDataCfg *track)
 }
 
 /**
- * This is to handle icons
+ * This is to handle the icon for the image
  */
 
-BraseroBurnResult
+gchar *
+brasero_track_data_cfg_get_scaled_icon_path (BraseroTrackDataCfg *track)
+{
+	BraseroTrackDataCfgPrivate *priv;
+	gchar *path;
+	gchar *uri;
+
+	g_return_val_if_fail (BRASERO_IS_TRACK_DATA_CFG (track), NULL);
+
+	priv = BRASERO_TRACK_DATA_CFG_PRIVATE (track);
+	if (!priv->icon || BRASERO_FILE_NODE_VIRTUAL (priv->icon))
+		return NULL;
+
+	uri = brasero_data_project_node_to_uri (BRASERO_DATA_PROJECT (priv->tree), priv->icon);
+	path = g_filename_from_uri (uri, NULL, NULL);
+	g_free (uri);
+
+	return path;
+}
+
+const gchar *
+brasero_track_data_cfg_get_icon_path (BraseroTrackDataCfg *track)
+{
+	BraseroTrackDataCfgPrivate *priv;
+
+	g_return_val_if_fail (BRASERO_IS_TRACK_DATA_CFG (track), NULL);
+
+	priv = BRASERO_TRACK_DATA_CFG_PRIVATE (track);
+	return priv->image_path;
+}
+
+gboolean
 brasero_track_data_cfg_set_icon (BraseroTrackDataCfg *track,
-				 const gchar *path)
+				 const gchar *icon_path,
+				 GError **error)
 {
 	gboolean result;
 	GdkPixbuf *pixbuf;
-	GError *error = NULL;
 	BraseroFileNode *root;
 	BraseroTrackDataCfgPrivate *priv;
 
+	g_return_val_if_fail (BRASERO_IS_TRACK_DATA_CFG (track), FALSE);
+
 	priv = BRASERO_TRACK_DATA_CFG_PRIVATE (track);
 
+	/* Check whether we don't have an added (by the user) autorun.inf as it
+	 * won't be possible to edit it. */
+	root = brasero_data_project_get_root (BRASERO_DATA_PROJECT (priv->tree));
+
+	if (!priv->autorun) {
+		if (brasero_file_node_check_name_existence_case (root, "autorun.inf")) {
+			/* There is a native autorun.inf file. That's why we can't edit
+			 * it; even if we were to create a temporary file with just the
+			 * icon changed then we could not save it as a project later.
+			 * If I change my mind, I should remember that it the path is
+			 * the value ON DISC. */
+			return FALSE;
+		}
+	}
+
 	/* Load and convert (48x48) the image into a pixbuf */
-	pixbuf = gdk_pixbuf_new_from_file_at_scale (path,
+	pixbuf = gdk_pixbuf_new_from_file_at_scale (icon_path,
 						    48,
 						    48,
 						    FALSE,
-						    &error);
+						    error);
 	if (!pixbuf)
-		return BRASERO_BURN_ERR;
-
-	root = brasero_data_project_get_root (BRASERO_DATA_PROJECT (priv->tree));
+		return FALSE;
 
 	/* See if we already have an icon set. If we do, reuse the tmp file */
-	if (!priv->icon_path) {
-		BraseroFileNode *node;
+	if (!priv->icon) {
 		gchar *buffer = NULL;
 		gchar *path = NULL;
+		gchar *name = NULL;
 		gsize buffer_size;
 		int icon_fd;
 		gchar *uri;
 
 		icon_fd = g_file_open_tmp (BRASERO_BURN_TMP_FILE_NAME,
 					   &path,
-					   NULL);
+					   error);
 		if (icon_fd == -1) {
 			g_object_unref (pixbuf);
-			return BRASERO_BURN_ERR;
+			return FALSE;
 		}
 
 		/* Add it as a graft to the project */
 		uri = g_filename_to_uri (path, NULL, NULL);
-		node = brasero_data_project_add_loading_node (BRASERO_DATA_PROJECT (priv->tree), uri, root);
-		brasero_data_project_rename_node (BRASERO_DATA_PROJECT (priv->tree), node, "Autorun.ico");
-		g_free (uri);
+		g_free (path);
 
-		/* That's just to be able to remove it later */
-		priv->icon_path = path;
+ 		name = brasero_track_data_cfg_find_icon_name (track);
+		priv->icon = brasero_data_project_add_hidden_node (BRASERO_DATA_PROJECT (priv->tree),
+								   uri,
+								   name,
+								   root);
+		g_free (name);
+		g_free (uri);
 
 		/* Write it as an "ico" file (or a png?) */
 		result = gdk_pixbuf_save_to_buffer (pixbuf,
 						    &buffer,
 						    &buffer_size,
 						    "ico",
-						    NULL,
+						    error,
 						    NULL);
 		if (!result) {
 			close (icon_fd);
 			g_object_unref (pixbuf);
-			return BRASERO_BURN_ERR;
+			return FALSE;
 		}
 
 		if (write (icon_fd, buffer, buffer_size) == -1) {
 			g_object_unref (pixbuf);
 			g_free (buffer);
 			close (icon_fd);
-			return BRASERO_BURN_ERR;
+			return FALSE;
 		}
 
 		g_free (buffer);
 		close (icon_fd);
 	}
 	else {
+		gchar *path;
+
+		path = brasero_track_data_cfg_get_scaled_icon_path (track);
+
 		/* Write it as an "ico" file (or a png?) */
 		result = gdk_pixbuf_save (pixbuf,
-					  priv->icon_path,
+					  path,
 					  "ico",
-					  &error,
+					  error,
 					  NULL);
+		g_free (path);
+
+		if (!result) {
+			g_object_unref (pixbuf);
+			return FALSE;
+		}
 	}
 
 	g_object_unref (pixbuf);
 
-	/* Get a temporary file if we don't have one yet */
-	if (!priv->autorun_path) {
-		const char *line = "[autorun]\nicon=Autorun.ico";
-		BraseroFileNode *node;
+	if (!priv->autorun) {
 		gchar *path = NULL;
 		gchar *uri;
 		int fd;
 
+		/* Get a temporary file if we don't have one yet */
 		fd = g_file_open_tmp (BRASERO_BURN_TMP_FILE_NAME,
 				      &path,
-				      NULL);
-		if (fd == -1)
-			return BRASERO_BURN_ERR;
-
-		/* Write the autorun.inf if we don't have one yet */
-		if (write (fd, line, sizeof (line)) == -1) {
-			close (fd);
-			return BRASERO_BURN_ERR;
-		}
+				      error);
 		close (fd);
 
 		/* Add it as a graft to the project */
 		uri = g_filename_to_uri (path, NULL, NULL);
-		node = brasero_data_project_add_loading_node (BRASERO_DATA_PROJECT (priv->tree), uri, root);
-		brasero_data_project_rename_node (BRASERO_DATA_PROJECT (priv->tree), node, "Autorun.inf");
+		priv->autorun = brasero_data_project_add_hidden_node (BRASERO_DATA_PROJECT (priv->tree),
+								      uri,
+								      "autorun.inf",
+								      root);
 		g_free (uri);
 
-		/* That's just to be able to remove it later */
-		priv->autorun_path = path;
+		/* write the autorun.inf */
+		brasero_track_data_cfg_autorun_inf_update (track);
 	}
 
-	return BRASERO_BURN_OK;
+	priv->image_path = g_strdup (icon_path);
+	g_signal_emit (track,
+		       brasero_track_data_cfg_signals [ICON_CHANGED],
+		       0);
+	return TRUE;
 }
 
 static void
@@ -2626,6 +3016,10 @@ brasero_track_data_cfg_init (BraseroTrackDataCfg *object)
 			  G_CALLBACK (brasero_track_data_cfg_image_uri_cb),
 			  object);
 	g_signal_connect (priv->tree,
+			  "virtual-sibling",
+			  G_CALLBACK (brasero_track_data_cfg_virtual_sibling_cb),
+			  object);
+	g_signal_connect (priv->tree,
 			  "name-collision",
 			  G_CALLBACK (brasero_track_data_cfg_name_collision_cb),
 			  object);
@@ -2795,6 +3189,17 @@ brasero_track_data_cfg_class_init (BraseroTrackDataCfgClass *klass)
 			  G_TYPE_NONE,
 			  1,
 			  G_TYPE_POINTER);
+
+	brasero_track_data_cfg_signals [ICON_CHANGED] = 
+	    g_signal_new ("icon_changed",
+			  G_TYPE_FROM_CLASS (klass),
+			  G_SIGNAL_RUN_LAST|G_SIGNAL_NO_RECURSE,
+			  0,
+			  NULL, NULL,
+			  g_cclosure_marshal_VOID__VOID,
+			  G_TYPE_NONE,
+			  0,
+			  G_TYPE_NONE);
 }
 
 BraseroTrackDataCfg *
diff --git a/libbrasero-burn/brasero-track-data-cfg.h b/libbrasero-burn/brasero-track-data-cfg.h
index 5a860d2..ec39ccf 100644
--- a/libbrasero-burn/brasero-track-data-cfg.h
+++ b/libbrasero-burn/brasero-track-data-cfg.h
@@ -89,6 +89,11 @@ BraseroTrackDataCfg *
 brasero_track_data_cfg_new (void);
 
 gboolean
+brasero_track_data_cfg_get_contents (BraseroTrackData *track,
+				     GSList **grafts,
+				     GSList **excluded);
+
+gboolean
 brasero_track_data_cfg_add (BraseroTrackDataCfg *track,
 			    const gchar *uri,
 			    GtkTreePath *parent);
@@ -148,9 +153,6 @@ brasero_track_data_cfg_restore (BraseroTrackDataCfg *track,
 GtkTreeModel *
 brasero_track_data_cfg_get_filtered_model (BraseroTrackDataCfg *track);
 
-BraseroBurnResult
-brasero_track_data_cfg_set_icon (BraseroTrackDataCfg *track,
-				 const gchar *path);
 
 /**
  * Track Spanning
@@ -173,10 +175,16 @@ brasero_track_data_cfg_span_stop (BraseroTrackDataCfg *track);
 /**
  * Icon
  */
+gchar *
+brasero_track_data_cfg_get_scaled_icon_path (BraseroTrackDataCfg *track);
 
-BraseroBurnResult
+const gchar *
+brasero_track_data_cfg_get_icon_path (BraseroTrackDataCfg *track);
+
+gboolean
 brasero_track_data_cfg_set_icon (BraseroTrackDataCfg *track,
-				 const gchar *path);
+				 const gchar *path,
+				 GError **error);
 
 G_END_DECLS
 
diff --git a/libbrasero-burn/libbrasero-marshal.list b/libbrasero-burn/libbrasero-marshal.list
index 63dee6b..69bfeb8 100644
--- a/libbrasero-burn/libbrasero-marshal.list
+++ b/libbrasero-burn/libbrasero-marshal.list
@@ -4,6 +4,7 @@ INT:STRING
 INT:OBJECT,INT,INT
 INT:POINTER,BOOLEAN
 BOOLEAN:STRING
+BOOLEAN:POINTER
 VOID:INT,STRING
 VOID:POINTER,STRING
 VOID:POINTER,POINTER
diff --git a/src/brasero-data-disc.c b/src/brasero-data-disc.c
index 1fc0e6d..35fd842 100644
--- a/src/brasero-data-disc.c
+++ b/src/brasero-data-disc.c
@@ -168,6 +168,13 @@ static GtkTargetEntry ntables_source [] = {
 static guint nb_targets_source = sizeof (ntables_source) / sizeof (ntables_source[0]);
 
 enum {
+	ICON_CHANGED, 
+	LAST_SIGNAL
+};
+
+static gulong brasero_data_disc_signals [LAST_SIGNAL] = { 0 };
+
+enum {
 	PROP_NONE,
 	PROP_REJECT_FILE,
 };
@@ -322,6 +329,8 @@ brasero_data_disc_new_folder_clicked_cb (GtkButton *button,
 
 	parent = brasero_data_disc_get_parent (disc);
 	treepath = brasero_track_data_cfg_add_empty_directory (BRASERO_TRACK_DATA_CFG (priv->project), NULL, parent);
+	gtk_tree_path_free (parent);
+
 	gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), 1);
 
 	/* grab focus must be called before next function to avoid
@@ -497,8 +506,10 @@ brasero_data_disc_name_edited_cb (GtkCellRendererText *cellrenderertext,
 
 	if (name && !strcmp (name, text)) {
 		gtk_tree_path_free (path);
+		g_free (name);
 		return;
 	}
+	g_free (name);
 
 	/* NOTE: BraseroDataProject is where we handle name collisions,
 	 * UTF-8 validity, ...
@@ -1137,6 +1148,15 @@ brasero_data_disc_session_available_cb (BraseroTrackDataCfg *session,
 }
 
 static void
+brasero_data_disc_icon_changed_cb (BraseroTrackDataCfg *session,
+				   BraseroDataDisc *self)
+{
+	g_signal_emit (self,
+		       brasero_data_disc_signals [ICON_CHANGED],
+		       0);
+}
+
+static void
 brasero_data_disc_session_loaded_cb (BraseroTrackDataCfg *session,
 				     BraseroMedium *medium,
 				     gboolean loaded,
@@ -1321,18 +1341,23 @@ static BraseroDiscResult
 brasero_data_disc_get_track (BraseroDisc *disc,
 			     BraseroDiscTrack *track)
 {
+	gboolean res;
 	GSList *grafts = NULL;
+	GSList *excluded = NULL;
 	BraseroDataDiscPrivate *priv;
 
 	priv = BRASERO_DATA_DISC_PRIVATE (disc);
 
-	grafts = brasero_track_data_get_grafts (BRASERO_TRACK_DATA (priv->project));
-	if (!grafts)
+	res = brasero_track_data_cfg_get_contents (BRASERO_TRACK_DATA (priv->project),
+						   &grafts,
+						   &excluded);
+	if (!res)
 		return BRASERO_DISC_ERROR_EMPTY_SELECTION;
 
+	track->contents.data.icon = g_strdup (brasero_track_data_cfg_get_icon_path (priv->project));
 	track->type = BRASERO_PROJECT_TYPE_DATA;
 	track->contents.data.grafts = grafts;
-	track->contents.data.excluded = brasero_track_data_get_excluded (BRASERO_TRACK_DATA (priv->project), TRUE);
+	track->contents.data.excluded = excluded;
 
 	/* get restored */
 	track->contents.data.restored = brasero_track_data_cfg_get_restored_list (BRASERO_TRACK_DATA_CFG (priv->project));
@@ -1387,7 +1412,7 @@ brasero_data_disc_load_track (BraseroDisc *disc,
 		gchar *uri;
 
 		uri = iter->data;
-		brasero_track_data_cfg_dont_filter_uri (BRASERO_TRACK_DATA_CFG (priv->project), uri);
+		brasero_track_data_cfg_dont_filter_uri (priv->project, uri);
 	}
 
 	res = brasero_track_data_set_source (BRASERO_TRACK_DATA (priv->project),
@@ -1435,6 +1460,11 @@ brasero_data_disc_load_track (BraseroDisc *disc,
 	gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), 1);
 
 	brasero_status_free (status);
+
+	/* The icon */
+	if (track->contents.data.icon)
+		brasero_track_data_cfg_set_icon (priv->project, track->contents.data.icon, NULL);
+
 	return BRASERO_DISC_OK;
 }
 
@@ -2067,13 +2097,33 @@ brasero_data_disc_contents_removed_cb (GtkTreeModel *model,
 	BraseroDataDiscPrivate *priv;
 
 	priv = BRASERO_DATA_DISC_PRIVATE (self);
-
 	brasero_disc_contents_changed (BRASERO_DISC (self), gtk_tree_model_iter_n_children (GTK_TREE_MODEL (priv->project), NULL));
 }
 
 /**
- * Object creation/destruction
+ * Misc functions
  */
+
+gboolean
+brasero_data_disc_set_icon_path (BraseroDataDisc *self,
+				 const gchar *path,
+				 GError **error)
+{
+	BraseroDataDiscPrivate *priv;
+
+	priv = BRASERO_DATA_DISC_PRIVATE (self);
+	return brasero_track_data_cfg_set_icon (priv->project, path, error);
+}
+
+gchar *
+brasero_data_disc_get_scaled_icon_path (BraseroDataDisc *disc)
+{
+	BraseroDataDiscPrivate *priv;
+
+	priv = BRASERO_DATA_DISC_PRIVATE (disc);
+	return brasero_track_data_cfg_get_scaled_icon_path (priv->project);
+}
+
 void
 brasero_data_disc_set_right_button_group (BraseroDataDisc *self,
 					  GtkSizeGroup *size_group)
@@ -2084,6 +2134,9 @@ brasero_data_disc_set_right_button_group (BraseroDataDisc *self,
 	brasero_file_filtered_set_right_button_group (BRASERO_FILE_FILTERED (priv->filter), size_group);
 }
 
+/**
+ * Object creation/destruction
+ */
 static void
 brasero_data_disc_init (BraseroDataDisc *object)
 {
@@ -2182,6 +2235,11 @@ brasero_data_disc_init (BraseroDataDisc *object)
 			  G_CALLBACK (brasero_data_disc_session_loaded_cb),
 			  object);
 
+	g_signal_connect (priv->project,
+			  "icon-changed",
+			  G_CALLBACK (brasero_data_disc_icon_changed_cb),
+			  object);
+
 	/* Tree */
 	priv->tree = gtk_tree_view_new_with_model (GTK_TREE_MODEL (priv->project));
 	gtk_tree_view_set_rubber_banding (GTK_TREE_VIEW (priv->tree), TRUE);
@@ -2419,6 +2477,17 @@ brasero_data_disc_class_init (BraseroDataDiscClass *klass)
 	object_class->set_property = brasero_data_disc_set_property;
 	object_class->get_property = brasero_data_disc_get_property;
 
+	brasero_data_disc_signals [ICON_CHANGED] = 
+	    g_signal_new ("icon_changed",
+			  G_TYPE_FROM_CLASS (klass),
+			  G_SIGNAL_RUN_LAST|G_SIGNAL_NO_RECURSE,
+			  0,
+			  NULL, NULL,
+			  g_cclosure_marshal_VOID__VOID,
+			  G_TYPE_NONE,
+			  0,
+			  G_TYPE_NONE);
+
 	g_object_class_install_property (object_class,
 					 PROP_REJECT_FILE,
 					 g_param_spec_boolean
diff --git a/src/brasero-data-disc.h b/src/brasero-data-disc.h
index b640bb7..504273d 100644
--- a/src/brasero-data-disc.h
+++ b/src/brasero-data-disc.h
@@ -56,6 +56,13 @@ GType brasero_data_disc_get_type (void) G_GNUC_CONST;
 GtkWidget *
 brasero_data_disc_new (void);
 
+gboolean
+brasero_data_disc_set_icon_path (BraseroDataDisc *disc,
+				 const gchar *path,
+				 GError **error);
+gchar *
+brasero_data_disc_get_scaled_icon_path (BraseroDataDisc *disc);
+
 void
 brasero_data_disc_set_right_button_group (BraseroDataDisc *disc,
 					  GtkSizeGroup *size_group);
diff --git a/src/brasero-project-parse.c b/src/brasero-project-parse.c
index e0a4c2a..f3e9b34 100644
--- a/src/brasero-project-parse.c
+++ b/src/brasero-project-parse.c
@@ -113,6 +113,9 @@ brasero_track_clear (BraseroDiscTrack *track)
 		g_slist_free (track->contents.tracks);
 	}
 	else if (track->type == BRASERO_PROJECT_TYPE_DATA) {
+		g_free (track->contents.data.icon);
+		track->contents.data.icon = NULL;
+
 		g_slist_foreach (track->contents.data.grafts, (GFunc) brasero_graft_point_free, NULL);
 		g_slist_free (track->contents.data.grafts);
 		g_slist_foreach (track->contents.data.restored, (GFunc) g_free, NULL);
@@ -212,6 +215,20 @@ _read_data_track (xmlDocPtr project,
 			if (!_read_graft_point (project, item->xmlChildrenNode, track))
 				goto error;
 		}
+		else if (!xmlStrcmp (item->name, (const xmlChar *) "icon")) {
+			xmlChar *icon_path;
+
+			icon_path = xmlNodeListGetString (project,
+							  item->xmlChildrenNode,
+							  1);
+			if (!icon_path)
+				goto error;
+
+			if (track->contents.data.icon)
+				g_free (track->contents.data.icon);
+
+			track->contents.data.icon = (gchar *) icon_path;
+		}
 		else if (!xmlStrcmp (item->name, (const xmlChar *) "restored")) {
 			xmlChar *restored;
 
diff --git a/src/brasero-project-parse.h b/src/brasero-project-parse.h
index 3e365a6..e00593e 100644
--- a/src/brasero-project-parse.h
+++ b/src/brasero-project-parse.h
@@ -78,6 +78,7 @@ typedef struct {
 			GSList *grafts;
 			GSList *excluded;
 			GSList *restored;
+			gchar *icon;
 		} data;
 
 		GSList *tracks; /* BraseroDiscSong */
diff --git a/src/brasero-project.c b/src/brasero-project.c
index 928374c..b2a2ddc 100644
--- a/src/brasero-project.c
+++ b/src/brasero-project.c
@@ -154,6 +154,8 @@ typedef enum {
 
 struct BraseroProjectPrivate {
 	GtkWidget *name_display;
+	GtkWidget *button_img;
+	GtkWidget *icon_img;
 	GtkWidget *discs;
 	GtkWidget *audio;
 	GtkWidget *data;
@@ -417,10 +419,121 @@ brasero_project_name_changed_cb (BraseroProjectName *name,
 }
 
 static void
+brasero_project_data_icon_error (BraseroProject *project,
+				 GError *error)
+{
+	if (error) {
+		brasero_app_alert (brasero_app_get_default (),
+				   /* Translators: this is a picture not
+				    * a disc image */
+				   C_("picture", "Please select another image."),
+				   error->message,
+				   GTK_MESSAGE_ERROR);
+	}
+	else {
+		brasero_app_alert (brasero_app_get_default (),
+				   /* Translators: this is a picture not
+				    * a disc image */
+				   C_("picture", "Please select another image."),
+				   _("Unknown error"),
+				   GTK_MESSAGE_ERROR);
+	}
+}
+
+static void
+brasero_project_icon_changed_cb (BraseroDisc *disc,
+				 BraseroProject *project)
+{
+	GError *error = NULL;
+	GdkPixbuf *pixbuf;
+	gchar *icon; 
+
+	icon = brasero_data_disc_get_scaled_icon_path (BRASERO_DATA_DISC (project->priv->current));
+	if (!icon) {
+		gtk_image_set_from_icon_name (GTK_IMAGE (project->priv->icon_img),
+					      "media-optical",
+					      GTK_ICON_SIZE_LARGE_TOOLBAR);
+		return;
+	}
+
+	/* Load and convert (48x48) the image into a pixbuf */
+	pixbuf = gdk_pixbuf_new_from_file_at_scale (icon,
+						    48,
+						    48,
+						    FALSE,
+						    &error);
+	g_free (icon);
+
+	if (!pixbuf) {
+		gtk_image_set_from_icon_name (GTK_IMAGE (project->priv->icon_img),
+					      "media-optical",
+					      GTK_ICON_SIZE_LARGE_TOOLBAR);
+		brasero_project_data_icon_error (project, error);
+		g_error_free (error);
+		return;
+	}
+
+	gtk_image_set_from_pixbuf (GTK_IMAGE (project->priv->icon_img), pixbuf);
+	g_object_unref (pixbuf);
+}
+
+static void
+brasero_project_icon_button_clicked (GtkWidget *button,
+				     BraseroProject *project)
+{
+	GtkFileFilter *filter;
+	GError *error = NULL;
+	GtkWidget *chooser;
+	gchar *path;
+	gint res;
+
+	if (!BRASERO_IS_DATA_DISC (project->priv->current))
+		return;
+
+	chooser = gtk_file_chooser_dialog_new (_("Medium Icon"),
+					       GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (project))),
+					       GTK_FILE_CHOOSER_ACTION_OPEN,
+					       GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+					       GTK_STOCK_OK, GTK_RESPONSE_OK,
+					       NULL);
+
+	filter = gtk_file_filter_new ();
+	gtk_file_filter_set_name (filter, _("All files"));
+	gtk_file_filter_add_pattern (filter, "*");
+	gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (chooser), filter);
+
+	filter = gtk_file_filter_new ();
+	/* Translators: this is an image, a picture, not a "Disc Image" */
+	gtk_file_filter_set_name (filter, C_("picture", "Image files"));
+	gtk_file_filter_add_mime_type (filter, "image/*");
+	gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (chooser), filter);
+
+	gtk_widget_show (chooser);
+	res = gtk_dialog_run (GTK_DIALOG (chooser));
+	if (res != GTK_RESPONSE_OK) {
+		gtk_widget_destroy (chooser);
+		return;
+	}
+
+	path = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (chooser));
+	gtk_widget_destroy (chooser);
+
+	if (!brasero_data_disc_set_icon_path (BRASERO_DATA_DISC (project->priv->current), path, &error)) {
+		if (error) {
+			brasero_project_data_icon_error (project, error);
+			g_error_free (error);
+		}
+	}
+	g_free (path);
+}
+
+static void
 brasero_project_init (BraseroProject *obj)
 {
 	GtkSizeGroup *size_group;
 	GtkWidget *alignment;
+	GtkWidget *button;
+	GtkWidget *image;
 	GtkWidget *label;
 	GtkWidget *box;
 
@@ -441,6 +554,25 @@ brasero_project_init (BraseroProject *obj)
 	gtk_widget_show (box);
 	gtk_box_pack_end (GTK_BOX (obj), box, FALSE, TRUE, 0);
 
+	/* Icon button */
+	image = gtk_image_new_from_icon_name ("media-optical", GTK_ICON_SIZE_LARGE_TOOLBAR);
+	gtk_widget_show (image);
+	obj->priv->icon_img = image;
+
+	button = gtk_button_new ();
+	gtk_widget_show (button);
+	gtk_button_set_image (GTK_BUTTON (button), image);
+	obj->priv->button_img = button;
+
+	gtk_widget_set_tooltip_text (button, _("Select an icon for the disc that will appear in file managers"));
+
+	g_signal_connect (button,
+			  "clicked",
+			  G_CALLBACK (brasero_project_icon_button_clicked),
+			  obj);
+
+	gtk_box_pack_start (GTK_BOX (box), button, FALSE, TRUE, 0);
+
 	/* Name widget */
 	label = gtk_label_new_with_mnemonic (_("_Name:"));
 	gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
@@ -517,6 +649,10 @@ brasero_project_init (BraseroProject *obj)
 			  "selection-changed",
 			  G_CALLBACK (brasero_project_selection_changed_cb),
 			  obj);
+	g_signal_connect (obj->priv->data,
+			  "icon-changed",
+			  G_CALLBACK (brasero_project_icon_changed_cb),
+			  obj);
 
 	obj->priv->video = brasero_video_disc_new ();
 	gtk_widget_show (obj->priv->video);
@@ -1015,6 +1151,10 @@ brasero_project_switch (BraseroProject *project, BraseroProjectType type)
 		project->priv->project_status = NULL;
 	}
 
+	gtk_image_set_from_icon_name (GTK_IMAGE (project->priv->icon_img),
+				      "media-optical",
+				      GTK_ICON_SIZE_LARGE_TOOLBAR);
+
 	if (project->priv->current)
 		brasero_disc_reset (project->priv->current);
 
@@ -1046,6 +1186,7 @@ brasero_project_switch (BraseroProject *project, BraseroProjectType type)
 					  project->priv->merge_id);
 
 	if (type == BRASERO_PROJECT_TYPE_AUDIO) {
+		gtk_widget_hide (project->priv->button_img);
 		project->priv->current = BRASERO_DISC (project->priv->audio);
 		project->priv->merge_id = brasero_disc_add_ui (project->priv->current,
 							       project->priv->manager,
@@ -1055,6 +1196,7 @@ brasero_project_switch (BraseroProject *project, BraseroProjectType type)
 		brasero_project_update_project_size (project, 0);
 	}
 	else if (type == BRASERO_PROJECT_TYPE_DATA) {
+		gtk_widget_show (project->priv->button_img);
 		project->priv->current = BRASERO_DISC (project->priv->data);
 		project->priv->merge_id = brasero_disc_add_ui (project->priv->current,
 							       project->priv->manager,
@@ -1064,6 +1206,7 @@ brasero_project_switch (BraseroProject *project, BraseroProjectType type)
 		brasero_project_update_project_size (project, 0);
 	}
 	else if (type == BRASERO_PROJECT_TYPE_VIDEO) {
+		gtk_widget_hide (project->priv->button_img);
 		project->priv->current = BRASERO_DISC (project->priv->video);
 		project->priv->merge_id = brasero_disc_add_ui (project->priv->current,
 							       project->priv->manager,
@@ -1979,6 +2122,13 @@ _save_data_track_xml (xmlTextWriter *project,
 	GSList *grafts;
 	BraseroGraftPt *graft;
 
+	if (track->contents.data.icon) {
+		/* Write the icon if any */
+		success = xmlTextWriterWriteElement (project, (xmlChar *) "icon", (xmlChar *) track->contents.data.icon);
+		if (success < 0)
+			return FALSE;
+	}
+
 	for (grafts = track->contents.data.grafts; grafts; grafts = grafts->next) {
 		graft = grafts->data;
 
@@ -2384,6 +2534,7 @@ brasero_project_save_project_real (BraseroProject *project,
 		return FALSE;
 
 	bzero (&track, sizeof (track));
+
 	result = brasero_disc_get_track (project->priv->current, &track);
 	if (result == BRASERO_DISC_ERROR_EMPTY_SELECTION) {
 		if (BRASERO_IS_AUDIO_DISC (project->priv->current))
@@ -2636,6 +2787,8 @@ brasero_project_save_session (BraseroProject *project,
 
     	bzero (&track, sizeof (track));
 	if (brasero_disc_get_track (project->priv->current, &track) == BRASERO_DISC_OK) {
+		/* NOTE: is this right? because brasero could not shut itself
+		 * down if an error occurs. */
 		if (!brasero_project_save_project_xml (project,
 						       uri,
 						       &track,



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