[brasero: 3/18] Buildable tree after implementing new type of track (BraseroTrackDataCfg) and porting nautilus exten



commit 8bb0637daa0677ac79b897716caa1884054ecce6
Author: Philippe Rouquier <bonfire-app wanadoo fr>
Date:   Wed Apr 29 15:59:52 2009 +0200

    Buildable tree after implementing new type of track (BraseroTrackDataCfg) and porting nautilus extension to it
---
 libbrasero-burn/Makefile.am               |    4 +-
 libbrasero-burn/brasero-data-project.c    |   35 +-
 libbrasero-burn/brasero-data-project.h    |   30 +-
 libbrasero-burn/brasero-data-session.c    |   30 +-
 libbrasero-burn/brasero-data-session.h    |   30 +-
 libbrasero-burn/brasero-data-tree-model.c | 1558 ++--------------------
 libbrasero-burn/brasero-data-tree-model.h |   72 +-
 libbrasero-burn/brasero-data-vfs.c        |  232 +---
 libbrasero-burn/brasero-data-vfs.h        |   54 +-
 libbrasero-burn/brasero-file-monitor.c    |   30 +-
 libbrasero-burn/brasero-file-monitor.h    |   30 +-
 libbrasero-burn/brasero-file-node.c       |   60 +-
 libbrasero-burn/brasero-file-node.h       |   40 +-
 libbrasero-burn/brasero-filtered-uri.c    |  277 ++++
 libbrasero-burn/brasero-filtered-uri.h    |  102 ++
 libbrasero-burn/brasero-status.h          |    7 +
 libbrasero-burn/brasero-track-data-cfg.c  | 2073 ++++++++++++++++++++++++++++-
 libbrasero-burn/brasero-track-data-cfg.h  |   71 +-
 libbrasero-burn/brasero-track-data.c      |   21 +-
 libbrasero-burn/brasero-track-data.h      |   11 +-
 libbrasero-burn/libbrasero-marshal.list   |    2 +
 libbrasero-utils/brasero-misc.c           |   80 +-
 libbrasero-utils/brasero-misc.h           |    9 +-
 nautilus/nautilus-burn-extension.c        |   20 +-
 src/brasero-data-disc.c                   |  727 ++++-------
 src/brasero-file-filtered.c               |  454 ++-----
 src/brasero-file-filtered.h               |   22 +-
 src/brasero-multi-dnd.c                   |   71 +
 28 files changed, 3374 insertions(+), 2778 deletions(-)

diff --git a/libbrasero-burn/Makefile.am b/libbrasero-burn/Makefile.am
index 77326f6..32bfcfc 100644
--- a/libbrasero-burn/Makefile.am
+++ b/libbrasero-burn/Makefile.am
@@ -186,8 +186,8 @@ libbrasero_burn_la_SOURCES = 		\
 	brasero-data-tree-model.h                 \
 	brasero-track-data-cfg.c                 \
 	brasero-track-data-cfg.h                 \
-	eggtreemultidnd.c                 \
-	eggtreemultidnd.h
+	brasero-filtered-uri.c                 \
+	brasero-filtered-uri.h
 
 if BUILD_INOTIFY
 libbrasero_burn_la_SOURCES += brasero-file-monitor.c brasero-file-monitor.h
diff --git a/libbrasero-burn/brasero-data-project.c b/libbrasero-burn/brasero-data-project.c
index b87cc42..19d6f8a 100644
--- a/libbrasero-burn/brasero-data-project.c
+++ b/libbrasero-burn/brasero-data-project.c
@@ -1,20 +1,28 @@
 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
 /*
- * brasero
- * Copyright (C) Philippe Rouquier 2007-2008 <bonfire-app wanadoo fr>
- * 
- *  Brasero is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
+ * Libbrasero-burn
+ * Copyright (C) Philippe Rouquier 2005-2009 <bonfire-app wanadoo fr>
+ *
+ * Libbrasero-burn is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The Libbrasero-burn authors hereby grant permission for non-GPL compatible
+ * GStreamer plugins to be used and distributed together with GStreamer
+ * and Libbrasero-burn. This permission is above and beyond the permissions granted
+ * by the GPL license by which Libbrasero-burn is covered. If you modify this code
+ * you may extend this exception to your version of the code, but you are not
+ * obligated to do so. If you do not wish to do so, delete this exception
+ * statement from your version.
  * 
- * brasero is distributed in the hope that it will be useful,
+ * Libbrasero-burn is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Library General Public License for more details.
  * 
  * You should have received a copy of the GNU General Public License
- * along with brasero.  If not, write to:
+ * along with this program; if not, write to:
  * 	The Free Software Foundation, Inc.,
  * 	51 Franklin Street, Fifth Floor
  * 	Boston, MA  02110-1301, USA.
@@ -84,6 +92,7 @@ struct _BraseroDataProjectPrivate
 #ifdef BUILD_INOTIFY
 
 #include "brasero-file-monitor.h"
+
 G_DEFINE_TYPE (BraseroDataProject, brasero_data_project, BRASERO_TYPE_FILE_MONITOR);
 
 #else
@@ -1594,7 +1603,7 @@ brasero_data_project_restore_uri (BraseroDataProject *self,
 
 	priv = BRASERO_DATA_PROJECT_PRIVATE (self);
 
-	name = brasero_file_node_get_uri_name (uri);
+	name = brasero_utils_get_uri_name (uri);
 
 	parent_uri = g_path_get_dirname (uri);
 	nodes = brasero_data_project_uri_to_nodes (self, parent_uri);
@@ -2006,7 +2015,7 @@ brasero_data_project_add_loading_node (BraseroDataProject *self,
 		parent = priv->root;
 
 	/* NOTE: find the name of the node through the URI */
-	name = brasero_file_node_get_uri_name (uri);
+	name = brasero_utils_get_uri_name (uri);
 
 	/* make sure that name doesn't exist */
 	node = brasero_file_node_check_name_existence (parent, name);
diff --git a/libbrasero-burn/brasero-data-project.h b/libbrasero-burn/brasero-data-project.h
index 45980f8..ac16698 100644
--- a/libbrasero-burn/brasero-data-project.h
+++ b/libbrasero-burn/brasero-data-project.h
@@ -1,20 +1,28 @@
 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
 /*
- * brasero
- * Copyright (C) Philippe Rouquier 2007-2008 <bonfire-app wanadoo fr>
+ * Libbrasero-burn
+ * Copyright (C) Philippe Rouquier 2005-2009 <bonfire-app wanadoo fr>
+ *
+ * Libbrasero-burn is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The Libbrasero-burn authors hereby grant permission for non-GPL compatible
+ * GStreamer plugins to be used and distributed together with GStreamer
+ * and Libbrasero-burn. This permission is above and beyond the permissions granted
+ * by the GPL license by which Libbrasero-burn is covered. If you modify this code
+ * you may extend this exception to your version of the code, but you are not
+ * obligated to do so. If you do not wish to do so, delete this exception
+ * statement from your version.
  * 
- *  Brasero is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- * 
- * brasero is distributed in the hope that it will be useful,
+ * Libbrasero-burn is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Library General Public License for more details.
  * 
  * You should have received a copy of the GNU General Public License
- * along with brasero.  If not, write to:
+ * along with this program; if not, write to:
  * 	The Free Software Foundation, Inc.,
  * 	51 Franklin Street, Fifth Floor
  * 	Boston, MA  02110-1301, USA.
diff --git a/libbrasero-burn/brasero-data-session.c b/libbrasero-burn/brasero-data-session.c
index 9b731e0..c3cf5a2 100644
--- a/libbrasero-burn/brasero-data-session.c
+++ b/libbrasero-burn/brasero-data-session.c
@@ -1,20 +1,28 @@
 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
 /*
- * brasero
- * Copyright (C) Philippe Rouquier 2007-2008 <bonfire-app wanadoo fr>
+ * Libbrasero-burn
+ * Copyright (C) Philippe Rouquier 2005-2009 <bonfire-app wanadoo fr>
+ *
+ * Libbrasero-burn is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The Libbrasero-burn authors hereby grant permission for non-GPL compatible
+ * GStreamer plugins to be used and distributed together with GStreamer
+ * and Libbrasero-burn. This permission is above and beyond the permissions granted
+ * by the GPL license by which Libbrasero-burn is covered. If you modify this code
+ * you may extend this exception to your version of the code, but you are not
+ * obligated to do so. If you do not wish to do so, delete this exception
+ * statement from your version.
  * 
- *  Brasero is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- * 
- * brasero is distributed in the hope that it will be useful,
+ * Libbrasero-burn is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Library General Public License for more details.
  * 
  * You should have received a copy of the GNU General Public License
- * along with brasero.  If not, write to:
+ * along with this program; if not, write to:
  * 	The Free Software Foundation, Inc.,
  * 	51 Franklin Street, Fifth Floor
  * 	Boston, MA  02110-1301, USA.
diff --git a/libbrasero-burn/brasero-data-session.h b/libbrasero-burn/brasero-data-session.h
index 99493b6..da4ed4b 100644
--- a/libbrasero-burn/brasero-data-session.h
+++ b/libbrasero-burn/brasero-data-session.h
@@ -1,20 +1,28 @@
 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
 /*
- * brasero
- * Copyright (C) Philippe Rouquier 2007-2008 <bonfire-app wanadoo fr>
+ * Libbrasero-burn
+ * Copyright (C) Philippe Rouquier 2005-2009 <bonfire-app wanadoo fr>
+ *
+ * Libbrasero-burn is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The Libbrasero-burn authors hereby grant permission for non-GPL compatible
+ * GStreamer plugins to be used and distributed together with GStreamer
+ * and Libbrasero-burn. This permission is above and beyond the permissions granted
+ * by the GPL license by which Libbrasero-burn is covered. If you modify this code
+ * you may extend this exception to your version of the code, but you are not
+ * obligated to do so. If you do not wish to do so, delete this exception
+ * statement from your version.
  * 
- *  Brasero is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- * 
- * brasero is distributed in the hope that it will be useful,
+ * Libbrasero-burn is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Library General Public License for more details.
  * 
  * You should have received a copy of the GNU General Public License
- * along with brasero.  If not, write to:
+ * along with this program; if not, write to:
  * 	The Free Software Foundation, Inc.,
  * 	51 Franklin Street, Fifth Floor
  * 	Boston, MA  02110-1301, USA.
diff --git a/libbrasero-burn/brasero-data-tree-model.c b/libbrasero-burn/brasero-data-tree-model.c
index 4d90c71..a3572b0 100644
--- a/libbrasero-burn/brasero-data-tree-model.c
+++ b/libbrasero-burn/brasero-data-tree-model.c
@@ -1,20 +1,28 @@
 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
 /*
- * brasero
- * Copyright (C) Philippe Rouquier 2007-2008 <bonfire-app wanadoo fr>
+ * Libbrasero-burn
+ * Copyright (C) Philippe Rouquier 2005-2009 <bonfire-app wanadoo fr>
+ *
+ * Libbrasero-burn is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The Libbrasero-burn authors hereby grant permission for non-GPL compatible
+ * GStreamer plugins to be used and distributed together with GStreamer
+ * and Libbrasero-burn. This permission is above and beyond the permissions granted
+ * by the GPL license by which Libbrasero-burn is covered. If you modify this code
+ * you may extend this exception to your version of the code, but you are not
+ * obligated to do so. If you do not wish to do so, delete this exception
+ * statement from your version.
  * 
- *  Brasero is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- * 
- * brasero is distributed in the hope that it will be useful,
+ * Libbrasero-burn is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Library General Public License for more details.
  * 
  * You should have received a copy of the GNU General Public License
- * along with brasero.  If not, write to:
+ * along with this program; if not, write to:
  * 	The Free Software Foundation, Inc.,
  * 	51 Franklin Street, Fifth Floor
  * 	Boston, MA  02110-1301, USA.
@@ -33,1226 +41,47 @@
 
 #include "brasero-misc.h"
 
+#include "libbrasero-marshal.h"
 #include "brasero-data-tree-model.h"
 #include "brasero-data-project.h"
 #include "brasero-data-vfs.h"
 #include "brasero-file-node.h"
 
-#include "eggtreemultidnd.h"
-
 typedef struct _BraseroDataTreeModelPrivate BraseroDataTreeModelPrivate;
 struct _BraseroDataTreeModelPrivate
 {
 	guint stamp;
-
-	GtkIconTheme *theme;
-
-	GSList *shown;
-
-	gint sort_column;
-	GtkSortType sort_type;
 };
 
 #define BRASERO_DATA_TREE_MODEL_PRIVATE(o)  (G_TYPE_INSTANCE_GET_PRIVATE ((o), BRASERO_TYPE_DATA_TREE_MODEL, BraseroDataTreeModelPrivate))
 
-typedef enum {
-	BRASERO_ROW_REGULAR		= 0,
-	BRASERO_ROW_BOGUS
-} BraseroFileRowType;
-
-static void
-brasero_data_tree_model_multi_drag_source_iface_init (gpointer g_iface, gpointer data);
-static void
-brasero_data_tree_model_drag_source_iface_init (gpointer g_iface, gpointer data);
-static void
-brasero_data_tree_model_drag_dest_iface_init (gpointer g_iface, gpointer data);
-static void
-brasero_data_tree_model_sortable_iface_init (gpointer g_iface, gpointer data);
-static void
-brasero_data_tree_model_iface_init (gpointer g_iface, gpointer data);
-
-G_DEFINE_TYPE_WITH_CODE (BraseroDataTreeModel,
-			 brasero_data_tree_model,
-			 BRASERO_TYPE_DATA_VFS,
-			 G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_MODEL,
-					        brasero_data_tree_model_iface_init)
-			 G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_DRAG_DEST,
-					        brasero_data_tree_model_drag_dest_iface_init)
-			 G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_DRAG_SOURCE,
-					        brasero_data_tree_model_drag_source_iface_init)
-			 G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_SORTABLE,
-						brasero_data_tree_model_sortable_iface_init)
-			 G_IMPLEMENT_INTERFACE (EGG_TYPE_TREE_MULTI_DRAG_SOURCE,
-					        brasero_data_tree_model_multi_drag_source_iface_init));
-
-
-static gboolean
-brasero_data_tree_model_iter_parent (GtkTreeModel *model,
-				     GtkTreeIter *iter,
-				     GtkTreeIter *child)
-{
-	BraseroDataTreeModelPrivate *priv;
-	BraseroFileNode *node;
-
-	priv = BRASERO_DATA_TREE_MODEL_PRIVATE (model);
-
-	/* make sure that iter comes from us */
-	g_return_val_if_fail (priv->stamp == child->stamp, FALSE);
-	g_return_val_if_fail (child->user_data != NULL, FALSE);
-
-	node = child->user_data;
-	if (child->user_data2 == GINT_TO_POINTER (BRASERO_ROW_BOGUS)) {
-		/* This is a bogus row intended for empty directories
-		 * user_data has the parent empty directory. */
-		iter->user_data2 = GINT_TO_POINTER (BRASERO_ROW_REGULAR);
-		iter->user_data = child->user_data;
-		iter->stamp = priv->stamp;
-		return TRUE;
-	}
-
-	if (!node->parent) {
-		iter->user_data = NULL;
-		return FALSE;
-	}
-
-	iter->stamp = priv->stamp;
-	iter->user_data = node->parent;
-	iter->user_data2 = GINT_TO_POINTER (BRASERO_ROW_REGULAR);
-	return TRUE;
-}
-
-static gboolean
-brasero_data_tree_model_iter_nth_child (GtkTreeModel *model,
-					GtkTreeIter *iter,
-					GtkTreeIter *parent,
-					gint n)
-{
-	BraseroDataTreeModelPrivate *priv;
-	BraseroFileNode *node;
-
-	priv = BRASERO_DATA_TREE_MODEL_PRIVATE (model);
-
-	if (parent) {
-		/* make sure that iter comes from us */
-		g_return_val_if_fail (priv->stamp == parent->stamp, FALSE);
-		g_return_val_if_fail (parent->user_data != NULL, FALSE);
-
-		if (parent->user_data2 == GINT_TO_POINTER (BRASERO_ROW_BOGUS)) {
-			/* This is a bogus row intended for empty directories,
-			 * it hasn't got children. */
-			return FALSE;
-		}
-
-		node = parent->user_data;
-	}
-	else
-		node = brasero_data_project_get_root (BRASERO_DATA_PROJECT (model));
-
-	iter->user_data = brasero_file_node_nth_child (node, n);
-	if (!iter->user_data)
-		return FALSE;
-
-	iter->stamp = priv->stamp;
-	iter->user_data2 = GINT_TO_POINTER (BRASERO_ROW_REGULAR);
-	return TRUE;
-}
-
-static gint
-brasero_data_tree_model_iter_n_children (GtkTreeModel *model,
-					 GtkTreeIter *iter)
-{
-	BraseroDataTreeModelPrivate *priv;
-	BraseroFileNode *node;
-
-	priv = BRASERO_DATA_TREE_MODEL_PRIVATE (model);
-
-	if (iter == NULL) {
-		/* special case */
-		node = brasero_data_project_get_root (BRASERO_DATA_PROJECT (model));
-		return brasero_file_node_get_n_children (node);
-	}
-
-	/* make sure that iter comes from us */
-	g_return_val_if_fail (priv->stamp == iter->stamp, 0);
-	g_return_val_if_fail (iter->user_data != NULL, 0);
-
-	if (iter->user_data2 == GINT_TO_POINTER (BRASERO_ROW_BOGUS))
-		return 0;
-
-	node = iter->user_data;
-	if (node->is_file)
-		return 0;
-
-	/* return at least one for the bogus row labelled "empty". */
-	if (!BRASERO_FILE_NODE_CHILDREN (node))
-		return 1;
-
-	return brasero_file_node_get_n_children (node);
-}
-
-static gboolean
-brasero_data_tree_model_iter_has_child (GtkTreeModel *model,
-					GtkTreeIter *iter)
-{
-	BraseroDataTreeModelPrivate *priv;
-	BraseroFileNode *node;
-
-	priv = BRASERO_DATA_TREE_MODEL_PRIVATE (model);
-
-	/* make sure that iter comes from us */
-	g_return_val_if_fail (priv->stamp == iter->stamp, FALSE);
-	g_return_val_if_fail (iter->user_data != NULL, FALSE);
-
-	if (iter->user_data2 == GINT_TO_POINTER (BRASERO_ROW_BOGUS)) {
-		/* This is a bogus row intended for empty directories
-		 * it hasn't got children */
-		return FALSE;
-	}
-
-	node = iter->user_data;
-
-	/* This is a workaround for a warning in gailtreeview.c line 2946 where
-	 * gail uses the GtkTreePath and not a copy which if the node inserted
-	 * declares to have children and is not expanded leads to the path being
-	 * upped and therefore wrong. */
-	if (node->is_inserting)
-		return FALSE;
-
-	if (node->is_file)
-		return FALSE;
-
-	/* always return TRUE here when it's a directory since even if
-	 * it's empty we'll add a row written empty underneath it
-	 * anyway. */
-	return TRUE;
-}
-
-static gboolean
-brasero_data_tree_model_iter_children (GtkTreeModel *model,
-				       GtkTreeIter *iter,
-				       GtkTreeIter *parent)
-{
-	BraseroDataTreeModelPrivate *priv;
-	BraseroFileNode *node;
-
-	priv = BRASERO_DATA_TREE_MODEL_PRIVATE (model);
-
-	if (!parent) {
-		BraseroFileNode *root;
-
-		/* This is for the top directory */
-		root = brasero_data_project_get_root (BRASERO_DATA_PROJECT (model));
-		if (!root || !BRASERO_FILE_NODE_CHILDREN (root))
-			return FALSE;
-
-		iter->stamp = priv->stamp;
-		iter->user_data = BRASERO_FILE_NODE_CHILDREN (root);
-		iter->user_data2 = GINT_TO_POINTER (BRASERO_ROW_REGULAR);
-		return TRUE;
-	}
-
-	/* make sure that iter comes from us */
-	g_return_val_if_fail (priv->stamp == parent->stamp, FALSE);
-	g_return_val_if_fail (parent->user_data != NULL, FALSE);
-
-	if (parent->user_data2 == GINT_TO_POINTER (BRASERO_ROW_BOGUS)) {
-		iter->user_data = NULL;
-		return FALSE;
-	}
-
-	node = parent->user_data;
-	if (node->is_file) {
-		iter->user_data = NULL;
-		return FALSE;
-	}
-
-	iter->stamp = priv->stamp;
-	if (!BRASERO_FILE_NODE_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. */
-		iter->user_data = parent->user_data;
-		iter->user_data2 = GINT_TO_POINTER (BRASERO_ROW_BOGUS);
-		return TRUE;
-	}
-
-	iter->user_data = BRASERO_FILE_NODE_CHILDREN (node);
-	iter->user_data2 = GINT_TO_POINTER (BRASERO_ROW_REGULAR);
-	return TRUE;
-}
-
-static gboolean
-brasero_data_tree_model_iter_next (GtkTreeModel *model,
-				   GtkTreeIter *iter)
-{
-	BraseroDataTreeModelPrivate *priv;
-	BraseroFileNode *node;
-
-	priv = BRASERO_DATA_TREE_MODEL_PRIVATE (model);
-
-	/* make sure that iter comes from us */
-	g_return_val_if_fail (priv->stamp == iter->stamp, FALSE);
-	g_return_val_if_fail (iter->user_data != NULL, FALSE);
-
-	if (iter->user_data2 == GINT_TO_POINTER (BRASERO_ROW_BOGUS)) {
-		/* This is a bogus row intended for empty directories
-		 * user_data has the parent empty directory. It hasn't
-		 * got any peer.*/
-		iter->user_data = NULL;
-		return FALSE;
-	}
-
-	node = iter->user_data;
-	iter->user_data = node->next;
-	if (!node->next)
-		return FALSE;
-
-	return TRUE;
-}
-
-static void
-brasero_data_tree_model_node_shown (GtkTreeModel *model,
-				    GtkTreeIter *iter)
-{
-	BraseroFileNode *node;
-	BraseroDataTreeModelPrivate *priv;
-
-	priv = BRASERO_DATA_TREE_MODEL_PRIVATE (model);
-	node = iter->user_data;
-
-	/* Check if that's a BOGUS row. In this case that means the parent was
-	 * expanded. Therefore ask vfs to increase its priority if it's loading
-	 * its contents. */
-	if (iter->user_data2 == GINT_TO_POINTER (BRASERO_ROW_BOGUS)) {
-		/* NOTE: this has to be a directory */
-		/* NOTE: there is no need to check for is_loading case here
-		 * since before showing its BOGUS row the tree will have shown
-		 * its parent itself and therefore that's the cases that follow
-		 */
-		if (node->is_exploring) {
-			/* the directory is being explored increase priority */
-			brasero_data_vfs_require_directory_contents (BRASERO_DATA_VFS (model), node);
-		}
-
-		/* Otherwise, that's simply a BOGUS row and its parent was
-		 * loaded but it is empty. Nothing to do. */
-
-		return;
-	}
-
-	if (!node)
-		return;
-
-	node->is_visible ++;
-
-	if (node->is_imported) {
-		if (node->is_fake && !node->is_file) {
-			/* we don't load all nodes when importing a session do it now */
-			brasero_data_session_load_directory_contents (BRASERO_DATA_SESSION (model), node, NULL);
-		}
-
-		return;
-	}
-
-	if (node->is_visible > 1)
-		return;
-
-	/* NOTE: no need to see if that's a directory being explored here. If it
-	 * is being explored then it has a BOGUS row and that's the above case 
-	 * that is reached. */
-	if (node->is_loading) {
-		/* in this case have vfs to increase priority for this node */
-		brasero_data_vfs_require_node_load (BRASERO_DATA_VFS (model), node);
-	}
-	else if (!BRASERO_FILE_NODE_MIME (node)) {
-		/* that means that file wasn't completly loaded. To save
-		 * some time we delayed the detection of the mime type
-		 * since that takes a lot of time. */
-		brasero_data_vfs_load_mime (BRASERO_DATA_VFS (model), node);
-	}
-
-	/* add the node to the visible list that is used to update the disc 
-	 * share for the node (we don't want to update the whole tree).
-	 * Moreover, we only want files since directories don't have space. */
-	priv->shown = g_slist_prepend (priv->shown, node);
-}
-
-static void
-brasero_data_tree_model_node_hidden (GtkTreeModel *model,
-				     GtkTreeIter *iter)
-{
-	BraseroFileNode *node;
-	BraseroDataTreeModelPrivate *priv;
-
-	/* if it's a BOGUS row stop here since they are not added to shown list.
-	 * In the same way returns if it is a file. */
-	if (iter->user_data2 == GINT_TO_POINTER (BRASERO_ROW_BOGUS))
-		return;
-
-	node = iter->user_data;
-
-	if (!node)
-		return;
-
-	node->is_visible --;
-
-	if (node->is_imported)
-		return;
-
-	priv = BRASERO_DATA_TREE_MODEL_PRIVATE (model);
-
-	/* update shown list */
-	if (!node->is_visible)
-		priv->shown = g_slist_remove (priv->shown, node);
-}
-
-static void
-brasero_data_tree_model_get_value (GtkTreeModel *model,
-				   GtkTreeIter *iter,
-				   gint column,
-				   GValue *value)
-{
-	BraseroDataTreeModelPrivate *priv;
-	BraseroDataTreeModel *self;
-	BraseroFileNode *node;
-
-	self = BRASERO_DATA_TREE_MODEL (model);
-	priv = BRASERO_DATA_TREE_MODEL_PRIVATE (model);
-
-	/* make sure that iter comes from us */
-	g_return_if_fail (priv->stamp == iter->stamp);
-	g_return_if_fail (iter->user_data != NULL);
-
-	node = iter->user_data;
-
-	if (iter->user_data2 == GINT_TO_POINTER (BRASERO_ROW_BOGUS)) {
-		switch (column) {
-		case BRASERO_DATA_TREE_MODEL_NAME:
-			g_value_init (value, G_TYPE_STRING);
-			if (node->is_exploring)
-				g_value_set_string (value, _("(loading ...)"));
-			else
-				g_value_set_string (value, _("Empty"));
-
-			return;
-
-		case BRASERO_DATA_TREE_MODEL_MIME_DESC:
-		case BRASERO_DATA_TREE_MODEL_MIME_ICON:
-		case BRASERO_DATA_TREE_MODEL_SIZE:
-			g_value_init (value, G_TYPE_STRING);
-			g_value_set_string (value, NULL);
-			return;
-
-		case BRASERO_DATA_TREE_MODEL_SHOW_PERCENT:
-			g_value_init (value, G_TYPE_BOOLEAN);
-			g_value_set_boolean (value, FALSE);
-			return;
-
-		case BRASERO_DATA_TREE_MODEL_PERCENT:
-			g_value_init (value, G_TYPE_INT);
-			g_value_set_int (value, 0);
-			return;
-
-		case BRASERO_DATA_TREE_MODEL_STYLE:
-			g_value_init (value, PANGO_TYPE_STYLE);
-			g_value_set_enum (value, PANGO_STYLE_ITALIC);
-			return;
-
-		case BRASERO_DATA_TREE_MODEL_EDITABLE:
-			g_value_init (value, G_TYPE_BOOLEAN);
-			g_value_set_boolean (value, FALSE);
-			return;
-	
-		case BRASERO_DATA_TREE_MODEL_COLOR:
-			g_value_init (value, G_TYPE_STRING);
-			g_value_set_string (value, NULL);
-			return;
-
-		default:
-			return;
-		}
-
-		return;
-	}
-
-	switch (column) {
-	case BRASERO_DATA_TREE_MODEL_EDITABLE:
-		g_value_init (value, G_TYPE_BOOLEAN);
-		g_value_set_boolean (value, (node->is_imported == FALSE) && node->is_selected);
-		return;
-
-	case BRASERO_DATA_TREE_MODEL_NAME: {
-		gchar *filename;
-
-		g_value_init (value, G_TYPE_STRING);
-		filename = g_filename_to_utf8 (BRASERO_FILE_NODE_NAME (node),
-					       -1,
-					       NULL,
-					       NULL,
-					       NULL);
-		if (!filename)
-			filename = brasero_utils_validate_utf8 (BRASERO_FILE_NODE_NAME (node));
-
-		if (filename)
-			g_value_set_string (value, filename);
-		else	/* Glib section on g_convert advise to use a string like
-			 * "Invalid Filename". */
-			g_value_set_string (value, BRASERO_FILE_NODE_NAME (node));
-
-		g_free (filename);
-		return;
-	}
-
-	case BRASERO_DATA_TREE_MODEL_MIME_DESC:
-		g_value_init (value, G_TYPE_STRING);
-		if (node->is_loading)
-			g_value_set_string (value, _("(loading ...)"));
-		else if (!node->is_file) {
-			gchar *description;
-
-			description = g_content_type_get_description ("inode/directory");
-			g_value_set_string (value, description);
-			g_free (description);
-		}
-		else if (node->is_imported)
-			g_value_set_string (value, _("Disc file"));
-		else if (!BRASERO_FILE_NODE_MIME (node))
-			g_value_set_string (value, _("(loading ...)"));
-		else {
-			gchar *description;
-
-			description = g_content_type_get_description (BRASERO_FILE_NODE_MIME (node));
-			g_value_set_string (value, description);
-			g_free (description);
-		}
-
-		return;
-
-	case BRASERO_DATA_TREE_MODEL_MIME_ICON:
-		g_value_init (value, G_TYPE_STRING);
-		if (node->is_loading)
-			g_value_set_string (value, "image-loading");
-		else if (!node->is_file) {
-			/* Here we have two states collapsed and expanded */
-			if (node->is_expanded)
-				g_value_set_string (value, "folder-open");
-			else if (node->is_imported)
-				/* that's for all the imported folders */
-				g_value_set_string (value, "folder-visiting");
-			else
-				g_value_set_string (value, "folder");
-		}
-		else if (node->is_imported) {
-			g_value_set_string (value, "media-cdrom");
-		}
-		else if (BRASERO_FILE_NODE_MIME (node)) {
-			const gchar *icon_string = "text-x-preview";
-			GIcon *icon;
-
-			/* NOTE: implemented in glib 2.15.6 (not for windows though) */
-			icon = g_content_type_get_icon (BRASERO_FILE_NODE_MIME (node));
-			if (G_IS_THEMED_ICON (icon)) {
-				const gchar * const *names = NULL;
-
-				names = g_themed_icon_get_names (G_THEMED_ICON (icon));
-				if (names) {
-					gint i;
-
-					for (i = 0; names [i]; i++) {
-						if (gtk_icon_theme_has_icon (priv->theme, names [i])) {
-							icon_string = names [i];
-							break;
-						}
-					}
-				}
-			}
-
-			g_value_set_string (value, icon_string);
-			g_object_unref (icon);
-		}
-		else
-			g_value_set_string (value, "image-loading");
-
-		return;
-
-	case BRASERO_DATA_TREE_MODEL_SIZE:
-		g_value_init (value, G_TYPE_STRING);
-		if (node->is_loading)
-			g_value_set_string (value, _("(loading ...)"));
-		else if (!node->is_file) {
-			guint nb_items;
-
-			if (node->is_exploring) {
-				g_value_set_string (value, _("(loading ...)"));
-				return;
-			}
-
-			nb_items = brasero_file_node_get_n_children (node);
-			if (!nb_items)
-				g_value_set_string (value, _("Empty"));
-			else {
-				gchar *text;
-
-				text = g_strdup_printf (ngettext ("%d item", "%d items", nb_items), nb_items);
-				g_value_set_string (value, text);
-				g_free (text);
-			}
-		}
-		else {
-			gchar *text;
-
-			text = g_format_size_for_display (BRASERO_FILE_NODE_SECTORS (node) * 2048);
-			g_value_set_string (value, text);
-			g_free (text);
-		}
-
-		return;
-
-	case BRASERO_DATA_TREE_MODEL_SHOW_PERCENT:
-		g_value_init (value, G_TYPE_BOOLEAN);
-		if (node->is_imported || node->is_loading)
-			g_value_set_boolean (value, FALSE);
-		else
-			g_value_set_boolean (value, TRUE);
-
-		return;
-
-	case BRASERO_DATA_TREE_MODEL_PERCENT:
-		g_value_init (value, G_TYPE_INT);
-		if (!node->is_imported && !brasero_data_vfs_is_active (BRASERO_DATA_VFS (self))) {
-			gint64 size;
-			guint node_size;
-
-			size = brasero_data_project_get_size (BRASERO_DATA_PROJECT (self));
-
-			if (!node->is_file)
-				node_size = brasero_data_project_get_folder_size (BRASERO_DATA_PROJECT (self), node);
-			else
-				node_size = BRASERO_FILE_NODE_SECTORS (node);
-			if (size)
-				g_value_set_int (value, MAX (0, MIN (node_size * 100 / size, 100)));
-			else
-				g_value_set_int (value, 0);
-		}
-		else
-			g_value_set_int (value, 0);
-
-		return;
-
-	case BRASERO_DATA_TREE_MODEL_STYLE:
-		g_value_init (value, PANGO_TYPE_STYLE);
-		if (node->is_imported)
-			g_value_set_enum (value, PANGO_STYLE_ITALIC);
-
-		return;
-
-	case BRASERO_DATA_TREE_MODEL_COLOR:
-		g_value_init (value, G_TYPE_STRING);
-		if (node->is_imported)
-			g_value_set_string (value, "grey50");
-
-		return;
-
-	default:
-		return;
-	}
-
-	return;
-}
-
-GtkTreePath *
-brasero_data_tree_model_node_to_path (BraseroDataTreeModel *self,
-				      BraseroFileNode *node)
-{
-	BraseroDataTreeModelPrivate *priv;
-	GtkTreePath *path;
-
-	priv = BRASERO_DATA_TREE_MODEL_PRIVATE (self);
-
-	path = gtk_tree_path_new ();
-	for (; node->parent && !node->is_root; node = node->parent) {
-		guint nth;
-
-		nth = brasero_file_node_get_pos_as_child (node);
-		gtk_tree_path_prepend_index (path, nth);
-	}
-
-	return path;
-}
-
-static GtkTreePath *
-brasero_data_tree_model_get_path (GtkTreeModel *model,
-				  GtkTreeIter *iter)
-{
-	BraseroDataTreeModelPrivate *priv;
-	BraseroFileNode *node;
-	GtkTreePath *path;
-
-	priv = BRASERO_DATA_TREE_MODEL_PRIVATE (model);
-
-	/* make sure that iter comes from us */
-	g_return_val_if_fail (priv->stamp == iter->stamp, NULL);
-	g_return_val_if_fail (iter->user_data != NULL, NULL);
-
-	node = iter->user_data;
-
-	/* NOTE: there is only one single node without a name: root */
-	path = brasero_data_tree_model_node_to_path (BRASERO_DATA_TREE_MODEL (model), node);
-
-	/* Add index 0 for empty bogus row */
-	if (iter->user_data2 == GINT_TO_POINTER (BRASERO_ROW_BOGUS))
-		gtk_tree_path_append_index (path, 0);
-
-	return path;
-}
-
-BraseroFileNode *
-brasero_data_tree_model_path_to_node (BraseroDataTreeModel *self,
-				      GtkTreePath *path)
-{
-	BraseroDataTreeModelPrivate *priv;
-	BraseroFileNode *node;
-	gint *indices;
-	guint depth;
-	guint i;
-
-	priv = BRASERO_DATA_TREE_MODEL_PRIVATE (self);
-
-	indices = gtk_tree_path_get_indices (path);
-	depth = gtk_tree_path_get_depth (path);
-
-	node = brasero_data_project_get_root (BRASERO_DATA_PROJECT (self));
-	for (i = 0; i < depth; i ++) {
-		BraseroFileNode *parent;
-
-		parent = node;
-		node = brasero_file_node_nth_child (parent, indices [i]);
-		if (!node)
-			return NULL;
-	}
-	return node;
-}
-
-static gboolean
-brasero_data_tree_model_get_iter (GtkTreeModel *model,
-				  GtkTreeIter *iter,
-				  GtkTreePath *path)
-{
-	BraseroDataTreeModelPrivate *priv;
-	BraseroFileNode *root;
-	BraseroFileNode *node;
-	const gint *indices;
-	guint depth;
-	guint i;
-
-	priv = BRASERO_DATA_TREE_MODEL_PRIVATE (model);
-
-	indices = gtk_tree_path_get_indices (path);
-	depth = gtk_tree_path_get_depth (path);
-
-	root = brasero_data_project_get_root (BRASERO_DATA_PROJECT (model));
-	/* NOTE: if we're in reset, then root won't exist anymore */
-	if (!root)
-		return FALSE;
-		
-	node = brasero_file_node_nth_child (root, indices [0]);
-	if (!node)
-		return FALSE;
-
-	for (i = 1; i < depth; i ++) {
-		BraseroFileNode *parent;
-
-		parent = node;
-		node = brasero_file_node_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)
-			&&   indices [i] == 0) {
-				iter->stamp = priv->stamp;
-				iter->user_data = parent;
-				iter->user_data2 = GINT_TO_POINTER (BRASERO_ROW_BOGUS);
-				return TRUE;
-			}
-
-			iter->user_data = NULL;
-			return FALSE;
-		}
-	}
-
-	iter->user_data2 = GINT_TO_POINTER (BRASERO_ROW_REGULAR);
-	iter->stamp = priv->stamp;
-	iter->user_data = node;
-
-	return TRUE;
-}
-
-static GType
-brasero_data_tree_model_get_column_type (GtkTreeModel *model,
-					 gint index)
-{
-	switch (index) {
-	case BRASERO_DATA_TREE_MODEL_NAME:
-		return G_TYPE_STRING;
-
-	case BRASERO_DATA_TREE_MODEL_MIME_DESC:
-		return G_TYPE_STRING;
-
-	case BRASERO_DATA_TREE_MODEL_MIME_ICON:
-		return G_TYPE_STRING;
-
-	case BRASERO_DATA_TREE_MODEL_SIZE:
-		return G_TYPE_STRING;
-
-	case BRASERO_DATA_TREE_MODEL_SHOW_PERCENT:
-		return G_TYPE_BOOLEAN;
-
-	case BRASERO_DATA_TREE_MODEL_PERCENT:
-		return G_TYPE_INT;
+G_DEFINE_TYPE (BraseroDataTreeModel, brasero_data_tree_model, BRASERO_TYPE_DATA_VFS);
 
-	case BRASERO_DATA_TREE_MODEL_STYLE:
-		return PANGO_TYPE_STYLE;
-
-	case BRASERO_DATA_TREE_MODEL_COLOR:
-		return G_TYPE_STRING;
-
-	case BRASERO_DATA_TREE_MODEL_EDITABLE:
-		return G_TYPE_BOOLEAN;
-
-	default:
-		break;
-	}
-
-	return G_TYPE_INVALID;
-}
-
-static gint
-brasero_data_tree_model_get_n_columns (GtkTreeModel *model)
-{
-	return BRASERO_DATA_TREE_MODEL_COL_NUM;
-}
-
-static GtkTreeModelFlags
-brasero_data_tree_model_get_flags (GtkTreeModel *model)
-{
-	return 0;
-}
-
-static gboolean
-brasero_data_tree_model_multi_row_draggable (EggTreeMultiDragSource *drag_source,
-					     GList *path_list)
-{
-	GList *iter;
-
-	for (iter = path_list; iter && iter->data; iter = iter->next) {
-		GtkTreeRowReference *reference;
-		BraseroFileNode *node;
-		GtkTreePath *treepath;
-
-		reference = iter->data;
-		treepath = gtk_tree_row_reference_get_path (reference);
-		node = brasero_data_tree_model_path_to_node (BRASERO_DATA_TREE_MODEL (drag_source), treepath);
-		gtk_tree_path_free (treepath);
-
-		/* at least one row must not be an imported row. */
-		if (node && !node->is_imported)
-			return TRUE;
-	}
-
-	return FALSE;
-}
-
-static gboolean
-brasero_data_tree_model_multi_drag_data_get (EggTreeMultiDragSource *drag_source,
-					     GList *path_list,
-					     GtkSelectionData *selection_data)
-{
-	if (selection_data->target == gdk_atom_intern (BRASERO_DND_TARGET_SELF_FILE_NODES, TRUE)) {
-		BraseroDNDDataContext context;
-
-		context.model = GTK_TREE_MODEL (drag_source);
-		context.references = path_list;
-
-		gtk_selection_data_set (selection_data,
-					gdk_atom_intern_static_string (BRASERO_DND_TARGET_SELF_FILE_NODES),
-					8,
-					(void *) &context,
-					sizeof (context));
-	}
-	else
-		return FALSE;
-
-	return TRUE;
-}
-
-static gboolean
-brasero_data_tree_model_multi_drag_data_delete (EggTreeMultiDragSource *drag_source,
-						GList *path_list)
-{
-	/* NOTE: it's not the data in the selection_data here that should be
-	 * deleted but rather the rows selected when there is a move. FALSE
-	 * here means that we didn't delete anything. */
-	/* return TRUE to stop other handlers */
-	return TRUE;
-}
-
-static gboolean
-brasero_data_tree_model_drag_data_received (GtkTreeDragDest *drag_dest,
-					    GtkTreePath *dest_path,
-					    GtkSelectionData *selection_data)
-{
-	BraseroFileNode *node;
-	BraseroFileNode *parent;
-	GtkTreePath *dest_parent;
-	BraseroDataTreeModel *self;
-
-	self = BRASERO_DATA_TREE_MODEL (drag_dest);
-
-	/* NOTE: dest_path is the path to insert before; so we may not have a 
-	 * valid path if it's in an empty directory */
-
-	dest_parent = gtk_tree_path_copy (dest_path);
-	gtk_tree_path_up (dest_parent);
-	parent = brasero_data_tree_model_path_to_node (self, dest_parent);
-	if (!parent) {
-		gtk_tree_path_up (dest_parent);
-		parent = brasero_data_tree_model_path_to_node (self, dest_parent);
-	}
-	else if (parent->is_file)
-		parent = parent->parent;
-
-	gtk_tree_path_free (dest_parent);
-
-	/* Received data: see where it comes from:
-	 * - from us, then that's a simple move
-	 * - from another widget then it's going to be URIS and we add
-	 *   them to the DataProject */
-	if (selection_data->target == gdk_atom_intern (BRASERO_DND_TARGET_SELF_FILE_NODES, TRUE)) {
-		BraseroDNDDataContext *context;
-		GList *iter;
-
-		context = (BraseroDNDDataContext *) selection_data->data;
-		if (context->model != GTK_TREE_MODEL (drag_dest))
-			return TRUE;
-
-		/* That's us: move the row and its children. */
-		for (iter = context->references; iter; iter = iter->next) {
-			GtkTreeRowReference *reference;
-			GtkTreePath *treepath;
-
-			reference = iter->data;
-			treepath = gtk_tree_row_reference_get_path (reference);
-
-			node = brasero_data_tree_model_path_to_node (BRASERO_DATA_TREE_MODEL (drag_dest), treepath);
-			gtk_tree_path_free (treepath);
-
-			brasero_data_project_move_node (BRASERO_DATA_PROJECT (self), node, parent);
-		}
-	}
-	else if (selection_data->target == gdk_atom_intern ("text/uri-list", TRUE)) {
-		gint i;
-		gchar **uris;
-		gboolean success = FALSE;
-
-		/* NOTE: there can be many URIs at the same time. One
-		 * success is enough to return TRUE. */
-		success = FALSE;
-		uris = gtk_selection_data_get_uris (selection_data);
-		if (!uris)
-			return TRUE;
-
-		for (i = 0; uris [i]; i ++) {
-			BraseroFileNode *node;
-
-			/* Add the URIs to the project */
-			node = brasero_data_project_add_loading_node (BRASERO_DATA_PROJECT (self),
-								      uris [i],
-								      parent);
-			if (node)
-				success = TRUE;
-		}
-		g_strfreev (uris);
-	}
-	else
-		return FALSE;
-
-	return TRUE;
-}
-
-static gboolean
-brasero_data_tree_model_row_drop_possible (GtkTreeDragDest *drag_dest,
-					   GtkTreePath *dest_path,
-					   GtkSelectionData *selection_data)
-{
-	/* See if we are dropping to ourselves */
-	if (selection_data->target == gdk_atom_intern_static_string (BRASERO_DND_TARGET_SELF_FILE_NODES)) {
-		BraseroDNDDataContext *context;
-		GtkTreePath *dest_parent;
-		BraseroFileNode *parent;
-		GList *iter;
-
-		context = (BraseroDNDDataContext *) selection_data->data;
-		if (context->model != GTK_TREE_MODEL (drag_dest))
-			return FALSE;
-
-		/* make sure the parent is a directory.
-		 * NOTE: in this case dest_path is the exact path where it
-		 * should be inserted. */
-		dest_parent = gtk_tree_path_copy (dest_path);
-		gtk_tree_path_up (dest_parent);
-
-		parent = brasero_data_tree_model_path_to_node (BRASERO_DATA_TREE_MODEL (drag_dest), dest_parent);
-
-		if (!parent) {
-			/* See if that isn't a BOGUS row; if so, try with parent */
-			gtk_tree_path_up (dest_parent);
-			parent = brasero_data_tree_model_path_to_node (BRASERO_DATA_TREE_MODEL (drag_dest), dest_parent);
-
-			if (!parent) {
-				gtk_tree_path_free (dest_parent);
-				return FALSE;
-			}
-		}
-		else if (parent->is_file) {
-			/* if that's a file try with parent */
-			gtk_tree_path_up (dest_parent);
-			parent = parent->parent;
-		}
-
-		if (parent->is_loading) {
-			gtk_tree_path_free (dest_parent);
-			return FALSE;
-		}
-
-		for (iter = context->references; iter; iter = iter->next) {
-			GtkTreePath *src_path;
-			GtkTreeRowReference *reference;
-
-			reference = iter->data;
-			src_path = gtk_tree_row_reference_get_path (reference);
-
-			/* see if we are not moving a parent to one of its children */
-			if (gtk_tree_path_is_ancestor (src_path, dest_path)) {
-				gtk_tree_path_free (src_path);
-				continue;
-			}
-
-			if (gtk_tree_path_up (src_path)) {
-				/* check that node was moved to another directory */
-				if (!parent->parent) {
-					if (gtk_tree_path_get_depth (src_path)) {
-						gtk_tree_path_free (src_path);
-						gtk_tree_path_free (dest_parent);
-						return TRUE;
-					}
-				}
-				else if (!gtk_tree_path_get_depth (src_path)
-				     ||   gtk_tree_path_compare (src_path, dest_parent)) {
-					gtk_tree_path_free (src_path);
-					gtk_tree_path_free (dest_parent);
-					return TRUE;
-				}
-			}
-
-			gtk_tree_path_free (src_path);
-		}
-
-		gtk_tree_path_free (dest_parent);
-		return FALSE;
-	}
-	else if (selection_data->target == gdk_atom_intern_static_string ("text/uri-list"))
-		return TRUE;
-
-	return FALSE;
-}
-
-static gboolean
-brasero_data_tree_model_drag_data_delete (GtkTreeDragSource *source,
-					  GtkTreePath *treepath)
-{
-	return TRUE;
-}
-
-/**
- * Sorting part
- */
-static gboolean
-brasero_data_tree_model_get_sort_column_id (GtkTreeSortable *sortable,
-					    gint *column,
-					    GtkSortType *type)
-{
-	BraseroDataTreeModelPrivate *priv;
-
-	priv = BRASERO_DATA_TREE_MODEL_PRIVATE (sortable);
-
-	if (column)
-		*column = priv->sort_column;
-
-	if (type)
-		*type = priv->sort_type;
-
-	return TRUE;
-}
-
-static void
-brasero_data_tree_model_set_sort_column_id (GtkTreeSortable *sortable,
-					    gint column,
-					    GtkSortType type)
-{
-	BraseroDataTreeModelPrivate *priv;
-
-	priv = BRASERO_DATA_TREE_MODEL_PRIVATE (sortable);
-	priv->sort_column = column;
-	priv->sort_type = type;
-
-	switch (column) {
-	case BRASERO_DATA_TREE_MODEL_NAME:
-		brasero_data_project_set_sort_function (BRASERO_DATA_PROJECT (sortable),
-							type,
-							brasero_file_node_sort_name_cb);
-		break;
-	case BRASERO_DATA_TREE_MODEL_SIZE:
-		brasero_data_project_set_sort_function (BRASERO_DATA_PROJECT (sortable),
-							type,
-							brasero_file_node_sort_size_cb);
-		break;
-	case BRASERO_DATA_TREE_MODEL_MIME_DESC:
-		brasero_data_project_set_sort_function (BRASERO_DATA_PROJECT (sortable),
-							type,
-							brasero_file_node_sort_mime_cb);
-		break;
-	default:
-		brasero_data_project_set_sort_function (BRASERO_DATA_PROJECT (sortable),
-							type,
-							brasero_file_node_sort_default_cb);
-		break;
-	}
-
-	gtk_tree_sortable_sort_column_changed (sortable);
-}
-
-static gboolean
-brasero_data_tree_model_has_default_sort_func (GtkTreeSortable *sortable)
-{
-	/* That's always true since we sort files and directories */
-	return TRUE;
-}
-
-static void
-brasero_data_tree_model_clear (BraseroDataTreeModel *self, 
-			       guint num_nodes)
-{
-	guint i;
-	GtkTreePath *treepath;
-	BraseroDataTreeModelPrivate *priv;
-
-	priv = BRASERO_DATA_TREE_MODEL_PRIVATE (self);
-	if (priv->shown) {
-		g_slist_free (priv->shown);
-		priv->shown = NULL;
-	}
-
-	/* NOTE: no need to move to the next row since previous one was deleted */
-	treepath = gtk_tree_path_new_first ();
-	for (i = 0; i < num_nodes; i ++)
-		gtk_tree_model_row_deleted (GTK_TREE_MODEL (self), treepath);
-
-	gtk_tree_path_free (treepath);
-}
-
-static void
-brasero_data_tree_model_reset (BraseroDataProject *project,
-			       guint num_nodes)
-{
-	brasero_data_tree_model_clear (BRASERO_DATA_TREE_MODEL (project), num_nodes);
+enum {
+	ROW_ADDED,
+	ROW_REMOVED,
+	ROW_CHANGED,
+	ROWS_REORDERED,
+	LAST_SIGNAL
+};
 
-	/* chain up this function except if we invalidated the node */
-	if (BRASERO_DATA_PROJECT_CLASS (brasero_data_tree_model_parent_class)->reset)
-		BRASERO_DATA_PROJECT_CLASS (brasero_data_tree_model_parent_class)->reset (project, num_nodes);
-}
+static guint brasero_data_tree_model_signals [LAST_SIGNAL] = {0};
 
 static gboolean
 brasero_data_tree_model_node_added (BraseroDataProject *project,
 				    BraseroFileNode *node,
 				    const gchar *uri)
 {
-	BraseroDataTreeModelPrivate *priv;
-	BraseroFileNode *parent;
-	GtkTreePath *path;
-	GtkTreeIter iter;
-
 	/* see if we really need to tell the treeview we changed */
 	if (node->parent
 	&& !node->parent->is_root
 	&& !node->parent->is_visible)
 		goto end;
 
-	priv = BRASERO_DATA_TREE_MODEL_PRIVATE (project);
-
-	iter.stamp = priv->stamp;
-	iter.user_data = node;
-	iter.user_data2 = GINT_TO_POINTER (BRASERO_ROW_REGULAR);
-
-	path = brasero_data_tree_model_node_to_path (BRASERO_DATA_TREE_MODEL (project), node);
-
-	/* if the node is reloading (because of a file system change or because
-	 * it was a node that was a tmp folder) then no need to signal an added
-	 * signal but a changed one */
-	if (node->is_reloading) {
-		gtk_tree_model_row_changed (GTK_TREE_MODEL (project), path, &iter);
-		gtk_tree_path_free (path);
-		goto end;
-	}
-
-	/* Add the row itself */
-	/* This is a workaround for a warning in gailtreeview.c line 2946 where
-	 * gail uses the GtkTreePath and not a copy which if the node inserted
-	 * declares to have children and is not expanded leads to the path being
-	 * upped and therefore wrong. */
-	node->is_inserting = 1;
-	gtk_tree_model_row_inserted (GTK_TREE_MODEL (project),
-				     path,
-				     &iter);
-	node->is_inserting = 0;
-	gtk_tree_path_free (path);
-
-	parent = node->parent;
-	if (!parent->is_root) {
-		/* Tell the tree that the parent changed (since the number of children
-		 * changed as well). */
-		iter.user_data = parent;
-		path = brasero_data_tree_model_node_to_path (BRASERO_DATA_TREE_MODEL (project), parent);
-
-		gtk_tree_model_row_changed (GTK_TREE_MODEL (project), path, &iter);
-
-		/* 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) {
-			gtk_tree_path_append_index (path, 1);
-			gtk_tree_model_row_deleted (GTK_TREE_MODEL (project), path);
-		}
-
-		gtk_tree_path_free (path);
-	}
-
-	/* Now see if this is a directory which is empty and needs a BOGUS */
-	if (!node->is_file && !node->is_loading) {
-		/* emit child-toggled. Thanks to bogus rows we only need to emit
-		 * this signal once since a directory will always have a child
-		 * in the tree */
-		path = brasero_data_tree_model_node_to_path (BRASERO_DATA_TREE_MODEL (project), node);
-		gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (project), path, &iter);
-		gtk_tree_path_free (path);
-	}
-
-	/* we also have to set the is_visible property as all nodes added to 
-	 * root are always visible but ref_node is not necessarily called on
-	 * these nodes. */
-//	if (parent->is_root)
-//		node->is_visible = TRUE;
+	g_signal_emit (project,
+		       brasero_data_tree_model_signals [ROW_ADDED],
+		       0,
+		       node);
 
 end:
 	/* chain up this function */
@@ -1268,10 +97,6 @@ brasero_data_tree_model_node_removed (BraseroDataProject *project,
 				      guint former_position,
 				      BraseroFileNode *node)
 {
-	BraseroDataTreeModelPrivate *priv;
-	GSList *iter, *next;
-	GtkTreePath *path;
-
 	/* see if we really need to tell the treeview we changed */
 	if (!node->is_visible
 	&&   former_parent
@@ -1279,44 +104,12 @@ brasero_data_tree_model_node_removed (BraseroDataProject *project,
 	&&  !former_parent->is_visible)
 		goto end;
 
-	priv = BRASERO_DATA_TREE_MODEL_PRIVATE (project);
-
-	/* 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) {
-		BraseroFileNode *tmp;
-
-		tmp = iter->data;
-		next = iter->next;
-		if (brasero_file_node_is_ancestor (node, tmp))
-			priv->shown = g_slist_remove (priv->shown, tmp);
-	}
-
-	/* See if the parent of this node still has children. If not we need to
-	 * 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)) {
-		GtkTreeIter iter;
-
-		iter.stamp = priv->stamp;
-		iter.user_data = former_parent;
-		iter.user_data2 = GINT_TO_POINTER (BRASERO_ROW_BOGUS);
-
-		path = brasero_data_tree_model_node_to_path (BRASERO_DATA_TREE_MODEL (project), former_parent);
-		gtk_tree_path_append_index (path, 1);
-
-		gtk_tree_model_row_inserted (GTK_TREE_MODEL (project), path, &iter);
-		gtk_tree_path_free (path);
-	}
-
-	/* remove the node. Do it after adding a possible BOGUS row.
-	 * NOTE since BOGUS row has been added move row. */
-	path = brasero_data_tree_model_node_to_path (BRASERO_DATA_TREE_MODEL (project), former_parent);
-	gtk_tree_path_append_index (path, former_position);
-
-	gtk_tree_model_row_deleted (GTK_TREE_MODEL (project), path);
-	gtk_tree_path_free (path);
+	g_signal_emit (project,
+		       brasero_data_tree_model_signals [ROW_REMOVED],
+		       0,
+		       former_parent,
+		       former_position,
+		       node);
 
 end:
 	/* chain up this function */
@@ -1331,60 +124,16 @@ static void
 brasero_data_tree_model_node_changed (BraseroDataProject *project,
 				      BraseroFileNode *node)
 {
-	BraseroDataTreeModelPrivate *priv;
-	GtkTreePath *path;
-	GtkTreeIter iter;
-
 	/* see if we really need to tell the treeview we changed */
 	if (node->parent
 	&& !node->parent->is_root
 	&& !node->parent->is_visible)
 		goto end;
 
-	priv = BRASERO_DATA_TREE_MODEL_PRIVATE (project);
-
-	/* Get the iter for the node */
-	iter.stamp = priv->stamp;
-	iter.user_data = node;
-	iter.user_data2 = GINT_TO_POINTER (BRASERO_ROW_REGULAR);
-
-	path = brasero_data_tree_model_node_to_path (BRASERO_DATA_TREE_MODEL (project), node);
-	gtk_tree_model_row_changed (GTK_TREE_MODEL (project),
-				    path,
-				    &iter);
-
-	/* Now see if this is a directory which is empty and needs a BOGUS */
-	if (!node->is_file) {
-		/* NOTE: No need to check for the number of children ... */
-
-		/* emit child-toggled. Thanks to bogus rows we only need to emit
-		 * this signal once since a directory will always have a child
-		 * in the tree */
-		gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (project),
-						      path,
-						      &iter);
-
-		/* The problem is that without that, the folder contents on disc
-		 * won't be added to the tree if the node it replaced was
-		 * already visible. */
-		if (node->is_imported
-		&&  node->is_visible
-		&&  node->is_fake)
-			brasero_data_session_load_directory_contents (BRASERO_DATA_SESSION (project),
-								      node,
-								      NULL);
-
-		/* add the row */
-		if (!BRASERO_FILE_NODE_CHILDREN (node))  {
-			iter.user_data2 = GINT_TO_POINTER (BRASERO_ROW_BOGUS);
-			gtk_tree_path_append_index (path, 0);
-
-			gtk_tree_model_row_inserted (GTK_TREE_MODEL (project),
-						     path,
-						     &iter);
-		}
-	}
-	gtk_tree_path_free (path);
+	g_signal_emit (project,
+		       brasero_data_tree_model_signals [ROW_ADDED],
+		       0,
+		       node);
 
 end:
 	/* chain up this function */
@@ -1397,36 +146,16 @@ brasero_data_tree_model_node_reordered (BraseroDataProject *project,
 					BraseroFileNode *parent,
 					gint *new_order)
 {
-	GtkTreePath *treepath;
-	BraseroDataTreeModelPrivate *priv;
-
 	/* see if we really need to tell the treeview we changed */
 	if (!parent->is_root
 	&&  !parent->is_visible)
 		goto end;
 
-	priv = BRASERO_DATA_TREE_MODEL_PRIVATE (project);
-
-	treepath = brasero_data_tree_model_node_to_path (BRASERO_DATA_TREE_MODEL (project), parent);
-	if (parent != brasero_data_project_get_root (project)) {
-		GtkTreeIter iter;
-
-		iter.stamp = priv->stamp;
-		iter.user_data = parent;
-		iter.user_data2 = GINT_TO_POINTER (BRASERO_ROW_REGULAR);
-
-		gtk_tree_model_rows_reordered (GTK_TREE_MODEL (project),
-					       treepath,
-					       &iter,
-					       new_order);
-	}
-	else
-		gtk_tree_model_rows_reordered (GTK_TREE_MODEL (project),
-					       treepath,
-					       NULL,
-					       new_order);
-
-	gtk_tree_path_free (treepath);
+	g_signal_emit (project,
+		       brasero_data_tree_model_signals [ROW_ADDED],
+		       0,
+		       parent,
+		       new_order);
 
 end:
 	/* chain up this function */
@@ -1435,174 +164,73 @@ end:
 }
 
 static void
-brasero_data_tree_model_activity_changed (BraseroDataVFS *vfs,
-					  gboolean active)
-{
-	GtkTreeIter iter;
-	GSList *nodes;
-	BraseroDataTreeModelPrivate *priv;
-
-	if (brasero_data_vfs_is_active (vfs))
-		return;
-
-	priv = BRASERO_DATA_TREE_MODEL_PRIVATE (vfs);
-
-	iter.stamp = priv->stamp;
-	iter.user_data2 = GINT_TO_POINTER (BRASERO_ROW_REGULAR);
-
-	/* NOTE: we shouldn't need to use reference here as unref_node is used */
-	for (nodes = priv->shown; nodes; nodes = nodes->next) {
-		GtkTreePath *treepath;
-
-		iter.user_data = nodes->data;
-		treepath = brasero_data_tree_model_node_to_path (BRASERO_DATA_TREE_MODEL (vfs), nodes->data);
-
-		gtk_tree_model_row_changed (GTK_TREE_MODEL (vfs), treepath, &iter);
-		gtk_tree_path_free (treepath);
-	}
-
-	/* chain up this function */
-	if (BRASERO_DATA_VFS_CLASS (brasero_data_tree_model_parent_class)->activity_changed)
-		BRASERO_DATA_VFS_CLASS (brasero_data_tree_model_parent_class)->activity_changed (vfs, active);
-}
-
-static void
 brasero_data_tree_model_init (BraseroDataTreeModel *object)
-{
-	BraseroDataTreeModelPrivate *priv;
-
-	priv = BRASERO_DATA_TREE_MODEL_PRIVATE (object);
-
-	priv->sort_column = GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID;
-	do {
-		priv->stamp = g_random_int ();
-	} while (!priv->stamp);
-
-	priv->theme = gtk_icon_theme_get_default ();
-}
+{ }
 
 static void
 brasero_data_tree_model_finalize (GObject *object)
 {
-	BraseroDataTreeModelPrivate *priv;
-
-	priv = BRASERO_DATA_TREE_MODEL_PRIVATE (object);
-
-	if (priv->shown) {
-		g_slist_free (priv->shown);
-		priv->shown = NULL;
-	}
-
 	G_OBJECT_CLASS (brasero_data_tree_model_parent_class)->finalize (object);
 }
 
 static void
-brasero_data_tree_model_iface_init (gpointer g_iface, gpointer data)
-{
-	GtkTreeModelIface *iface = g_iface;
-	static gboolean initialized = FALSE;
-
-	if (initialized)
-		return;
-
-	initialized = TRUE;
-
-	iface->ref_node = brasero_data_tree_model_node_shown;
-	iface->unref_node = brasero_data_tree_model_node_hidden;
-
-	iface->get_flags = brasero_data_tree_model_get_flags;
-	iface->get_n_columns = brasero_data_tree_model_get_n_columns;
-	iface->get_column_type = brasero_data_tree_model_get_column_type;
-	iface->get_iter = brasero_data_tree_model_get_iter;
-	iface->get_path = brasero_data_tree_model_get_path;
-	iface->get_value = brasero_data_tree_model_get_value;
-	iface->iter_next = brasero_data_tree_model_iter_next;
-	iface->iter_children = brasero_data_tree_model_iter_children;
-	iface->iter_has_child = brasero_data_tree_model_iter_has_child;
-	iface->iter_n_children = brasero_data_tree_model_iter_n_children;
-	iface->iter_nth_child = brasero_data_tree_model_iter_nth_child;
-	iface->iter_parent = brasero_data_tree_model_iter_parent;
-}
-
-static void
-brasero_data_tree_model_multi_drag_source_iface_init (gpointer g_iface, gpointer data)
-{
-	EggTreeMultiDragSourceIface *iface = g_iface;
-	static gboolean initialized = FALSE;
-
-	if (initialized)
-		return;
-
-	initialized = TRUE;
-
-	iface->row_draggable = brasero_data_tree_model_multi_row_draggable;
-	iface->drag_data_get = brasero_data_tree_model_multi_drag_data_get;
-	iface->drag_data_delete = brasero_data_tree_model_multi_drag_data_delete;
-}
-
-static void
-brasero_data_tree_model_drag_source_iface_init (gpointer g_iface, gpointer data)
-{
-	GtkTreeDragSourceIface *iface = g_iface;
-	static gboolean initialized = FALSE;
-
-	if (initialized)
-		return;
-
-	initialized = TRUE;
-
-	iface->drag_data_delete = brasero_data_tree_model_drag_data_delete;
-}
-
-static void
-brasero_data_tree_model_drag_dest_iface_init (gpointer g_iface, gpointer data)
-{
-	GtkTreeDragDestIface *iface = g_iface;
-	static gboolean initialized = FALSE;
-
-	if (initialized)
-		return;
-
-	initialized = TRUE;
-
-	iface->drag_data_received = brasero_data_tree_model_drag_data_received;
-	iface->row_drop_possible = brasero_data_tree_model_row_drop_possible;
-}
-
-static void
-brasero_data_tree_model_sortable_iface_init (gpointer g_iface, gpointer data)
-{
-	GtkTreeSortableIface *iface = g_iface;
-	static gboolean initialized = FALSE;
-
-	if (initialized)
-		return;
-
-	initialized = TRUE;
-
-	iface->get_sort_column_id = brasero_data_tree_model_get_sort_column_id;
-	iface->set_sort_column_id = brasero_data_tree_model_set_sort_column_id;
-	iface->has_default_sort_func = brasero_data_tree_model_has_default_sort_func;
-}
-
-static void
 brasero_data_tree_model_class_init (BraseroDataTreeModelClass *klass)
 {
 	GObjectClass* object_class = G_OBJECT_CLASS (klass);
-	BraseroDataVFSClass *vfs_class = BRASERO_DATA_VFS_CLASS (klass);
 	BraseroDataProjectClass *data_project_class = BRASERO_DATA_PROJECT_CLASS (klass);
 
 	g_type_class_add_private (klass, sizeof (BraseroDataTreeModelPrivate));
 
 	object_class->finalize = brasero_data_tree_model_finalize;
 
-	vfs_class->activity_changed = brasero_data_tree_model_activity_changed;
-
-	data_project_class->reset = brasero_data_tree_model_reset;
 	data_project_class->node_added = brasero_data_tree_model_node_added;
 	data_project_class->node_removed = brasero_data_tree_model_node_removed;
 	data_project_class->node_changed = brasero_data_tree_model_node_changed;
 	data_project_class->node_reordered = brasero_data_tree_model_node_reordered;
+
+	brasero_data_tree_model_signals [ROW_ADDED] = 
+	    g_signal_new ("row_added",
+			  G_TYPE_FROM_CLASS (klass),
+			  G_SIGNAL_RUN_LAST|G_SIGNAL_NO_RECURSE,
+			  0,
+			  NULL, NULL,
+			  g_cclosure_marshal_VOID__POINTER,
+			  G_TYPE_NONE,
+			  1,
+			  G_TYPE_POINTER);
+	brasero_data_tree_model_signals [ROW_REMOVED] = 
+	    g_signal_new ("row_removed",
+			  G_TYPE_FROM_CLASS (klass),
+			  G_SIGNAL_RUN_LAST|G_SIGNAL_NO_RECURSE,
+			  0,
+			  NULL, NULL,
+			  brasero_marshal_VOID__POINTER_UINT_POINTER,
+			  G_TYPE_NONE,
+			  3,
+			  G_TYPE_POINTER,
+			  G_TYPE_UINT,
+			  G_TYPE_POINTER);
+	brasero_data_tree_model_signals [ROW_CHANGED] = 
+	    g_signal_new ("row_changed",
+			  G_TYPE_FROM_CLASS (klass),
+			  G_SIGNAL_RUN_LAST|G_SIGNAL_NO_RECURSE,
+			  0,
+			  NULL, NULL,
+			  g_cclosure_marshal_VOID__POINTER,
+			  G_TYPE_NONE,
+			  1,
+			  G_TYPE_POINTER);
+	brasero_data_tree_model_signals [ROWS_REORDERED] = 
+	    g_signal_new ("rows_reordered",
+			  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);
 }
 
 BraseroDataTreeModel *
diff --git a/libbrasero-burn/brasero-data-tree-model.h b/libbrasero-burn/brasero-data-tree-model.h
index 9ef5edf..9f25467 100644
--- a/libbrasero-burn/brasero-data-tree-model.h
+++ b/libbrasero-burn/brasero-data-tree-model.h
@@ -1,20 +1,28 @@
 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
 /*
- * brasero
- * Copyright (C) Philippe Rouquier 2007-2008 <bonfire-app wanadoo fr>
+ * Libbrasero-burn
+ * Copyright (C) Philippe Rouquier 2005-2009 <bonfire-app wanadoo fr>
+ *
+ * Libbrasero-burn is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The Libbrasero-burn authors hereby grant permission for non-GPL compatible
+ * GStreamer plugins to be used and distributed together with GStreamer
+ * and Libbrasero-burn. This permission is above and beyond the permissions granted
+ * by the GPL license by which Libbrasero-burn is covered. If you modify this code
+ * you may extend this exception to your version of the code, but you are not
+ * obligated to do so. If you do not wish to do so, delete this exception
+ * statement from your version.
  * 
- *  Brasero is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- * 
- * brasero is distributed in the hope that it will be useful,
+ * Libbrasero-burn is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Library General Public License for more details.
  * 
  * You should have received a copy of the GNU General Public License
- * along with brasero.  If not, write to:
+ * along with this program; if not, write to:
  * 	The Free Software Foundation, Inc.,
  * 	51 Franklin Street, Fifth Floor
  * 	Boston, MA  02110-1301, USA.
@@ -30,28 +38,6 @@
 
 G_BEGIN_DECLS
 
-/* This DND target when moving nodes inside ourselves */
-#define BRASERO_DND_TARGET_SELF_FILE_NODES	"GTK_TREE_MODEL_ROW"
-
-struct _BraseroDNDDataContext {
-	GtkTreeModel *model;
-	GList *references;
-};
-typedef struct _BraseroDNDDataContext BraseroDNDDataContext;
-
-typedef enum {
-	BRASERO_DATA_TREE_MODEL_NAME		= 0,
-	BRASERO_DATA_TREE_MODEL_MIME_DESC,
-	BRASERO_DATA_TREE_MODEL_MIME_ICON,
-	BRASERO_DATA_TREE_MODEL_SIZE,
-	BRASERO_DATA_TREE_MODEL_SHOW_PERCENT,
-	BRASERO_DATA_TREE_MODEL_PERCENT,
-	BRASERO_DATA_TREE_MODEL_STYLE,
-	BRASERO_DATA_TREE_MODEL_COLOR,
-	BRASERO_DATA_TREE_MODEL_EDITABLE,
-	BRASERO_DATA_TREE_MODEL_COL_NUM
-} BraseroDataProjectColumn;
-
 #define BRASERO_TYPE_DATA_TREE_MODEL             (brasero_data_tree_model_get_type ())
 #define BRASERO_DATA_TREE_MODEL(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), BRASERO_TYPE_DATA_TREE_MODEL, BraseroDataTreeModel))
 #define BRASERO_DATA_TREE_MODEL_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), BRASERO_TYPE_DATA_TREE_MODEL, BraseroDataTreeModelClass))
@@ -70,6 +56,19 @@ struct _BraseroDataTreeModelClass
 struct _BraseroDataTreeModel
 {
 	BraseroDataVFS parent_instance;
+
+	/* Signals */
+	void		(*row_added)		(BraseroDataTreeModel *model,
+						 BraseroFileNode *node);
+	void		(*row_changed)		(BraseroDataTreeModel *model,
+						 BraseroFileNode *node);
+	void		(*row_removed)		(BraseroDataTreeModel *model,
+						 BraseroFileNode *former_parent,
+						 guint former_position,
+						 BraseroFileNode *node);
+	void		(*rows_reordered)	(BraseroDataTreeModel *model,
+						 BraseroFileNode *parent,
+						 guint *new_order);
 };
 
 GType brasero_data_tree_model_get_type (void) G_GNUC_CONST;
@@ -77,13 +76,6 @@ GType brasero_data_tree_model_get_type (void) G_GNUC_CONST;
 BraseroDataTreeModel *
 brasero_data_tree_model_new (void);
 
-BraseroFileNode *
-brasero_data_tree_model_path_to_node (BraseroDataTreeModel *self,
-				      GtkTreePath *path);
-GtkTreePath *
-brasero_data_tree_model_node_to_path (BraseroDataTreeModel *self,
-				      BraseroFileNode *node);
-
 G_END_DECLS
 
 #endif /* _BRASERO_DATA_TREE_MODEL_H_ */
diff --git a/libbrasero-burn/brasero-data-vfs.c b/libbrasero-burn/brasero-data-vfs.c
index de509fc..3460fc3 100644
--- a/libbrasero-burn/brasero-data-vfs.c
+++ b/libbrasero-burn/brasero-data-vfs.c
@@ -1,20 +1,28 @@
 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
 /*
- * brasero
- * Copyright (C) Philippe Rouquier 2007-2008 <bonfire-app wanadoo fr>
+ * Libbrasero-burn
+ * Copyright (C) Philippe Rouquier 2005-2009 <bonfire-app wanadoo fr>
+ *
+ * Libbrasero-burn is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The Libbrasero-burn authors hereby grant permission for non-GPL compatible
+ * GStreamer plugins to be used and distributed together with GStreamer
+ * and Libbrasero-burn. This permission is above and beyond the permissions granted
+ * by the GPL license by which Libbrasero-burn is covered. If you modify this code
+ * you may extend this exception to your version of the code, but you are not
+ * obligated to do so. If you do not wish to do so, delete this exception
+ * statement from your version.
  * 
- *  Brasero is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- * 
- * brasero is distributed in the hope that it will be useful,
+ * Libbrasero-burn is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Library General Public License for more details.
  * 
  * You should have received a copy of the GNU General Public License
- * along with brasero.  If not, write to:
+ * along with this program; if not, write to:
  * 	The Free Software Foundation, Inc.,
  * 	51 Franklin Street, Fifth Floor
  * 	Boston, MA  02110-1301, USA.
@@ -37,6 +45,8 @@
 #include "brasero-data-project.h"
 #include "brasero-file-node.h"
 #include "brasero-io.h"
+#include "brasero-filtered-uri.h"
+
 #include "libbrasero-marshal.h"
 
 #include "burn-debug.h"
@@ -51,9 +61,7 @@ struct _BraseroDataVFSPrivate
 	GHashTable *loading;
 	GHashTable *directories;
 
-	/* This keeps a record of all URIs that have been restored by
-	 * the user despite the filtering rules. */
-	GHashTable *filtered;
+	BraseroFilteredUri *filtered;
 
 	BraseroIO *io;
 	BraseroIOJobBase *load_uri;
@@ -70,7 +78,6 @@ enum {
 	UNREADABLE_SIGNAL,
 	RECURSIVE_SIGNAL,
 	IMAGE_SIGNAL,
-	FILTERED_SIGNAL,
 	ACTIVITY_SIGNAL,
 	UNKNOWN_SIGNAL,
 	LAST_SIGNAL
@@ -78,82 +85,17 @@ enum {
 
 static gulong brasero_data_vfs_signals [LAST_SIGNAL] = { 0 };
 
-typedef enum {
-	BRASERO_DATA_VFS_NONE		= 0,
-	BRASERO_DATA_VFS_RESTORED,
-	BRASERO_DATA_VFS_FILTERED
-} BraseroDataVFSFilterStatus;
 
 G_DEFINE_TYPE (BraseroDataVFS, brasero_data_vfs, BRASERO_TYPE_DATA_SESSION);
 
-static void
-brasero_data_vfs_restored_list_cb (gpointer key,
-				   gpointer data,
-				   gpointer callback_data)
-{
-	GSList **list = callback_data;
-
-	if (GPOINTER_TO_INT (data) == BRASERO_DATA_VFS_RESTORED)
-		*list = g_slist_prepend (*list, g_strdup (key));
-}
-
-gboolean
-brasero_data_vfs_get_restored (BraseroDataVFS *self,
-			       GSList **restored)
+BraseroFilteredUri *
+brasero_data_vfs_get_filtered_model (BraseroDataVFS *vfs)
 {
 	BraseroDataVFSPrivate *priv;
 
-	priv = BRASERO_DATA_VFS_PRIVATE (self);
+	priv = BRASERO_DATA_VFS_PRIVATE (vfs);
 
-	*restored = NULL;
-	g_hash_table_foreach (priv->filtered,
-			      brasero_data_vfs_restored_list_cb,
-			      restored);
-	return TRUE;
-}
-
-void
-brasero_data_vfs_add_restored (BraseroDataVFS *self,
-			       const gchar *restored)
-{
-	BraseroDataVFSPrivate *priv;
-	guint value;
-
-	priv = BRASERO_DATA_VFS_PRIVATE (self);
-
-	value = GPOINTER_TO_INT (g_hash_table_lookup (priv->filtered, restored));
-	if (value) {
-		if (GPOINTER_TO_INT (value) != BRASERO_DATA_VFS_RESTORED)
-			g_hash_table_insert (priv->filtered,
-					     (gchar *) restored,
-					     GINT_TO_POINTER (BRASERO_DATA_VFS_RESTORED));
-	}
-	else
-		g_hash_table_insert (priv->filtered,
-				     (gchar *) brasero_utils_register_string (restored),
-				     GINT_TO_POINTER (BRASERO_DATA_VFS_RESTORED));
-}
-
-void
-brasero_data_vfs_remove_restored (BraseroDataVFS *self,
-				  const gchar *restored)
-{
-	BraseroDataVFSPrivate *priv;
-	guint value;
-
-	priv = BRASERO_DATA_VFS_PRIVATE (self);
-
-	value = GPOINTER_TO_INT (g_hash_table_lookup (priv->filtered, restored));
-	if (value) {
-		if (GPOINTER_TO_INT (value) != BRASERO_DATA_VFS_FILTERED)
-			g_hash_table_insert (priv->filtered,
-					     (gchar *) restored,
-					     GINT_TO_POINTER (BRASERO_DATA_VFS_FILTERED));
-	}
-	else
-		g_hash_table_insert (priv->filtered,
-				     (gchar *) brasero_utils_register_string (restored),
-				     GINT_TO_POINTER (BRASERO_DATA_VFS_FILTERED));
+	return priv->filtered;
 }
 
 gboolean
@@ -437,60 +379,25 @@ brasero_data_vfs_directory_load_result (GObject *owner,
 	/* See if it's a broken symlink */
 	if (g_file_info_get_is_symlink (info)
 	&& !g_file_info_get_symlink_target (info)) {
-		BraseroDataVFSFilterStatus status;
-
-		/* See if this file is already in filtered */
-		status = GPOINTER_TO_INT (g_hash_table_lookup (priv->filtered, uri));
-		if (status == BRASERO_DATA_VFS_NONE) {
-			uri = brasero_utils_register_string (uri);
-			g_hash_table_insert (priv->filtered,
-					     (gchar *) uri,
-					     GINT_TO_POINTER (BRASERO_DATA_VFS_FILTERED));
-		}
-
-		/* See if we are supposed to keep them */
-		if (status != BRASERO_DATA_VFS_RESTORED && priv->filter_broken_sym) {
-			brasero_data_project_exclude_uri (BRASERO_DATA_PROJECT (self),
-							  uri);
-
-			if (status == BRASERO_DATA_VFS_NONE) {
-				/* Advertise only once this filtered URI */
-				g_signal_emit (self,
-					       brasero_data_vfs_signals [FILTERED_SIGNAL],
-					       0,
-					       BRASERO_FILTER_BROKEN_SYM,
-					       uri);
-			}
-
+		/* See if this file is already in restored or if we should filter */
+		if (priv->filter_broken_sym
+		&& !brasero_filtered_uri_lookup_restored (priv->filtered, uri)) {
+			brasero_filtered_uri_filter (priv->filtered,
+						     uri,
+						     BRASERO_FILTER_BROKEN_SYM);
+			brasero_data_project_exclude_uri (BRASERO_DATA_PROJECT (self), uri);
 			return;
 		}
 	}
-
 	/* A new hidden file ? */
 	else if (name [0] == '.') {
-		BraseroDataVFSFilterStatus status;
-
-		/* See if this file is already in restored */
-		status = GPOINTER_TO_INT (g_hash_table_lookup (priv->filtered, uri));
-		if (status == BRASERO_DATA_VFS_NONE) {
-			uri = brasero_utils_register_string (uri);
-			g_hash_table_insert (priv->filtered,
-					     (gchar *) uri,
-					     GINT_TO_POINTER (BRASERO_DATA_VFS_FILTERED));
-		}
-
-		/* See if we are supposed to keep them */
-		if (status != BRASERO_DATA_VFS_RESTORED && priv->filter_hidden) {
+		/* See if this file is already in restored or if we should filter */
+		if (priv->filter_hidden
+		&& !brasero_filtered_uri_lookup_restored (priv->filtered, uri)) {
+			brasero_filtered_uri_filter (priv->filtered,
+						     uri,
+						     BRASERO_FILTER_HIDDEN);
 			brasero_data_project_exclude_uri (BRASERO_DATA_PROJECT (self), uri);
-			if (status == BRASERO_DATA_VFS_NONE) {
-				/* Advertise only once this filtered URI */
-				g_signal_emit (self,
-					       brasero_data_vfs_signals [FILTERED_SIGNAL],
-					       0,
-					       BRASERO_FILTER_HIDDEN,
-					       uri);
-			}
-
 			return;
 		}
 	}
@@ -1062,15 +969,6 @@ brasero_data_vfs_empty_loading_cb (gpointer key,
 	return TRUE;
 }
 
-static gboolean
-brasero_data_vfs_empty_filtered_cb (gpointer key,
-				    gpointer data,
-				    gpointer callback_data)
-{
-	brasero_utils_unregister_string (key);
-	return TRUE;
-}
-
 static void
 brasero_data_vfs_clear (BraseroDataVFS *self)
 {
@@ -1097,32 +995,8 @@ brasero_data_vfs_clear (BraseroDataVFS *self)
 	g_hash_table_foreach_remove (priv->directories,
 				     brasero_data_vfs_empty_loading_cb,
 				     self);
-	g_hash_table_foreach_remove (priv->filtered,
-				     brasero_data_vfs_empty_filtered_cb,
-				     self);
-}
 
-static gboolean
-brasero_data_vfs_remove_filtered_uris (gpointer key,
-				       gpointer value,
-				       gpointer callback_data)
-{
-	guint len;
-	gchar *key_uri = key;
-	gchar *uri = callback_data;
-
-	/* always keep restored */
-	if (GPOINTER_TO_INT (value) == BRASERO_DATA_VFS_RESTORED)
-		return FALSE;
-
-	len = strlen (uri);
-	if (!strncmp (uri, key, len)
-	&&   key_uri [len] == G_DIR_SEPARATOR) {
-		brasero_utils_unregister_string (key);
-		return TRUE;
-	}
-
-	return FALSE;
+	brasero_filtered_uri_clear (priv->filtered);
 }
 
 static void
@@ -1136,14 +1010,7 @@ brasero_data_vfs_uri_removed (BraseroDataProject *project,
 	/* That happens when a graft is removed from the tree, that is when this
 	 * graft uri doesn't appear anywhere and when it hasn't got any more 
 	 * parent uri grafted. */
-	g_hash_table_foreach_remove (priv->filtered,
-				     brasero_data_vfs_remove_filtered_uris,
-				     (gpointer) uri);
-	g_signal_emit (project,
-		       brasero_data_vfs_signals [FILTERED_SIGNAL],
-		       0,
-		       BRASERO_FILTER_NONE,
-		       uri);
+	brasero_filtered_uri_remove_with_children (priv->filtered, uri);
 }
 
 static void
@@ -1219,6 +1086,8 @@ brasero_data_vfs_init (BraseroDataVFS *object)
 
 	priv = BRASERO_DATA_VFS_PRIVATE (object);
 
+	priv->filtered = brasero_filtered_uri_new ();
+
 	/* load the fitering rules */
 	client = gconf_client_get_default ();
 	priv->replace_sym = gconf_client_get_bool (client,
@@ -1254,7 +1123,6 @@ brasero_data_vfs_init (BraseroDataVFS *object)
 	/* create the hash tables */
 	priv->loading = g_hash_table_new (g_str_hash, g_str_equal);
 	priv->directories = g_hash_table_new (g_str_hash, g_str_equal);
-	priv->filtered = g_hash_table_new (g_str_hash, g_str_equal);
 
 	/* get the vfs object */
 	priv->io = brasero_io_get_default ();
@@ -1280,7 +1148,7 @@ brasero_data_vfs_finalize (GObject *object)
 	}
 
 	if (priv->filtered) {
-		g_hash_table_destroy (priv->filtered);
+		g_object_unref (priv->filtered);
 		priv->filtered = NULL;
 	}
 
@@ -1333,18 +1201,6 @@ brasero_data_vfs_class_init (BraseroDataVFSClass *klass)
 			  1,
 			  G_TYPE_STRING);
 
-	brasero_data_vfs_signals [FILTERED_SIGNAL] = 
-	    g_signal_new ("filtered_uri",
-			  G_TYPE_FROM_CLASS (klass),
-			  G_SIGNAL_RUN_FIRST,
-			  0,
-			  NULL, NULL,
-			  brasero_marshal_VOID__INT_STRING,
-			  G_TYPE_NONE,
-			  2,
-			  G_TYPE_INT,
-			  G_TYPE_STRING);
-
 	brasero_data_vfs_signals [UNREADABLE_SIGNAL] = 
 	    g_signal_new ("unreadable_uri",
 			  G_TYPE_FROM_CLASS (klass),
diff --git a/libbrasero-burn/brasero-data-vfs.h b/libbrasero-burn/brasero-data-vfs.h
index 0d70731..1926986 100644
--- a/libbrasero-burn/brasero-data-vfs.h
+++ b/libbrasero-burn/brasero-data-vfs.h
@@ -1,20 +1,28 @@
 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
 /*
- * brasero
- * Copyright (C) Philippe Rouquier 2007-2008 <bonfire-app wanadoo fr>
+ * Libbrasero-burn
+ * Copyright (C) Philippe Rouquier 2005-2009 <bonfire-app wanadoo fr>
+ *
+ * Libbrasero-burn is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The Libbrasero-burn authors hereby grant permission for non-GPL compatible
+ * GStreamer plugins to be used and distributed together with GStreamer
+ * and Libbrasero-burn. This permission is above and beyond the permissions granted
+ * by the GPL license by which Libbrasero-burn is covered. If you modify this code
+ * you may extend this exception to your version of the code, but you are not
+ * obligated to do so. If you do not wish to do so, delete this exception
+ * statement from your version.
  * 
- *  Brasero is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- * 
- * brasero is distributed in the hope that it will be useful,
+ * Libbrasero-burn is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Library General Public License for more details.
  * 
  * You should have received a copy of the GNU General Public License
- * along with brasero.  If not, write to:
+ * along with this program; if not, write to:
  * 	The Free Software Foundation, Inc.,
  * 	51 Franklin Street, Fifth Floor
  * 	Boston, MA  02110-1301, USA.
@@ -24,8 +32,10 @@
 #define _BRASERO_DATA_VFS_H_
 
 #include <glib-object.h>
+#include <gtk/gtk.h>
 
 #include "brasero-data-session.h"
+#include "brasero-filtered-uri.h"
 
 G_BEGIN_DECLS
 
@@ -33,15 +43,6 @@ G_BEGIN_DECLS
 #define BRASERO_FILTER_BROKEN_SYM_KEY		"/apps/brasero/filter/broken_sym"
 #define BRASERO_REPLACE_SYMLINK_KEY		"/apps/brasero/filter/replace_sym"
 
-typedef enum {
-	/* Following means it has been removed */
-	BRASERO_FILTER_NONE			= 0,
-	BRASERO_FILTER_HIDDEN			= 1,
-	BRASERO_FILTER_UNREADABLE,
-	BRASERO_FILTER_BROKEN_SYM,
-	BRASERO_FILTER_RECURSIVE_SYM,
-	BRASERO_FILTER_UNKNOWN
-} BraseroFilterStatus;
 
 #define BRASERO_TYPE_DATA_VFS             (brasero_data_vfs_get_type ())
 #define BRASERO_DATA_VFS(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), BRASERO_TYPE_DATA_VFS, BraseroDataVFS))
@@ -75,16 +76,6 @@ gboolean
 brasero_data_vfs_is_loading_uri (BraseroDataVFS *vfs);
 
 gboolean
-brasero_data_vfs_get_restored (BraseroDataVFS *vfs,
-			       GSList **restored);
-void
-brasero_data_vfs_add_restored (BraseroDataVFS *vfs,
-			       const gchar *restored);
-void
-brasero_data_vfs_remove_restored (BraseroDataVFS *vfs,
-				  const gchar *restored);
-
-gboolean
 brasero_data_vfs_load_mime (BraseroDataVFS *vfs,
 			    BraseroFileNode *node);
 
@@ -96,6 +87,9 @@ gboolean
 brasero_data_vfs_require_directory_contents (BraseroDataVFS *vfs,
 					     BraseroFileNode *node);
 
+BraseroFilteredUri *
+brasero_data_vfs_get_filtered_model (BraseroDataVFS *vfs);
+
 G_END_DECLS
 
 #endif /* _BRASERO_DATA_VFS_H_ */
diff --git a/libbrasero-burn/brasero-file-monitor.c b/libbrasero-burn/brasero-file-monitor.c
index c5f2ebf..97d77cc 100644
--- a/libbrasero-burn/brasero-file-monitor.c
+++ b/libbrasero-burn/brasero-file-monitor.c
@@ -1,20 +1,28 @@
 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
 /*
- * brasero
- * Copyright (C) Philippe Rouquier 2007-2008 <bonfire-app wanadoo fr>
+ * Libbrasero-burn
+ * Copyright (C) Philippe Rouquier 2005-2009 <bonfire-app wanadoo fr>
+ *
+ * Libbrasero-burn is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The Libbrasero-burn authors hereby grant permission for non-GPL compatible
+ * GStreamer plugins to be used and distributed together with GStreamer
+ * and Libbrasero-burn. This permission is above and beyond the permissions granted
+ * by the GPL license by which Libbrasero-burn is covered. If you modify this code
+ * you may extend this exception to your version of the code, but you are not
+ * obligated to do so. If you do not wish to do so, delete this exception
+ * statement from your version.
  * 
- *  Brasero is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- * 
- * brasero is distributed in the hope that it will be useful,
+ * Libbrasero-burn is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Library General Public License for more details.
  * 
  * You should have received a copy of the GNU General Public License
- * along with brasero.  If not, write to:
+ * along with this program; if not, write to:
  * 	The Free Software Foundation, Inc.,
  * 	51 Franklin Street, Fifth Floor
  * 	Boston, MA  02110-1301, USA.
diff --git a/libbrasero-burn/brasero-file-monitor.h b/libbrasero-burn/brasero-file-monitor.h
index 4fbc1af..b194a37 100644
--- a/libbrasero-burn/brasero-file-monitor.h
+++ b/libbrasero-burn/brasero-file-monitor.h
@@ -1,20 +1,28 @@
 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
 /*
- * brasero
- * Copyright (C) Philippe Rouquier 2007-2008 <bonfire-app wanadoo fr>
+ * Libbrasero-burn
+ * Copyright (C) Philippe Rouquier 2005-2009 <bonfire-app wanadoo fr>
+ *
+ * Libbrasero-burn is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The Libbrasero-burn authors hereby grant permission for non-GPL compatible
+ * GStreamer plugins to be used and distributed together with GStreamer
+ * and Libbrasero-burn. This permission is above and beyond the permissions granted
+ * by the GPL license by which Libbrasero-burn is covered. If you modify this code
+ * you may extend this exception to your version of the code, but you are not
+ * obligated to do so. If you do not wish to do so, delete this exception
+ * statement from your version.
  * 
- *  Brasero is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- * 
- * brasero is distributed in the hope that it will be useful,
+ * Libbrasero-burn is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Library General Public License for more details.
  * 
  * You should have received a copy of the GNU General Public License
- * along with brasero.  If not, write to:
+ * along with this program; if not, write to:
  * 	The Free Software Foundation, Inc.,
  * 	51 Franklin Street, Fifth Floor
  * 	Boston, MA  02110-1301, USA.
diff --git a/libbrasero-burn/brasero-file-node.c b/libbrasero-burn/brasero-file-node.c
index b4eb831..0e91ade 100644
--- a/libbrasero-burn/brasero-file-node.c
+++ b/libbrasero-burn/brasero-file-node.c
@@ -1,26 +1,31 @@
-/***************************************************************************
- *            brasero-file-node.c
- *
- *  Sat Dec  1 14:48:46 2007
- *  Copyright  2007  Philippe Rouquier
- *  <bonfire-app wanadoo fr>
- ****************************************************************************/
-
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
 /*
- * Libbrasero-media is free software; you can redistribute it and/or modify
-fy
+ * Libbrasero-burn
+ * Copyright (C) Philippe Rouquier 2005-2009 <bonfire-app wanadoo fr>
+ *
+ * Libbrasero-burn is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
+ *
+ * The Libbrasero-burn authors hereby grant permission for non-GPL compatible
+ * GStreamer plugins to be used and distributed together with GStreamer
+ * and Libbrasero-burn. This permission is above and beyond the permissions granted
+ * by the GPL license by which Libbrasero-burn is covered. If you modify this code
+ * you may extend this exception to your version of the code, but you are not
+ * obligated to do so. If you do not wish to do so, delete this exception
+ * statement from your version.
  * 
- * Brasero is distributed in the hope that it will be useful,
+ * Libbrasero-burn is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU Library General Public License for more details.
  * 
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor Boston, MA 02110-1301,  USA
+ * along with this program; if not, write to:
+ * 	The Free Software Foundation, Inc.,
+ * 	51 Franklin Street, Fifth Floor
+ * 	Boston, MA  02110-1301, USA.
  */
 
 #ifdef HAVE_CONFIG_H
@@ -586,32 +591,6 @@ brasero_file_node_check_imported_sibling (BraseroFileNode *node)
 	return NULL;
 }
 
-gchar *
-brasero_file_node_validate_utf8_name (const gchar *name)
-{
-	gchar *retval, *ptr;
-	const gchar *invalid;
-
-	if (!name)
-		return NULL;
-
-	if (g_utf8_validate (name, -1, &invalid))
-		return NULL;
-
-	retval = g_strdup (name);
-	ptr = retval + (invalid - name);
-	*ptr = '_';
-	ptr++;
-
-	while (!g_utf8_validate (ptr, -1, &invalid)) {
-		ptr = (gchar*) invalid;
-		*ptr = '?';
-		ptr ++;
-	}
-
-	return retval;
-}
-
 void
 brasero_file_node_graft (BraseroFileNode *file_node,
 			 BraseroURINode *uri_node)
@@ -821,11 +800,12 @@ brasero_file_node_get_uri_name (const gchar *uri)
 	/* NOTE: a graft should be added for non utf8 name since we
 	 * modify them; in fact we use this function only in the next
 	 * one which creates only grafted nodes. */
-	utf8_name = brasero_file_node_validate_utf8_name (name);
+	utf8_name = brasero_utils_get_uri_name (name);
 	if (utf8_name) {
 		g_free (name);
 		return utf8_name;
 	}
+
 	return name;
 }
 
diff --git a/libbrasero-burn/brasero-file-node.h b/libbrasero-burn/brasero-file-node.h
index 4faa4bb..fc216b0 100644
--- a/libbrasero-burn/brasero-file-node.h
+++ b/libbrasero-burn/brasero-file-node.h
@@ -1,26 +1,31 @@
-/***************************************************************************
- *            brasero-file-node.h
- *
- *  Sat Dec  1 14:50:56 2007
- *  Copyright  2007  Philippe Rouquier
- *  <bonfire-app wanadoo fr>
- ****************************************************************************/
-
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
 /*
- * Libbrasero-media is free software; you can redistribute it and/or modify
-fy
+ * Libbrasero-burn
+ * Copyright (C) Philippe Rouquier 2005-2009 <bonfire-app wanadoo fr>
+ *
+ * Libbrasero-burn is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
+ *
+ * The Libbrasero-burn authors hereby grant permission for non-GPL compatible
+ * GStreamer plugins to be used and distributed together with GStreamer
+ * and Libbrasero-burn. This permission is above and beyond the permissions granted
+ * by the GPL license by which Libbrasero-burn is covered. If you modify this code
+ * you may extend this exception to your version of the code, but you are not
+ * obligated to do so. If you do not wish to do so, delete this exception
+ * statement from your version.
  * 
- * Brasero is distributed in the hope that it will be useful,
+ * Libbrasero-burn is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU Library General Public License for more details.
  * 
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor Boston, MA 02110-1301,  USA
+ * along with this program; if not, write to:
+ * 	The Free Software Foundation, Inc.,
+ * 	51 Franklin Street, Fifth Floor
+ * 	Boston, MA  02110-1301, USA.
  */
  
 #ifndef _BRASERO_FILE_NODE_H
@@ -143,8 +148,7 @@ struct _BraseroFileNode {
 	guint is_tmp_parent:1;
 
 	/* this should be set by BraseroDataDisc */
-	guint is_expanded:1;
-	guint is_selected:1;
+	guint is_selected:1; /* Used to determne if the name is editable */
 
 	/* Used by the model */
 	/* This is a workaround for a warning in gailtreeview.c line 2946 where
@@ -153,6 +157,8 @@ struct _BraseroFileNode {
 	 * upped and therefore wrong. */
 	guint is_inserting:1;
 
+	guint is_expanded:1; /* Used to choose the icon for folders */
+
 	/* this is a ref count a max of 255 should be enough */
 	guint is_visible:7;
 };
@@ -287,10 +293,6 @@ brasero_file_node_save_imported (BraseroFileNode *node,
 				 BraseroFileNode *parent,
 				 GCompareFunc sort_func);
 
-gchar *
-brasero_file_node_get_uri_name (const gchar *uri);
-
-
 gint
 brasero_file_node_sort_name_cb (gconstpointer obj_a, gconstpointer obj_b);
 gint
diff --git a/libbrasero-burn/brasero-filtered-uri.c b/libbrasero-burn/brasero-filtered-uri.c
new file mode 100644
index 0000000..40e5a27
--- /dev/null
+++ b/libbrasero-burn/brasero-filtered-uri.c
@@ -0,0 +1,277 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/*
+ * Libbrasero-burn
+ * Copyright (C) Philippe Rouquier 2005-2009 <bonfire-app wanadoo fr>
+ *
+ * Libbrasero-burn is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The Libbrasero-burn authors hereby grant permission for non-GPL compatible
+ * GStreamer plugins to be used and distributed together with GStreamer
+ * and Libbrasero-burn. This permission is above and beyond the permissions granted
+ * by the GPL license by which Libbrasero-burn is covered. If you modify this code
+ * you may extend this exception to your version of the code, but you are not
+ * obligated to do so. If you do not wish to do so, delete this exception
+ * statement from your version.
+ * 
+ * Libbrasero-burn is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Library General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to:
+ * 	The Free Software Foundation, Inc.,
+ * 	51 Franklin Street, Fifth Floor
+ * 	Boston, MA  02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <glib.h>
+#include <glib/gi18n-lib.h>
+
+#include <gtk/gtk.h>
+
+#include "brasero-misc.h"
+#include "brasero-filtered-uri.h"
+#include "brasero-track-data-cfg.h"
+
+
+G_DEFINE_TYPE (BraseroFilteredUri, brasero_filtered_uri, GTK_TYPE_LIST_STORE);
+
+typedef struct _BraseroFilteredUriPrivate BraseroFilteredUriPrivate;
+struct _BraseroFilteredUriPrivate
+{
+	/* This keeps a record of all URIs that have been filtered/restored by
+	 * the user despite the filtering rules. */
+	GHashTable *restored;
+};
+
+#define BRASERO_FILTERED_URI_PRIVATE(o)  (G_TYPE_INSTANCE_GET_PRIVATE ((o), BRASERO_TYPE_FILTERED_URI, BraseroFilteredUriPrivate))
+
+static const gchar *labels [] = { N_("Hidden file"),
+				  N_("Unreadable file"),
+				  N_("Broken symbolic link"),
+				  N_("Recursive symbolic link"),
+				  NULL };
+
+GSList *
+brasero_filtered_uri_get_restored_list (BraseroFilteredUri *filtered)
+{
+	BraseroFilteredUriPrivate *priv;
+	GSList *retval = NULL;
+	GHashTableIter iter;
+	gpointer key;
+
+	priv = BRASERO_FILTERED_URI_PRIVATE (filtered);
+
+	g_hash_table_iter_init (&iter, priv->restored);
+	while (g_hash_table_iter_next (&iter, &key, NULL))
+		retval = g_slist_prepend (retval, g_strdup (key));
+
+	return retval;
+}
+
+BraseroFilterStatus
+brasero_filtered_uri_lookup_restored (BraseroFilteredUri *filtered,
+				      const gchar *uri)
+{
+	BraseroFilteredUriPrivate *priv;
+
+	priv = BRASERO_FILTERED_URI_PRIVATE (filtered);
+	/* See if this file is already in filtered */
+	return GPOINTER_TO_INT (g_hash_table_lookup (priv->restored, uri));
+}
+
+void
+brasero_filtered_uri_dont_filter (BraseroFilteredUri *filtered,
+				  const gchar *uri)
+{
+	BraseroFilteredUriPrivate *priv;
+
+	priv = BRASERO_FILTERED_URI_PRIVATE (filtered);
+	uri = brasero_utils_register_string (uri);
+	g_hash_table_insert (priv->restored,
+			     (gchar *) uri,
+			     GINT_TO_POINTER (1));
+}
+
+void
+brasero_filtered_uri_filter (BraseroFilteredUri *filtered,
+			     const gchar *uri,
+			     BraseroFilterStatus status)
+{
+	BraseroFilteredUriPrivate *priv;
+	GtkTreeIter iter;
+	gboolean fatal;
+
+	priv = BRASERO_FILTERED_URI_PRIVATE (filtered);
+
+	gtk_list_store_append (GTK_LIST_STORE (filtered), &iter);
+	fatal = (status != BRASERO_FILTER_HIDDEN && status != BRASERO_FILTER_BROKEN_SYM);
+
+	gtk_list_store_set (GTK_LIST_STORE (filtered), &iter,
+			    BRASERO_FILTERED_STOCK_ID_COL, fatal ? GTK_STOCK_CANCEL:NULL,
+			    BRASERO_FILTERED_URI_COL, uri,
+			    BRASERO_FILTERED_STATUS_COL, labels [status - 1],
+			    BRASERO_FILTERED_FATAL_ERROR_COL, fatal,
+			    -1);
+}
+
+void
+brasero_filtered_uri_remove_with_children (BraseroFilteredUri *filtered,
+					   const gchar *uri)
+{
+	BraseroFilteredUriPrivate *priv;
+	GtkTreeIter row_iter;
+	GHashTableIter iter;
+	gpointer value;
+	gpointer key;
+
+	priv = BRASERO_FILTERED_URI_PRIVATE (filtered);
+
+	g_hash_table_iter_init (&iter, priv->restored);
+	while (g_hash_table_iter_next (&iter, &key, &value)) {
+		gchar *key_uri;
+		gint len;
+
+		key_uri = key;
+		len = strlen (key_uri);
+
+		if (!strncmp (uri, key_uri, len)
+		&&   key_uri [len] == G_DIR_SEPARATOR) {
+			brasero_utils_unregister_string (key);
+			g_hash_table_iter_remove (&iter);
+		}
+	}
+
+	if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (filtered), &row_iter))
+		return;
+
+	do {
+		gchar *row_uri;
+		gint len;
+
+		gtk_tree_model_get (GTK_TREE_MODEL (filtered), &row_iter,
+				    BRASERO_FILTERED_URI_COL, &row_uri,
+				    -1);
+
+		len = strlen (row_uri);
+
+		if (!strncmp (uri, row_uri, len)
+		&&   row_uri [len] == G_DIR_SEPARATOR) {
+			gboolean res;
+
+			res = gtk_list_store_remove (GTK_LIST_STORE (filtered), &row_iter);
+			if (!res) {
+				g_free (row_uri);
+				break;
+			}
+		}
+		g_free (row_uri);
+
+	} while (gtk_tree_model_iter_next (GTK_TREE_MODEL (filtered), &row_iter));
+}
+
+gchar *
+brasero_filtered_uri_restore (BraseroFilteredUri *filtered,
+			      GtkTreePath *treepath)
+{
+	BraseroFilteredUriPrivate *priv;
+	GtkTreeIter iter;
+	guint value;
+	gchar *uri;
+
+	priv = BRASERO_FILTERED_URI_PRIVATE (filtered);
+
+	if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (filtered), &iter, treepath))
+		return NULL;
+
+	gtk_tree_model_get (GTK_TREE_MODEL (filtered), &iter,
+			    BRASERO_FILTERED_URI_COL, &uri,
+			    -1);
+
+	gtk_list_store_remove (GTK_LIST_STORE (filtered), &iter);
+
+	value = GPOINTER_TO_INT (g_hash_table_lookup (priv->restored, uri));
+	if (!value)
+		g_hash_table_insert (priv->restored,
+				     (gchar *) brasero_utils_register_string (uri),
+				     GINT_TO_POINTER (1));
+	return uri;
+}
+
+void
+brasero_filtered_uri_clear (BraseroFilteredUri *filtered)
+{
+	BraseroFilteredUriPrivate *priv;
+	GHashTableIter iter;
+	gpointer key;
+
+	priv = BRASERO_FILTERED_URI_PRIVATE (filtered);
+
+	g_hash_table_iter_init (&iter, priv->restored);
+	while (g_hash_table_iter_next (&iter, &key, NULL)) {
+		brasero_utils_unregister_string (key);
+		g_hash_table_iter_remove (&iter);
+	}
+
+	gtk_list_store_clear (GTK_LIST_STORE (filtered));
+}
+
+static void
+brasero_filtered_uri_init (BraseroFilteredUri *object)
+{
+	BraseroFilteredUriPrivate *priv;
+	GType types [BRASERO_FILTERED_NB_COL] = { 0, };
+
+	priv = BRASERO_FILTERED_URI_PRIVATE (object);
+
+	priv->restored = g_hash_table_new (g_str_hash, g_str_equal);
+
+	types [0] = G_TYPE_STRING;
+	types [1] = G_TYPE_STRING;
+	types [2] = G_TYPE_STRING;
+	types [3] = G_TYPE_BOOLEAN;
+	gtk_list_store_set_column_types (GTK_LIST_STORE (object),
+					 BRASERO_FILTERED_NB_COL,
+					 types);
+}
+
+static void
+brasero_filtered_uri_finalize (GObject *object)
+{
+	BraseroFilteredUriPrivate *priv;
+
+	priv = BRASERO_FILTERED_URI_PRIVATE (object);
+
+	brasero_filtered_uri_clear (BRASERO_FILTERED_URI (object));
+
+	if (priv->restored) {
+		g_hash_table_destroy (priv->restored);
+		priv->restored = NULL;
+	}
+
+	G_OBJECT_CLASS (brasero_filtered_uri_parent_class)->finalize (object);
+}
+
+static void
+brasero_filtered_uri_class_init (BraseroFilteredUriClass *klass)
+{
+	GObjectClass* object_class = G_OBJECT_CLASS (klass);
+
+	g_type_class_add_private (klass, sizeof (BraseroFilteredUriPrivate));
+
+	object_class->finalize = brasero_filtered_uri_finalize;
+}
+
+BraseroFilteredUri *
+brasero_filtered_uri_new ()
+{
+	return g_object_new (BRASERO_TYPE_FILTERED_URI, NULL);
+}
diff --git a/libbrasero-burn/brasero-filtered-uri.h b/libbrasero-burn/brasero-filtered-uri.h
new file mode 100644
index 0000000..81c502f
--- /dev/null
+++ b/libbrasero-burn/brasero-filtered-uri.h
@@ -0,0 +1,102 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/*
+ * Libbrasero-burn
+ * Copyright (C) Philippe Rouquier 2005-2009 <bonfire-app wanadoo fr>
+ *
+ * Libbrasero-burn is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The Libbrasero-burn authors hereby grant permission for non-GPL compatible
+ * GStreamer plugins to be used and distributed together with GStreamer
+ * and Libbrasero-burn. This permission is above and beyond the permissions granted
+ * by the GPL license by which Libbrasero-burn is covered. If you modify this code
+ * you may extend this exception to your version of the code, but you are not
+ * obligated to do so. If you do not wish to do so, delete this exception
+ * statement from your version.
+ * 
+ * Libbrasero-burn is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Library General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to:
+ * 	The Free Software Foundation, Inc.,
+ * 	51 Franklin Street, Fifth Floor
+ * 	Boston, MA  02110-1301, USA.
+ */
+
+#ifndef _BRASERO_FILTERED_URI_H_
+#define _BRASERO_FILTERED_URI_H_
+
+#include <glib-object.h>
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+typedef enum {
+	BRASERO_FILTER_NONE			= 0,
+	BRASERO_FILTER_HIDDEN			= 1,
+	BRASERO_FILTER_UNREADABLE,
+	BRASERO_FILTER_BROKEN_SYM,
+	BRASERO_FILTER_RECURSIVE_SYM,
+	BRASERO_FILTER_UNKNOWN,
+} BraseroFilterStatus;
+
+#define BRASERO_TYPE_FILTERED_URI             (brasero_filtered_uri_get_type ())
+#define BRASERO_FILTERED_URI(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), BRASERO_TYPE_FILTERED_URI, BraseroFilteredUri))
+#define BRASERO_FILTERED_URI_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), BRASERO_TYPE_FILTERED_URI, BraseroFilteredUriClass))
+#define BRASERO_IS_FILTERED_URI(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), BRASERO_TYPE_FILTERED_URI))
+#define BRASERO_IS_FILTERED_URI_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), BRASERO_TYPE_FILTERED_URI))
+#define BRASERO_FILTERED_URI_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), BRASERO_TYPE_FILTERED_URI, BraseroFilteredUriClass))
+
+typedef struct _BraseroFilteredUriClass BraseroFilteredUriClass;
+typedef struct _BraseroFilteredUri BraseroFilteredUri;
+
+struct _BraseroFilteredUriClass
+{
+	GtkListStoreClass parent_class;
+};
+
+struct _BraseroFilteredUri
+{
+	GtkListStore parent_instance;
+};
+
+GType brasero_filtered_uri_get_type (void) G_GNUC_CONST;
+
+BraseroFilteredUri *
+brasero_filtered_uri_new (void);
+
+gchar *
+brasero_filtered_uri_restore (BraseroFilteredUri *filtered,
+			      GtkTreePath *treepath);
+
+BraseroFilterStatus
+brasero_filtered_uri_lookup_restored (BraseroFilteredUri *filtered,
+				      const gchar *uri);
+
+GSList *
+brasero_filtered_uri_get_restored_list (BraseroFilteredUri *filtered);
+
+void
+brasero_filtered_uri_filter (BraseroFilteredUri *filtered,
+			     const gchar *uri,
+			     BraseroFilterStatus status);
+void
+brasero_filtered_uri_dont_filter (BraseroFilteredUri *filtered,
+				  const gchar *uri);
+
+void
+brasero_filtered_uri_clear (BraseroFilteredUri *filtered);
+
+void
+brasero_filtered_uri_remove_with_children (BraseroFilteredUri *filtered,
+					   const gchar *uri);
+
+G_END_DECLS
+
+#endif /* _BRASERO_FILTERED_URI_H_ */
diff --git a/libbrasero-burn/brasero-status.h b/libbrasero-burn/brasero-status.h
index eec4802..eca91ab 100644
--- a/libbrasero-burn/brasero-status.h
+++ b/libbrasero-burn/brasero-status.h
@@ -39,6 +39,13 @@ G_BEGIN_DECLS
 
 typedef struct _BraseroStatus BraseroStatus;
 
+typedef enum {
+	BRASERO_STATUS_OK			= 0,
+	BRASERO_STATUS_ERROR,
+	BRASERO_STATUS_QUESTION,
+	BRASERO_STATUS_INFORMATION
+} BraseroStatusType;
+
 BraseroStatus *
 brasero_status_new (void);
 
diff --git a/libbrasero-burn/brasero-track-data-cfg.c b/libbrasero-burn/brasero-track-data-cfg.c
index 1c56126..dc7aae7 100644
--- a/libbrasero-burn/brasero-track-data-cfg.c
+++ b/libbrasero-burn/brasero-track-data-cfg.c
@@ -41,6 +41,11 @@
 
 #include "brasero-track-data-cfg.h"
 
+#include "libbrasero-marshal.h"
+
+#include "brasero-filtered-uri.h"
+
+#include "brasero-misc.h"
 #include "brasero-data-project.h"
 #include "brasero-data-tree-model.h"
 
@@ -48,12 +53,1430 @@ typedef struct _BraseroTrackDataCfgPrivate BraseroTrackDataCfgPrivate;
 struct _BraseroTrackDataCfgPrivate
 {
 	BraseroDataTreeModel *tree;
+	guint stamp;
+
+	guint loading;
+	guint loading_remaining;
+	GSList *load_errors;
+
+	GtkIconTheme *theme;
+
+	GSList *shown;
+
+	gint sort_column;
+	GtkSortType sort_type;
+
+	guint deep_directory:1;
+	guint G2_files:1;
 };
 
 #define BRASERO_TRACK_DATA_CFG_PRIVATE(o)  (G_TYPE_INSTANCE_GET_PRIVATE ((o), BRASERO_TYPE_TRACK_DATA_CFG, BraseroTrackDataCfgPrivate))
 
 
-G_DEFINE_TYPE (BraseroTrackDataCfg, brasero_track_data_cfg, BRASERO_TYPE_TRACK_DATA);
+static void
+brasero_track_data_cfg_drag_source_iface_init (gpointer g_iface, gpointer data);
+static void
+brasero_track_data_cfg_drag_dest_iface_init (gpointer g_iface, gpointer data);
+static void
+brasero_track_data_cfg_sortable_iface_init (gpointer g_iface, gpointer data);
+static void
+brasero_track_data_cfg_iface_init (gpointer g_iface, gpointer data);
+
+G_DEFINE_TYPE_WITH_CODE (BraseroTrackDataCfg,
+			 brasero_track_data_cfg,
+			 BRASERO_TYPE_TRACK_DATA,
+			 G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_MODEL,
+					        brasero_track_data_cfg_iface_init)
+			 G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_DRAG_DEST,
+					        brasero_track_data_cfg_drag_dest_iface_init)
+			 G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_DRAG_SOURCE,
+					        brasero_track_data_cfg_drag_source_iface_init)
+			 G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_SORTABLE,
+						brasero_track_data_cfg_sortable_iface_init));
+
+typedef enum {
+	BRASERO_ROW_REGULAR		= 0,
+	BRASERO_ROW_BOGUS
+} BraseroFileRowType;
+
+enum {
+	AVAILABLE,
+	LOADED,
+	OVERSIZE,
+	ACTIVITY,
+	IMAGE,
+	UNREADABLE,
+	RECURSIVE,
+	UNKNOWN,
+	G2_FILE,
+	NAME_COLLISION,
+	DEEP_DIRECTORY,
+	SOURCE_LOADED, 
+	SOURCE_LOADING, 
+	LAST_SIGNAL
+};
+
+static gulong brasero_track_data_cfg_signals [LAST_SIGNAL] = { 0 };
+
+
+/**
+ * GtkTreeModel part
+ */
+
+static gboolean
+brasero_track_data_cfg_iter_parent (GtkTreeModel *model,
+				     GtkTreeIter *iter,
+				     GtkTreeIter *child)
+{
+	BraseroTrackDataCfgPrivate *priv;
+	BraseroFileNode *node;
+
+	priv = BRASERO_TRACK_DATA_CFG_PRIVATE (model);
+
+	/* make sure that iter comes from us */
+	g_return_val_if_fail (priv->stamp == child->stamp, FALSE);
+	g_return_val_if_fail (child->user_data != NULL, FALSE);
+
+	node = child->user_data;
+	if (child->user_data2 == GINT_TO_POINTER (BRASERO_ROW_BOGUS)) {
+		/* This is a bogus row intended for empty directories
+		 * user_data has the parent empty directory. */
+		iter->user_data2 = GINT_TO_POINTER (BRASERO_ROW_REGULAR);
+		iter->user_data = child->user_data;
+		iter->stamp = priv->stamp;
+		return TRUE;
+	}
+
+	if (!node->parent) {
+		iter->user_data = NULL;
+		return FALSE;
+	}
+
+	iter->stamp = priv->stamp;
+	iter->user_data = node->parent;
+	iter->user_data2 = GINT_TO_POINTER (BRASERO_ROW_REGULAR);
+	return TRUE;
+}
+
+static gboolean
+brasero_track_data_cfg_iter_nth_child (GtkTreeModel *model,
+					GtkTreeIter *iter,
+					GtkTreeIter *parent,
+					gint n)
+{
+	BraseroTrackDataCfgPrivate *priv;
+	BraseroFileNode *node;
+
+	priv = BRASERO_TRACK_DATA_CFG_PRIVATE (model);
+
+	if (parent) {
+		/* make sure that iter comes from us */
+		g_return_val_if_fail (priv->stamp == parent->stamp, FALSE);
+		g_return_val_if_fail (parent->user_data != NULL, FALSE);
+
+		if (parent->user_data2 == GINT_TO_POINTER (BRASERO_ROW_BOGUS)) {
+			/* This is a bogus row intended for empty directories,
+			 * it hasn't got children. */
+			return FALSE;
+		}
+
+		node = parent->user_data;
+	}
+	else
+		node = brasero_data_project_get_root (BRASERO_DATA_PROJECT (model));
+
+	iter->user_data = brasero_file_node_nth_child (node, n);
+	if (!iter->user_data)
+		return FALSE;
+
+	iter->stamp = priv->stamp;
+	iter->user_data2 = GINT_TO_POINTER (BRASERO_ROW_REGULAR);
+	return TRUE;
+}
+
+static gint
+brasero_track_data_cfg_iter_n_children (GtkTreeModel *model,
+					 GtkTreeIter *iter)
+{
+	BraseroTrackDataCfgPrivate *priv;
+	BraseroFileNode *node;
+
+	priv = BRASERO_TRACK_DATA_CFG_PRIVATE (model);
+
+	if (iter == NULL) {
+		/* special case */
+		node = brasero_data_project_get_root (BRASERO_DATA_PROJECT (model));
+		return brasero_file_node_get_n_children (node);
+	}
+
+	/* make sure that iter comes from us */
+	g_return_val_if_fail (priv->stamp == iter->stamp, 0);
+	g_return_val_if_fail (iter->user_data != NULL, 0);
+
+	if (iter->user_data2 == GINT_TO_POINTER (BRASERO_ROW_BOGUS))
+		return 0;
+
+	node = iter->user_data;
+	if (node->is_file)
+		return 0;
+
+	/* return at least one for the bogus row labelled "empty". */
+	if (!BRASERO_FILE_NODE_CHILDREN (node))
+		return 1;
+
+	return brasero_file_node_get_n_children (node);
+}
+
+static gboolean
+brasero_track_data_cfg_iter_has_child (GtkTreeModel *model,
+					GtkTreeIter *iter)
+{
+	BraseroTrackDataCfgPrivate *priv;
+	BraseroFileNode *node;
+
+	priv = BRASERO_TRACK_DATA_CFG_PRIVATE (model);
+
+	/* make sure that iter comes from us */
+	g_return_val_if_fail (priv->stamp == iter->stamp, FALSE);
+	g_return_val_if_fail (iter->user_data != NULL, FALSE);
+
+	if (iter->user_data2 == GINT_TO_POINTER (BRASERO_ROW_BOGUS)) {
+		/* This is a bogus row intended for empty directories
+		 * it hasn't got children */
+		return FALSE;
+	}
+
+	node = iter->user_data;
+
+	/* This is a workaround for a warning in gailtreeview.c line 2946 where
+	 * gail uses the GtkTreePath and not a copy which if the node inserted
+	 * declares to have children and is not expanded leads to the path being
+	 * upped and therefore wrong. */
+	if (node->is_inserting)
+		return FALSE;
+
+	if (node->is_file)
+		return FALSE;
+
+	/* always return TRUE here when it's a directory since even if
+	 * it's empty we'll add a row written empty underneath it
+	 * anyway. */
+	return TRUE;
+}
+
+static gboolean
+brasero_track_data_cfg_iter_children (GtkTreeModel *model,
+				       GtkTreeIter *iter,
+				       GtkTreeIter *parent)
+{
+	BraseroTrackDataCfgPrivate *priv;
+	BraseroFileNode *node;
+
+	priv = BRASERO_TRACK_DATA_CFG_PRIVATE (model);
+
+	if (!parent) {
+		BraseroFileNode *root;
+
+		/* This is for the top directory */
+		root = brasero_data_project_get_root (BRASERO_DATA_PROJECT (model));
+		if (!root || !BRASERO_FILE_NODE_CHILDREN (root))
+			return FALSE;
+
+		iter->stamp = priv->stamp;
+		iter->user_data = BRASERO_FILE_NODE_CHILDREN (root);
+		iter->user_data2 = GINT_TO_POINTER (BRASERO_ROW_REGULAR);
+		return TRUE;
+	}
+
+	/* make sure that iter comes from us */
+	g_return_val_if_fail (priv->stamp == parent->stamp, FALSE);
+	g_return_val_if_fail (parent->user_data != NULL, FALSE);
+
+	if (parent->user_data2 == GINT_TO_POINTER (BRASERO_ROW_BOGUS)) {
+		iter->user_data = NULL;
+		return FALSE;
+	}
+
+	node = parent->user_data;
+	if (node->is_file) {
+		iter->user_data = NULL;
+		return FALSE;
+	}
+
+	iter->stamp = priv->stamp;
+	if (!BRASERO_FILE_NODE_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. */
+		iter->user_data = parent->user_data;
+		iter->user_data2 = GINT_TO_POINTER (BRASERO_ROW_BOGUS);
+		return TRUE;
+	}
+
+	iter->user_data = BRASERO_FILE_NODE_CHILDREN (node);
+	iter->user_data2 = GINT_TO_POINTER (BRASERO_ROW_REGULAR);
+	return TRUE;
+}
+
+static gboolean
+brasero_track_data_cfg_iter_next (GtkTreeModel *model,
+				   GtkTreeIter *iter)
+{
+	BraseroTrackDataCfgPrivate *priv;
+	BraseroFileNode *node;
+
+	priv = BRASERO_TRACK_DATA_CFG_PRIVATE (model);
+
+	/* make sure that iter comes from us */
+	g_return_val_if_fail (priv->stamp == iter->stamp, FALSE);
+	g_return_val_if_fail (iter->user_data != NULL, FALSE);
+
+	if (iter->user_data2 == GINT_TO_POINTER (BRASERO_ROW_BOGUS)) {
+		/* This is a bogus row intended for empty directories
+		 * user_data has the parent empty directory. It hasn't
+		 * got any peer.*/
+		iter->user_data = NULL;
+		return FALSE;
+	}
+
+	node = iter->user_data;
+	iter->user_data = node->next;
+	if (!node->next)
+		return FALSE;
+
+	return TRUE;
+}
+
+static void
+brasero_track_data_cfg_node_shown (GtkTreeModel *model,
+				    GtkTreeIter *iter)
+{
+	BraseroFileNode *node;
+	BraseroTrackDataCfgPrivate *priv;
+
+	priv = BRASERO_TRACK_DATA_CFG_PRIVATE (model);
+	node = iter->user_data;
+
+	/* Check if that's a BOGUS row. In this case that means the parent was
+	 * expanded. Therefore ask vfs to increase its priority if it's loading
+	 * its contents. */
+	if (iter->user_data2 == GINT_TO_POINTER (BRASERO_ROW_BOGUS)) {
+		/* NOTE: this has to be a directory */
+		/* NOTE: there is no need to check for is_loading case here
+		 * since before showing its BOGUS row the tree will have shown
+		 * its parent itself and therefore that's the cases that follow
+		 */
+		if (node->is_exploring) {
+			/* the directory is being explored increase priority */
+			brasero_data_vfs_require_directory_contents (BRASERO_DATA_VFS (model), node);
+		}
+
+		/* Otherwise, that's simply a BOGUS row and its parent was
+		 * loaded but it is empty. Nothing to do. */
+		node->is_expanded = TRUE;
+		return;
+	}
+
+	if (node->parent && !node->parent->is_root)
+		node->parent->is_expanded = TRUE;
+
+	if (!node)
+		return;
+
+	node->is_visible ++;
+
+	if (node->is_imported) {
+		if (node->is_fake && !node->is_file) {
+			/* we don't load all nodes when importing a session do it now */
+			brasero_data_session_load_directory_contents (BRASERO_DATA_SESSION (model), node, NULL);
+		}
+
+		return;
+	}
+
+	if (node->is_visible > 1)
+		return;
+
+	/* NOTE: no need to see if that's a directory being explored here. If it
+	 * is being explored then it has a BOGUS row and that's the above case 
+	 * that is reached. */
+	if (node->is_loading) {
+		/* in this case have vfs to increase priority for this node */
+		brasero_data_vfs_require_node_load (BRASERO_DATA_VFS (model), node);
+	}
+	else if (!BRASERO_FILE_NODE_MIME (node)) {
+		/* that means that file wasn't completly loaded. To save
+		 * some time we delayed the detection of the mime type
+		 * since that takes a lot of time. */
+		brasero_data_vfs_load_mime (BRASERO_DATA_VFS (model), node);
+	}
+
+	/* add the node to the visible list that is used to update the disc 
+	 * share for the node (we don't want to update the whole tree).
+	 * Moreover, we only want files since directories don't have space. */
+	priv->shown = g_slist_prepend (priv->shown, node);
+}
+
+static void
+brasero_track_data_cfg_node_hidden (GtkTreeModel *model,
+				     GtkTreeIter *iter)
+{
+	BraseroFileNode *node;
+	BraseroTrackDataCfgPrivate *priv;
+
+	/* if it's a BOGUS row stop here since they are not added to shown list.
+	 * In the same way returns if it is a file. */
+	node = iter->user_data;
+	if (iter->user_data2 == GINT_TO_POINTER (BRASERO_ROW_BOGUS)) {
+		node->is_expanded = FALSE;
+		return;
+	}
+
+	if (node->parent && !node->parent->is_root)
+		node->parent->is_expanded = FALSE;
+
+	if (!node)
+		return;
+
+	node->is_visible --;
+
+	if (node->is_imported)
+		return;
+
+	priv = BRASERO_TRACK_DATA_CFG_PRIVATE (model);
+
+	/* update shown list */
+	if (!node->is_visible)
+		priv->shown = g_slist_remove (priv->shown, node);
+}
+
+static void
+brasero_track_data_cfg_get_value (GtkTreeModel *model,
+				   GtkTreeIter *iter,
+				   gint column,
+				   GValue *value)
+{
+	BraseroTrackDataCfgPrivate *priv;
+	BraseroTrackDataCfg *self;
+	BraseroFileNode *node;
+
+	self = BRASERO_TRACK_DATA_CFG (model);
+	priv = BRASERO_TRACK_DATA_CFG_PRIVATE (model);
+
+	/* make sure that iter comes from us */
+	g_return_if_fail (priv->stamp == iter->stamp);
+	g_return_if_fail (iter->user_data != NULL);
+
+	node = iter->user_data;
+
+	if (iter->user_data2 == GINT_TO_POINTER (BRASERO_ROW_BOGUS)) {
+		switch (column) {
+		case BRASERO_DATA_TREE_MODEL_NAME:
+			g_value_init (value, G_TYPE_STRING);
+			if (node->is_exploring)
+				g_value_set_string (value, _("(loading ...)"));
+			else
+				g_value_set_string (value, _("Empty"));
+
+			return;
+
+		case BRASERO_DATA_TREE_MODEL_MIME_DESC:
+		case BRASERO_DATA_TREE_MODEL_MIME_ICON:
+		case BRASERO_DATA_TREE_MODEL_SIZE:
+			g_value_init (value, G_TYPE_STRING);
+			g_value_set_string (value, NULL);
+			return;
+
+		case BRASERO_DATA_TREE_MODEL_SHOW_PERCENT:
+			g_value_init (value, G_TYPE_BOOLEAN);
+			g_value_set_boolean (value, FALSE);
+			return;
+
+		case BRASERO_DATA_TREE_MODEL_PERCENT:
+			g_value_init (value, G_TYPE_INT);
+			g_value_set_int (value, 0);
+			return;
+
+		case BRASERO_DATA_TREE_MODEL_STYLE:
+			g_value_init (value, PANGO_TYPE_STYLE);
+			g_value_set_enum (value, PANGO_STYLE_ITALIC);
+			return;
+
+		case BRASERO_DATA_TREE_MODEL_EDITABLE:
+			g_value_init (value, G_TYPE_BOOLEAN);
+			g_value_set_boolean (value, FALSE);
+			return;
+	
+		case BRASERO_DATA_TREE_MODEL_COLOR:
+			g_value_init (value, G_TYPE_STRING);
+			g_value_set_string (value, NULL);
+			return;
+
+		default:
+			return;
+		}
+
+		return;
+	}
+
+	switch (column) {
+	case BRASERO_DATA_TREE_MODEL_EDITABLE:
+		g_value_init (value, G_TYPE_BOOLEAN);
+		g_value_set_boolean (value, (node->is_imported == FALSE) && node->is_selected);
+		return;
+
+	case BRASERO_DATA_TREE_MODEL_NAME: {
+		gchar *filename;
+
+		g_value_init (value, G_TYPE_STRING);
+		filename = g_filename_to_utf8 (BRASERO_FILE_NODE_NAME (node),
+					       -1,
+					       NULL,
+					       NULL,
+					       NULL);
+		if (!filename)
+			filename = brasero_utils_validate_utf8 (BRASERO_FILE_NODE_NAME (node));
+
+		if (filename)
+			g_value_set_string (value, filename);
+		else	/* Glib section on g_convert advise to use a string like
+			 * "Invalid Filename". */
+			g_value_set_string (value, BRASERO_FILE_NODE_NAME (node));
+
+		g_free (filename);
+		return;
+	}
+
+	case BRASERO_DATA_TREE_MODEL_MIME_DESC:
+		g_value_init (value, G_TYPE_STRING);
+		if (node->is_loading)
+			g_value_set_string (value, _("(loading ...)"));
+		else if (!node->is_file) {
+			gchar *description;
+
+			description = g_content_type_get_description ("inode/directory");
+			g_value_set_string (value, description);
+			g_free (description);
+		}
+		else if (node->is_imported)
+			g_value_set_string (value, _("Disc file"));
+		else if (!BRASERO_FILE_NODE_MIME (node))
+			g_value_set_string (value, _("(loading ...)"));
+		else {
+			gchar *description;
+
+			description = g_content_type_get_description (BRASERO_FILE_NODE_MIME (node));
+			g_value_set_string (value, description);
+			g_free (description);
+		}
+
+		return;
+
+	case BRASERO_DATA_TREE_MODEL_MIME_ICON:
+		g_value_init (value, G_TYPE_STRING);
+		if (node->is_loading)
+			g_value_set_string (value, "image-loading");
+		else if (!node->is_file) {
+			/* Here we have two states collapsed and expanded */
+			if (node->is_expanded)
+				g_value_set_string (value, "folder-open");
+			else if (node->is_imported)
+				/* that's for all the imported folders */
+				g_value_set_string (value, "folder-visiting");
+			else
+				g_value_set_string (value, "folder");
+		}
+		else if (node->is_imported) {
+			g_value_set_string (value, "media-cdrom");
+		}
+		else if (BRASERO_FILE_NODE_MIME (node)) {
+			const gchar *icon_string = "text-x-preview";
+			GIcon *icon;
+
+			/* NOTE: implemented in glib 2.15.6 (not for windows though) */
+			icon = g_content_type_get_icon (BRASERO_FILE_NODE_MIME (node));
+			if (G_IS_THEMED_ICON (icon)) {
+				const gchar * const *names = NULL;
+
+				names = g_themed_icon_get_names (G_THEMED_ICON (icon));
+				if (names) {
+					gint i;
+
+					for (i = 0; names [i]; i++) {
+						if (gtk_icon_theme_has_icon (priv->theme, names [i])) {
+							icon_string = names [i];
+							break;
+						}
+					}
+				}
+			}
+
+			g_value_set_string (value, icon_string);
+			g_object_unref (icon);
+		}
+		else
+			g_value_set_string (value, "image-loading");
+
+		return;
+
+	case BRASERO_DATA_TREE_MODEL_SIZE:
+		g_value_init (value, G_TYPE_STRING);
+		if (node->is_loading)
+			g_value_set_string (value, _("(loading ...)"));
+		else if (!node->is_file) {
+			guint nb_items;
+
+			if (node->is_exploring) {
+				g_value_set_string (value, _("(loading ...)"));
+				return;
+			}
+
+			nb_items = brasero_file_node_get_n_children (node);
+			if (!nb_items)
+				g_value_set_string (value, _("Empty"));
+			else {
+				gchar *text;
+
+				text = g_strdup_printf (ngettext ("%d item", "%d items", nb_items), nb_items);
+				g_value_set_string (value, text);
+				g_free (text);
+			}
+		}
+		else {
+			gchar *text;
+
+			text = g_format_size_for_display (BRASERO_FILE_NODE_SECTORS (node) * 2048);
+			g_value_set_string (value, text);
+			g_free (text);
+		}
+
+		return;
+
+	case BRASERO_DATA_TREE_MODEL_SHOW_PERCENT:
+		g_value_init (value, G_TYPE_BOOLEAN);
+		if (node->is_imported || node->is_loading)
+			g_value_set_boolean (value, FALSE);
+		else
+			g_value_set_boolean (value, TRUE);
+
+		return;
+
+	case BRASERO_DATA_TREE_MODEL_PERCENT:
+		g_value_init (value, G_TYPE_INT);
+		if (!node->is_imported && !brasero_data_vfs_is_active (BRASERO_DATA_VFS (self))) {
+			gint64 size;
+			guint node_size;
+
+			size = brasero_data_project_get_size (BRASERO_DATA_PROJECT (self));
+
+			if (!node->is_file)
+				node_size = brasero_data_project_get_folder_size (BRASERO_DATA_PROJECT (self), node);
+			else
+				node_size = BRASERO_FILE_NODE_SECTORS (node);
+			if (size)
+				g_value_set_int (value, MAX (0, MIN (node_size * 100 / size, 100)));
+			else
+				g_value_set_int (value, 0);
+		}
+		else
+			g_value_set_int (value, 0);
+
+		return;
+
+	case BRASERO_DATA_TREE_MODEL_STYLE:
+		g_value_init (value, PANGO_TYPE_STYLE);
+		if (node->is_imported)
+			g_value_set_enum (value, PANGO_STYLE_ITALIC);
+
+		return;
+
+	case BRASERO_DATA_TREE_MODEL_COLOR:
+		g_value_init (value, G_TYPE_STRING);
+		if (node->is_imported)
+			g_value_set_string (value, "grey50");
+
+		return;
+
+	default:
+		return;
+	}
+
+	return;
+}
+
+GtkTreePath *
+brasero_track_data_cfg_node_to_path (BraseroTrackDataCfg *self,
+				      BraseroFileNode *node)
+{
+	BraseroTrackDataCfgPrivate *priv;
+	GtkTreePath *path;
+
+	priv = BRASERO_TRACK_DATA_CFG_PRIVATE (self);
+
+	path = gtk_tree_path_new ();
+	for (; node->parent && !node->is_root; node = node->parent) {
+		guint nth;
+
+		nth = brasero_file_node_get_pos_as_child (node);
+		gtk_tree_path_prepend_index (path, nth);
+	}
+
+	return path;
+}
+
+static GtkTreePath *
+brasero_track_data_cfg_get_path (GtkTreeModel *model,
+				  GtkTreeIter *iter)
+{
+	BraseroTrackDataCfgPrivate *priv;
+	BraseroFileNode *node;
+	GtkTreePath *path;
+
+	priv = BRASERO_TRACK_DATA_CFG_PRIVATE (model);
+
+	/* make sure that iter comes from us */
+	g_return_val_if_fail (priv->stamp == iter->stamp, NULL);
+	g_return_val_if_fail (iter->user_data != NULL, NULL);
+
+	node = iter->user_data;
+
+	/* NOTE: there is only one single node without a name: root */
+	path = brasero_track_data_cfg_node_to_path (BRASERO_TRACK_DATA_CFG (model), node);
+
+	/* Add index 0 for empty bogus row */
+	if (iter->user_data2 == GINT_TO_POINTER (BRASERO_ROW_BOGUS))
+		gtk_tree_path_append_index (path, 0);
+
+	return path;
+}
+
+BraseroFileNode *
+brasero_track_data_cfg_path_to_node (BraseroTrackDataCfg *self,
+				      GtkTreePath *path)
+{
+	BraseroTrackDataCfgPrivate *priv;
+	BraseroFileNode *node;
+	gint *indices;
+	guint depth;
+	guint i;
+
+	priv = BRASERO_TRACK_DATA_CFG_PRIVATE (self);
+
+	indices = gtk_tree_path_get_indices (path);
+	depth = gtk_tree_path_get_depth (path);
+
+	node = brasero_data_project_get_root (BRASERO_DATA_PROJECT (self));
+	for (i = 0; i < depth; i ++) {
+		BraseroFileNode *parent;
+
+		parent = node;
+		node = brasero_file_node_nth_child (parent, indices [i]);
+		if (!node)
+			return NULL;
+	}
+	return node;
+}
+
+static gboolean
+brasero_track_data_cfg_get_iter (GtkTreeModel *model,
+				  GtkTreeIter *iter,
+				  GtkTreePath *path)
+{
+	BraseroTrackDataCfgPrivate *priv;
+	BraseroFileNode *root;
+	BraseroFileNode *node;
+	const gint *indices;
+	guint depth;
+	guint i;
+
+	priv = BRASERO_TRACK_DATA_CFG_PRIVATE (model);
+
+	indices = gtk_tree_path_get_indices (path);
+	depth = gtk_tree_path_get_depth (path);
+
+	root = brasero_data_project_get_root (BRASERO_DATA_PROJECT (model));
+	/* NOTE: if we're in reset, then root won't exist anymore */
+	if (!root)
+		return FALSE;
+		
+	node = brasero_file_node_nth_child (root, indices [0]);
+	if (!node)
+		return FALSE;
+
+	for (i = 1; i < depth; i ++) {
+		BraseroFileNode *parent;
+
+		parent = node;
+		node = brasero_file_node_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)
+			&&   indices [i] == 0) {
+				iter->stamp = priv->stamp;
+				iter->user_data = parent;
+				iter->user_data2 = GINT_TO_POINTER (BRASERO_ROW_BOGUS);
+				return TRUE;
+			}
+
+			iter->user_data = NULL;
+			return FALSE;
+		}
+	}
+
+	iter->user_data2 = GINT_TO_POINTER (BRASERO_ROW_REGULAR);
+	iter->stamp = priv->stamp;
+	iter->user_data = node;
+
+	return TRUE;
+}
+
+static GType
+brasero_track_data_cfg_get_column_type (GtkTreeModel *model,
+					 gint index)
+{
+	switch (index) {
+	case BRASERO_DATA_TREE_MODEL_NAME:
+		return G_TYPE_STRING;
+
+	case BRASERO_DATA_TREE_MODEL_MIME_DESC:
+		return G_TYPE_STRING;
+
+	case BRASERO_DATA_TREE_MODEL_MIME_ICON:
+		return G_TYPE_STRING;
+
+	case BRASERO_DATA_TREE_MODEL_SIZE:
+		return G_TYPE_STRING;
+
+	case BRASERO_DATA_TREE_MODEL_SHOW_PERCENT:
+		return G_TYPE_BOOLEAN;
+
+	case BRASERO_DATA_TREE_MODEL_PERCENT:
+		return G_TYPE_INT;
+
+	case BRASERO_DATA_TREE_MODEL_STYLE:
+		return PANGO_TYPE_STYLE;
+
+	case BRASERO_DATA_TREE_MODEL_COLOR:
+		return G_TYPE_STRING;
+
+	case BRASERO_DATA_TREE_MODEL_EDITABLE:
+		return G_TYPE_BOOLEAN;
+
+	default:
+		break;
+	}
+
+	return G_TYPE_INVALID;
+}
+
+static gint
+brasero_track_data_cfg_get_n_columns (GtkTreeModel *model)
+{
+	return BRASERO_DATA_TREE_MODEL_COL_NUM;
+}
+
+static GtkTreeModelFlags
+brasero_track_data_cfg_get_flags (GtkTreeModel *model)
+{
+	return 0;
+}
+
+static gboolean
+brasero_track_data_cfg_row_draggable (GtkTreeDragSource *drag_source,
+				      GtkTreePath *treepath)
+{
+	BraseroFileNode *node;
+
+	node = brasero_track_data_cfg_path_to_node (BRASERO_TRACK_DATA_CFG (drag_source), treepath);
+	if (node && !node->is_imported)
+		return TRUE;
+
+	return FALSE;
+}
+
+static gboolean
+brasero_track_data_cfg_drag_data_get (GtkTreeDragSource *drag_source,
+				      GtkTreePath *treepath,
+				      GtkSelectionData *selection_data)
+{
+	if (selection_data->target == gdk_atom_intern (BRASERO_DND_TARGET_DATA_TRACK_REFERENCE_LIST, TRUE)) {
+		GtkTreeRowReference *reference;
+
+		reference = gtk_tree_row_reference_new (GTK_TREE_MODEL (drag_source), treepath);
+		gtk_selection_data_set (selection_data,
+					gdk_atom_intern_static_string (BRASERO_DND_TARGET_DATA_TRACK_REFERENCE_LIST),
+					8,
+					(void *) g_list_prepend (NULL, reference),
+					sizeof (GList *));
+	}
+	else
+		return FALSE;
+
+	return TRUE;
+}
+
+static gboolean
+brasero_track_data_cfg_drag_data_delete (GtkTreeDragSource *drag_source,
+					 GtkTreePath *path)
+{
+	/* NOTE: it's not the data in the selection_data here that should be
+	 * deleted but rather the rows selected when there is a move. FALSE
+	 * here means that we didn't delete anything. */
+	/* return TRUE to stop other handlers */
+	return TRUE;
+}
+
+static gboolean
+brasero_track_data_cfg_drag_data_received (GtkTreeDragDest *drag_dest,
+					   GtkTreePath *dest_path,
+					   GtkSelectionData *selection_data)
+{
+	BraseroFileNode *node;
+	BraseroFileNode *parent;
+	GtkTreePath *dest_parent;
+	BraseroTrackDataCfg *self;
+
+	self = BRASERO_TRACK_DATA_CFG (drag_dest);
+
+	/* NOTE: dest_path is the path to insert before; so we may not have a 
+	 * valid path if it's in an empty directory */
+
+	dest_parent = gtk_tree_path_copy (dest_path);
+	gtk_tree_path_up (dest_parent);
+	parent = brasero_track_data_cfg_path_to_node (self, dest_parent);
+	if (!parent) {
+		gtk_tree_path_up (dest_parent);
+		parent = brasero_track_data_cfg_path_to_node (self, dest_parent);
+	}
+	else if (parent->is_file)
+		parent = parent->parent;
+
+	gtk_tree_path_free (dest_parent);
+
+	/* Received data: see where it comes from:
+	 * - from us, then that's a simple move
+	 * - from another widget then it's going to be URIS and we add
+	 *   them to the DataProject */
+	if (selection_data->target == gdk_atom_intern (BRASERO_DND_TARGET_DATA_TRACK_REFERENCE_LIST, TRUE)) {
+		GList *iter;
+
+		iter = (GList *) selection_data->data;
+
+		/* That's us: move the row and its children. */
+		for (; iter; iter = iter->next) {
+			GtkTreeRowReference *reference;
+			GtkTreeModel *src_model;
+			GtkTreePath *treepath;
+
+			reference = iter->data;
+			src_model = gtk_tree_row_reference_get_model (reference);
+			if (src_model != GTK_TREE_MODEL (drag_dest))
+				continue;
+
+			treepath = gtk_tree_row_reference_get_path (reference);
+
+			node = brasero_track_data_cfg_path_to_node (BRASERO_TRACK_DATA_CFG (drag_dest), treepath);
+			gtk_tree_path_free (treepath);
+
+			brasero_data_project_move_node (BRASERO_DATA_PROJECT (self), node, parent);
+		}
+	}
+	else if (selection_data->target == gdk_atom_intern ("text/uri-list", TRUE)) {
+		gint i;
+		gchar **uris;
+		gboolean success = FALSE;
+
+		/* NOTE: there can be many URIs at the same time. One
+		 * success is enough to return TRUE. */
+		success = FALSE;
+		uris = gtk_selection_data_get_uris (selection_data);
+		if (!uris)
+			return TRUE;
+
+		for (i = 0; uris [i]; i ++) {
+			BraseroFileNode *node;
+
+			/* Add the URIs to the project */
+			node = brasero_data_project_add_loading_node (BRASERO_DATA_PROJECT (self),
+								      uris [i],
+								      parent);
+			if (node)
+				success = TRUE;
+		}
+		g_strfreev (uris);
+	}
+	else
+		return FALSE;
+
+	return TRUE;
+}
+
+static gboolean
+brasero_track_data_cfg_row_drop_possible (GtkTreeDragDest *drag_dest,
+					  GtkTreePath *dest_path,
+					  GtkSelectionData *selection_data)
+{
+	/* See if we are dropping to ourselves */
+	if (selection_data->target == gdk_atom_intern_static_string (BRASERO_DND_TARGET_DATA_TRACK_REFERENCE_LIST)) {
+		GtkTreePath *dest_parent;
+		BraseroFileNode *parent;
+		GList *iter;
+
+		iter = (GList *) selection_data->data;
+
+		/* make sure the parent is a directory.
+		 * NOTE: in this case dest_path is the exact path where it
+		 * should be inserted. */
+		dest_parent = gtk_tree_path_copy (dest_path);
+		gtk_tree_path_up (dest_parent);
+
+		parent = brasero_track_data_cfg_path_to_node (BRASERO_TRACK_DATA_CFG (drag_dest), dest_parent);
+
+		if (!parent) {
+			/* See if that isn't a BOGUS row; if so, try with parent */
+			gtk_tree_path_up (dest_parent);
+			parent = brasero_track_data_cfg_path_to_node (BRASERO_TRACK_DATA_CFG (drag_dest), dest_parent);
+
+			if (!parent) {
+				gtk_tree_path_free (dest_parent);
+				return FALSE;
+			}
+		}
+		else if (parent->is_file) {
+			/* if that's a file try with parent */
+			gtk_tree_path_up (dest_parent);
+			parent = parent->parent;
+		}
+
+		if (parent->is_loading) {
+			gtk_tree_path_free (dest_parent);
+			return FALSE;
+		}
+
+		for (; iter; iter = iter->next) {
+			GtkTreePath *src_path;
+			GtkTreeModel *src_model;
+			GtkTreeRowReference *reference;
+
+			reference = iter->data;
+			src_model = gtk_tree_row_reference_get_model (reference);
+			if (src_model != GTK_TREE_MODEL (drag_dest))
+				continue;
+
+			src_path = gtk_tree_row_reference_get_path (reference);
+
+			/* see if we are not moving a parent to one of its children */
+			if (gtk_tree_path_is_ancestor (src_path, dest_path)) {
+				gtk_tree_path_free (src_path);
+				continue;
+			}
+
+			if (gtk_tree_path_up (src_path)) {
+				/* check that node was moved to another directory */
+				if (!parent->parent) {
+					if (gtk_tree_path_get_depth (src_path)) {
+						gtk_tree_path_free (src_path);
+						gtk_tree_path_free (dest_parent);
+						return TRUE;
+					}
+				}
+				else if (!gtk_tree_path_get_depth (src_path)
+				     ||   gtk_tree_path_compare (src_path, dest_parent)) {
+					gtk_tree_path_free (src_path);
+					gtk_tree_path_free (dest_parent);
+					return TRUE;
+				}
+			}
+
+			gtk_tree_path_free (src_path);
+		}
+
+		gtk_tree_path_free (dest_parent);
+		return FALSE;
+	}
+	else if (selection_data->target == gdk_atom_intern_static_string ("text/uri-list"))
+		return TRUE;
+
+	return FALSE;
+}
+
+/**
+ * Sorting part
+ */
+
+static gboolean
+brasero_track_data_cfg_get_sort_column_id (GtkTreeSortable *sortable,
+					    gint *column,
+					    GtkSortType *type)
+{
+	BraseroTrackDataCfgPrivate *priv;
+
+	priv = BRASERO_TRACK_DATA_CFG_PRIVATE (sortable);
+
+	if (column)
+		*column = priv->sort_column;
+
+	if (type)
+		*type = priv->sort_type;
+
+	return TRUE;
+}
+
+static void
+brasero_track_data_cfg_set_sort_column_id (GtkTreeSortable *sortable,
+					    gint column,
+					    GtkSortType type)
+{
+	BraseroTrackDataCfgPrivate *priv;
+
+	priv = BRASERO_TRACK_DATA_CFG_PRIVATE (sortable);
+	priv->sort_column = column;
+	priv->sort_type = type;
+
+	switch (column) {
+	case BRASERO_DATA_TREE_MODEL_NAME:
+		brasero_data_project_set_sort_function (BRASERO_DATA_PROJECT (sortable),
+							type,
+							brasero_file_node_sort_name_cb);
+		break;
+	case BRASERO_DATA_TREE_MODEL_SIZE:
+		brasero_data_project_set_sort_function (BRASERO_DATA_PROJECT (sortable),
+							type,
+							brasero_file_node_sort_size_cb);
+		break;
+	case BRASERO_DATA_TREE_MODEL_MIME_DESC:
+		brasero_data_project_set_sort_function (BRASERO_DATA_PROJECT (sortable),
+							type,
+							brasero_file_node_sort_mime_cb);
+		break;
+	default:
+		brasero_data_project_set_sort_function (BRASERO_DATA_PROJECT (sortable),
+							type,
+							brasero_file_node_sort_default_cb);
+		break;
+	}
+
+	gtk_tree_sortable_sort_column_changed (sortable);
+}
+
+static gboolean
+brasero_track_data_cfg_has_default_sort_func (GtkTreeSortable *sortable)
+{
+	/* That's always true since we sort files and directories */
+	return TRUE;
+}
+
+static void
+brasero_track_data_cfg_node_added (BraseroDataProject *project,
+				   BraseroFileNode *node,
+				   BraseroTrackDataCfg *self)
+{
+	BraseroTrackDataCfgPrivate *priv;
+	BraseroFileNode *parent;
+	GtkTreePath *path;
+	GtkTreeIter iter;
+
+	priv = BRASERO_TRACK_DATA_CFG_PRIVATE (self);
+
+	iter.stamp = priv->stamp;
+	iter.user_data = node;
+	iter.user_data2 = GINT_TO_POINTER (BRASERO_ROW_REGULAR);
+
+	path = brasero_track_data_cfg_node_to_path (self, node);
+
+	/* if the node is reloading (because of a file system change or because
+	 * it was a node that was a tmp folder) then no need to signal an added
+	 * signal but a changed one */
+	if (node->is_reloading) {
+		gtk_tree_model_row_changed (GTK_TREE_MODEL (self), path, &iter);
+		gtk_tree_path_free (path);
+		return;
+	}
+
+	/* Add the row itself */
+	/* This is a workaround for a warning in gailtreeview.c line 2946 where
+	 * gail uses the GtkTreePath and not a copy which if the node inserted
+	 * declares to have children and is not expanded leads to the path being
+	 * upped and therefore wrong. */
+	node->is_inserting = 1;
+	gtk_tree_model_row_inserted (GTK_TREE_MODEL (self),
+				     path,
+				     &iter);
+	node->is_inserting = 0;
+	gtk_tree_path_free (path);
+
+	parent = node->parent;
+	if (!parent->is_root) {
+		/* Tell the tree that the parent changed (since the number of children
+		 * changed as well). */
+		iter.user_data = parent;
+		path = brasero_track_data_cfg_node_to_path (self, parent);
+
+		gtk_tree_model_row_changed (GTK_TREE_MODEL (self), path, &iter);
+
+		/* 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) {
+			gtk_tree_path_append_index (path, 1);
+			gtk_tree_model_row_deleted (GTK_TREE_MODEL (self), path);
+		}
+
+		gtk_tree_path_free (path);
+	}
+
+	/* Now see if this is a directory which is empty and needs a BOGUS */
+	if (!node->is_file && !node->is_loading) {
+		/* emit child-toggled. Thanks to bogus rows we only need to emit
+		 * this signal once since a directory will always have a child
+		 * in the tree */
+		path = brasero_track_data_cfg_node_to_path (self, node);
+		gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (self), path, &iter);
+		gtk_tree_path_free (path);
+	}
+
+	/* we also have to set the is_visible property as all nodes added to 
+	 * root are always visible but ref_node is not necessarily called on
+	 * these nodes. */
+//	if (parent->is_root)
+//		node->is_visible = TRUE;
+}
+
+static void
+brasero_track_data_cfg_node_removed (BraseroDataProject *project,
+				     BraseroFileNode *former_parent,
+				     guint former_position,
+				     BraseroFileNode *node,
+				     BraseroTrackDataCfg *self)
+{
+	BraseroTrackDataCfgPrivate *priv;
+	GSList *iter, *next;
+	GtkTreePath *path;
+
+	priv = BRASERO_TRACK_DATA_CFG_PRIVATE (self);
+
+	/* 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) {
+		BraseroFileNode *tmp;
+
+		tmp = iter->data;
+		next = iter->next;
+		if (brasero_file_node_is_ancestor (node, tmp))
+			priv->shown = g_slist_remove (priv->shown, tmp);
+	}
+
+	/* See if the parent of this node still has children. If not we need to
+	 * 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)) {
+		GtkTreeIter iter;
+
+		iter.stamp = priv->stamp;
+		iter.user_data = former_parent;
+		iter.user_data2 = GINT_TO_POINTER (BRASERO_ROW_BOGUS);
+
+		path = brasero_track_data_cfg_node_to_path (self, former_parent);
+		gtk_tree_path_append_index (path, 1);
+
+		gtk_tree_model_row_inserted (GTK_TREE_MODEL (self), path, &iter);
+		gtk_tree_path_free (path);
+	}
+
+	/* remove the node. Do it after adding a possible BOGUS row.
+	 * NOTE since BOGUS row has been added move row. */
+	path = brasero_track_data_cfg_node_to_path (self, former_parent);
+	gtk_tree_path_append_index (path, former_position);
+
+	gtk_tree_model_row_deleted (GTK_TREE_MODEL (self), path);
+	gtk_tree_path_free (path);
+}
+
+static void
+brasero_track_data_cfg_node_changed (BraseroDataProject *project,
+				     BraseroFileNode *node,
+				     BraseroTrackDataCfg *self)
+{
+	BraseroTrackDataCfgPrivate *priv;
+	GtkTreePath *path;
+	GtkTreeIter iter;
+
+	priv = BRASERO_TRACK_DATA_CFG_PRIVATE (self);
+
+	/* Get the iter for the node */
+	iter.stamp = priv->stamp;
+	iter.user_data = node;
+	iter.user_data2 = GINT_TO_POINTER (BRASERO_ROW_REGULAR);
+
+	path = brasero_track_data_cfg_node_to_path (self, node);
+	gtk_tree_model_row_changed (GTK_TREE_MODEL (self),
+				    path,
+				    &iter);
+
+	/* Now see if this is a directory which is empty and needs a BOGUS */
+	if (!node->is_file) {
+		/* NOTE: No need to check for the number of children ... */
+
+		/* emit child-toggled. Thanks to bogus rows we only need to emit
+		 * this signal once since a directory will always have a child
+		 * in the tree */
+		gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (self),
+						      path,
+						      &iter);
+
+		/* The problem is that without that, the folder contents on disc
+		 * won't be added to the tree if the node it replaced was
+		 * already visible. */
+		if (node->is_imported
+		&&  node->is_visible
+		&&  node->is_fake)
+			brasero_data_session_load_directory_contents (BRASERO_DATA_SESSION (project),
+								      node,
+								      NULL);
+
+		/* add the row */
+		if (!BRASERO_FILE_NODE_CHILDREN (node))  {
+			iter.user_data2 = GINT_TO_POINTER (BRASERO_ROW_BOGUS);
+			gtk_tree_path_append_index (path, 0);
+
+			gtk_tree_model_row_inserted (GTK_TREE_MODEL (self),
+						     path,
+						     &iter);
+		}
+	}
+	gtk_tree_path_free (path);
+}
+
+static void
+brasero_track_data_cfg_node_reordered (BraseroDataProject *project,
+				       BraseroFileNode *parent,
+				       gint *new_order,
+				       BraseroTrackDataCfg *self)
+{
+	GtkTreePath *treepath;
+	BraseroTrackDataCfgPrivate *priv;
+
+	priv = BRASERO_TRACK_DATA_CFG_PRIVATE (self);
+
+	treepath = brasero_track_data_cfg_node_to_path (self, parent);
+	if (parent != brasero_data_project_get_root (project)) {
+		GtkTreeIter iter;
+
+		iter.stamp = priv->stamp;
+		iter.user_data = parent;
+		iter.user_data2 = GINT_TO_POINTER (BRASERO_ROW_REGULAR);
+
+		gtk_tree_model_rows_reordered (GTK_TREE_MODEL (self),
+					       treepath,
+					       &iter,
+					       new_order);
+	}
+	else
+		gtk_tree_model_rows_reordered (GTK_TREE_MODEL (self),
+					       treepath,
+					       NULL,
+					       new_order);
+
+	gtk_tree_path_free (treepath);
+}
+
+static void
+brasero_track_data_cfg_finalize (GObject *object)
+{
+	BraseroTrackDataCfgPrivate *priv;
+
+	priv = BRASERO_TRACK_DATA_CFG_PRIVATE (object);
+
+	if (priv->shown) {
+		g_slist_free (priv->shown);
+		priv->shown = NULL;
+	}
+
+	G_OBJECT_CLASS (brasero_track_data_cfg_parent_class)->finalize (object);
+}
+
+static void
+brasero_track_data_cfg_iface_init (gpointer g_iface, gpointer data)
+{
+	GtkTreeModelIface *iface = g_iface;
+	static gboolean initialized = FALSE;
+
+	if (initialized)
+		return;
+
+	initialized = TRUE;
+
+	iface->ref_node = brasero_track_data_cfg_node_shown;
+	iface->unref_node = brasero_track_data_cfg_node_hidden;
+
+	iface->get_flags = brasero_track_data_cfg_get_flags;
+	iface->get_n_columns = brasero_track_data_cfg_get_n_columns;
+	iface->get_column_type = brasero_track_data_cfg_get_column_type;
+	iface->get_iter = brasero_track_data_cfg_get_iter;
+	iface->get_path = brasero_track_data_cfg_get_path;
+	iface->get_value = brasero_track_data_cfg_get_value;
+	iface->iter_next = brasero_track_data_cfg_iter_next;
+	iface->iter_children = brasero_track_data_cfg_iter_children;
+	iface->iter_has_child = brasero_track_data_cfg_iter_has_child;
+	iface->iter_n_children = brasero_track_data_cfg_iter_n_children;
+	iface->iter_nth_child = brasero_track_data_cfg_iter_nth_child;
+	iface->iter_parent = brasero_track_data_cfg_iter_parent;
+}
+
+static void
+brasero_track_data_cfg_drag_source_iface_init (gpointer g_iface, gpointer data)
+{
+	GtkTreeDragSourceIface *iface = g_iface;
+	static gboolean initialized = FALSE;
+
+	if (initialized)
+		return;
+
+	initialized = TRUE;
+
+	iface->row_draggable = brasero_track_data_cfg_row_draggable;
+	iface->drag_data_get = brasero_track_data_cfg_drag_data_get;
+	iface->drag_data_delete = brasero_track_data_cfg_drag_data_delete;
+}
+
+static void
+brasero_track_data_cfg_drag_dest_iface_init (gpointer g_iface, gpointer data)
+{
+	GtkTreeDragDestIface *iface = g_iface;
+	static gboolean initialized = FALSE;
+
+	if (initialized)
+		return;
+
+	initialized = TRUE;
+
+	iface->drag_data_received = brasero_track_data_cfg_drag_data_received;
+	iface->row_drop_possible = brasero_track_data_cfg_row_drop_possible;
+}
+
+static void
+brasero_track_data_cfg_sortable_iface_init (gpointer g_iface, gpointer data)
+{
+	GtkTreeSortableIface *iface = g_iface;
+	static gboolean initialized = FALSE;
+
+	if (initialized)
+		return;
+
+	initialized = TRUE;
+
+	iface->get_sort_column_id = brasero_track_data_cfg_get_sort_column_id;
+	iface->set_sort_column_id = brasero_track_data_cfg_set_sort_column_id;
+	iface->has_default_sort_func = brasero_track_data_cfg_has_default_sort_func;
+}
+
+/**
+ * Track part
+ */
 
 gboolean
 brasero_track_data_cfg_add (BraseroTrackDataCfg *track,
@@ -65,35 +1488,52 @@ brasero_track_data_cfg_add (BraseroTrackDataCfg *track,
 
 	g_return_val_if_fail (BRASERO_TRACK_DATA_CFG (track), FALSE);
 	priv = BRASERO_TRACK_DATA_CFG_PRIVATE (track);
-	parent_node = brasero_data_tree_model_path_to_node (BRASERO_DATA_TREE_MODEL (priv->tree), parent);
+
+	if (priv->loading)
+		return FALSE;
+
+	parent_node = brasero_track_data_cfg_path_to_node (BRASERO_TRACK_DATA_CFG (priv->tree), parent);
 	return (brasero_data_project_add_loading_node (BRASERO_DATA_PROJECT (priv->tree), uri, parent_node) != NULL);
 }
 
-gboolean
+GtkTreePath *
 brasero_track_data_cfg_add_empty_directory (BraseroTrackDataCfg *track,
 					    const gchar *name,
 					    GtkTreePath *parent)
 {
 	BraseroTrackDataCfgPrivate *priv;
 	BraseroFileNode *parent_node;
+	BraseroFileNode *node;
 
 	g_return_val_if_fail (BRASERO_TRACK_DATA_CFG (track), FALSE);
 	priv = BRASERO_TRACK_DATA_CFG_PRIVATE (track);
-	parent_node = brasero_data_tree_model_path_to_node (BRASERO_DATA_TREE_MODEL (priv->tree), parent);
-	return (brasero_data_project_add_empty_directory (BRASERO_DATA_PROJECT (priv->tree), name, parent_node) != NULL);
+
+	if (priv->loading)
+		return NULL;
+
+	parent_node = brasero_track_data_cfg_path_to_node (BRASERO_TRACK_DATA_CFG (priv->tree), parent);
+	node = brasero_data_project_add_empty_directory (BRASERO_DATA_PROJECT (priv->tree), name, parent_node);
+	if (!node)
+		return NULL;
+
+	return brasero_track_data_cfg_node_to_path (track, node);
 }
 
-void
+gboolean
 brasero_track_data_cfg_remove (BraseroTrackDataCfg *track,
 			       GtkTreePath *treepath)
 {
 	BraseroTrackDataCfgPrivate *priv;
 	BraseroFileNode *node;
 
-	g_return_if_fail (BRASERO_TRACK_DATA_CFG (track));
+	g_return_val_if_fail (BRASERO_TRACK_DATA_CFG (track), FALSE);
 	priv = BRASERO_TRACK_DATA_CFG_PRIVATE (track);
-	node = brasero_data_tree_model_path_to_node (BRASERO_DATA_TREE_MODEL (priv->tree), treepath);
-	return brasero_data_project_remove_node (BRASERO_DATA_PROJECT (priv->tree), node);
+	if (priv->loading)
+		return FALSE;
+
+	node = brasero_track_data_cfg_path_to_node (BRASERO_TRACK_DATA_CFG (priv->tree), treepath);
+	brasero_data_project_remove_node (BRASERO_DATA_PROJECT (priv->tree), node);
+	return TRUE;
 }
 
 gboolean
@@ -106,58 +1546,86 @@ brasero_track_data_cfg_rename (BraseroTrackDataCfg *track,
 
 	g_return_val_if_fail (BRASERO_TRACK_DATA_CFG (track), FALSE);
 	priv = BRASERO_TRACK_DATA_CFG_PRIVATE (track);
-	node = brasero_data_tree_model_path_to_node (BRASERO_DATA_TREE_MODEL (priv->tree), treepath);
+	node = brasero_track_data_cfg_path_to_node (BRASERO_TRACK_DATA_CFG (priv->tree), treepath);
 	return brasero_data_project_rename_node (BRASERO_DATA_PROJECT (priv->tree),
 						 node,
 						 newname);
 }
 
-void
+gboolean
 brasero_track_data_cfg_reset (BraseroTrackDataCfg *track)
 {
 	BraseroTrackDataCfgPrivate *priv;
 
-	g_return_if_fail (BRASERO_TRACK_DATA_CFG (track));
+	g_return_val_if_fail (BRASERO_TRACK_DATA_CFG (track), FALSE);
 	priv = BRASERO_TRACK_DATA_CFG_PRIVATE (track);
+	if (priv->loading)
+		return FALSE;
+
+	priv->loading = 0;
 	brasero_data_project_reset (BRASERO_DATA_PROJECT (priv->tree));
+	return TRUE;
 }
 
-GSList *
-brasero_track_data_cfg_get_restored_uri (BraseroTrackDataCfg *track)
+GtkTreeModel *
+brasero_track_data_cfg_get_filtered_model (BraseroTrackDataCfg *track)
 {
 	BraseroTrackDataCfgPrivate *priv;
-	GSList *list = NULL;
+	GtkTreeModel *model;
 
 	g_return_val_if_fail (BRASERO_TRACK_DATA_CFG (track), NULL);
 	priv = BRASERO_TRACK_DATA_CFG_PRIVATE (track);
-	brasero_data_vfs_get_restored (BRASERO_DATA_VFS (priv->tree), &list);
-	return list;
+	model = GTK_TREE_MODEL (brasero_data_vfs_get_filtered_model (BRASERO_DATA_VFS (priv->tree)));
+	g_object_ref (model);
+	return model;
 }
 
 void
-brasero_track_data_cfg_exclude_uri (BraseroTrackDataCfg *track,
-				    const gchar *uri)
+brasero_track_data_cfg_restore (BraseroTrackDataCfg *track,
+				GtkTreePath *treepath)
 {
 	BraseroTrackDataCfgPrivate *priv;
+	BraseroFilteredUri *filtered;
+	gchar *uri;
 
 	g_return_if_fail (BRASERO_TRACK_DATA_CFG (track));
 	priv = BRASERO_TRACK_DATA_CFG_PRIVATE (track);
-	brasero_data_vfs_remove_restored (BRASERO_DATA_VFS (priv->tree), uri);
-	brasero_data_project_exclude_uri (BRASERO_DATA_PROJECT (priv->tree), uri);
+
+	filtered = brasero_data_vfs_get_filtered_model (BRASERO_DATA_VFS (priv->tree));
+	uri = brasero_filtered_uri_restore (filtered, treepath);
+
+	brasero_data_project_restore_uri (BRASERO_DATA_PROJECT (priv->tree), uri);
+	g_free (uri);
 }
 
 void
-brasero_track_data_cfg_restore_uri (BraseroTrackDataCfg *track,
-				    const gchar *uri)
+brasero_track_data_cfg_dont_filter_uri (BraseroTrackDataCfg *track,
+					const gchar *uri)
 {
 	BraseroTrackDataCfgPrivate *priv;
+	BraseroFilteredUri *filtered;
 
 	g_return_if_fail (BRASERO_TRACK_DATA_CFG (track));
 	priv = BRASERO_TRACK_DATA_CFG_PRIVATE (track);
-	brasero_data_vfs_add_restored (BRASERO_DATA_VFS (priv->tree), uri);
+
+	filtered = brasero_data_vfs_get_filtered_model (BRASERO_DATA_VFS (priv->tree));
+	brasero_filtered_uri_dont_filter (filtered, uri);
 	brasero_data_project_restore_uri (BRASERO_DATA_PROJECT (priv->tree), uri);
 }
 
+GSList *
+brasero_track_data_cfg_get_restored_list (BraseroTrackDataCfg *track)
+{
+	BraseroTrackDataCfgPrivate *priv;
+	BraseroFilteredUri *filtered;
+
+	g_return_val_if_fail (BRASERO_TRACK_DATA_CFG (track), NULL);
+	priv = BRASERO_TRACK_DATA_CFG_PRIVATE (track);
+
+	filtered = brasero_data_vfs_get_filtered_model (BRASERO_DATA_VFS (priv->tree));
+	return brasero_filtered_uri_get_restored_list (filtered);
+}
+
 gboolean
 brasero_track_data_cfg_load_medium (BraseroTrackDataCfg *track,
 				    BraseroMedium *medium,
@@ -202,15 +1670,24 @@ brasero_track_data_cfg_get_available_media (BraseroTrackDataCfg *track)
 	return brasero_data_session_get_available_media (BRASERO_DATA_SESSION (track));
 }
 
-GtkTreeModel *
-brasero_track_data_cfg_get_tree_model (BraseroTrackDataCfg *track)
+static BraseroBurnResult
+brasero_track_data_cfg_set_source (BraseroTrackData *track,
+				   GSList *grafts,
+				   GSList *excluded)
 {
 	BraseroTrackDataCfgPrivate *priv;
 
-	g_return_val_if_fail (BRASERO_IS_TRACK_DATA_CFG (track), NULL);
-
 	priv = BRASERO_TRACK_DATA_CFG_PRIVATE (track);
-	return GTK_TREE_MODEL (priv->tree);
+	if (!grafts)
+		return BRASERO_BURN_ERR;
+
+	priv->loading = brasero_data_project_load_contents (BRASERO_DATA_PROJECT (priv->tree),
+							    grafts,
+							    excluded);
+	if (!priv->loading)
+		return BRASERO_BURN_OK;
+
+	return BRASERO_BURN_NOT_READY;
 }
 
 static BraseroImageFS
@@ -326,17 +1803,32 @@ brasero_track_data_cfg_get_status (BraseroTrack *track,
 
 	priv = BRASERO_TRACK_DATA_CFG_PRIVATE (track);
 
+	if (priv->loading) {
+		brasero_status_set_not_ready (status,
+					      (gdouble) (priv->loading - priv->loading_remaining) / (gdouble) priv->loading,
+					      g_strdup (_("Analysing files")));
+		return BRASERO_BURN_NOT_READY;
+	}
+
 	/* This one goes before the next since a node may be loading but not
 	 * yet in the project and therefore project will look empty */
 	if (brasero_data_vfs_is_active (BRASERO_DATA_VFS (priv->tree))) {
 		if (status)
 			brasero_status_set_not_ready (status,
-						      -1,
+						      -1.0,
 						      g_strdup (_("Analysing files")));
 
 		return BRASERO_BURN_NOT_READY;
 	}
 
+	if (priv->load_errors) {
+
+		g_slist_foreach (priv->load_errors, (GFunc) g_free, NULL);
+		g_slist_free (priv->load_errors);
+		priv->load_errors = NULL;
+		return BRASERO_BURN_ERR;
+	}
+
 	if (brasero_data_project_is_empty (BRASERO_DATA_PROJECT (priv->tree)))
 		return BRASERO_BURN_ERR;
 
@@ -363,19 +1855,380 @@ brasero_track_data_cfg_get_size (BraseroTrack *track,
 	return BRASERO_BURN_OK;
 }
 
+static BraseroBurnResult
+brasero_track_data_cfg_image_uri_cb (BraseroDataVFS *vfs,
+				     const gchar *uri,
+				     BraseroTrackDataCfg *self)
+{
+	BraseroTrackDataCfgPrivate *priv;
+	BraseroBurnResult result;
+
+	priv = BRASERO_TRACK_DATA_CFG_PRIVATE (self);
+
+	if (priv->loading)
+		return BRASERO_BURN_OK;
+
+	g_signal_emit (self,
+		       brasero_track_data_cfg_signals [UNKNOWN],
+		       0,
+		       uri,
+		       &result);
+	return result;
+}
+
 static void
-brasero_track_data_cfg_init (BraseroTrackDataCfg *object)
+brasero_track_data_cfg_unreadable_uri_cb (BraseroDataVFS *vfs,
+					  const GError *error,
+					  const gchar *uri,
+					  BraseroTrackDataCfg *self)
 {
 	BraseroTrackDataCfgPrivate *priv;
 
-	priv = BRASERO_TRACK_DATA_CFG_PRIVATE (object);
-	priv->tree = brasero_data_tree_model_new ();
+	priv = BRASERO_TRACK_DATA_CFG_PRIVATE (self);
+
+	if (priv->loading) {
+		priv->load_errors = g_slist_prepend (priv->load_errors,
+						     g_strdup (error->message));
+
+		return;
+	}
+
+	g_signal_emit (self,
+		       brasero_track_data_cfg_signals [UNREADABLE],
+		       0,
+		       error,
+		       uri);
 }
 
 static void
-brasero_track_data_cfg_finalize (GObject *object)
+brasero_track_data_cfg_recursive_uri_cb (BraseroDataVFS *vfs,
+					 const gchar *uri,
+					 BraseroTrackDataCfg *self)
 {
-	G_OBJECT_CLASS (brasero_track_data_cfg_parent_class)->finalize (object);
+	BraseroTrackDataCfgPrivate *priv;
+
+	priv = BRASERO_TRACK_DATA_CFG_PRIVATE (self);
+
+	if (priv->loading) {
+		gchar *message;
+		gchar *name;
+
+		name = brasero_utils_get_uri_name (uri);
+		message = g_strdup_printf (_("\"%s\" is a recursive symlink."), name);
+		priv->load_errors = g_slist_prepend (priv->load_errors, message);
+		g_free (name);
+
+		return;
+	}
+	g_signal_emit (self,
+		       brasero_track_data_cfg_signals [RECURSIVE],
+		       0,
+		       uri);
+}
+
+static void
+brasero_track_data_cfg_unknown_uri_cb (BraseroDataVFS *vfs,
+				       const gchar *uri,
+				       BraseroTrackDataCfg *self)
+{
+	BraseroTrackDataCfgPrivate *priv;
+
+	priv = BRASERO_TRACK_DATA_CFG_PRIVATE (self);
+
+	if (priv->loading) {
+		gchar *message;
+		gchar *name;
+
+		name = brasero_utils_get_uri_name (uri);
+		message = g_strdup_printf (_("\"%s\" cannot be found."), name);
+		priv->load_errors = g_slist_prepend (priv->load_errors, message);
+		g_free (name);
+
+		return;
+	}
+	g_signal_emit (self,
+		       brasero_track_data_cfg_signals [UNKNOWN],
+		       0,
+		       uri);
+}
+
+static gboolean
+brasero_track_data_cfg_name_collision_cb (BraseroDataProject *project,
+					  const gchar *name,
+					  BraseroTrackDataCfg *self)
+{
+	BraseroTrackDataCfgPrivate *priv;
+	gboolean result;
+
+	priv = BRASERO_TRACK_DATA_CFG_PRIVATE (self);
+
+	if (priv->loading) {
+		/* don't do anything accept replacement */
+		return FALSE;
+	}
+
+	g_signal_emit (self,
+		       brasero_track_data_cfg_signals [NAME_COLLISION],
+		       0,
+		       name,
+		       &result);
+	return result;
+}
+
+static gboolean
+brasero_track_data_cfg_deep_directory (BraseroDataProject *project,
+				       const gchar *string,
+				       BraseroTrackDataCfg *self)
+{
+	BraseroTrackDataCfgPrivate *priv;
+	gboolean result;
+
+	priv = BRASERO_TRACK_DATA_CFG_PRIVATE (self);
+
+	if (priv->deep_directory)
+		return FALSE;
+
+	if (priv->loading) {
+		/* don't do anything just accept these directories from now on */
+		priv->deep_directory = TRUE;
+		return FALSE;
+	}
+
+	g_signal_emit (self,
+		       brasero_track_data_cfg_signals [DEEP_DIRECTORY],
+		       0,
+		       string,
+		       &result);
+
+	priv->deep_directory = result;
+	return result;
+}
+
+static gboolean
+brasero_track_data_cfg_2G_file (BraseroDataProject *project,
+				const gchar *string,
+				BraseroTrackDataCfg *self)
+{
+	BraseroTrackDataCfgPrivate *priv;
+	gboolean result;
+
+	priv = BRASERO_TRACK_DATA_CFG_PRIVATE (self);
+
+	/* This is to make sure we asked once */
+	if (priv->G2_files)
+		return FALSE;
+
+	if (priv->loading) {
+		/* don't do anything just accept these files from now on */
+		priv->G2_files = TRUE;
+		return FALSE;
+	}
+
+	g_signal_emit (self,
+		       brasero_track_data_cfg_signals [G2_FILE],
+		       0,
+		       string,
+		       &result);
+	priv->G2_files = result;
+	return result;
+}
+
+static void
+brasero_track_data_cfg_project_loaded (BraseroDataProject *project,
+				       gint loading,
+				       BraseroTrackDataCfg *self)
+{
+	BraseroTrackDataCfgPrivate *priv;
+
+	priv = BRASERO_TRACK_DATA_CFG_PRIVATE (self);
+
+	priv->loading_remaining = loading;
+	if (loading > 0) {
+		gdouble progress;
+
+		progress = (gdouble) (priv->loading - priv->loading_remaining) / (gdouble) priv->loading;
+		g_signal_emit (self,
+			       brasero_track_data_cfg_signals [SOURCE_LOADING],
+			       0,
+			       progress);
+		return;
+	}
+
+	priv->loading = 0;
+	g_signal_emit (self,
+		       brasero_track_data_cfg_signals [SOURCE_LOADED],
+		       0,
+		       priv->load_errors);
+}
+
+static void
+brasero_track_data_cfg_activity_changed (BraseroDataVFS *vfs,
+					 gboolean active,
+					 BraseroTrackDataCfg *self)
+{
+	GtkTreeIter iter;
+	GSList *nodes;
+	BraseroTrackDataCfgPrivate *priv;
+
+	if (brasero_data_vfs_is_active (vfs))
+		goto emit_signal;
+
+	priv = BRASERO_TRACK_DATA_CFG_PRIVATE (self);
+
+	iter.stamp = priv->stamp;
+	iter.user_data2 = GINT_TO_POINTER (BRASERO_ROW_REGULAR);
+
+	/* NOTE: we shouldn't need to use reference here as unref_node is used */
+	for (nodes = priv->shown; nodes; nodes = nodes->next) {
+		GtkTreePath *treepath;
+
+		iter.user_data = nodes->data;
+		treepath = brasero_track_data_cfg_node_to_path (self, nodes->data);
+		gtk_tree_model_row_changed (GTK_TREE_MODEL (self), treepath, &iter);
+		gtk_tree_path_free (treepath);
+	}
+
+emit_signal:
+
+	g_signal_emit (self,
+		       brasero_track_data_cfg_signals [ACTIVITY],
+		       0,
+		       active);
+}
+
+static void
+brasero_track_data_cfg_oversized_cb (BraseroDataProject *project,
+				     gboolean is_oversized,
+				     gboolean overburn_possible,
+				     BraseroTrackDataCfg *self)
+{
+	g_signal_emit (self,
+		       brasero_track_data_cfg_signals [OVERSIZE],
+		       0,
+		       is_oversized,
+		       overburn_possible);
+}
+
+static void
+brasero_track_data_cfg_size_changed_cb (BraseroDataProject *project,
+					BraseroTrackDataCfg *self)
+{
+	brasero_track_changed (BRASERO_TRACK (self));
+}
+
+static void
+brasero_track_data_cfg_session_available_cb (BraseroDataSession *session,
+					     BraseroMedium *medium,
+					     gboolean available,
+					     BraseroTrackDataCfg *self)
+{
+	g_signal_emit (self,
+		       brasero_track_data_cfg_signals [OVERSIZE],
+		       0,
+		       medium,
+		       available);
+}
+
+static void
+brasero_track_data_cfg_session_loaded_cb (BraseroDataSession *session,
+					  BraseroMedium *medium,
+					  gboolean loaded,
+					  BraseroTrackDataCfg *self)
+{
+	g_signal_emit (self,
+		       brasero_track_data_cfg_signals [OVERSIZE],
+		       0,
+		       medium,
+		       loaded);
+}
+
+static void
+brasero_track_data_cfg_init (BraseroTrackDataCfg *object)
+{
+	BraseroTrackDataCfgPrivate *priv;
+
+	priv = BRASERO_TRACK_DATA_CFG_PRIVATE (object);
+
+	priv->sort_column = GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID;
+	do {
+		priv->stamp = g_random_int ();
+	} while (!priv->stamp);
+
+	priv->theme = gtk_icon_theme_get_default ();
+
+	priv->tree = brasero_data_tree_model_new ();
+
+	g_signal_connect (priv->tree,
+			  "row-added",
+			  G_CALLBACK (brasero_track_data_cfg_node_added),
+			  object);
+	g_signal_connect (priv->tree,
+			  "row-changed",
+			  G_CALLBACK (brasero_track_data_cfg_node_changed),
+			  object);
+	g_signal_connect (priv->tree,
+			  "row-removed",
+			  G_CALLBACK (brasero_track_data_cfg_node_removed),
+			  object);
+	g_signal_connect (priv->tree,
+			  "rows-reordered",
+			  G_CALLBACK (brasero_track_data_cfg_node_reordered),
+			  object);
+
+	g_signal_connect (priv->tree,
+			  "oversize",
+			  G_CALLBACK (brasero_track_data_cfg_oversized_cb),
+			  object);
+	g_signal_connect (priv->tree,
+			  "size-changed",
+			  G_CALLBACK (brasero_track_data_cfg_size_changed_cb),
+			  object);
+
+	g_signal_connect (priv->tree,
+			  "session-available",
+			  G_CALLBACK (brasero_track_data_cfg_session_available_cb),
+			  object);
+	g_signal_connect (priv->tree,
+			  "session-loaded",
+			  G_CALLBACK (brasero_track_data_cfg_session_loaded_cb),
+			  object);
+	
+	g_signal_connect (priv->tree,
+			  "project-loaded",
+			  G_CALLBACK (brasero_track_data_cfg_project_loaded),
+			  object);
+	g_signal_connect (priv->tree,
+			  "vfs_activity",
+			  G_CALLBACK (brasero_track_data_cfg_activity_changed),
+			  object);
+	g_signal_connect (priv->tree,
+			  "deep-directory",
+			  G_CALLBACK (brasero_track_data_cfg_deep_directory),
+			  object);
+	g_signal_connect (priv->tree,
+			  "2G-file",
+			  G_CALLBACK (brasero_track_data_cfg_2G_file),
+			  object);
+	g_signal_connect (priv->tree,
+			  "unreadable-uri",
+			  G_CALLBACK (brasero_track_data_cfg_unknown_uri_cb),
+			  object);
+	g_signal_connect (priv->tree,
+			  "unknown-uri",
+			  G_CALLBACK (brasero_track_data_cfg_unreadable_uri_cb),
+			  object);
+	g_signal_connect (priv->tree,
+			  "recursive-sym",
+			  G_CALLBACK (brasero_track_data_cfg_recursive_uri_cb),
+			  object);
+	g_signal_connect (priv->tree,
+			  "image-uri",
+			  G_CALLBACK (brasero_track_data_cfg_image_uri_cb),
+			  object);
+	g_signal_connect (priv->tree,
+			  "name-collision",
+			  G_CALLBACK (brasero_track_data_cfg_name_collision_cb),
+			  object);
 }
 
 static void
@@ -393,9 +2246,159 @@ brasero_track_data_cfg_class_init (BraseroTrackDataCfgClass *klass)
 	track_class->get_type = brasero_track_data_cfg_get_track_type;
 	track_class->get_status = brasero_track_data_cfg_get_status;
 
+	parent_class->set_source = brasero_track_data_cfg_set_source;
+
 	parent_class->get_fs = brasero_track_data_cfg_get_fs;
 	parent_class->get_grafts = brasero_track_data_cfg_get_grafts;
 	parent_class->get_excluded = brasero_track_data_cfg_get_excluded;
 	parent_class->get_file_num = brasero_track_data_cfg_get_file_num;
+
+	brasero_track_data_cfg_signals [AVAILABLE] = 
+	    g_signal_new ("session_available",
+			  G_TYPE_FROM_CLASS (klass),
+			  G_SIGNAL_RUN_LAST,
+			  0,
+			  NULL, NULL,
+			  brasero_marshal_VOID__OBJECT_BOOLEAN,
+			  G_TYPE_NONE,
+			  2,
+			  G_TYPE_OBJECT,
+			  G_TYPE_BOOLEAN);
+	brasero_track_data_cfg_signals [LOADED] = 
+	    g_signal_new ("session_loaded",
+			  G_TYPE_FROM_CLASS (klass),
+			  G_SIGNAL_RUN_LAST,
+			  0,
+			  NULL, NULL,
+			  brasero_marshal_VOID__OBJECT_BOOLEAN,
+			  G_TYPE_NONE,
+			  2,
+			  G_TYPE_OBJECT,
+			  G_TYPE_BOOLEAN);
+	brasero_track_data_cfg_signals [OVERSIZE] = 
+	    g_signal_new ("session_oversized",
+			  G_TYPE_FROM_CLASS (klass),
+			  G_SIGNAL_RUN_LAST,
+			  0,
+			  NULL, NULL,
+			  brasero_marshal_VOID__BOOLEAN_BOOLEAN,
+			  G_TYPE_NONE,
+			  2,
+			  G_TYPE_BOOLEAN,
+			  G_TYPE_BOOLEAN);
+
+	brasero_track_data_cfg_signals [ACTIVITY] = 
+	    g_signal_new ("vfs_activity",
+			  G_TYPE_FROM_CLASS (klass),
+			  G_SIGNAL_RUN_FIRST|G_SIGNAL_NO_RECURSE,
+			  G_STRUCT_OFFSET (BraseroDataVFSClass,
+					   activity_changed),
+			  NULL, NULL,
+			  g_cclosure_marshal_VOID__BOOLEAN,
+			  G_TYPE_NONE,
+			  1,
+			  G_TYPE_BOOLEAN);
+
+	brasero_track_data_cfg_signals [IMAGE] = 
+	    g_signal_new ("image_uri",
+			  G_TYPE_FROM_CLASS (klass),
+			  G_SIGNAL_RUN_LAST|G_SIGNAL_NO_RECURSE,
+			  0,
+			  NULL, NULL,
+			  brasero_marshal_INT__STRING,
+			  G_TYPE_INT,
+			  1,
+			  G_TYPE_STRING);
+
+
+	brasero_track_data_cfg_signals [UNREADABLE] = 
+	    g_signal_new ("unreadable_uri",
+			  G_TYPE_FROM_CLASS (klass),
+			  G_SIGNAL_RUN_FIRST,
+			  0,
+			  NULL, NULL,
+			  brasero_marshal_VOID__POINTER_STRING,
+			  G_TYPE_NONE,
+			  2,
+			  G_TYPE_POINTER,
+			  G_TYPE_STRING);
+
+	brasero_track_data_cfg_signals [RECURSIVE] = 
+	    g_signal_new ("recursive_sym",
+			  G_TYPE_FROM_CLASS (klass),
+			  G_SIGNAL_RUN_FIRST,
+			  0,
+			  NULL, NULL,
+			  g_cclosure_marshal_VOID__STRING,
+			  G_TYPE_NONE,
+			  1,
+			  G_TYPE_STRING);
+
+	brasero_track_data_cfg_signals [UNKNOWN] = 
+	    g_signal_new ("unknown_uri",
+			  G_TYPE_FROM_CLASS (klass),
+			  G_SIGNAL_RUN_FIRST,
+			  0,
+			  NULL, NULL,
+			  g_cclosure_marshal_VOID__STRING,
+			  G_TYPE_NONE,
+			  1,
+			  G_TYPE_STRING);
+	brasero_track_data_cfg_signals [G2_FILE] = 
+	    g_signal_new ("2G_file",
+			  G_TYPE_FROM_CLASS (klass),
+			  G_SIGNAL_RUN_LAST|G_SIGNAL_NO_RECURSE,
+			  0,
+			  NULL, NULL,
+			  brasero_marshal_BOOLEAN__STRING,
+			  G_TYPE_BOOLEAN,
+			  1,
+			  G_TYPE_STRING);
+	brasero_track_data_cfg_signals [NAME_COLLISION] = 
+	    g_signal_new ("name_collision",
+			  G_TYPE_FROM_CLASS (klass),
+			  G_SIGNAL_RUN_LAST|G_SIGNAL_NO_RECURSE,
+			  0,
+			  NULL, NULL,
+			  brasero_marshal_BOOLEAN__STRING,
+			  G_TYPE_BOOLEAN,
+			  1,
+			  G_TYPE_STRING);
+	brasero_track_data_cfg_signals [DEEP_DIRECTORY] = 
+	    g_signal_new ("deep_directory",
+			  G_TYPE_FROM_CLASS (klass),
+			  G_SIGNAL_RUN_LAST|G_SIGNAL_NO_RECURSE,
+			  0,
+			  NULL, NULL,
+			  brasero_marshal_BOOLEAN__STRING,
+			  G_TYPE_BOOLEAN,
+			  1,
+			  G_TYPE_STRING);
+
+	brasero_track_data_cfg_signals [SOURCE_LOADING] = 
+	    g_signal_new ("source_loading",
+			  G_TYPE_FROM_CLASS (klass),
+			  G_SIGNAL_RUN_LAST|G_SIGNAL_NO_RECURSE,
+			  0,
+			  NULL, NULL,
+			  g_cclosure_marshal_VOID__DOUBLE,
+			  G_TYPE_NONE,
+			  1,
+			  G_TYPE_DOUBLE);
+	brasero_track_data_cfg_signals [SOURCE_LOADED] = 
+	    g_signal_new ("source_loaded",
+			  G_TYPE_FROM_CLASS (klass),
+			  G_SIGNAL_RUN_LAST|G_SIGNAL_NO_RECURSE,
+			  0,
+			  NULL, NULL,
+			  g_cclosure_marshal_VOID__POINTER,
+			  G_TYPE_NONE,
+			  1,
+			  G_TYPE_POINTER);
 }
 
+BraseroTrackDataCfg *
+brasero_track_data_cfg_new (void)
+{
+	return g_object_new (BRASERO_TYPE_TRACK_DATA_CFG, NULL);
+}
diff --git a/libbrasero-burn/brasero-track-data-cfg.h b/libbrasero-burn/brasero-track-data-cfg.h
index 4c7292e..fe422ec 100644
--- a/libbrasero-burn/brasero-track-data-cfg.h
+++ b/libbrasero-burn/brasero-track-data-cfg.h
@@ -33,10 +33,36 @@
 
 #include <glib-object.h>
 #include <gtk/gtk.h>
+
 #include <brasero-track-data.h>
 
 G_BEGIN_DECLS
 
+/**
+ * GtkTreeModel Part
+ */
+
+/* This DND target when moving nodes inside ourselves */
+#define BRASERO_DND_TARGET_DATA_TRACK_REFERENCE_LIST	"GTK_TREE_MODEL_ROW"
+
+typedef enum {
+	BRASERO_DATA_TREE_MODEL_NAME		= 0,
+	BRASERO_DATA_TREE_MODEL_URI,
+	BRASERO_DATA_TREE_MODEL_MIME_DESC,
+	BRASERO_DATA_TREE_MODEL_MIME_ICON,
+	BRASERO_DATA_TREE_MODEL_SIZE,
+	BRASERO_DATA_TREE_MODEL_SHOW_PERCENT,
+	BRASERO_DATA_TREE_MODEL_PERCENT,
+	BRASERO_DATA_TREE_MODEL_STYLE,
+	BRASERO_DATA_TREE_MODEL_COLOR,
+	BRASERO_DATA_TREE_MODEL_EDITABLE,
+	BRASERO_DATA_TREE_MODEL_IS_FILE,
+	BRASERO_DATA_TREE_MODEL_IS_LOADING,
+	BRASERO_DATA_TREE_MODEL_IS_IMPORTED,
+	BRASERO_DATA_TREE_MODEL_COL_NUM
+} BraseroTrackDataCfgColumn;
+
+
 #define BRASERO_TYPE_TRACK_DATA_CFG             (brasero_track_data_cfg_get_type ())
 #define BRASERO_TRACK_DATA_CFG(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), BRASERO_TYPE_TRACK_DATA_CFG, BraseroTrackDataCfg))
 #define BRASERO_TRACK_DATA_CFG_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), BRASERO_TYPE_TRACK_DATA_CFG, BraseroTrackDataCfgClass))
@@ -62,19 +88,16 @@ GType brasero_track_data_cfg_get_type (void) G_GNUC_CONST;
 BraseroTrackDataCfg *
 brasero_track_data_cfg_new (void);
 
-GtkTreeModel *
-brasero_track_data_cfg_get_tree_model (BraseroTrackDataCfg *track);
-
 gboolean
 brasero_track_data_cfg_add (BraseroTrackDataCfg *track,
 			    const gchar *uri,
 			    GtkTreePath *parent);
-gboolean
+GtkTreePath *
 brasero_track_data_cfg_add_empty_directory (BraseroTrackDataCfg *track,
 					    const gchar *name,
 					    GtkTreePath *parent);
 
-void
+gboolean
 brasero_track_data_cfg_remove (BraseroTrackDataCfg *track,
 			       GtkTreePath *treepath);
 gboolean
@@ -82,18 +105,9 @@ brasero_track_data_cfg_rename (BraseroTrackDataCfg *track,
 			       const gchar *newname,
 			       GtkTreePath *treepath);
 
-void
+gboolean
 brasero_track_data_cfg_reset (BraseroTrackDataCfg *track);
 
-void
-brasero_track_data_cfg_exclude_uri (BraseroTrackDataCfg *track,
-				    const gchar *uri);
-void
-brasero_track_data_cfg_restore_uri (BraseroTrackDataCfg *track,
-				    const gchar *uri);
-GSList *
-brasero_track_data_cfg_get_restored_uri (BraseroTrackDataCfg *track);
-
 gboolean
 brasero_track_data_cfg_load_medium (BraseroTrackDataCfg *track,
 				    BraseroMedium *medium,
@@ -107,6 +121,33 @@ brasero_track_data_cfg_get_current_medium (BraseroTrackDataCfg *track);
 GSList *
 brasero_track_data_cfg_get_available_media (BraseroTrackDataCfg *track);
 
+/**
+ * For filtered URIs tree model
+ */
+
+void
+brasero_track_data_cfg_dont_filter_uri (BraseroTrackDataCfg *track,
+					const gchar *uri);
+
+GSList *
+brasero_track_data_cfg_get_restored_list (BraseroTrackDataCfg *track);
+
+enum  {
+	BRASERO_FILTERED_STOCK_ID_COL,
+	BRASERO_FILTERED_URI_COL,
+	BRASERO_FILTERED_STATUS_COL,
+	BRASERO_FILTERED_FATAL_ERROR_COL,
+	BRASERO_FILTERED_NB_COL,
+};
+
+
+void
+brasero_track_data_cfg_restore (BraseroTrackDataCfg *track,
+				GtkTreePath *treepath);
+
+GtkTreeModel *
+brasero_track_data_cfg_get_filtered_model (BraseroTrackDataCfg *track);
+
 G_END_DECLS
 
 #endif /* _BRASERO_TRACK_DATA_CFG_H_ */
diff --git a/libbrasero-burn/brasero-track-data.c b/libbrasero-burn/brasero-track-data.c
index 7f3c2ae..149d3b3 100644
--- a/libbrasero-burn/brasero-track-data.c
+++ b/libbrasero-burn/brasero-track-data.c
@@ -81,9 +81,9 @@ brasero_graft_point_copy (BraseroGraftPt *graft)
 }
 
 BraseroBurnResult
-brasero_track_data_set_source (BraseroTrackData *track,
-			       GSList *grafts,
-			       GSList *unreadable)
+brasero_track_data_set_source_real (BraseroTrackData *track,
+				    GSList *grafts,
+				    GSList *unreadable)
 {
 	BraseroTrackDataPrivate *priv;
 
@@ -109,6 +109,19 @@ brasero_track_data_set_source (BraseroTrackData *track,
 }
 
 BraseroBurnResult
+brasero_track_data_set_source (BraseroTrackData *track,
+			       GSList *grafts,
+			       GSList *unreadable)
+{
+	BraseroTrackDataClass *klass;
+
+	g_return_val_if_fail (BRASERO_IS_TRACK_DATA (track), BRASERO_BURN_ERR);
+
+	klass = BRASERO_TRACK_DATA_CLASS (track);
+	return klass->set_source (track, grafts, unreadable);
+}
+
+BraseroBurnResult
 brasero_track_data_add_fs (BraseroTrackData *track,
 			   BraseroImageFS fstype)
 {
@@ -386,6 +399,8 @@ brasero_track_data_class_init (BraseroTrackDataClass *klass)
 	track_class->get_status = brasero_track_data_get_status;
 	track_class->get_size = brasero_track_data_get_size;
 
+	track_data_class->set_source = brasero_track_data_set_source_real;
+
 	track_data_class->get_fs = brasero_track_data_get_fs_real;
 	track_data_class->get_grafts = brasero_track_data_get_grafts_real;
 	track_data_class->get_excluded = brasero_track_data_get_excluded_real;
diff --git a/libbrasero-burn/brasero-track-data.h b/libbrasero-burn/brasero-track-data.h
index c647ade..3ace6cc 100644
--- a/libbrasero-burn/brasero-track-data.h
+++ b/libbrasero-burn/brasero-track-data.h
@@ -65,10 +65,13 @@ struct _BraseroTrackDataClass
 	BraseroTrackClass parent_class;
 
 	/* virtual functions */
-	BraseroImageFS	(*get_fs)		(BraseroTrackData *track);
-	GSList*		(*get_grafts)		(BraseroTrackData *track);
-	GSList*		(*get_excluded)		(BraseroTrackData *track);
-	guint64		(*get_file_num)		(BraseroTrackData *track);
+	BraseroBurnResult	(*set_source)		(BraseroTrackData *track,
+							 GSList *grafts,
+							 GSList *unreadable);
+	BraseroImageFS		(*get_fs)		(BraseroTrackData *track);
+	GSList*			(*get_grafts)		(BraseroTrackData *track);
+	GSList*			(*get_excluded)		(BraseroTrackData *track);
+	guint64			(*get_file_num)		(BraseroTrackData *track);
 };
 
 struct _BraseroTrackData
diff --git a/libbrasero-burn/libbrasero-marshal.list b/libbrasero-burn/libbrasero-marshal.list
index 83a5de2..63dee6b 100644
--- a/libbrasero-burn/libbrasero-marshal.list
+++ b/libbrasero-burn/libbrasero-marshal.list
@@ -6,6 +6,8 @@ INT:POINTER,BOOLEAN
 BOOLEAN:STRING
 VOID:INT,STRING
 VOID:POINTER,STRING
+VOID:POINTER,POINTER
 VOID:OBJECT,BOOLEAN
 VOID:BOOLEAN,BOOLEAN
 VOID:DOUBLE,DOUBLE,LONG
+VOID:POINTER,UINT,POINTER
diff --git a/libbrasero-utils/brasero-misc.c b/libbrasero-utils/brasero-misc.c
index 63919eb..30329e8 100644
--- a/libbrasero-utils/brasero-misc.c
+++ b/libbrasero-utils/brasero-misc.c
@@ -130,6 +130,60 @@ brasero_utils_init (void)
 	g_atexit (brasero_utils_free);
 }
 
+gchar*
+brasero_utils_validate_utf8 (const gchar *name)
+{
+	gchar *retval, *ptr;
+	const gchar *invalid;
+
+	if (!name)
+		return NULL;
+
+	if (g_utf8_validate (name, -1, &invalid))
+		return NULL;
+
+	retval = g_strdup (name);
+	ptr = retval + (invalid - name);
+	*ptr = '_';
+	ptr++;
+
+	while (!g_utf8_validate (ptr, -1, &invalid)) {
+		ptr = (gchar*) invalid;
+		*ptr = '?';
+		ptr ++;
+	}
+
+	return retval;
+}
+
+gchar *
+brasero_utils_get_uri_name (const gchar *uri)
+{
+	gchar *utf8_name;
+	GFile *vfs_uri;
+	gchar *name;
+
+	/* g_path_get_basename is not comfortable with uri related
+	 * to the root directory so check that before */
+	vfs_uri = g_file_new_for_uri (uri);
+	name = g_file_get_basename (vfs_uri);
+	g_object_unref (vfs_uri);
+
+	/* NOTE and reminder names are already unescaped; the following is not
+	 * needed: unescaped_name = g_uri_unescape_string (name, NULL); */
+
+	/* NOTE: a graft should be added for non utf8 name since we
+	 * modify them; in fact we use this function only in the next
+	 * one which creates only grafted nodes. */
+	utf8_name = brasero_utils_validate_utf8 (name);
+	if (utf8_name) {
+		g_free (name);
+		return utf8_name;
+	}
+
+	return name;
+}
+
 /**
  * Allows multiple uses of the same string
  */
@@ -318,32 +372,6 @@ brasero_utils_make_button (const gchar *text,
 	return button;
 }
 
-gchar*
-brasero_utils_validate_utf8 (const gchar *name)
-{
-	gchar *retval, *ptr;
-	const gchar *invalid;
-
-	if (!name)
-		return NULL;
-
-	if (g_utf8_validate (name, -1, &invalid))
-		return NULL;
-
-	retval = g_strdup (name);
-	ptr = retval + (invalid - name);
-	*ptr = '_';
-	ptr++;
-
-	while (!g_utf8_validate (ptr, -1, &invalid)) {
-		ptr = (gchar*) invalid;
-		*ptr = '?';
-		ptr ++;
-	}
-
-	return retval;
-}
-
 GtkWidget *
 brasero_utils_create_message_dialog (GtkWidget *parent,
 				     const gchar *primary_message,
diff --git a/libbrasero-utils/brasero-misc.h b/libbrasero-utils/brasero-misc.h
index a0be14d..37fdda3 100644
--- a/libbrasero-utils/brasero-misc.h
+++ b/libbrasero-utils/brasero-misc.h
@@ -75,6 +75,12 @@ brasero_utils_debug_message (const gchar *domain,
 	g_free (escaped_basename);						\
 }
 
+
+gchar *
+brasero_utils_get_uri_name (const gchar *uri);
+gchar*
+brasero_utils_validate_utf8 (const gchar *name);
+
 gchar *
 brasero_utils_register_string (const gchar *string);
 void
@@ -90,9 +96,6 @@ brasero_utils_make_button (const gchar *text,
 			   const gchar *theme,
 			   GtkIconSize size);
 
-gchar*
-brasero_utils_validate_utf8 (const gchar *name);
-
 GtkWidget *
 brasero_utils_create_message_dialog (GtkWidget *parent,
 				     const gchar *primary_message,
diff --git a/nautilus/nautilus-burn-extension.c b/nautilus/nautilus-burn-extension.c
index d6ecb11..20b991f 100644
--- a/nautilus/nautilus-burn-extension.c
+++ b/nautilus/nautilus-burn-extension.c
@@ -39,7 +39,7 @@
 
 #include "brasero-burn-lib.h"
 #include "brasero-track.h"
-#include "brasero-track-data.h"
+#include "brasero-track-data-cfg.h"
 #include "brasero-track-image-cfg.h"
 #include "brasero-track-disc.h"
 #include "brasero-session.h"
@@ -217,8 +217,7 @@ nautilus_disc_burn_is_empty (GtkWindow *toplevel)
 static void
 write_activate (GtkWindow *toplevel)
 {
-	BraseroTrackData	*track;
-	BraseroGraftPt		*graft;
+	BraseroTrackDataCfg	*track;
 	GtkWidget 		*name_options;
 	GtkWidget		*options;
 	gchar			*string;
@@ -226,19 +225,8 @@ write_activate (GtkWindow *toplevel)
 	if (nautilus_disc_burn_is_empty (toplevel))
 		return;
 
-	track = brasero_track_data_new ();
-
-	graft = g_new0 (BraseroGraftPt, 1);
-	graft->uri = g_strdup (BURN_URI);
-	brasero_track_data_set_source (track,
-				       g_slist_prepend (NULL, graft),
-				       NULL);
-
-	/* This should make a decent disc */
-	brasero_track_data_add_fs (track,
-				   BRASERO_IMAGE_FS_ISO|
-				   BRASERO_IMAGE_ISO_FS_LEVEL_3|
-				   BRASERO_IMAGE_ISO_FS_DEEP_DIRECTORY);
+	track = brasero_track_data_cfg_new ();
+	brasero_track_data_cfg_add (track, BURN_URI, NULL);
 
 	/* add name widget here to set the label of the volume */
 	name_options = brasero_project_name_new ();
diff --git a/src/brasero-data-disc.c b/src/brasero-data-disc.c
index ab08dba..5864c05 100644
--- a/src/brasero-data-disc.c
+++ b/src/brasero-data-disc.c
@@ -39,11 +39,6 @@
 #include "baobab-cell-renderer-progress.h"
 
 #include "brasero-data-disc.h"
-#include "brasero-file-node.h"
-#include "brasero-data-project.h"
-#include "brasero-data-vfs.h"
-#include "brasero-data-session.h"
-#include "brasero-data-tree-model.h"
 #include "brasero-file-filtered.h"
 #include "brasero-disc.h"
 #include "brasero-utils.h"
@@ -61,6 +56,7 @@
 #include "brasero-tags.h"
 #include "brasero-track.h"
 #include "brasero-track-data.h"
+#include "brasero-track-data-cfg.h"
 #include "brasero-session.h"
 
 #include "brasero-volume.h"
@@ -71,7 +67,7 @@ struct _BraseroDataDiscPrivate
 {
 	GtkWidget *tree;
 	GtkWidget *filter;
-	BraseroDataProject *project;
+	BraseroTrackDataCfg *project;
 	GtkWidget *notebook;
 
 	GtkWidget *message;
@@ -83,21 +79,18 @@ struct _BraseroDataDiscPrivate
 	gint press_start_x;
 	gint press_start_y;
 
-	BraseroFileNode *selected;
+	GtkTreeRowReference *selected;
 
 	GSList *load_errors;
 
 	gint size_changed_id;
 
-	guint loading;
-
 	guint editing:1;
 	guint reject_files:1;
 
 	guint overburning:1;
 
-	guint G2_files:1;
-	guint deep_directory:1;
+	guint loading:1;
 };
 
 #define BRASERO_DATA_DISC_PRIVATE(o)  (G_TYPE_INSTANCE_GET_PRIVATE ((o), BRASERO_TYPE_DATA_DISC, BraseroDataDiscPrivate))
@@ -164,13 +157,13 @@ enum {
 };
 
 static GtkTargetEntry ntables_cd [] = {
-	{BRASERO_DND_TARGET_SELF_FILE_NODES, GTK_TARGET_SAME_WIDGET, TREE_MODEL_ROW},
+	{BRASERO_DND_TARGET_DATA_TRACK_REFERENCE_LIST, GTK_TARGET_SAME_WIDGET, TREE_MODEL_ROW},
 	{"text/uri-list", 0, TARGET_URIS_LIST}
 };
 static guint nb_targets_cd = sizeof (ntables_cd) / sizeof (ntables_cd[0]);
 
 static GtkTargetEntry ntables_source [] = {
-	{BRASERO_DND_TARGET_SELF_FILE_NODES, GTK_TARGET_SAME_WIDGET, TREE_MODEL_ROW},
+	{BRASERO_DND_TARGET_DATA_TRACK_REFERENCE_LIST, GTK_TARGET_SAME_WIDGET, TREE_MODEL_ROW},
 };
 
 static guint nb_targets_source = sizeof (ntables_source) / sizeof (ntables_source[0]);
@@ -198,7 +191,7 @@ brasero_data_disc_get_loaded_medium (BraseroDataDisc *self)
 {
 	BraseroDataDiscPrivate *priv;
 	priv = BRASERO_DATA_DISC_PRIVATE (self);
-	return brasero_data_session_get_loaded_medium (BRASERO_DATA_SESSION (priv->project));
+	return brasero_track_data_cfg_get_current_medium (priv->project);
 }
 
 /**
@@ -227,7 +220,7 @@ brasero_data_disc_import_session (BraseroDataDisc *disc,
 	if (import) {
 		GError *error = NULL;
 
-		if (!brasero_data_session_add_last (BRASERO_DATA_SESSION (priv->project), medium, &error)) {
+		if (!brasero_track_data_cfg_load_medium (priv->project, medium, &error)) {
 			brasero_data_disc_import_failure_dialog (disc, error);
 			return FALSE;
 		}
@@ -236,7 +229,7 @@ brasero_data_disc_import_session (BraseroDataDisc *disc,
 		return TRUE;
 	}
 
-	brasero_data_session_remove_last (BRASERO_DATA_SESSION (priv->project));
+	brasero_track_data_cfg_unload_current_medium (priv->project);
 	return FALSE;
 }
 
@@ -267,43 +260,52 @@ brasero_data_disc_import_session_cb (GtkToggleAction *action,
 	}
 }
 
-static BraseroFileNode *
+static GtkTreePath *
 brasero_data_disc_get_parent (BraseroDataDisc *self)
 {
 	BraseroDataDiscPrivate *priv;
 	GtkTreeSelection *selection;
-	BraseroFileNode *parent;
 	GtkTreePath *treepath;
-	GtkTreeModel *sort;
+	gboolean is_loading;
+	gboolean is_file;
+	GtkTreeIter iter;
 	GList *list;
 
 	priv = BRASERO_DATA_DISC_PRIVATE (self);
 
 	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->tree));
-	list = gtk_tree_selection_get_selected_rows (selection, &sort);
+	list = gtk_tree_selection_get_selected_rows (selection, NULL);
 
-	if (g_list_length (list) > 1) {
+	if (g_list_length (list) != 1) {
 		g_list_foreach (list, (GFunc) gtk_tree_path_free, NULL);
 		g_list_free (list);
-		return brasero_data_project_get_root (priv->project);
+		return gtk_tree_path_new_first ();
 	}
 
-	if (!list)
-		return brasero_data_project_get_root (priv->project);
-
 	treepath = list->data;
 	g_list_free (list);
 
-	parent = brasero_data_tree_model_path_to_node (BRASERO_DATA_TREE_MODEL (priv->project), treepath);
-	gtk_tree_path_free (treepath);
+	gtk_tree_model_get_iter (GTK_TREE_MODEL (priv->project), &iter, treepath);
 
-	if (parent->is_loading)
-		return brasero_data_project_get_root (priv->project);
+	gtk_tree_model_get (GTK_TREE_MODEL (priv->project), &iter,
+			    BRASERO_DATA_TREE_MODEL_IS_LOADING, &is_loading,
+			    -1);
 
-	if (parent->is_file)
-		parent = parent->parent;
+	if (is_loading) {
+		gtk_tree_path_free (treepath);
+		return gtk_tree_path_new_first ();
+	}
 
-	return parent;
+	gtk_tree_model_get (GTK_TREE_MODEL (priv->project), &iter,
+			    BRASERO_DATA_TREE_MODEL_IS_FILE, &is_file,
+			    -1);
+
+	if (is_file && !gtk_tree_path_up (treepath)) {
+		gtk_tree_path_free (treepath);
+		treepath = gtk_tree_path_new_first ();
+	}
+
+	return treepath;
 }
 
 static void
@@ -311,13 +313,14 @@ brasero_data_disc_new_folder_clicked_cb (GtkButton *button,
 					 BraseroDataDisc *disc)
 {
 	BraseroDataDiscPrivate *priv;
-	BraseroFileNode *parent;
-	BraseroFileNode *node;
+	GtkTreeViewColumn *column;
+	GtkTreePath *treepath;
+	GtkTreePath *parent;
 	gchar *name;
 	gint nb;
 
 	priv = BRASERO_DATA_DISC_PRIVATE (disc);
-	if (priv->loading || priv->reject_files)
+	if (priv->reject_files)
 		return;
 
 	parent = brasero_data_disc_get_parent (disc);
@@ -326,40 +329,34 @@ brasero_data_disc_new_folder_clicked_cb (GtkButton *button,
 
 newname:
 
-	if (brasero_file_node_check_name_existence (parent, name)) {
+	/* just to make sure that tree is not hidden behind info */
+	treepath = brasero_track_data_cfg_add_empty_directory (BRASERO_TRACK_DATA_CFG (priv->project), name, parent);
+	if (!treepath) {
 		g_free (name);
 		name = g_strdup_printf (_("New folder %i"), nb);
 		nb++;
 		goto newname;
 	}
 
-	/* just to make sure that tree is not hidden behind info */
 	gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), 1);
-	node = brasero_data_project_add_empty_directory (priv->project, name, parent);
-	if (node) {
-		GtkTreePath *treepath;
-		GtkTreeViewColumn *column;
 
-		/* grab focus must be called before next function to avoid
-		 * triggering a bug where if pointer is not in the widget 
-		 * any more and enter is pressed the cell will remain editable */
-		column = gtk_tree_view_get_column (GTK_TREE_VIEW (priv->tree), 0);
-		gtk_widget_grab_focus (priv->tree);
-
-		treepath = brasero_data_tree_model_node_to_path (BRASERO_DATA_TREE_MODEL (priv->project), node);
-		gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->tree),
-					  treepath,
-					  column,
-					  TRUE);
-		gtk_tree_path_free (treepath);
-	}
+	/* grab focus must be called before next function to avoid
+	 * triggering a bug where if pointer is not in the widget 
+	 * any more and enter is pressed the cell will remain editable */
+	column = gtk_tree_view_get_column (GTK_TREE_VIEW (priv->tree), 0);
+	gtk_widget_grab_focus (priv->tree);
 
+	gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->tree),
+				  treepath,
+				  column,
+				  TRUE);
+	gtk_tree_path_free (treepath);
 	g_free (name);
 }
 
 struct _BraseroClipData {
 	BraseroDataDisc *disc;
-	guint reference;
+	GtkTreeRowReference *reference;
 };
 typedef struct _BraseroClipData BraseroClipData;
 
@@ -368,15 +365,15 @@ brasero_data_disc_clipboard_text_cb (GtkClipboard *clipboard,
 				     const char *text,
 				     BraseroClipData *data)
 {
-	BraseroFileNode *parent = NULL;
 	BraseroDataDiscPrivate *priv;
+	GtkTreePath *parent = NULL;
 	gchar **array;
 	gchar **item;
 
 	priv = BRASERO_DATA_DISC_PRIVATE (data->disc);
 
 	if (data->reference)
-		parent = brasero_data_project_reference_get (priv->project, data->reference);
+		parent = gtk_tree_row_reference_get_path (data->reference);
 
 	array = g_strsplit_set (text, "\n\r", 0);
 	item = array;
@@ -389,9 +386,9 @@ brasero_data_disc_clipboard_text_cb (GtkClipboard *clipboard,
 			uri = g_file_get_uri (file);
 			g_object_unref (file);
 
-			brasero_data_project_add_loading_node (priv->project,
-							       uri,
-							       parent);
+			brasero_track_data_cfg_add (BRASERO_TRACK_DATA_CFG (priv->project),
+						    uri,
+						    parent);
 
 			/* NOTE: no need to care about the notebook page since 
 			 * to reach this part the tree should be displayed first
@@ -403,7 +400,7 @@ brasero_data_disc_clipboard_text_cb (GtkClipboard *clipboard,
 	g_strfreev (array);
 
 	if (data->reference)
-		brasero_data_project_reference_free (priv->project, data->reference);
+		gtk_tree_row_reference_free (data->reference);
 
 	g_free (data);
 }
@@ -440,7 +437,7 @@ brasero_data_disc_clipboard_targets_cb (GtkClipboard *clipboard,
 	}
 
 	if (data->reference)
-		brasero_data_project_reference_free (priv->project, data->reference);
+		gtk_tree_row_reference_free (data->reference);
 
 	g_free (data);
 }
@@ -451,8 +448,8 @@ brasero_data_disc_paste_activated_cb (GtkAction *action,
 {
 	BraseroDataDiscPrivate *priv;
 	GtkClipboard *clipboard;
-	BraseroFileNode *parent;
 	BraseroClipData *data;
+	GtkTreePath *parent;
 
 	priv = BRASERO_DATA_DISC_PRIVATE (disc);
 
@@ -463,7 +460,7 @@ brasero_data_disc_paste_activated_cb (GtkAction *action,
 
 	parent = brasero_data_disc_get_parent (disc);
 	if (parent)
-		data->reference = brasero_data_project_reference_new (priv->project, parent);
+		data->reference = gtk_tree_row_reference_new (GTK_TREE_MODEL (priv->project), parent);
 
 	clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
 	gtk_clipboard_request_targets (clipboard,
@@ -504,9 +501,9 @@ brasero_data_disc_name_edited_cb (GtkCellRendererText *cellrenderertext,
 				  BraseroDataDisc *self)
 {
 	BraseroDataDiscPrivate *priv;
-	BraseroFileNode *node;
 	GtkTreePath *path;
 	GtkTreeIter row;
+	gchar *name;
 
 	priv = BRASERO_DATA_DISC_PRIVATE (self);
 
@@ -521,17 +518,21 @@ brasero_data_disc_name_edited_cb (GtkCellRendererText *cellrenderertext,
 		return;
 	}
 
-	node = brasero_data_tree_model_path_to_node (BRASERO_DATA_TREE_MODEL (priv->project), path);
-	gtk_tree_path_free (path);
-
 	/* make sure it actually changed */
-	if (!strcmp (BRASERO_FILE_NODE_NAME (node), text))
+	gtk_tree_model_get (GTK_TREE_MODEL (priv->project), &row,
+			    BRASERO_DATA_TREE_MODEL_NAME, &name,
+			    -1);
+
+	if (name && !strcmp (name, text)) {
+		gtk_tree_path_free (path);
 		return;
+	}
 
 	/* NOTE: BraseroDataProject is where we handle name collisions,
 	 * UTF-8 validity, ...
 	 * Here if there is a name collision then rename gets aborted. */
-	brasero_data_project_rename_node (priv->project, node, text);
+	brasero_track_data_cfg_rename (BRASERO_TRACK_DATA_CFG (priv->project), text, path);
+	gtk_tree_path_free (path);
 }
 
 /**
@@ -539,41 +540,6 @@ brasero_data_disc_name_edited_cb (GtkCellRendererText *cellrenderertext,
  */
 
 static void
-brasero_data_disc_set_expand_state (BraseroDataDisc *self,
-				    GtkTreePath *treepath,
-				    gboolean expanded)
-{
-	BraseroDataDiscPrivate *priv;
-	BraseroFileNode *node;
-
-	priv = BRASERO_DATA_DISC_PRIVATE (self);
-
-	/* only directories can be collapsed */
-	node = brasero_data_tree_model_path_to_node (BRASERO_DATA_TREE_MODEL (priv->project), treepath);
-
-	if (node)
-		node->is_expanded = expanded;
-}
-
-static void
-brasero_data_disc_row_collapsed_cb (GtkTreeView *tree,
-				    GtkTreeIter *sortparent,
-				    GtkTreePath *sortpath,
-				    BraseroDataDisc *self)
-{
-	brasero_data_disc_set_expand_state (self, sortpath, FALSE);
-}
-
-static void
-brasero_data_disc_row_expanded_cb (GtkTreeView *tree,
-				   GtkTreeIter *parent,
-				   GtkTreePath *treepath,
-				   BraseroDataDisc *self)
-{
-	brasero_data_disc_set_expand_state (self, treepath, TRUE);
-}
-
-static void
 brasero_data_disc_use_overburn_response_cb (GtkButton *button,
 					    GtkResponseType response,
 					    BraseroDataDisc *self)
@@ -589,7 +555,7 @@ brasero_data_disc_use_overburn_response_cb (GtkButton *button,
 }
 
 static void
-brasero_data_disc_project_oversized_cb (BraseroDataProject *project,
+brasero_data_disc_project_oversized_cb (BraseroTrackDataCfg *project,
 					gboolean oversized,
 					gboolean overburn,
 					BraseroDataDisc *self)
@@ -644,28 +610,40 @@ brasero_data_disc_project_oversized_cb (BraseroDataProject *project,
 }
 
 static void
-brasero_data_disc_project_loaded_cb (BraseroDataProject *project,
-				     gint loading,
-				     BraseroDataDisc *self)
+brasero_data_disc_project_loading_cb (BraseroTrackDataCfg *project,
+				      gdouble progress,
+				      BraseroDataDisc *self)
 {
 	BraseroDataDiscPrivate *priv;
 	GtkWidget *message;
 
 	priv = BRASERO_DATA_DISC_PRIVATE (self);
+	priv->loading = TRUE;
 
 	message = brasero_notify_get_message_by_context_id (BRASERO_NOTIFY (priv->message), BRASERO_NOTIFY_CONTEXT_LOADING);
 	if (!message)
 		return;
 
-	if (loading > 0) {
-		/* we're not done yet update progress. */
-		brasero_disc_message_set_progress (BRASERO_DISC_MESSAGE (message),
-						   (gdouble) (priv->loading - loading) / (gdouble) priv->loading);
+	/* we're not done yet update progress. */
+	brasero_disc_message_set_progress (BRASERO_DISC_MESSAGE (message), progress);
+}
+
+static void
+brasero_data_disc_project_loaded_cb (BraseroTrackDataCfg *project,
+				     GSList *errors,
+				     BraseroDataDisc *self)
+{
+	BraseroDataDiscPrivate *priv;
+	GtkWidget *message;
+
+	priv = BRASERO_DATA_DISC_PRIVATE (self);
+	priv->loading = FALSE;
+
+	message = brasero_notify_get_message_by_context_id (BRASERO_NOTIFY (priv->message), BRASERO_NOTIFY_CONTEXT_LOADING);
+	if (!message)
 		return;
-	}
 
-	priv->loading = 0;
-	if (priv->load_errors) {
+	if (errors) {
 		brasero_disc_message_remove_buttons (BRASERO_DISC_MESSAGE (message));
 
 		brasero_disc_message_set_primary (BRASERO_DISC_MESSAGE (message),
@@ -701,7 +679,7 @@ brasero_data_disc_project_loaded_cb (BraseroDataProject *project,
 }
 
 static void
-brasero_data_disc_activity_changed_cb (BraseroDataVFS *vfs,
+brasero_data_disc_activity_changed_cb (BraseroTrackDataCfg *vfs,
 				       gboolean active,
 				       BraseroDataDisc *self)
 {
@@ -723,23 +701,8 @@ brasero_data_disc_activity_changed_cb (BraseroDataVFS *vfs,
 		gdk_window_set_cursor (GTK_WIDGET (self)->window, NULL);
 }
 
-static void
-brasero_data_disc_filtered_uri_cb (BraseroDataVFS *vfs,
-				   BraseroFilterStatus status,
-				   const gchar *uri,
-				   BraseroDataDisc *self)
-{
-	BraseroDataDiscPrivate *priv;
-
-	priv = BRASERO_DATA_DISC_PRIVATE (self);
-	if (status != BRASERO_FILTER_NONE)
-		brasero_file_filtered_add (BRASERO_FILE_FILTERED (priv->filter), uri, status);
-	else
-		brasero_file_filtered_remove (BRASERO_FILE_FILTERED (priv->filter), uri);
-}
-
 static BraseroBurnResult
-brasero_data_disc_image_uri_cb (BraseroDataVFS *vfs,
+brasero_data_disc_image_uri_cb (BraseroTrackDataCfg *vfs,
 				const gchar *uri,
 				BraseroDataDisc *self)
 {
@@ -753,10 +716,7 @@ brasero_data_disc_image_uri_cb (BraseroDataVFS *vfs,
 
 	priv = BRASERO_DATA_DISC_PRIVATE (self);
 
-	if (priv->loading)
-		return BRASERO_BURN_OK;
-
-	name = brasero_file_node_get_uri_name (uri);
+	name = brasero_utils_get_uri_name (uri);
 	string = g_strdup_printf (_("Do you want to burn \"%s\" to a disc or add it in to the data project?"), name);
 	dialog = brasero_app_dialog (brasero_app_get_default (),
 				     string,
@@ -787,7 +747,7 @@ brasero_data_disc_image_uri_cb (BraseroDataVFS *vfs,
 		return BRASERO_BURN_OK;
 
 	/* Tell project manager to switch. First function to avoid warnings */
-	brasero_data_project_reset (priv->project);
+	brasero_track_data_cfg_reset (priv->project);
 	manager = brasero_app_get_project_manager (brasero_app_get_default ());
 	brasero_project_manager_iso (BRASERO_PROJECT_MANAGER (manager), uri);
 
@@ -809,32 +769,7 @@ brasero_data_disc_filter_expanded_cb (GtkExpander *expander,
 }
 
 static void
-brasero_data_disc_filtered_file_cb (BraseroFileFiltered *filter,
-				    const gchar *uri,
-				    BraseroDataDisc *self)
-{
-	BraseroDataDiscPrivate *priv;
-
-	priv = BRASERO_DATA_DISC_PRIVATE (self);
-	brasero_data_vfs_remove_restored (BRASERO_DATA_VFS (priv->project), uri);
-	brasero_data_project_exclude_uri (BRASERO_DATA_PROJECT (priv->project), uri);
-}
-
-static void
-brasero_data_disc_restored_file_cb (BraseroFileFiltered *filter,
-				    const gchar *uri,
-				    BraseroDataDisc *self)
-{
-	BraseroDataDiscPrivate *priv;
-
-	priv = BRASERO_DATA_DISC_PRIVATE (self);
-
-	brasero_data_vfs_add_restored (BRASERO_DATA_VFS (priv->project), uri);
-	brasero_data_project_restore_uri (BRASERO_DATA_PROJECT (priv->project), uri);
-}
-
-static void
-brasero_data_disc_unreadable_uri_cb (BraseroDataVFS *vfs,
+brasero_data_disc_unreadable_uri_cb (BraseroTrackDataCfg *vfs,
 				     const GError *error,
 				     const gchar *uri,
 				     BraseroDataDisc *self)
@@ -845,14 +780,7 @@ brasero_data_disc_unreadable_uri_cb (BraseroDataVFS *vfs,
 
 	priv = BRASERO_DATA_DISC_PRIVATE (self);
 
-	name = brasero_file_node_get_uri_name (uri);
-	if (priv->loading) {
-		priv->load_errors = g_slist_prepend (priv->load_errors,
-						     g_strdup (error->message));
-
-		return;
-	}
-
+	name = brasero_utils_get_uri_name (uri);
 	primary = g_strdup_printf (_("\"%s\" cannot be added to the selection."), name);
 	brasero_app_alert (brasero_app_get_default (),
 			   primary,
@@ -863,7 +791,7 @@ brasero_data_disc_unreadable_uri_cb (BraseroDataVFS *vfs,
 }
 
 static void
-brasero_data_disc_recursive_uri_cb (BraseroDataVFS *vfs,
+brasero_data_disc_recursive_uri_cb (BraseroTrackDataCfg *vfs,
 				    const gchar *uri,
 				    BraseroDataDisc *self)
 {
@@ -873,17 +801,7 @@ brasero_data_disc_recursive_uri_cb (BraseroDataVFS *vfs,
 
 	priv = BRASERO_DATA_DISC_PRIVATE (self);
 
-	name = brasero_file_node_get_uri_name (uri);
-	if (priv->loading) {
-		gchar *message;
-
-		message = g_strdup_printf (_("\"%s\" is a recursive symlink."), name);
-		priv->load_errors = g_slist_prepend (priv->load_errors, message);
-		g_free (name);
-
-		return;
-	}
-
+	name = brasero_utils_get_uri_name (uri);
 	primary = g_strdup_printf (_("\"%s\" cannot be added to the selection."), name);
 	brasero_app_alert (brasero_app_get_default (),
 			   primary,
@@ -894,7 +812,7 @@ brasero_data_disc_recursive_uri_cb (BraseroDataVFS *vfs,
 }
 
 static void
-brasero_data_disc_unknown_uri_cb (BraseroDataVFS *vfs,
+brasero_data_disc_unknown_uri_cb (BraseroTrackDataCfg *vfs,
 				  const gchar *uri,
 				  BraseroDataDisc *self)
 {
@@ -904,17 +822,7 @@ brasero_data_disc_unknown_uri_cb (BraseroDataVFS *vfs,
 
 	priv = BRASERO_DATA_DISC_PRIVATE (self);
 
-	name = brasero_file_node_get_uri_name (uri);
-	if (priv->loading) {
-		gchar *message;
-
-		message = g_strdup_printf (_("\"%s\" cannot be found."), name);
-		priv->load_errors = g_slist_prepend (priv->load_errors, message);
-		g_free (name);
-
-		return;
-	}
-
+	name = brasero_utils_get_uri_name (uri);
 	primary = g_strdup_printf (_("\"%s\" cannot be added to the selection."), name);
 	brasero_app_alert (brasero_app_get_default (),
 			   primary,
@@ -925,7 +833,7 @@ brasero_data_disc_unknown_uri_cb (BraseroDataVFS *vfs,
 }
 
 static gboolean
-brasero_data_disc_name_collision_cb (BraseroDataProject *project,
+brasero_data_disc_name_collision_cb (BraseroTrackDataCfg *project,
 				     const gchar *name,
 				     BraseroDataDisc *self)
 {
@@ -936,11 +844,6 @@ brasero_data_disc_name_collision_cb (BraseroDataProject *project,
 
 	priv = BRASERO_DATA_DISC_PRIVATE (self);
 
-	if (priv->loading) {
-		/* don't do anything accept replacement */
-		return FALSE;
-	}
-
 	string = g_strdup_printf (_("Do you really want to replace \"%s\"?"), name);
 	dialog = brasero_app_dialog (brasero_app_get_default (),
 				     string,
@@ -964,7 +867,7 @@ brasero_data_disc_name_collision_cb (BraseroDataProject *project,
 }
 
 static gboolean
-brasero_data_disc_2G_file_cb (BraseroDataProject *project,
+brasero_data_disc_2G_file_cb (BraseroTrackDataCfg *project,
 			      const gchar *name,
 			      BraseroDataDisc *self)
 {
@@ -975,15 +878,6 @@ brasero_data_disc_2G_file_cb (BraseroDataProject *project,
 
 	priv = BRASERO_DATA_DISC_PRIVATE (self);
 
-	if (priv->G2_files)
-		return FALSE;
-
-	if (priv->loading) {
-		/* don't do anything just accept these files from now on */
-		priv->G2_files = TRUE;
-		return FALSE;
-	}
-
 	string = g_strdup_printf (_("Do you really want to add \"%s\" to the selection and use the third version of ISO9660 standard to support it?"), name);
 	dialog = brasero_app_dialog (brasero_app_get_default (),
 				     string,
@@ -1003,12 +897,11 @@ brasero_data_disc_2G_file_cb (BraseroDataProject *project,
 	answer = gtk_dialog_run (GTK_DIALOG (dialog));
 	gtk_widget_destroy (dialog);
 
-	priv->G2_files = (answer == GTK_RESPONSE_YES);
 	return (answer != GTK_RESPONSE_YES);
 }
 
 static gboolean
-brasero_data_disc_deep_directory_cb (BraseroDataProject *project,
+brasero_data_disc_deep_directory_cb (BraseroTrackDataCfg *project,
 				     const gchar *name,
 				     BraseroDataDisc *self)
 {
@@ -1019,15 +912,6 @@ brasero_data_disc_deep_directory_cb (BraseroDataProject *project,
 
 	priv = BRASERO_DATA_DISC_PRIVATE (self);
 
-	if (priv->deep_directory)
-		return FALSE;
-
-	if (priv->loading) {
-		/* don't do anything just accept these directories from now on */
-		priv->deep_directory = TRUE;
-		return FALSE;
-	}
-
 	string = g_strdup_printf (_("Do you really want to add \"%s\" to the selection?"), name);
 	dialog = brasero_app_dialog (brasero_app_get_default (),
 				     string,
@@ -1047,29 +931,30 @@ brasero_data_disc_deep_directory_cb (BraseroDataProject *project,
 	answer = gtk_dialog_run (GTK_DIALOG (dialog));
 	gtk_widget_destroy (dialog);
 
-	priv->deep_directory = (answer == GTK_RESPONSE_YES);
 	return (answer != GTK_RESPONSE_YES);
 }
 
 static gboolean
 brasero_data_disc_size_changed (gpointer user_data)
 {
-	gint64 size;
+	gint64 bytes;
 	BraseroDataDisc *self;
 	BraseroDataDiscPrivate *priv;
 
 	self = BRASERO_DATA_DISC (user_data);
 	priv = BRASERO_DATA_DISC_PRIVATE (self);
 
-	size = brasero_data_project_get_size (BRASERO_DATA_PROJECT (priv->project));
-	brasero_disc_size_changed (BRASERO_DISC (self), size);
+	brasero_track_get_size (BRASERO_TRACK (priv->project),
+				NULL,
+				&bytes);
+	brasero_disc_size_changed (BRASERO_DISC (self), bytes);
 
 	priv->size_changed_id = 0;
 	return FALSE;
 }
 
 static void
-brasero_data_disc_size_changed_cb (BraseroDataProject *project,
+brasero_data_disc_size_changed_cb (BraseroTrackDataCfg *project,
 				   BraseroDataDisc *self)
 {
 	BraseroDataDiscPrivate *priv;
@@ -1204,7 +1089,7 @@ brasero_data_disc_import_button_new (BraseroDataDisc *self,
 }
 
 static void
-brasero_data_disc_session_available_cb (BraseroDataSession *session,
+brasero_data_disc_session_available_cb (BraseroTrackDataCfg *session,
 					BraseroMedium *medium,
 					gboolean available,
 					BraseroDataDisc *self)
@@ -1277,7 +1162,7 @@ brasero_data_disc_session_available_cb (BraseroDataSession *session,
 }
 
 static void
-brasero_data_disc_session_loaded_cb (BraseroDataSession *session,
+brasero_data_disc_session_loaded_cb (BraseroTrackDataCfg *session,
 				     BraseroMedium *medium,
 				     gboolean loaded,
 				     BraseroDataDisc *self)
@@ -1314,16 +1199,13 @@ brasero_data_disc_clear (BraseroDisc *disc)
 
 	priv = BRASERO_DATA_DISC_PRIVATE (disc);
 
-	if (priv->loading)
-		return;
-
 	if (priv->size_changed_id) {
 		g_source_remove (priv->size_changed_id);
 		priv->size_changed_id = 0;
 	}
 
-	if (brasero_data_session_get_loaded_medium (BRASERO_DATA_SESSION (priv->project)))
-		brasero_data_session_remove_last (BRASERO_DATA_SESSION (priv->project));
+	if (brasero_track_data_cfg_get_current_medium (BRASERO_TRACK_DATA_CFG (priv->project)))
+		brasero_track_data_cfg_unload_current_medium (BRASERO_TRACK_DATA_CFG (priv->project));
 
 	if (priv->load_errors) {
 		g_slist_foreach (priv->load_errors, (GFunc) g_free , NULL);
@@ -1332,15 +1214,12 @@ brasero_data_disc_clear (BraseroDisc *disc)
 	}
 
 	priv->overburning = FALSE;
-	priv->G2_files = FALSE;
-	priv->deep_directory = FALSE;
 
  	brasero_notify_message_remove (BRASERO_NOTIFY (priv->message), BRASERO_NOTIFY_CONTEXT_SIZE);
 	brasero_notify_message_remove (BRASERO_NOTIFY (priv->message), BRASERO_NOTIFY_CONTEXT_LOADING);
 	brasero_notify_message_remove (BRASERO_NOTIFY (priv->message), BRASERO_NOTIFY_CONTEXT_MULTISESSION);
 
-	brasero_data_project_reset (priv->project);
-	brasero_file_filtered_clear (BRASERO_FILE_FILTERED (priv->filter));
+	brasero_track_data_cfg_reset (priv->project);
 	brasero_disc_size_changed (disc, 0);
 
 	gdk_window_set_cursor (GTK_WIDGET (disc)->window, NULL);
@@ -1359,8 +1238,8 @@ brasero_data_disc_reset (BraseroDisc *disc)
 	}
 
 	/* Unload session */
-	if (brasero_data_session_get_loaded_medium (BRASERO_DATA_SESSION (priv->project)))
-		brasero_data_session_remove_last (BRASERO_DATA_SESSION (priv->project));
+	if (brasero_track_data_cfg_get_current_medium (BRASERO_TRACK_DATA_CFG (priv->project)))
+		brasero_track_data_cfg_unload_current_medium (BRASERO_TRACK_DATA_CFG (priv->project));
 
 	/* Hide all toggle actions for session importing */
 	if (gtk_action_group_get_visible (priv->import_group))
@@ -1375,19 +1254,12 @@ brasero_data_disc_reset (BraseroDisc *disc)
 		priv->load_errors = NULL;
 	}
 
-	brasero_data_project_reset (priv->project);
-
-	priv->overburning = FALSE;
-
-	priv->loading = FALSE;
-	priv->G2_files = FALSE;
-	priv->deep_directory = FALSE;
+	brasero_track_data_cfg_reset (priv->project);
 
- 	brasero_notify_message_remove (BRASERO_NOTIFY (priv->message), BRASERO_NOTIFY_CONTEXT_SIZE);
+	brasero_notify_message_remove (BRASERO_NOTIFY (priv->message), BRASERO_NOTIFY_CONTEXT_SIZE);
 	brasero_notify_message_remove (BRASERO_NOTIFY (priv->message), BRASERO_NOTIFY_CONTEXT_LOADING);
 	brasero_notify_message_remove (BRASERO_NOTIFY (priv->message), BRASERO_NOTIFY_CONTEXT_MULTISESSION);
 
-	brasero_file_filtered_clear (BRASERO_FILE_FILTERED (priv->filter));
 	brasero_disc_size_changed (disc, 0);
 
 	if (GTK_WIDGET (disc)->window)
@@ -1406,9 +1278,6 @@ brasero_data_disc_delete_selected (BraseroDisc *disc)
 
 	priv = BRASERO_DATA_DISC_PRIVATE (disc);
 
-	if (priv->loading)
-		return;
-
 	/* we must start by the end for the treepaths to point to valid rows */
 	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->tree));
 	list = gtk_tree_selection_get_selected_rows (selection, NULL);
@@ -1420,7 +1289,6 @@ brasero_data_disc_delete_selected (BraseroDisc *disc)
 
 	for (iter = list; iter; iter = iter->next) {
 		GtkTreePath *treepath;
-		BraseroFileNode *node;
 
 		treepath = iter->data;
 		if (cursorpath && !gtk_tree_path_compare (cursorpath, treepath)) {
@@ -1437,10 +1305,8 @@ brasero_data_disc_delete_selected (BraseroDisc *disc)
 			gtk_tree_path_free (tmp_path);
 		}
 
-		node = brasero_data_tree_model_path_to_node (BRASERO_DATA_TREE_MODEL (priv->project), treepath);
+		brasero_track_data_cfg_remove (BRASERO_TRACK_DATA_CFG (priv->project), treepath);
  		gtk_tree_path_free (treepath);
-
-		brasero_data_project_remove_node (priv->project, node);
 	}
 	g_list_free (list);
 
@@ -1458,17 +1324,20 @@ static BraseroDiscResult
 brasero_data_disc_add_uri (BraseroDisc *disc, const gchar *uri)
 {
 	BraseroDataDiscPrivate *priv;
-	BraseroFileNode *parent = NULL;
+	GtkTreePath *parent = NULL;
 
 	priv = BRASERO_DATA_DISC_PRIVATE (disc);
 
-	if (priv->loading || priv->reject_files)
+	if (priv->reject_files)
 		return BRASERO_DISC_LOADING;
 
 	parent = brasero_data_disc_get_parent (BRASERO_DATA_DISC (disc));
 	gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), 1);
-	if (brasero_data_project_add_loading_node (priv->project, uri, parent))
+	if (brasero_track_data_cfg_add (BRASERO_TRACK_DATA_CFG (priv->project), uri, parent)) {
+		gtk_tree_path_free (parent);
 		return BRASERO_DISC_OK;
+	}
+	gtk_tree_path_free (parent);
 
 	return BRASERO_DISC_ERROR_UNKNOWN;
 }
@@ -1478,27 +1347,20 @@ brasero_data_disc_get_track (BraseroDisc *disc,
 			     BraseroDiscTrack *track)
 {
 	GSList *grafts = NULL;
-	GSList *restored = NULL;
-	GSList *unreadable = NULL;
 	BraseroDataDiscPrivate *priv;
 
 	priv = BRASERO_DATA_DISC_PRIVATE (disc);
 
-	brasero_data_project_get_contents (priv->project,
-					   &grafts,
-					   &unreadable,
-					   FALSE,
-					   FALSE);
+	grafts = brasero_track_data_get_grafts (BRASERO_TRACK_DATA (priv->project));
 	if (!grafts)
 		return BRASERO_DISC_ERROR_EMPTY_SELECTION;
 
 	track->type = BRASERO_PROJECT_TYPE_DATA;
 	track->contents.data.grafts = grafts;
-	track->contents.data.excluded = unreadable;
+	track->contents.data.excluded = brasero_track_data_get_excluded (BRASERO_TRACK_DATA (priv->project), TRUE);
 
 	/* get restored */
-	brasero_data_vfs_get_restored (BRASERO_DATA_VFS (priv->project), &restored);
-	track->contents.data.restored = restored;
+	track->contents.data.restored = brasero_track_data_cfg_get_restored_list (BRASERO_TRACK_DATA_CFG (priv->project));
 
 	return BRASERO_DISC_OK;
 }
@@ -1507,95 +1369,11 @@ static BraseroDiscResult
 brasero_data_disc_set_session_contents (BraseroDisc *self,
 					BraseroBurnSession *session)
 {
-	GValue *value;
-	BraseroFileNode *root;
-	GSList *grafts = NULL;
-	BraseroImageFS fs_type;
-	BraseroTrackData *track;
-	GSList *unreadable = NULL;
-	BraseroFileTreeStats *stats;
 	BraseroDataDiscPrivate *priv;
 
 	priv = BRASERO_DATA_DISC_PRIVATE (self);
 
-	root = brasero_data_project_get_root (priv->project);
-	stats = BRASERO_FILE_NODE_STATS (root);
-
-	fs_type = BRASERO_IMAGE_FS_ISO;
-	if (brasero_data_project_has_symlinks (priv->project))
-		fs_type |= BRASERO_IMAGE_FS_SYMLINK;
-	else {
-		/* These two are incompatible with symlinks */
-		if (brasero_data_project_is_joliet_compliant (priv->project))
-			fs_type |= BRASERO_IMAGE_FS_JOLIET;
-
-		if (brasero_data_project_is_video_project (priv->project))
-			fs_type |= BRASERO_IMAGE_FS_VIDEO;
-	}
-
-	if (stats->num_2GiB != 0) {
-		fs_type |= BRASERO_IMAGE_ISO_FS_LEVEL_3;
-		if (!(fs_type & BRASERO_IMAGE_FS_SYMLINK))
-			fs_type |= BRASERO_IMAGE_FS_UDF;
-	}
-
-	if (stats->num_deep != 0)
-		fs_type |= BRASERO_IMAGE_ISO_FS_DEEP_DIRECTORY;
-
-	value = g_new0 (GValue, 1);
-	g_value_init (value, G_TYPE_INT64);
-	g_value_set_int64 (value, brasero_data_project_get_size (priv->project));
-	brasero_burn_session_tag_add (session,
-				      BRASERO_DATA_TRACK_SIZE_TAG,
-				      value);
-
-	/* set multisession options */
-	if (brasero_data_session_get_loaded_medium (BRASERO_DATA_SESSION (priv->project))) {
-		BraseroDrive *drive;
-		BraseroMedium *medium;
-
-		medium = brasero_data_session_get_loaded_medium (BRASERO_DATA_SESSION (priv->project));
-		if (medium)
-			drive = brasero_medium_get_drive (medium);
-		else
-			drive = NULL;
-
-		if (priv->overburning)
-			brasero_burn_session_add_flag (session, BRASERO_BURN_FLAG_OVERBURN);
-
-		/* remove the following flag just in case */
-		brasero_burn_session_remove_flag (session,
-						  BRASERO_BURN_FLAG_FAST_BLANK|
-						  BRASERO_BURN_FLAG_BLANK_BEFORE_WRITE);
-		brasero_burn_session_add_flag (session, BRASERO_BURN_FLAG_MERGE);
-		brasero_burn_session_set_burner (session, drive);
-	}
-
-	/* there should be only one data track */
-	track = brasero_track_data_new ();
-	brasero_track_data_add_fs (track, fs_type);
-
-	/* Set the number of files in the tree */
-	if (stats)
-		brasero_track_data_set_file_num (track, stats->children);
-
-	/* append a slash for mkisofs */
-	brasero_data_project_get_contents (priv->project,
-					   &grafts,
-					   &unreadable,
-					   (fs_type & BRASERO_IMAGE_FS_JOLIET) != 0,
-					   TRUE); 
-
-	if (!grafts)
-		return BRASERO_DISC_ERROR_EMPTY_SELECTION;
-
-	brasero_track_data_set_source (track, grafts, unreadable);
-	brasero_burn_session_add_track (session, BRASERO_TRACK (track));
-
-	/* It's good practice to unref the track afterwards as we don't need it
-	 * anymore. BraseroBurnSession refs it. */
-	g_object_unref (track);
-
+	brasero_burn_session_add_track (session, BRASERO_TRACK (priv->project));
 	return BRASERO_DISC_OK;
 }
 
@@ -1614,7 +1392,6 @@ brasero_data_disc_message_response_cb (BraseroDiscMessage *message,
 	if (response != GTK_RESPONSE_CANCEL)
 		return;
 
-	priv->loading = FALSE;
 	brasero_data_disc_clear (BRASERO_DISC (self));
 }
 
@@ -1623,6 +1400,8 @@ brasero_data_disc_load_track (BraseroDisc *disc,
 			      BraseroDiscTrack *track)
 {
 	BraseroDataDiscPrivate *priv;
+	BraseroBurnResult res;
+	BraseroStatus *status;
 	GtkWidget *message;
 	GSList *iter;
 
@@ -1633,19 +1412,27 @@ brasero_data_disc_load_track (BraseroDisc *disc,
 		gchar *uri;
 
 		uri = iter->data;
-		brasero_data_vfs_add_restored (BRASERO_DATA_VFS (priv->project), uri);
+		brasero_track_data_cfg_dont_filter_uri (BRASERO_TRACK_DATA_CFG (priv->project), uri);
 	}
 
-	priv->loading = brasero_data_project_load_contents (priv->project,
-							    track->contents.data.grafts,
-							    track->contents.data.excluded);
-	if (!priv->loading) {
+	res = brasero_track_data_set_source (BRASERO_TRACK_DATA (priv->project),
+					     track->contents.data.grafts,
+					     track->contents.data.excluded);
+	if (res == BRASERO_BURN_OK) {
+		brasero_status_free (status);
 		gtk_widget_set_sensitive (GTK_WIDGET (priv->tree), TRUE);
 		gtk_widget_set_sensitive (GTK_WIDGET (priv->filter), TRUE);
 		gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), 1);
 		return BRASERO_DISC_OK;
 	}
 
+	if (res == BRASERO_BURN_NOT_READY)
+		return BRASERO_DISC_ERROR_UNKNOWN;
+
+
+	status = brasero_status_new ();
+	brasero_track_get_status (BRASERO_TRACK (priv->project), status);
+
 	message = brasero_notify_message_add (BRASERO_NOTIFY (priv->message),
 					      _("Please wait while the project is loading."),
 					      NULL,
@@ -1653,7 +1440,8 @@ brasero_data_disc_load_track (BraseroDisc *disc,
 					      BRASERO_NOTIFY_CONTEXT_LOADING);
 
 	brasero_disc_message_set_image (BRASERO_DISC_MESSAGE (message),GTK_STOCK_DIALOG_INFO);
-	brasero_disc_message_set_progress (BRASERO_DISC_MESSAGE (message), 0.0);
+	brasero_disc_message_set_progress (BRASERO_DISC_MESSAGE (message),
+					   brasero_status_get_progress (status));
 
 	brasero_notify_button_add (BRASERO_NOTIFY (priv->message),
 				   BRASERO_DISC_MESSAGE (message),
@@ -1669,34 +1457,44 @@ brasero_data_disc_load_track (BraseroDisc *disc,
 	gtk_widget_set_sensitive (GTK_WIDGET (priv->filter), FALSE);
 
 	gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), 1);
+
+	brasero_status_free (status);
 	return BRASERO_DISC_OK;
 }
 
 static BraseroDiscResult
 brasero_data_disc_get_status (BraseroDisc *disc,
-			      gint *remaining,
+			      gint *progress,
 			      gchar **current_task)
 {
 	BraseroDataDiscPrivate *priv;
+	BraseroStatus *status;
 
 	priv = BRASERO_DATA_DISC_PRIVATE (disc);
 
-	if (priv->loading)
-		return BRASERO_DISC_LOADING;
+	status = brasero_status_new ();
+	brasero_track_get_status (BRASERO_TRACK (priv->project), status);
 
-	/* This one goes before the next since a node may be loading but not
-	 * yet in the project and therefore project will look empty */
-	if (brasero_data_vfs_is_active (BRASERO_DATA_VFS (priv->project))) {
-		if (remaining)
-			*remaining = -1;
+	if (brasero_status_get_result (status) == BRASERO_BURN_NOT_READY) {
+		if (progress)
+			*progress = brasero_status_get_progress (status);
 
 		if (current_task)
-			*current_task = g_strdup (_("Analysing files"));
+			*current_task = brasero_status_get_current_action (status);
 
+		brasero_status_free (status);
+
+		if (priv->loading)
+			return BRASERO_DISC_LOADING;
+
+		/* This one goes before the next since a node may be loading but not
+		 * yet in the project and therefore project will look empty */
 		return BRASERO_DISC_NOT_READY;
 	}
 
-	if (brasero_data_project_is_empty (priv->project))
+	brasero_status_free (status);
+
+	if (gtk_tree_model_iter_n_children (GTK_TREE_MODEL (priv->project), NULL))
 		return BRASERO_DISC_ERROR_EMPTY_SELECTION;
 
 	return BRASERO_DISC_OK;
@@ -1707,6 +1505,8 @@ brasero_data_disc_get_selected_uri (BraseroDisc *disc,
 				    gchar **uri)
 {
 	BraseroDataDiscPrivate *priv;
+	GtkTreePath *path;
+	GtkTreeIter iter;
 
 	priv = BRASERO_DATA_DISC_PRIVATE (disc);
 
@@ -1716,7 +1516,16 @@ brasero_data_disc_get_selected_uri (BraseroDisc *disc,
 	if (!uri)
 		return TRUE;
 
-	*uri = brasero_data_project_node_to_uri (priv->project, priv->selected);
+	path = gtk_tree_row_reference_get_path (priv->selected);
+	if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (priv->project), &iter, path)) {
+		gtk_tree_path_free (path);
+		return FALSE;
+	}
+
+	gtk_tree_path_free (path);
+	gtk_tree_model_get (GTK_TREE_MODEL (priv->project), &iter,
+			    BRASERO_DATA_TREE_MODEL_URI, uri,
+			    -1);
 	return TRUE;
 }
 
@@ -1782,7 +1591,7 @@ brasero_data_disc_add_ui (BraseroDisc *disc,
 						    priv->import_group,
 						    0);
 
-		list = brasero_data_session_get_available_media (BRASERO_DATA_SESSION (priv->project));
+		list = brasero_track_data_cfg_get_available_media (priv->project);
 		for (iter = list; iter; iter = iter->next) {
 			BraseroMedium *medium;
 
@@ -1805,7 +1614,6 @@ brasero_data_disc_add_ui (BraseroDisc *disc,
 static void
 brasero_data_disc_open_file (BraseroDataDisc *disc, GList *list)
 {
-	gchar *uri;
 	GList *item;
 	GSList *uris;
 	BraseroDataDiscPrivate *priv;
@@ -1815,17 +1623,26 @@ brasero_data_disc_open_file (BraseroDataDisc *disc, GList *list)
 	uris = NULL;
 	for (item = list; item; item = item->next) {
 		GtkTreePath *treepath;
-		BraseroFileNode *node;
+		gboolean is_imported;
+		gchar *uri = NULL;
+		GtkTreeIter iter;
 
 		treepath = item->data;
 		if (!treepath)
 			continue;
 
-		node = brasero_data_tree_model_path_to_node (BRASERO_DATA_TREE_MODEL (priv->project), treepath);
-		if (!node || node->is_imported)
+		if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (priv->project), &iter, treepath))
+			continue;
+
+		gtk_tree_model_get (GTK_TREE_MODEL (priv->project), &iter,
+				    BRASERO_DATA_TREE_MODEL_IS_IMPORTED, &is_imported,
+				    -1);
+		if (is_imported)
 			continue;
 
-		uri = brasero_data_project_node_to_uri (priv->project, node);
+		gtk_tree_model_get (GTK_TREE_MODEL (priv->project), &iter,
+				    BRASERO_DATA_TREE_MODEL_URI, &uri,
+				    -1);
 		if (uri)
 			uris = g_slist_prepend (uris, uri);
 
@@ -1864,12 +1681,9 @@ brasero_data_disc_mass_rename_cb (GtkTreeModel *model,
 				  const gchar *old_name,
 				  const gchar *new_name)
 {
-	BraseroFileNode *node;
-
-	node = brasero_data_tree_model_path_to_node (BRASERO_DATA_TREE_MODEL (model), treepath);
-	return brasero_data_project_rename_node (BRASERO_DATA_PROJECT (model),
-						 node,
-						 new_name);
+	return brasero_track_data_cfg_rename (BRASERO_TRACK_DATA_CFG (model),
+					      new_name,
+					      treepath);
 }
 
 static void
@@ -1887,13 +1701,21 @@ brasero_data_disc_rename_activated (BraseroDataDisc *disc)
 
 	list = gtk_tree_selection_get_selected_rows (selection, NULL);
 	if (g_list_length (list) == 1) {
-		BraseroFileNode *node;
+		gboolean is_imported;
+		GtkTreeIter iter;
 
 		treepath = list->data;
 		g_list_free (list);
 
-		node = brasero_data_tree_model_path_to_node (BRASERO_DATA_TREE_MODEL (priv->project), treepath);
-		if (!node || node->is_imported) {
+		if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (priv->project), &iter, treepath)) {
+			gtk_tree_path_free (treepath);
+			return;
+		}
+
+		gtk_tree_model_get (GTK_TREE_MODEL (priv->project), &iter,
+				    BRASERO_DATA_TREE_MODEL_IS_IMPORTED, &is_imported,
+				    -1);
+		if (is_imported) {
 			gtk_tree_path_free (treepath);
 			return;
 		}
@@ -1986,14 +1808,20 @@ brasero_data_disc_selection_changed_cb (GtkTreeSelection *selection,
 	selected = gtk_tree_selection_get_selected_rows (selection, &model);
 	if (selected) {
 		GtkTreePath *treepath;
-		BraseroFileNode *node;
+		GtkTreeIter iter;
 
 		treepath = selected->data;
 
 		/* we need to make sure that this is not a bogus row */
-		node = brasero_data_tree_model_path_to_node (BRASERO_DATA_TREE_MODEL (priv->project), treepath);
-		if (node && !node->is_imported)
-			priv->selected = node;
+		if (gtk_tree_model_get_iter (GTK_TREE_MODEL (priv->project), &iter, treepath)) {
+			gboolean is_imported;
+
+			gtk_tree_model_get (GTK_TREE_MODEL (priv->project), &iter,
+					    BRASERO_DATA_TREE_MODEL_IS_IMPORTED, &is_imported,
+					    -1);
+			if (!is_imported)
+				priv->selected = gtk_tree_row_reference_new (GTK_TREE_MODEL (priv->project), treepath);
+		}
 
 		g_list_foreach (selected, (GFunc) gtk_tree_path_free, NULL);
 		g_list_free (selected);
@@ -2009,20 +1837,30 @@ brasero_data_disc_tree_select_function (GtkTreeSelection *selection,
 					gboolean is_selected,
 					gpointer null_data)
 {
-	BraseroFileNode *node;
+	GtkTreeIter iter;
+	gboolean is_imported;
+
+	if (!gtk_tree_model_get_iter (model, &iter, treepath))
+		return FALSE;
 
-	node = brasero_data_tree_model_path_to_node (BRASERO_DATA_TREE_MODEL (model), treepath);
-	if (!node || node->is_imported) {
+	gtk_tree_model_get (model, &iter, 
+			    BRASERO_DATA_TREE_MODEL_IS_IMPORTED, &is_imported,
+			    -1);
+
+	if (is_imported) {
 		if (is_selected)
 			return TRUE;
 
 		return FALSE;
 	}
 
+	/* FIXME: this should be reenable if the bug in multiDND and cell
+	 * editing appears again. 
 	if (is_selected)
 		node->is_selected = FALSE;
 	else
 		node->is_selected = TRUE;
+	*/
 
 	return TRUE;
 }
@@ -2092,8 +1930,8 @@ brasero_data_disc_button_pressed_cb (GtkTreeView *tree,
 				     GdkEventButton *event,
 				     BraseroDataDisc *self)
 {
-	gboolean result;
-	BraseroFileNode *node = NULL;
+	GtkTreeIter iter;
+	gboolean result = FALSE;
 	GtkTreePath *treepath = NULL;
 	GtkWidgetClass *widget_class;
 	BraseroDataDiscPrivate *priv;
@@ -2110,24 +1948,20 @@ brasero_data_disc_button_pressed_cb (GtkTreeView *tree,
 							NULL,
 							NULL);
 
-		if (treepath)
-			node = brasero_data_tree_model_path_to_node (BRASERO_DATA_TREE_MODEL (priv->project),
-								     treepath);
-
-		if (node) {
-			GtkTreeSelection *selection;
-			selection = gtk_tree_view_get_selection (tree);
-			keep_selection = gtk_tree_selection_path_is_selected (selection, treepath);
-		}
-
-		if (!node && treepath) {
-			/* That may be a BOGUS row */
-			gtk_tree_path_free (treepath);
-			treepath = NULL;
+		if (treepath) {
+			if (gtk_tree_model_get_iter (GTK_TREE_MODEL (priv->project), &iter, treepath)) {
+				GtkTreeSelection *selection;
+				selection = gtk_tree_view_get_selection (tree);
+				keep_selection = gtk_tree_selection_path_is_selected (selection, treepath);
+			}
+			else {
+				/* That may be a BOGUS row */
+				gtk_tree_path_free (treepath);
+				treepath = NULL;
+				result = FALSE;
+			}
 		}
 	}
-	else
-		result = FALSE;
 
 	/* we call the default handler for the treeview before everything else
 	 * so it can update itself (particularly its selection) before we use it
@@ -2142,10 +1976,17 @@ brasero_data_disc_button_pressed_cb (GtkTreeView *tree,
 	}
 
 	if ((event->state & (GDK_CONTROL_MASK|GDK_SHIFT_MASK)) == 0) {
-		if (node && !node->is_imported)
-			priv->selected = node;
+		if (result) {
+			gboolean is_imported;
+
+			gtk_tree_model_get (GTK_TREE_MODEL (priv->project), &iter,
+					    BRASERO_DATA_TREE_MODEL_IS_IMPORTED, &is_imported,
+					    -1);
+			if (!is_imported)
+				priv->selected = gtk_tree_row_reference_new (GTK_TREE_MODEL (priv->project), treepath);
+		}
 		else if ((event->state & GDK_SHIFT_MASK) == 0)
-			priv->selected = node;
+			priv->selected = gtk_tree_row_reference_new (GTK_TREE_MODEL (priv->project), treepath);
 		else
 			priv->selected = NULL;
 
@@ -2167,7 +2008,7 @@ brasero_data_disc_button_pressed_cb (GtkTreeView *tree,
 				g_list_free (list);
 			}
 		}
-		else  if (!node) {
+		else if (!result) {
 			GtkTreeSelection *selection;
 
 			/* This is to deselect any row when selecting a row that cannot
@@ -2184,7 +2025,7 @@ brasero_data_disc_button_pressed_cb (GtkTreeView *tree,
 		if (!keep_selection) {
 			widget_class->button_press_event (GTK_WIDGET (tree), event);
 
-			if (!node) {
+			if (!result) {
 				GtkTreeSelection *selection;
 
 				/* This is to deselect any row when selecting a row that cannot
@@ -2246,13 +2087,11 @@ brasero_data_disc_contents_removed_cb (GtkTreeModel *model,
 				       GtkTreePath *treepath,
 				       BraseroDataDisc *self)
 {
-	BraseroFileNode *root;
 	BraseroDataDiscPrivate *priv;
 
 	priv = BRASERO_DATA_DISC_PRIVATE (self);
 
-	root = brasero_data_project_get_root (priv->project);
-	brasero_disc_contents_changed (BRASERO_DISC (self), (root && BRASERO_FILE_NODE_CHILDREN (root) != NULL));
+	brasero_disc_contents_changed (BRASERO_DISC (self), gtk_tree_model_iter_n_children (GTK_TREE_MODEL (priv->project), NULL));
 }
 
 /**
@@ -2293,14 +2132,10 @@ brasero_data_disc_init (BraseroDataDisc *object)
 	gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook), mainbox, NULL);
 	gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), 0);
 
-	priv->project = BRASERO_DATA_PROJECT (brasero_data_tree_model_new ());
+	priv->project = brasero_track_data_cfg_new ();
 	model = GTK_TREE_MODEL (priv->project);
 
 	g_signal_connect (priv->project,
-			  "name-collision",
-			  G_CALLBACK (brasero_data_disc_name_collision_cb),
-			  object);
-	g_signal_connect (priv->project,
 			  "2G-file",
 			  G_CALLBACK (brasero_data_disc_2G_file_cb),
 			  object);
@@ -2308,20 +2143,30 @@ brasero_data_disc_init (BraseroDataDisc *object)
 			  "deep-directory",
 			  G_CALLBACK (brasero_data_disc_deep_directory_cb),
 			  object);
+
 	g_signal_connect (priv->project,
-			  "size-changed",
-			  G_CALLBACK (brasero_data_disc_size_changed_cb),
+			  "source-loading",
+			  G_CALLBACK (brasero_data_disc_project_loading_cb),
 			  object);
 	g_signal_connect (priv->project,
-			  "project-loaded",
+			  "source-loaded",
 			  G_CALLBACK (brasero_data_disc_project_loaded_cb),
 			  object);
+
 	g_signal_connect (priv->project,
 			  "oversize",
 			  G_CALLBACK (brasero_data_disc_project_oversized_cb),
 			  object);
 
 	g_signal_connect (priv->project,
+			  "size-changed",
+			  G_CALLBACK (brasero_data_disc_size_changed_cb),
+			  object);
+	g_signal_connect (priv->project,
+			  "name-collision",
+			  G_CALLBACK (brasero_data_disc_name_collision_cb),
+			  object);
+	g_signal_connect (priv->project,
 			  "row-inserted",
 			  G_CALLBACK (brasero_data_disc_contents_added_cb),
 			  object);
@@ -2335,10 +2180,6 @@ brasero_data_disc_init (BraseroDataDisc *object)
 			  G_CALLBACK (brasero_data_disc_activity_changed_cb),
 			  object);
 	g_signal_connect (priv->project,
-			  "filtered-uri",
-			  G_CALLBACK (brasero_data_disc_filtered_uri_cb),
-			  object);
-	g_signal_connect (priv->project,
 			  "image-uri",
 			  G_CALLBACK (brasero_data_disc_image_uri_cb),
 			  object);
@@ -2504,32 +2345,14 @@ brasero_data_disc_init (BraseroDataDisc *object)
 						nb_targets_source,
 						GDK_ACTION_MOVE);
 
-	g_signal_connect (G_OBJECT (priv->tree),
-			  "row-expanded",
-			  G_CALLBACK (brasero_data_disc_row_expanded_cb),
-			  object);
-	g_signal_connect (G_OBJECT (priv->tree),
-			  "row-collapsed",
-			  G_CALLBACK (brasero_data_disc_row_collapsed_cb),
-			  object);
-
 	/* filtered files */
-	priv->filter = brasero_file_filtered_new ();
+	priv->filter = brasero_file_filtered_new (priv->project);
 	g_signal_connect (priv->filter,
 			  "activate",
 			  G_CALLBACK (brasero_data_disc_filter_expanded_cb),
 			  object);
 	gtk_widget_show (priv->filter);
 	gtk_box_pack_end (GTK_BOX (object), priv->filter, FALSE, TRUE, 0);
-
-	g_signal_connect (priv->filter,
-			  "filtered",
-			  G_CALLBACK (brasero_data_disc_filtered_file_cb),
-			  object);
-	g_signal_connect (priv->filter,
-			  "restored",
-			  G_CALLBACK (brasero_data_disc_restored_file_cb),
-			  object);
 }
 
 static void
diff --git a/src/brasero-file-filtered.c b/src/brasero-file-filtered.c
index 1f94854..e2ed163 100644
--- a/src/brasero-file-filtered.c
+++ b/src/brasero-file-filtered.c
@@ -32,20 +32,12 @@
 
 #include <gtk/gtk.h>
 
-
 #include "brasero-file-filtered.h"
 #include "brasero-filter-option.h"
 #include "brasero-utils.h"
-#include "brasero-data-vfs.h"
-
-enum  {
-	STOCK_ID_COL,
-	UNESCAPED_URI_COL,
-	TYPE_COL,
-	STATUS_COL,
-	ACTIVABLE_COL,
-	NB_COL,
-};
+
+#include "brasero-track-data-cfg.h"
+
 
 typedef struct _BraseroFileFilteredPrivate BraseroFileFilteredPrivate;
 struct _BraseroFileFilteredPrivate
@@ -54,38 +46,31 @@ struct _BraseroFileFilteredPrivate
 	GtkWidget *restore;
 	GtkWidget *options;
 
-	GSList *broken;
-	GSList *hidden;
-	GSList *recursive;
-	GSList *unreadable;
-
-	guint idle_id;
-
-	guint num;
+	BraseroTrackDataCfg *track;
 };
 
 #define BRASERO_FILE_FILTERED_PRIVATE(o)  (G_TYPE_INSTANCE_GET_PRIVATE ((o), BRASERO_TYPE_FILE_FILTERED, BraseroFileFilteredPrivate))
 
-enum
-{
-	FILTERED_SIGNAL,
-	RESTORED_SIGNAL,
-
-	LAST_SIGNAL
-};
-
-
-static guint file_filtered_signals[LAST_SIGNAL] = { 0 };
-
 G_DEFINE_TYPE (BraseroFileFiltered, brasero_file_filtered, GTK_TYPE_EXPANDER);
 
+enum {
+	PROP_0,
+	PROP_TRACK
+};
 
 static gchar *
-brasero_file_filtered_get_label_text (guint num, gboolean expanded)
+brasero_file_filtered_get_label_text (BraseroFileFiltered *self)
 {
+	guint num;
 	gchar *label;
+	GtkTreeModel *model;
+	BraseroFileFilteredPrivate *priv;
+
+	priv = BRASERO_FILE_FILTERED_PRIVATE (self);
+	model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->tree));
+	num = gtk_tree_model_iter_n_children (model, NULL);
 
-	if (expanded) {
+	if (gtk_expander_get_expanded (GTK_EXPANDER (self))) {
 		if (!num)
 			label = g_strdup (_("No file filtered"));
 		else
@@ -110,8 +95,8 @@ brasero_file_filtered_update (BraseroFileFiltered *self)
 
 	priv = BRASERO_FILE_FILTERED_PRIVATE (self);
 
-	markup = brasero_file_filtered_get_label_text (priv->num,
-						       gtk_expander_get_expanded (GTK_EXPANDER (self)));
+	markup = brasero_file_filtered_get_label_text (self);
+
 	widget = gtk_expander_get_label_widget (GTK_EXPANDER (self));
 	gtk_label_set_markup_with_mnemonic (GTK_LABEL (widget), markup);
 	g_free (markup);
@@ -125,200 +110,20 @@ brasero_file_filtered_activate (GtkExpander *self)
 }
 
 void
-brasero_file_filtered_remove (BraseroFileFiltered *self,
-			      const gchar *uri)
+brasero_file_filtered_row_inserted (GtkTreeModel *model,
+				    GtkTreePath *treepath,
+				    GtkTreeIter *iter,
+				    BraseroFileFiltered *self)
 {
-	BraseroFileFilteredPrivate *priv;
-	GtkTreeModel *model;
-	GtkTreeIter iter;
-	guint len;
-
-	priv = BRASERO_FILE_FILTERED_PRIVATE (self);
-
-	model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->tree));
-	if (!gtk_tree_model_get_iter_first (model, &iter))
-		return;
-
-	len = strlen (uri);
-	while (1) {
-		gchar *iter_uri;
-
-		iter_uri = NULL;
-		gtk_tree_model_get (model, &iter,
-				    UNESCAPED_URI_COL, &iter_uri,
-				    -1);
-
-		if (!iter_uri)
-			continue;
-
-		if (!strcmp (uri, iter_uri)) {
-			g_free (iter_uri);
-			priv->num --;
-			if (!gtk_list_store_remove (GTK_LIST_STORE (model), &iter))
-				break;
-
-			continue;
-		}
-
-		if (!strncmp (uri, iter_uri, len)
-		&&   iter_uri [len] == G_DIR_SEPARATOR) {
-			g_free (iter_uri);
-			priv->num --;
-			if (!gtk_list_store_remove (GTK_LIST_STORE (model), &iter))
-				break;
-
-			continue;
-		}
-
-		g_free (iter_uri);
-		if (!gtk_tree_model_iter_next (model, &iter))
-			break;
-	}
-
 	brasero_file_filtered_update (self);
 }
 
-static void
-brasero_file_filtered_add_real (BraseroFileFiltered *self,
-				const gchar *unescaped_uri,
-				BraseroFilterStatus status)
-{
-	gchar *labels [] = { N_("Hidden file"),
-			     N_("Unreadable file"),
-			     N_("Broken symbolic link"),
-			     N_("Recursive symbolic link"),
-			     NULL };
-	BraseroFileFilteredPrivate *priv;
-	const gchar *stock_id;
-	GtkTreeModel *model;
-	GtkTreeIter iter;
-	gchar *type;
-
-	priv = BRASERO_FILE_FILTERED_PRIVATE (self);
-
-	type = labels [ status - 1 ];
-	if (status == BRASERO_FILTER_UNREADABLE)
-		stock_id = GTK_STOCK_CANCEL;
-	else
-		stock_id = NULL;
-
-	model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->tree));
-	gtk_list_store_append (GTK_LIST_STORE (model), &iter);
-
-	gtk_list_store_set (GTK_LIST_STORE (model), &iter,
-			    STOCK_ID_COL, stock_id,
-			    UNESCAPED_URI_COL, unescaped_uri,
-			    TYPE_COL, _(type),
-			    STATUS_COL, status,
-			    ACTIVABLE_COL, (status != BRASERO_FILTER_UNREADABLE && status != BRASERO_FILTER_RECURSIVE_SYM),
-			    -1);
-
-	priv->num ++;
-}
-
-static gboolean
-brasero_file_filtered_add_loop (gpointer data)
-{
-	GSList *iter;
-	BraseroFileFilteredPrivate *priv;
-	BraseroFileFiltered *self = BRASERO_FILE_FILTERED (data);
-
-	priv = BRASERO_FILE_FILTERED_PRIVATE (self);
-
-	for (iter = priv->hidden; iter; iter = iter->next) {
-		gchar *unescaped_uri;
-
-		unescaped_uri = iter->data;
-		brasero_file_filtered_add_real (self,
-						unescaped_uri,
-						BRASERO_FILTER_HIDDEN);
-		g_free (unescaped_uri);
-	}
-	g_slist_free (priv->hidden);
-	priv->hidden = NULL;
-
-	for (iter = priv->broken; iter; iter = iter->next) {
-		gchar *unescaped_uri;
-
-		unescaped_uri = iter->data;
-		brasero_file_filtered_add_real (self,
-						unescaped_uri,
-						BRASERO_FILTER_BROKEN_SYM);
-		g_free (unescaped_uri);
-	}
-	g_slist_free (priv->broken);
-	priv->broken = NULL;
-
-	for (iter = priv->recursive; iter; iter = iter->next) {
-		gchar *unescaped_uri;
-
-		unescaped_uri = iter->data;
-		brasero_file_filtered_add_real (self,
-						unescaped_uri,
-						BRASERO_FILTER_RECURSIVE_SYM);
-		g_free (unescaped_uri);
-	}
-	g_slist_free (priv->recursive);
-	priv->recursive = NULL;
-
-	for (iter = priv->unreadable; iter; iter = iter->next) {
-		gchar *unescaped_uri;
-
-		unescaped_uri = iter->data;
-		brasero_file_filtered_add_real (self,
-						unescaped_uri,
-						BRASERO_FILTER_UNREADABLE);
-		g_free (unescaped_uri);
-	}
-	g_slist_free (priv->unreadable);
-	priv->unreadable = NULL;
-
-	/* update label */
-	brasero_file_filtered_update (self);
-
-	priv->idle_id = 0;
-	return FALSE;
-}
-
 void
-brasero_file_filtered_add (BraseroFileFiltered *self,
-			   const gchar *uri,
-			   BraseroFilterStatus status)
+brasero_file_filtered_row_deleted (GtkTreeModel *model,
+				   GtkTreePath *treepath,
+				   BraseroFileFiltered *self)
 {
-	BraseroFileFilteredPrivate *priv;
-
-	priv = BRASERO_FILE_FILTERED_PRIVATE (self);
-
-	/* The idea here is to delay the introduction of each file in the tree
-	 * and the label update so as not slow down brasero too much */
-	switch (status) {
-	case BRASERO_FILTER_HIDDEN:
-		priv->hidden = g_slist_prepend (priv->hidden,
-						g_uri_unescape_string (uri, NULL));
-		break;
-
-	case BRASERO_FILTER_BROKEN_SYM:
-		priv->broken = g_slist_prepend (priv->broken,
-						g_uri_unescape_string (uri, NULL));
-		break;
-	case BRASERO_FILTER_RECURSIVE_SYM:
-		priv->recursive = g_slist_prepend (priv->recursive,
-						   g_uri_unescape_string (uri, NULL));
-		break;
-	case BRASERO_FILTER_UNREADABLE:
-		priv->unreadable = g_slist_prepend (priv->unreadable,
-						    g_uri_unescape_string (uri, NULL));
-		break;
-	case BRASERO_FILTER_NONE:
-	case BRASERO_FILTER_UNKNOWN:
-		default:
-		break;
-	}
-
-	if (!priv->idle_id)
-		priv->idle_id = g_timeout_add_seconds (1,
-						       brasero_file_filtered_add_loop,
-						       self);
+	brasero_file_filtered_update (self);
 }
 
 static void
@@ -360,39 +165,13 @@ brasero_file_filtered_restore_pressed_cb (GtkButton *button,
 	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->tree));
 	selected = gtk_tree_selection_get_selected_rows (selection, &model);
 
-	/* reverse the list so as to be able to delete properly item */
 	selected = g_list_reverse (selected);
 
 	for (iter = selected; iter; iter = iter->next) {
 		GtkTreePath *treepath;
-		GtkTreeIter treeiter;
-		gchar *escaped_uri;
-		gchar *uri;
 
 		treepath = iter->data;
-		if (!gtk_tree_model_get_iter (model, &treeiter, treepath)) {
-			gtk_tree_path_free (treepath);
-			continue;
-		}
-
-		gtk_tree_path_free (treepath);
-
-		uri = NULL;
-		gtk_tree_model_get (model, &treeiter,
-				    UNESCAPED_URI_COL, &uri, 
-				    -1);
-
-		escaped_uri = g_uri_escape_string (uri,
-						   G_URI_RESERVED_CHARS_ALLOWED_IN_PATH,
-						   FALSE);
-		g_signal_emit (self,
-			       file_filtered_signals [RESTORED_SIGNAL],
-			       0,
-			       escaped_uri);
-		g_free (escaped_uri);
-
-		gtk_list_store_remove (GTK_LIST_STORE (model), &treeiter);
-		priv->num --;
+		brasero_track_data_cfg_restore (priv->track, treepath);
 	}
 	g_list_free (selected);
 
@@ -415,51 +194,6 @@ brasero_file_filtered_selection_changed_cb (GtkTreeSelection *selection,
 }
 
 void
-brasero_file_filtered_clear (BraseroFileFiltered *self)
-{
-	BraseroFileFilteredPrivate *priv;
-	GtkTreeModel *model;
-
-	priv = BRASERO_FILE_FILTERED_PRIVATE (self);
-
-	if (priv->idle_id) {
-		g_source_remove (priv->idle_id);
-		priv->idle_id = 0;
-	}
-
-	if (priv->hidden) {
-		g_slist_foreach (priv->hidden, (GFunc) g_free, NULL);
-		g_slist_free (priv->hidden);
-		priv->hidden = NULL;
-	}
-
-	if (priv->broken) {
-		g_slist_foreach (priv->broken, (GFunc) g_free, NULL);
-		g_slist_free (priv->broken);
-		priv->broken = NULL;
-	}
-
-	if (priv->recursive) {
-		g_slist_foreach (priv->recursive, (GFunc) g_free, NULL);
-		g_slist_free (priv->recursive);
-		priv->recursive = NULL;
-	}
-
-	if (priv->unreadable) {
-		g_slist_foreach (priv->unreadable, (GFunc) g_free, NULL);
-		g_slist_free (priv->unreadable);
-		priv->unreadable = NULL;
-	}
-
-	priv->num = 0;
-
-	model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->tree));
-	gtk_list_store_clear (GTK_LIST_STORE (model));
-
-	brasero_file_filtered_update (self);
-}
-
-void
 brasero_file_filtered_set_right_button_group (BraseroFileFiltered *self,
 					      GtkSizeGroup *group)
 {
@@ -478,7 +212,6 @@ brasero_file_filtered_init (BraseroFileFiltered *object)
 	GtkWidget *button;
 	GtkWidget *scroll;
 	GtkWidget *mainbox;
-	GtkListStore *model;
 	GtkTreeViewColumn *column;
 	GtkCellRenderer *renderer;
 	BraseroFileFilteredPrivate *priv;
@@ -494,20 +227,12 @@ brasero_file_filtered_init (BraseroFileFiltered *object)
 	hbox = gtk_hbox_new (FALSE, 6);
 	gtk_widget_show (hbox);
 
-	model = gtk_list_store_new (NB_COL,
-				    G_TYPE_STRING,
-				    G_TYPE_STRING,
-				    G_TYPE_STRING,
-				    G_TYPE_INT,
-				    G_TYPE_BOOLEAN);
-
-	priv->tree = gtk_tree_view_new_with_model (GTK_TREE_MODEL (model));
+	priv->tree = gtk_tree_view_new ();
 	gtk_widget_show (priv->tree);
 	gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (priv->tree), TRUE);
 	gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->tree)),
 				     GTK_SELECTION_MULTIPLE);
 	gtk_tree_view_set_rubber_banding (GTK_TREE_VIEW (priv->tree), TRUE);
-	g_object_unref (model);
 
 	g_signal_connect (gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->tree)),
 						       "changed",
@@ -519,15 +244,20 @@ brasero_file_filtered_init (BraseroFileFiltered *object)
 	renderer = gtk_cell_renderer_pixbuf_new ();
 	gtk_tree_view_column_pack_start (column, renderer, FALSE);
 	gtk_tree_view_column_add_attribute (column, renderer,
-					    "stock-id", STOCK_ID_COL);
+					    "stock-id", BRASERO_FILTERED_STOCK_ID_COL);
+	gtk_tree_view_column_add_attribute (column, renderer,
+					    "sensitive", BRASERO_FILTERED_FATAL_ERROR_COL);
 
 	renderer = gtk_cell_renderer_text_new ();
 	gtk_tree_view_column_pack_end (column, renderer, TRUE);
 	gtk_tree_view_column_add_attribute (column, renderer,
-					    "text", UNESCAPED_URI_COL);
+					    "text", BRASERO_FILTERED_URI_COL);
+	gtk_tree_view_column_add_attribute (column, renderer,
+					    "sensitive", BRASERO_FILTERED_FATAL_ERROR_COL);
+
 	gtk_tree_view_column_set_title (column, _("Files"));
 	gtk_tree_view_append_column (GTK_TREE_VIEW (priv->tree), column);
-	gtk_tree_view_column_set_sort_column_id (column, UNESCAPED_URI_COL);
+	gtk_tree_view_column_set_sort_column_id (column, BRASERO_FILTERED_URI_COL);
 	gtk_tree_view_column_set_clickable (column, TRUE);
 	gtk_tree_view_column_set_resizable (column, TRUE);
 	gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
@@ -535,10 +265,11 @@ brasero_file_filtered_init (BraseroFileFiltered *object)
 
 	renderer = gtk_cell_renderer_text_new ();
 	column = gtk_tree_view_column_new_with_attributes (_("Type"), renderer,
-							   "text", TYPE_COL,
+							   "text", BRASERO_FILTERED_STATUS_COL,
+							   "sensitive", BRASERO_FILTERED_FATAL_ERROR_COL,
 							   NULL);
 	gtk_tree_view_append_column (GTK_TREE_VIEW (priv->tree), column);
-	gtk_tree_view_column_set_sort_column_id (column, TYPE_COL);
+	gtk_tree_view_column_set_sort_column_id (column, BRASERO_FILTERED_STATUS_COL);
 	gtk_tree_view_column_set_clickable (column, TRUE);
 
 	scroll = gtk_scrolled_window_new (NULL, NULL);
@@ -589,39 +320,67 @@ brasero_file_filtered_init (BraseroFileFiltered *object)
 }
 
 static void
-brasero_file_filtered_finalize (GObject *object)
+brasero_file_filtered_set_property (GObject *object,
+				    guint property_id,
+				    const GValue *value,
+				    GParamSpec *pspec)
 {
 	BraseroFileFilteredPrivate *priv;
+	GtkTreeModel *model;
 
 	priv = BRASERO_FILE_FILTERED_PRIVATE (object);
 
-	if (priv->idle_id) {
-		g_source_remove (priv->idle_id);
-		priv->idle_id = 0;
-	}
+	switch (property_id) {
+	case PROP_TRACK: /* Readable and only writable at creation time */
+		priv->track = g_object_ref (g_value_get_object (value));
+		model = brasero_track_data_cfg_get_filtered_model (priv->track);
+		gtk_tree_view_set_model (GTK_TREE_VIEW (priv->tree), model);
+		g_object_unref (model);
+
+		g_signal_connect (g_value_get_object (value),
+				  "row-deleted",
+				  G_CALLBACK (brasero_file_filtered_row_deleted),
+				  object);
+		g_signal_connect (g_value_get_object (value),
+				  "row-inserted",
+				  G_CALLBACK (brasero_file_filtered_row_inserted),
+				  object);
+		break;
 
-	if (priv->hidden) {
-		g_slist_foreach (priv->hidden, (GFunc) g_free, NULL);
-		g_slist_free (priv->hidden);
-		priv->hidden = NULL;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 	}
+}
 
-	if (priv->broken) {
-		g_slist_foreach (priv->broken, (GFunc) g_free, NULL);
-		g_slist_free (priv->broken);
-		priv->broken = NULL;
-	}
+static void
+brasero_file_filtered_get_property (GObject *object,
+				    guint property_id,
+				    GValue *value,
+				    GParamSpec *pspec)
+{
+	BraseroFileFilteredPrivate *priv;
+
+	priv = BRASERO_FILE_FILTERED_PRIVATE (object);
+
+	switch (property_id) {
+	case PROP_TRACK:
+		g_value_set_object (value, G_OBJECT (priv->track));
+		break;
 
-	if (priv->recursive) {
-		g_slist_foreach (priv->recursive, (GFunc) g_free, NULL);
-		g_slist_free (priv->recursive);
-		priv->recursive = NULL;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 	}
+}
 
-	if (priv->unreadable) {
-		g_slist_foreach (priv->unreadable, (GFunc) g_free, NULL);
-		g_slist_free (priv->unreadable);
-		priv->unreadable = NULL;
+static void
+brasero_file_filtered_finalize (GObject *object)
+{
+	BraseroFileFilteredPrivate *priv;
+
+	priv = BRASERO_FILE_FILTERED_PRIVATE (object);
+	if (priv->track) {
+		g_object_unref (priv->track);
+		priv->track = NULL;
 	}
 
 	G_OBJECT_CLASS (brasero_file_filtered_parent_class)->finalize (object);
@@ -636,39 +395,28 @@ brasero_file_filtered_class_init (BraseroFileFilteredClass *klass)
 	g_type_class_add_private (klass, sizeof (BraseroFileFilteredPrivate));
 
 	object_class->finalize = brasero_file_filtered_finalize;
+	object_class->set_property = brasero_file_filtered_set_property;
+	object_class->get_property = brasero_file_filtered_get_property;
 
 	expander_class->activate = brasero_file_filtered_activate;
 
-	file_filtered_signals[FILTERED_SIGNAL] =
-		g_signal_new ("filtered",
-		              G_OBJECT_CLASS_TYPE (klass),
-		              G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
-		              G_STRUCT_OFFSET (BraseroFileFilteredClass, filtered),
-		              NULL, NULL,
-		              g_cclosure_marshal_VOID__STRING,
-		              G_TYPE_NONE, 1,
-		              G_TYPE_STRING);
-
-	file_filtered_signals[RESTORED_SIGNAL] =
-		g_signal_new ("restored",
-		              G_OBJECT_CLASS_TYPE (klass),
-		              G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
-		              G_STRUCT_OFFSET (BraseroFileFilteredClass, restored),
-		              NULL, NULL,
-		              g_cclosure_marshal_VOID__STRING,
-		              G_TYPE_NONE, 1,
-		              G_TYPE_STRING);
+	g_object_class_install_property (object_class,
+					 PROP_TRACK,
+					 g_param_spec_object ("track",
+							      "A BraseroTrackDataCfg",
+							      "The BraseroTrackDataCfg used by the internal GtkTreeView",
+							      BRASERO_TYPE_TRACK_DATA_CFG,
+							      G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
 }
 
 GtkWidget*
-brasero_file_filtered_new (void)
+brasero_file_filtered_new (BraseroTrackDataCfg *track)
 {
 	gchar *markup;
 	GtkWidget *object;
 
-	markup = brasero_file_filtered_get_label_text (0, FALSE);
 	object = g_object_new (BRASERO_TYPE_FILE_FILTERED,
-			       "label", markup,
+			       "track", track,
 			       "use-markup", TRUE,
 			       "use-underline", TRUE,
 			       NULL);
diff --git a/src/brasero-file-filtered.h b/src/brasero-file-filtered.h
index 2824817..5eb5a60 100644
--- a/src/brasero-file-filtered.h
+++ b/src/brasero-file-filtered.h
@@ -24,9 +24,9 @@
 #define _BRASERO_FILE_FILTERED_H_
 
 #include <glib-object.h>
-
 #include <gtk/gtk.h>
-#include "brasero-data-vfs.h"
+
+#include "brasero-track-data-cfg.h"
 
 G_BEGIN_DECLS
 
@@ -43,10 +43,6 @@ typedef struct _BraseroFileFiltered BraseroFileFiltered;
 struct _BraseroFileFilteredClass
 {
 	GtkExpanderClass parent_class;
-
-	/* Signals */
-	void	(*filtered) (BraseroFileFiltered *self, const gchar *uri);
-	void	(*restored) (BraseroFileFiltered *self, const gchar *uri);
 };
 
 struct _BraseroFileFiltered
@@ -57,24 +53,12 @@ struct _BraseroFileFiltered
 GType brasero_file_filtered_get_type (void) G_GNUC_CONST;
 
 GtkWidget*
-brasero_file_filtered_new (void);
+brasero_file_filtered_new (BraseroTrackDataCfg *track);
 
 void
 brasero_file_filtered_set_right_button_group (BraseroFileFiltered *self,
 					      GtkSizeGroup *group);
 
-void
-brasero_file_filtered_add (BraseroFileFiltered *filter,
-			   const gchar *uri,
-			   BraseroFilterStatus status);
-
-void
-brasero_file_filtered_remove (BraseroFileFiltered *filter,
-			      const gchar *uri);
-
-void
-brasero_file_filtered_clear (BraseroFileFiltered *self);
-
 G_END_DECLS
 
 #endif /* _BRASERO_FILE_FILTERED_H_ */
diff --git a/src/brasero-multi-dnd.c b/src/brasero-multi-dnd.c
index 2056d34..699d64d 100644
--- a/src/brasero-multi-dnd.c
+++ b/src/brasero-multi-dnd.c
@@ -24,6 +24,7 @@
 
 #include <gtk/gtk.h>
 
+#include "brasero-track-data-cfg.h"
 #include "eggtreemultidnd.h"
 
 static gboolean
@@ -124,6 +125,72 @@ static const GInterfaceInfo multi_DND_drag_source_info = {
 	NULL
 };
 
+static gboolean
+brasero_data_track_cfg_multi_DND_row_draggable (EggTreeMultiDragSource *drag_source,
+						GList *path_list)
+{
+	GList *iter;
+
+	/* at least one row must not be an imported row. */
+	for (iter = path_list; iter && iter->data; iter = iter->next) {
+		GtkTreePath *path;
+		GtkTreeRowReference *reference;
+
+		reference = iter->data;
+		path = gtk_tree_row_reference_get_path (reference);
+		if (gtk_tree_drag_source_row_draggable (GTK_TREE_DRAG_SOURCE (drag_source), path)) {
+			gtk_tree_path_free (path);
+			return TRUE;
+		}
+		gtk_tree_path_free (path);
+	}
+
+	return FALSE;
+}
+
+static gboolean
+brasero_data_track_cfg_multi_DND_drag_data_get (EggTreeMultiDragSource *drag_source,
+						GList *path_list,
+						GtkSelectionData *selection_data)
+{
+	if (selection_data->target == gdk_atom_intern (BRASERO_DND_TARGET_DATA_TRACK_REFERENCE_LIST, TRUE)) {
+		gtk_selection_data_set (selection_data,
+					gdk_atom_intern_static_string (BRASERO_DND_TARGET_DATA_TRACK_REFERENCE_LIST),
+					8,
+					(void *) path_list,
+					sizeof (path_list));
+	}
+	else
+		return FALSE;
+
+	return TRUE;
+}
+
+static gboolean
+brasero_data_track_cfg_multi_DND_drag_data_delete (EggTreeMultiDragSource *drag_source,
+						   GList *path_list)
+{
+	/* NOTE: it's not the data in the selection_data here that should be
+	 * deleted but rather the rows selected when there is a move. FALSE
+	 * here means that we didn't delete anything. */
+	/* return TRUE to stop other handlers */
+	return TRUE;
+}
+
+static void
+brasero_data_track_cfg_multi_DND_drag_source_init (EggTreeMultiDragSourceIface *iface)
+{
+	iface->row_draggable = brasero_data_track_cfg_multi_DND_row_draggable;
+	iface->drag_data_get = brasero_data_track_cfg_multi_DND_drag_data_get;
+	iface->drag_data_delete = brasero_data_track_cfg_multi_DND_drag_data_delete;
+}
+
+static const GInterfaceInfo brasero_data_track_cfg_multi_DND_drag_source_info = {
+	(GInterfaceInitFunc) brasero_data_track_cfg_multi_DND_drag_source_init,
+	NULL,
+	NULL
+};
+
 void
 brasero_enable_multi_DND (void)
 {
@@ -148,5 +215,9 @@ brasero_enable_multi_DND (void)
 	g_type_add_interface_static (object_type,
 				     EGG_TYPE_TREE_MULTI_DRAG_SOURCE,
 				     &multi_DND_drag_source_info);
+
+	g_type_add_interface_static (BRASERO_TYPE_TRACK_DATA_CFG,
+				     EGG_TYPE_TREE_MULTI_DRAG_SOURCE,
+				     &brasero_data_track_cfg_multi_DND_drag_source_info);
 }
  



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