summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefano Teso <stefano.teso@gmail.com>2011-02-25 14:58:48 -0500
committerCosimo Cecchi <cosimoc@gnome.org>2011-02-25 15:02:06 -0500
commita9515134c3bce4df1d1563340394b796ae40d183 (patch)
treeadf8bf1dc0238af2c2708a9bd986d4ff448865ff
parent97b1ff2fa3b4d706969ab40d4bf17adad281e42f (diff)
downloadnautilus-a9515134c3bce4df1d1563340394b796ae40d183.tar.gz
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
-rw-r--r--src/nautilus-list-view.c158
-rw-r--r--src/nautilus-view.c74
-rw-r--r--src/nautilus-view.h8
3 files changed, 212 insertions, 28 deletions
diff --git a/src/nautilus-list-view.c b/src/nautilus-list-view.c
index 0ab7c14e8..ede500f69 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 3df845ae1..18d35c92f 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 d5afaf1c0..b53c45f16 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