[nautilus] list-view: create folders in subdirectories when possible



commit a9515134c3bce4df1d1563340394b796ae40d183
Author: Stefano Teso <stefano teso gmail com>
Date:   Fri Feb 25 14:58:48 2011 -0500

    list-view: create folders in subdirectories when possible
    
    Don't always choose the tree root as parent when creating a new folder,
    but look at the current selection's directory.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=330644

 src/nautilus-list-view.c |  158 ++++++++++++++++++++++++++++++++++++++++++++++
 src/nautilus-view.c      |   74 +++++++++++++--------
 src/nautilus-view.h      |    8 +++
 3 files changed, 212 insertions(+), 28 deletions(-)
---
diff --git a/src/nautilus-list-view.c b/src/nautilus-list-view.c
index 0ab7c14..ede500f 100644
--- a/src/nautilus-list-view.c
+++ b/src/nautilus-list-view.c
@@ -2025,6 +2025,163 @@ nautilus_list_view_file_changed (NautilusView *view, NautilusFile *file, Nautilu
 	}
 }
 
+typedef struct {
+	GtkTreePath *path;
+	gboolean is_common;
+	gboolean is_root;
+} HasCommonParentData;
+
+static void
+tree_selection_has_common_parent_foreach_func (GtkTreeModel *model,
+						GtkTreePath *path,
+						GtkTreeIter *iter,
+						gpointer user_data)
+{
+	HasCommonParentData *data;
+	GtkTreePath *parent_path;
+	gboolean has_parent;
+
+	data = (HasCommonParentData *) user_data;
+
+	parent_path = gtk_tree_path_copy (path);
+	gtk_tree_path_up (parent_path);
+
+	has_parent = (gtk_tree_path_get_depth (parent_path) > 0) ? TRUE : FALSE;
+
+	if (!has_parent) {
+		data->is_root = TRUE;
+	}
+
+	if (data->is_common && !data->is_root) {
+		if (data->path == NULL) {
+			data->path = gtk_tree_path_copy (parent_path);
+		} else if (gtk_tree_path_compare (data->path, parent_path) != 0) {
+			data->is_common = FALSE;
+		}
+	}
+
+	gtk_tree_path_free (parent_path);
+}
+
+static void
+tree_selection_has_common_parent (GtkTreeSelection *selection,
+				  gboolean *is_common,
+				  gboolean *is_root)
+{
+	HasCommonParentData data;
+
+	g_assert (is_common != NULL);
+	g_assert (is_root != NULL);
+
+	data.path = NULL;
+	data.is_common = *is_common = TRUE;
+	data.is_root = *is_root = FALSE;
+
+	gtk_tree_selection_selected_foreach (selection,
+					     tree_selection_has_common_parent_foreach_func,
+					     &data);
+
+	*is_common = data.is_common;
+	*is_root = data.is_root;
+
+	if (data.path != NULL) {
+		gtk_tree_path_free (data.path);
+	}
+}
+
+static char *
+nautilus_list_view_get_backing_uri (NautilusView *view)
+{
+	NautilusListView *list_view;
+	NautilusListModel *list_model;
+	NautilusFile *file;
+	GtkTreeView *tree_view;
+	GtkTreeSelection *selection;
+	GtkTreePath *path;
+	GList *paths;
+	guint length;
+	char *uri;
+
+	g_return_val_if_fail (NAUTILUS_IS_LIST_VIEW (view), NULL);
+
+	list_view = NAUTILUS_LIST_VIEW (view);
+	list_model = list_view->details->model;
+	tree_view = list_view->details->tree_view;
+
+	g_assert (list_model);
+
+	/* We currently handle three common cases here:
+	 * (a) if the selection contains non-filesystem items (i.e., the
+	 *     "(Empty)" label), we return the uri of the parent.
+	 * (b) if the selection consists of exactly one _expanded_ directory, we
+	 *     return its URI.
+	 * (c) if the selection consists of either exactly one item which is not
+	 *     an expanded directory) or multiple items in the same directory,
+	 *     we return the URI of the common parent.
+	 */
+
+	uri = NULL;
+
+	selection = gtk_tree_view_get_selection (tree_view);
+	length = gtk_tree_selection_count_selected_rows (selection);
+
+	if (length == 1) {
+
+		paths = gtk_tree_selection_get_selected_rows (selection, NULL);
+		path = (GtkTreePath *) paths->data;
+
+		file = nautilus_list_model_file_for_path (list_model, path);
+		if (file == NULL) {
+			/* The selected item is a label, not a file */
+			gtk_tree_path_up (path);
+			file = nautilus_list_model_file_for_path (list_model, path);
+		}
+
+		if (file != NULL) {
+			if (nautilus_file_is_directory (file) &&
+			    gtk_tree_view_row_expanded (tree_view, path)) {
+				uri = nautilus_file_get_uri (file);
+			}
+			nautilus_file_unref (file);
+		}
+
+		gtk_tree_path_free (path);
+		g_list_free (paths);
+	}
+
+	if (uri == NULL && length > 0) {
+
+		gboolean is_common, is_root;
+
+		/* Check that all the selected items belong to the same
+		 * directory and that directory is not the root directory (which
+		 * is handled by NautilusView::get_backing_directory.) */
+
+		tree_selection_has_common_parent (selection, &is_common, &is_root);
+
+		if (is_common && !is_root) {
+
+			paths = gtk_tree_selection_get_selected_rows (selection, NULL);
+			path = (GtkTreePath *) paths->data;
+
+			file = nautilus_list_model_file_for_path (list_model, path);
+			g_assert (file != NULL);
+			uri = nautilus_file_get_parent_uri (file);
+			nautilus_file_unref (file);
+
+			g_list_foreach (paths, (GFunc) gtk_tree_path_free, NULL);
+			g_list_free (paths);
+		}
+	}
+
+	if (uri != NULL) {
+		return uri;
+	}
+
+	return EEL_CALL_PARENT_WITH_RETURN_VALUE (NAUTILUS_VIEW_CLASS,
+						  get_backing_uri, (view));
+}
+
 static void
 nautilus_list_view_get_selection_foreach_func (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
 {
@@ -3100,6 +3257,7 @@ nautilus_list_view_class_init (NautilusListViewClass *class)
         nautilus_view_class->click_policy_changed = nautilus_list_view_click_policy_changed;
 	nautilus_view_class->clear = nautilus_list_view_clear;
 	nautilus_view_class->file_changed = nautilus_list_view_file_changed;
+	nautilus_view_class->get_backing_uri = nautilus_list_view_get_backing_uri;
 	nautilus_view_class->get_selection = nautilus_list_view_get_selection;
 	nautilus_view_class->get_selection_for_file_transfer = nautilus_list_view_get_selection_for_file_transfer;
 	nautilus_view_class->get_item_count = nautilus_list_view_get_item_count;
diff --git a/src/nautilus-view.c b/src/nautilus-view.c
index 3df845a..18d35c9 100644
--- a/src/nautilus-view.c
+++ b/src/nautilus-view.c
@@ -360,6 +360,51 @@ nautilus_view_unmerge_menus (NautilusView *view)
 		 unmerge_menus, (view));
 }
 
+static char *
+real_get_backing_uri (NautilusView *view)
+{
+	NautilusDirectory *directory;
+	char *uri;
+       
+	g_return_val_if_fail (NAUTILUS_IS_VIEW (view), NULL);
+
+	if (view->details->model == NULL) {
+		return NULL;
+	}
+       
+	directory = view->details->model;
+       
+	if (NAUTILUS_IS_DESKTOP_DIRECTORY (directory)) {
+		directory = nautilus_desktop_directory_get_real_directory (NAUTILUS_DESKTOP_DIRECTORY (directory));
+	} else {
+		nautilus_directory_ref (directory);
+	}
+       
+	uri = nautilus_directory_get_uri (directory);
+
+	nautilus_directory_unref (directory);
+
+	return uri;
+}
+
+/**
+ *
+ * nautilus_view_get_backing_uri:
+ *
+ * Returns the URI for the target location of new directory, new file, new
+ * link, new launcher, and paste operations.
+ */
+
+char *
+nautilus_view_get_backing_uri (NautilusView *view)
+{
+	g_return_val_if_fail (NAUTILUS_IS_VIEW (view), NULL);
+
+	return EEL_CALL_METHOD_WITH_RETURN_VALUE
+		(NAUTILUS_VIEW_CLASS, view,
+		 get_backing_uri, (view));
+}
+
 /**
  * nautilus_view_select_all:
  *
@@ -1287,34 +1332,6 @@ action_other_application_callback (GtkAction *action,
 	open_with_other_program (NAUTILUS_VIEW (callback_data));
 }
 
-/* Get the real directory where files will be stored and created */
-char *
-nautilus_view_get_backing_uri (NautilusView *view)
-{
-	NautilusDirectory *directory;
-	char *uri;
-	
-	g_return_val_if_fail (NAUTILUS_IS_VIEW (view), NULL);
-
-	if (view->details->model == NULL) {
-		return NULL;
-	}
-	
-	directory = view->details->model;
-	
-	if (NAUTILUS_IS_DESKTOP_DIRECTORY (directory)) {
-		directory = nautilus_desktop_directory_get_real_directory (NAUTILUS_DESKTOP_DIRECTORY (directory));
-	} else {
-		nautilus_directory_ref (directory);
-	}
-	
-	uri = nautilus_directory_get_uri (directory);
-
-	nautilus_directory_unref (directory);
-
-	return uri;
-}
-
 static void
 trash_or_delete_selected_files (NautilusView *view)
 {
@@ -9760,6 +9777,7 @@ nautilus_view_class_init (NautilusViewClass *klass)
 	klass->load_error = real_load_error;
 	klass->can_rename_file = can_rename_file;
 	klass->start_renaming_file = start_renaming_file;
+	klass->get_backing_uri = real_get_backing_uri;
 	klass->using_manual_layout = real_using_manual_layout;
         klass->merge_menus = real_merge_menus;
         klass->unmerge_menus = real_unmerge_menus;
diff --git a/src/nautilus-view.h b/src/nautilus-view.h
index d5afaf1..b53c45f 100644
--- a/src/nautilus-view.h
+++ b/src/nautilus-view.h
@@ -142,6 +142,14 @@ struct NautilusViewClass {
          */
         void     (* reset_to_defaults)	         (NautilusView *view);
 
+	/* get_backing uri is a function pointer for subclasses to
+	 * override. Subclasses may replace it with a function that
+	 * returns the URI for the location where to create new folders,
+	 * files, links, launchers, and paste the clipboard to.
+	 */
+
+	char *	(* get_backing_uri)		(NautilusView *view);
+
 	/* get_selection is not a signal; it is just a function pointer for
 	 * subclasses to replace (override). Subclasses must replace it
 	 * with a function that returns a newly-allocated GList of



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