summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libnautilus-private/nautilus-canvas-container.c41
-rw-r--r--libnautilus-private/nautilus-canvas-container.h1
-rw-r--r--libnautilus-private/nautilus-directory.c22
-rw-r--r--libnautilus-private/nautilus-directory.h2
-rw-r--r--src/nautilus-canvas-view.c18
-rw-r--r--src/nautilus-create-folder-dialog.ui (renamed from src/nautilus-file-name-dialog.ui)6
-rw-r--r--src/nautilus-list-view.c42
-rw-r--r--src/nautilus-rename-file-popover.ui66
-rw-r--r--src/nautilus-view.c436
-rw-r--r--src/nautilus-view.h2
-rw-r--r--src/nautilus.gresource.xml3
11 files changed, 430 insertions, 209 deletions
diff --git a/libnautilus-private/nautilus-canvas-container.c b/libnautilus-private/nautilus-canvas-container.c
index a2620dc81..d40b77abb 100644
--- a/libnautilus-private/nautilus-canvas-container.c
+++ b/libnautilus-private/nautilus-canvas-container.c
@@ -6380,6 +6380,47 @@ nautilus_canvas_container_get_icon_locations (NautilusCanvasContainer *container
return result;
}
+/* Returns an array of GdkRectangles of the icons. */
+static GArray *
+nautilus_canvas_container_get_icons_bounding_box (NautilusCanvasContainer *container,
+ GList *icons)
+{
+ GArray *result;
+ GList *node;
+ int index;
+ int x1, x2, y1, y2;
+
+ result = g_array_new (FALSE, TRUE, sizeof (GdkRectangle));
+ result = g_array_set_size (result, g_list_length (icons));
+
+ for (index = 0, node = icons; node != NULL; index++, node = node->next) {
+ icon_get_bounding_box ((NautilusCanvasIcon *)node->data,
+ &x1, &y1, &x2, &y2,
+ BOUNDS_USAGE_FOR_ENTIRE_ITEM);
+ g_array_index (result, GdkRectangle, index).x = x1;
+ g_array_index (result, GdkRectangle, index).width = x2 - x1;
+ g_array_index (result, GdkRectangle, index).y = y1;
+ g_array_index (result, GdkRectangle, index).height = y2 - y1;
+ }
+
+ return result;
+}
+
+GArray *
+nautilus_canvas_container_get_selected_icons_bounding_box (NautilusCanvasContainer *container)
+{
+ GArray *result;
+ GList *icons;
+
+ g_return_val_if_fail (NAUTILUS_IS_CANVAS_CONTAINER (container), NULL);
+
+ icons = nautilus_canvas_container_get_selected_icons (container);
+ result = nautilus_canvas_container_get_icons_bounding_box (container, icons);
+ g_list_free (icons);
+
+ return result;
+}
+
/**
* nautilus_canvas_container_get_selected_icon_locations:
* @container: An canvas container widget.
diff --git a/libnautilus-private/nautilus-canvas-container.h b/libnautilus-private/nautilus-canvas-container.h
index 9519b4abe..711b3ea4b 100644
--- a/libnautilus-private/nautilus-canvas-container.h
+++ b/libnautilus-private/nautilus-canvas-container.h
@@ -270,6 +270,7 @@ void nautilus_canvas_container_invert_selection (NautilusCanvasContainer
void nautilus_canvas_container_set_selection (NautilusCanvasContainer *view,
GList *selection);
GArray * nautilus_canvas_container_get_selected_icon_locations (NautilusCanvasContainer *view);
+GArray * nautilus_canvas_container_get_selected_icons_bounding_box (NautilusCanvasContainer *container);
gboolean nautilus_canvas_container_has_stretch_handles (NautilusCanvasContainer *container);
gboolean nautilus_canvas_container_is_stretched (NautilusCanvasContainer *container);
void nautilus_canvas_container_show_stretch_handles (NautilusCanvasContainer *container);
diff --git a/libnautilus-private/nautilus-directory.c b/libnautilus-private/nautilus-directory.c
index 4f408080a..e150e8106 100644
--- a/libnautilus-private/nautilus-directory.c
+++ b/libnautilus-private/nautilus-directory.c
@@ -1447,6 +1447,28 @@ nautilus_directory_contains_file (NautilusDirectory *directory,
return NAUTILUS_DIRECTORY_CLASS (G_OBJECT_GET_CLASS (directory))->contains_file (directory, file);
}
+NautilusFile*
+nautilus_directory_get_file_by_name (NautilusDirectory *directory,
+ const gchar *name)
+{
+ GList *files;
+ GList *l;
+ NautilusFile *result = NULL;
+
+ files = nautilus_directory_get_file_list (directory);
+
+ for (l = files; l != NULL; l = l->next) {
+ if (nautilus_file_compare_display_name (l->data, name) == 0) {
+ result = nautilus_file_ref (l->data);
+ break;
+ }
+ }
+
+ nautilus_file_list_free (files);
+
+ return result;
+}
+
void
nautilus_directory_call_when_ready (NautilusDirectory *directory,
NautilusFileAttributes file_attributes,
diff --git a/libnautilus-private/nautilus-directory.h b/libnautilus-private/nautilus-directory.h
index 46040d7d1..5f6c0cdd8 100644
--- a/libnautilus-private/nautilus-directory.h
+++ b/libnautilus-private/nautilus-directory.h
@@ -167,6 +167,8 @@ GFile * nautilus_directory_get_location (NautilusDirector
gboolean nautilus_directory_contains_file (NautilusDirectory *directory,
NautilusFile *file);
+NautilusFile* nautilus_directory_get_file_by_name (NautilusDirectory *directory,
+ const gchar *name);
/* Get (and ref) a NautilusFile object for this directory. */
NautilusFile * nautilus_directory_get_corresponding_file (NautilusDirectory *directory);
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-file-name-dialog.ui b/src/nautilus-create-folder-dialog.ui
index 4e2c4c770..21bf6b2ad 100644
--- a/src/nautilus-file-name-dialog.ui
+++ b/src/nautilus-create-folder-dialog.ui
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk+" version="3.14"/>
- <object class="GtkDialog" id="file_name_dialog">
+ <object class="GtkDialog" id="create_folder_dialog">
<property name="resizable">False</property>
<property name="modal">True</property>
<property name="window_position">center-on-parent</property>
@@ -32,8 +32,8 @@
<object class="GtkEntry" id="name_entry">
<property name="visible">True</property>
<property name="can_focus">True</property>
- <signal name="notify::text" handler="nautilus_view_file_name_dialog_entry_on_validate" swapped="no" />
- <signal name="activate" handler="nautilus_view_file_name_dialog_entry_on_activate" swapped="no" />
+ <signal name="changed" handler="create_folder_dialog_entry_on_changed" swapped="no" />
+ <signal name="activate" handler="create_folder_dialog_entry_on_activate" swapped="no" />
</object>
<packing>
<property name="expand">False</property>
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 <libnautilus-private/nautilus-debug.h>
+/* 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 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <object class="GtkPopover" id="rename_file_popover">
+ <property name="position">bottom</property>
+ <signal name="closed" handler="rename_file_popover_on_closed"/>
+ <child>
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="margin">10</property>
+ <property name="row-spacing">6</property>
+ <property name="column-spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="name_label">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Name</property>
+ <property name="halign">start</property>
+ <property name="mnemonic_widget">name_entry</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="name_entry">
+ <property name="visible">True</property>
+ <property name="activates-default">True</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="rename_button">
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="label" translatable="yes">_Rename</property>
+ <property name="use_underline">True</property>
+ <property name="can_default">True</property>
+ <style>
+ <class name="suggested-action"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="error_label">
+ <property name="visible">True</property>
+ <property name="halign">start</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">2</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+</interface>
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 @@
<file>nautilus-toolbar-ui.xml</file>
<file>nautilus-toolbar-view-menu.xml</file>
<file>nautilus-toolbar-action-menu.xml</file>
- <file>nautilus-file-name-dialog.ui</file>
+ <file>nautilus-create-folder-dialog.ui</file>
+ <file>nautilus-rename-file-popover.ui</file>
<file>nautilus-view-context-menus.xml</file>
<file>nautilus-progress-info-widget.xml</file>
<file>nautilus-move-to-trash-shortcut-changed.ui</file>