From 328348c6f76bc72823c1a8464937b7f4208674d9 Mon Sep 17 00:00:00 2001 From: Carlos Soriano Date: Sat, 15 Aug 2015 17:20:21 +0200 Subject: nautilus-view: use popover for renaming Some users felt it quite disruptive to us a dialog, even if the attention has to be on the name entry. Also it's the way that GtkFileChooser implemented it and it actually feels less disruptive and desigerns agreed it works better. So continue to use a dialog for the new folder creation, but use a popover for renaming. --- src/nautilus-canvas-view.c | 18 ++ src/nautilus-create-folder-dialog.ui | 82 +++++++ src/nautilus-file-name-dialog.ui | 82 ------- src/nautilus-list-view.c | 42 ++++ src/nautilus-rename-file-popover.ui | 66 ++++++ src/nautilus-view.c | 436 +++++++++++++++++++---------------- src/nautilus-view.h | 2 + src/nautilus.gresource.xml | 3 +- 8 files changed, 443 insertions(+), 288 deletions(-) create mode 100644 src/nautilus-create-folder-dialog.ui delete mode 100644 src/nautilus-file-name-dialog.ui create mode 100644 src/nautilus-rename-file-popover.ui (limited to 'src') diff --git a/src/nautilus-canvas-view.c b/src/nautilus-canvas-view.c index 53e37d9d5..8d42d6f83 100644 --- a/src/nautilus-canvas-view.c +++ b/src/nautilus-canvas-view.c @@ -1172,6 +1172,23 @@ nautilus_canvas_view_reveal_selection (NautilusView *view) nautilus_file_list_free (selection); } +static GdkRectangle* +nautilus_canvas_view_compute_rename_popover_relative_to (NautilusView *view) +{ + GArray *bounding_boxes; + GdkRectangle *bounding_box; + NautilusCanvasContainer *canvas_container; + + canvas_container = get_canvas_container (NAUTILUS_CANVAS_VIEW (view)); + bounding_boxes = nautilus_canvas_container_get_selected_icons_bounding_box (canvas_container); + /* We only allow renaming one item at once */ + bounding_box = &g_array_index (bounding_boxes, GdkRectangle, 0); + + g_array_free (bounding_boxes, FALSE); + + return bounding_box; +} + static GArray * nautilus_canvas_view_get_selected_icon_locations (NautilusView *view) { @@ -1877,6 +1894,7 @@ nautilus_canvas_view_class_init (NautilusCanvasViewClass *klass) nautilus_view_class->end_loading = nautilus_canvas_view_end_loading; nautilus_view_class->file_changed = nautilus_canvas_view_file_changed; nautilus_view_class->get_selected_icon_locations = nautilus_canvas_view_get_selected_icon_locations; + nautilus_view_class->compute_rename_popover_relative_to = nautilus_canvas_view_compute_rename_popover_relative_to; nautilus_view_class->get_selection = nautilus_canvas_view_get_selection; nautilus_view_class->get_selection_for_file_transfer = nautilus_canvas_view_get_selection; nautilus_view_class->is_empty = nautilus_canvas_view_is_empty; diff --git a/src/nautilus-create-folder-dialog.ui b/src/nautilus-create-folder-dialog.ui new file mode 100644 index 000000000..21bf6b2ad --- /dev/null +++ b/src/nautilus-create-folder-dialog.ui @@ -0,0 +1,82 @@ + + + + + False + True + center-on-parent + True + dialog + 1 + 450 + + + vertical + 18 + 12 + 18 + 18 + 6 + + + True + 0 + + + False + True + 1 + + + + + True + True + + + + + False + True + 2 + + + + + True + 0 + + + + False + True + 3 + + + + + + + Cancel + True + True + True + + + + + True + True + True + True + False + + + + ok_button + cancel_button + + + diff --git a/src/nautilus-file-name-dialog.ui b/src/nautilus-file-name-dialog.ui deleted file mode 100644 index 4e2c4c770..000000000 --- a/src/nautilus-file-name-dialog.ui +++ /dev/null @@ -1,82 +0,0 @@ - - - - - False - True - center-on-parent - True - dialog - 1 - 450 - - - vertical - 18 - 12 - 18 - 18 - 6 - - - True - 0 - - - False - True - 1 - - - - - True - True - - - - - False - True - 2 - - - - - True - 0 - - - - False - True - 3 - - - - - - - Cancel - True - True - True - - - - - True - True - True - True - False - - - - ok_button - cancel_button - - - diff --git a/src/nautilus-list-view.c b/src/nautilus-list-view.c index 20a4882c4..35a7472f6 100644 --- a/src/nautilus-list-view.c +++ b/src/nautilus-list-view.c @@ -59,6 +59,12 @@ #define DEBUG_FLAG NAUTILUS_DEBUG_LIST_VIEW #include +/* We use a rectangle to make the popover point to the right column. In an + * ideal world with GtkListBox we would just point to the GtkListBoxRow. In our case, we + * need to use a rectangle and we provide some width to not make the popover arrow pointy + * in the edges if the window is small */ +#define RENAME_POPOVER_RELATIVE_TO_RECTANGLE_WIDTH 40 + struct NautilusListViewDetails { GtkTreeView *tree_view; NautilusListModel *model; @@ -3240,6 +3246,41 @@ nautilus_list_view_get_id (NautilusView *view) return NAUTILUS_LIST_VIEW_ID; } +static GdkRectangle* +nautilus_list_view_compute_rename_popover_relative_to (NautilusView *view) +{ + GtkTreeSelection *selection; + GtkTreePath *path; + GdkRectangle *rect; + GtkTreeModel *model; + GtkTreeView *tree_view; + GList *list; + NautilusListView *list_view; + + rect = g_malloc0 (sizeof(GdkRectangle)); + list_view = NAUTILUS_LIST_VIEW (view); + tree_view = list_view->details->tree_view; + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (list_view->details->tree_view)); + model = GTK_TREE_MODEL (list_view->details->model); + list = gtk_tree_selection_get_selected_rows (selection, &model); + path = list->data; + gtk_tree_view_get_cell_area (tree_view, path, NULL, rect); + gtk_tree_view_convert_bin_window_to_widget_coords (tree_view, + rect->x, rect->y, + &rect->x, &rect->y); + + rect->x = CLAMP (gtk_widget_get_allocated_width (GTK_WIDGET (tree_view)) * 0.5 - + RENAME_POPOVER_RELATIVE_TO_RECTANGLE_WIDTH * 0.5, + 0, + gtk_widget_get_allocated_width (GTK_WIDGET (tree_view)) - + RENAME_POPOVER_RELATIVE_TO_RECTANGLE_WIDTH); + rect->width = RENAME_POPOVER_RELATIVE_TO_RECTANGLE_WIDTH; + + g_list_free_full (list, (GDestroyNotify) gtk_tree_path_free); + + return rect; +} + static void nautilus_list_view_class_init (NautilusListViewClass *class) { @@ -3277,6 +3318,7 @@ nautilus_list_view_class_init (NautilusListViewClass *class) nautilus_view_class->get_view_id = nautilus_list_view_get_id; nautilus_view_class->get_first_visible_file = nautilus_list_view_get_first_visible_file; nautilus_view_class->scroll_to_file = list_view_scroll_to_file; + nautilus_view_class->compute_rename_popover_relative_to = nautilus_list_view_compute_rename_popover_relative_to; } static void diff --git a/src/nautilus-rename-file-popover.ui b/src/nautilus-rename-file-popover.ui new file mode 100644 index 000000000..5214857c2 --- /dev/null +++ b/src/nautilus-rename-file-popover.ui @@ -0,0 +1,66 @@ + + + + bottom + + + + True + 10 + 6 + 6 + + + True + Name + start + name_entry + + + + + + 2 + + + + + True + True + + + 0 + 1 + + + + + True + False + _Rename + True + True + + + + 1 + 1 + + + + + True + start + + + 0 + 2 + 2 + + + + + + diff --git a/src/nautilus-view.c b/src/nautilus-view.c index 073bacc0e..d5ec6a121 100644 --- a/src/nautilus-view.c +++ b/src/nautilus-view.c @@ -116,8 +116,8 @@ #define MAX_MENU_LEVELS 5 #define TEMPLATE_LIMIT 30 -/* Time to show the duplicated folder label */ -#define DIALOG_DUPLICATED_NAME_ERROR_LABEL_TIMEOUT 500 +/* Delay to show the duplicated label when creating a folder */ +#define CREATE_FOLDER_DUPLICATED_LABEL_TIMEOUT 500 /* Delay to show the Loading... floating bar */ #define FLOATING_BAR_LOADING_DELAY 500 /* ms */ @@ -159,7 +159,8 @@ struct NautilusViewDetails NautilusFile *directory_as_file; guint dir_merge_id; - gint dialog_duplicated_name_label_timeout_id; + gint create_folder_duplicated_label_timeout_id; + GtkWidget *rename_file_popover; gboolean supports_zooming; @@ -1699,16 +1700,18 @@ context_menu_to_file_operation_position (NautilusView *view) typedef struct { NautilusView *view; - GtkWidget *dialog; + GtkWidget *widget; GtkWidget *error_label; GtkWidget *name_entry; gboolean target_is_folder; NautilusFile *target_file; + GtkWidget *activate_button; gboolean duplicated_is_folder; -} FileNameDialogData; +} FileNameWidgetData; typedef struct { NautilusView *view; + GtkWidget *widget; GtkWidget *name_entry; NautilusFile *target_file; } RenameDialogData; @@ -1720,143 +1723,152 @@ typedef struct { } NewFolderDialogData; static gboolean -duplicated_file_label_show (FileNameDialogData *data) +duplicated_file_label_show (FileNameWidgetData *data) { if (data->duplicated_is_folder) gtk_label_set_label (GTK_LABEL (data->error_label), _("A folder with that name already exists.")); else gtk_label_set_label (GTK_LABEL (data->error_label), _("A file with that name already exists.")); - data->view->details->dialog_duplicated_name_label_timeout_id = 0; - return FALSE; + data->view->details->create_folder_duplicated_label_timeout_id = 0; + + return G_SOURCE_REMOVE; } -static void -nautilus_view_file_name_dialog_validate_name (FileNameDialogData *data) +static gchar* +validate_file_name (const gchar *name, + gboolean is_folder) { - gboolean duplicated_name; - gboolean valid_name; - gchar *name; - GList *files; - GList *node; - NautilusFile *file; - - g_assert (data != NULL); - g_assert (GTK_IS_ENTRY (data->name_entry)); - g_assert (GTK_IS_LABEL (data->error_label)); - g_assert (GTK_IS_DIALOG (data->dialog)); - g_assert (NAUTILUS_IS_VIEW (data->view)); + gchar *error_message = NULL; - name = g_strstrip (g_strdup (gtk_entry_get_text (GTK_ENTRY (data->name_entry)))); - duplicated_name = FALSE; - valid_name = FALSE; - files = nautilus_directory_get_file_list (data->view->details->model); - - for (node = files; node != NULL; node = node->next) { - file = node->data; - - if (nautilus_file_compare_display_name (file, name) == 0) { - /* If we are renaming, we don't want to block the user to - * rename the file with the current file name */ - if (data->target_file == NULL || - nautilus_file_compare_display_name (data->target_file, name) != 0) { - duplicated_name = TRUE; - data->duplicated_is_folder = nautilus_file_is_directory (file); - break; - } - } - } - - nautilus_file_list_free (files); - - /* Remove any sources left behind by - * previous calls of this function. - */ - if (data->view->details->dialog_duplicated_name_label_timeout_id > 0) { - g_source_remove (data->view->details->dialog_duplicated_name_label_timeout_id); - data->view->details->dialog_duplicated_name_label_timeout_id = 0; - } - - if (duplicated_name) { - data->view->details->dialog_duplicated_name_label_timeout_id = - g_timeout_add (DIALOG_DUPLICATED_NAME_ERROR_LABEL_TIMEOUT, - (GSourceFunc)duplicated_file_label_show, - data); - } else if (strstr (name, "/") != NULL) { - if (data->target_is_folder) - gtk_label_set_label (GTK_LABEL (data->error_label), _("Folder names cannot contain “/”.")); + if (strstr (name, "/") != NULL) { + if (is_folder) + error_message = _("Folder names cannot contain “/”."); else - gtk_label_set_label (GTK_LABEL (data->error_label), _("Files names cannot contain “/”.")); + error_message = _("Files names cannot contain “/”."); } else if (strcmp (name, ".") == 0){ - if (data->target_is_folder) - gtk_label_set_label (GTK_LABEL (data->error_label), _("A folder can not be called “.”.")); + if (is_folder) + error_message = _("A folder can not be called “.”."); else - gtk_label_set_label (GTK_LABEL (data->error_label), _("A file can not be called “.”.")); + error_message = _("A file can not be called “.”."); } else if (strcmp (name, "..") == 0){ - if (data->target_is_folder) - gtk_label_set_label (GTK_LABEL (data->error_label), _("A folder can not be called “..”.")); + if (is_folder) + error_message = _("A folder can not be called “..”."); else - gtk_label_set_label (GTK_LABEL (data->error_label), _("A file can not be called “..”.")); - } else { - /* No errors detected, empty the label */ - gtk_label_set_label (GTK_LABEL (data->error_label), NULL); - valid_name = strlen (name) > 0; + error_message = _("A file can not be called “..”."); } - gtk_dialog_set_response_sensitive (GTK_DIALOG (data->dialog), - GTK_RESPONSE_OK, - valid_name); - g_free (name); + return error_message; } static void -nautilus_view_file_name_dialog_entry_on_validate (GObject *object, - GParamSpec *params, - gpointer user_data) +create_folder_dialog_entry_on_changed (GtkEntry *entry, + gpointer user_data) { - FileNameDialogData *data; + FileNameWidgetData *data; + NautilusFile *existing_file; + gchar *name; + gchar *error_message; + gboolean valid_name; + gboolean can_create_folder; + + data = (FileNameWidgetData *) user_data; + name = g_strstrip (g_strdup (gtk_entry_get_text (GTK_ENTRY (data->name_entry)))); + error_message = validate_file_name (name, TRUE); + gtk_label_set_label (GTK_LABEL (data->error_label), error_message); + + existing_file = nautilus_directory_get_file_by_name (data->view->details->model, name); + + valid_name = strlen (name) > 0 && error_message == NULL; + can_create_folder = existing_file == NULL && valid_name; + gtk_widget_set_sensitive (data->activate_button, can_create_folder); - data = (FileNameDialogData *) user_data; + if (data->view->details->create_folder_duplicated_label_timeout_id > 0) { + g_source_remove (data->view->details->create_folder_duplicated_label_timeout_id); + data->view->details->create_folder_duplicated_label_timeout_id = 0; + } + + /* Report duplicated file only if not other message shown (for instance, + * folders like "." or ".." will always exists, but we consider it as an + * error, not as a duplicated file) */ + if (existing_file != NULL && valid_name) { + data->duplicated_is_folder = nautilus_file_is_directory (existing_file); + data->view->details->create_folder_duplicated_label_timeout_id = + g_timeout_add (CREATE_FOLDER_DUPLICATED_LABEL_TIMEOUT, + (GSourceFunc)duplicated_file_label_show, + data); + } - nautilus_view_file_name_dialog_validate_name (data); + if (existing_file != NULL) + nautilus_file_unref (existing_file); } static void -nautilus_view_file_name_dialog_entry_on_activate (GtkWidget *entry, - gpointer user_data) +rename_file_popover_entry_on_changed (GtkEntry *entry, + gpointer user_data) { - FileNameDialogData *data; - GtkWidget *create_button; + FileNameWidgetData *data; + gboolean valid_name; + gchar *name; + gchar *error_message; - data = (FileNameDialogData *) user_data; - create_button = gtk_dialog_get_widget_for_response (GTK_DIALOG (data->dialog), - GTK_RESPONSE_OK); + data = (FileNameWidgetData *) user_data; + name = g_strstrip (g_strdup (gtk_entry_get_text (GTK_ENTRY (data->name_entry)))); + error_message = validate_file_name (name, nautilus_file_is_directory (data->target_file)); + gtk_label_set_label (GTK_LABEL (data->error_label), error_message); - /* nautilus_view_new_folder_dialog_validate_name performs - * all the necessary validation, and it's not needed to check - * it all again. Checking if the "Create" button is sensitive - * is enough. - */ - if (gtk_widget_get_sensitive (create_button)) { - gtk_dialog_response (GTK_DIALOG (data->dialog), + valid_name = strlen (name) > 0 && error_message == NULL; + gtk_widget_set_sensitive (data->activate_button, valid_name); + + g_free (name); +} + +static void +create_folder_dialog_entry_on_activate (GtkWidget *entry, + gpointer user_data) +{ + FileNameWidgetData *data; + NautilusFile *existing_file; + gchar *name; + gchar *error_message; + gboolean valid_name; + gboolean can_create_folder; + + data = (FileNameWidgetData *) user_data; + name = g_strstrip (g_strdup (gtk_entry_get_text (GTK_ENTRY (data->name_entry)))); + existing_file = nautilus_directory_get_file_by_name (data->view->details->model, name); + error_message = validate_file_name (name, TRUE); + valid_name = strlen (name) > 0 && error_message == NULL; + can_create_folder = existing_file == NULL && valid_name; + + if (data->view->details->create_folder_duplicated_label_timeout_id > 0) { + g_source_remove (data->view->details->create_folder_duplicated_label_timeout_id); + data->view->details->create_folder_duplicated_label_timeout_id = 0; + } + + if (can_create_folder) { + gtk_dialog_response (GTK_DIALOG (data->widget), GTK_RESPONSE_OK); - } else { - NautilusView *view = data->view; + } else { + /* Report duplicated file only if not other message shown (for instance, + * folders like "." or ".." will always exists, but we consider it as an + * error, not as a duplicated file) */ + if (existing_file != NULL && valid_name) { + data->duplicated_is_folder = nautilus_file_is_directory (existing_file); + /* Show it inmediatily since the user tried to trigger the action */ + duplicated_file_label_show (data); + } + } - /* Since typos are immediately shown, only - * handle name collisions here. - */ - if (view->details->dialog_duplicated_name_label_timeout_id > 0) { - g_source_remove (view->details->dialog_duplicated_name_label_timeout_id); - duplicated_file_label_show (data); - } - } + if (existing_file != NULL) + nautilus_file_unref (existing_file); + + g_free (name); } static void -nautilus_view_rename_dialog_on_response (GtkDialog *dialog, - gint response_id, - gpointer user_data) +rename_file_popover_rename_button_on_clicked (GtkButton *entry, + gpointer *user_data) { RenameDialogData *rename_data; gchar *name; @@ -1867,96 +1879,113 @@ nautilus_view_rename_dialog_on_response (GtkDialog *dialog, g_assert (GTK_IS_ENTRY (rename_data->name_entry)); g_assert (NAUTILUS_IS_FILE (rename_data->target_file)); - if (response_id == GTK_RESPONSE_OK) { - name = g_strstrip (g_strdup (gtk_entry_get_text (GTK_ENTRY (rename_data->name_entry)))); - nautilus_rename_file (rename_data->target_file, name, NULL, NULL); - g_free (name); - } + name = g_strstrip (g_strdup (gtk_entry_get_text (GTK_ENTRY (rename_data->name_entry)))); + nautilus_rename_file (rename_data->target_file, name, NULL, NULL); + g_free (name); + nautilus_view_select_file (rename_data->view, rename_data->target_file); nautilus_view_reveal_selection (rename_data->view); - /* If there's any resources left from the delayed - * message, it should be removed before it gets - * triggered. - */ - if (rename_data->view->details->dialog_duplicated_name_label_timeout_id > 0) { - g_source_remove (rename_data->view->details->dialog_duplicated_name_label_timeout_id); - rename_data->view->details->dialog_duplicated_name_label_timeout_id = 0; - } + gtk_widget_hide (rename_data->widget); - g_free (user_data); - gtk_widget_destroy (GTK_WIDGET (dialog)); + g_free (rename_data); +} + +static void +rename_file_popover_on_closed (GtkPopover *popover, + gpointer user_data) +{ + FileNameWidgetData *widget_data; + + widget_data = (FileNameWidgetData *) user_data; + widget_data->view->details->rename_file_popover = NULL; + g_free (widget_data); +} + +static GdkRectangle* +nautilus_view_compute_rename_popover_relative_to (NautilusView *view) +{ + return NAUTILUS_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->compute_rename_popover_relative_to (view); } static void -nautilus_view_rename_dialog_new (NautilusView *view, - NautilusFile *target_file) +nautilus_view_rename_file_popover_new (NautilusView *view, + NautilusFile *target_file) { - FileNameDialogData *dialog_data; - RenameDialogData *user_data; - GtkWidget *button_ok; + FileNameWidgetData *widget_data; + RenameDialogData *rename_data; GtkWidget *label_file_name; GtkBuilder *builder; gint start_offset, end_offset; - gchar *file_name; - gchar *title; + GdkRectangle *relative_to; - builder = gtk_builder_new_from_resource ("/org/gnome/nautilus/nautilus-file-name-dialog.ui"); - button_ok = GTK_WIDGET (gtk_builder_get_object (builder, "ok_button")); - label_file_name = GTK_WIDGET (gtk_builder_get_object (builder, "name_label")); + if (view->details->rename_file_popover != NULL) + return; - dialog_data = g_new (FileNameDialogData, 1); - dialog_data->view = view; - dialog_data->dialog = GTK_WIDGET (gtk_builder_get_object (builder, "file_name_dialog")); - dialog_data->error_label = GTK_WIDGET (gtk_builder_get_object (builder, "error_label")); - dialog_data->name_entry = GTK_WIDGET (gtk_builder_get_object (builder, "name_entry")); - dialog_data->target_is_folder = nautilus_file_is_directory (target_file); - dialog_data->target_file = target_file; + builder = gtk_builder_new_from_resource ("/org/gnome/nautilus/nautilus-rename-file-popover.ui"); + label_file_name = GTK_WIDGET (gtk_builder_get_object (builder, "name_label")); - user_data = g_new (RenameDialogData, 1); - user_data->view = view; - user_data->target_file = target_file; - user_data->name_entry = dialog_data->name_entry; + widget_data = g_new (FileNameWidgetData, 1); + widget_data->view = view; + widget_data->widget = GTK_WIDGET (gtk_builder_get_object (builder, "rename_file_popover")); + widget_data->activate_button = GTK_WIDGET (gtk_builder_get_object (builder, "rename_button")); + widget_data->error_label = GTK_WIDGET (gtk_builder_get_object (builder, "error_label")); + widget_data->name_entry = GTK_WIDGET (gtk_builder_get_object (builder, "name_entry")); + widget_data->target_is_folder = nautilus_file_is_directory (target_file); + widget_data->target_file = target_file; - gtk_window_set_transient_for (GTK_WINDOW (dialog_data->dialog), - GTK_WINDOW (nautilus_view_get_window (view))); + view->details->rename_file_popover = widget_data->widget; - /* Connect signals */ - gtk_builder_add_callback_symbols (builder, - "nautilus_view_file_name_dialog_entry_on_validate", - G_CALLBACK (nautilus_view_file_name_dialog_entry_on_validate), - "nautilus_view_file_name_dialog_entry_on_activate", - G_CALLBACK (nautilus_view_file_name_dialog_entry_on_activate), - NULL); + rename_data = g_new (RenameDialogData, 1); + rename_data->view = view; + rename_data->widget = widget_data->widget; + rename_data->target_file = target_file; + rename_data->name_entry = widget_data->name_entry; - dialog_data->target_is_folder = nautilus_file_is_directory (target_file); - gtk_button_set_label (GTK_BUTTON (button_ok), _("Rename")); - file_name = nautilus_file_get_display_name (target_file); - title = g_strdup_printf (_("Rename “%s”"), file_name); - gtk_window_set_title (GTK_WINDOW (dialog_data->dialog), title); - g_free (file_name); - g_free (title); - if (dialog_data->target_is_folder) + if (widget_data->target_is_folder) gtk_label_set_text (GTK_LABEL (label_file_name), _("Folder name")); else gtk_label_set_text (GTK_LABEL (label_file_name), _("File name")); - gtk_entry_set_text (GTK_ENTRY (dialog_data->name_entry), nautilus_file_get_name (target_file)); - gtk_builder_connect_signals (builder, dialog_data); - - g_signal_connect (dialog_data->dialog, - "response", - G_CALLBACK (nautilus_view_rename_dialog_on_response), - user_data); + gtk_entry_set_text (GTK_ENTRY (widget_data->name_entry), nautilus_file_get_name (target_file)); + + g_signal_connect (widget_data->activate_button, + "clicked", + G_CALLBACK (rename_file_popover_rename_button_on_clicked), + rename_data); + + g_signal_connect (widget_data->name_entry, + "changed", + G_CALLBACK (rename_file_popover_entry_on_changed), + widget_data); + + g_signal_connect (GTK_POPOVER (widget_data->widget), + "closed", + G_CALLBACK (rename_file_popover_on_closed), + widget_data); + + g_signal_connect (GTK_POPOVER (widget_data->widget), + "unmap", + G_CALLBACK (gtk_widget_destroy), + NULL); + + relative_to = nautilus_view_compute_rename_popover_relative_to (view); + gtk_popover_set_default_widget (GTK_POPOVER (widget_data->widget), + widget_data->activate_button); + gtk_popover_set_pointing_to (GTK_POPOVER (widget_data->widget), relative_to); + gtk_popover_set_relative_to (GTK_POPOVER (widget_data->widget), + GTK_WIDGET (view)); + gtk_widget_show (widget_data->widget); - gtk_widget_show_all (dialog_data->dialog); /* Select the name part withouth the file extension */ eel_filename_get_rename_region (nautilus_file_get_name (target_file), &start_offset, &end_offset); - gtk_editable_select_region (GTK_EDITABLE (dialog_data->name_entry), + gtk_editable_select_region (GTK_EDITABLE (widget_data->name_entry), start_offset, end_offset); - /* Update the ok button status */ - nautilus_view_file_name_dialog_validate_name (dialog_data); + /* Update the rename button status */ + rename_file_popover_entry_on_changed (GTK_ENTRY (widget_data->name_entry), + widget_data); + g_object_unref (builder); } @@ -2000,70 +2029,67 @@ nautilus_view_new_folder_dialog_on_response (GtkDialog *dialog, g_free (name); } - /* If there's any resources left from the delayed - * message, it should be removed before it gets - * triggered. - */ - if (new_folder_data->view->details->dialog_duplicated_name_label_timeout_id > 0) { - g_source_remove (new_folder_data->view->details->dialog_duplicated_name_label_timeout_id); - new_folder_data->view->details->dialog_duplicated_name_label_timeout_id = 0; - } + if (new_folder_data->view->details->create_folder_duplicated_label_timeout_id > 0) { + g_source_remove (new_folder_data->view->details->create_folder_duplicated_label_timeout_id); + new_folder_data->view->details->create_folder_duplicated_label_timeout_id = 0; + } - g_free (user_data); gtk_widget_destroy (GTK_WIDGET (dialog)); + g_free (user_data); } static void nautilus_view_new_folder_dialog_new (NautilusView *view, gboolean with_selection) { - FileNameDialogData *dialog_data; + FileNameWidgetData *widget_data; NewFolderDialogData *user_data; - GtkWidget *button_ok; GtkWidget *label_file_name; GtkBuilder *builder; - builder = gtk_builder_new_from_resource ("/org/gnome/nautilus/nautilus-file-name-dialog.ui"); - button_ok = GTK_WIDGET (gtk_builder_get_object (builder, "ok_button")); + builder = gtk_builder_new_from_resource ("/org/gnome/nautilus/nautilus-create-folder-dialog.ui"); label_file_name = GTK_WIDGET (gtk_builder_get_object (builder, "name_label")); - dialog_data = g_new (FileNameDialogData, 1); - dialog_data->view = view; - dialog_data->dialog = GTK_WIDGET (gtk_builder_get_object (builder, "file_name_dialog")); - dialog_data->error_label = GTK_WIDGET (gtk_builder_get_object (builder, "error_label")); - dialog_data->name_entry = GTK_WIDGET (gtk_builder_get_object (builder, "name_entry")); - dialog_data->target_is_folder = TRUE; - dialog_data->target_file = NULL; + widget_data = g_new (FileNameWidgetData, 1); + widget_data->view = view; + widget_data->widget = GTK_WIDGET (gtk_builder_get_object (builder, "create_folder_dialog")); + widget_data->activate_button = GTK_WIDGET (gtk_builder_get_object (builder, "ok_button")); + widget_data->error_label = GTK_WIDGET (gtk_builder_get_object (builder, "error_label")); + widget_data->name_entry = GTK_WIDGET (gtk_builder_get_object (builder, "name_entry")); + widget_data->target_is_folder = TRUE; + widget_data->target_file = NULL; user_data = g_new (NewFolderDialogData, 1); user_data->view = view; user_data->with_selection = with_selection; - user_data->name_entry = dialog_data->name_entry; + user_data->name_entry = widget_data->name_entry; - gtk_window_set_transient_for (GTK_WINDOW (dialog_data->dialog), + gtk_window_set_transient_for (GTK_WINDOW (widget_data->widget), GTK_WINDOW (nautilus_view_get_window (view))); /* Connect signals */ gtk_builder_add_callback_symbols (builder, - "nautilus_view_file_name_dialog_entry_on_validate", - G_CALLBACK (nautilus_view_file_name_dialog_entry_on_validate), - "nautilus_view_file_name_dialog_entry_on_activate", - G_CALLBACK (nautilus_view_file_name_dialog_entry_on_activate), + "create_folder_dialog_entry_on_changed", + G_CALLBACK (create_folder_dialog_entry_on_changed), + "create_folder_dialog_entry_on_activate", + G_CALLBACK (create_folder_dialog_entry_on_activate), NULL); - gtk_builder_connect_signals (builder, dialog_data); - gtk_button_set_label (GTK_BUTTON (button_ok), _("Create")); + gtk_builder_connect_signals (builder, widget_data); + gtk_button_set_label (GTK_BUTTON (widget_data->activate_button), + _("Create")); gtk_label_set_text (GTK_LABEL (label_file_name), _("Folder name")); - gtk_window_set_title (GTK_WINDOW (dialog_data->dialog), _("New Folder")); + gtk_window_set_title (GTK_WINDOW (widget_data->widget), _("New Folder")); - g_signal_connect (dialog_data->dialog, + g_signal_connect (widget_data->widget, "response", G_CALLBACK (nautilus_view_new_folder_dialog_on_response), user_data); - gtk_widget_show_all (dialog_data->dialog); + gtk_widget_show_all (widget_data->widget); /* Update the ok button status */ - nautilus_view_file_name_dialog_validate_name (dialog_data); + create_folder_dialog_entry_on_changed (GTK_ENTRY (widget_data->name_entry), + widget_data); g_object_unref (builder); } @@ -5488,7 +5514,7 @@ real_action_rename (NautilusView *view, * they are always pre-selected as a whole */ select_all = nautilus_file_is_directory (file); } - nautilus_view_rename_dialog_new (view, file); + nautilus_view_rename_file_popover_new (view, file); } } diff --git a/src/nautilus-view.h b/src/nautilus-view.h index 93fbc894d..3cc87dab0 100644 --- a/src/nautilus-view.h +++ b/src/nautilus-view.h @@ -276,6 +276,8 @@ struct NautilusViewClass { const char *uri); NautilusWindow * (*get_window) (NautilusView *view); + + GdkRectangle * (*compute_rename_popover_relative_to) (NautilusView *view); }; /* GObject support */ diff --git a/src/nautilus.gresource.xml b/src/nautilus.gresource.xml index acab5ff41..c80a529d4 100644 --- a/src/nautilus.gresource.xml +++ b/src/nautilus.gresource.xml @@ -8,7 +8,8 @@ nautilus-toolbar-ui.xml nautilus-toolbar-view-menu.xml nautilus-toolbar-action-menu.xml - nautilus-file-name-dialog.ui + nautilus-create-folder-dialog.ui + nautilus-rename-file-popover.ui nautilus-view-context-menus.xml nautilus-progress-info-widget.xml nautilus-move-to-trash-shortcut-changed.ui -- cgit v1.2.1