summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Larsson <alexl@redhat.com>2003-12-12 17:55:47 +0000
committerAlexander Larsson <alexl@src.gnome.org>2003-12-12 17:55:47 +0000
commit00b39e067c148c5eed16691a3b103e1b6219bb27 (patch)
tree11351765c343d3a7ba2a997919baf6d86ff3fb31
parent1e841b24202d3f0cc880f75a1af961da22d22bc2 (diff)
downloadnautilus-00b39e067c148c5eed16691a3b103e1b6219bb27.tar.gz
New function nautilus_file_operations_new_file.
2003-12-12 Alexander Larsson <alexl@redhat.com> * libnautilus-private/nautilus-file-operations.[ch]: New function nautilus_file_operations_new_file. * libnautilus-private/nautilus-file-utilities.[ch]: New template directory functions * src/nautilus-navigation-window-ui.xml: * src/nautilus-spatial-window-ui.xml: * src/nautilus-window-menus.c: Add Templates in location menu * src/file-manager/fm-directory-view.[ch]: * src/file-manager/nautilus-directory-view-ui.xml: Implement the templates menu. Fix issue that affected create new folder too, sometimes the file has already been added before we get the done callback.
-rw-r--r--ChangeLog20
-rw-r--r--libnautilus-private/nautilus-file-operations.c204
-rw-r--r--libnautilus-private/nautilus-file-operations.h36
-rw-r--r--libnautilus-private/nautilus-file-utilities.c29
-rw-r--r--libnautilus-private/nautilus-file-utilities.h4
-rw-r--r--src/file-manager/fm-directory-view.c534
-rw-r--r--src/file-manager/fm-directory-view.h2
-rw-r--r--src/file-manager/nautilus-directory-view-ui.xml23
-rw-r--r--src/nautilus-navigation-window-ui.xml5
-rw-r--r--src/nautilus-spatial-window-ui.xml5
-rw-r--r--src/nautilus-window-menus.c15
11 files changed, 806 insertions, 71 deletions
diff --git a/ChangeLog b/ChangeLog
index a08aaaff4..3d35a96ce 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,23 @@
+2003-12-12 Alexander Larsson <alexl@redhat.com>
+
+ * libnautilus-private/nautilus-file-operations.[ch]:
+ New function nautilus_file_operations_new_file.
+
+ * libnautilus-private/nautilus-file-utilities.[ch]:
+ New template directory functions
+
+ * src/nautilus-navigation-window-ui.xml:
+ * src/nautilus-spatial-window-ui.xml:
+ * src/nautilus-window-menus.c:
+ Add Templates in location menu
+
+ * src/file-manager/fm-directory-view.[ch]:
+ * src/file-manager/nautilus-directory-view-ui.xml:
+ Implement the templates menu.
+ Fix issue that affected create new folder too,
+ sometimes the file has already been added before
+ we get the done callback.
+
2003-12-12 Christian Neumair <chris@gnome-de.org>
* components/Makefile.am
diff --git a/libnautilus-private/nautilus-file-operations.c b/libnautilus-private/nautilus-file-operations.c
index fe64cef28..395ae9a76 100644
--- a/libnautilus-private/nautilus-file-operations.c
+++ b/libnautilus-private/nautilus-file-operations.c
@@ -2089,7 +2089,7 @@ new_folder_transfer_callback (GnomeVFSAsyncHandle *handle,
case GNOME_VFS_XFER_PROGRESS_STATUS_OK:
nautilus_file_changes_consume_changes (TRUE);
(* state->done_callback) (progress_info->target_name, state->data);
- return 0;
+ return 1;
case GNOME_VFS_XFER_PROGRESS_STATUS_DUPLICATE:
@@ -2165,6 +2165,208 @@ nautilus_file_operations_new_folder (GtkWidget *parent_view,
gnome_vfs_uri_unref (parent_uri);
}
+typedef struct {
+ GnomeVFSAsyncHandle *handle;
+ void (* done_callback)(const char *new_folder_uri, gpointer data);
+ gpointer data;
+ GtkWidget *parent_view;
+ char *empty_file;
+ GHashTable *debuting_uris;
+} NewFileTransferState;
+
+
+static int
+handle_new_file_vfs_error (const GnomeVFSXferProgressInfo *progress_info, NewFileTransferState *state)
+{
+ const char *error_string;
+ char *error_string_to_free;
+
+ error_string_to_free = NULL;
+
+ if (progress_info->vfs_status == GNOME_VFS_ERROR_ACCESS_DENIED) {
+ error_string = _("You do not have permissions to write to the destination.");
+ } else if (progress_info->vfs_status == GNOME_VFS_ERROR_NO_SPACE) {
+ error_string = _("There is no space on the destination.");
+ } else {
+ error_string = g_strdup_printf (_("Error \"%s\" creating new document."),
+ gnome_vfs_result_to_string (progress_info->vfs_status));
+ error_string_to_free = (char *)error_string;
+ }
+
+ eel_show_error_dialog (_("Error creating new document."), error_string, _("Error Creating New Document"),
+ GTK_WINDOW (gtk_widget_get_toplevel (state->parent_view)));
+
+ g_free (error_string_to_free);
+
+ return GNOME_VFS_XFER_ERROR_ACTION_ABORT;
+}
+
+static void
+get_new_file_uri (gpointer key,
+ gpointer value,
+ gpointer user_data)
+{
+ char *uri;
+ char **uri_out;
+
+ uri = key;
+ uri_out = user_data;
+
+ *uri_out = uri;
+}
+
+
+static int
+new_file_transfer_callback (GnomeVFSAsyncHandle *handle,
+ GnomeVFSXferProgressInfo *progress_info,
+ gpointer data)
+{
+ NewFileTransferState *state;
+ char *temp_string;
+ char *uri;
+
+ state = (NewFileTransferState *) data;
+
+ switch (progress_info->phase) {
+
+ case GNOME_VFS_XFER_PHASE_COMPLETED:
+ uri = NULL;
+ g_hash_table_foreach (state->debuting_uris,
+ get_new_file_uri, &uri);
+
+ (* state->done_callback) (uri, state->data);
+ /* uri is owned by hashtable, don't free */
+
+ if (state->empty_file != NULL) {
+ unlink (state->empty_file);
+ g_free (state->empty_file);
+ }
+ eel_remove_weak_pointer (&state->parent_view);
+ g_hash_table_destroy (state->debuting_uris);
+ g_free (state);
+ return 0;
+
+ default:
+ switch (progress_info->status) {
+ case GNOME_VFS_XFER_PROGRESS_STATUS_OK:
+ nautilus_file_changes_consume_changes (TRUE);
+ return 1;
+
+ case GNOME_VFS_XFER_PROGRESS_STATUS_DUPLICATE:
+
+ temp_string = progress_info->duplicate_name;
+
+ if (progress_info->vfs_status == GNOME_VFS_ERROR_NAME_TOO_LONG) {
+ /* special case an 8.3 file system */
+ progress_info->duplicate_name = g_strndup (temp_string, 8);
+ progress_info->duplicate_name[8] = '\0';
+ g_free (temp_string);
+ temp_string = progress_info->duplicate_name;
+ progress_info->duplicate_name = g_strdup_printf
+ ("%s.%d",
+ progress_info->duplicate_name,
+ progress_info->duplicate_count);
+ } else {
+ progress_info->duplicate_name = g_strdup_printf
+ ("%s%%20%d",
+ progress_info->duplicate_name,
+ progress_info->duplicate_count);
+ }
+ g_free (temp_string);
+ return GNOME_VFS_XFER_ERROR_ACTION_SKIP;
+
+ case GNOME_VFS_XFER_PROGRESS_STATUS_VFSERROR:
+ return handle_new_file_vfs_error (progress_info, state);
+
+
+
+ default:
+ g_warning (_("Unknown GnomeVFSXferProgressStatus %d"),
+ progress_info->status);
+ return 0;
+ }
+ }
+}
+
+void
+nautilus_file_operations_new_file (GtkWidget *parent_view,
+ const char *parent_dir,
+ const char *source_uri_text,
+ void (*done_callback) (const char *, gpointer),
+ gpointer data)
+{
+ GList *target_uri_list;
+ GList *source_uri_list;
+ GnomeVFSURI *target_uri, *parent_uri, *source_uri;
+ char *filename;
+ NewFileTransferState *state;
+ SyncTransferInfo *sync_transfer_info;
+
+ state = g_new (NewFileTransferState, 1);
+ state->done_callback = done_callback;
+ state->data = data;
+ state->parent_view = parent_view;
+ state->empty_file = NULL;
+
+ /* pass in the target directory and the new folder name as a destination URI */
+ parent_uri = gnome_vfs_uri_new (parent_dir);
+
+ if (source_uri_text != NULL) {
+ source_uri = gnome_vfs_uri_new (source_uri_text);
+ if (source_uri == NULL) {
+ (*done_callback) (NULL, data);
+ g_free (state);
+ return;
+ }
+ filename = gnome_vfs_uri_extract_short_path_name (source_uri);
+ target_uri = gnome_vfs_uri_append_string (parent_uri, filename);
+ g_free (filename);
+ } else {
+ char empty_file[] = "/tmp/emptyXXXXXX";
+ char *empty_uri;
+ int fd;
+
+ fd = mkstemp (empty_file);
+ if (fd == -1) {
+ (*done_callback) (NULL, data);
+ g_free (state);
+ }
+ close (fd);
+
+ empty_uri = gnome_vfs_get_uri_from_local_path (empty_file);
+ source_uri = gnome_vfs_uri_new (empty_uri);
+ g_free (empty_uri);
+
+ state->empty_file = g_strdup (empty_file);
+
+ filename = g_filename_from_utf8 (_("new file"), -1, NULL, NULL, NULL);
+ target_uri = gnome_vfs_uri_append_file_name (parent_uri, filename);
+ g_free (filename);
+ }
+
+ state->debuting_uris = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+ eel_add_weak_pointer (&state->parent_view);
+
+ target_uri_list = g_list_prepend (NULL, target_uri);
+ source_uri_list = g_list_prepend (NULL, source_uri);
+
+ sync_transfer_info = g_new (SyncTransferInfo, 1);
+ sync_transfer_info->iterator = NULL;
+ sync_transfer_info->debuting_uris = state->debuting_uris;
+
+ gnome_vfs_async_xfer (&state->handle, source_uri_list, target_uri_list,
+ GNOME_VFS_XFER_USE_UNIQUE_NAMES,
+ GNOME_VFS_XFER_ERROR_MODE_QUERY,
+ GNOME_VFS_XFER_OVERWRITE_MODE_QUERY,
+ GNOME_VFS_PRIORITY_DEFAULT,
+ new_file_transfer_callback, state,
+ sync_transfer_callback, sync_transfer_info);
+
+ gnome_vfs_uri_list_free (target_uri_list);
+ gnome_vfs_uri_list_free (source_uri_list);
+ gnome_vfs_uri_unref (parent_uri);
+}
+
void
nautilus_file_operations_delete (const GList *item_uris,
GtkWidget *parent_view)
diff --git a/libnautilus-private/nautilus-file-operations.h b/libnautilus-private/nautilus-file-operations.h
index 3fe6918ca..ead8f44ad 100644
--- a/libnautilus-private/nautilus-file-operations.h
+++ b/libnautilus-private/nautilus-file-operations.h
@@ -34,22 +34,30 @@ typedef void (* NautilusCopyCallback) (GHashTable *debuting_uris,
gpointer callback_data);
typedef void (* NautilusNewFolderCallback) (const char *new_folder_uri,
gpointer callback_data);
+typedef void (* NautilusNewFileCallback) (const char *new_file_uri,
+ gpointer callback_data);
/* FIXME: int copy_action should be an enum */
-void nautilus_file_operations_copy_move (const GList *item_uris,
- GArray *target_item_points,
- const char *target_dir_uri,
- GdkDragAction copy_action,
- GtkWidget *parent_view,
- NautilusCopyCallback done_callback,
- gpointer done_callback_data);
-void nautilus_file_operations_empty_trash (GtkWidget *parent_view);
-void nautilus_file_operations_new_folder (GtkWidget *parent_view,
- const char *parent_dir_uri,
- NautilusNewFolderCallback done_callback,
- gpointer done_callback_data);
-void nautilus_file_operations_delete (const GList *item_uris,
- GtkWidget *parent_view);
+void nautilus_file_operations_copy_move (const GList *item_uris,
+ GArray *target_item_points,
+ const char *target_dir_uri,
+ GdkDragAction copy_action,
+ GtkWidget *parent_view,
+ NautilusCopyCallback done_callback,
+ gpointer done_callback_data);
+void nautilus_file_operations_empty_trash (GtkWidget *parent_view);
+void nautilus_file_operations_new_folder (GtkWidget *parent_view,
+ const char *parent_dir_uri,
+ NautilusNewFolderCallback done_callback,
+ gpointer done_callback_data);
+void nautilus_file_operations_new_file (GtkWidget *parent_view,
+ const char *parent_dir,
+ const char *source_uri_text,
+ NautilusNewFileCallback done_callback,
+ gpointer data);
+void nautilus_file_operations_delete (const GList *item_uris,
+ GtkWidget *parent_view);
+
#endif /* NAUTILUS_FILE_OPERATIONS_H */
diff --git a/libnautilus-private/nautilus-file-utilities.c b/libnautilus-private/nautilus-file-utilities.c
index 1e6bd302c..94b25e135 100644
--- a/libnautilus-private/nautilus-file-utilities.c
+++ b/libnautilus-private/nautilus-file-utilities.c
@@ -166,6 +166,35 @@ nautilus_get_desktop_directory_uri_no_create (void)
return desktop_uri;
}
+char *
+nautilus_get_templates_directory (void)
+{
+ return g_build_filename (g_get_home_dir(),
+ "Templates", NULL);
+}
+
+void
+nautilus_create_templates_directory (void)
+{
+ char *dir;
+
+ dir = nautilus_get_templates_directory ();
+ if (!g_file_test (dir, G_FILE_TEST_EXISTS)) {
+ mkdir (dir, DEFAULT_NAUTILUS_DIRECTORY_MODE);
+ }
+ g_free (dir);
+}
+
+char *
+nautilus_get_templates_directory_uri (void)
+{
+ char *directory, *uri;
+
+ directory = nautilus_get_templates_directory ();
+ uri = gnome_vfs_get_uri_from_local_path (directory);
+ g_free (directory);
+ return uri;
+}
/* These need to be reset to NULL when desktop_is_home_dir changes */
static char *escaped_desktop_dir = NULL;
diff --git a/libnautilus-private/nautilus-file-utilities.h b/libnautilus-private/nautilus-file-utilities.h
index 9f83dd565..831e353b6 100644
--- a/libnautilus-private/nautilus-file-utilities.h
+++ b/libnautilus-private/nautilus-file-utilities.h
@@ -43,6 +43,10 @@ gboolean nautilus_is_desktop_directory_escaped (char *escaped_dir);
char * nautilus_get_gmc_desktop_directory (void);
char * nautilus_get_pixmap_directory (void);
+char * nautilus_get_templates_directory (void);
+char * nautilus_get_templates_directory_uri (void);
+void nautilus_create_templates_directory (void);
+
/* This function returns something that needs to be freed with g_free,
* is not NULL, but is not garaunteed to exist */
char * nautilus_get_desktop_directory_uri_no_create (void);
diff --git a/src/file-manager/fm-directory-view.c b/src/file-manager/fm-directory-view.c
index 29e204357..7c8c74866 100644
--- a/src/file-manager/fm-directory-view.c
+++ b/src/file-manager/fm-directory-view.c
@@ -139,6 +139,8 @@
#define FM_DIRECTORY_VIEW_COMMAND_MEDIA_PROPERTIES_VOLUME_CONDITIONAL "/commands/Media Properties Conditional"
#define FM_DIRECTORY_VIEW_MENU_PATH_OPEN_WITH "/menu/File/Open Placeholder/Open With"
+#define FM_DIRECTORY_VIEW_MENU_PATH_NEW_DOCUMENTS "/menu/File/New Items Placeholder/New Documents"
+#define FM_DIRECTORY_VIEW_MENU_PATH_NEW_DOCUMENTS_NO_TEMPLATES "/menu/File/New Items Placeholder/New Documents/No Templates"
#define FM_DIRECTORY_VIEW_MENU_PATH_SCRIPTS "/menu/File/Open Placeholder/Scripts"
#define FM_DIRECTORY_VIEW_MENU_PATH_TRASH "/menu/Edit/Dangerous File Items Placeholder/Trash"
#define FM_DIRECTORY_VIEW_MENU_PATH_DELETE "/menu/Edit/Dangerous File Items Placeholder/Delete"
@@ -151,6 +153,8 @@
#define FM_DIRECTORY_VIEW_MENU_PATH_OTHER_VIEWER "/menu/File/Open Placeholder/Open With/OtherViewer"
#define FM_DIRECTORY_VIEW_MENU_PATH_SCRIPTS_PLACEHOLDER "/menu/File/Open Placeholder/Scripts/Scripts Placeholder"
#define FM_DIRECTORY_VIEW_MENU_PATH_SCRIPTS_SEPARATOR "/menu/File/Open Placeholder/Scripts/After Scripts"
+#define FM_DIRECTORY_VIEW_MENU_PATH_NEW_DOCUMENTS_PLACEHOLDER "/menu/File/New Items Placeholder/New Documents/New Documents Placeholder"
+#define FM_DIRECTORY_VIEW_MENU_PATH_NEW_DOCUMENTS_SEPARATOR "/menu/File/New Items Placeholder/New Documents/After New Documents"
#define FM_DIRECTORY_VIEW_MENU_PATH_CUT_FILES "/menu/Edit/Cut"
#define FM_DIRECTORY_VIEW_MENU_PATH_COPY_FILES "/menu/Edit/Copy"
#define FM_DIRECTORY_VIEW_MENU_PATH_PASTE_FILES "/menu/File/Paste"
@@ -161,6 +165,10 @@
#define FM_DIRECTORY_VIEW_POPUP_PATH_BACKGROUND_SCRIPTS "/popups/background/Before Zoom Items/Scripts"
#define FM_DIRECTORY_VIEW_POPUP_PATH_BACKGROUND_SCRIPTS_PLACEHOLDER "/popups/background/Before Zoom Items/Scripts/Scripts Placeholder"
#define FM_DIRECTORY_VIEW_POPUP_PATH_BACKGROUND_SCRIPTS_SEPARATOR "/popups/background/Before Zoom Items/Scripts/After Scripts"
+#define FM_DIRECTORY_VIEW_POPUP_PATH_BACKGROUND_NEW_DOCUMENTS "/popups/background/Before Zoom Items/New Documents"
+#define FM_DIRECTORY_VIEW_POPUP_PATH_BACKGROUND_NEW_DOCUMENTS_NO_TEMPLATES "/popups/background/Before Zoom Items/New Documents/No Templates"
+#define FM_DIRECTORY_VIEW_POPUP_PATH_BACKGROUND_NEW_DOCUMENTS_PLACEHOLDER "/popups/background/Before Zoom Items/New Documents/New Documents Placeholder"
+#define FM_DIRECTORY_VIEW_POPUP_PATH_BACKGROUND_NEW_DOCUMENTS_SEPARATOR "/popups/background/Before Zoom Items/New Documents/After New Documents"
#define FM_DIRECTORY_VIEW_POPUP_PATH_APPLICATIONS_PLACEHOLDER "/popups/selection/Open Placeholder/Open With/Applications Placeholder"
#define FM_DIRECTORY_VIEW_POPUP_PATH_BEFORE_VIEWERS_SEPARATOR "/popups/selection/Open Placeholder/Open With/Before Viewers"
@@ -198,6 +206,9 @@ static gboolean confirm_trash_auto_value;
static char *scripts_directory_uri;
static int scripts_directory_uri_length;
+static char *templates_directory_uri;
+static int templates_directory_uri_length;
+
struct FMDirectoryViewDetails
{
NautilusView *nautilus_view;
@@ -208,6 +219,7 @@ struct FMDirectoryViewDetails
BonoboUIComponent *ui;
GList *scripts_directory_list;
+ GList *templates_directory_list;
guint display_selection_idle_id;
guint update_menus_timeout_id;
@@ -234,6 +246,7 @@ struct FMDirectoryViewDetails
gboolean menus_merged;
gboolean menu_states_untrustworthy;
gboolean scripts_invalid;
+ gboolean templates_invalid;
gboolean reported_load_error;
gboolean sort_directories_first;
@@ -389,6 +402,12 @@ typedef struct {
FMDirectoryView *directory_view;
} ScriptLaunchParameters;
+typedef struct {
+ NautilusFile *file;
+ FMDirectoryView *directory_view;
+} CreateTemplateParameters;
+
+
static ApplicationLaunchParameters *
application_launch_parameters_new (GnomeVFSMimeApplication *application,
NautilusFile *file,
@@ -463,6 +482,30 @@ script_launch_parameters_free (ScriptLaunchParameters *parameters)
g_free (parameters);
}
+static CreateTemplateParameters *
+create_template_parameters_new (NautilusFile *file,
+ FMDirectoryView *directory_view)
+{
+ CreateTemplateParameters *result;
+
+ result = g_new0 (CreateTemplateParameters, 1);
+ g_object_ref (directory_view);
+ result->directory_view = directory_view;
+ nautilus_file_ref (file);
+ result->file = file;
+
+ return result;
+}
+
+static void
+create_templates_parameters_free (CreateTemplateParameters *parameters)
+{
+ g_object_unref (parameters->directory_view);
+ nautilus_file_unref (parameters->file);
+ g_free (parameters);
+}
+
+
/* Returns the GtkWindow that this directory view occupies, or NULL
* if at the moment this directory view is not in a GtkWindow or the
* GtkWindow cannot be determined. Primarily used for parenting dialogs.
@@ -1072,6 +1115,14 @@ new_folder_callback (BonoboUIComponent *component, gpointer callback_data, const
}
static void
+new_empty_file_callback (BonoboUIComponent *component, gpointer callback_data, const char *verb)
+{
+ g_assert (FM_IS_DIRECTORY_VIEW (callback_data));
+
+ fm_directory_view_new_file (FM_DIRECTORY_VIEW (callback_data), NULL);
+}
+
+static void
new_launcher_callback (BonoboUIComponent *component, gpointer callback_data, const char *verb)
{
char *parent_uri;
@@ -1285,6 +1336,17 @@ set_up_scripts_directory_global (void)
}
static void
+set_up_templates_directory_global (void)
+{
+ if (templates_directory_uri != NULL) {
+ return;
+ }
+
+ templates_directory_uri = nautilus_get_templates_directory_uri ();
+ templates_directory_uri_length = strlen (templates_directory_uri);
+}
+
+static void
create_scripts_directory (void)
{
char *gnome1_path, *gnome1_uri_str;
@@ -1330,6 +1392,19 @@ scripts_added_or_changed_callback (NautilusDirectory *directory,
}
static void
+templates_added_or_changed_callback (NautilusDirectory *directory,
+ GList *files,
+ gpointer callback_data)
+{
+ FMDirectoryView *view;
+
+ view = FM_DIRECTORY_VIEW (callback_data);
+
+ view->details->templates_invalid = TRUE;
+ schedule_update_menus (view);
+}
+
+static void
icons_changed_callback (gpointer callback_data)
{
FMDirectoryView *view;
@@ -1337,57 +1412,100 @@ icons_changed_callback (gpointer callback_data)
view = FM_DIRECTORY_VIEW (callback_data);
view->details->scripts_invalid = TRUE;
+ view->details->templates_invalid = TRUE;
schedule_update_menus (view);
}
static void
-add_directory_to_scripts_directory_list (FMDirectoryView *view,
- NautilusDirectory *directory)
+add_directory_to_directory_list (FMDirectoryView *view,
+ NautilusDirectory *directory,
+ GList **directory_list,
+ GCallback changed_callback)
{
NautilusFileAttributes attributes;
- if (g_list_find (view->details->scripts_directory_list, directory) == NULL) {
+ if (g_list_find (*directory_list, directory) == NULL) {
nautilus_directory_ref (directory);
attributes = nautilus_icon_factory_get_required_file_attributes ();
attributes |= NAUTILUS_FILE_ATTRIBUTE_CAPABILITIES |
NAUTILUS_FILE_ATTRIBUTE_DIRECTORY_ITEM_COUNT;
- nautilus_directory_file_monitor_add (directory, &view->details->scripts_directory_list,
+ nautilus_directory_file_monitor_add (directory, directory_list,
FALSE, FALSE, attributes,
- scripts_added_or_changed_callback, view);
+ (NautilusDirectoryCallback)changed_callback, view);
g_signal_connect_object (directory, "files_added",
- G_CALLBACK (scripts_added_or_changed_callback), view, 0);
+ G_CALLBACK (changed_callback), view, 0);
g_signal_connect_object (directory, "files_changed",
- G_CALLBACK (scripts_added_or_changed_callback), view, 0);
+ G_CALLBACK (changed_callback), view, 0);
- view->details->scripts_directory_list = g_list_append
- (view->details->scripts_directory_list, directory);
+ *directory_list = g_list_append (*directory_list, directory);
}
}
static void
-remove_directory_from_scripts_directory_list (FMDirectoryView *view,
- NautilusDirectory *directory)
+remove_directory_from_directory_list (FMDirectoryView *view,
+ NautilusDirectory *directory,
+ GList **directory_list,
+ GCallback changed_callback)
{
- view->details->scripts_directory_list = g_list_remove
- (view->details->scripts_directory_list, directory);
+ *directory_list = g_list_remove (*directory_list, directory);
g_signal_handlers_disconnect_by_func (directory,
- G_CALLBACK (scripts_added_or_changed_callback),
+ G_CALLBACK (changed_callback),
view);
- nautilus_directory_file_monitor_remove (directory, &view->details->scripts_directory_list);
+ nautilus_directory_file_monitor_remove (directory, directory_list);
nautilus_directory_unref (directory);
}
+
+static void
+add_directory_to_scripts_directory_list (FMDirectoryView *view,
+ NautilusDirectory *directory)
+{
+ add_directory_to_directory_list (view, directory,
+ &view->details->scripts_directory_list,
+ G_CALLBACK (scripts_added_or_changed_callback));
+}
+
+static void
+remove_directory_from_scripts_directory_list (FMDirectoryView *view,
+ NautilusDirectory *directory)
+{
+ remove_directory_from_directory_list (view, directory,
+ &view->details->scripts_directory_list,
+ G_CALLBACK (scripts_added_or_changed_callback));
+}
+
+static void
+add_directory_to_templates_directory_list (FMDirectoryView *view,
+ NautilusDirectory *directory)
+{
+ add_directory_to_directory_list (view, directory,
+ &view->details->templates_directory_list,
+ G_CALLBACK (templates_added_or_changed_callback));
+}
+
+static void
+remove_directory_from_templates_directory_list (FMDirectoryView *view,
+ NautilusDirectory *directory)
+{
+ remove_directory_from_directory_list (view, directory,
+ &view->details->templates_directory_list,
+ G_CALLBACK (templates_added_or_changed_callback));
+}
+
+
+
static void
fm_directory_view_init (FMDirectoryView *view)
{
static gboolean setup_autos = FALSE;
NautilusDirectory *scripts_directory;
+ NautilusDirectory *templates_directory;
if (!setup_autos) {
setup_autos = TRUE;
@@ -1410,11 +1528,15 @@ fm_directory_view_init (FMDirectoryView *view)
view->details->nautilus_view = nautilus_view_new (GTK_WIDGET (view));
set_up_scripts_directory_global ();
-
scripts_directory = nautilus_directory_get (scripts_directory_uri);
add_directory_to_scripts_directory_list (view, scripts_directory);
nautilus_directory_unref (scripts_directory);
+ set_up_templates_directory_global ();
+ templates_directory = nautilus_directory_get (templates_directory_uri);
+ add_directory_to_templates_directory_list (view, templates_directory);
+ nautilus_directory_unref (templates_directory);
+
view->details->zoomable = bonobo_zoomable_new ();
bonobo_zoomable_set_parameters_full (view->details->zoomable,
0.0, .25, 4.0, TRUE, TRUE, FALSE,
@@ -1512,6 +1634,12 @@ fm_directory_view_finalize (GObject *object)
remove_directory_from_scripts_directory_list (view, node->data);
}
+ for (node = view->details->templates_directory_list; node != NULL; node = next) {
+ next = node->next;
+ remove_directory_from_templates_directory_list (view, node->data);
+ }
+
+
nautilus_directory_unref (view->details->model);
view->details->model = NULL;
nautilus_file_unref (view->details->directory_as_file);
@@ -3246,29 +3374,58 @@ start_renaming_file (FMDirectoryView *view, NautilusFile *file)
}
static void
+rename_file (FMDirectoryView *view, NautilusFile *new_file)
+{
+ /* no need to select because start_renaming_file selects
+ * fm_directory_view_select_file (view, new_file);
+ */
+ EEL_CALL_METHOD (FM_DIRECTORY_VIEW_CLASS, view, start_renaming_file, (view, new_file));
+ fm_directory_view_reveal_selection (view);
+}
+
+static void
reveal_newly_added_folder (FMDirectoryView *view, NautilusFile *new_file, const char *target_uri)
{
if (nautilus_file_matches_uri (new_file, target_uri)) {
g_signal_handlers_disconnect_by_func (view,
G_CALLBACK (reveal_newly_added_folder),
(void *) target_uri);
- /* no need to select because start_renaming_file selects
- * fm_directory_view_select_file (view, new_file);
- */
- EEL_CALL_METHOD (FM_DIRECTORY_VIEW_CLASS, view, start_renaming_file, (view, new_file));
- fm_directory_view_reveal_selection (view);
+ rename_file (view, new_file);
}
}
+typedef struct {
+ FMDirectoryView *directory_view;
+ GHashTable *added_uris;
+} NewFolderData;
+
+
static void
-new_folder_done (const char *new_folder_uri, gpointer data)
+track_newly_added_uris (FMDirectoryView *view, NautilusFile *new_file, gpointer user_data)
+{
+ NewFolderData *data;
+
+ data = user_data;
+
+ g_hash_table_insert (data->added_uris, nautilus_file_get_uri (new_file), NULL);
+}
+
+static void
+new_folder_done (const char *new_folder_uri, gpointer user_data)
{
FMDirectoryView *directory_view;
NautilusFile *file;
char *screen_string;
GdkScreen *screen;
+ NewFolderData *data;
- directory_view = (FMDirectoryView *) data;
+ data = (NewFolderData *)user_data;
+
+ if (new_folder_uri == NULL) {
+ goto fail;
+ }
+
+ directory_view = data->directory_view;
g_assert (FM_IS_DIRECTORY_VIEW (directory_view));
screen = gtk_widget_get_screen (GTK_WIDGET (directory_view));
@@ -3281,31 +3438,92 @@ new_folder_done (const char *new_folder_uri, gpointer data)
screen_string);
g_free (screen_string);
- /* We need to run after the default handler adds the folder we want to
- * operate on. The ADD_FILE signal is registered as G_SIGNAL_RUN_LAST, so we
- * must use connect_after.
- */
- g_signal_connect_data (directory_view,
- "add_file",
- G_CALLBACK (reveal_newly_added_folder),
- g_strdup (new_folder_uri),
- (GClosureNotify)g_free,
- G_CONNECT_AFTER);
+ g_signal_handlers_disconnect_by_func (directory_view,
+ G_CALLBACK (track_newly_added_uris),
+ (void *) data);
+
+ if (g_hash_table_lookup_extended (data->added_uris, new_folder_uri, NULL, NULL)) {
+ /* The file was already added */
+ rename_file (directory_view, file);
+ } else {
+ /* We need to run after the default handler adds the folder we want to
+ * operate on. The ADD_FILE signal is registered as G_SIGNAL_RUN_LAST, so we
+ * must use connect_after.
+ */
+ g_signal_connect_data (directory_view,
+ "add_file",
+ G_CALLBACK (reveal_newly_added_folder),
+ g_strdup (new_folder_uri),
+ (GClosureNotify)g_free,
+ G_CONNECT_AFTER);
+ }
+
+ fail:
+ g_hash_table_destroy (data->added_uris);
+ g_free (data);
}
void
fm_directory_view_new_folder (FMDirectoryView *directory_view)
{
char *parent_uri;
+ NewFolderData *data;
+
+ data = g_new (NewFolderData, 1);
+ data->directory_view = directory_view;
+ data->added_uris = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, NULL);
+
+ g_signal_connect_data (directory_view,
+ "add_file",
+ G_CALLBACK (track_newly_added_uris),
+ data,
+ (GClosureNotify)NULL,
+ G_CONNECT_AFTER);
parent_uri = fm_directory_view_get_backing_uri (directory_view);
nautilus_file_operations_new_folder (GTK_WIDGET (directory_view),
parent_uri,
- new_folder_done, directory_view);
+ new_folder_done, data);
g_free (parent_uri);
}
+void
+fm_directory_view_new_file (FMDirectoryView *directory_view,
+ NautilusFile *source)
+{
+ char *parent_uri;
+ char *source_uri;
+ NewFolderData *data;
+
+ data = g_new (NewFolderData, 1);
+ data->directory_view = directory_view;
+ data->added_uris = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, NULL);
+
+ g_signal_connect_data (directory_view,
+ "add_file",
+ G_CALLBACK (track_newly_added_uris),
+ data,
+ (GClosureNotify)NULL,
+ G_CONNECT_AFTER);
+
+
+ source_uri = NULL;
+ if (source != NULL) {
+ source_uri = nautilus_file_get_uri (source);
+ }
+ parent_uri = fm_directory_view_get_backing_uri (directory_view);
+ nautilus_file_operations_new_file (GTK_WIDGET (directory_view),
+ parent_uri,
+ source_uri,
+ new_folder_done, data);
+ g_free (parent_uri);
+ g_free (source_uri);
+}
+
+
/* handle the open command */
static void
@@ -3364,6 +3582,10 @@ add_numbered_menu_item (BonoboUIComponent *ui,
GDestroyNotify destroy_notify)
{
char *escaped_parent_path, *escaped_label, *verb_name, *item_path;
+
+ if (parent_path == NULL) {
+ return;
+ }
escaped_parent_path = eel_str_double_underscores (parent_path);
@@ -3399,11 +3621,13 @@ add_submenu (BonoboUIComponent *ui,
{
char *escaped_parent_path, *escaped_label;
- escaped_parent_path = eel_str_double_underscores (parent_path);
- escaped_label = eel_str_double_underscores (label);
- nautilus_bonobo_add_submenu (ui, escaped_parent_path, escaped_label, pixbuf);
- g_free (escaped_label);
- g_free (escaped_parent_path);
+ if (parent_path != NULL) {
+ escaped_parent_path = eel_str_double_underscores (parent_path);
+ escaped_label = eel_str_double_underscores (label);
+ nautilus_bonobo_add_submenu (ui, escaped_parent_path, escaped_label, pixbuf);
+ g_free (escaped_label);
+ g_free (escaped_parent_path);
+ }
}
static void
@@ -4170,12 +4394,12 @@ run_script_callback (BonoboUIComponent *component, gpointer callback_data, const
}
static void
-add_script_to_script_menus (FMDirectoryView *directory_view,
- NautilusFile *file,
- int index,
- const char *menu_path,
- const char *popup_path,
- const char *popup_bg_path)
+add_script_to_scripts_menus (FMDirectoryView *directory_view,
+ NautilusFile *file,
+ int index,
+ const char *menu_path,
+ const char *popup_path,
+ const char *popup_bg_path)
{
ScriptLaunchParameters *launch_parameters;
char *tip;
@@ -4227,11 +4451,11 @@ add_script_to_script_menus (FMDirectoryView *directory_view,
}
static void
-add_submenu_to_script_menus (FMDirectoryView *directory_view,
- NautilusFile *file,
- const char *menu_path,
- const char *popup_path,
- const char *popup_bg_path)
+add_submenu_to_directory_menus (FMDirectoryView *directory_view,
+ NautilusFile *file,
+ const char *menu_path,
+ const char *popup_path,
+ const char *popup_bg_path)
{
char *name;
GdkPixbuf *pixbuf;
@@ -4279,19 +4503,22 @@ update_directory_in_scripts_menu (FMDirectoryView *view, NautilusDirectory *dire
NautilusFile *file;
NautilusDirectory *dir;
char *uri;
+ char *escaped_path;
int i;
uri = nautilus_directory_get_uri (directory);
+ escaped_path = gnome_vfs_escape_path_string (uri + scripts_directory_uri_length);
+ g_free (uri);
menu_path = g_strconcat (FM_DIRECTORY_VIEW_MENU_PATH_SCRIPTS_PLACEHOLDER,
- uri + scripts_directory_uri_length,
+ escaped_path,
NULL);
popup_path = g_strconcat (FM_DIRECTORY_VIEW_POPUP_PATH_SCRIPTS_PLACEHOLDER,
- uri + scripts_directory_uri_length,
+ escaped_path,
NULL);
popup_bg_path = g_strconcat (FM_DIRECTORY_VIEW_POPUP_PATH_BACKGROUND_SCRIPTS_PLACEHOLDER,
- uri + scripts_directory_uri_length,
+ escaped_path,
NULL);
- g_free (uri);
+ g_free (escaped_path);
file_list = nautilus_directory_get_file_list (directory);
filtered = nautilus_file_list_filter_hidden_and_backup (file_list, FALSE, FALSE);
@@ -4305,7 +4532,7 @@ update_directory_in_scripts_menu (FMDirectoryView *view, NautilusDirectory *dire
file = node->data;
if (file_is_launchable (file)) {
- add_script_to_script_menus (view, file, i++, menu_path, popup_path, popup_bg_path);
+ add_script_to_scripts_menus (view, file, i++, menu_path, popup_path, popup_bg_path);
any_scripts = TRUE;
} else if (nautilus_file_is_directory (file)) {
uri = nautilus_file_get_uri (file);
@@ -4314,7 +4541,7 @@ update_directory_in_scripts_menu (FMDirectoryView *view, NautilusDirectory *dire
add_directory_to_scripts_directory_list (view, dir);
nautilus_directory_unref (dir);
- add_submenu_to_script_menus (view, file, menu_path, popup_path, popup_bg_path);
+ add_submenu_to_directory_menus (view, file, menu_path, popup_path, popup_bg_path);
any_scripts = TRUE;
}
@@ -4389,6 +4616,196 @@ update_scripts_menu (FMDirectoryView *view)
}
static void
+create_template_callback (BonoboUIComponent *component, gpointer callback_data, const char *path)
+{
+ CreateTemplateParameters *parameters;
+
+ parameters = callback_data;
+
+ fm_directory_view_new_file (parameters->directory_view, parameters->file);
+}
+
+
+static void
+add_template_to_templates_menus (FMDirectoryView *directory_view,
+ NautilusFile *file,
+ int index,
+ const char *menu_path,
+ const char *popup_bg_path)
+{
+ char *tip;
+ char *name;
+ GdkPixbuf *pixbuf;
+ CreateTemplateParameters *parameters;
+
+ name = nautilus_file_get_display_name (file);
+ tip = g_strdup_printf (_("Create Document from template \"%s\""), name);
+
+ pixbuf = nautilus_icon_factory_get_pixbuf_for_file
+ (file, NULL, NAUTILUS_ICON_SIZE_FOR_MENUS);
+
+ parameters = create_template_parameters_new (file, directory_view);
+ add_numbered_menu_item (directory_view->details->ui,
+ menu_path,
+ name,
+ tip,
+ index,
+ pixbuf,
+ create_template_callback,
+ parameters,
+ (GDestroyNotify) create_templates_parameters_free);
+
+ /* Use same uri and no DestroyNotify for popup item, which has same
+ * lifetime as the item in the File menu in the menu bar.
+ */
+ add_numbered_menu_item (directory_view->details->ui,
+ popup_bg_path,
+ name,
+ tip,
+ index,
+ pixbuf,
+ create_template_callback,
+ parameters,
+ NULL);
+
+ g_object_unref (pixbuf);
+ g_free (name);
+ g_free (tip);
+}
+
+
+static gboolean
+directory_belongs_in_templates_menu (const char *uri)
+{
+ int num_levels;
+ int i;
+
+ if (!eel_str_has_prefix (uri, templates_directory_uri)) {
+ return FALSE;
+ }
+
+ num_levels = 0;
+ for (i = templates_directory_uri_length; uri[i] != '\0'; i++) {
+ if (uri[i] == '/') {
+ num_levels++;
+ }
+ }
+
+ if (num_levels > MAX_MENU_LEVELS) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+update_directory_in_templates_menu (FMDirectoryView *view, NautilusDirectory *directory)
+{
+ char *menu_path, *popup_bg_path;
+ GList *file_list, *filtered, *node;
+ gboolean any_templates;
+ NautilusFile *file;
+ NautilusDirectory *dir;
+ char *escaped_path;
+ char *uri;
+ int i;
+
+ uri = nautilus_directory_get_uri (directory);
+ escaped_path = gnome_vfs_escape_path_string (uri + templates_directory_uri_length);
+ g_free (uri);
+ menu_path = g_strconcat (FM_DIRECTORY_VIEW_MENU_PATH_NEW_DOCUMENTS_PLACEHOLDER,
+ escaped_path,
+ NULL);
+ popup_bg_path = g_strconcat (FM_DIRECTORY_VIEW_POPUP_PATH_BACKGROUND_NEW_DOCUMENTS_PLACEHOLDER,
+ escaped_path,
+ NULL);;
+
+ g_free (escaped_path);
+
+ file_list = nautilus_directory_get_file_list (directory);
+ filtered = nautilus_file_list_filter_hidden_and_backup (file_list, FALSE, FALSE);
+ nautilus_file_list_free (file_list);
+
+ file_list = nautilus_file_list_sort_by_display_name (filtered);
+
+ any_templates = FALSE;
+ i = 0;
+ for (node = file_list; node != NULL; node = node->next) {
+ file = node->data;
+
+ if (nautilus_file_is_directory (file)) {
+ uri = nautilus_file_get_uri (file);
+ if (directory_belongs_in_templates_menu (uri)) {
+ dir = nautilus_directory_get (uri);
+ add_directory_to_templates_directory_list (view, dir);
+ nautilus_directory_unref (dir);
+
+ add_submenu_to_directory_menus (view, file, menu_path, NULL, popup_bg_path);
+
+ any_templates = TRUE;
+ }
+ g_free (uri);
+ } else if (nautilus_file_can_read (file)) {
+ add_template_to_templates_menus (view, file, i++, menu_path, popup_bg_path);
+ any_templates = TRUE;
+ }
+ }
+
+ nautilus_file_list_free (file_list);
+
+ g_free (popup_bg_path);
+ g_free (menu_path);
+
+ return any_templates;
+}
+
+
+
+static void
+update_templates_menu (FMDirectoryView *view)
+{
+ gboolean any_templates;
+ GList *sorted_copy, *node;
+ NautilusDirectory *directory;
+ char *uri;
+
+ /* There is a race condition here. If we don't mark the scripts menu as
+ valid before we begin our task then we can lose template menu updates that
+ occur before we finish. */
+ view->details->templates_invalid = FALSE;
+
+ nautilus_bonobo_remove_menu_items_and_commands
+ (view->details->ui, FM_DIRECTORY_VIEW_MENU_PATH_NEW_DOCUMENTS_PLACEHOLDER);
+ nautilus_bonobo_remove_menu_items_and_commands
+ (view->details->ui, FM_DIRECTORY_VIEW_POPUP_PATH_BACKGROUND_NEW_DOCUMENTS_PLACEHOLDER);
+
+ /* As we walk through the directories, remove any that no longer belong. */
+ any_templates = FALSE;
+ sorted_copy = nautilus_directory_list_sort_by_uri
+ (nautilus_directory_list_copy (view->details->templates_directory_list));
+ for (node = sorted_copy; node != NULL; node = node->next) {
+ directory = node->data;
+
+ uri = nautilus_directory_get_uri (directory);
+ if (!directory_belongs_in_templates_menu (uri)) {
+ remove_directory_from_templates_directory_list (view, directory);
+ } else if (update_directory_in_templates_menu (view, directory)) {
+ any_templates = TRUE;
+ }
+ g_free (uri);
+ }
+ nautilus_directory_list_free (sorted_copy);
+
+ nautilus_bonobo_set_hidden (view->details->ui,
+ FM_DIRECTORY_VIEW_MENU_PATH_NEW_DOCUMENTS_NO_TEMPLATES,
+ any_templates);
+ nautilus_bonobo_set_hidden (view->details->ui,
+ FM_DIRECTORY_VIEW_POPUP_PATH_BACKGROUND_NEW_DOCUMENTS_NO_TEMPLATES,
+ any_templates);
+}
+
+
+static void
open_scripts_folder_callback (BonoboUIComponent *component,
gpointer callback_data,
const char *verb)
@@ -4860,6 +5277,7 @@ real_merge_menus (FMDirectoryView *view)
BONOBO_UI_VERB ("Duplicate", duplicate_callback),
BONOBO_UI_VERB ("Empty Trash", bonobo_menu_empty_trash_callback),
BONOBO_UI_VERB ("New Folder", new_folder_callback),
+ BONOBO_UI_VERB ("New Empty File", new_empty_file_callback),
BONOBO_UI_VERB ("New Launcher", new_launcher_callback),
BONOBO_UI_VERB ("Open Scripts Folder", open_scripts_folder_callback),
BONOBO_UI_VERB ("Open", open_callback),
@@ -4900,6 +5318,7 @@ real_merge_menus (FMDirectoryView *view)
}
view->details->scripts_invalid = TRUE;
+ view->details->templates_invalid = TRUE;
}
static void
@@ -5274,6 +5693,9 @@ real_update_menus (FMDirectoryView *view)
if (view->details->scripts_invalid) {
update_scripts_menu (view);
}
+ if (view->details->templates_invalid) {
+ update_templates_menu (view);
+ }
}
/**
diff --git a/src/file-manager/fm-directory-view.h b/src/file-manager/fm-directory-view.h
index 2fa6afaef..3e444f8d5 100644
--- a/src/file-manager/fm-directory-view.h
+++ b/src/file-manager/fm-directory-view.h
@@ -370,6 +370,8 @@ gboolean fm_directory_view_should_show_file (FMDirect
gboolean fm_directory_view_should_sort_directories_first (FMDirectoryView *view);
void fm_directory_view_update_menus (FMDirectoryView *view);
void fm_directory_view_new_folder (FMDirectoryView *view);
+void fm_directory_view_new_file (FMDirectoryView *view,
+ NautilusFile *source);
void fm_directory_view_ignore_hidden_file_preferences (FMDirectoryView *view);
#endif /* FM_DIRECTORY_VIEW_H */
diff --git a/src/file-manager/nautilus-directory-view-ui.xml b/src/file-manager/nautilus-directory-view-ui.xml
index 35f8a238f..13065cb0e 100644
--- a/src/file-manager/nautilus-directory-view-ui.xml
+++ b/src/file-manager/nautilus-directory-view-ui.xml
@@ -18,6 +18,9 @@
<cmd name="New Folder"
_label="Create _Folder"
_tip="Create a new empty folder inside this folder"/>
+ <cmd name="New Empty File"
+ _label="_Empty File"
+ _tip="Create a new empty file inside this folder"/>
<cmd name="New Launcher"
_label="Create L_auncher"
_tip="Create a new launcher"/>
@@ -101,6 +104,16 @@
<menuitem name="New Folder"
accel="*Shift**Control*n"
verb="New Folder"/>
+ <submenu name="New Documents"
+ _label="Create _Document">
+ <menuitem name="No Templates"
+ _label="No templates Installed"
+ sensitive="0"/>
+ <placeholder name="New Documents Placeholder" delimit="none"/>
+ <separator name="After New Documents"/>
+ <menuitem name="New Empty File"
+ verb="New Empty File"/>
+ </submenu>
<menuitem name="New Launcher"
pixtype="stock" pixname="gtk-new"
verb="New Launcher"/>
@@ -209,6 +222,16 @@
pixtype="stock" pixname="gtk-new"
verb="New Launcher"/>
</placeholder>
+ <submenu name="New Documents"
+ _label="Create _Document">
+ <menuitem name="No Templates"
+ _label="No templates Installed"
+ sensitive="0"/>
+ <placeholder name="New Documents Placeholder" delimit="none"/>
+ <separator name="After New Documents"/>
+ <menuitem name="New Empty File"
+ verb="New Empty File"/>
+ </submenu>
<submenu name="Scripts"
_label="_Scripts"
_tip="Run or manage scripts from ~/Nautilus/scripts"
diff --git a/src/nautilus-navigation-window-ui.xml b/src/nautilus-navigation-window-ui.xml
index 9bdeb5691..ab3ce0565 100644
--- a/src/nautilus-navigation-window-ui.xml
+++ b/src/nautilus-navigation-window-ui.xml
@@ -81,6 +81,11 @@
_label="_Computer"
pixtype="stock" pixname="gnome-fs-client"
verb="Go to Computer"/>
+ <menuitem name="Go to Templates"
+ _label="_Templates"
+ _tip="Go to templates folder"
+ pixtype="stock" pixname="gnome-fs-client"
+ verb="Go to Templates"/>
<menuitem name="Go to Trash"
_label="_Trash"
_tip="Go to the trash folder"
diff --git a/src/nautilus-spatial-window-ui.xml b/src/nautilus-spatial-window-ui.xml
index 4a706a1ad..e789e918d 100644
--- a/src/nautilus-spatial-window-ui.xml
+++ b/src/nautilus-spatial-window-ui.xml
@@ -44,6 +44,11 @@
_tip="Go to Computer"
pixtype="stock" pixname="gnome-fs-client"
verb="Go to Computer"/>
+ <menuitem name="Go to Templates"
+ _label="_Templates"
+ _tip="Go to templates folder"
+ pixtype="stock" pixname="gnome-fs-client"
+ verb="Go to Templates"/>
<menuitem name="Go to Trash"
_label="_Trash"
_tip="Go to the trash folder"
diff --git a/src/nautilus-window-menus.c b/src/nautilus-window-menus.c
index 3d5db411f..577ae5059 100644
--- a/src/nautilus-window-menus.c
+++ b/src/nautilus-window-menus.c
@@ -382,6 +382,20 @@ go_menu_go_to_computer_callback (BonoboUIComponent *component,
}
static void
+go_menu_go_to_templates_callback (BonoboUIComponent *component,
+ gpointer user_data,
+ const char *verb)
+{
+ char *uri;
+
+ nautilus_create_templates_directory ();
+ uri = nautilus_get_templates_directory_uri ();
+ nautilus_window_go_to (NAUTILUS_WINDOW (user_data),
+ uri);
+ g_free (uri);
+}
+
+static void
go_menu_go_to_trash_callback (BonoboUIComponent *component,
gpointer user_data,
const char *verb)
@@ -662,6 +676,7 @@ nautilus_window_initialize_menus_part_1 (NautilusWindow *window)
BONOBO_UI_VERB ("Home", go_menu_home_callback),
BONOBO_UI_VERB ("Start Here", go_menu_start_here_callback),
BONOBO_UI_VERB ("Go to Computer", go_menu_go_to_computer_callback),
+ BONOBO_UI_VERB ("Go to Templates", go_menu_go_to_templates_callback),
BONOBO_UI_VERB ("Go to Trash", go_menu_go_to_trash_callback),
BONOBO_UI_VERB ("Go to Burn CD", go_menu_go_to_burn_cd_callback),
BONOBO_UI_VERB ("Go to Location", go_menu_location_callback),