[nautilus/wip/razvan/compression-support: 1/7] files-view: move file name widget logic to separate controllers



commit 47dfb263c0f2986eb0aaec94cc470f730f0e1c77
Author: Razvan Chitu <razvan ch95 gmail com>
Date:   Sat Jul 30 18:50:10 2016 +0300

    files-view: move file name widget logic to separate controllers
    
    The rename file popover and the new folder dialog share common logic for
    validating file names entered by the user. The control logic was implemented
    with a simple structure in files-view. Besides common logic, the structure also
    held parameters specific to only one of the operations. Another problem is that
    the current implementation does not allow flexibility in obtaining the file name
    from the widgets and displaying error messages.
    
    In order to fix this, reimplement the structure as an abstract class and create
    two subclasses for the "Rename" and "New Folder" widgets.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=769336

 src/Makefile.am                                   |    6 +
 src/nautilus-file-name-widget-controller.c        |  389 ++++++++++++++++
 src/nautilus-file-name-widget-controller.h        |   32 ++
 src/nautilus-files-view.c                         |  508 ++++----------------
 src/nautilus-new-folder-dialog-controller.c       |  151 ++++++
 src/nautilus-new-folder-dialog-controller.h       |   20 +
 src/nautilus-rename-file-popover-controller.c     |  226 +++++++++
 src/nautilus-rename-file-popover-controller.h     |   19 +
 src/resources/ui/nautilus-create-folder-dialog.ui |    3 -
 src/resources/ui/nautilus-rename-file-popover.ui  |    7 +-
 10 files changed, 946 insertions(+), 415 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 7238e57..652cab7 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -272,6 +272,12 @@ nautilus_no_main_sources = \
        nautilus-file-changes-queue.h \
        nautilus-file-conflict-dialog.c \
        nautilus-file-conflict-dialog.h \
+       nautilus-file-name-widget-controller.c \
+       nautilus-file-name-widget-controller.h \
+       nautilus-rename-file-popover-controller.c \
+       nautilus-rename-file-popover-controller.h \
+       nautilus-new-folder-dialog-controller.c \
+       nautilus-new-folder-dialog-controller.h \
        nautilus-file-operations.c \
        nautilus-file-operations.h \
        nautilus-file-private.h \
diff --git a/src/nautilus-file-name-widget-controller.c b/src/nautilus-file-name-widget-controller.c
new file mode 100644
index 0000000..1488582
--- /dev/null
+++ b/src/nautilus-file-name-widget-controller.c
@@ -0,0 +1,389 @@
+#include <glib/gi18n.h>
+
+#include "nautilus-file-name-widget-controller.h"
+
+
+#define FILE_NAME_DUPLICATED_LABEL_TIMEOUT 500
+
+typedef struct {
+        GtkWidget *error_label;
+        GtkWidget *name_entry;
+        GtkWidget *activate_button;
+        NautilusDirectory *containing_directory;
+
+        gboolean duplicated_is_folder;
+        gint duplicated_label_timeout_id;
+} NautilusFileNameWidgetControllerPrivate;
+
+enum {
+        NAME_ACCEPTED,
+        CANCELLED,
+        LAST_SIGNAL
+};
+
+enum {
+        PROP_ERROR_LABEL = 1,
+        PROP_NAME_ENTRY,
+        PROP_ACTION_BUTTON,
+        PROP_CONTAINING_DIRECTORY,
+        NUM_PROPERTIES
+};
+
+static guint signals[LAST_SIGNAL];
+
+G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (NautilusFileNameWidgetController, nautilus_file_name_widget_controller, 
G_TYPE_OBJECT)
+
+gchar *
+nautilus_file_name_widget_controller_get_new_name (NautilusFileNameWidgetController *self)
+{
+        return NAUTILUS_FILE_NAME_WIDGET_CONTROLLER_GET_CLASS (self)->get_new_name (self);
+}
+
+static gboolean
+nautilus_file_name_widget_controller_name_is_valid (NautilusFileNameWidgetController  *self,
+                                                    gchar                             *name,
+                                                    gchar                            **error_message)
+{
+        return NAUTILUS_FILE_NAME_WIDGET_CONTROLLER_GET_CLASS (self)->name_is_valid (self,
+                                                                                     name,
+                                                                                     error_message);
+}
+
+static gboolean
+nautilus_file_name_widget_controller_ignore_existing_file (NautilusFileNameWidgetController *self,
+                                                           NautilusFile                     *existing_file)
+{
+        return NAUTILUS_FILE_NAME_WIDGET_CONTROLLER_GET_CLASS (self)->ignore_existing_file (self,
+                                                                                            existing_file);
+}
+
+static gchar *
+real_get_new_name (NautilusFileNameWidgetController *self)
+{
+        NautilusFileNameWidgetControllerPrivate *priv;
+
+        priv = nautilus_file_name_widget_controller_get_instance_private (self);
+
+        return g_strstrip (g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->name_entry))));
+}
+
+static gboolean
+real_name_is_valid (NautilusFileNameWidgetController  *self,
+                    gchar                             *name,
+                    gchar                            **error_message)
+{
+        g_assert (*error_message == NULL);
+
+        if (strlen (name) == 0) {
+                return FALSE;
+        }
+
+        if (strstr (name, "/") != NULL) {
+                *error_message = _("File names cannot contain “/”.");
+        } else if (strcmp (name, ".") == 0){
+                *error_message = _("A file can not be called “.”.");
+        } else if (strcmp (name, "..") == 0){
+                *error_message = _("A file can not be called “..”.");
+        }
+
+        return *error_message == NULL;
+}
+
+static gboolean
+real_ignore_existing_file (NautilusFileNameWidgetController *self,
+                           NautilusFile                     *existing_file)
+{
+        return FALSE;
+}
+
+static gboolean
+duplicated_file_label_show (NautilusFileNameWidgetController *self)
+{
+        NautilusFileNameWidgetControllerPrivate *priv;
+
+        priv = nautilus_file_name_widget_controller_get_instance_private (self);
+        if (priv->duplicated_is_folder) {
+                gtk_label_set_label (GTK_LABEL (priv->error_label),
+                                     _("A folder with that name already exists."));
+        } else {
+                gtk_label_set_label (GTK_LABEL (priv->error_label),
+                                     _("A file with that name already exists."));
+        }
+
+        priv->duplicated_label_timeout_id = 0;
+
+        return G_SOURCE_REMOVE;
+}
+
+static void
+file_name_widget_controller_process_new_name (NautilusFileNameWidgetController *controller,
+                                              gboolean                         *duplicated_name,
+                                              gboolean                         *valid_name)
+{
+        NautilusFileNameWidgetControllerPrivate *priv;
+        g_autofree gchar *name;
+        gchar *error_message = NULL;
+        NautilusFile *existing_file;
+        priv = nautilus_file_name_widget_controller_get_instance_private (controller);
+
+        name = nautilus_file_name_widget_controller_get_new_name (controller);
+        *valid_name = nautilus_file_name_widget_controller_name_is_valid (controller,
+                                                                          name,
+                                                                          &error_message);
+
+        gtk_label_set_label (GTK_LABEL (priv->error_label), error_message);
+
+        existing_file = nautilus_directory_get_file_by_name (priv->containing_directory, name);
+        *duplicated_name = existing_file != NULL &&
+                           !nautilus_file_name_widget_controller_ignore_existing_file (controller,
+                                                                                       existing_file);
+
+        gtk_widget_set_sensitive (priv->activate_button, *valid_name && !*duplicated_name);
+
+        if (priv->duplicated_label_timeout_id != 0) {
+                g_source_remove (priv->duplicated_label_timeout_id);
+                priv->duplicated_label_timeout_id = 0;
+        }
+
+        if (*duplicated_name) {
+                priv->duplicated_is_folder = nautilus_file_is_directory (existing_file);
+        }
+
+        if (existing_file != NULL) {
+                nautilus_file_unref (existing_file);
+        }
+}
+
+static void
+file_name_widget_controller_on_changed_directory_info_ready (NautilusDirectory *directory,
+                                                             GList             *files,
+                                                             gpointer           user_data)
+{
+        NautilusFileNameWidgetController *controller;
+        NautilusFileNameWidgetControllerPrivate *priv;
+        gboolean duplicated_name;
+        gboolean valid_name;
+
+        controller = NAUTILUS_FILE_NAME_WIDGET_CONTROLLER (user_data);
+        priv = nautilus_file_name_widget_controller_get_instance_private (controller);
+
+        file_name_widget_controller_process_new_name (controller,
+                                                      &duplicated_name,
+                                                      &valid_name);
+
+        /* 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 or if the name is the same as the file
+         * we are renaming also don't report as a duplicated */
+        if (duplicated_name && valid_name) {
+                priv->duplicated_label_timeout_id = g_timeout_add (FILE_NAME_DUPLICATED_LABEL_TIMEOUT,
+                                                                   (GSourceFunc)duplicated_file_label_show,
+                                                                   controller);
+        }
+}
+
+static void
+file_name_widget_controller_on_changed (gpointer user_data)
+{
+        NautilusFileNameWidgetController *controller;
+        NautilusFileNameWidgetControllerPrivate *priv;
+
+        controller = NAUTILUS_FILE_NAME_WIDGET_CONTROLLER (user_data);
+        priv = nautilus_file_name_widget_controller_get_instance_private (controller);
+
+        nautilus_directory_call_when_ready (priv->containing_directory,
+                                            NAUTILUS_FILE_ATTRIBUTE_INFO,
+                                            TRUE,
+                                            file_name_widget_controller_on_changed_directory_info_ready,
+                                            controller);
+}
+
+static void
+file_name_widget_controller_on_activate_directory_info_ready (NautilusDirectory *directory,
+                                                              GList             *files,
+                                                              gpointer           user_data)
+{
+        NautilusFileNameWidgetController *controller;
+        gboolean duplicated_name;
+        gboolean valid_name;
+
+        controller = NAUTILUS_FILE_NAME_WIDGET_CONTROLLER (user_data);
+
+        file_name_widget_controller_process_new_name (controller,
+                                                      &duplicated_name,
+                                                      &valid_name);
+
+        if (valid_name && !duplicated_name) {
+                g_signal_emit (controller, signals[NAME_ACCEPTED], 0);
+        } 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 (duplicated_name && valid_name) {
+                        /* Show it inmediatily since the user tried to trigger the action */
+                        duplicated_file_label_show (controller);
+                }
+        }
+}
+
+static void
+file_name_widget_controller_on_activate (gpointer user_data)
+{
+        NautilusFileNameWidgetController *controller;
+        NautilusFileNameWidgetControllerPrivate *priv;
+
+        controller = NAUTILUS_FILE_NAME_WIDGET_CONTROLLER (user_data);
+        priv = nautilus_file_name_widget_controller_get_instance_private (controller);
+
+        nautilus_directory_call_when_ready (priv->containing_directory,
+                                            NAUTILUS_FILE_ATTRIBUTE_INFO,
+                                            TRUE,
+                                            file_name_widget_controller_on_activate_directory_info_ready,
+                                            controller);
+}
+
+static void
+nautilus_file_name_widget_controller_init (NautilusFileNameWidgetController *self)
+{
+
+}
+
+static void
+nautilus_file_name_widget_controller_set_property (GObject      *object,
+                                                   guint         prop_id,
+                                                   const GValue *value,
+                                                   GParamSpec   *pspec)
+{
+        NautilusFileNameWidgetController *controller;
+        NautilusFileNameWidgetControllerPrivate *priv;
+
+        controller = NAUTILUS_FILE_NAME_WIDGET_CONTROLLER (object);
+        priv = nautilus_file_name_widget_controller_get_instance_private (controller);
+
+        switch (prop_id) {
+                case PROP_ERROR_LABEL:
+                        priv->error_label = GTK_WIDGET (g_value_get_object (value));
+                        break;
+                case PROP_NAME_ENTRY:
+                        priv->name_entry = GTK_WIDGET (g_value_get_object (value));
+
+                        g_signal_connect_swapped (G_OBJECT (priv->name_entry),
+                                                  "activate",
+                                                  (GCallback)file_name_widget_controller_on_activate,
+                                                  controller);
+                        g_signal_connect_swapped (G_OBJECT (priv->name_entry),
+                                                  "changed",
+                                                  (GCallback)file_name_widget_controller_on_changed,
+                                                  controller);
+                        break;
+                case PROP_ACTION_BUTTON:
+                        priv->activate_button = GTK_WIDGET (g_value_get_object (value));
+
+                        g_signal_connect_swapped (G_OBJECT (priv->activate_button),
+                                                  "clicked",
+                                                  (GCallback)file_name_widget_controller_on_activate,
+                                                  controller);
+                        break;
+                case PROP_CONTAINING_DIRECTORY:
+                        priv->containing_directory = NAUTILUS_DIRECTORY (g_value_get_object (value));
+                        nautilus_directory_ref (priv->containing_directory);
+                        break;
+                default:
+                        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                        break;
+        }
+}
+
+static void
+nautilus_file_name_widget_controller_finalize (GObject *object)
+{
+        NautilusFileNameWidgetController *self;
+        NautilusFileNameWidgetControllerPrivate *priv;
+
+        self = NAUTILUS_FILE_NAME_WIDGET_CONTROLLER (object);
+        priv = nautilus_file_name_widget_controller_get_instance_private (self);
+
+        if (priv->containing_directory != NULL) {
+                nautilus_directory_cancel_callback (priv->containing_directory,
+                                                    
file_name_widget_controller_on_changed_directory_info_ready,
+                                                    self);
+                nautilus_directory_cancel_callback (priv->containing_directory,
+                                                    
file_name_widget_controller_on_activate_directory_info_ready,
+                                                    self);
+                g_clear_object (&priv->containing_directory);
+        }
+
+        if (priv->duplicated_label_timeout_id > 0) {
+                g_source_remove (priv->duplicated_label_timeout_id);
+                priv->duplicated_label_timeout_id = 0;
+        }
+
+        G_OBJECT_CLASS (nautilus_file_name_widget_controller_parent_class)->finalize (object);
+}
+
+static void
+nautilus_file_name_widget_controller_class_init (NautilusFileNameWidgetControllerClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->set_property = nautilus_file_name_widget_controller_set_property;
+        object_class->finalize = nautilus_file_name_widget_controller_finalize;
+
+        klass->get_new_name = real_get_new_name;
+        klass->name_is_valid = real_name_is_valid;
+        klass->ignore_existing_file = real_ignore_existing_file;
+
+        signals[NAME_ACCEPTED] =
+                g_signal_new ("name-accepted",
+                              G_TYPE_FROM_CLASS (klass),
+                              G_SIGNAL_RUN_FIRST,
+                              G_STRUCT_OFFSET (NautilusFileNameWidgetControllerClass, name_accepted),
+                              NULL, NULL,
+                              g_cclosure_marshal_generic,
+                              G_TYPE_NONE, 0);
+        signals[CANCELLED] =
+                g_signal_new ("cancelled",
+                              G_TYPE_FROM_CLASS (klass),
+                              G_SIGNAL_RUN_LAST,
+                              0,
+                              NULL, NULL,
+                              g_cclosure_marshal_generic,
+                              G_TYPE_NONE, 0);
+
+        g_object_class_install_property (
+                object_class,
+                PROP_ERROR_LABEL,
+                g_param_spec_object ("error-label",
+                                     "Error Label",
+                                     "The label used for displaying errors",
+                                     GTK_TYPE_WIDGET,
+                                     G_PARAM_WRITABLE |
+                                     G_PARAM_CONSTRUCT_ONLY));
+        g_object_class_install_property (
+                object_class,
+                PROP_NAME_ENTRY,
+                g_param_spec_object ("name-entry",
+                                     "Name Entry",
+                                     "The entry for the file name",
+                                     GTK_TYPE_WIDGET,
+                                     G_PARAM_WRITABLE |
+                                     G_PARAM_CONSTRUCT_ONLY));
+        g_object_class_install_property (
+                object_class,
+                PROP_ACTION_BUTTON,
+                g_param_spec_object ("activate-button",
+                                     "Activate Button",
+                                     "The activate button of the widget",
+                                     GTK_TYPE_WIDGET,
+                                     G_PARAM_WRITABLE |
+                                     G_PARAM_CONSTRUCT_ONLY));
+        g_object_class_install_property (
+                object_class,
+                PROP_CONTAINING_DIRECTORY,
+                g_param_spec_object ("containing-directory",
+                                     "Containing Directory",
+                                     "The directory used to check for duplicate names",
+                                     NAUTILUS_TYPE_DIRECTORY,
+                                     G_PARAM_WRITABLE |
+                                     G_PARAM_CONSTRUCT_ONLY));
+}
diff --git a/src/nautilus-file-name-widget-controller.h b/src/nautilus-file-name-widget-controller.h
new file mode 100644
index 0000000..8e5b597
--- /dev/null
+++ b/src/nautilus-file-name-widget-controller.h
@@ -0,0 +1,32 @@
+#ifndef NAUTILUS_FILE_NAME_WIDGET_CONTROLLER_H
+#define NAUTILUS_FILE_NAME_WIDGET_CONTROLLER_H
+
+#include <glib.h>
+#include <gtk/gtk.h>
+
+#include "nautilus-file.h"
+#include "nautilus-directory.h"
+
+#define NAUTILUS_TYPE_FILE_NAME_WIDGET_CONTROLLER nautilus_file_name_widget_controller_get_type ()
+G_DECLARE_DERIVABLE_TYPE (NautilusFileNameWidgetController, nautilus_file_name_widget_controller, NAUTILUS, 
FILE_NAME_WIDGET_CONTROLLER, GObject)
+
+struct _NautilusFileNameWidgetControllerClass
+{
+        GObjectClass parent_class;
+
+        gchar *  (*get_new_name)         (NautilusFileNameWidgetController *controller);
+
+        gboolean (*name_is_valid)        (NautilusFileNameWidgetController  *controller,
+                                          gchar                             *name,
+                                          gchar                            **error_message);
+
+        gboolean (*ignore_existing_file) (NautilusFileNameWidgetController *controller,
+                                          NautilusFile                     *existing_file);
+
+        void     (*name_accepted)        (NautilusFileNameWidgetController *controller);
+};
+
+gchar * nautilus_file_name_widget_controller_get_new_name (NautilusFileNameWidgetController *controller);
+
+
+#endif /* NAUTILUS_FILE_NAME_WIDGET_CONTROLLER_H */
diff --git a/src/nautilus-files-view.c b/src/nautilus-files-view.c
index 097f1f2..df56e55 100644
--- a/src/nautilus-files-view.c
+++ b/src/nautilus-files-view.c
@@ -78,6 +78,9 @@
 #include "nautilus-file-operations.h"
 #include "nautilus-file-utilities.h"
 #include "nautilus-file-private.h"
+#include "nautilus-file-name-widget-controller.h"
+#include "nautilus-rename-file-popover-controller.h"
+#include "nautilus-new-folder-dialog-controller.h"
 #include "nautilus-global-preferences.h"
 #include "nautilus-link.h"
 #include "nautilus-metadata.h"
@@ -110,9 +113,6 @@
 #define DUPLICATE_HORIZONTAL_ICON_OFFSET 70
 #define DUPLICATE_VERTICAL_ICON_OFFSET   30
 
-#define RENAME_ENTRY_MIN_CHARS 20
-#define RENAME_ENTRY_MAX_CHARS 35
-
 #define MAX_QUEUED_UPDATES 500
 
 #define MAX_MENU_LEVELS 5
@@ -120,9 +120,6 @@
 
 #define SHORTCUTS_PATH "/nautilus/scripts-accels"
 
-/* Delay to show the duplicated label when creating a folder */
-#define FILE_NAME_DUPLICATED_LABEL_TIMEOUT 500
-
 /* Delay to show the Loading... floating bar */
 #define FLOATING_BAR_LOADING_DELAY 200 /* ms */
 
@@ -178,8 +175,8 @@ struct NautilusFilesViewDetails
 
         NautilusQuery *search_query;
 
-        gint duplicated_label_timeout_id;
-        GtkWidget *rename_file_popover;
+        NautilusRenameFilePopoverController *rename_file_controller;
+        NautilusNewFolderDialogController *new_folder_controller;
 
         gboolean supports_zooming;
 
@@ -1697,456 +1694,158 @@ context_menu_to_file_operation_position (NautilusFilesView *view)
         }
 }
 
-typedef struct {
-        NautilusFilesView *view;
-        GtkWidget *widget;
-        GtkWidget *error_label;
-        GtkWidget *name_entry;
-        GtkWidget *activate_button;
-        gboolean target_is_folder;
-        NautilusFile *target_file;
-        gboolean duplicated_is_folder;
-        void (*on_name_accepted) (gpointer data);
-        /* For create folder only */
-        gboolean with_selection;
-} FileNameWidgetData;
-
-static gboolean
-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->duplicated_label_timeout_id = 0;
-
-        return G_SOURCE_REMOVE;
-}
-
-static gchar*
-validate_file_name (const gchar *name,
-                    gboolean     is_folder)
-{
-        gchar *error_message = NULL;
-
-        if (strstr (name, "/") != NULL) {
-                if (is_folder)
-                        error_message = _("Folder names cannot contain “/”.");
-                else
-                        error_message = _("Files names cannot contain “/”.");
-        } else if (strcmp (name, ".") == 0){
-                if (is_folder)
-                        error_message = _("A folder can not be called “.”.");
-                else
-                        error_message = _("A file can not be called “.”.");
-        } else if (strcmp (name, "..") == 0){
-                if (is_folder)
-                        error_message = _("A folder can not be called “..”.");
-                else
-                        error_message = _("A file can not be called “..”.");
-        }
-
-        return error_message;
-}
-
-static void
-file_name_widget_entry_on_directory_info_ready (NautilusDirectory *directory,
-                                                GList             *files,
-                                                gpointer           callback_data) {
-        FileNameWidgetData *data;
-        gchar *name;
-        gchar *error_message;
-        NautilusFile *existing_file;
-        gboolean valid_name;
-        gboolean duplicated;
-
-        data = (FileNameWidgetData *) callback_data;
-
-        if (data->view == NULL) {
-                nautilus_directory_unref (directory);
-                return;
-        }
-
-        g_object_remove_weak_pointer (G_OBJECT (data->view),
-                                      (gpointer *) &data->view);
-
-        name = g_strstrip (g_strdup (gtk_entry_get_text (GTK_ENTRY (data->name_entry))));
-        error_message = validate_file_name (name, data->target_is_folder);
-        gtk_label_set_label (GTK_LABEL (data->error_label), error_message);
-
-        existing_file = nautilus_directory_get_file_by_name (directory, name);
-
-        valid_name = strlen (name) > 0 && error_message == NULL;
-        /* If there is a target file and the name is the same, we don't show it
-         * as duplicated. This is the case for renaming. */
-        duplicated = existing_file != NULL &&
-                     (data->target_file == NULL ||
-                      nautilus_file_compare_display_name (data->target_file, name) != 0);
-        gtk_widget_set_sensitive (data->activate_button, valid_name && !duplicated);
-
-        if (data->view->details->duplicated_label_timeout_id > 0) {
-                g_source_remove (data->view->details->duplicated_label_timeout_id);
-                data->view->details->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 or if the name is the same as the file
-         * we are renaming also don't report as a duplicated */
-        if (duplicated && valid_name) {
-                data->duplicated_is_folder = nautilus_file_is_directory (existing_file);
-                data->view->details->duplicated_label_timeout_id =
-                        g_timeout_add (FILE_NAME_DUPLICATED_LABEL_TIMEOUT,
-                                       (GSourceFunc)duplicated_file_label_show,
-                                       data);
-        }
-
-        if (existing_file != NULL)
-                nautilus_file_unref (existing_file);
-
-        g_free (name);
-
-        nautilus_directory_unref (directory);
-}
-
-static void
-file_name_widget_entry_on_changed (gpointer user_data)
+static GdkRectangle*
+nautilus_files_view_compute_rename_popover_relative_to (NautilusFilesView *view)
 {
-        FileNameWidgetData *data;
-        NautilusFile *parent_location;
-        NautilusDirectory *containing_dir;
-
-        data = (FileNameWidgetData *) user_data;
-
-        if (data->target_file != NULL &&
-            !nautilus_file_is_self_owned (data->target_file)) {
-                parent_location = nautilus_file_get_parent (data->target_file);
-                containing_dir = nautilus_directory_get_for_file (parent_location);
-
-                nautilus_file_unref (parent_location);
-        } else {
-                containing_dir = nautilus_directory_get_by_uri (nautilus_files_view_get_backing_uri 
(data->view));
-        }
-
-        g_object_add_weak_pointer (G_OBJECT (data->view),
-                                   (gpointer *) &data->view);
-
-        nautilus_directory_call_when_ready (containing_dir,
-                                            NAUTILUS_FILE_ATTRIBUTE_INFO,
-                                            TRUE,
-                                            file_name_widget_entry_on_directory_info_ready,
-                                            data);
+        return NAUTILUS_FILES_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->compute_rename_popover_relative_to 
(view);
 }
 
 static void
-create_folder_dialog_on_response (GtkDialog *dialog,
-                                  gint       response_id,
-                                  gpointer   user_data)
+rename_file_popover_controller_on_name_accepted (NautilusFileNameWidgetController *controller,
+                                                 gpointer                          user_data)
 {
-        FileNameWidgetData *widget_data;
-
-        widget_data = (FileNameWidgetData *) user_data;
-
-        if (response_id == GTK_RESPONSE_OK) {
-                NewFolderData *data;
-                GdkPoint *pos;
-                char *parent_uri;
-                gchar *name;
-
-                data = new_folder_data_new (widget_data->view, widget_data->with_selection);
+        NautilusFilesView *view;
+        NautilusFile *target_file;
+        g_autofree gchar *name;
 
-                name = g_strstrip (g_strdup (gtk_entry_get_text (GTK_ENTRY (widget_data->name_entry))));
-                g_signal_connect_data (widget_data->view,
-                                       "add-file",
-                                       G_CALLBACK (track_newly_added_locations),
-                                       data,
-                                       (GClosureNotify)NULL,
-                                       G_CONNECT_AFTER);
+        view = NAUTILUS_FILES_VIEW (user_data);
 
-                pos = context_menu_to_file_operation_position (widget_data->view);
+        name = nautilus_file_name_widget_controller_get_new_name (controller);
 
-                parent_uri = nautilus_files_view_get_backing_uri (widget_data->view);
-                nautilus_file_operations_new_folder (GTK_WIDGET (widget_data->view),
-                                                     pos, parent_uri, name,
-                                                     new_folder_done, data);
-
-                g_free (parent_uri);
-                g_free (name);
-        }
-
-        gtk_widget_destroy (GTK_WIDGET (dialog));
-        g_free (user_data);
-}
+        target_file =
+                nautilus_rename_file_popover_controller_get_target_file 
(view->details->rename_file_controller);
 
+        /* Put it on the queue for reveal after the view acknowledges the change */
+        g_hash_table_insert (view->details->pending_reveal,
+                             target_file,
+                             GUINT_TO_POINTER (FALSE));
 
-static void
-create_folder_on_name_accepted (gpointer user_data)
-{
-        FileNameWidgetData *data;
+        nautilus_rename_file (target_file, name, NULL, NULL);
 
-        data = (FileNameWidgetData *) user_data;
-        gtk_dialog_response (GTK_DIALOG (data->widget),
-                             GTK_RESPONSE_OK);
+        g_clear_object (&view->details->rename_file_controller);
 }
 
 static void
-rename_file_on_name_accepted (gpointer user_data)
+rename_file_popover_controller_on_cancelled (NautilusFileNameWidgetController *controller,
+                                             gpointer                          user_data)
 {
-        FileNameWidgetData *data;
-        gchar *name;
-
-        data = (FileNameWidgetData *) user_data;
-
-        name = g_strstrip (g_strdup (gtk_entry_get_text (GTK_ENTRY (data->name_entry))));
-
-        /* Put it on the queue for reveal after the view acknowledges the change */
-        g_hash_table_insert (data->view->details->pending_reveal,
-                             data->target_file,
-                             GUINT_TO_POINTER (FALSE));
-
-        nautilus_rename_file (data->target_file, name, NULL, NULL);
+        NautilusFilesView *view;
 
-        gtk_widget_hide (data->widget);
+        view = NAUTILUS_FILES_VIEW (user_data);
 
-        g_free (name);
+        g_clear_object (&view->details->rename_file_controller);
 }
 
 static void
-file_name_widget_on_directory_info_ready (NautilusDirectory *directory,
-                                          GList             *files,
-                                          gpointer           callback_data) {
-        FileNameWidgetData *data;
-        NautilusFile *existing_file;
-        gchar *name;
-        gchar *error_message;
-        gboolean valid_name;
-        gboolean duplicated;
-
-        data = (FileNameWidgetData *) callback_data;
+nautilus_files_view_rename_file_popover_new (NautilusFilesView *view,
+                                             NautilusFile      *target_file)
+{
+        GdkRectangle *pointing_to;
 
-        if (data->view == NULL) {
-                nautilus_directory_unref (directory);
+        if (view->details->rename_file_controller != NULL) {
                 return;
         }
 
-        g_object_remove_weak_pointer (G_OBJECT (data->view),
-                                      (gpointer *) &data->view);
-
-        name = g_strstrip (g_strdup (gtk_entry_get_text (GTK_ENTRY (data->name_entry))));
+        pointing_to = nautilus_files_view_compute_rename_popover_relative_to (view);
 
-        existing_file = nautilus_directory_get_file_by_name (directory, name);
+        view->details->rename_file_controller =
+                nautilus_rename_file_popover_controller_new (target_file,
+                                                             pointing_to,
+                                                             GTK_WIDGET (view));
 
-        error_message = validate_file_name (name, data->target_is_folder);
-        valid_name = strlen (name) > 0 && error_message == NULL;
-        duplicated = existing_file != NULL &&
-                     (data->target_file == NULL ||
-                      nautilus_file_compare_display_name (data->target_file, name) != 0);
-
-        if (data->view->details->duplicated_label_timeout_id > 0) {
-                g_source_remove (data->view->details->duplicated_label_timeout_id);
-                data->view->details->duplicated_label_timeout_id = 0;
-        }
-
-        if (valid_name && !duplicated) {
-                data->on_name_accepted ((gpointer) data);
-        } 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);
-                }
-        }
-
-        if (existing_file != NULL)
-                nautilus_file_unref (existing_file);
-
-        nautilus_directory_unref (directory);
+        g_signal_connect (view->details->rename_file_controller,
+                          "name-accepted",
+                          (GCallback)rename_file_popover_controller_on_name_accepted,
+                          view);
+        g_signal_connect (view->details->rename_file_controller,
+                          "cancelled",
+                          (GCallback)rename_file_popover_controller_on_cancelled,
+                          view);
 }
 
 static void
-file_name_widget_on_activate (gpointer user_data)
+new_folder_dialog_controller_on_name_accepted (NautilusFileNameWidgetController *controller,
+                                               gpointer                          user_data)
 {
-        FileNameWidgetData *data;
-        NautilusFile *parent_location;
-        NautilusDirectory *containing_dir;
-
-        data = (FileNameWidgetData *) user_data;
+        NautilusFilesView *view;
+        NewFolderData *data;
+        GdkPoint *pos;
+        g_autofree gchar *parent_uri;
+        g_autofree gchar *name;
+        gboolean with_selection;
 
-        if (data->target_file != NULL &&
-            !nautilus_file_is_self_owned (data->target_file)) {
-                parent_location = nautilus_file_get_parent (data->target_file);
-                containing_dir = nautilus_directory_get_for_file (parent_location);
+        view = NAUTILUS_FILES_VIEW (user_data);
 
-                nautilus_file_unref (parent_location);
-        } else {
-                containing_dir = nautilus_directory_get_by_uri (nautilus_files_view_get_backing_uri 
(data->view));
-        }
+        with_selection =
+                nautilus_new_folder_dialog_controller_get_with_selection 
(view->details->new_folder_controller);
 
-        g_object_add_weak_pointer (G_OBJECT (data->view),
-                                   (gpointer *) &data->view);
+        data = new_folder_data_new (view, with_selection);
 
-        nautilus_directory_call_when_ready (containing_dir,
-                                            NAUTILUS_FILE_ATTRIBUTE_INFO,
-                                            TRUE,
-                                            file_name_widget_on_directory_info_ready,
-                                            data);
-}
+        name = nautilus_file_name_widget_controller_get_new_name (controller);
+        g_signal_connect_data (view,
+                               "add-file",
+                               G_CALLBACK (track_newly_added_locations),
+                               data,
+                               (GClosureNotify)NULL,
+                               G_CONNECT_AFTER);
 
-static void
-rename_file_popover_on_closed (GtkPopover *popover,
-                               gpointer    user_data)
-{
-        FileNameWidgetData *widget_data;
+        pos = context_menu_to_file_operation_position (view);
 
-        widget_data = (FileNameWidgetData *) user_data;
-        widget_data->view->details->rename_file_popover = NULL;
-        if (widget_data->view->details->duplicated_label_timeout_id > 0) {
-                g_source_remove (widget_data->view->details->duplicated_label_timeout_id);
-                widget_data->view->details->duplicated_label_timeout_id = 0;
-        }
-        g_free (widget_data);
-}
+        parent_uri = nautilus_files_view_get_backing_uri (view);
+        nautilus_file_operations_new_folder (GTK_WIDGET (view),
+                                             pos, parent_uri, name,
+                                             new_folder_done, data);
 
-static GdkRectangle*
-nautilus_files_view_compute_rename_popover_relative_to (NautilusFilesView *view)
-{
-        return NAUTILUS_FILES_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->compute_rename_popover_relative_to 
(view);
+        g_clear_object (&view->details->new_folder_controller);
 }
 
 static void
-nautilus_files_view_rename_file_popover_new (NautilusFilesView *view,
-                                             NautilusFile      *target_file)
+new_folder_dialog_controller_on_cancelled (NautilusNewFolderDialogController *controller,
+                                           gpointer                           user_data)
 {
-        FileNameWidgetData *widget_data;
-        GtkWidget *label_file_name;
-        GtkBuilder *builder;
-        gint start_offset, end_offset;
-        GdkRectangle *relative_to;
-        gint n_chars;
-
-        if (view->details->rename_file_popover != NULL)
-          return;
-
-        builder = gtk_builder_new_from_resource ("/org/gnome/nautilus/ui/nautilus-rename-file-popover.ui");
-        label_file_name = GTK_WIDGET (gtk_builder_get_object (builder, "name_label"));
-
-        widget_data = g_new (FileNameWidgetData, 1);
-        widget_data->view = view;
-        widget_data->on_name_accepted = rename_file_on_name_accepted;
-        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;
-
-        view->details->rename_file_popover = widget_data->widget;
-
-        /* Connect signals */
-        gtk_builder_add_callback_symbols (builder,
-                                          "file_name_widget_entry_on_changed",
-                                          G_CALLBACK (file_name_widget_entry_on_changed),
-                                          "file_name_widget_on_activate",
-                                          G_CALLBACK (file_name_widget_on_activate),
-                                          "rename_file_popover_on_closed",
-                                          G_CALLBACK (rename_file_popover_on_closed),
-                                          "rename_file_popover_on_unmap",
-                                          G_CALLBACK (gtk_widget_destroy),
-                                          NULL);
-
-        gtk_builder_connect_signals (builder, widget_data);
-
-        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 (widget_data->name_entry), nautilus_file_get_display_name 
(target_file));
-
-        relative_to = nautilus_files_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_grab_focus (widget_data->name_entry);
-
-        /* Select the name part withouth the file extension */
-        eel_filename_get_rename_region (nautilus_file_get_display_name (target_file),
-                                        &start_offset, &end_offset);
-        n_chars = g_utf8_strlen (nautilus_file_get_display_name (target_file), -1);
-        gtk_entry_set_width_chars (GTK_ENTRY (widget_data->name_entry),
-                                   MIN (MAX (n_chars, RENAME_ENTRY_MIN_CHARS), RENAME_ENTRY_MAX_CHARS));
-        gtk_editable_select_region (GTK_EDITABLE (widget_data->name_entry),
-                                    start_offset, end_offset);
-
-        /* Update the rename button status */
-        file_name_widget_entry_on_changed (widget_data);
+        NautilusFilesView *view;
 
+        view = NAUTILUS_FILES_VIEW (user_data);
 
-        g_object_unref (builder);
+        g_clear_object (&view->details->new_folder_controller);
 }
 
 static void
 nautilus_files_view_new_folder_dialog_new (NautilusFilesView *view,
                                            gboolean           with_selection)
 {
-        FileNameWidgetData *widget_data;
-        GtkWidget *label_file_name;
-        GtkBuilder *builder;
+        NautilusDirectory *containing_directory;
         GList *selection;
-        char *common_prefix;
-
-        builder = gtk_builder_new_from_resource ("/org/gnome/nautilus/ui/nautilus-create-folder-dialog.ui");
-        label_file_name = GTK_WIDGET (gtk_builder_get_object (builder, "name_label"));
-
-        widget_data = g_new (FileNameWidgetData, 1);
-        widget_data->view = view;
-        widget_data->on_name_accepted = create_folder_on_name_accepted;
-        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;
-        widget_data->with_selection = with_selection;
-
-        gtk_window_set_transient_for (GTK_WINDOW (widget_data->widget),
-                                      GTK_WINDOW (nautilus_files_view_get_window (view)));
-
-        /* Connect signals */
-        gtk_builder_add_callback_symbols (builder,
-                                          "file_name_widget_entry_on_changed",
-                                          G_CALLBACK (file_name_widget_entry_on_changed),
-                                          "file_name_widget_on_activate",
-                                          G_CALLBACK (file_name_widget_on_activate),
-                                          "create_folder_dialog_on_response",
-                                          G_CALLBACK (create_folder_dialog_on_response),
-                                          NULL);
+        g_autofree char *uri = NULL;
+        g_autofree char *common_prefix = NULL;
+
+        if (view->details->new_folder_controller != NULL) {
+                return;
+        }
+
+        uri = nautilus_files_view_get_backing_uri (view);
+        containing_directory = nautilus_directory_get_by_uri (uri);
 
         selection = nautilus_view_get_selection (NAUTILUS_VIEW (view));
         common_prefix = nautilus_get_common_filename_prefix (selection, MIN_COMMON_FILENAME_PREFIX_LENGTH);
-        if (common_prefix != NULL) {
-                gtk_entry_set_text (GTK_ENTRY (widget_data->name_entry), common_prefix);
-                g_free (common_prefix);
-        }
 
-        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 (widget_data->widget), _("New Folder"));
+        view->details->new_folder_controller =
+                nautilus_new_folder_dialog_controller_new (nautilus_files_view_get_containing_window (view),
+                                                           containing_directory,
+                                                           with_selection,
+                                                           common_prefix);
 
-        gtk_widget_show_all (widget_data->widget);
-        /* Update the ok button status */
-        file_name_widget_entry_on_changed (widget_data);
+        g_signal_connect (view->details->new_folder_controller,
+                          "name-accepted",
+                          (GCallback)new_folder_dialog_controller_on_name_accepted,
+                          view);
+        g_signal_connect (view->details->new_folder_controller,
+                          "cancelled",
+                          (GCallback)new_folder_dialog_controller_on_cancelled,
+                          view);
 
         nautilus_file_list_free (selection);
-        g_object_unref (builder);
+        nautilus_directory_unref (containing_directory);
 }
 
 static void
@@ -2931,13 +2630,10 @@ nautilus_files_view_finalize (GObject *object)
         g_clear_object (&view->details->selection_menu);
         g_clear_object (&view->details->toolbar_menu_sections->zoom_section);
         g_clear_object (&view->details->toolbar_menu_sections->extended_section);
+        g_clear_object (&view->details->rename_file_controller);
+        g_clear_object (&view->details->new_folder_controller);
         g_free (view->details->toolbar_menu_sections);
 
-        if (view->details->rename_file_popover != NULL) {
-                gtk_popover_set_relative_to (GTK_POPOVER (view->details->rename_file_popover),
-                                             NULL);
-        }
-
         g_hash_table_destroy (view->details->non_ready_files);
         g_hash_table_destroy (view->details->pending_reveal);
 
diff --git a/src/nautilus-new-folder-dialog-controller.c b/src/nautilus-new-folder-dialog-controller.c
new file mode 100644
index 0000000..ba79a78
--- /dev/null
+++ b/src/nautilus-new-folder-dialog-controller.c
@@ -0,0 +1,151 @@
+#include <glib/gi18n.h>
+
+#include <eel/eel-vfs-extensions.h>
+
+#include "nautilus-new-folder-dialog-controller.h"
+
+
+struct _NautilusNewFolderDialogController {
+        NautilusFileNameWidgetController parent_instance;
+
+        GtkWidget *new_folder_dialog;
+
+        gboolean with_selection;
+
+        gint response_handler_id;
+};
+
+G_DEFINE_TYPE (NautilusNewFolderDialogController, nautilus_new_folder_dialog_controller, 
NAUTILUS_TYPE_FILE_NAME_WIDGET_CONTROLLER)
+
+static gboolean
+nautilus_new_folder_dialog_controller_name_is_valid (NautilusFileNameWidgetController  *self,
+                                                     gchar                             *name,
+                                                     gchar                            **error_message)
+{
+        g_assert (*error_message == NULL);
+
+        if (strlen (name) == 0) {
+                return FALSE;
+        }
+
+        if (strstr (name, "/") != NULL) {
+                *error_message = _("Folder names cannot contain “/”.");
+        } else if (strcmp (name, ".") == 0){
+                *error_message = _("A folder can not be called “.”.");
+        } else if (strcmp (name, "..") == 0){
+                *error_message = _("A folder can not be called “..”.");
+        }
+
+        return *error_message == NULL;
+}
+
+static void
+new_folder_dialog_controller_on_response (GtkDialog *dialog,
+                                          gint       response_id,
+                                          gpointer   user_data)
+{
+        NautilusNewFolderDialogController *controller;
+
+        controller = NAUTILUS_NEW_FOLDER_DIALOG_CONTROLLER (user_data);
+
+        if (response_id != GTK_RESPONSE_OK) {
+                g_signal_emit_by_name (controller, "cancelled");
+        }
+}
+
+NautilusNewFolderDialogController *
+nautilus_new_folder_dialog_controller_new (GtkWindow         *parent_window,
+                                           NautilusDirectory *destination_directory,
+                                           gboolean           with_selection,
+                                           gchar             *initial_name)
+{
+        NautilusNewFolderDialogController *self;
+        GtkBuilder *builder;
+        GtkWidget *new_folder_dialog;
+        GtkWidget *error_label;
+        GtkWidget *name_entry;
+        GtkWidget *activate_button;
+        GtkWidget *name_label;
+
+        builder = gtk_builder_new_from_resource ("/org/gnome/nautilus/ui/nautilus-create-folder-dialog.ui");
+        new_folder_dialog = GTK_WIDGET (gtk_builder_get_object (builder, "create_folder_dialog"));
+        error_label = GTK_WIDGET (gtk_builder_get_object (builder, "error_label"));
+        name_entry = GTK_WIDGET (gtk_builder_get_object (builder, "name_entry"));
+        activate_button = GTK_WIDGET (gtk_builder_get_object (builder, "ok_button"));
+        name_label = GTK_WIDGET (gtk_builder_get_object (builder, "name_label"));
+
+        gtk_window_set_transient_for (GTK_WINDOW (new_folder_dialog),
+                                      parent_window);
+
+        self = g_object_new (NAUTILUS_TYPE_NEW_FOLDER_DIALOG_CONTROLLER,
+                             "error-label", error_label,
+                             "name-entry", name_entry,
+                             "activate-button", activate_button,
+                             "containing-directory", destination_directory, NULL);
+
+        self->with_selection = with_selection;
+
+        self->new_folder_dialog = new_folder_dialog;
+
+        self->response_handler_id = g_signal_connect (new_folder_dialog,
+                                                      "response",
+                                                      (GCallback)new_folder_dialog_controller_on_response,
+                                                      self);
+
+        if (initial_name != NULL) {
+                gtk_entry_set_text (GTK_ENTRY (name_entry), initial_name);
+        }
+
+        gtk_button_set_label (GTK_BUTTON (activate_button), _("Create"));
+        gtk_label_set_text (GTK_LABEL (name_label), _("Folder name"));
+        gtk_window_set_title (GTK_WINDOW (new_folder_dialog), _("New Folder"));
+
+        gtk_widget_show_all (new_folder_dialog);
+
+        g_object_unref (builder);
+
+        return self;
+}
+
+gboolean
+nautilus_new_folder_dialog_controller_get_with_selection (NautilusNewFolderDialogController *self)
+{
+        return self->with_selection;
+}
+
+static void
+nautilus_new_folder_dialog_controller_init (NautilusNewFolderDialogController *self)
+{
+
+}
+
+static void
+nautilus_new_folder_dialog_controller_finalize (GObject *object)
+{
+        NautilusNewFolderDialogController *self;
+
+        self = NAUTILUS_NEW_FOLDER_DIALOG_CONTROLLER (object);
+
+        if (self->new_folder_dialog != NULL) {
+                if (self->response_handler_id) {
+                        g_signal_handler_disconnect (self->new_folder_dialog,
+                                                     self->response_handler_id);
+                        self->response_handler_id = 0;
+                }
+                gtk_widget_destroy (self->new_folder_dialog);
+                self->new_folder_dialog = NULL;
+        }
+
+        G_OBJECT_CLASS (nautilus_new_folder_dialog_controller_parent_class)->finalize (object);
+}
+
+static void
+nautilus_new_folder_dialog_controller_class_init (NautilusNewFolderDialogControllerClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+        NautilusFileNameWidgetControllerClass *parent_class = NAUTILUS_FILE_NAME_WIDGET_CONTROLLER_CLASS 
(klass);
+
+        object_class->finalize = nautilus_new_folder_dialog_controller_finalize;
+
+        parent_class->name_is_valid = nautilus_new_folder_dialog_controller_name_is_valid;
+}
diff --git a/src/nautilus-new-folder-dialog-controller.h b/src/nautilus-new-folder-dialog-controller.h
new file mode 100644
index 0000000..a9a8f28
--- /dev/null
+++ b/src/nautilus-new-folder-dialog-controller.h
@@ -0,0 +1,20 @@
+#ifndef NAUTILUS_NEW_FOLDER_DIALOG_CONTROLLER_H
+#define NAUTILUS_NEW_FOLDER_DIALOG_CONTROLLER_H
+
+#include <glib.h>
+#include <gtk/gtk.h>
+
+#include "nautilus-file-name-widget-controller.h"
+#include "nautilus-directory.h"
+
+#define NAUTILUS_TYPE_NEW_FOLDER_DIALOG_CONTROLLER nautilus_new_folder_dialog_controller_get_type ()
+G_DECLARE_FINAL_TYPE (NautilusNewFolderDialogController, nautilus_new_folder_dialog_controller, NAUTILUS, 
NEW_FOLDER_DIALOG_CONTROLLER, NautilusFileNameWidgetController)
+
+NautilusNewFolderDialogController * nautilus_new_folder_dialog_controller_new (GtkWindow         
*parent_window,
+                                                                               NautilusDirectory 
*destination_directory,
+                                                                               gboolean           
with_selection,
+                                                                               gchar             
*initial_name);
+
+gboolean nautilus_new_folder_dialog_controller_get_with_selection (NautilusNewFolderDialogController 
*controller);
+
+#endif /* NAUTILUS_NEW_FOLDER_DIALOG_CONTROLLER_H */
diff --git a/src/nautilus-rename-file-popover-controller.c b/src/nautilus-rename-file-popover-controller.c
new file mode 100644
index 0000000..9455a1c
--- /dev/null
+++ b/src/nautilus-rename-file-popover-controller.c
@@ -0,0 +1,226 @@
+#include <glib/gi18n.h>
+
+#include <eel/eel-vfs-extensions.h>
+
+#include "nautilus-rename-file-popover-controller.h"
+
+#include "nautilus-directory.h"
+#include "nautilus-file-private.h"
+
+
+#define RENAME_ENTRY_MIN_CHARS 20
+#define RENAME_ENTRY_MAX_CHARS 35
+
+struct _NautilusRenameFilePopoverController {
+        NautilusFileNameWidgetController parent_instance;
+
+        NautilusFile *target_file;
+        gboolean target_is_folder;
+
+        GtkWidget *rename_file_popover;
+
+        gint closed_handler_id;
+};
+
+G_DEFINE_TYPE (NautilusRenameFilePopoverController, nautilus_rename_file_popover_controller, 
NAUTILUS_TYPE_FILE_NAME_WIDGET_CONTROLLER)
+
+static void
+rename_file_popover_controller_on_closed (GtkPopover *popover,
+                                          gpointer    user_data)
+{
+        NautilusRenameFilePopoverController *controller;
+
+        controller = NAUTILUS_RENAME_FILE_POPOVER_CONTROLLER (user_data);
+
+        g_signal_handler_disconnect (controller->rename_file_popover,
+                                     controller->closed_handler_id);
+        controller->closed_handler_id = 0;
+        controller->rename_file_popover = NULL;
+
+        g_signal_emit_by_name (controller, "cancelled");
+}
+
+static gboolean
+nautilus_rename_file_popover_controller_name_is_valid (NautilusFileNameWidgetController  *controller,
+                                                       gchar                             *name,
+                                                       gchar                            **error_message)
+{
+        NautilusRenameFilePopoverController *self;
+
+        g_assert (*error_message == NULL);
+
+        self = NAUTILUS_RENAME_FILE_POPOVER_CONTROLLER (controller);
+
+        if (strlen (name) == 0) {
+                return FALSE;
+        }
+
+        if (strstr (name, "/") != NULL) {
+                if (self->target_is_folder) {
+                        *error_message = _("Folder names cannot contain “/”.");
+                }
+                else {
+                        *error_message = _("File names cannot contain “/”.");
+                }
+        } else if (strcmp (name, ".") == 0){
+                if (self->target_is_folder) {
+                        *error_message = _("A folder can not be called “.”.");
+                }
+                else {
+                        *error_message = _("A file can not be called “.”.");
+                }
+        } else if (strcmp (name, "..") == 0){
+                if (self->target_is_folder) {
+                        *error_message = _("A folder can not be called “..”.");
+                }
+                else {
+                        *error_message = _("A file can not be called “..”.");
+                }
+        }
+
+        return *error_message == NULL;
+}
+
+static gboolean
+nautilus_rename_file_popover_controller_ignore_existing_file (NautilusFileNameWidgetController *controller,
+                                                              NautilusFile                     
*existing_file)
+{
+        NautilusRenameFilePopoverController *self;
+        g_autofree gchar *display_name;
+
+        self = NAUTILUS_RENAME_FILE_POPOVER_CONTROLLER (controller);
+
+        display_name = nautilus_file_get_display_name (existing_file);
+
+        return nautilus_file_compare_display_name (self->target_file, display_name) == 0;
+}
+
+NautilusRenameFilePopoverController *
+nautilus_rename_file_popover_controller_new (NautilusFile *target_file,
+                                             GdkRectangle *pointing_to,
+                                             GtkWidget    *relative_to)
+{
+        NautilusRenameFilePopoverController *self;
+        GtkBuilder *builder;
+        GtkWidget *rename_file_popover;
+        GtkWidget *error_label;
+        GtkWidget *name_entry;
+        GtkWidget *activate_button;
+        GtkWidget *name_label;
+        NautilusDirectory *containing_directory;
+        gint start_offset;
+        gint end_offset;
+        gint n_chars;
+
+        builder = gtk_builder_new_from_resource ("/org/gnome/nautilus/ui/nautilus-rename-file-popover.ui");
+        rename_file_popover = GTK_WIDGET (gtk_builder_get_object (builder, "rename_file_popover"));
+        error_label = GTK_WIDGET (gtk_builder_get_object (builder, "error_label"));
+        name_entry = GTK_WIDGET (gtk_builder_get_object (builder, "name_entry"));
+        activate_button = GTK_WIDGET (gtk_builder_get_object (builder, "rename_button"));
+        name_label = GTK_WIDGET (gtk_builder_get_object (builder, "name_label"));
+
+        if (!nautilus_file_is_self_owned (target_file)) {
+                NautilusFile *parent_location;
+
+                parent_location = nautilus_file_get_parent (target_file);
+                containing_directory = nautilus_directory_get_for_file (parent_location);
+
+                nautilus_file_unref (parent_location);
+        } else {
+                containing_directory = nautilus_directory_get_for_file (target_file);
+        }
+
+        self = g_object_new (NAUTILUS_TYPE_RENAME_FILE_POPOVER_CONTROLLER,
+                             "error-label", error_label,
+                             "name-entry", name_entry,
+                             "activate-button", activate_button,
+                             "containing-directory", containing_directory, NULL);
+
+        self->target_is_folder = nautilus_file_is_directory (target_file);
+        self->target_file = nautilus_file_ref (target_file);
+
+        self->rename_file_popover = rename_file_popover;
+
+        self->closed_handler_id = g_signal_connect (rename_file_popover,
+                                                    "closed",
+                                                    (GCallback)rename_file_popover_controller_on_closed,
+                                                    self);
+        g_signal_connect (rename_file_popover,
+                          "unmap",
+                          (GCallback)gtk_widget_destroy,
+                          NULL);
+
+        gtk_label_set_text (GTK_LABEL (name_label),
+                            self->target_is_folder ? _("Folder name") :
+                                                     _("File name"));
+
+        gtk_entry_set_text (GTK_ENTRY (name_entry),
+                            nautilus_file_get_display_name (target_file));
+
+        gtk_popover_set_default_widget (GTK_POPOVER (rename_file_popover), name_entry);
+        gtk_popover_set_pointing_to (GTK_POPOVER (rename_file_popover), pointing_to);
+        gtk_popover_set_relative_to (GTK_POPOVER (rename_file_popover), relative_to);
+
+        gtk_widget_show (rename_file_popover);
+
+        /* Select the name part withouth the file extension */
+        eel_filename_get_rename_region (nautilus_file_get_display_name (target_file),
+                                        &start_offset, &end_offset);
+        n_chars = g_utf8_strlen (nautilus_file_get_display_name (target_file), -1);
+        gtk_entry_set_width_chars (GTK_ENTRY (name_entry),
+                                   MIN (MAX (n_chars, RENAME_ENTRY_MIN_CHARS), RENAME_ENTRY_MAX_CHARS));
+        gtk_editable_select_region (GTK_EDITABLE (name_entry), start_offset, end_offset);
+
+        g_object_unref (builder);
+        nautilus_directory_unref (containing_directory);
+
+        return self;
+}
+
+NautilusFile *
+nautilus_rename_file_popover_controller_get_target_file (NautilusRenameFilePopoverController *self)
+{
+        g_return_val_if_fail (NAUTILUS_IS_RENAME_FILE_POPOVER_CONTROLLER (self), NULL);
+
+        return self->target_file;
+}
+
+static void
+nautilus_rename_file_popover_controller_init (NautilusRenameFilePopoverController *self)
+{
+
+}
+
+static void
+nautilus_rename_file_popover_controller_finalize (GObject *object)
+{
+        NautilusRenameFilePopoverController *self;
+
+        self = NAUTILUS_RENAME_FILE_POPOVER_CONTROLLER (object);
+
+        if (self->rename_file_popover) {
+                if (self->closed_handler_id) {
+                        g_signal_handler_disconnect (self->rename_file_popover,
+                                                     self->closed_handler_id);
+                        self->closed_handler_id = 0;
+                }
+                gtk_widget_hide (self->rename_file_popover);
+                self->rename_file_popover = NULL;
+        }
+
+        nautilus_file_unref (self->target_file);
+
+        G_OBJECT_CLASS (nautilus_rename_file_popover_controller_parent_class)->finalize (object);
+}
+
+static void
+nautilus_rename_file_popover_controller_class_init (NautilusRenameFilePopoverControllerClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+        NautilusFileNameWidgetControllerClass *parent_class = NAUTILUS_FILE_NAME_WIDGET_CONTROLLER_CLASS 
(klass);
+
+        object_class->finalize = nautilus_rename_file_popover_controller_finalize;
+
+        parent_class->name_is_valid = nautilus_rename_file_popover_controller_name_is_valid;
+        parent_class->ignore_existing_file = nautilus_rename_file_popover_controller_ignore_existing_file;
+}
diff --git a/src/nautilus-rename-file-popover-controller.h b/src/nautilus-rename-file-popover-controller.h
new file mode 100644
index 0000000..540b3fd
--- /dev/null
+++ b/src/nautilus-rename-file-popover-controller.h
@@ -0,0 +1,19 @@
+#ifndef NAUTILUS_RENAME_FILE_POPOVER_CONTROLLER_H
+#define NAUTILUS_RENAME_FILE_POPOVER_CONTROLLER_H
+
+#include <glib.h>
+#include <gtk/gtk.h>
+
+#include "nautilus-file-name-widget-controller.h"
+#include "nautilus-file.h"
+
+#define NAUTILUS_TYPE_RENAME_FILE_POPOVER_CONTROLLER nautilus_rename_file_popover_controller_get_type ()
+G_DECLARE_FINAL_TYPE (NautilusRenameFilePopoverController, nautilus_rename_file_popover_controller, 
NAUTILUS, RENAME_FILE_POPOVER_CONTROLLER, NautilusFileNameWidgetController)
+
+NautilusRenameFilePopoverController * nautilus_rename_file_popover_controller_new (NautilusFile *target_file,
+                                                                                   GdkRectangle *pointing_to,
+                                                                                   GtkWidget    
*relative_to);
+
+NautilusFile * nautilus_rename_file_popover_controller_get_target_file (NautilusRenameFilePopoverController 
*controller);
+
+#endif /* NAUTILUS_RENAME_FILE_POPOVER_CONTROLLER_H */
diff --git a/src/resources/ui/nautilus-create-folder-dialog.ui 
b/src/resources/ui/nautilus-create-folder-dialog.ui
index e39f5e6..1e044bf 100644
--- a/src/resources/ui/nautilus-create-folder-dialog.ui
+++ b/src/resources/ui/nautilus-create-folder-dialog.ui
@@ -9,7 +9,6 @@
     <property name="type_hint">dialog</property>
     <property name="use-header-bar">1</property>
     <property name="width_request">450</property>
-    <signal name="response" handler="create_folder_dialog_on_response"/>
     <child internal-child="vbox">
       <object class="GtkBox" id="vbox">
         <property name="orientation">vertical</property>
@@ -33,8 +32,6 @@
           <object class="GtkEntry" id="name_entry">
             <property name="visible">True</property>
             <property name="can_focus">True</property>
-            <signal name="changed" handler="file_name_widget_entry_on_changed" swapped="yes" />
-            <signal name="activate" handler="file_name_widget_on_activate" swapped="yes" />
           </object>
           <packing>
             <property name="expand">False</property>
diff --git a/src/resources/ui/nautilus-rename-file-popover.ui 
b/src/resources/ui/nautilus-rename-file-popover.ui
index ff60a97..fb10559 100644
--- a/src/resources/ui/nautilus-rename-file-popover.ui
+++ b/src/resources/ui/nautilus-rename-file-popover.ui
@@ -2,8 +2,6 @@
 <interface>
   <object class="GtkPopover" id="rename_file_popover">
     <property name="position">bottom</property>
-    <signal name="closed" handler="rename_file_popover_on_closed"/>
-    <signal name="unmap" handler="rename_file_popover_on_unmap"/>
     <child>
       <object class="GtkGrid">
         <property name="visible">True</property>
@@ -27,8 +25,7 @@
         <child>
           <object class="GtkEntry" id="name_entry">
             <property name="visible">True</property>
-            <property name="activates-default">True</property>
-            <signal name="changed" handler="file_name_widget_entry_on_changed" swapped="yes" />
+            <property name="can_default">True</property>
           </object>
           <packing>
             <property name="left-attach">0</property>
@@ -41,8 +38,6 @@
             <property name="sensitive">False</property>
             <property name="label" translatable="yes">_Rename</property>
             <property name="use_underline">True</property>
-            <property name="can_default">True</property>
-            <signal name="clicked" handler="file_name_widget_on_activate" swapped="yes" />
             <style>
               <class name="suggested-action"/>
             </style>


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