diff options
author | Stefano Teso <stefano.teso@gmail.com> | 2011-02-25 14:58:48 -0500 |
---|---|---|
committer | Cosimo Cecchi <cosimoc@gnome.org> | 2011-02-25 15:02:06 -0500 |
commit | a9515134c3bce4df1d1563340394b796ae40d183 (patch) | |
tree | adf8bf1dc0238af2c2708a9bd986d4ff448865ff | |
parent | 97b1ff2fa3b4d706969ab40d4bf17adad281e42f (diff) | |
download | nautilus-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.c | 158 | ||||
-rw-r--r-- | src/nautilus-view.c | 74 | ||||
-rw-r--r-- | 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 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 |