summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDave Camp <campd@src.gnome.org>2004-01-06 21:52:39 +0000
committerDave Camp <campd@src.gnome.org>2004-01-06 21:52:39 +0000
commitebee7d61a54cc79965c0133c4e63d6a7a00eb1d2 (patch)
tree35ddcddb0bcf9c1d0ea0e425fc5c0d5a1f494d9e /src
parentbd6e1847ced6fc5f041f5a05c108290a450c8c05 (diff)
downloadnautilus-ebee7d61a54cc79965c0133c4e63d6a7a00eb1d2.tar.gz
Diffstat (limited to 'src')
-rw-r--r--src/Nautilus_shell.server.in11
-rw-r--r--src/file-manager/Makefile.am4
-rw-r--r--src/file-manager/fm-directory-view.c762
-rw-r--r--src/file-manager/fm-directory-view.h5
-rw-r--r--src/file-manager/fm-error-reporting.c13
-rw-r--r--src/file-manager/fm-icon-container.c33
-rw-r--r--src/file-manager/fm-icon-view.c43
-rw-r--r--src/file-manager/fm-list-model.c51
-rw-r--r--src/file-manager/fm-list-model.h1
-rw-r--r--src/file-manager/fm-list-view.c154
-rw-r--r--src/file-manager/fm-properties-window.c107
-rw-r--r--src/file-manager/fm-properties-window.h5
-rw-r--r--src/file-manager/fm-search-list-view.c99
-rw-r--r--src/file-manager/fm-tree-model.c1797
-rw-r--r--src/file-manager/fm-tree-model.h88
-rw-r--r--src/file-manager/fm-tree-view.c1305
-rw-r--r--src/file-manager/fm-tree-view.h53
-rw-r--r--src/file-manager/nautilus-directory-view-ui.xml24
-rw-r--r--src/file-manager/nautilus-indexing-info.c30
-rw-r--r--src/nautilus-application.c53
-rw-r--r--src/nautilus-application.h2
-rw-r--r--src/nautilus-connect-server-dialog.c27
-rw-r--r--src/nautilus-information-panel.c19
-rw-r--r--src/nautilus-location-bar.c20
-rw-r--r--src/nautilus-location-dialog.c20
-rw-r--r--src/nautilus-location-entry.c1
-rw-r--r--src/nautilus-main.c15
-rw-r--r--src/nautilus-navigation-bar.c2
-rw-r--r--src/nautilus-navigation-bar.h6
-rw-r--r--src/nautilus-navigation-window-menus.c26
-rw-r--r--src/nautilus-navigation-window-ui.xml4
-rw-r--r--src/nautilus-navigation-window.c32
-rw-r--r--src/nautilus-property-browser.c34
-rw-r--r--src/nautilus-server-connect.c28
-rw-r--r--src/nautilus-spatial-window-ui.xml13
-rw-r--r--src/nautilus-spatial-window.c48
-rw-r--r--src/nautilus-view-frame.c2
-rw-r--r--src/nautilus-view-frame.h6
-rw-r--r--src/nautilus-window-manage-views.c103
-rw-r--r--src/nautilus-window-manage-views.h3
-rw-r--r--src/nautilus-window-menus.c17
-rw-r--r--src/nautilus-window-private.h7
-rw-r--r--src/nautilus-window.c52
-rw-r--r--src/nautilus-window.h5
44 files changed, 4675 insertions, 455 deletions
diff --git a/src/Nautilus_shell.server.in b/src/Nautilus_shell.server.in
index 51b7ef937..a9c8d9d62 100644
--- a/src/Nautilus_shell.server.in
+++ b/src/Nautilus_shell.server.in
@@ -109,4 +109,15 @@
<oaf_attribute name="description" type="string" _value="Produces metafile objects for accessing Nautilus metadata"/>
</oaf_server>
+<oaf_server iid="OAFIID:Nautilus_File_Manager_Tree_View" type="factory" location="OAFIID:Nautilus_Factory">
+ <oaf_attribute name="repo_ids" type="stringv">
+ <item value="IDL:Bonobo/Unknown:1.0"/>
+ <item value="IDL:Bonobo/Control:1.0"/>
+ <item value="IDL:Nautilus/View:1.0"/>
+ </oaf_attribute>
+ <oaf_attribute name="name" type="string" _value="Nautilus Tree View"/>
+ <oaf_attribute name="description" type="string" _value="Nautilus Tree side pane"/>
+ <oaf_attribute name="nautilus:sidebar_panel_name" type="string" _value="Tree"/>
+</oaf_server>
+
</oaf_info>
diff --git a/src/file-manager/Makefile.am b/src/file-manager/Makefile.am
index f96ea8ea1..03640c88a 100644
--- a/src/file-manager/Makefile.am
+++ b/src/file-manager/Makefile.am
@@ -27,6 +27,8 @@ libnautilus_file_manager_la_SOURCES= \
fm-search-list-view.c \
nautilus-indexing-info.c \
fm-bonobo-provider.h \
+ fm-tree-model.c \
+ fm-tree-view.c \
fm-desktop-icon-view.h \
fm-directory-view.h \
fm-error-reporting.h \
@@ -38,6 +40,8 @@ libnautilus_file_manager_la_SOURCES= \
fm-properties-window.h \
fm-search-list-view.h \
nautilus-indexing-info.h \
+ fm-tree-model.h \
+ fm-tree-view.h \
$(NULL)
uidir = $(datadir)/gnome-2.0/ui
diff --git a/src/file-manager/fm-directory-view.c b/src/file-manager/fm-directory-view.c
index b757e08a6..336a8fad7 100644
--- a/src/file-manager/fm-directory-view.c
+++ b/src/file-manager/fm-directory-view.c
@@ -141,6 +141,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"
@@ -153,6 +155,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/Edit/Paste"
@@ -164,6 +168,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"
@@ -201,6 +209,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;
@@ -211,9 +222,11 @@ struct FMDirectoryViewDetails
BonoboUIComponent *ui;
GList *scripts_directory_list;
+ GList *templates_directory_list;
guint display_selection_idle_id;
guint update_menus_timeout_id;
+ guint update_status_idle_id;
guint display_pending_idle_id;
@@ -237,6 +250,7 @@ struct FMDirectoryViewDetails
gboolean menus_merged;
gboolean menu_states_untrustworthy;
gboolean scripts_invalid;
+ gboolean templates_invalid;
gboolean reported_load_error;
gboolean sort_directories_first;
@@ -331,6 +345,8 @@ static void zoomable_zoom_to_fit_callback (BonoboZoomable
static void schedule_update_menus (FMDirectoryView *view);
static void schedule_update_menus_callback (gpointer callback_data);
static void remove_update_menus_timeout_callback (FMDirectoryView *view);
+static void schedule_update_status (FMDirectoryView *view);
+static void remove_update_status_idle_callback (FMDirectoryView *view);
static void schedule_idle_display_of_pending_files (FMDirectoryView *view);
static void unschedule_idle_display_of_pending_files (FMDirectoryView *view);
static void unschedule_display_of_pending_files (FMDirectoryView *view);
@@ -362,6 +378,7 @@ EEL_IMPLEMENT_MUST_OVERRIDE_SIGNAL (fm_directory_view, clear)
EEL_IMPLEMENT_MUST_OVERRIDE_SIGNAL (fm_directory_view, file_changed)
EEL_IMPLEMENT_MUST_OVERRIDE_SIGNAL (fm_directory_view, get_background_widget)
EEL_IMPLEMENT_MUST_OVERRIDE_SIGNAL (fm_directory_view, get_selection)
+EEL_IMPLEMENT_MUST_OVERRIDE_SIGNAL (fm_directory_view, get_item_count)
EEL_IMPLEMENT_MUST_OVERRIDE_SIGNAL (fm_directory_view, is_empty)
EEL_IMPLEMENT_MUST_OVERRIDE_SIGNAL (fm_directory_view, reset_to_defaults)
EEL_IMPLEMENT_MUST_OVERRIDE_SIGNAL (fm_directory_view, restore_default_zoom_level)
@@ -386,6 +403,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,
@@ -460,6 +483,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.
@@ -485,19 +532,20 @@ fm_directory_view_confirm_multiple_windows (FMDirectoryView *view, int count)
GtkDialog *dialog;
char *prompt;
char *title;
+ char *detail;
int response;
if (count <= SILENT_WINDOW_OPEN_LIMIT) {
return TRUE;
}
- prompt = g_strdup_printf (_("This will open %d separate windows. "
- "Are you sure you want to do this?"), count);
title = g_strdup_printf (_("Open %d Windows?"), count);
- dialog = eel_show_yes_no_dialog (prompt, title,
+ prompt = _("Are you sure you want to open all files?");
+ detail = g_strdup_printf (_("This will open %d separate windows."), count);
+ dialog = eel_show_yes_no_dialog (prompt, detail, title,
GTK_STOCK_OK, GTK_STOCK_CANCEL,
fm_directory_view_get_containing_window (view));
- g_free (prompt);
+ g_free (detail);
g_free (title);
response = gtk_dialog_run (dialog);
@@ -552,10 +600,28 @@ open_callback (BonoboUIComponent *component, gpointer callback_data, const char
view = FM_DIRECTORY_VIEW (callback_data);
selection = fm_directory_view_get_selection (view);
- fm_directory_view_activate_files (view, selection, Nautilus_ViewFrame_OPEN_ACCORDING_TO_MODE, 0);
+ fm_directory_view_activate_files (view, selection,
+ Nautilus_ViewFrame_OPEN_ACCORDING_TO_MODE,
+ 0);
+ nautilus_file_list_free (selection);
+}
+
+static void
+open_close_parent_callback (BonoboUIComponent *component, gpointer callback_data, const char *verb)
+{
+ GList *selection;
+ FMDirectoryView *view;
+
+ view = FM_DIRECTORY_VIEW (callback_data);
+
+ selection = fm_directory_view_get_selection (view);
+ fm_directory_view_activate_files (view, selection,
+ Nautilus_ViewFrame_OPEN_ACCORDING_TO_MODE,
+ Nautilus_ViewFrame_OPEN_FLAG_CLOSE_BEHIND);
nautilus_file_list_free (selection);
}
+
static void
open_alternate_callback (BonoboUIComponent *component, gpointer callback_data, const char *verb)
{
@@ -840,6 +906,7 @@ confirm_delete_directly (FMDirectoryView *view,
dialog = eel_show_yes_no_dialog
(prompt,
+ _("If you delete an item, it is permanently lost."),
_("Delete?"), GTK_STOCK_DELETE, GTK_STOCK_CANCEL,
fm_directory_view_get_containing_window (view));
@@ -1049,6 +1116,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;
@@ -1080,7 +1155,7 @@ open_properties_window_callback (BonoboUIComponent *component, gpointer callback
view = FM_DIRECTORY_VIEW (callback_data);
selection = fm_directory_view_get_selection (view);
- fm_properties_window_present (selection, view);
+ fm_properties_window_present (selection, GTK_WIDGET (view));
nautilus_file_list_free (selection);
}
@@ -1262,6 +1337,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;
@@ -1307,6 +1393,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;
@@ -1314,57 +1413,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;
@@ -1387,11 +1529,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,
@@ -1489,6 +1635,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);
@@ -1498,6 +1650,7 @@ fm_directory_view_finalize (GObject *object)
}
remove_update_menus_timeout_callback (view);
+ remove_update_status_idle_callback (view);
fm_directory_view_ignore_hidden_file_preferences (view);
@@ -1541,7 +1694,7 @@ fm_directory_view_display_selection_info (FMDirectoryView *view)
GnomeVFSFileSize non_folder_size;
guint non_folder_count, folder_count, folder_item_count;
gboolean folder_item_count_known;
- guint item_count;
+ guint file_item_count;
GList *p;
char *first_item_name;
char *non_folder_str;
@@ -1568,8 +1721,8 @@ fm_directory_view_display_selection_info (FMDirectoryView *view)
file = p->data;
if (nautilus_file_is_directory (file)) {
folder_count++;
- if (nautilus_file_get_directory_item_count (file, &item_count, NULL)) {
- folder_item_count += item_count;
+ if (nautilus_file_get_directory_item_count (file, &file_item_count, NULL)) {
+ folder_item_count += file_item_count;
} else {
folder_item_count_known = FALSE;
}
@@ -1656,7 +1809,23 @@ fm_directory_view_display_selection_info (FMDirectoryView *view)
}
if (folder_count == 0 && non_folder_count == 0) {
- status_string = g_strdup ("");
+ char *free_space_str;
+ char *item_count_str;
+ guint item_count;
+
+ item_count = fm_directory_view_get_item_count (view);
+
+ item_count_str = g_strdup_printf (ngettext ("%u item", "%u items", item_count), item_count);
+
+ free_space_str = nautilus_file_get_volume_free_space (view->details->directory_as_file);
+ if (free_space_str != NULL) {
+ status_string = g_strdup_printf (_("%s, Free space: %s"), item_count_str, free_space_str);
+ g_free (free_space_str);
+ g_free (item_count_str);
+ } else {
+ status_string = item_count_str;
+ }
+
} else if (folder_count == 0) {
status_string = g_strdup (non_folder_str);
} else if (non_folder_count == 0) {
@@ -1801,14 +1970,14 @@ real_file_limit_reached (FMDirectoryView *view)
* no more than the constant limit are displayed.
*/
message = g_strdup_printf (_("The folder \"%s\" contains more files than "
- "Nautilus can handle. Some files will not be "
- "displayed."),
+ "Nautilus can handle."),
directory_name);
g_free (directory_name);
dialog = eel_show_warning_dialog (message,
- _("Too Many Files"),
- fm_directory_view_get_containing_window (view));
+ _("Some files will not be displayed."),
+ _("Too Many Files"),
+ fm_directory_view_get_containing_window (view));
g_free (message);
}
@@ -1836,6 +2005,7 @@ done_loading (FMDirectoryView *view)
if (view->details->nautilus_view != NULL) {
nautilus_view_report_load_complete (view->details->nautilus_view);
schedule_update_menus (view);
+ schedule_update_status (view);
check_for_directory_hard_limit (view);
uris_selected = view->details->pending_uris_selected;
@@ -2455,6 +2625,9 @@ files_added_callback (NautilusDirectory *directory,
view = FM_DIRECTORY_VIEW (callback_data);
queue_pending_files (view, files, &view->details->new_added_files);
+
+ /* The number of items could have changed */
+ schedule_update_status (view);
}
static void
@@ -2467,6 +2640,9 @@ files_changed_callback (NautilusDirectory *directory,
view = FM_DIRECTORY_VIEW (callback_data);
queue_pending_files (view, files, &view->details->new_changed_files);
+ /* The free space or the number of items could have changed */
+ schedule_update_status (view);
+
/* A change in MIME type could affect the Open with menu, for
* one thing, so we need to update menus when files change.
*/
@@ -2777,6 +2953,16 @@ fm_directory_view_get_selection (FMDirectoryView *view)
get_selection, (view));
}
+guint
+fm_directory_view_get_item_count (FMDirectoryView *view)
+{
+ g_return_val_if_fail (FM_IS_DIRECTORY_VIEW (view), 0);
+
+ return EEL_CALL_METHOD_WITH_RETURN_VALUE
+ (FM_DIRECTORY_VIEW_CLASS, view,
+ get_item_count, (view));
+}
+
/**
* fm_directory_view_get_bonobo_ui_container:
*
@@ -3040,7 +3226,9 @@ fm_directory_view_confirm_deletion (FMDirectoryView *view, GList *uris, gboolean
{
GtkDialog *dialog;
char *prompt;
+ char *detail;
int uri_count;
+ char *uri;
char *file_name;
int response;
@@ -3050,29 +3238,31 @@ fm_directory_view_confirm_deletion (FMDirectoryView *view, GList *uris, gboolean
g_assert (uri_count > 0);
if (uri_count == 1) {
- file_name = file_name_from_uri ((char *) uris->data);
-
- prompt = g_strdup_printf (_("\"%s\" cannot be moved to the Trash. Do "
- "you want to delete it immediately?"), file_name);
+ uri = (char *) uris->data;
+ if (eel_uri_is_desktop (uri)) {
+ /* Don't ask for desktop icons */
+ return TRUE;
+ }
+ file_name = file_name_from_uri (uri);
+ prompt = _("Cannot move file to trash, do you want to delete immediately?");
+ detail = g_strdup_printf (_("The file \"%s\" cannot be moved to the trash."), file_name);
g_free (file_name);
} else {
if (all) {
- prompt = g_strdup_printf (_("The %d selected items cannot be moved "
- "to the Trash. Do you want to delete them "
- "immediately?"), uri_count);
+ prompt = _("Cannot move items to trash, do you want to delete them immediately?");
+ detail = g_strdup_printf ("None of the %d selected items can be moved to the Trash", uri_count);
} else {
- prompt = g_strdup_printf (_("%d of the selected items cannot be moved "
- "to the Trash. Do you want to delete those "
- "%d items immediately?"), uri_count, uri_count);
+ prompt = _("Cannot move some items to trash, do you want to delete these immediately?");
+ detail = g_strdup_printf ("%d of the selected items cannot be moved to the Trash", uri_count);
}
}
dialog = eel_show_yes_no_dialog
(prompt,
- _("Delete Immediately?"), GTK_STOCK_DELETE, GTK_STOCK_CANCEL,
+ detail, _("Delete Immediately?"), GTK_STOCK_DELETE, GTK_STOCK_CANCEL,
fm_directory_view_get_containing_window (view));
- g_free (prompt);
+ g_free (detail);
response = gtk_dialog_run (dialog);
gtk_object_destroy (GTK_OBJECT (dialog));
@@ -3102,15 +3292,15 @@ confirm_delete_from_trash (FMDirectoryView *view, GList *uris)
if (uri_count == 1) {
file_name = file_name_from_uri ((char *) uris->data);
prompt = g_strdup_printf (_("Are you sure you want to permanently delete \"%s\" "
- "from the Trash?"), file_name);
+ "from the trash?"), file_name);
g_free (file_name);
} else {
prompt = g_strdup_printf (_("Are you sure you want to permanently delete "
- "the %d selected items from the Trash?"), uri_count);
+ "the %d selected items from the trash?"), uri_count);
}
dialog = eel_show_yes_no_dialog (
- prompt,
+ prompt, _("If you delete an item, it will be permanently lost."),
_("Delete From Trash?"), GTK_STOCK_DELETE, GTK_STOCK_CANCEL,
fm_directory_view_get_containing_window (view));
@@ -3219,29 +3409,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
+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 data)
+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));
@@ -3254,31 +3473,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
@@ -3337,6 +3617,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);
@@ -3372,11 +3656,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
@@ -3878,12 +4164,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;
@@ -3935,11 +4221,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;
@@ -3987,19 +4273,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);
@@ -4013,7 +4302,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);
@@ -4022,7 +4311,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;
}
@@ -4097,6 +4386,204 @@ 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;
+ char *dot;
+ GdkPixbuf *pixbuf;
+ CreateTemplateParameters *parameters;
+
+ name = nautilus_file_get_display_name (file);
+
+ tip = g_strdup_printf (_("Create Document from template \"%s\""), name);
+
+ /* Remove extension */
+ dot = strrchr (name, '.');
+ if (dot != NULL) {
+ *dot = 0;
+ }
+
+ 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)
@@ -4109,7 +4596,8 @@ open_scripts_folder_callback (BonoboUIComponent *component,
eel_show_info_dialog_with_details
(_("All executable files in this folder will appear in the "
- "Scripts menu. Choosing a script from the menu will run "
+ "Scripts menu."),
+ _("Choosing a script from the menu will run "
"that script with any selected items as input."),
_("About Scripts"),
_("All executable files in this folder will appear in the "
@@ -4437,7 +4925,8 @@ drive_mounted_callback (gboolean succeeded,
gpointer data)
{
if (!succeeded) {
- eel_show_error_dialog_with_details (error, _("Mount Error"), detailed_error, NULL);
+ eel_show_error_dialog_with_details (error, NULL,
+ _("Mount Error"), detailed_error, NULL);
}
}
@@ -4498,9 +4987,11 @@ volume_or_drive_unmounted_callback (gboolean succeeded,
eject = GPOINTER_TO_INT (data);
if (!succeeded) {
if (eject) {
- eel_show_error_dialog_with_details (error, _("Unmount Error"), detailed_error, NULL);
+ eel_show_error_dialog_with_details (error, NULL,
+ _("Unmount Error"), detailed_error, NULL);
} else {
- eel_show_error_dialog_with_details (error, _("Eject Error"), detailed_error, NULL);
+ eel_show_error_dialog_with_details (error, NULL,
+ _("Eject Error"), detailed_error, NULL);
}
}
}
@@ -4564,9 +5055,11 @@ 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),
+ BONOBO_UI_VERB ("OpenCloseParent", open_close_parent_callback),
BONOBO_UI_VERB ("OpenAlternate", open_alternate_callback),
BONOBO_UI_VERB ("OtherApplication", other_application_callback),
BONOBO_UI_VERB ("OtherViewer", other_viewer_callback),
@@ -4603,6 +5096,7 @@ real_merge_menus (FMDirectoryView *view)
}
view->details->scripts_invalid = TRUE;
+ view->details->templates_invalid = TRUE;
}
static void
@@ -4977,6 +5471,9 @@ real_update_menus (FMDirectoryView *view)
if (view->details->scripts_invalid) {
update_scripts_menu (view);
}
+ if (view->details->templates_invalid) {
+ update_templates_menu (view);
+ }
}
/**
@@ -5051,6 +5548,47 @@ schedule_update_menus (FMDirectoryView *view)
}
}
+static void
+remove_update_status_idle_callback (FMDirectoryView *view)
+{
+ if (view->details->update_status_idle_id != 0) {
+ g_source_remove (view->details->update_status_idle_id);
+ view->details->update_status_idle_id = 0;
+ }
+}
+
+static gboolean
+update_status_idle_callback (gpointer data)
+{
+ FMDirectoryView *view;
+
+ view = FM_DIRECTORY_VIEW (data);
+ fm_directory_view_display_selection_info (view);
+ view->details->update_status_idle_id = 0;
+ return FALSE;
+}
+
+static void
+schedule_update_status (FMDirectoryView *view)
+{
+ g_assert (FM_IS_DIRECTORY_VIEW (view));
+
+ /* Make sure we haven't already destroyed it */
+ g_assert (view->details->nautilus_view != NULL);
+
+ if (view->details->loading) {
+ /* Don't update status bar while loading the dir */
+ return;
+ }
+
+ if (view->details->update_status_idle_id == 0) {
+ view->details->update_status_idle_id =
+ g_idle_add_full (G_PRIORITY_DEFAULT_IDLE - 20,
+ update_status_idle_callback, view, NULL);
+ }
+}
+
+
/**
* fm_directory_view_notify_selection_changed:
*
@@ -5110,6 +5648,7 @@ report_broken_symbolic_link (FMDirectoryView *view, NautilusFile *file)
{
char *target_path;
char *prompt;
+ char *detail;
GtkDialog *dialog;
GList file_as_list;
int response;
@@ -5117,17 +5656,16 @@ report_broken_symbolic_link (FMDirectoryView *view, NautilusFile *file)
g_assert (nautilus_file_is_broken_symbolic_link (file));
target_path = nautilus_file_get_symbolic_link_target_path (file);
+ prompt = _("The link is borken, do you want to move it to the Trash?");
if (target_path == NULL) {
- prompt = g_strdup_printf (_("This link can't be used, because it has no target. "
- "Do you want to move this link to the Trash?"));
+ detail = g_strdup (_("This link can't be used, because it has no target."));
} else {
- prompt = g_strdup_printf (_("This link can't be used, because its target \"%s\" doesn't exist. "
- "Do you want to move this link to the Trash?"),
- target_path);
+ detail = g_strdup_printf (_("This link can't be used, because its target "
+ "\"%s\" doesn't exist."), target_path);
}
dialog = eel_show_yes_no_dialog (prompt,
- _("Broken Link"), _("Mo_ve to Trash"), GTK_STOCK_CANCEL,
+ detail, _("Broken Link"), _("Mo_ve to Trash"), GTK_STOCK_CANCEL,
fm_directory_view_get_containing_window (view));
gtk_dialog_set_default_response (dialog, GTK_RESPONSE_YES);
@@ -5152,7 +5690,7 @@ report_broken_symbolic_link (FMDirectoryView *view, NautilusFile *file)
}
g_free (target_path);
- g_free (prompt);
+ g_free (detail);
}
static ActivationAction
@@ -5161,6 +5699,7 @@ get_executable_text_file_action (FMDirectoryView *view, NautilusFile *file)
GtkDialog *dialog;
char *file_name;
char *prompt;
+ char *detail;
int preferences_value;
int response;
@@ -5184,21 +5723,25 @@ get_executable_text_file_action (FMDirectoryView *view, NautilusFile *file)
file_name = nautilus_file_get_display_name (file);
- prompt = g_strdup_printf (_("\"%s\" is an executable text file. "
- "Do you want to run it, or display its contents?"),
- file_name);
+ prompt = g_strdup_printf (_("Do you want to run \"%s\", or display its contents?"),
+ file_name);
+ detail = g_strdup_printf (_("\"%s\" is an executable text file."),
+ file_name);
g_free (file_name);
dialog = eel_create_question_dialog (prompt,
+ detail,
_("Run or Display?"),
- _("_Display"), RESPONSE_DISPLAY,
_("Run in _Terminal"), RESPONSE_RUN_IN_TERMINAL,
+ _("_Display"), RESPONSE_DISPLAY,
fm_directory_view_get_containing_window (view));
gtk_dialog_add_button (dialog, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
gtk_dialog_add_button (dialog, _("_Run"), RESPONSE_RUN);
+ gtk_dialog_set_default_response (dialog, GTK_RESPONSE_CANCEL);
gtk_widget_show (GTK_WIDGET (dialog));
g_free (prompt);
+ g_free (detail);
response = gtk_dialog_run (dialog);
gtk_object_destroy (GTK_OBJECT (dialog));
@@ -5292,9 +5835,13 @@ activate_callback (NautilusFile *file, gpointer callback_data)
nautilus_launch_show_file
(file, fm_directory_view_get_containing_window (view));
- file_uri = nautilus_file_get_uri (file);
- egg_recent_model_add (nautilus_recent_get_model (), file_uri);
- g_free (file_uri);
+ /* We should not add trash and directory uris.*/
+ if ((!nautilus_file_is_in_trash (file)) &&
+ (!nautilus_file_is_directory (file))) {
+ file_uri = nautilus_file_get_uri (file);
+ egg_recent_model_add (nautilus_recent_get_model (), file_uri);
+ g_free (file_uri);
+ }
}
}
@@ -5323,7 +5870,10 @@ activation_drive_mounted_callback (gboolean succeeded,
} else {
if (!parameters->cancelled) {
eel_timed_wait_stop (cancel_activate_callback, parameters);
- eel_show_error_dialog_with_details (error, _("Mount Error"), detailed_error, NULL);
+ eel_show_error_dialog_with_details (error, NULL,
+ _("Mount Error"),
+ detailed_error,
+ NULL);
}
nautilus_file_unref (parameters->file);
@@ -5454,7 +6004,7 @@ fm_directory_view_activate_file (FMDirectoryView *view,
parameters->cancelled = FALSE;
file_name = nautilus_file_get_display_name (file);
- timed_wait_prompt = g_strdup_printf (_("Opening \"%s\""), file_name);
+ timed_wait_prompt = g_strdup_printf (_("Opening \"%s\"."), file_name);
g_free (file_name);
eel_timed_wait_start
@@ -5523,6 +6073,7 @@ file_changed_callback (NautilusFile *file, gpointer callback_data)
FMDirectoryView *view = FM_DIRECTORY_VIEW (callback_data);
schedule_update_menus (view);
+ schedule_update_status (view);
/* We might have different capabilities, so we need to update
relative icon emblems . (Writeable etc) */
@@ -6429,6 +6980,7 @@ fm_directory_view_class_init (FMDirectoryViewClass *klass)
EEL_ASSIGN_MUST_OVERRIDE_SIGNAL (klass, fm_directory_view, file_changed);
EEL_ASSIGN_MUST_OVERRIDE_SIGNAL (klass, fm_directory_view, get_background_widget);
EEL_ASSIGN_MUST_OVERRIDE_SIGNAL (klass, fm_directory_view, get_selection);
+ EEL_ASSIGN_MUST_OVERRIDE_SIGNAL (klass, fm_directory_view, get_item_count);
EEL_ASSIGN_MUST_OVERRIDE_SIGNAL (klass, fm_directory_view, is_empty);
EEL_ASSIGN_MUST_OVERRIDE_SIGNAL (klass, fm_directory_view, reset_to_defaults);
EEL_ASSIGN_MUST_OVERRIDE_SIGNAL (klass, fm_directory_view, restore_default_zoom_level);
diff --git a/src/file-manager/fm-directory-view.h b/src/file-manager/fm-directory-view.h
index 2fa6afaef..6f138e9bb 100644
--- a/src/file-manager/fm-directory-view.h
+++ b/src/file-manager/fm-directory-view.h
@@ -152,6 +152,8 @@ struct FMDirectoryViewClass {
/* Return an array of locations of selected icons in their view. */
GArray * (* get_selected_icon_locations) (FMDirectoryView *view);
+ guint (* get_item_count) (FMDirectoryView *view);
+
/* bump_zoom_level is a function pointer that subclasses must override
* to change the zoom level of an object. */
void (* bump_zoom_level) (FMDirectoryView *view,
@@ -299,6 +301,7 @@ gboolean fm_directory_view_can_accept_item (Nautilus
void fm_directory_view_display_selection_info (FMDirectoryView *view);
GList * fm_directory_view_get_selection (FMDirectoryView *view);
void fm_directory_view_stop (FMDirectoryView *view);
+guint fm_directory_view_get_item_count (FMDirectoryView *view);
gboolean fm_directory_view_can_zoom_in (FMDirectoryView *view);
gboolean fm_directory_view_can_zoom_out (FMDirectoryView *view);
GtkWidget * fm_directory_view_get_background_widget (FMDirectoryView *view);
@@ -370,6 +373,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/fm-error-reporting.c b/src/file-manager/fm-error-reporting.c
index 48167add6..09d22c33e 100644
--- a/src/file-manager/fm-error-reporting.c
+++ b/src/file-manager/fm-error-reporting.c
@@ -68,7 +68,8 @@ fm_report_error_loading_directory (NautilusFile *file,
message = g_strdup_printf (_("Sorry, couldn't display all the contents of \"%s\"."), file_name);
}
- eel_show_error_dialog (message, _("Error Displaying Folder"), parent_window);
+ eel_show_error_dialog (_("The folder contents could not be displayed."), message,
+ _("Error Displaying Folder"), parent_window);
g_free (file_name);
g_free (message);
@@ -140,7 +141,8 @@ fm_report_error_renaming_file (NautilusFile *file,
g_free (original_name_truncated);
g_free (new_name_truncated);
- eel_show_error_dialog (message, _("Renaming Error"), parent_window);
+ eel_show_error_dialog (_("The item could not be renamed."), message,
+ _("Renaming Error"), parent_window);
g_free (message);
}
@@ -176,7 +178,7 @@ fm_report_error_setting_group (NautilusFile *file,
g_free (file_name);
}
- eel_show_error_dialog (message, _("Error Setting Group"), parent_window);
+ eel_show_error_dialog (_("The group could not be changed."), message , _("Error Setting Group"), parent_window);
g_free (file_name);
g_free (message);
@@ -208,7 +210,7 @@ fm_report_error_setting_owner (NautilusFile *file,
message = g_strdup_printf (_("Sorry, couldn't change the owner of \"%s\"."), file_name);
}
- eel_show_error_dialog (message, _("Error Setting Owner"), parent_window);
+ eel_show_error_dialog (_("The owner could not be changed."), message, _("Error Setting Owner"), parent_window);
g_free (file_name);
g_free (message);
@@ -240,7 +242,8 @@ fm_report_error_setting_permissions (NautilusFile *file,
message = g_strdup_printf (_("Sorry, couldn't change the permissions of \"%s\"."), file_name);
}
- eel_show_error_dialog (message, _("Error Setting Permissions"), parent_window);
+ eel_show_error_dialog (_("The permissions could not be changed."), message,
+ _("Error Setting Permissions"), parent_window);
g_free (file_name);
g_free (message);
diff --git a/src/file-manager/fm-icon-container.c b/src/file-manager/fm-icon-container.c
index 6cffbaabe..b84509898 100644
--- a/src/file-manager/fm-icon-container.c
+++ b/src/file-manager/fm-icon-container.c
@@ -24,6 +24,8 @@
#include <config.h>
#include <libgnome/gnome-macros.h>
+#include <libgnome/gnome-i18n.h>
+#include <libgnomevfs/gnome-vfs-mime-handlers.h>
#include <libgnomevfs/gnome-vfs-ops.h>
#include <libgnomevfs/gnome-vfs-uri.h>
#include <libgnomevfs/gnome-vfs-utils.h>
@@ -54,7 +56,8 @@ fm_icon_container_get_icon_images (NautilusIconContainer *container,
NautilusIconData *data,
GList **emblem_icons,
char **embedded_text,
- gboolean *embedded_text_needs_loading)
+ gboolean *embedded_text_needs_loading,
+ gboolean *has_window_open)
{
FMIconView *icon_view;
EelStringList *emblems_to_ignore;
@@ -78,9 +81,32 @@ fm_icon_container_get_icon_images (NautilusIconContainer *container,
eel_string_list_free (emblems_to_ignore);
}
+ *has_window_open = nautilus_file_has_open_window (file);
+
return nautilus_icon_factory_get_icon_for_file (file, TRUE);
}
+static char *
+fm_icon_container_get_icon_description (NautilusIconContainer *container,
+ NautilusIconData *data)
+{
+ NautilusFile *file;
+ char *mime_type;
+ const char *description;
+
+ file = NAUTILUS_FILE (data);
+ g_assert (NAUTILUS_IS_FILE (file));
+
+ if (NAUTILUS_IS_DESKTOP_ICON_FILE (file)) {
+ return NULL;
+ }
+
+ mime_type = nautilus_file_get_mime_type (file);
+ description = gnome_vfs_mime_get_description (mime_type);
+ g_free (mime_type);
+ return g_strdup (description);
+}
+
static void
fm_icon_container_start_monitor_top_left (NautilusIconContainer *container,
NautilusIconData *data,
@@ -445,6 +471,7 @@ fm_icon_container_class_init (FMIconContainerClass *klass)
ic_class->get_icon_text = fm_icon_container_get_icon_text;
ic_class->get_icon_images = fm_icon_container_get_icon_images;
+ ic_class->get_icon_description = fm_icon_container_get_icon_description;
ic_class->start_monitor_top_left = fm_icon_container_start_monitor_top_left;
ic_class->stop_monitor_top_left = fm_icon_container_stop_monitor_top_left;
ic_class->prioritize_thumbnailing = fm_icon_container_prioritize_thumbnailing;
@@ -463,9 +490,13 @@ fm_icon_container_instance_init (FMIconContainer *icon_container)
NautilusIconContainer *
fm_icon_container_construct (FMIconContainer *icon_container, FMIconView *view)
{
+ AtkObject *atk_obj;
+
g_return_val_if_fail (FM_IS_ICON_VIEW (view), NULL);
icon_container->view = view;
+ atk_obj = gtk_widget_get_accessible (GTK_WIDGET (icon_container));
+ atk_object_set_name (atk_obj, _("Icon View"));
return NAUTILUS_ICON_CONTAINER (icon_container);
}
diff --git a/src/file-manager/fm-icon-view.c b/src/file-manager/fm-icon-view.c
index f2e66989c..3ee68925c 100644
--- a/src/file-manager/fm-icon-view.c
+++ b/src/file-manager/fm-icon-view.c
@@ -1358,6 +1358,33 @@ fm_icon_view_get_selection (FMDirectoryView *view)
}
static void
+count_item (NautilusIconData *icon_data,
+ gpointer callback_data)
+{
+ guint *count;
+
+ count = callback_data;
+ (*count)++;
+}
+
+static guint
+fm_icon_view_get_item_count (FMDirectoryView *view)
+{
+ guint count;
+
+ g_return_val_if_fail (FM_IS_ICON_VIEW (view), 0);
+
+ count = 0;
+
+ nautilus_icon_container_for_each
+ (get_icon_container (FM_ICON_VIEW (view)),
+ count_item, &count);
+
+ return count;
+}
+
+
+static void
set_sort_criterion_by_id (FMIconView *icon_view, const char *id)
{
const SortCriterion *sort;
@@ -1771,8 +1798,9 @@ play_file (gpointer callback_data)
file_uri = nautilus_file_get_uri (file);
mime_type = nautilus_file_get_mime_type (file);
is_mp3 = eel_strcasecmp (mime_type, "audio/mpeg") == 0;
- is_ogg = eel_strcasecmp (mime_type, "application/x-ogg") == 0;
-
+ is_ogg = eel_strcasecmp (mime_type, "application/x-ogg") == 0 ||
+ eel_strcasecmp (mime_type, "application/ogg") == 0;
+
mp3_pid = fork ();
if (mp3_pid == (pid_t) 0) {
/* Set the group (session) id to this process for future killing. */
@@ -2541,8 +2569,9 @@ icon_view_handle_uri_list (NautilusIconContainer *container, const char *item_ur
if (eel_vfs_has_capability (container_uri,
EEL_VFS_CAPABILITY_IS_REMOTE_AND_SLOW)) {
- eel_show_warning_dialog (_("Drag and drop is only supported to local file systems."),
- _("Drag and Drop error"),
+ eel_show_warning_dialog (_("Drag and drop is not supported."),
+ _("Drag and drop is only supported on local file systems."),
+ _("Drag and Drop Error"),
fm_directory_view_get_containing_window (FM_DIRECTORY_VIEW (view)));
g_free (container_uri);
return;
@@ -2564,8 +2593,9 @@ icon_view_handle_uri_list (NautilusIconContainer *container, const char *item_ur
(action != GDK_ACTION_COPY) &&
(action != GDK_ACTION_MOVE) &&
(action != GDK_ACTION_LINK)) {
- eel_show_warning_dialog (_("An invalid drag type was used."),
- _("Drag and Drop error"),
+ eel_show_warning_dialog (_("Drag and drop is not supported."),
+ _("An invalid drag type was used."),
+ _("Drag and Drop Error"),
fm_directory_view_get_containing_window (FM_DIRECTORY_VIEW (view)));
g_free (container_uri);
return;
@@ -2747,6 +2777,7 @@ fm_icon_view_class_init (FMIconViewClass *klass)
fm_directory_view_class->get_background_widget = fm_icon_view_get_background_widget;
fm_directory_view_class->get_selected_icon_locations = fm_icon_view_get_selected_icon_locations;
fm_directory_view_class->get_selection = fm_icon_view_get_selection;
+ fm_directory_view_class->get_item_count = fm_icon_view_get_item_count;
fm_directory_view_class->is_empty = fm_icon_view_is_empty;
fm_directory_view_class->remove_file = fm_icon_view_remove_file;
fm_directory_view_class->reset_to_defaults = fm_icon_view_reset_to_defaults;
diff --git a/src/file-manager/fm-list-model.c b/src/file-manager/fm-list-model.c
index ad3c746f9..48558537d 100644
--- a/src/file-manager/fm-list-model.c
+++ b/src/file-manager/fm-list-model.c
@@ -189,6 +189,7 @@ fm_list_model_get_value (GtkTreeModel *tree_model, GtkTreeIter *iter, int column
int icon_size;
NautilusZoomLevel zoom_level;
int width, height;
+ char *modifier;
model = (FMListModel *)tree_model;
@@ -220,7 +221,31 @@ fm_list_model_get_value (GtkTreeModel *tree_model, GtkTreeIter *iter, int column
zoom_level = fm_list_model_get_zoom_level_from_column_id (column);
icon_size = nautilus_get_icon_size_for_zoom_level (zoom_level);
- icon = nautilus_icon_factory_get_pixbuf_for_file (file, NULL, icon_size);
+
+ modifier = NULL;
+ if (model->details->drag_view != NULL) {
+ GtkTreePath *path_a, *path_b;
+
+ gtk_tree_view_get_drag_dest_row (model->details->drag_view,
+ &path_a,
+ NULL);
+ if (path_a != NULL) {
+ path_b = gtk_tree_model_get_path (tree_model, iter);
+
+ if (gtk_tree_path_compare (path_a, path_b) == 0) {
+ modifier = "visiting";
+ }
+
+ gtk_tree_path_free (path_a);
+ gtk_tree_path_free (path_b);
+ }
+ }
+
+ if (nautilus_file_has_open_window (file)) {
+ modifier = "accept";
+ }
+
+ icon = nautilus_icon_factory_get_pixbuf_for_file (file, modifier, icon_size);
height = gdk_pixbuf_get_height (icon);
if (height > icon_size) {
@@ -649,6 +674,13 @@ fm_list_model_is_empty (FMListModel *model)
return (g_sequence_get_length (model->details->files) == 0);
}
+guint
+fm_list_model_get_length (FMListModel *model)
+{
+ return g_sequence_get_length (model->details->files);
+}
+
+
static void
fm_list_model_remove (FMListModel *model, GtkTreeIter *iter)
{
@@ -691,6 +723,23 @@ fm_list_model_clear (FMListModel *model)
}
}
+NautilusFile *
+fm_list_model_file_for_path (FMListModel *model, GtkTreePath *path)
+{
+ NautilusFile *file;
+ GtkTreeIter iter;
+
+ file = NULL;
+ if (gtk_tree_model_get_iter (GTK_TREE_MODEL (model),
+ &iter, path)) {
+ gtk_tree_model_get (GTK_TREE_MODEL (model),
+ &iter,
+ FM_LIST_MODEL_FILE_COLUMN, &file,
+ -1);
+ }
+ return file;
+}
+
void
fm_list_model_set_should_sort_directories_first (FMListModel *model, gboolean sort_directories_first)
{
diff --git a/src/file-manager/fm-list-model.h b/src/file-manager/fm-list-model.h
index 7c6d846ef..dcf3b4c09 100644
--- a/src/file-manager/fm-list-model.h
+++ b/src/file-manager/fm-list-model.h
@@ -71,6 +71,7 @@ void fm_list_model_add_file (FMListModel *
void fm_list_model_file_changed (FMListModel *model,
NautilusFile *file);
gboolean fm_list_model_is_empty (FMListModel *model);
+guint fm_list_model_get_length (FMListModel *model);
void fm_list_model_remove_file (FMListModel *model,
NautilusFile *file);
void fm_list_model_clear (FMListModel *model);
diff --git a/src/file-manager/fm-list-view.c b/src/file-manager/fm-list-view.c
index fcfd774fb..6d0355646 100644
--- a/src/file-manager/fm-list-view.c
+++ b/src/file-manager/fm-list-view.c
@@ -80,6 +80,7 @@ struct FMListViewDetails {
int drag_y;
gboolean drag_started;
+ gboolean row_selected_on_button_down;
};
/*
@@ -161,11 +162,18 @@ activate_selected_items (FMListView *view)
}
static void
-activate_selected_items_alternate (FMListView *view)
+activate_selected_items_alternate (FMListView *view,
+ NautilusFile *file)
{
GList *file_list;
-
- file_list = fm_list_view_get_selection (FM_DIRECTORY_VIEW (view));
+
+
+ if (file != NULL) {
+ nautilus_file_ref (file);
+ file_list = g_list_prepend (NULL, file);
+ } else {
+ file_list = fm_list_view_get_selection (FM_DIRECTORY_VIEW (view));
+ }
fm_directory_view_activate_files (FM_DIRECTORY_VIEW (view),
file_list,
Nautilus_ViewFrame_OPEN_ACCORDING_TO_MODE,
@@ -193,12 +201,17 @@ fm_list_view_did_not_drag (FMListView *view,
if (gtk_tree_view_get_path_at_pos (tree_view, event->x, event->y,
&path, NULL, NULL, NULL)) {
- if((event->button == 1 || event->button == 2)
- && (click_policy_auto_value == NAUTILUS_CLICK_POLICY_DOUBLE)
- && gtk_tree_selection_path_is_selected (selection, path)
- && !button_event_modifies_selection (event)) {
- gtk_tree_selection_unselect_all (selection);
- gtk_tree_selection_select_path (selection, path);
+ if ((event->button == 1 || event->button == 2)
+ && ((event->state & GDK_CONTROL_MASK) != 0 ||
+ (event->state & GDK_SHIFT_MASK) == 0)
+ && view->details->row_selected_on_button_down
+ && (click_policy_auto_value == NAUTILUS_CLICK_POLICY_DOUBLE)) {
+ if (!button_event_modifies_selection (event)) {
+ gtk_tree_selection_unselect_all (selection);
+ gtk_tree_selection_select_path (selection, path);
+ } else {
+ gtk_tree_selection_unselect_path (selection, path);
+ }
}
if ((click_policy_auto_value == NAUTILUS_CLICK_POLICY_SINGLE)
@@ -206,7 +219,7 @@ fm_list_view_did_not_drag (FMListView *view,
if (event->button == 1) {
activate_selected_items (view);
} else if (event->button == 2) {
- activate_selected_items_alternate (view);
+ activate_selected_items_alternate (view, NULL);
}
}
gtk_tree_path_free (path);
@@ -436,6 +449,7 @@ button_press_callback (GtkWidget *widget, GdkEventButton *event, gpointer callba
return TRUE;
}
+
call_parent = TRUE;
allow_drag = FALSE;
if (gtk_tree_view_get_path_at_pos (tree_view, event->x, event->y,
@@ -448,15 +462,26 @@ button_press_callback (GtkWidget *widget, GdkEventButton *event, gpointer callba
view->details->double_click_path[1] = view->details->double_click_path[0];
view->details->double_click_path[0] = gtk_tree_path_copy (path);
}
-
if (event->type == GDK_2BUTTON_PRESS) {
+ /* Double clicking does not trigger a D&D action. */
+ view->details->drag_button = 0;
+ call_parent = TRUE;
if (view->details->double_click_path[1] &&
- gtk_tree_path_compare (view->details->double_click_path[0], view->details->double_click_path[1]) == 0
- && !button_event_modifies_selection (event)) {
- if ((event->button == 1 || event->button == 3)) {
- activate_selected_items (view);
- } else if (event->button == 2) {
- activate_selected_items_alternate (view);
+ gtk_tree_path_compare (view->details->double_click_path[0], view->details->double_click_path[1]) == 0) {
+ if (!button_event_modifies_selection (event)) {
+ if ((event->button == 1 || event->button == 3)) {
+ activate_selected_items (view);
+ } else if (event->button == 2) {
+ activate_selected_items_alternate (view, NULL);
+ }
+ } else if (event->button == 1 &&
+ (event->state & GDK_SHIFT_MASK) != 0) {
+ NautilusFile *file;
+ file = fm_list_model_file_for_path (view->details->model, path);
+ if (file != NULL) {
+ activate_selected_items_alternate (view, file);
+ nautilus_file_unref (file);
+ }
}
}
}
@@ -471,17 +496,26 @@ button_press_callback (GtkWidget *widget, GdkEventButton *event, gpointer callba
call_parent = FALSE;
}
- if(!button_event_modifies_selection (event) &&
- (event->button == 1 || event->button == 2) &&
- gtk_tree_selection_path_is_selected (selection, path)) {
- call_parent = FALSE;
+ if ((event->button == 1 || event->button == 2) &&
+ ((event->state & GDK_CONTROL_MASK) != 0 ||
+ (event->state & GDK_SHIFT_MASK) == 0)) {
+ view->details->row_selected_on_button_down = gtk_tree_selection_path_is_selected (selection, path);
+ if (view->details->row_selected_on_button_down) {
+ call_parent = FALSE;
+ } else if ((event->state & GDK_CONTROL_MASK) != 0) {
+ call_parent = FALSE;
+ gtk_tree_selection_select_path (selection, path);
+ }
}
if (call_parent) {
tree_view_class->button_press_event (widget, event);
+ } else if (gtk_tree_selection_path_is_selected (selection, path)) {
+ gtk_widget_grab_focus (widget);
}
- if (event->button == 1 || event->button == 2) {
+ if ((event->button == 1 || event->button == 2) &&
+ event->type == GDK_BUTTON_PRESS) {
view->details->drag_started = FALSE;
view->details->drag_button = event->button;
view->details->drag_x = event->x;
@@ -494,9 +528,21 @@ button_press_callback (GtkWidget *widget, GdkEventButton *event, gpointer callba
gtk_tree_path_free (path);
} else {
+ if ((event->button == 1 || event->button == 2) &&
+ event->type == GDK_BUTTON_PRESS) {
+ if (view->details->double_click_path[1]) {
+ gtk_tree_path_free (view->details->double_click_path[1]);
+ }
+ view->details->double_click_path[1] = view->details->double_click_path[0];
+ view->details->double_click_path[0] = NULL;
+ }
/* Deselect if people click outside any row. It's OK to
let default code run; it won't reselect anything. */
gtk_tree_selection_unselect_all (gtk_tree_view_get_selection (tree_view));
+
+ if (event->button == 3) {
+ do_popup_menu (widget, view, event);
+ }
}
/* We chained to the default handler in this method, so never
@@ -701,6 +747,7 @@ create_and_set_up_tree_view (FMListView *view)
GtkCellRenderer *cell;
GtkTreeViewColumn *column;
GtkTargetEntry *drag_types;
+ AtkObject *atk_obj;
int num_drag_types;
view->details->tree_view = GTK_TREE_VIEW (gtk_tree_view_new ());
@@ -742,6 +789,9 @@ create_and_set_up_tree_view (FMListView *view)
view->details->model = g_object_new (FM_TYPE_LIST_MODEL, NULL);
gtk_tree_view_set_model (view->details->tree_view, GTK_TREE_MODEL (view->details->model));
+ /* Need the model for the dnd drop icon "accept" change */
+ fm_list_model_set_drag_view (FM_LIST_MODEL (view->details->model),
+ view->details->tree_view, 0, 0);
g_signal_connect_object (view->details->model, "sort_column_changed",
G_CALLBACK (sort_column_changed_callback), view, 0);
@@ -815,6 +865,9 @@ create_and_set_up_tree_view (FMListView *view)
gtk_widget_show (GTK_WIDGET (view->details->tree_view));
gtk_container_add (GTK_CONTAINER (view), GTK_WIDGET (view->details->tree_view));
+
+ atk_obj = gtk_widget_get_accessible (GTK_WIDGET (view->details->tree_view));
+ atk_object_set_name (atk_obj, _("List View"));
}
static void
@@ -964,6 +1017,15 @@ fm_list_view_get_selection (FMDirectoryView *view)
return list;
}
+
+static guint
+fm_list_view_get_item_count (FMDirectoryView *view)
+{
+ g_return_val_if_fail (FM_IS_LIST_VIEW (view), 0);
+
+ return fm_list_model_get_length (FM_LIST_VIEW (view)->details->model);
+}
+
static gboolean
fm_list_view_is_empty (FMDirectoryView *view)
{
@@ -973,7 +1035,52 @@ fm_list_view_is_empty (FMDirectoryView *view)
static void
fm_list_view_remove_file (FMDirectoryView *view, NautilusFile *file)
{
- fm_list_model_remove_file (FM_LIST_VIEW (view)->details->model, file);
+ GtkTreePath *path;
+ GtkTreeIter iter;
+ GtkTreeIter temp_iter;
+ GtkTreeRowReference* row_reference;
+ FMListView *list_view;
+ GtkTreeModel* tree_model;
+
+ path = NULL;
+ row_reference = NULL;
+ list_view = FM_LIST_VIEW (view);
+ tree_model = GTK_TREE_MODEL(list_view->details->model);
+
+ if(fm_list_model_get_tree_iter_from_file (list_view->details->model, file, &iter)) {
+ temp_iter = iter;
+
+ /* get reference for next element in the list view. If the element to be deleted is the
+ * last one, get reference to previous element. If there is only one element in view
+ * no need to select anything. */
+
+ if(gtk_tree_model_iter_next (tree_model, &iter)) {
+ path = gtk_tree_model_get_path (tree_model, &iter);
+ row_reference = gtk_tree_row_reference_new (tree_model, path);
+ } else {
+ path = gtk_tree_model_get_path (tree_model, &temp_iter);
+ if(gtk_tree_path_prev (path)) {
+ row_reference = gtk_tree_row_reference_new (tree_model, path);
+ }
+ }
+
+ gtk_tree_path_free (path);
+
+ fm_list_model_remove_file (list_view->details->model, file);
+
+ if(gtk_tree_row_reference_valid(row_reference)) {
+ path = gtk_tree_row_reference_get_path (row_reference);
+ gtk_tree_view_set_cursor (list_view->details->tree_view, path, NULL, FALSE);
+ gtk_tree_path_free (path);
+
+ }
+
+ if(row_reference) {
+ gtk_tree_row_reference_free (row_reference);
+ }
+ }
+
+
}
static void
@@ -1432,6 +1539,7 @@ fm_list_view_class_init (FMListViewClass *class)
fm_directory_view_class->file_changed = fm_list_view_file_changed;
fm_directory_view_class->get_background_widget = fm_list_view_get_background_widget;
fm_directory_view_class->get_selection = fm_list_view_get_selection;
+ fm_directory_view_class->get_item_count = fm_list_view_get_item_count;
fm_directory_view_class->is_empty = fm_list_view_is_empty;
fm_directory_view_class->remove_file = fm_list_view_remove_file;
fm_directory_view_class->reset_to_defaults = fm_list_view_reset_to_defaults;
diff --git a/src/file-manager/fm-properties-window.c b/src/file-manager/fm-properties-window.c
index 55464fcd2..7af9e5b7c 100644
--- a/src/file-manager/fm-properties-window.c
+++ b/src/file-manager/fm-properties-window.c
@@ -26,6 +26,7 @@
#include "fm-properties-window.h"
#include "fm-error-reporting.h"
+#include <eel/eel-accessibility.h>
#include <eel/eel-ellipsizing-label.h>
#include <eel/eel-gdk-pixbuf-extensions.h>
#include <eel/eel-glib-extensions.h>
@@ -152,7 +153,7 @@ enum {
typedef struct {
GList *original_files;
GList *target_files;
- FMDirectoryView *directory_view;
+ GtkWidget *parent_widget;
char *pending_key;
GHashTable *pending_files;
} StartupData;
@@ -186,7 +187,7 @@ static void is_directory_ready_callback (NautilusFile *file,
gpointer data);
static void cancel_group_change_callback (gpointer callback_data);
static void cancel_owner_change_callback (gpointer callback_data);
-static void directory_view_destroyed_callback (FMDirectoryView *view,
+static void parent_widget_destroyed_callback (GtkWidget *widget,
gpointer callback_data);
static void select_image_button_callback (GtkWidget *widget,
FMPropertiesWindow *properties_window);
@@ -473,8 +474,8 @@ fm_properties_window_drag_data_received (GtkWidget *widget, GdkDragContext *cont
if (!exactly_one) {
eel_show_error_dialog
- (_("You can't assign more than one custom icon at a time! "
- "Please drag just one image to set a custom icon."),
+ (_("You can't assign more than one custom icon at a time!"),
+ _("Please drag just one image to set a custom icon."),
_("More Than One Image"),
window);
} else {
@@ -484,15 +485,15 @@ fm_properties_window_drag_data_received (GtkWidget *widget, GdkDragContext *cont
} else {
if (eel_is_remote_uri (uris[0])) {
eel_show_error_dialog
- (_("The file that you dropped is not local. "
- "You can only use local images as custom icons."),
+ (_("The file that you dropped is not local."),
+ _("You can only use local images as custom icons."),
_("Local Images Only"),
window);
} else {
eel_show_error_dialog
- (_("The file that you dropped is not an image. "
- "You can only use local images as custom icons."),
+ (_("The file that you dropped is not an image."),
+ _("You can only use local images as custom icons."),
_("Images Only"),
window);
}
@@ -1375,7 +1376,7 @@ activate_group_callback (GtkMenuItem *menu_item, FileNamePair *pair)
(cancel_group_change_callback,
pair->file,
_("Cancel Group Change?"),
- _("Changing group"),
+ _("Changing group."),
NULL); /* FIXME bugzilla.gnome.org 42397: Parent this? */
nautilus_file_set_group
(pair->file, pair->name,
@@ -1537,7 +1538,7 @@ activate_owner_callback (GtkMenuItem *menu_item, FileNamePair *pair)
(cancel_owner_change_callback,
pair->file,
_("Cancel Owner Change?"),
- _("Changing owner"),
+ _("Changing owner."),
NULL); /* FIXME bugzilla.gnome.org 42397: Parent this? */
nautilus_file_set_owner
(pair->file, pair->name,
@@ -2667,10 +2668,12 @@ static void
add_permissions_checkbox (FMPropertiesWindow *window,
GtkTable *table,
int row, int column,
- GnomeVFSFilePermissions permission_to_check)
+ GnomeVFSFilePermissions permission_to_check,
+ GtkLabel *label_for)
{
GtkWidget *check_button;
gchar *label;
+ gboolean a11y_enabled;
if (column == PERMISSIONS_CHECKBOXES_READ_COLUMN) {
label = _("_Read");
@@ -2691,6 +2694,12 @@ add_permissions_checkbox (FMPropertiesWindow *window,
set_up_permissions_checkbox (window,
check_button,
permission_to_check);
+
+ a11y_enabled = GTK_IS_ACCESSIBLE (gtk_widget_get_accessible (check_button));
+ if (a11y_enabled) {
+ eel_accessibility_set_up_label_widget_relation (GTK_WIDGET (label_for),
+ check_button);
+ }
}
static GtkWidget *
@@ -2845,6 +2854,9 @@ create_permissions_page (FMPropertiesWindow *window)
guint checkbox_titles_row;
GtkLabel *group_label;
GtkLabel *owner_label;
+ GtkLabel *owner_perm_label;
+ GtkLabel *group_perm_label;
+ GtkLabel *other_perm_label;
GtkOptionMenu *group_menu;
GtkOptionMenu *owner_menu;
GList *file_list;
@@ -2877,7 +2889,7 @@ create_permissions_page (FMPropertiesWindow *window)
owner_label = attach_title_field (page_table, last_row, _("File _owner:"));
/* Option menu in this case. */
owner_menu = attach_owner_menu (page_table, last_row, get_target_file (window));
- gtk_label_set_mnemonic_widget (GTK_LABEL (owner_label),
+ gtk_label_set_mnemonic_widget (owner_label,
GTK_WIDGET (owner_menu));
} else {
attach_title_field (page_table, last_row, _("File owner:"));
@@ -2896,7 +2908,7 @@ create_permissions_page (FMPropertiesWindow *window)
/* Option menu in this case. */
group_menu = attach_group_menu (page_table, last_row,
get_target_file (window));
- gtk_label_set_mnemonic_widget (GTK_LABEL (group_label),
+ gtk_label_set_mnemonic_widget (group_label,
GTK_WIDGET (group_menu));
} else {
last_row = append_title_field (page_table,
@@ -2912,9 +2924,9 @@ create_permissions_page (FMPropertiesWindow *window)
append_separator (page_table);
- checkbox_titles_row = append_title_field (page_table, _("Owner:"), NULL);
- append_title_field (page_table, _("Group:"), NULL);
- append_title_field (page_table, _("Others:"), NULL);
+ checkbox_titles_row = append_title_field (page_table, _("Owner:"), &owner_perm_label);
+ append_title_field (page_table, _("Group:"), &group_perm_label);
+ append_title_field (page_table, _("Others:"), &other_perm_label);
check_button_table = GTK_TABLE (gtk_table_new
(PERMISSIONS_CHECKBOXES_ROW_COUNT,
@@ -2932,55 +2944,64 @@ create_permissions_page (FMPropertiesWindow *window)
check_button_table,
PERMISSIONS_CHECKBOXES_OWNER_ROW,
PERMISSIONS_CHECKBOXES_READ_COLUMN,
- GNOME_VFS_PERM_USER_READ);
+ GNOME_VFS_PERM_USER_READ,
+ owner_perm_label);
add_permissions_checkbox (window,
check_button_table,
PERMISSIONS_CHECKBOXES_OWNER_ROW,
PERMISSIONS_CHECKBOXES_WRITE_COLUMN,
- GNOME_VFS_PERM_USER_WRITE);
+ GNOME_VFS_PERM_USER_WRITE,
+ owner_perm_label);
add_permissions_checkbox (window,
check_button_table,
PERMISSIONS_CHECKBOXES_OWNER_ROW,
PERMISSIONS_CHECKBOXES_EXECUTE_COLUMN,
- GNOME_VFS_PERM_USER_EXEC);
+ GNOME_VFS_PERM_USER_EXEC,
+ owner_perm_label);
add_permissions_checkbox (window,
check_button_table,
PERMISSIONS_CHECKBOXES_GROUP_ROW,
PERMISSIONS_CHECKBOXES_READ_COLUMN,
- GNOME_VFS_PERM_GROUP_READ);
+ GNOME_VFS_PERM_GROUP_READ,
+ group_perm_label);
add_permissions_checkbox (window,
check_button_table,
PERMISSIONS_CHECKBOXES_GROUP_ROW,
PERMISSIONS_CHECKBOXES_WRITE_COLUMN,
- GNOME_VFS_PERM_GROUP_WRITE);
+ GNOME_VFS_PERM_GROUP_WRITE,
+ group_perm_label);
add_permissions_checkbox (window,
check_button_table,
PERMISSIONS_CHECKBOXES_GROUP_ROW,
PERMISSIONS_CHECKBOXES_EXECUTE_COLUMN,
- GNOME_VFS_PERM_GROUP_EXEC);
+ GNOME_VFS_PERM_GROUP_EXEC,
+ group_perm_label);
add_permissions_checkbox (window,
check_button_table,
PERMISSIONS_CHECKBOXES_OTHERS_ROW,
PERMISSIONS_CHECKBOXES_READ_COLUMN,
- GNOME_VFS_PERM_OTHER_READ);
+ GNOME_VFS_PERM_OTHER_READ,
+ other_perm_label);
add_permissions_checkbox (window,
check_button_table,
PERMISSIONS_CHECKBOXES_OTHERS_ROW,
PERMISSIONS_CHECKBOXES_WRITE_COLUMN,
- GNOME_VFS_PERM_OTHER_WRITE);
+ GNOME_VFS_PERM_OTHER_WRITE,
+ other_perm_label);
add_permissions_checkbox (window,
check_button_table,
PERMISSIONS_CHECKBOXES_OTHERS_ROW,
PERMISSIONS_CHECKBOXES_EXECUTE_COLUMN,
- GNOME_VFS_PERM_OTHER_EXEC);
+ GNOME_VFS_PERM_OTHER_EXEC,
+ other_perm_label);
append_separator (page_table);
@@ -3115,7 +3136,7 @@ static StartupData *
startup_data_new (GList *original_files,
GList *target_files,
const char *pending_key,
- FMDirectoryView *directory_view)
+ GtkWidget *parent_widget)
{
StartupData *data;
GList *l;
@@ -3123,7 +3144,7 @@ startup_data_new (GList *original_files,
data = g_new0 (StartupData, 1);
data->original_files = nautilus_file_list_copy (original_files);
data->target_files = nautilus_file_list_copy (target_files);
- data->directory_view = directory_view;
+ data->parent_widget = parent_widget;
data->pending_key = g_strdup (pending_key);
data->pending_files = g_hash_table_new (g_direct_hash,
g_direct_equal);
@@ -3149,19 +3170,15 @@ static void
help_button_callback (GtkWidget *widget, GtkWidget *property_window)
{
GError *error = NULL;
- char *message;
egg_help_display_desktop_on_screen (NULL, "user-guide", "wgosnautilus.xml", "gosnautilus-51",
gtk_window_get_screen (GTK_WINDOW (property_window)),
&error);
if (error) {
- message = g_strdup_printf (_("There was an error displaying help: \n%s"),
- error->message);
- eel_show_error_dialog (message, _("Couldn't show help"),
+ eel_show_error_dialog (_("There was an error displaying help."), error->message, _("Couldn't Show Help"),
GTK_WINDOW (property_window));
g_error_free (error);
- g_free (message);
}
}
@@ -3183,7 +3200,7 @@ create_properties_window (StartupData *startup_data)
gtk_window_set_wmclass (GTK_WINDOW (window), "file_properties", "Nautilus");
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
gtk_window_set_screen (GTK_WINDOW (window),
- gtk_widget_get_screen (GTK_WIDGET (startup_data->directory_view)));
+ gtk_widget_get_screen (startup_data->parent_widget));
/* Set initial window title */
update_properties_window_title (window);
@@ -3354,9 +3371,9 @@ cancel_create_properties_window_callback (gpointer callback_data)
}
static void
-directory_view_destroyed_callback (FMDirectoryView *view, gpointer callback_data)
+parent_widget_destroyed_callback (GtkWidget *widget, gpointer callback_data)
{
- g_assert (view == ((StartupData *)callback_data)->directory_view);
+ g_assert (widget == ((StartupData *)callback_data)->parent_widget);
remove_pending ((StartupData *)callback_data, TRUE, TRUE, FALSE);
}
@@ -3389,8 +3406,8 @@ remove_pending (StartupData *startup_data,
(cancel_create_properties_window_callback, startup_data);
}
if (cancel_destroy_handler) {
- g_signal_handlers_disconnect_by_func (startup_data->directory_view,
- G_CALLBACK (directory_view_destroyed_callback),
+ g_signal_handlers_disconnect_by_func (startup_data->parent_widget,
+ G_CALLBACK (parent_widget_destroyed_callback),
startup_data);
}
@@ -3432,7 +3449,7 @@ is_directory_ready_callback (NautilusFile *file,
void
fm_properties_window_present (GList *original_files,
- FMDirectoryView *directory_view)
+ GtkWidget *parent_widget)
{
GList *l, *next;
GtkWidget *parent_window;
@@ -3442,7 +3459,7 @@ fm_properties_window_present (GList *original_files,
char *pending_key;
g_return_if_fail (original_files != NULL);
- g_return_if_fail (FM_IS_DIRECTORY_VIEW (directory_view));
+ g_return_if_fail (GTK_IS_WIDGET (parent_widget));
/* Create the hash tables first time through. */
if (windows == NULL) {
@@ -3459,7 +3476,7 @@ fm_properties_window_present (GList *original_files,
existing_window = get_existing_window (original_files);
if (existing_window != NULL) {
gtk_window_set_screen (existing_window,
- gtk_widget_get_screen (GTK_WIDGET (directory_view)));
+ gtk_widget_get_screen (parent_widget));
gtk_window_present (existing_window);
return;
}
@@ -3477,7 +3494,7 @@ fm_properties_window_present (GList *original_files,
startup_data = startup_data_new (original_files,
target_files,
pending_key,
- directory_view);
+ parent_widget);
nautilus_file_list_free (target_files);
g_free(pending_key);
@@ -3487,16 +3504,16 @@ fm_properties_window_present (GList *original_files,
*/
g_hash_table_insert (pending_lists, startup_data->pending_key, startup_data->pending_key);
- g_signal_connect (directory_view, "destroy",
- G_CALLBACK (directory_view_destroyed_callback), startup_data);
+ g_signal_connect (parent_widget, "destroy",
+ G_CALLBACK (parent_widget_destroyed_callback), startup_data);
- parent_window = gtk_widget_get_ancestor (GTK_WIDGET (directory_view), GTK_TYPE_WINDOW);
+ parent_window = gtk_widget_get_ancestor (parent_widget, GTK_TYPE_WINDOW);
eel_timed_wait_start
(cancel_create_properties_window_callback,
startup_data,
_("Cancel Showing Properties Window?"),
- _("Creating Properties window"),
+ _("Creating Properties window."),
parent_window == NULL ? NULL : GTK_WINDOW (parent_window));
diff --git a/src/file-manager/fm-properties-window.h b/src/file-manager/fm-properties-window.h
index 32d59d99a..b05c3b729 100644
--- a/src/file-manager/fm-properties-window.h
+++ b/src/file-manager/fm-properties-window.h
@@ -26,10 +26,9 @@
#ifndef FM_PROPERTIES_WINDOW_H
#define FM_PROPERTIES_WINDOW_H
-#include "fm-directory-view.h"
-
#include <gtk/gtkwindow.h>
#include <libnautilus-private/nautilus-file.h>
+#include <libnautilus/nautilus-view.h>
typedef struct FMPropertiesWindow FMPropertiesWindow;
@@ -60,6 +59,6 @@ typedef struct FMPropertiesWindowClass FMPropertiesWindowClass;
GType fm_properties_window_get_type (void);
void fm_properties_window_present (GList *files,
- FMDirectoryView *directory_view);
+ GtkWidget *parent_widget);
#endif /* FM_PROPERTIES_WINDOW_H */
diff --git a/src/file-manager/fm-search-list-view.c b/src/file-manager/fm-search-list-view.c
index 682daa757..8b43400fc 100644
--- a/src/file-manager/fm-search-list-view.c
+++ b/src/file-manager/fm-search-list-view.c
@@ -163,8 +163,9 @@ load_location_callback (NautilusView *nautilus_view, char *location)
}
}
#else
- eel_show_error_dialog (_("Sorry, but the Medusa search service is not available because it is not installed."),
- _("Search Service Not Available"),
+ eel_show_error_dialog (_("Sorry, but the Medusa search service is not available."),
+ _("Medusa is not installed."),
+ _("Search Service Not Available"),
NULL);
#endif
@@ -179,7 +180,6 @@ real_load_error (FMDirectoryView *nautilus_view,
GnomeVFSResult result)
{
GtkDialog *load_error_dialog;
- char *error_string;
/* Do not call parent's function; we handle all search errors
* here and don't want fm-directory-view's default handling.
@@ -190,42 +190,38 @@ real_load_error (FMDirectoryView *nautilus_view,
load_error_dialog = eel_show_info_dialog (_("The search you have selected "
"is newer than the index on your "
"system. The search will return "
- "no results right now. You can create a new "
- " index by running \"medusa-indexd\" as root "
+ "no results right now."),
+ _("You can create a new "
+ "index by running \"medusa-indexd\" as root "
"on the command line."),
- _("Search for items that are too new"),
+ _("Search For Items That Are Too New"),
NULL);
break;
case GNOME_VFS_ERROR_TOO_BIG:
eel_show_error_dialog (_("Every indexed file on your computer "
- "matches the criteria you selected. "
- "You can check the spelling on your selections "
+ "matches the criteria you selected. "),
+ _("You can check the spelling on your selections "
"or add more criteria to narrow your results."),
- _("Error during search"),
+ _("Error During Search"),
NULL);
break;
case GNOME_VFS_ERROR_SERVICE_NOT_AVAILABLE:
/* FIXME: This dialog does not get shown because a slow search
will be performed and will not return an error. */
eel_show_error_dialog (_("Find cannot open your file system index. "
- "Your index may be missing or corrupt. You can "
- "create a new index by running \"medusa-indexd\" as root "
+ "Your index may be missing or corrupt."),
+ _("You can create a new index by running \"medusa-indexd\" as root "
"on the command line."),
- _("Error reading file index"),
+ _("Error Reading File Index"),
NULL);
break;
case GNOME_VFS_ERROR_CANCELLED:
break;
default:
- error_string = g_strdup_printf (_("An error occurred while loading "
- "this search's contents: "
- "%s"),
- gnome_vfs_result_to_string (result));
- eel_show_error_dialog (error_string,
- _("Error during search"),
- NULL);
- g_free (error_string);
-
+ eel_show_error_dialog (_("An error occurred while loading this search's contents."),
+ gnome_vfs_result_to_string (result),
+ _("Error During Search"),
+ NULL);
}
}
@@ -234,7 +230,7 @@ real_load_error (FMDirectoryView *nautilus_view,
static void
display_indexed_search_problems_dialog (gboolean backup_search_is_available)
{
- const char *error_string, *title_string;
+ const char *error_string, *detail_string, *title_string;
if (medusa_indexed_search_system_index_files_look_available ()) {
/* There is an index on the system, but there is no
@@ -242,17 +238,19 @@ display_indexed_search_problems_dialog (gboolean backup_search_is_available)
confused. Tell the user this. */
error_string = backup_search_is_available
? N_("To do a fast search, Find requires an index "
- "of the files on your system. "
- "Find can't access your index right now "
+ "of the files on your system.")
+ : N_("To do a content search, Find requires an index "
+ "of the files on your system.");
+ detail_string = backup_search_is_available
+ ? N_("Find can't access your index right now "
"so a slower search will be performed that "
"doesn't use the index.")
- : N_("To do a content search, Find requires an index "
- "of the files on your system. "
- "Find can't access your index right now. ");
+ : N_("Find can't access your index right now.");
title_string = backup_search_is_available
- ? N_("Fast searches are not available")
- : N_("Content searches are not available");
+ ? N_("Fast Searches Are Not Available")
+ : N_("Content Searches Are Not Available");
eel_show_error_dialog_with_details (error_string,
+ detail_string,
title_string,
_("Your index files are available "
"but the Medusa search daemon, which handles "
@@ -270,19 +268,23 @@ display_indexed_search_problems_dialog (gboolean backup_search_is_available)
error_string = backup_search_is_available
? N_("To do a fast search, Find requires an index "
"of the files on your system. "
- "Your computer is currently creating that "
- "index. Because Find cannot use an index, "
- "this search may take several "
- "minutes.")
+ "Your computer is currently creating that "
+ "index.")
: N_("To do a content search, Find requires an index "
"of the content on your system. "
"Your computer is currently creating that "
- "index. Content searches will be available "
+ "index.");
+ detail_string = backup_search_is_available
+ ? N_("Because Find cannot use an index, "
+ "this search may take several "
+ "minutes.")
+ : N_("Content searches will be available "
"when the index is complete.");
title_string = backup_search_is_available
- ? N_("Indexed searches are not available")
- : N_("Content searches are not available");
+ ? N_("Indexed Searches Are Not Available")
+ : N_("Content Searches Are Not Available");
eel_show_error_dialog (error_string,
+ detail_string,
title_string,
NULL);
}
@@ -290,22 +292,26 @@ display_indexed_search_problems_dialog (gboolean backup_search_is_available)
error_string = backup_search_is_available
? N_("To do a fast search, Find requires an index "
"of the files on your system. No index "
- "is available right now. You can create an "
+ "is available right now.")
+ : N_("To do a content search, Find requires an index "
+ "of the content on your system. No index is "
+ "available right now.");
+ detail_string = backup_search_is_available
+ ? N_("You can create an "
"index by running \"medusa-indexd\" as root "
"on the command line. Until a complete index "
"is available, searches will "
"take several minutes.")
- : N_("To do a content search, Find requires an index "
- "of the content on your system. No index is "
- "available right now. You can create an "
+ : N_("You can create an "
"index by running \"medusa-indexd\" as root "
"on the command line. Until a complete index "
"is available, content searches cannot be "
"performed.");
title_string = backup_search_is_available
- ? N_("Indexed searches are not available")
- : N_("Content searches are not available");
+ ? N_("Indexed Searches Are Not Available")
+ : N_("Content Searches Are Not Available");
eel_show_error_dialog (error_string,
+ detail_string,
title_string,
NULL);
}
@@ -320,11 +326,12 @@ display_system_services_are_disabled_dialog (gboolean unindexed_search_is_availa
char *details_string;
details_string = nautilus_medusa_get_explanation_of_enabling ();
- dialog_shown = eel_show_info_dialog_with_details (_("To do a fast search, Find requires an index of "
+ dialog_shown = eel_show_info_dialog_with_details (_("Fast searches are not enabled on your computer."),
+ _("To do a fast search, Find requires an index of "
"the files on your system. Your system administrator "
"has disabled fast search on your computer, so no index "
"is available."),
- _("Fast searches are not enabled on your computer"),
+ _("Fast Searches Not Enabled"),
details_string,
NULL);
g_free (details_string);
@@ -681,8 +688,8 @@ real_file_limit_reached (FMDirectoryView *view)
* to the way files are collected in batches. So you can't assume that
* no more than the constant limit are displayed.
*/
- eel_show_warning_dialog (_("Nautilus found more search results than it can display. "
- "Some matching items will not be displayed. "),
+ eel_show_warning_dialog (_("Nautilus found more search results than it can display."),
+ _("Some matching items will not be displayed. "),
_("Too Many Matches"),
fm_directory_view_get_containing_window (view));
}
diff --git a/src/file-manager/fm-tree-model.c b/src/file-manager/fm-tree-model.c
new file mode 100644
index 000000000..bcee8867a
--- /dev/null
+++ b/src/file-manager/fm-tree-model.c
@@ -0,0 +1,1797 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+
+/*
+ * Copyright C) 2000, 2001 Eazel, Inc
+ * Copyright (C) 2002 Anders Carlsson
+ * Copyright (C) 2002 Bent Spoon Software
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors: Anders Carlsson <andersca@gnu.org>
+ * Darin Adler <darin@bentspoon.com>
+ */
+
+/* fm-tree-model.c - model for the tree view */
+
+#include <config.h>
+#include "fm-tree-model.h"
+
+#include <eel/eel-glib-extensions.h>
+#include <libgnome/gnome-i18n.h>
+#include <libnautilus-private/nautilus-directory.h>
+#include <libnautilus-private/nautilus-file-attributes.h>
+#include <libnautilus-private/nautilus-file.h>
+#include <libnautilus-private/nautilus-icon-factory.h>
+#include <string.h>
+
+enum {
+ ROW_LOADED,
+ LAST_SIGNAL
+};
+
+static guint tree_model_signals[LAST_SIGNAL] = { 0 };
+
+typedef gboolean (* FilePredicate) (NautilusFile *);
+
+/* The user_data of the GtkTreeIter is the TreeNode pointer.
+ * It's NULL for the dummy node. If it's NULL, then user_data2
+ * is the TreeNode pointer to the parent.
+ */
+
+typedef struct TreeNode TreeNode;
+typedef struct FMTreeModelRoot FMTreeModelRoot;
+
+struct TreeNode {
+ /* part of this node for the file itself */
+ int ref_count;
+
+ NautilusFile *file;
+ char *display_name;
+ char *icon_name;
+ GdkPixbuf *closed_pixbuf;
+ GdkPixbuf *open_pixbuf;
+
+ FMTreeModelRoot *root;
+
+ TreeNode *parent;
+ TreeNode *next;
+ TreeNode *prev;
+
+ /* part of the node used only for directories */
+ int dummy_child_ref_count;
+ int all_children_ref_count;
+
+ NautilusDirectory *directory;
+ guint done_loading_id;
+ guint files_added_id;
+ guint files_changed_id;
+
+ TreeNode *first_child;
+
+ /* misc. flags */
+ guint done_loading : 1;
+ guint inserting_first_child : 1;
+ guint inserted : 1;
+};
+
+struct FMTreeModelDetails {
+ int stamp;
+
+ TreeNode *root_node;
+
+ guint monitoring_update_idle_id;
+
+ gboolean show_hidden_files;
+ gboolean show_backup_files;
+ gboolean show_only_directories;
+};
+
+struct FMTreeModelRoot {
+ FMTreeModel *model;
+
+ /* separate hash table for each root node needed */
+ GHashTable *file_to_node_map;
+
+ TreeNode *root_node;
+
+ gulong changed_handler_id;
+};
+
+typedef struct {
+ NautilusDirectory *directory;
+ FMTreeModel *model;
+} DoneLoadingParameters;
+
+static GObjectClass *parent_class;
+
+static void schedule_monitoring_update (FMTreeModel *model);
+static void destroy_node_without_reporting (FMTreeModel *model,
+ TreeNode *node);
+static void report_node_contents_changed (FMTreeModel *model,
+ TreeNode *node);
+
+static guint
+fm_tree_model_get_flags (GtkTreeModel *tree_model)
+{
+ return GTK_TREE_MODEL_ITERS_PERSIST;
+}
+
+static void
+object_unref_if_not_NULL (gpointer object)
+{
+ if (object == NULL) {
+ return;
+ }
+ g_object_unref (object);
+}
+
+static FMTreeModelRoot *
+tree_model_root_new (FMTreeModel *model)
+{
+ FMTreeModelRoot *root;
+
+ root = g_new0 (FMTreeModelRoot, 1);
+ root->model = model;
+ root->file_to_node_map = g_hash_table_new (NULL, NULL);
+
+ return root;
+}
+
+static TreeNode *
+tree_node_new (NautilusFile *file, FMTreeModelRoot *root)
+{
+ TreeNode *node;
+
+ node = g_new0 (TreeNode, 1);
+ node->file = nautilus_file_ref (file);
+ node->root = root;
+ return node;
+}
+
+static void
+tree_node_unparent (FMTreeModel *model, TreeNode *node)
+{
+ TreeNode *parent, *next, *prev;
+
+ parent = node->parent;
+ next = node->next;
+ prev = node->prev;
+
+ if (parent == NULL &&
+ node == model->details->root_node) {
+ /* it's the first root node -> if there is a next then let it be the first root node */
+ model->details->root_node = next;
+ }
+
+ if (next != NULL) {
+ next->prev = prev;
+ }
+ if (prev == NULL && parent != NULL) {
+ g_assert (parent->first_child == node);
+ parent->first_child = next;
+ } else if (prev != NULL) {
+ prev->next = next;
+ }
+
+ node->parent = NULL;
+ node->next = NULL;
+ node->prev = NULL;
+ node->root = NULL;
+}
+
+static void
+tree_node_destroy (FMTreeModel *model, TreeNode *node)
+{
+ g_assert (node->first_child == NULL);
+ g_assert (node->ref_count == 0);
+
+ tree_node_unparent (model, node);
+
+ g_object_unref (node->file);
+ g_free (node->display_name);
+ g_free (node->icon_name);
+ object_unref_if_not_NULL (node->closed_pixbuf);
+ object_unref_if_not_NULL (node->open_pixbuf);
+
+ g_assert (node->done_loading_id == 0);
+ g_assert (node->files_added_id == 0);
+ g_assert (node->files_changed_id == 0);
+ object_unref_if_not_NULL (node->directory);
+
+ g_free (node);
+}
+
+static void
+tree_node_parent (TreeNode *node, TreeNode *parent)
+{
+ TreeNode *first_child;
+
+ g_assert (parent != NULL);
+ g_assert (node->parent == NULL);
+ g_assert (node->prev == NULL);
+ g_assert (node->next == NULL);
+
+ first_child = parent->first_child;
+
+ node->parent = parent;
+ node->root = parent->root;
+ node->next = first_child;
+
+ if (first_child != NULL) {
+ g_assert (first_child->prev == NULL);
+ first_child->prev = node;
+ }
+
+ parent->first_child = node;
+}
+
+static GdkPixbuf *
+tree_node_get_pixbuf_from_factory (TreeNode *node,
+ const char *modifier)
+{
+ if (node->parent == NULL) {
+ return nautilus_icon_factory_get_pixbuf_from_name
+ (node->icon_name, NULL,
+ NAUTILUS_ICON_SIZE_FOR_MENUS, NULL);
+ }
+ return nautilus_icon_factory_get_pixbuf_for_file
+ (node->file, modifier, NAUTILUS_ICON_SIZE_FOR_MENUS);
+}
+
+static gboolean
+tree_node_update_pixbuf (TreeNode *node,
+ GdkPixbuf **pixbuf_storage,
+ const char *modifier)
+{
+ GdkPixbuf *pixbuf;
+
+ if (*pixbuf_storage == NULL) {
+ return FALSE;
+ }
+ pixbuf = tree_node_get_pixbuf_from_factory (node, modifier);
+ if (pixbuf == *pixbuf_storage) {
+ g_object_unref (pixbuf);
+ return FALSE;
+ }
+ g_object_unref (*pixbuf_storage);
+ *pixbuf_storage = pixbuf;
+ return TRUE;
+}
+
+static gboolean
+tree_node_update_closed_pixbuf (TreeNode *node)
+{
+ return tree_node_update_pixbuf (node, &node->closed_pixbuf, NULL);
+}
+
+static gboolean
+tree_node_update_open_pixbuf (TreeNode *node)
+{
+ return tree_node_update_pixbuf (node, &node->open_pixbuf, "accept");
+}
+
+static gboolean
+tree_node_update_display_name (TreeNode *node)
+{
+ char *display_name;
+
+ if (node->display_name == NULL) {
+ return FALSE;
+ }
+ /* don't update root node display names */
+ if (node->parent == NULL) {
+ return FALSE;
+ }
+ display_name = nautilus_file_get_display_name (node->file);
+ if (strcmp (display_name, node->display_name) == 0) {
+ g_free (display_name);
+ return FALSE;
+ }
+ g_free (node->display_name);
+ node->display_name = NULL;
+ return TRUE;
+}
+
+static GdkPixbuf *
+tree_node_get_closed_pixbuf (TreeNode *node)
+{
+ if (node->closed_pixbuf == NULL) {
+ node->closed_pixbuf = tree_node_get_pixbuf_from_factory (node, NULL);
+ }
+ return node->closed_pixbuf;
+}
+
+static GdkPixbuf *
+tree_node_get_open_pixbuf (TreeNode *node)
+{
+ if (node->open_pixbuf == NULL) {
+ node->open_pixbuf = tree_node_get_pixbuf_from_factory (node, "accept");
+ }
+ return node->open_pixbuf;
+}
+
+static const char *
+tree_node_get_display_name (TreeNode *node)
+{
+ if (node->display_name == NULL) {
+ node->display_name = nautilus_file_get_display_name (node->file);
+ }
+ return node->display_name;
+}
+
+static gboolean
+tree_node_has_dummy_child (TreeNode *node)
+{
+ return node->directory != NULL
+ && (!node->done_loading
+ || node->first_child == NULL
+ || node->inserting_first_child);
+}
+
+static int
+tree_node_get_child_index (TreeNode *parent, TreeNode *child)
+{
+ int i;
+ TreeNode *node;
+
+ if (child == NULL) {
+ g_assert (tree_node_has_dummy_child (parent));
+ return 0;
+ }
+
+ i = tree_node_has_dummy_child (parent) ? 1 : 0;
+ for (node = parent->first_child; node != NULL; node = node->next, i++) {
+ if (child == node) {
+ return i;
+ }
+ }
+
+ g_assert_not_reached ();
+ return 0;
+}
+
+static gboolean
+make_iter_invalid (GtkTreeIter *iter)
+{
+ iter->stamp = 0;
+ iter->user_data = NULL;
+ iter->user_data2 = NULL;
+ iter->user_data3 = NULL;
+ return FALSE;
+}
+
+static gboolean
+make_iter_for_node (TreeNode *node, GtkTreeIter *iter, int stamp)
+{
+ if (node == NULL) {
+ return make_iter_invalid (iter);
+ }
+ iter->stamp = stamp;
+ iter->user_data = node;
+ iter->user_data2 = NULL;
+ iter->user_data3 = NULL;
+ return TRUE;
+}
+
+static gboolean
+make_iter_for_dummy_row (TreeNode *parent, GtkTreeIter *iter, int stamp)
+{
+ g_assert (tree_node_has_dummy_child (parent));
+ g_assert (parent != NULL);
+ iter->stamp = stamp;
+ iter->user_data = NULL;
+ iter->user_data2 = parent;
+ iter->user_data3 = NULL;
+ return TRUE;
+}
+
+static TreeNode *
+get_node_from_file (FMTreeModelRoot *root, NautilusFile *file)
+{
+ return g_hash_table_lookup (root->file_to_node_map, file);
+}
+
+static TreeNode *
+get_parent_node_from_file (FMTreeModelRoot *root, NautilusFile *file)
+{
+ NautilusFile *parent_file;
+ TreeNode *parent_node;
+
+ parent_file = nautilus_file_get_parent (file);
+ parent_node = get_node_from_file (root, parent_file);
+ nautilus_file_unref (parent_file);
+ return parent_node;
+}
+
+static TreeNode *
+create_node_for_file (FMTreeModelRoot *root, NautilusFile *file)
+{
+ TreeNode *node;
+
+ g_assert (get_node_from_file (root, file) == NULL);
+ node = tree_node_new (file, root);
+ g_hash_table_insert (root->file_to_node_map, node->file, node);
+ return node;
+}
+
+#if LOG_REF_COUNTS
+
+static char *
+get_node_uri (GtkTreeIter *iter)
+{
+ TreeNode *node, *parent;
+ char *parent_uri, *node_uri;
+
+ node = iter->user_data;
+ if (node != NULL) {
+ return nautilus_file_get_uri (node->file);
+ }
+
+ parent = iter->user_data2;
+ parent_uri = nautilus_file_get_uri (parent->file);
+ node_uri = g_strconcat (parent_uri, " -- DUMMY", NULL);
+ g_free (parent_uri);
+ return node_uri;
+}
+
+#endif
+
+static void
+decrement_ref_count (FMTreeModel *model, TreeNode *node, int count)
+{
+ node->all_children_ref_count -= count;
+ if (node->all_children_ref_count == 0) {
+ schedule_monitoring_update (model);
+ }
+}
+
+static void
+abandon_node_ref_count (FMTreeModel *model, TreeNode *node)
+{
+ if (node->parent != NULL) {
+ decrement_ref_count (model, node->parent, node->ref_count);
+#if LOG_REF_COUNTS
+ if (node->ref_count != 0) {
+ char *uri;
+
+ uri = nautilus_file_get_uri (node->file);
+ g_message ("abandoning %d ref of %s, count is now %d",
+ node->ref_count, uri, node->parent->all_children_ref_count);
+ g_free (uri);
+ }
+#endif
+ }
+ node->ref_count = 0;
+}
+
+static void
+abandon_dummy_row_ref_count (FMTreeModel *model, TreeNode *node)
+{
+ decrement_ref_count (model, node, node->dummy_child_ref_count);
+ if (node->dummy_child_ref_count != 0) {
+#if LOG_REF_COUNTS
+ char *uri;
+
+ uri = nautilus_file_get_uri (node->file);
+ g_message ("abandoning %d ref of %s -- DUMMY, count is now %d",
+ node->dummy_child_ref_count, uri, node->all_children_ref_count);
+ g_free (uri);
+#endif
+ }
+ node->dummy_child_ref_count = 0;
+}
+
+static void
+report_row_inserted (FMTreeModel *model, GtkTreeIter *iter)
+{
+ GtkTreePath *path;
+
+ path = gtk_tree_model_get_path (GTK_TREE_MODEL (model), iter);
+ gtk_tree_model_row_inserted (GTK_TREE_MODEL (model), path, iter);
+ gtk_tree_path_free (path);
+}
+
+static void
+report_row_contents_changed (FMTreeModel *model, GtkTreeIter *iter)
+{
+ GtkTreePath *path;
+
+ path = gtk_tree_model_get_path (GTK_TREE_MODEL (model), iter);
+ gtk_tree_model_row_changed (GTK_TREE_MODEL (model), path, iter);
+ gtk_tree_path_free (path);
+}
+
+static void
+report_row_has_child_toggled (FMTreeModel *model, GtkTreeIter *iter)
+{
+ GtkTreePath *path;
+
+ path = gtk_tree_model_get_path (GTK_TREE_MODEL (model), iter);
+ gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (model), path, iter);
+ gtk_tree_path_free (path);
+}
+
+static GtkTreePath *
+get_node_path (FMTreeModel *model, TreeNode *node)
+{
+ GtkTreeIter iter;
+
+ make_iter_for_node (node, &iter, model->details->stamp);
+ return gtk_tree_model_get_path (GTK_TREE_MODEL (model), &iter);
+}
+
+static void
+report_dummy_row_inserted (FMTreeModel *model, TreeNode *parent)
+{
+ GtkTreeIter iter;
+
+ if (!parent->inserted) {
+ return;
+ }
+ make_iter_for_dummy_row (parent, &iter, model->details->stamp);
+ report_row_inserted (model, &iter);
+}
+
+static void
+report_dummy_row_deleted (FMTreeModel *model, TreeNode *parent)
+{
+ GtkTreeIter iter;
+ GtkTreePath *path;
+
+ abandon_dummy_row_ref_count (model, parent);
+ if (!parent->inserted) {
+ return;
+ }
+ make_iter_for_node (parent, &iter, model->details->stamp);
+ path = gtk_tree_model_get_path (GTK_TREE_MODEL (model), &iter);
+ gtk_tree_path_append_index (path, 0);
+ gtk_tree_model_row_deleted (GTK_TREE_MODEL (model), path);
+ gtk_tree_path_free (path);
+}
+
+static void
+report_node_inserted (FMTreeModel *model, TreeNode *node)
+{
+ GtkTreeIter iter;
+
+ make_iter_for_node (node, &iter, model->details->stamp);
+ report_row_inserted (model, &iter);
+ node->inserted = TRUE;
+
+ if (node->directory != NULL) {
+ report_row_has_child_toggled (model, &iter);
+ }
+ if (tree_node_has_dummy_child (node)) {
+ report_dummy_row_inserted (model, node);
+ }
+}
+
+static void
+report_node_contents_changed (FMTreeModel *model, TreeNode *node)
+{
+ GtkTreeIter iter;
+
+ if (!node->inserted) {
+ return;
+ }
+ make_iter_for_node (node, &iter, model->details->stamp);
+ report_row_contents_changed (model, &iter);
+}
+
+static void
+report_node_has_child_toggled (FMTreeModel *model, TreeNode *node)
+{
+ GtkTreeIter iter;
+
+ if (!node->inserted) {
+ return;
+ }
+ make_iter_for_node (node, &iter, model->details->stamp);
+ report_row_has_child_toggled (model, &iter);
+}
+
+static void
+report_dummy_row_contents_changed (FMTreeModel *model, TreeNode *parent)
+{
+ GtkTreeIter iter;
+
+ if (!parent->inserted) {
+ return;
+ }
+ make_iter_for_dummy_row (parent, &iter, model->details->stamp);
+ report_row_contents_changed (model, &iter);
+}
+
+static void
+stop_monitoring_directory (FMTreeModel *model, TreeNode *node)
+{
+ NautilusDirectory *directory;
+
+ if (node->done_loading_id == 0) {
+ g_assert (node->files_added_id == 0);
+ g_assert (node->files_changed_id == 0);
+ return;
+ }
+
+ directory = node->directory;
+
+ g_signal_handler_disconnect (node->directory, node->done_loading_id);
+ g_signal_handler_disconnect (node->directory, node->files_added_id);
+ g_signal_handler_disconnect (node->directory, node->files_changed_id);
+
+ node->done_loading_id = 0;
+ node->files_added_id = 0;
+ node->files_changed_id = 0;
+
+ nautilus_directory_file_monitor_remove (node->directory, model);
+}
+
+static void
+destroy_children_without_reporting (FMTreeModel *model, TreeNode *parent)
+{
+ while (parent->first_child != NULL) {
+ destroy_node_without_reporting (model, parent->first_child);
+ }
+}
+
+static void
+destroy_node_without_reporting (FMTreeModel *model, TreeNode *node)
+{
+ abandon_node_ref_count (model, node);
+ stop_monitoring_directory (model, node);
+ node->inserted = FALSE;
+ destroy_children_without_reporting (model, node);
+ g_hash_table_remove (node->root->file_to_node_map, node->file);
+ tree_node_destroy (model, node);
+}
+
+static void
+destroy_node (FMTreeModel *model, TreeNode *node)
+{
+ TreeNode *parent;
+ gboolean parent_had_dummy_child;
+ GtkTreePath *path;
+
+ parent = node->parent;
+ parent_had_dummy_child = tree_node_has_dummy_child (parent);
+
+ path = get_node_path (model, node);
+
+ destroy_node_without_reporting (model, node);
+
+ gtk_tree_model_row_deleted (GTK_TREE_MODEL (model), path);
+ gtk_tree_path_free (path);
+
+ if (tree_node_has_dummy_child (parent)) {
+ if (!parent_had_dummy_child) {
+ report_dummy_row_inserted (model, parent);
+ }
+ } else {
+ g_assert (!parent_had_dummy_child);
+ }
+}
+
+static void
+destroy_children (FMTreeModel *model, TreeNode *parent)
+{
+ while (parent->first_child != NULL) {
+ destroy_node (model, parent->first_child);
+ }
+}
+
+static void
+destroy_children_by_function (FMTreeModel *model, TreeNode *parent, FilePredicate f)
+{
+ TreeNode *child, *next;
+
+ for (child = parent->first_child; child != NULL; child = next) {
+ next = child->next;
+ if (f (child->file)) {
+ destroy_node (model, child);
+ } else {
+ destroy_children_by_function (model, child, f);
+ }
+ }
+}
+
+static void
+destroy_by_function (FMTreeModel *model, FilePredicate f)
+{
+ TreeNode *node;
+ for (node = model->details->root_node; node != NULL; node = node->next) {
+ destroy_children_by_function (model, node, f);
+ }
+}
+
+static gboolean
+update_node_without_reporting (FMTreeModel *model, TreeNode *node)
+{
+ gboolean changed;
+
+ changed = FALSE;
+
+ if (node->directory == NULL && nautilus_file_is_directory (node->file)) {
+ node->directory = nautilus_directory_get_for_file (node->file);
+ } else if (node->directory != NULL && !nautilus_file_is_directory (node->file)) {
+ stop_monitoring_directory (model, node);
+ destroy_children (model, node);
+ nautilus_directory_unref (node->directory);
+ node->directory = NULL;
+ }
+
+ changed |= tree_node_update_display_name (node);
+ changed |= tree_node_update_closed_pixbuf (node);
+ changed |= tree_node_update_open_pixbuf (node);
+
+ return changed;
+}
+
+static void
+insert_node (FMTreeModel *model, TreeNode *parent, TreeNode *node)
+{
+ gboolean parent_empty;
+
+ parent_empty = parent->first_child == NULL;
+ if (parent_empty) {
+ parent->inserting_first_child = TRUE;
+ }
+
+ tree_node_parent (node, parent);
+
+ update_node_without_reporting (model, node);
+ report_node_inserted (model, node);
+
+ if (parent_empty) {
+ parent->inserting_first_child = FALSE;
+ if (!tree_node_has_dummy_child (parent)) {
+ report_dummy_row_deleted (model, parent);
+ }
+ }
+}
+
+static void
+reparent_node (FMTreeModel *model, TreeNode *node)
+{
+ GtkTreePath *path;
+ TreeNode *new_parent;
+
+ new_parent = get_parent_node_from_file (node->root, node->file);
+ if (new_parent == NULL || new_parent->directory == NULL) {
+ destroy_node (model, node);
+ return;
+ }
+
+ path = get_node_path (model, node);
+
+ abandon_node_ref_count (model, node);
+ tree_node_unparent (model, node);
+
+ gtk_tree_model_row_deleted (GTK_TREE_MODEL (model), path);
+ gtk_tree_path_free (path);
+
+ insert_node (model, new_parent, node);
+}
+
+static gboolean
+should_show_file (FMTreeModel *model, NautilusFile *file)
+{
+ gboolean should;
+ TreeNode *node;
+
+ should = nautilus_file_should_show (file,
+ model->details->show_hidden_files,
+ model->details->show_backup_files);
+
+ if (should
+ && model->details->show_only_directories
+ &&! nautilus_file_is_directory (file)) {
+ should = FALSE;
+ }
+
+ if (should && nautilus_file_is_gone (file)) {
+ should = FALSE;
+ }
+
+ for (node = model->details->root_node; node != NULL; node = node->next) {
+ if (!should && node != NULL && file == node->file) {
+ should = TRUE;
+ }
+ }
+
+ return should;
+}
+
+static void
+update_node (FMTreeModel *model, TreeNode *node)
+{
+ gboolean had_dummy_child, has_dummy_child;
+ gboolean had_directory, has_directory;
+ gboolean changed;
+
+ if (!should_show_file (model, node->file)) {
+ destroy_node (model, node);
+ return;
+ }
+
+ if (node->parent != NULL && node->parent->directory != NULL
+ && !nautilus_directory_contains_file (node->parent->directory, node->file)) {
+ reparent_node (model, node);
+ return;
+ }
+
+ had_dummy_child = tree_node_has_dummy_child (node);
+ had_directory = node->directory != NULL;
+
+ changed = update_node_without_reporting (model, node);
+
+ has_dummy_child = tree_node_has_dummy_child (node);
+ has_directory = node->directory != NULL;
+
+ if (had_dummy_child != has_dummy_child) {
+ if (has_dummy_child) {
+ report_dummy_row_inserted (model, node);
+ } else {
+ report_dummy_row_deleted (model, node);
+ }
+ }
+ if (had_directory != has_directory) {
+ report_node_has_child_toggled (model, node);
+ }
+
+ if (changed) {
+ report_node_contents_changed (model, node);
+ }
+}
+
+static void
+process_file_change (FMTreeModelRoot *root,
+ NautilusFile *file)
+{
+ TreeNode *node, *parent;
+
+ node = get_node_from_file (root, file);
+ if (node != NULL) {
+ update_node (root->model, node);
+ return;
+ }
+
+ if (!should_show_file (root->model, file)) {
+ return;
+ }
+
+ parent = get_parent_node_from_file (root, file);
+ if (parent == NULL) {
+ return;
+ }
+
+ insert_node (root->model, parent, create_node_for_file (root, file));
+}
+
+static void
+files_changed_callback (NautilusDirectory *directory,
+ GList *changed_files,
+ gpointer callback_data)
+{
+ FMTreeModelRoot *root;
+ GList *node;
+
+ root = (FMTreeModelRoot *) (callback_data);
+
+ for (node = changed_files; node != NULL; node = node->next) {
+ process_file_change (root, NAUTILUS_FILE (node->data));
+ }
+}
+
+static void
+set_done_loading (FMTreeModel *model, TreeNode *node, gboolean done_loading)
+{
+ gboolean had_dummy;
+
+ if (node == NULL || node->done_loading == done_loading) {
+ return;
+ }
+
+ had_dummy = tree_node_has_dummy_child (node);
+
+ node->done_loading = done_loading;
+
+ if (tree_node_has_dummy_child (node)) {
+ if (had_dummy) {
+ report_dummy_row_contents_changed (model, node);
+ } else {
+ report_dummy_row_inserted (model, node);
+ }
+ } else {
+ if (had_dummy) {
+ report_dummy_row_deleted (model, node);
+ } else {
+ g_assert_not_reached ();
+ }
+ }
+}
+
+static void
+done_loading_callback (NautilusDirectory *directory,
+ FMTreeModelRoot *root)
+{
+ NautilusFile *file;
+ TreeNode *node;
+ GtkTreeIter iter;
+
+ file = nautilus_directory_get_corresponding_file (directory);
+ node = get_node_from_file (root, file);
+ g_assert (node != NULL);
+ set_done_loading (root->model, node, TRUE);
+ nautilus_file_unref (file);
+
+ make_iter_for_node (node, &iter, root->model->details->stamp);
+ g_signal_emit_by_name (root->model, "row_loaded", &iter);
+}
+
+static NautilusFileAttributes
+get_tree_monitor_attributes (void)
+{
+ NautilusFileAttributes attributes;
+
+ attributes = nautilus_icon_factory_get_required_file_attributes ();
+ attributes |= NAUTILUS_FILE_ATTRIBUTE_IS_DIRECTORY |
+ NAUTILUS_FILE_ATTRIBUTE_DISPLAY_NAME;
+
+ return attributes;
+}
+
+static void
+start_monitoring_directory (FMTreeModel *model, TreeNode *node)
+{
+ NautilusDirectory *directory;
+ NautilusFileAttributes attributes;
+
+ if (node->done_loading_id != 0) {
+ return;
+ }
+
+ g_assert (node->files_added_id == 0);
+ g_assert (node->files_changed_id == 0);
+
+ directory = node->directory;
+
+ node->done_loading_id = g_signal_connect
+ (directory, "done_loading",
+ G_CALLBACK (done_loading_callback), node->root);
+ node->files_added_id = g_signal_connect
+ (directory, "files_added",
+ G_CALLBACK (files_changed_callback), node->root);
+ node->files_changed_id = g_signal_connect
+ (directory, "files_changed",
+ G_CALLBACK (files_changed_callback), node->root);
+
+ set_done_loading (model, node, nautilus_directory_are_all_files_seen (directory));
+
+ attributes = get_tree_monitor_attributes ();
+ nautilus_directory_file_monitor_add (directory, model,
+ model->details->show_hidden_files,
+ model->details->show_backup_files,
+ attributes, files_changed_callback, node->root);
+}
+
+static int
+fm_tree_model_get_n_columns (GtkTreeModel *model)
+{
+ return FM_TREE_MODEL_NUM_COLUMNS;
+}
+
+static GType
+fm_tree_model_get_column_type (GtkTreeModel *model, int index)
+{
+ switch (index) {
+ case FM_TREE_MODEL_DISPLAY_NAME_COLUMN:
+ return G_TYPE_STRING;
+ case FM_TREE_MODEL_CLOSED_PIXBUF_COLUMN:
+ return GDK_TYPE_PIXBUF;
+ case FM_TREE_MODEL_OPEN_PIXBUF_COLUMN:
+ return GDK_TYPE_PIXBUF;
+ case FM_TREE_MODEL_FONT_STYLE_COLUMN:
+ return PANGO_TYPE_STYLE;
+ case FM_TREE_MODEL_FONT_WEIGHT_COLUMN:
+ return PANGO_TYPE_WEIGHT;
+ default:
+ g_assert_not_reached ();
+ }
+
+ return G_TYPE_INVALID;
+}
+
+static gboolean
+iter_is_valid (FMTreeModel *model, const GtkTreeIter *iter)
+{
+ TreeNode *node, *parent;
+
+ if (iter->stamp != model->details->stamp) {
+ return FALSE;
+ }
+
+ node = iter->user_data;
+ parent = iter->user_data2;
+ if (node == NULL) {
+ if (parent != NULL) {
+ if (!NAUTILUS_IS_FILE (parent->file)) {
+ return FALSE;
+ }
+ if (!tree_node_has_dummy_child (parent)) {
+ return FALSE;
+ }
+ }
+ } else {
+ if (!NAUTILUS_IS_FILE (node->file)) {
+ return FALSE;
+ }
+ if (parent != NULL) {
+ return FALSE;
+ }
+ }
+ if (iter->user_data3 != NULL) {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static gboolean
+fm_tree_model_get_iter (GtkTreeModel *model, GtkTreeIter *iter, GtkTreePath *path)
+{
+ int *indices;
+ GtkTreeIter parent;
+ int depth, i;
+
+ indices = gtk_tree_path_get_indices (path);
+ depth = gtk_tree_path_get_depth (path);
+
+ if (! gtk_tree_model_iter_nth_child (model, iter, NULL, indices[0])) {
+ return FALSE;
+ }
+
+ for (i = 1; i < depth; i++) {
+ parent = *iter;
+
+ if (! gtk_tree_model_iter_nth_child (model, iter, &parent, indices[i])) {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+static GtkTreePath *
+fm_tree_model_get_path (GtkTreeModel *model, GtkTreeIter *iter)
+{
+ FMTreeModel *tree_model;
+ TreeNode *node, *parent, *cnode;
+ GtkTreePath *path;
+ GtkTreeIter parent_iter;
+ int i;
+
+ g_return_val_if_fail (FM_IS_TREE_MODEL (model), NULL);
+ tree_model = FM_TREE_MODEL (model);
+ g_return_val_if_fail (iter_is_valid (tree_model, iter), NULL);
+
+ node = iter->user_data;
+ if (node == NULL) {
+ parent = iter->user_data2;
+ if (parent == NULL) {
+ return gtk_tree_path_new ();
+ }
+ } else {
+ parent = node->parent;
+ if (parent == NULL) {
+ i = 0;
+ for (cnode = tree_model->details->root_node; cnode != node; cnode = cnode->next) {
+ i++;
+ }
+ path = gtk_tree_path_new ();
+ gtk_tree_path_append_index (path, i);
+ return path;
+ }
+ }
+
+ parent_iter.stamp = iter->stamp;
+ parent_iter.user_data = parent;
+ parent_iter.user_data2 = NULL;
+ parent_iter.user_data3 = NULL;
+
+ path = fm_tree_model_get_path (model, &parent_iter);
+
+ gtk_tree_path_append_index (path, tree_node_get_child_index (parent, node));
+
+ return path;
+}
+
+static void
+fm_tree_model_get_value (GtkTreeModel *model, GtkTreeIter *iter, int column, GValue *value)
+{
+ TreeNode *node, *parent;
+
+ g_return_if_fail (FM_IS_TREE_MODEL (model));
+ g_return_if_fail (iter_is_valid (FM_TREE_MODEL (model), iter));
+
+ node = iter->user_data;
+
+ switch (column) {
+ case FM_TREE_MODEL_DISPLAY_NAME_COLUMN:
+ g_value_init (value, G_TYPE_STRING);
+ if (node == NULL) {
+ parent = iter->user_data2;
+ g_value_set_static_string (value, parent->done_loading
+ ? _("(Empty)") : _("Loading..."));
+ } else {
+ g_value_set_string (value, tree_node_get_display_name (node));
+ }
+ break;
+ case FM_TREE_MODEL_CLOSED_PIXBUF_COLUMN:
+ g_value_init (value, GDK_TYPE_PIXBUF);
+ g_value_set_object (value, node == NULL ? NULL : tree_node_get_closed_pixbuf (node));
+ break;
+ case FM_TREE_MODEL_OPEN_PIXBUF_COLUMN:
+ g_value_init (value, GDK_TYPE_PIXBUF);
+ g_value_set_object (value, node == NULL ? NULL : tree_node_get_open_pixbuf (node));
+ break;
+ case FM_TREE_MODEL_FONT_STYLE_COLUMN:
+ g_value_init (value, PANGO_TYPE_STYLE);
+ if (node == NULL) {
+ g_value_set_enum (value, PANGO_STYLE_ITALIC);
+ } else {
+ g_value_set_enum (value, PANGO_STYLE_NORMAL);
+ }
+ break;
+ case FM_TREE_MODEL_FONT_WEIGHT_COLUMN:
+ g_value_init (value, PANGO_TYPE_STYLE);
+ if (node != NULL && node->parent == NULL) {
+ g_value_set_enum (value, PANGO_WEIGHT_BOLD);
+ } else {
+ g_value_set_enum (value, PANGO_WEIGHT_NORMAL);
+ }
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+static gboolean
+fm_tree_model_iter_next (GtkTreeModel *model, GtkTreeIter *iter)
+{
+ TreeNode *node, *parent, *next;
+
+ g_return_val_if_fail (FM_IS_TREE_MODEL (model), FALSE);
+ g_return_val_if_fail (iter_is_valid (FM_TREE_MODEL (model), iter), FALSE);
+
+ node = iter->user_data;
+
+ if (node == NULL) {
+ parent = iter->user_data2;
+ next = parent->first_child;
+ } else {
+ next = node->next;
+ }
+
+ return make_iter_for_node (next, iter, iter->stamp);
+}
+
+static gboolean
+fm_tree_model_iter_children (GtkTreeModel *model, GtkTreeIter *iter, GtkTreeIter *parent_iter)
+{
+ TreeNode *parent;
+
+ g_return_val_if_fail (FM_IS_TREE_MODEL (model), FALSE);
+ g_return_val_if_fail (iter_is_valid (FM_TREE_MODEL (model), parent_iter), FALSE);
+
+ parent = parent_iter->user_data;
+ if (parent == NULL) {
+ return make_iter_invalid (iter);
+ }
+
+ if (tree_node_has_dummy_child (parent)) {
+ return make_iter_for_dummy_row (parent, iter, parent_iter->stamp);
+ }
+ return make_iter_for_node (parent->first_child, iter, parent_iter->stamp);
+}
+
+static gboolean
+fm_tree_model_iter_parent (GtkTreeModel *model, GtkTreeIter *iter, GtkTreeIter *child_iter)
+{ TreeNode *child, *parent;
+
+ g_return_val_if_fail (FM_IS_TREE_MODEL (model), FALSE);
+ g_return_val_if_fail (iter_is_valid (FM_TREE_MODEL (model), child_iter), FALSE);
+
+ child = child_iter->user_data;
+
+ if (child == NULL) {
+ parent = child_iter->user_data2;
+ } else {
+ parent = child->parent;
+ }
+
+ return make_iter_for_node (parent, iter, child_iter->stamp);
+}
+
+static gboolean
+fm_tree_model_iter_has_child (GtkTreeModel *model, GtkTreeIter *iter)
+{
+ gboolean has_child;
+ TreeNode *node;
+
+ g_return_val_if_fail (FM_IS_TREE_MODEL (model), FALSE);
+ g_return_val_if_fail (iter_is_valid (FM_TREE_MODEL (model), iter), FALSE);
+
+ node = iter->user_data;
+
+ has_child = node != NULL && node->directory != NULL;
+
+#if 0
+ g_warning ("Node '%s' %s",
+ node && node->file ? nautilus_file_get_uri (node->file) : "no name",
+ has_child ? "has child" : "no child");
+#endif
+
+ return has_child;
+}
+
+static int
+fm_tree_model_iter_n_children (GtkTreeModel *model, GtkTreeIter *iter)
+{
+ FMTreeModel *tree_model;
+ TreeNode *parent, *node;
+ int n;
+
+ g_return_val_if_fail (FM_IS_TREE_MODEL (model), FALSE);
+ g_return_val_if_fail (iter == NULL || iter_is_valid (FM_TREE_MODEL (model), iter), FALSE);
+
+ tree_model = FM_TREE_MODEL (model);
+
+ if (iter == NULL) {
+ return 1;
+ }
+
+ parent = iter->user_data;
+ if (parent == NULL) {
+ return 0;
+ }
+
+ n = tree_node_has_dummy_child (parent) ? 1 : 0;
+ for (node = parent->first_child; node != NULL; node = node->next) {
+ n++;
+ }
+
+ return n;
+}
+
+static gboolean
+fm_tree_model_iter_nth_child (GtkTreeModel *model, GtkTreeIter *iter,
+ GtkTreeIter *parent_iter, int n)
+{
+ FMTreeModel *tree_model;
+ TreeNode *parent, *node;
+ int i;
+
+ g_return_val_if_fail (FM_IS_TREE_MODEL (model), FALSE);
+ g_return_val_if_fail (parent_iter == NULL
+ || iter_is_valid (FM_TREE_MODEL (model), parent_iter), FALSE);
+
+ tree_model = FM_TREE_MODEL (model);
+
+ if (parent_iter == NULL) {
+ node = tree_model->details->root_node;
+ for (i = 0; i < n && node != NULL; i++, node = node->next);
+ return make_iter_for_node (node, iter,
+ tree_model->details->stamp);
+ }
+
+ parent = parent_iter->user_data;
+ if (parent == NULL) {
+ return make_iter_invalid (iter);
+ }
+
+ i = tree_node_has_dummy_child (parent) ? 1 : 0;
+ if (n == 0 && i == 1) {
+ return make_iter_for_dummy_row (parent, iter, parent_iter->stamp);
+ }
+ for (node = parent->first_child; i != n; i++, node = node->next) {
+ if (node == NULL) {
+ return make_iter_invalid (iter);
+ }
+ }
+
+ return make_iter_for_node (node, iter, parent_iter->stamp);
+}
+
+static void
+update_monitoring (FMTreeModel *model, TreeNode *node)
+{
+ TreeNode *child;
+
+ if (node->all_children_ref_count == 0) {
+ stop_monitoring_directory (model, node);
+ destroy_children (model, node);
+ } else {
+ for (child = node->first_child; child != NULL; child = child->next) {
+ update_monitoring (model, child);
+ }
+ start_monitoring_directory (model, node);
+ }
+}
+
+static gboolean
+update_monitoring_idle_callback (gpointer callback_data)
+{
+ FMTreeModel *model;
+ TreeNode *node;
+
+ model = FM_TREE_MODEL (callback_data);
+ model->details->monitoring_update_idle_id = 0;
+ for (node = model->details->root_node; node != NULL; node = node->next) {
+ update_monitoring (model, node);
+ }
+ return FALSE;
+}
+
+static void
+schedule_monitoring_update (FMTreeModel *model)
+{
+ if (model->details->monitoring_update_idle_id == 0) {
+ model->details->monitoring_update_idle_id =
+ g_idle_add (update_monitoring_idle_callback, model);
+ }
+}
+
+static void
+stop_monitoring_directory_and_children (FMTreeModel *model, TreeNode *node)
+{
+ TreeNode *child;
+
+ stop_monitoring_directory (model, node);
+ for (child = node->first_child; child != NULL; child = child->next) {
+ stop_monitoring_directory_and_children (model, child);
+ }
+}
+
+static void
+stop_monitoring (FMTreeModel *model)
+{
+ TreeNode *node;
+
+ for (node = model->details->root_node; node != NULL; node = node->next) {
+ stop_monitoring_directory_and_children (model, node);
+ }
+}
+
+static void
+fm_tree_model_ref_node (GtkTreeModel *model, GtkTreeIter *iter)
+{
+ TreeNode *node, *parent;
+#if LOG_REF_COUNTS
+ char *uri;
+#endif
+
+ g_return_if_fail (FM_IS_TREE_MODEL (model));
+ g_return_if_fail (iter_is_valid (FM_TREE_MODEL (model), iter));
+
+ node = iter->user_data;
+ if (node == NULL) {
+ parent = iter->user_data2;
+ g_assert (parent->dummy_child_ref_count >= 0);
+ ++parent->dummy_child_ref_count;
+ } else {
+ parent = node->parent;
+ g_assert (node->ref_count >= 0);
+ ++node->ref_count;
+ }
+
+ if (parent != NULL) {
+ g_assert (parent->all_children_ref_count >= 0);
+ if (++parent->all_children_ref_count == 1) {
+ if (parent->first_child == NULL) {
+ parent->done_loading = FALSE;
+ }
+ schedule_monitoring_update (FM_TREE_MODEL (model));
+ }
+#if LOG_REF_COUNTS
+ uri = get_node_uri (iter);
+ g_message ("ref of %s, count is now %d",
+ uri, parent->all_children_ref_count);
+ g_free (uri);
+#endif
+ }
+}
+
+static void
+fm_tree_model_unref_node (GtkTreeModel *model, GtkTreeIter *iter)
+{
+ TreeNode *node, *parent;
+#if LOG_REF_COUNTS
+ char *uri;
+#endif
+
+ g_return_if_fail (FM_IS_TREE_MODEL (model));
+ g_return_if_fail (iter_is_valid (FM_TREE_MODEL (model), iter));
+
+ node = iter->user_data;
+ if (node == NULL) {
+ parent = iter->user_data2;
+ g_assert (parent->dummy_child_ref_count > 0);
+ --parent->dummy_child_ref_count;
+ } else {
+ parent = node->parent;
+ g_assert (node->ref_count > 0);
+ --node->ref_count;
+ }
+
+ if (parent != NULL) {
+ g_assert (parent->all_children_ref_count > 0);
+#if LOG_REF_COUNTS
+ uri = get_node_uri (iter);
+ g_message ("unref of %s, count is now %d",
+ uri, parent->all_children_ref_count - 1);
+ g_free (uri);
+#endif
+ if (--parent->all_children_ref_count == 0) {
+ schedule_monitoring_update (FM_TREE_MODEL (model));
+ }
+ }
+}
+
+static void
+root_node_file_changed_callback (NautilusFile *file, FMTreeModelRoot *root)
+{
+ if (root->root_node != NULL) {
+ update_node (root->model, root->root_node);
+ }
+}
+
+void
+fm_tree_model_add_root_uri (FMTreeModel *model, const char *root_uri, const char *display_name, const char *icon_name)
+{
+ NautilusFile *file;
+ TreeNode *node, *cnode;
+ NautilusFileAttributes attributes;
+ FMTreeModelRoot *newroot;
+
+ file = nautilus_file_get (root_uri);
+
+ newroot = tree_model_root_new (model);
+ node = create_node_for_file (newroot, file);
+ node->display_name = g_strdup (display_name);
+ node->icon_name = g_strdup (icon_name);
+ newroot->root_node = node;
+ node->parent = NULL;
+ if (model->details->root_node == NULL) {
+ model->details->root_node = node;
+ } else {
+ /* append it */
+ for (cnode = model->details->root_node; cnode->next != NULL; cnode = cnode->next);
+ cnode->next = node;
+ node->prev = cnode;
+ }
+
+ newroot->changed_handler_id = g_signal_connect (node->file, "changed",
+ G_CALLBACK (root_node_file_changed_callback),
+ node->root);
+
+ attributes = get_tree_monitor_attributes ();
+ nautilus_file_monitor_add (file, model, attributes);
+
+ nautilus_file_unref (file);
+
+ update_node_without_reporting (model, node);
+ report_node_inserted (model, node);
+}
+
+void
+fm_tree_model_remove_root_uri (FMTreeModel *model, const char *uri)
+{
+ TreeNode *node;
+ GtkTreePath *path;
+ FMTreeModelRoot *root;
+ NautilusFile *file;
+
+ file = nautilus_file_get (uri);
+ for (node = model->details->root_node; node != NULL; node = node->next) {
+ if (file == node->file) {
+ break;
+ }
+ }
+ nautilus_file_unref (file);
+
+ if (node) {
+ /* remove the node */
+ nautilus_file_monitor_remove (node->file, model);
+ path = get_node_path (model, node);
+
+ if (node->prev) {
+ node->prev->next = node->next;
+ }
+ if (node->next) {
+ node->next->prev = node->prev;
+ }
+ if (node == model->details->root_node) {
+ model->details->root_node = node->next;
+ }
+
+ /* destroy the root identifier */
+ root = node->root;
+ destroy_node_without_reporting (model, node);
+ g_hash_table_destroy (root->file_to_node_map);
+ g_free (root);
+ gtk_tree_model_row_deleted (GTK_TREE_MODEL (model), path);
+ gtk_tree_path_free (path);
+ }
+}
+
+FMTreeModel *
+fm_tree_model_new (void)
+{
+ FMTreeModel *model;
+
+ model = g_object_new (FM_TYPE_TREE_MODEL, NULL);
+
+ return model;
+}
+
+static void
+set_theme (TreeNode *node, FMTreeModel *model)
+{
+ TreeNode *child;
+
+ tree_node_update_closed_pixbuf (node);
+ tree_node_update_open_pixbuf (node);
+
+ report_node_contents_changed (model, node);
+
+ for (child = node->first_child; child != NULL; child = child->next) {
+ set_theme (child, model);
+ }
+}
+
+void
+fm_tree_model_set_theme (FMTreeModel *model)
+{
+ TreeNode *node;
+
+ g_return_if_fail (FM_IS_TREE_MODEL (model));
+
+ node = model->details->root_node;
+ while (node != NULL) {
+ set_theme (node, model);
+ node = node->next;
+ }
+}
+
+
+void
+fm_tree_model_set_show_hidden_files (FMTreeModel *model,
+ gboolean show_hidden_files)
+{
+ g_return_if_fail (FM_IS_TREE_MODEL (model));
+ g_return_if_fail (show_hidden_files == FALSE || show_hidden_files == TRUE);
+
+ show_hidden_files = show_hidden_files != FALSE;
+ if (model->details->show_hidden_files == show_hidden_files) {
+ return;
+ }
+ model->details->show_hidden_files = show_hidden_files;
+ stop_monitoring (model);
+ if (!show_hidden_files) {
+ destroy_by_function (model, nautilus_file_is_hidden_file);
+ }
+ schedule_monitoring_update (model);
+}
+
+void
+fm_tree_model_set_show_backup_files (FMTreeModel *model,
+ gboolean show_backup_files)
+{
+ g_return_if_fail (FM_IS_TREE_MODEL (model));
+ g_return_if_fail (show_backup_files == FALSE || show_backup_files == TRUE);
+
+ show_backup_files = show_backup_files != FALSE;
+ if (model->details->show_backup_files == show_backup_files) {
+ return;
+ }
+ model->details->show_backup_files = show_backup_files;
+ stop_monitoring (model);
+ if (!show_backup_files) {
+ destroy_by_function (model, nautilus_file_is_backup_file);
+ }
+ schedule_monitoring_update (model);
+}
+
+static gboolean
+file_is_not_directory (NautilusFile *file)
+{
+ return !nautilus_file_is_directory (file);
+}
+
+void
+fm_tree_model_set_show_only_directories (FMTreeModel *model,
+ gboolean show_only_directories)
+{
+ g_return_if_fail (FM_IS_TREE_MODEL (model));
+ g_return_if_fail (show_only_directories == FALSE || show_only_directories == TRUE);
+
+ show_only_directories = show_only_directories != FALSE;
+ if (model->details->show_only_directories == show_only_directories) {
+ return;
+ }
+ model->details->show_only_directories = show_only_directories;
+ stop_monitoring (model);
+ if (show_only_directories) {
+ destroy_by_function (model, file_is_not_directory);
+ }
+ schedule_monitoring_update (model);
+}
+
+NautilusFile *
+fm_tree_model_iter_get_file (FMTreeModel *model, GtkTreeIter *iter)
+{
+ TreeNode *node;
+
+ g_return_val_if_fail (FM_IS_TREE_MODEL (model), 0);
+ g_return_val_if_fail (iter_is_valid (FM_TREE_MODEL (model), iter), 0);
+
+ node = iter->user_data;
+ return node == NULL ? NULL : nautilus_file_ref (node->file);
+}
+
+gboolean
+fm_tree_model_iter_is_root (FMTreeModel *model, GtkTreeIter *iter)
+{
+ TreeNode *node;
+
+ g_return_val_if_fail (FM_IS_TREE_MODEL (model), 0);
+ g_return_val_if_fail (iter_is_valid (model, iter), 0);
+ node = iter->user_data;
+ if (node == NULL) {
+ return FALSE;
+ } else {
+ return (node->parent == NULL);
+ }
+}
+
+gboolean
+fm_tree_model_file_get_iter (FMTreeModel *model,
+ GtkTreeIter *iter,
+ NautilusFile *file,
+ GtkTreeIter *current_iter)
+{
+ TreeNode *node, *root_node;
+
+ if (current_iter != NULL && current_iter->user_data != NULL) {
+ node = get_node_from_file (((TreeNode *) current_iter->user_data)->root, file);
+ return make_iter_for_node (node, iter, model->details->stamp);
+ }
+
+ for (root_node = model->details->root_node; root_node != NULL; root_node = root_node->next) {
+ node = get_node_from_file (root_node->root, file);
+ if (node != NULL) {
+ return make_iter_for_node (node, iter, model->details->stamp);
+ }
+ }
+ return FALSE;
+}
+
+static void
+fm_tree_model_init (FMTreeModel *model)
+{
+ model->details = g_new0 (FMTreeModelDetails, 1);
+
+ do {
+ model->details->stamp = g_random_int ();
+ } while (model->details->stamp == 0);
+}
+
+static void
+fm_tree_model_finalize (GObject *object)
+{
+ FMTreeModel *model;
+ TreeNode *root_node, *next_root;
+ FMTreeModelRoot *root;
+
+ model = FM_TREE_MODEL (object);
+
+ for (root_node = model->details->root_node; root_node != NULL; root_node = next_root) {
+ next_root = root_node->next;
+ root = root_node->root;
+ g_signal_handler_disconnect (root_node->file, root->changed_handler_id);
+ nautilus_file_monitor_remove (root_node->file, model);
+ destroy_node_without_reporting (model, root_node);
+ g_hash_table_destroy (root->file_to_node_map);
+ g_free (root);
+ }
+
+ if (model->details->monitoring_update_idle_id != 0) {
+ g_source_remove (model->details->monitoring_update_idle_id);
+ }
+
+ g_free (model->details);
+
+ parent_class->finalize (object);
+}
+
+static void
+fm_tree_model_class_init (FMTreeModelClass *class)
+{
+ parent_class = g_type_class_peek_parent (class);
+
+ G_OBJECT_CLASS (class)->finalize = fm_tree_model_finalize;
+
+ tree_model_signals[ROW_LOADED] =
+ g_signal_new ("row_loaded",
+ FM_TYPE_TREE_MODEL,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (FMTreeModelClass, row_loaded),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__BOXED,
+ G_TYPE_NONE, 1,
+ GTK_TYPE_TREE_ITER);
+}
+
+static void
+fm_tree_model_tree_model_init (GtkTreeModelIface *iface)
+{
+ iface->get_flags = fm_tree_model_get_flags;
+ iface->get_n_columns = fm_tree_model_get_n_columns;
+ iface->get_column_type = fm_tree_model_get_column_type;
+ iface->get_iter = fm_tree_model_get_iter;
+ iface->get_path = fm_tree_model_get_path;
+ iface->get_value = fm_tree_model_get_value;
+ iface->iter_next = fm_tree_model_iter_next;
+ iface->iter_children = fm_tree_model_iter_children;
+ iface->iter_has_child = fm_tree_model_iter_has_child;
+ iface->iter_n_children = fm_tree_model_iter_n_children;
+ iface->iter_nth_child = fm_tree_model_iter_nth_child;
+ iface->iter_parent = fm_tree_model_iter_parent;
+ iface->ref_node = fm_tree_model_ref_node;
+ iface->unref_node = fm_tree_model_unref_node;
+}
+
+GType
+fm_tree_model_get_type (void)
+{
+ static GType object_type = 0;
+
+ if (object_type == 0) {
+ static const GTypeInfo object_info = {
+ sizeof (FMTreeModelClass),
+ NULL,
+ NULL,
+ (GClassInitFunc) fm_tree_model_class_init,
+ NULL,
+ NULL,
+ sizeof (FMTreeModel),
+ 0,
+ (GInstanceInitFunc) fm_tree_model_init,
+ };
+
+ static const GInterfaceInfo tree_model_info = {
+ (GInterfaceInitFunc) fm_tree_model_tree_model_init,
+ NULL,
+ NULL
+ };
+
+ object_type = g_type_register_static (G_TYPE_OBJECT, "FMTreeModel", &object_info, 0);
+ g_type_add_interface_static (object_type,
+ GTK_TYPE_TREE_MODEL,
+ &tree_model_info);
+ }
+
+ return object_type;
+}
diff --git a/src/file-manager/fm-tree-model.h b/src/file-manager/fm-tree-model.h
new file mode 100644
index 000000000..5d7146de5
--- /dev/null
+++ b/src/file-manager/fm-tree-model.h
@@ -0,0 +1,88 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+
+/*
+ * Copyright (C) 2002 Anders Carlsson
+ * Copyright (C) 2002 Bent Spoon Software
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Anders Carlsson <andersca@gnu.org>
+ */
+
+/* fm-tree-model.h - Model for the tree view */
+
+#ifndef FM_TREE_MODEL_H
+#define FM_TREE_MODEL_H
+
+#include <glib-object.h>
+#include <gtk/gtktreemodel.h>
+#include <libnautilus-private/nautilus-file.h>
+
+#define FM_TYPE_TREE_MODEL (fm_tree_model_get_type ())
+#define FM_TREE_MODEL(obj) (GTK_CHECK_CAST ((obj), FM_TYPE_TREE_MODEL, FMTreeModel))
+#define FM_TREE_MODEL_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), FM_TYPE_TREE_MODEL, FMTreeModelClass))
+#define FM_IS_TREE_MODEL(obj) (GTK_CHECK_TYPE ((obj), FM_TYPE_TREE_MODEL))
+#define FM_IS_TREE_MODEL_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), FM_TYPE_TREE_MODEL))
+
+enum {
+ FM_TREE_MODEL_DISPLAY_NAME_COLUMN,
+ FM_TREE_MODEL_CLOSED_PIXBUF_COLUMN,
+ FM_TREE_MODEL_OPEN_PIXBUF_COLUMN,
+ FM_TREE_MODEL_FONT_STYLE_COLUMN,
+ FM_TREE_MODEL_FONT_WEIGHT_COLUMN,
+ FM_TREE_MODEL_NUM_COLUMNS
+};
+
+typedef struct FMTreeModelDetails FMTreeModelDetails;
+
+typedef struct {
+ GObject parent;
+ FMTreeModelDetails *details;
+} FMTreeModel;
+
+typedef struct {
+ GObjectClass parent_class;
+
+ void (* row_loaded) (FMTreeModel *tree_model,
+ GtkTreeIter *iter);
+} FMTreeModelClass;
+
+GType fm_tree_model_get_type (void);
+FMTreeModel *fm_tree_model_new (void);
+void fm_tree_model_set_show_hidden_files (FMTreeModel *model,
+ gboolean show_hidden_files);
+void fm_tree_model_set_show_backup_files (FMTreeModel *model,
+ gboolean show_backup_files);
+void fm_tree_model_set_show_only_directories (FMTreeModel *model,
+ gboolean show_only_directories);
+NautilusFile * fm_tree_model_iter_get_file (FMTreeModel *model,
+ GtkTreeIter *iter);
+void fm_tree_model_add_root_uri (FMTreeModel *model,
+ const char *root_uri,
+ const char *display_name,
+ const char *icon_name);
+void fm_tree_model_remove_root_uri (FMTreeModel *model,
+ const char *root_uri);
+gboolean fm_tree_model_iter_is_root (FMTreeModel *model,
+ GtkTreeIter *iter);
+gboolean fm_tree_model_file_get_iter (FMTreeModel *model,
+ GtkTreeIter *iter,
+ NautilusFile *file,
+ GtkTreeIter *currentIter);
+
+void fm_tree_model_set_theme (FMTreeModel *model);
+
+#endif /* FM_TREE_MODEL_H */
diff --git a/src/file-manager/fm-tree-view.c b/src/file-manager/fm-tree-view.c
new file mode 100644
index 000000000..9e556a1ab
--- /dev/null
+++ b/src/file-manager/fm-tree-view.c
@@ -0,0 +1,1305 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+
+/*
+ * Copyright (C) 2000, 2001 Eazel, Inc
+ * Copyright (C) 2002 Anders Carlsson
+ * Copyright (C) 2002 Darin Adler
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors:
+ * Maciej Stachowiak <mjs@eazel.com>
+ * Anders Carlsson <andersca@gnu.org>
+ * Darin Adler <darin@bentspoon.com>
+ */
+
+/* fm-tree-view.c - tree sidebar panel
+ */
+
+#include <config.h>
+#include "fm-tree-view.h"
+
+#include "fm-tree-model.h"
+#include "fm-properties-window.h"
+#include <eel/eel-glib-extensions.h>
+#include <eel/eel-preferences.h>
+#include <eel/eel-string.h>
+#include <eel/eel-vfs-extensions.h>
+#include <gtk/gtkcellrendererpixbuf.h>
+#include <gtk/gtkcellrenderertext.h>
+#include <gtk/gtkscrolledwindow.h>
+#include <gtk/gtktreemodelsort.h>
+#include <gtk/gtktreeselection.h>
+#include <gtk/gtktreeview.h>
+#include <gtk/gtkstock.h>
+#include <gtk/gtkimage.h>
+#include <gtk/gtkimagemenuitem.h>
+#include <gtk/gtkseparatormenuitem.h>
+#include <gtk/gtkmenu.h>
+#include <gtk/gtkmenushell.h>
+#include <gtk/gtkclipboard.h>
+#include <libgnome/gnome-i18n.h>
+#include <libgnomeui/gnome-uidefs.h>
+#include <libgnomeui/gnome-popup-menu.h>
+#include <libgnomevfs/gnome-vfs-utils.h>
+#include <libgnomevfs/gnome-vfs-volume-monitor.h>
+#include <libnautilus-private/nautilus-file-attributes.h>
+#include <libnautilus-private/nautilus-file-operations.h>
+#include <libnautilus-private/nautilus-global-preferences.h>
+#include <libnautilus-private/nautilus-program-choosing.h>
+#include <libnautilus-private/nautilus-tree-view-drag-dest.h>
+#include <libnautilus-private/nautilus-icon-factory.h>
+
+struct FMTreeViewDetails {
+ GtkWidget *scrolled_window;
+ GtkTreeView *tree_widget;
+ GtkTreeModelSort *sort_model;
+ FMTreeModel *child_model;
+
+ NautilusFile *activation_file;
+ gboolean activation_in_new_window;
+
+ NautilusTreeViewDragDest *drag_dest;
+
+ char *selection_location;
+ gboolean selecting;
+
+ guint show_selection_idle_id;
+
+ GtkWidget *popup;
+ GtkWidget *popup_open;
+ GtkWidget *popup_open_in_new_window;
+ GtkWidget *popup_create_folder;
+ GtkWidget *popup_cut;
+ GtkWidget *popup_copy;
+ GtkWidget *popup_paste;
+ GtkWidget *popup_rename;
+ GtkWidget *popup_trash;
+ GtkWidget *popup_properties;
+ NautilusFile *popup_file;
+};
+
+typedef struct {
+ GList *uris;
+ FMTreeView *view;
+} PrependURIParameters;
+
+static GdkAtom copied_files_atom;
+
+enum {
+ GNOME_COPIED_FILES
+};
+
+static const GtkTargetEntry clipboard_targets[] = {
+ { "x-special/gnome-copied-files", 0, GNOME_COPIED_FILES },
+};
+
+BONOBO_CLASS_BOILERPLATE (FMTreeView, fm_tree_view,
+ NautilusView, NAUTILUS_TYPE_VIEW)
+
+static gboolean
+show_iter_for_file (FMTreeView *view, NautilusFile *file, GtkTreeIter *iter)
+{
+ GtkTreeModel *model;
+ NautilusFile *parent_file;
+ GtkTreeIter parent_iter;
+ GtkTreePath *path, *sort_path;
+ GtkTreeIter cur_iter;
+
+ if (view->details->child_model == NULL) {
+ return FALSE;
+ }
+ model = GTK_TREE_MODEL (view->details->child_model);
+
+ /* check if file is visible in the same root as the currently selected folder is */
+ gtk_tree_view_get_cursor (view->details->tree_widget, &path, NULL);
+ if (path != NULL) {
+ if (gtk_tree_model_get_iter (model, &cur_iter, path)) {
+ if (fm_tree_model_file_get_iter (view->details->child_model,
+ iter, file, &cur_iter)) {
+ return TRUE;
+ }
+ }
+ }
+ /* check if file is visible at all */
+ if (fm_tree_model_file_get_iter (view->details->child_model,
+ iter, file, NULL)) {
+ return TRUE;
+ }
+
+ parent_file = nautilus_file_get_parent (file);
+
+ if (parent_file == NULL) {
+ return FALSE;
+ }
+ if (!show_iter_for_file (view, parent_file, &parent_iter)) {
+ nautilus_file_unref (parent_file);
+ return FALSE;
+ }
+ nautilus_file_unref (parent_file);
+
+ if (parent_iter.user_data == NULL || parent_iter.stamp == 0) {
+ return FALSE;
+ }
+ path = gtk_tree_model_get_path (model, &parent_iter);
+ sort_path = gtk_tree_model_sort_convert_child_path_to_path
+ (view->details->sort_model, path);
+ gtk_tree_path_free (path);
+ gtk_tree_view_expand_row (view->details->tree_widget, sort_path, FALSE);
+ gtk_tree_path_free (sort_path);
+
+ return FALSE;
+}
+
+static gboolean
+show_selection_idle_callback (gpointer callback_data)
+{
+ FMTreeView *view;
+ NautilusFile *file, *old_file;
+ GtkTreeIter iter;
+ GtkTreePath *path, *sort_path;
+
+ view = FM_TREE_VIEW (callback_data);
+
+ view->details->show_selection_idle_id = 0;
+
+ file = nautilus_file_get (view->details->selection_location);
+ if (file == NULL) {
+ return FALSE;
+ }
+
+ if (!nautilus_file_is_directory (file)) {
+ old_file = file;
+ file = nautilus_file_get_parent (file);
+ nautilus_file_unref (old_file);
+ if (file == NULL) {
+ return FALSE;
+ }
+ }
+
+ view->details->selecting = TRUE;
+ if (!show_iter_for_file (view, file, &iter)) {
+ nautilus_file_unref (file);
+ return FALSE;
+ }
+ view->details->selecting = FALSE;
+
+ path = gtk_tree_model_get_path (GTK_TREE_MODEL (view->details->child_model), &iter);
+ sort_path = gtk_tree_model_sort_convert_child_path_to_path
+ (view->details->sort_model, path);
+ gtk_tree_path_free (path);
+ gtk_tree_view_set_cursor (view->details->tree_widget, sort_path, NULL, FALSE);
+ gtk_tree_view_scroll_to_cell (view->details->tree_widget, sort_path, NULL, FALSE, 0, 0);
+ gtk_tree_path_free (sort_path);
+
+ nautilus_file_unref (file);
+
+ return FALSE;
+}
+
+static void
+schedule_show_selection (FMTreeView *view)
+{
+ if (view->details->show_selection_idle_id == 0) {
+ view->details->show_selection_idle_id = g_idle_add (show_selection_idle_callback, view);
+ }
+}
+
+static void
+row_loaded_callback (GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ FMTreeView *view)
+{
+ NautilusFile *file, *tmp_file, *selection_file;
+
+ if (view->details->selection_location == NULL
+ || !view->details->selecting
+ || iter->user_data == NULL || iter->stamp == 0) {
+ return;
+ }
+
+ file = fm_tree_model_iter_get_file (view->details->child_model, iter);
+ if (file == NULL) {
+ return;
+ }
+ if (!nautilus_file_is_directory (file)) {
+ nautilus_file_unref(file);
+ return;
+ }
+
+ /* if iter is ancestor of wanted selection_location then update selection */
+ selection_file = nautilus_file_get (view->details->selection_location);
+ while (selection_file != NULL) {
+ if (file == selection_file) {
+ nautilus_file_unref (file);
+ nautilus_file_unref (selection_file);
+
+ schedule_show_selection (view);
+ return;
+ }
+ tmp_file = nautilus_file_get_parent (selection_file);
+ nautilus_file_unref (selection_file);
+ selection_file = tmp_file;
+ }
+ nautilus_file_unref (file);
+}
+
+static NautilusFile *
+sort_model_iter_to_file (FMTreeView *view, GtkTreeIter *iter)
+{
+ GtkTreeIter child_iter;
+
+ gtk_tree_model_sort_convert_iter_to_child_iter (view->details->sort_model, &child_iter, iter);
+ return fm_tree_model_iter_get_file (view->details->child_model, &child_iter);
+}
+
+static NautilusFile *
+sort_model_path_to_file (FMTreeView *view, GtkTreePath *path)
+{
+ GtkTreeIter iter;
+
+ if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (view->details->sort_model), &iter, path)) {
+ return NULL;
+ }
+ return sort_model_iter_to_file (view, &iter);
+}
+
+static void
+got_activation_uri_callback (NautilusFile *file, gpointer callback_data)
+{
+ char *uri, *file_uri;
+ FMTreeView *view;
+ GdkScreen *screen;
+ Nautilus_ViewFrame_OpenMode mode;
+
+ view = FM_TREE_VIEW (callback_data);
+
+ screen = gtk_widget_get_screen (GTK_WIDGET (view->details->tree_widget));
+
+ g_assert (file == view->details->activation_file);
+
+ mode = view->details->activation_in_new_window ? Nautilus_ViewFrame_OPEN_IN_NAVIGATION : Nautilus_ViewFrame_OPEN_ACCORDING_TO_MODE;
+
+ /* FIXME: reenable && !eel_uris_match_ignore_fragments (view->details->current_main_view_uri, uri) */
+
+ uri = nautilus_file_get_activation_uri (file);
+ if (uri != NULL
+ && eel_str_has_prefix (uri, NAUTILUS_COMMAND_SPECIFIER)) {
+
+ uri += strlen (NAUTILUS_COMMAND_SPECIFIER);
+ nautilus_launch_application_from_command (screen, NULL, uri, NULL, FALSE);
+
+ } else if (uri != NULL
+ && eel_str_has_prefix (uri, NAUTILUS_DESKTOP_COMMAND_SPECIFIER)) {
+
+ file_uri = nautilus_file_get_uri (file);
+ nautilus_launch_desktop_file (screen, file_uri, NULL, NULL);
+ g_free (file_uri);
+
+ } else if (uri != NULL
+ && nautilus_file_is_executable (file)
+ && nautilus_file_can_execute (file)
+ && !nautilus_file_is_directory (file)) {
+
+ file_uri = gnome_vfs_get_local_path_from_uri (uri);
+
+ /* Non-local executables don't get launched. They act like non-executables. */
+ if (file_uri == NULL) {
+ nautilus_view_open_location
+ (NAUTILUS_VIEW (view),
+ uri,
+ mode,
+ 0,
+ NULL);
+ } else {
+ nautilus_launch_application_from_command (screen, NULL, file_uri, NULL, FALSE);
+ g_free (file_uri);
+ }
+
+ } else if (uri != NULL) {
+ if (view->details->selection_location == NULL ||
+ strcmp (uri, view->details->selection_location) != 0) {
+ if (view->details->selection_location != NULL) {
+ g_free (view->details->selection_location);
+ }
+ view->details->selection_location = g_strdup (uri);
+ nautilus_view_open_location
+ (NAUTILUS_VIEW (view),
+ uri,
+ mode,
+ 0,
+ NULL);
+ }
+ }
+
+ g_free (uri);
+ nautilus_file_unref (view->details->activation_file);
+ view->details->activation_file = NULL;
+}
+
+static void
+cancel_activation (FMTreeView *view)
+{
+ if (view->details->activation_file == NULL) {
+ return;
+ }
+
+ nautilus_file_cancel_call_when_ready
+ (view->details->activation_file,
+ got_activation_uri_callback, view);
+ nautilus_file_unref (view->details->activation_file);
+ view->details->activation_file = NULL;
+}
+
+static void
+row_activated_callback (GtkTreeView *treeview, GtkTreePath *path,
+ GtkTreeViewColumn *column, FMTreeView *view)
+{
+ if (gtk_tree_view_row_expanded (view->details->tree_widget, path)) {
+ gtk_tree_view_collapse_row (view->details->tree_widget, path);
+ } else {
+ gtk_tree_view_expand_row (view->details->tree_widget,
+ path, FALSE);
+ }
+}
+
+
+static void
+selection_changed_callback (GtkTreeSelection *selection,
+ FMTreeView *view)
+{
+ NautilusFileAttributes attributes;
+ GtkTreeIter iter;
+
+ /* no activation if popup menu is open */
+ if (view->details->popup_file != NULL) {
+ return;
+ }
+
+ cancel_activation (view);
+
+ if (!gtk_tree_selection_get_selected (selection, NULL, &iter)) {
+ return;
+ }
+
+ view->details->activation_file = sort_model_iter_to_file (view, &iter);
+ if (view->details->activation_file == NULL) {
+ return;
+ }
+ view->details->activation_in_new_window = FALSE;
+
+ attributes = NAUTILUS_FILE_ATTRIBUTE_ACTIVATION_URI;
+ nautilus_file_call_when_ready (view->details->activation_file, attributes,
+ got_activation_uri_callback, view);
+}
+
+static int
+compare_rows (GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer callback_data)
+{
+ NautilusFile *file_a, *file_b;
+ int result;
+
+ if (a->user_data == NULL) {
+ return -1;
+ }
+ else if (b->user_data == NULL) {
+ return -1;
+ }
+
+ /* don't sort root nodes */
+ if (fm_tree_model_iter_is_root (FM_TREE_MODEL (model), a)
+ || fm_tree_model_iter_is_root (FM_TREE_MODEL (model), b)) {
+ return 0;
+ }
+
+ file_a = fm_tree_model_iter_get_file (FM_TREE_MODEL (model), a);
+ file_b = fm_tree_model_iter_get_file (FM_TREE_MODEL (model), b);
+
+ if (file_a == file_b) {
+ result = 0;
+ } else if (file_a == NULL) {
+ result = -1;
+ } else if (file_b == NULL) {
+ result = +1;
+ } else {
+ result = nautilus_file_compare_for_sort (file_a, file_b,
+ NAUTILUS_FILE_SORT_BY_DISPLAY_NAME,
+ FALSE, FALSE);
+ }
+
+ nautilus_file_unref (file_a);
+ nautilus_file_unref (file_b);
+
+ return result;
+}
+
+
+static char *
+get_root_uri_callback (NautilusTreeViewDragDest *dest,
+ gpointer user_data)
+{
+ FMTreeView *view;
+
+ view = FM_TREE_VIEW (user_data);
+
+ /* Don't allow drops on background */
+ return NULL;
+}
+
+static NautilusFile *
+get_file_for_path_callback (NautilusTreeViewDragDest *dest,
+ GtkTreePath *path,
+ gpointer user_data)
+{
+ FMTreeView *view;
+
+ view = FM_TREE_VIEW (user_data);
+
+ return sort_model_path_to_file (view, path);
+}
+
+static void
+move_copy_items_callback (NautilusTreeViewDragDest *dest,
+ const GList *item_uris,
+ const char *target_uri,
+ guint action,
+ int x,
+ int y,
+ gpointer user_data)
+{
+ FMTreeView *view;
+
+ view = FM_TREE_VIEW (user_data);
+
+ nautilus_file_operations_copy_move
+ (item_uris,
+ NULL,
+ target_uri,
+ action,
+ GTK_WIDGET (view->details->tree_widget),
+ NULL, NULL);
+}
+
+static void
+theme_changed_callback (GObject *icon_factory, gpointer callback_data)
+{
+ FMTreeView *view;
+
+ view = FM_TREE_VIEW (callback_data);
+ if (view->details->child_model != NULL) {
+ fm_tree_model_set_theme (FM_TREE_MODEL (view->details->child_model));
+ }
+}
+
+static void
+add_root_for_volume (FMTreeView *view,
+ GnomeVFSVolume *volume)
+{
+ char *icon, *mount_uri, *name;
+
+ if (!gnome_vfs_volume_is_user_visible (volume)) {
+ return;
+ }
+
+ icon = gnome_vfs_volume_get_icon (volume);
+ mount_uri = gnome_vfs_volume_get_activation_uri (volume);
+ name = gnome_vfs_volume_get_display_name (volume);
+
+ fm_tree_model_add_root_uri (view->details->child_model,
+ mount_uri, name, icon);
+
+ g_free (icon);
+ g_free (name);
+ g_free (mount_uri);
+
+}
+
+static void
+volume_mounted_callback (GnomeVFSVolumeMonitor *volume_monitor,
+ GnomeVFSVolume *volume,
+ FMTreeView *view)
+{
+ add_root_for_volume (view, volume);
+}
+
+static void
+volume_unmounted_callback (GnomeVFSVolumeMonitor *volume_monitor,
+ GnomeVFSVolume *volume,
+ FMTreeView *view)
+{
+ char *mount_uri;
+
+ mount_uri = gnome_vfs_volume_get_activation_uri (volume);
+ fm_tree_model_remove_root_uri (view->details->child_model,
+ mount_uri);
+ g_free (mount_uri);
+}
+
+static void
+clipboard_contents_received_callback (GtkClipboard *clipboard,
+ GtkSelectionData *selection_data,
+ gpointer data)
+{
+ FMTreeView *view;
+
+ view = FM_TREE_VIEW (data);
+
+ if (selection_data->type == copied_files_atom
+ && selection_data->length > 0) {
+ gtk_widget_set_sensitive (view->details->popup_paste, TRUE);
+ }
+}
+
+static GtkClipboard *
+get_clipboard (GtkWidget *widget)
+{
+ return gtk_clipboard_get_for_display (gtk_widget_get_display (widget),
+ GDK_SELECTION_CLIPBOARD);
+}
+
+static gboolean
+can_move_uri_to_trash (const char *file_uri_string)
+{
+ /* Return TRUE if we can get a trash directory on the same volume as this file. */
+ GnomeVFSURI *file_uri;
+ GnomeVFSURI *directory_uri;
+ GnomeVFSURI *trash_dir_uri;
+ gboolean result;
+
+ g_return_val_if_fail (file_uri_string != NULL, FALSE);
+
+ file_uri = gnome_vfs_uri_new (file_uri_string);
+
+ if (file_uri == NULL) {
+ return FALSE;
+ }
+
+ /* FIXME: Why can't we just pass file_uri to gnome_vfs_find_directory? */
+ directory_uri = gnome_vfs_uri_get_parent (file_uri);
+ gnome_vfs_uri_unref (file_uri);
+
+ if (directory_uri == NULL) {
+ return FALSE;
+ }
+
+ /*
+ * Create a new trash if needed but don't go looking for an old Trash.
+ * Passing 0 permissions as gnome-vfs would override the permissions
+ * passed with 700 while creating .Trash directory
+ */
+ result = gnome_vfs_find_directory (directory_uri, GNOME_VFS_DIRECTORY_KIND_TRASH,
+ &trash_dir_uri, TRUE, FALSE, 0) == GNOME_VFS_OK;
+ if (result) {
+ gnome_vfs_uri_unref (trash_dir_uri);
+ }
+ gnome_vfs_uri_unref (directory_uri);
+
+ return result;
+}
+
+static gboolean
+button_pressed_callback (GtkTreeView *treeview, GdkEventButton *event,
+ FMTreeView *view)
+{
+ GtkTreePath *path, *cursor_path;
+ char *uri;
+
+ if (event->button == 3) {
+ if (!gtk_tree_view_get_path_at_pos (treeview, event->x, event->y,
+ &path, NULL, NULL, NULL)) {
+ return FALSE;
+ }
+
+ view->details->popup_file = sort_model_path_to_file (view, path);
+ if (view->details->popup_file == NULL) {
+ gtk_tree_path_free (path);
+ return FALSE;
+ }
+ gtk_tree_view_get_cursor (view->details->tree_widget, &cursor_path, NULL);
+ gtk_tree_view_set_cursor (view->details->tree_widget, path, NULL, FALSE);
+ gtk_tree_path_free (path);
+ uri = nautilus_file_get_uri (view->details->popup_file);
+
+ gtk_widget_set_sensitive (view->details->popup_open_in_new_window,
+ nautilus_file_is_directory (view->details->popup_file));
+ gtk_widget_set_sensitive (view->details->popup_create_folder,
+ nautilus_file_is_directory (view->details->popup_file) &&
+ nautilus_file_can_write (view->details->popup_file));
+ gtk_widget_set_sensitive (view->details->popup_paste, FALSE);
+ if (nautilus_file_is_directory (view->details->popup_file) &&
+ nautilus_file_can_write (view->details->popup_file)) {
+ gtk_clipboard_request_contents (get_clipboard (GTK_WIDGET (view->details->tree_widget)),
+ copied_files_atom,
+ clipboard_contents_received_callback, view);
+ }
+ gtk_widget_set_sensitive (view->details->popup_trash, can_move_uri_to_trash (uri));
+ g_free (uri);
+
+ gnome_popup_menu_do_popup_modal (view->details->popup,
+ NULL, NULL, event, NULL,
+ GTK_WIDGET (treeview));
+
+ gtk_tree_view_set_cursor (view->details->tree_widget, cursor_path, NULL, FALSE);
+ gtk_tree_path_free (cursor_path);
+
+ nautilus_file_unref (view->details->popup_file);
+ view->details->popup_file = NULL;
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+fm_tree_view_activate_file (FMTreeView *view,
+ NautilusFile *file,
+ gboolean open_in_new_window)
+{
+ NautilusFileAttributes attributes;
+
+ cancel_activation (view);
+
+ view->details->activation_file = nautilus_file_ref (file);
+ view->details->activation_in_new_window = open_in_new_window;
+
+ attributes = NAUTILUS_FILE_ATTRIBUTE_ACTIVATION_URI;
+ nautilus_file_call_when_ready (view->details->activation_file, attributes,
+ got_activation_uri_callback, view);
+}
+
+static void
+fm_tree_view_open_cb (GtkWidget *menu_item,
+ FMTreeView *view)
+{
+ fm_tree_view_activate_file (view, view->details->popup_file, FALSE);
+}
+
+static void
+fm_tree_view_open_in_new_window_cb (GtkWidget *menu_item,
+ FMTreeView *view)
+{
+ fm_tree_view_activate_file (view, view->details->popup_file, TRUE);
+}
+
+static void
+new_folder_done (const char *new_folder_uri, gpointer data)
+{
+ GList *list;
+
+ /* show the properties window for the newly created
+ * folder so the user can change its name
+ */
+ list = g_list_prepend (NULL, nautilus_file_get (new_folder_uri));
+
+ fm_properties_window_present (list, GTK_WIDGET (data));
+
+ nautilus_file_list_free (list);
+}
+
+static void
+fm_tree_view_create_folder_cb (GtkWidget *menu_item,
+ FMTreeView *view)
+{
+ char *parent_uri;
+
+ parent_uri = nautilus_file_get_uri (view->details->popup_file);
+ nautilus_file_operations_new_folder (GTK_WIDGET (view->details->tree_widget),
+ parent_uri,
+ new_folder_done, view->details->tree_widget);
+
+ g_free (parent_uri);
+}
+
+static void
+get_clipboard_callback (GtkClipboard *clipboard,
+ GtkSelectionData *selection_data,
+ guint info,
+ gpointer user_data_or_owner)
+{
+ char *str = user_data_or_owner;
+
+ gtk_selection_data_set (selection_data,
+ copied_files_atom,
+ 8,
+ str,
+ strlen (str));
+}
+
+static void
+clear_clipboard_callback (GtkClipboard *clipboard,
+ gpointer user_data_or_owner)
+{
+ g_free (user_data_or_owner);
+}
+
+static char *
+convert_file_to_string (NautilusFile *file,
+ gboolean cut)
+{
+ GString *uris;
+ char *uri, *result;
+
+ uris = g_string_new (cut ? "cut" : "copy");
+
+ uri = nautilus_file_get_uri (file);
+ g_string_append_c (uris, '\n');
+ g_string_append (uris, uri);
+ g_free (uri);
+
+ result = uris->str;
+ g_string_free (uris, FALSE);
+
+ return result;
+}
+
+static void
+copy_or_cut_files (FMTreeView *view,
+ gboolean cut)
+{
+ char *status_string, *name;
+ char *clipboard_string;
+
+ clipboard_string = convert_file_to_string (view->details->popup_file, cut);
+
+ gtk_clipboard_set_with_data (get_clipboard (GTK_WIDGET (view->details->tree_widget)),
+ clipboard_targets, G_N_ELEMENTS (clipboard_targets),
+ get_clipboard_callback, clear_clipboard_callback,
+ clipboard_string);
+
+ name = nautilus_file_get_display_name (view->details->popup_file);
+ if (cut) {
+ status_string = g_strdup_printf (_("\"%s\" will be moved "
+ "if you select the Paste Files command"),
+ name);
+ } else {
+ status_string = g_strdup_printf (_("\"%s\" will be copied "
+ "if you select the Paste Files command"),
+ name);
+ }
+ g_free (name);
+
+ nautilus_view_report_status (NAUTILUS_VIEW (view),
+ status_string);
+ g_free (status_string);
+}
+
+static void
+fm_tree_view_cut_cb (GtkWidget *menu_item,
+ FMTreeView *view)
+{
+ copy_or_cut_files (view, TRUE);
+}
+
+static void
+fm_tree_view_copy_cb (GtkWidget *menu_item,
+ FMTreeView *view)
+{
+ copy_or_cut_files (view, FALSE);
+}
+
+static GList *
+convert_lines_to_str_list (char **lines, gboolean *cut)
+{
+ int i;
+ GList *result;
+
+ if (lines[0] == NULL) {
+ return NULL;
+ }
+
+ if (strcmp (lines[0], "cut") == 0) {
+ *cut = TRUE;
+ } else if (strcmp (lines[0], "copy") == 0) {
+ *cut = FALSE;
+ } else {
+ return NULL;
+ }
+
+ result = NULL;
+ for (i = 1; lines[i] != NULL; i++) {
+ result = g_list_prepend (result, g_strdup (lines[i]));
+ }
+ return g_list_reverse (result);
+}
+
+static void
+paste_clipboard_data (FMTreeView *view,
+ GtkSelectionData *selection_data,
+ char *destination_uri)
+{
+ char **lines;
+ gboolean cut;
+ GList *item_uris;
+
+ if (selection_data->type != copied_files_atom
+ || selection_data->length <= 0) {
+ item_uris = NULL;
+ } else {
+ /* Not sure why it's legal to assume there's an extra byte
+ * past the end of the selection data that it's safe to write
+ * to. But gtk_editable_selection_received does this, so I
+ * think it is OK.
+ */
+ selection_data->data[selection_data->length] = '\0';
+ lines = g_strsplit (selection_data->data, "\n", 0);
+ item_uris = convert_lines_to_str_list (lines, &cut);
+ g_strfreev (lines);
+ }
+
+ if (item_uris == NULL|| destination_uri == NULL) {
+ nautilus_view_report_status (NAUTILUS_VIEW (view),
+ _("There is nothing on the clipboard to paste."));
+ } else {
+ nautilus_file_operations_copy_move
+ (item_uris, NULL, destination_uri,
+ cut ? GDK_ACTION_MOVE : GDK_ACTION_COPY,
+ GTK_WIDGET (view->details->tree_widget),
+ NULL, NULL);
+ }
+}
+
+static void
+paste_into_clipboard_received_callback (GtkClipboard *clipboard,
+ GtkSelectionData *selection_data,
+ gpointer data)
+{
+ FMTreeView *view;
+ char *directory_uri;
+
+ view = FM_TREE_VIEW (data);
+
+ directory_uri = nautilus_file_get_uri (view->details->popup_file);
+
+ paste_clipboard_data (view, selection_data, directory_uri);
+
+ g_free (directory_uri);
+}
+
+static void
+fm_tree_view_paste_cb (GtkWidget *menu_item,
+ FMTreeView *view)
+{
+ gtk_clipboard_request_contents (get_clipboard (GTK_WIDGET (view->details->tree_widget)),
+ copied_files_atom,
+ paste_into_clipboard_received_callback, view);
+}
+
+static void
+fm_tree_view_trash_cb (GtkWidget *menu_item,
+ FMTreeView *view)
+{
+ GList *list;
+ char *directory_uri;
+
+ directory_uri = nautilus_file_get_uri (view->details->popup_file);
+
+ if (can_move_uri_to_trash (directory_uri))
+ {
+ list = g_list_prepend (NULL, g_strdup (directory_uri));
+
+ nautilus_file_operations_copy_move (list, NULL,
+ EEL_TRASH_URI, GDK_ACTION_MOVE, GTK_WIDGET (view->details->tree_widget),
+ NULL, NULL);
+ }
+
+ g_free (directory_uri);
+}
+
+static void
+fm_tree_view_properties_cb (GtkWidget *menu_item,
+ FMTreeView *view)
+{
+ GList *list;
+
+ list = g_list_prepend (NULL, nautilus_file_ref (view->details->popup_file));
+
+ fm_properties_window_present (list, GTK_WIDGET (view->details->tree_widget));
+
+ nautilus_file_list_free (list);
+}
+
+static void
+create_popup_menu (FMTreeView *view)
+{
+ GtkWidget *popup, *menu_item, *menu_image, *separator_item;
+
+ popup = gtk_menu_new ();
+
+ /* add the "open" menu item */
+ menu_image = gtk_image_new_from_stock (GTK_STOCK_OPEN,
+ GTK_ICON_SIZE_MENU);
+ gtk_widget_show (menu_image);
+ menu_item = gtk_image_menu_item_new_with_label (_("Open"));
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_item),
+ menu_image);
+ g_signal_connect (menu_item, "activate",
+ G_CALLBACK (fm_tree_view_open_cb),
+ view);
+ gtk_widget_show (menu_item);
+ gtk_menu_shell_append (GTK_MENU_SHELL (popup), menu_item);
+ view->details->popup_open = menu_item;
+
+ /* add the "open in new window" menu item */
+ menu_item = gtk_image_menu_item_new_with_label (_("Open in New Window"));
+ g_signal_connect (menu_item, "activate",
+ G_CALLBACK (fm_tree_view_open_in_new_window_cb),
+ view);
+ gtk_widget_show (menu_item);
+ gtk_menu_shell_append (GTK_MENU_SHELL (popup), menu_item);
+ view->details->popup_open_in_new_window = menu_item;
+
+ separator_item = gtk_separator_menu_item_new ();
+ gtk_widget_show (separator_item);
+ gtk_menu_shell_append (GTK_MENU_SHELL (popup), separator_item);
+
+ /* add the "create folder" menu item */
+ menu_item = gtk_image_menu_item_new_with_label (_("Create Folder"));
+ g_signal_connect (menu_item, "activate",
+ G_CALLBACK (fm_tree_view_create_folder_cb),
+ view);
+ gtk_widget_show (menu_item);
+ gtk_menu_shell_append (GTK_MENU_SHELL (popup), menu_item);
+ view->details->popup_create_folder = menu_item;
+
+ separator_item = gtk_separator_menu_item_new ();
+ gtk_widget_show (separator_item);
+ gtk_menu_shell_append (GTK_MENU_SHELL (popup), separator_item);
+
+ /* add the "cut folder" menu item */
+ menu_image = gtk_image_new_from_stock (GTK_STOCK_CUT,
+ GTK_ICON_SIZE_MENU);
+ gtk_widget_show (menu_image);
+ menu_item = gtk_image_menu_item_new_with_label (_("Cut Folder"));
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_item),
+ menu_image);
+ g_signal_connect (menu_item, "activate",
+ G_CALLBACK (fm_tree_view_cut_cb),
+ view);
+ gtk_widget_show (menu_item);
+ gtk_menu_shell_append (GTK_MENU_SHELL (popup), menu_item);
+ view->details->popup_cut = menu_item;
+
+ /* add the "copy folder" menu item */
+ menu_image = gtk_image_new_from_stock (GTK_STOCK_COPY,
+ GTK_ICON_SIZE_MENU);
+ gtk_widget_show (menu_image);
+ menu_item = gtk_image_menu_item_new_with_label (_("Copy Folder"));
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_item),
+ menu_image);
+ g_signal_connect (menu_item, "activate",
+ G_CALLBACK (fm_tree_view_copy_cb),
+ view);
+ gtk_widget_show (menu_item);
+ gtk_menu_shell_append (GTK_MENU_SHELL (popup), menu_item);
+ view->details->popup_copy = menu_item;
+
+ /* add the "paste files into folder" menu item */
+ menu_image = gtk_image_new_from_stock (GTK_STOCK_PASTE,
+ GTK_ICON_SIZE_MENU);
+ gtk_widget_show (menu_image);
+ menu_item = gtk_image_menu_item_new_with_label (_("Paste Files into Folder"));
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_item),
+ menu_image);
+ g_signal_connect (menu_item, "activate",
+ G_CALLBACK (fm_tree_view_paste_cb),
+ view);
+ gtk_widget_show (menu_item);
+ gtk_menu_shell_append (GTK_MENU_SHELL (popup), menu_item);
+ view->details->popup_paste = menu_item;
+
+ separator_item = gtk_separator_menu_item_new ();
+ gtk_widget_show (separator_item);
+ gtk_menu_shell_append (GTK_MENU_SHELL (popup), separator_item);
+
+ /* add the "move to trash" menu item */
+ menu_image = gtk_image_new_from_stock (GTK_STOCK_DELETE,
+ GTK_ICON_SIZE_MENU);
+ gtk_widget_show (menu_image);
+ menu_item = gtk_image_menu_item_new_with_label (_("Move to Trash"));
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_item),
+ menu_image);
+ g_signal_connect (menu_item, "activate",
+ G_CALLBACK (fm_tree_view_trash_cb),
+ view);
+ gtk_widget_show (menu_item);
+ gtk_menu_shell_append (GTK_MENU_SHELL (popup), menu_item);
+ view->details->popup_trash = menu_item;
+
+ separator_item = gtk_separator_menu_item_new ();
+ gtk_widget_show (separator_item);
+ gtk_menu_shell_append (GTK_MENU_SHELL (popup), separator_item);
+
+ /* add the "properties" menu item */
+ menu_image = gtk_image_new_from_stock (GTK_STOCK_PROPERTIES,
+ GTK_ICON_SIZE_MENU);
+ gtk_widget_show (menu_image);
+ menu_item = gtk_image_menu_item_new_with_label (_("Properties"));
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_item),
+ menu_image);
+ g_signal_connect (menu_item, "activate",
+ G_CALLBACK (fm_tree_view_properties_cb),
+ view);
+ gtk_widget_show (menu_item);
+ gtk_menu_shell_append (GTK_MENU_SHELL (popup), menu_item);
+ view->details->popup_properties = menu_item;
+
+ view->details->popup = popup;
+}
+
+static void
+create_tree (FMTreeView *view)
+{
+ GtkCellRenderer *cell;
+ GtkTreeViewColumn *column;
+ GnomeVFSVolumeMonitor *volume_monitor;
+ char *home_uri;
+ GList *volumes, *l;
+
+ view->details->child_model = fm_tree_model_new ();
+ view->details->sort_model = GTK_TREE_MODEL_SORT
+ (gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (view->details->child_model)));
+ view->details->tree_widget = GTK_TREE_VIEW
+ (gtk_tree_view_new_with_model (GTK_TREE_MODEL (view->details->sort_model)));
+ g_object_unref (view->details->sort_model);
+ g_signal_connect_object
+ (view->details->child_model, "row_loaded",
+ G_CALLBACK (row_loaded_callback),
+ view, G_CONNECT_AFTER);
+ home_uri = gnome_vfs_get_uri_from_local_path (g_get_home_dir ());
+ fm_tree_model_add_root_uri (view->details->child_model, home_uri, _("Home Folder"), "gnome-home");
+ g_free (home_uri);
+ fm_tree_model_add_root_uri (view->details->child_model, "file:///", _("Filesystem"), "gnome-folder");
+#ifdef NOT_YET_USABLE
+ fm_tree_model_add_root_uri (view->details->child_model, "network:///", _("Network Neighbourhood"), "gnome-fs-network");
+#endif
+
+ volume_monitor = gnome_vfs_get_volume_monitor ();
+ volumes = gnome_vfs_volume_monitor_get_mounted_volumes (volume_monitor);
+ for (l = volumes; l != NULL; l = l->next) {
+ add_root_for_volume (view, l->data);
+ gnome_vfs_volume_unref (l->data);
+ }
+ g_list_free (volumes);
+
+ g_signal_connect_object (volume_monitor, "volume_mounted",
+ G_CALLBACK (volume_mounted_callback), view, 0);
+ g_signal_connect_object (volume_monitor, "volume_unmounted",
+ G_CALLBACK (volume_unmounted_callback), view, 0);
+
+ g_object_unref (view->details->child_model);
+
+ gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (view->details->sort_model),
+ compare_rows, view, NULL);
+
+ gtk_tree_view_set_headers_visible (view->details->tree_widget, FALSE);
+
+ view->details->drag_dest =
+ nautilus_tree_view_drag_dest_new (view->details->tree_widget);
+ g_signal_connect_object (view->details->drag_dest,
+ "get_root_uri",
+ G_CALLBACK (get_root_uri_callback),
+ view, 0);
+ g_signal_connect_object (view->details->drag_dest,
+ "get_file_for_path",
+ G_CALLBACK (get_file_for_path_callback),
+ view, 0);
+ g_signal_connect_object (view->details->drag_dest,
+ "move_copy_items",
+ G_CALLBACK (move_copy_items_callback),
+ view, 0);
+
+ /* Create column */
+ column = gtk_tree_view_column_new ();
+
+ cell = gtk_cell_renderer_pixbuf_new ();
+ gtk_tree_view_column_pack_start (column, cell, FALSE);
+ gtk_tree_view_column_set_attributes (column, cell,
+ "pixbuf", FM_TREE_MODEL_CLOSED_PIXBUF_COLUMN,
+ "pixbuf_expander_closed", FM_TREE_MODEL_CLOSED_PIXBUF_COLUMN,
+ "pixbuf_expander_open", FM_TREE_MODEL_OPEN_PIXBUF_COLUMN,
+ NULL);
+
+ cell = gtk_cell_renderer_text_new ();
+ gtk_tree_view_column_pack_start (column, cell, TRUE);
+ gtk_tree_view_column_set_attributes (column, cell,
+ "text", FM_TREE_MODEL_DISPLAY_NAME_COLUMN,
+ "style", FM_TREE_MODEL_FONT_STYLE_COLUMN,
+ "weight", FM_TREE_MODEL_FONT_WEIGHT_COLUMN,
+ NULL);
+
+ gtk_tree_view_append_column (view->details->tree_widget, column);
+
+ gtk_widget_show (GTK_WIDGET (view->details->tree_widget));
+
+ gtk_container_add (GTK_CONTAINER (view->details->scrolled_window),
+ GTK_WIDGET (view->details->tree_widget));
+
+ g_signal_connect_object (gtk_tree_view_get_selection (GTK_TREE_VIEW (view->details->tree_widget)), "changed",
+ G_CALLBACK (selection_changed_callback), view, 0);
+
+ g_signal_connect (G_OBJECT (view->details->tree_widget),
+ "row-activated", G_CALLBACK (row_activated_callback),
+ view);
+
+ g_signal_connect (G_OBJECT (view->details->tree_widget),
+ "button_press_event", G_CALLBACK (button_pressed_callback),
+ view);
+
+ schedule_show_selection (view);
+}
+
+static void
+update_filtering_from_preferences (FMTreeView *view)
+{
+ if (view->details->child_model == NULL) {
+ return;
+ }
+
+ fm_tree_model_set_show_hidden_files
+ (view->details->child_model,
+ eel_preferences_get_boolean (NAUTILUS_PREFERENCES_SHOW_HIDDEN_FILES));
+ fm_tree_model_set_show_backup_files
+ (view->details->child_model,
+ eel_preferences_get_boolean (NAUTILUS_PREFERENCES_SHOW_BACKUP_FILES));
+ fm_tree_model_set_show_only_directories
+ (view->details->child_model,
+ eel_preferences_get_boolean (NAUTILUS_PREFERENCES_TREE_SHOW_ONLY_DIRECTORIES));
+}
+
+static void
+tree_activate_callback (BonoboControl *control, gboolean activating, gpointer user_data)
+{
+ FMTreeView *view;
+
+ view = FM_TREE_VIEW (user_data);
+
+ if (activating && view->details->tree_widget == NULL) {
+ create_tree (view);
+ update_filtering_from_preferences (view);
+ }
+}
+
+static void
+filtering_changed_callback (gpointer callback_data)
+{
+ update_filtering_from_preferences (FM_TREE_VIEW (callback_data));
+}
+
+static void
+load_location_callback (FMTreeView *view, char *location)
+{
+ if (view->details->selection_location != NULL) {
+ g_free (view->details->selection_location);
+ }
+ view->details->selection_location = g_strdup (location);
+
+ schedule_show_selection (view);
+}
+
+static void
+fm_tree_view_instance_init (FMTreeView *view)
+{
+ BonoboControl *control;
+
+ view->details = g_new0 (FMTreeViewDetails, 1);
+
+ view->details->scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (view->details->scrolled_window),
+ GTK_POLICY_AUTOMATIC,
+ GTK_POLICY_AUTOMATIC);
+
+ gtk_widget_show (view->details->scrolled_window);
+
+ control = bonobo_control_new (view->details->scrolled_window);
+ g_signal_connect_object (control, "activate",
+ G_CALLBACK (tree_activate_callback), view, 0);
+
+ nautilus_view_construct_from_bonobo_control (NAUTILUS_VIEW (view), control);
+
+ view->details->selection_location = NULL;
+ g_signal_connect_object (view, "load_location",
+ G_CALLBACK (load_location_callback), view, 0);
+ view->details->selecting = FALSE;
+
+ eel_preferences_add_callback (NAUTILUS_PREFERENCES_SHOW_HIDDEN_FILES,
+ filtering_changed_callback, view);
+ eel_preferences_add_callback (NAUTILUS_PREFERENCES_SHOW_BACKUP_FILES,
+ filtering_changed_callback, view);
+ eel_preferences_add_callback (NAUTILUS_PREFERENCES_TREE_SHOW_ONLY_DIRECTORIES,
+ filtering_changed_callback, view);
+
+ g_signal_connect_object (nautilus_icon_factory_get(), "icons_changed",
+ G_CALLBACK (theme_changed_callback), view, 0);
+
+ view->details->popup_file = NULL;
+ create_popup_menu (view);
+}
+
+static void
+fm_tree_view_dispose (GObject *object)
+{
+ FMTreeView *view;
+
+ view = FM_TREE_VIEW (object);
+
+ if (view->details->drag_dest) {
+ g_object_unref (view->details->drag_dest);
+ view->details->drag_dest = NULL;
+ }
+
+ if (view->details->show_selection_idle_id) {
+ g_source_remove (view->details->show_selection_idle_id);
+ view->details->show_selection_idle_id = 0;
+ }
+
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+fm_tree_view_finalize (GObject *object)
+{
+ FMTreeView *view;
+
+ view = FM_TREE_VIEW (object);
+
+ eel_preferences_remove_callback (NAUTILUS_PREFERENCES_SHOW_HIDDEN_FILES,
+ filtering_changed_callback, view);
+ eel_preferences_remove_callback (NAUTILUS_PREFERENCES_SHOW_BACKUP_FILES,
+ filtering_changed_callback, view);
+ eel_preferences_remove_callback (NAUTILUS_PREFERENCES_TREE_SHOW_ONLY_DIRECTORIES,
+ filtering_changed_callback, view);
+
+ cancel_activation (view);
+
+ if (view->details->selection_location != NULL) {
+ g_free (view->details->selection_location);
+ }
+
+ g_free (view->details);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+fm_tree_view_class_init (FMTreeViewClass *class)
+{
+ G_OBJECT_CLASS (class)->dispose = fm_tree_view_dispose;
+ G_OBJECT_CLASS (class)->finalize = fm_tree_view_finalize;
+
+ copied_files_atom = gdk_atom_intern ("x-special/gnome-copied-files", FALSE);
+}
diff --git a/src/file-manager/fm-tree-view.h b/src/file-manager/fm-tree-view.h
new file mode 100644
index 000000000..31ec9da54
--- /dev/null
+++ b/src/file-manager/fm-tree-view.h
@@ -0,0 +1,53 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+
+/*
+ * Copyright (C) 2000, 2001 Eazel, Inc
+ * Copyright (C) 2002 Anders Carlsson
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors: Maciej Stachowiak <mjs@eazel.com>
+ * Anders Carlsson <andersca@gnu.org>
+ */
+
+/* fm-tree-view.h - tree view. */
+
+
+#ifndef FM_TREE_VIEW_H
+#define FM_TREE_VIEW_H
+
+#include <libnautilus/nautilus-view.h>
+
+#define FM_TYPE_TREE_VIEW (fm_tree_view_get_type ())
+#define FM_TREE_VIEW(obj) (GTK_CHECK_CAST ((obj), FM_TYPE_TREE_VIEW, FMTreeView))
+#define FM_TREE_VIEW_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), FM_TYPE_TREE_VIEW, FMTreeViewClass))
+#define FM_IS_TREE_VIEW(obj) (GTK_CHECK_TYPE ((obj), FM_TYPE_TREE_VIEW))
+#define FM_IS_TREE_VIEW_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), FM_TYPE_TREE_VIEW))
+
+typedef struct FMTreeViewDetails FMTreeViewDetails;
+
+typedef struct {
+ NautilusView parent;
+ FMTreeViewDetails *details;
+} FMTreeView;
+
+typedef struct {
+ NautilusViewClass parent_class;
+} FMTreeViewClass;
+
+GType fm_tree_view_get_type (void);
+
+#endif /* FM_TREE_VIEW_H */
diff --git a/src/file-manager/nautilus-directory-view-ui.xml b/src/file-manager/nautilus-directory-view-ui.xml
index 58f8c20ad..dbceac809 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"/>
@@ -92,6 +95,7 @@
<accel name="Delete" verb="Trash"/>
<accel name="*Shift*KP_Delete" verb="Delete"/>
<accel name="*Alt*Down" verb="Open"/>
+ <accel name="*Alt**Shift*Down" verb="OpenCloseParent"/>
</keybindings>
<menu>
<submenu name="File">
@@ -100,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"/>
@@ -210,6 +224,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/file-manager/nautilus-indexing-info.c b/src/file-manager/nautilus-indexing-info.c
index f570856a3..85e445e12 100644
--- a/src/file-manager/nautilus-indexing-info.c
+++ b/src/file-manager/nautilus-indexing-info.c
@@ -161,23 +161,18 @@ last_index_time_dialog_new (void)
GtkWidget *label;
GtkDialog *dialog;
- dialog = eel_create_info_dialog (_("Once a day your files and text content are indexed so "
+ time_str = nautilus_indexing_info_get_last_index_time ();
+ label_str = g_strdup_printf (_("Your files were last indexed at %s."),
+ time_str);
+ g_free (time_str);
+
+ dialog = eel_create_info_dialog (label_str,
+ _("Once a day your files and text content are indexed so "
"your searches are fast. "),
_("Indexing Status"),
NULL);
set_close_hides_for_dialog (dialog);
- time_str = nautilus_indexing_info_get_last_index_time ();
- label_str = g_strdup_printf (_("Your files were last indexed at %s"),
- time_str);
- g_free (time_str);
-
- label = gtk_label_new (label_str);
- gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
- eel_gtk_label_make_bold (GTK_LABEL (label));
- gtk_box_pack_start (GTK_BOX (dialog->vbox), label,
- FALSE, FALSE, 0);
-
return dialog;
}
@@ -199,8 +194,9 @@ index_progress_dialog_new (void)
ProgressChangeData *progress_data;
guint timeout_id;
- dialog = eel_create_info_dialog (_("Once a day your files and text content are indexed so "
- "your searches are fast. Your files are currently being indexed."),
+ dialog = eel_create_info_dialog (_("Your files are currently being indexed."),
+ _("Once a day your files and text content are indexed so "
+ "your searches are fast."),
_("Indexing Status"), NULL);
set_close_hides_for_dialog (dialog);
percentage_complete = get_index_percentage_complete ();
@@ -258,11 +254,12 @@ show_indexing_info_dialog (void)
if (!medusa_system_services_are_enabled ()) {
details_string = nautilus_medusa_get_explanation_of_enabling ();
- dialog_shown = eel_show_info_dialog_with_details (_("When Fast Search is enabled, Find creates an "
+ dialog_shown = eel_show_info_dialog_with_details (_("There is no index of your files right now."),
+ _("When Fast Search is enabled, Find creates an "
"index to speed up searches. Fast searching "
"is not enabled on your computer, so you "
"do not have an index right now."),
- _("There is no index of your files right now."),
+ _("No Index of Files"),
details_string,
NULL);
g_free (details_string);
@@ -300,6 +297,7 @@ static void
show_search_service_not_available_dialog (void)
{
eel_show_error_dialog (_("Sorry, but the medusa search service is not available."),
+ _("Please verify medusa has been setup correctly."),
_("Search Service Not Available"),
NULL);
}
diff --git a/src/nautilus-application.c b/src/nautilus-application.c
index bdae8db1c..a5df8da7e 100644
--- a/src/nautilus-application.c
+++ b/src/nautilus-application.c
@@ -34,6 +34,7 @@
#include "file-manager/fm-icon-view.h"
#include "file-manager/fm-list-view.h"
#include "file-manager/fm-search-list-view.h"
+#include "file-manager/fm-tree-view.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
@@ -86,6 +87,7 @@
#define FACTORY_IID "OAFIID:Nautilus_Factory"
#define SEARCH_LIST_VIEW_IID "OAFIID:Nautilus_File_Manager_Search_List_View"
#define SHELL_IID "OAFIID:Nautilus_Shell"
+#define TREE_VIEW_IID "OAFIID:Nautilus_File_Manager_Tree_View"
/* Keeps track of all the desktop windows. */
static GList *nautilus_application_desktop_windows;
@@ -138,6 +140,8 @@ create_object (PortableServer_Servant servant,
object = BONOBO_OBJECT (nautilus_shell_new (application));
} else if (strcmp (iid, METAFILE_FACTORY_IID) == 0) {
object = BONOBO_OBJECT (nautilus_metafile_factory_get_instance ());
+ } else if (strcmp (iid, TREE_VIEW_IID) == 0) {
+ object = BONOBO_OBJECT (g_object_new (fm_tree_view_get_type (), NULL));
} else {
object = CORBA_OBJECT_NIL;
}
@@ -184,6 +188,7 @@ nautilus_application_instance_init (NautilusApplication *application)
nautilus_bonobo_register_activation_shortcut (NAUTILUS_DESKTOP_ICON_VIEW_IID, create_object_shortcut, application);
nautilus_bonobo_register_activation_shortcut (NAUTILUS_LIST_VIEW_IID, create_object_shortcut, application);
nautilus_bonobo_register_activation_shortcut (SEARCH_LIST_VIEW_IID, create_object_shortcut, application);
+ nautilus_bonobo_register_activation_shortcut (TREE_VIEW_IID, create_object_shortcut, application);
}
NautilusApplication *
@@ -211,6 +216,7 @@ nautilus_application_destroy (BonoboObject *object)
nautilus_bonobo_unregister_activation_shortcut (NAUTILUS_DESKTOP_ICON_VIEW_IID);
nautilus_bonobo_unregister_activation_shortcut (NAUTILUS_LIST_VIEW_IID);
nautilus_bonobo_unregister_activation_shortcut (SEARCH_LIST_VIEW_IID);
+ nautilus_bonobo_unregister_activation_shortcut (TREE_VIEW_IID);
nautilus_bookmarks_exiting ();
@@ -227,6 +233,7 @@ check_required_directories (NautilusApplication *application)
EelStringList *directories;
char *directories_as_string;
char *error_string;
+ char *detail_string;
char *dialog_title;
GtkDialog *dialog;
int failed_count;
@@ -251,30 +258,28 @@ check_required_directories (NautilusApplication *application)
failed_count = eel_string_list_get_length (directories);
if (failed_count != 0) {
- directories_as_string = eel_string_list_as_string (directories, "\n", EEL_STRING_LIST_ALL_STRINGS);
+ directories_as_string = eel_string_list_as_string (directories, ", ", EEL_STRING_LIST_ALL_STRINGS);
if (failed_count == 1) {
- dialog_title = g_strdup (_("Couldn't Create Required Folder"));
- error_string = g_strdup_printf (_("Nautilus could not create the required folder \"%s\". "
- "Before running Nautilus, please create this folder, or "
- "set permissions such that Nautilus can create it."),
+ dialog_title = _("Couldn't Create Required Folder");
+ error_string = g_strdup_printf (_("Nautilus could not create the required folder \"%s\"."),
directories_as_string);
+ detail_string = _("Before running Nautilus, please create the following folder, or "
+ "set permissions such that Nautilus can create it.");
} else {
- dialog_title = g_strdup (_("Couldn't Create Required Folders"));
- error_string = g_strdup_printf (_("Nautilus could not create the following required folders:\n\n"
- "%s\n\n"
- "Before running Nautilus, please create these folders, or "
- "set permissions such that Nautilus can create them."),
- directories_as_string);
+ dialog_title = _("Couldn't Create Required Folders");
+ error_string = g_strdup_printf (_("Nautilus could not create the following required folders: "
+ "%s."), directories_as_string);
+ detail_string = _("Before running Nautilus, please create these folders, or "
+ "set permissions such that Nautilus can create them.");
}
- dialog = eel_show_error_dialog (error_string, dialog_title, NULL);
+ dialog = eel_show_error_dialog (error_string, detail_string, dialog_title, NULL);
/* We need the main event loop so the user has a chance to see the dialog. */
nautilus_main_event_loop_register (GTK_OBJECT (dialog));
g_free (directories_as_string);
g_free (error_string);
- g_free (dialog_title);
}
eel_string_list_free (directories);
@@ -349,10 +354,10 @@ migrate_old_nautilus_files (void)
close (fd);
}
- eel_show_info_dialog (_("The location of the desktop directory has changed in GNOME 2.4. "
- "A link called \"Link To Old Desktop\" has been created on the desktop. "
- "You can open this to move over the files you want, then delete the link."),
- _("Migrated old desktop"),
+ eel_show_info_dialog (_("A link called \"Link To Old Desktop\" has been created on the desktop."),
+ _("The location of the desktop directory has changed in GNOME 2.4. "
+ "You can open the link and move over the files you want, then delete the link."),
+ _("Migrated Old Desktop"),
NULL);
}
g_free (old_desktop_dir);
@@ -597,7 +602,7 @@ nautilus_application_startup (NautilusApplication *application,
}
if (message != NULL) {
- dialog = eel_show_error_dialog_with_details (message, NULL, detailed_message, NULL);
+ dialog = eel_show_error_dialog_with_details (message, NULL, NULL, detailed_message, NULL);
/* We need the main event loop so the user has a chance to see the dialog. */
nautilus_main_event_loop_register (GTK_OBJECT (dialog));
goto out;
@@ -886,20 +891,20 @@ find_parent_spatial_window (NautilusSpatialWindow *window)
}
void
-nautilus_application_close_with_parent_windows (NautilusSpatialWindow *window)
+nautilus_application_close_parent_windows (NautilusSpatialWindow *window)
{
NautilusSpatialWindow *parent_window;
+ NautilusSpatialWindow *new_parent_window;
g_return_if_fail (NAUTILUS_IS_SPATIAL_WINDOW (window));
parent_window = find_parent_spatial_window (window);
- nautilus_window_close (NAUTILUS_WINDOW (window));
- window = parent_window;
while (parent_window) {
- parent_window = find_parent_spatial_window (window);
- nautilus_window_close (NAUTILUS_WINDOW (window));
- window = parent_window;
+
+ new_parent_window = find_parent_spatial_window (parent_window);
+ nautilus_window_close (NAUTILUS_WINDOW (parent_window));
+ parent_window = new_parent_window;
}
}
diff --git a/src/nautilus-application.h b/src/nautilus-application.h
index 6b43d2d0e..84e16333e 100644
--- a/src/nautilus-application.h
+++ b/src/nautilus-application.h
@@ -78,7 +78,7 @@ NautilusWindow * nautilus_application_present_spatial_window (NautilusAp
NautilusWindow * nautilus_application_create_navigation_window (NautilusApplication *application,
GdkScreen *screen);
void nautilus_application_close_all_navigation_windows (void);
-void nautilus_application_close_with_parent_windows (NautilusSpatialWindow *window);
+void nautilus_application_close_parent_windows (NautilusSpatialWindow *window);
void nautilus_application_open_desktop (NautilusApplication *application);
void nautilus_application_close_desktop (void);
diff --git a/src/nautilus-connect-server-dialog.c b/src/nautilus-connect-server-dialog.c
index 763fdce28..4a8d611fa 100644
--- a/src/nautilus-connect-server-dialog.c
+++ b/src/nautilus-connect-server-dialog.c
@@ -46,8 +46,7 @@ EEL_CLASS_BOILERPLATE (NautilusConnectServerDialog,
nautilus_connect_server_dialog,
GTK_TYPE_DIALOG)
enum {
- RESPONSE_CONNECT,
- RESPONSE_CANCEL
+ RESPONSE_CONNECT
};
static void
@@ -84,7 +83,9 @@ connect_to_server (NautilusConnectServerDialog *dialog)
name = gtk_editable_get_chars (GTK_EDITABLE (dialog->details->name_entry), 0, -1);
if (strlen (name) == 0) {
- eel_show_error_dialog (_("You must enter a name for the server"), _("Can't connect to server"), GTK_WINDOW (dialog));
+ eel_show_error_dialog (_("You must enter a name for the server."),
+ _("Please enter a name and try again."),
+ _("Can't Connect to Server"), GTK_WINDOW (dialog));
g_free (name);
return;
}
@@ -97,9 +98,10 @@ connect_to_server (NautilusConnectServerDialog *dialog)
if (vfs_uri == NULL) {
error_message = g_strdup_printf
- (_("\"%s\" is not a valid location. Please check the spelling and try again."),
+ (_("\"%s\" is not a valid location."),
uri);
- eel_show_error_dialog (error_message, _("Can't connect to server"), GTK_WINDOW (dialog));
+ eel_show_error_dialog (error_message, _("Please check the spelling and try again."),
+ _("Can't Connect to Server"), GTK_WINDOW (dialog));
g_free (error_message);
} else {
gnome_vfs_uri_unref (vfs_uri);
@@ -132,7 +134,7 @@ response_callback (NautilusConnectServerDialog *dialog,
break;
case GTK_RESPONSE_NONE:
case GTK_RESPONSE_DELETE_EVENT:
- case RESPONSE_CANCEL:
+ case GTK_RESPONSE_CANCEL:
gtk_widget_destroy (GTK_WIDGET (dialog));
break;
default :
@@ -174,15 +176,19 @@ nautilus_connect_server_dialog_init (NautilusConnectServerDialog *dialog)
gtk_window_set_title (GTK_WINDOW (dialog), _("Connect to Server"));
gtk_window_set_default_size (GTK_WINDOW (dialog), 300, -1);
gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
+ gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
+ gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->vbox), 2);
table = gtk_table_new (2, 2, FALSE);
+ gtk_container_set_border_width (GTK_CONTAINER (table), 5);
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox),
- table, TRUE, TRUE, 12);
+ table, TRUE, TRUE, 0);
gtk_table_set_row_spacings (GTK_TABLE (table), 6);
- gtk_table_set_col_spacings (GTK_TABLE (table), 6);
+ gtk_table_set_col_spacings (GTK_TABLE (table), 12);
gtk_widget_show (table);
label = gtk_label_new_with_mnemonic (_("_Name:"));
+ gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
gtk_widget_show (label);
gtk_table_attach (GTK_TABLE (table), label,
0, 1,
@@ -201,6 +207,7 @@ nautilus_connect_server_dialog_init (NautilusConnectServerDialog *dialog)
label = gtk_label_new_with_mnemonic (_("_Location:"));
+ gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
gtk_widget_show (label);
gtk_table_attach (GTK_TABLE (table), label,
0, 1,
@@ -223,9 +230,9 @@ nautilus_connect_server_dialog_init (NautilusConnectServerDialog *dialog)
gtk_dialog_add_button (GTK_DIALOG (dialog),
GTK_STOCK_CANCEL,
- RESPONSE_CANCEL);
+ GTK_RESPONSE_CANCEL);
gtk_dialog_add_button (GTK_DIALOG (dialog),
- _("Connect"),
+ _("C_onnect"),
RESPONSE_CONNECT);
gtk_dialog_set_default_response (GTK_DIALOG (dialog),
RESPONSE_CONNECT);
diff --git a/src/nautilus-information-panel.c b/src/nautilus-information-panel.c
index b599150c8..4826bcf41 100644
--- a/src/nautilus-information-panel.c
+++ b/src/nautilus-information-panel.c
@@ -503,8 +503,8 @@ receive_dropped_uri_list (NautilusInformationPanel *information_panel,
if (!exactly_one) {
eel_show_error_dialog (
- _("You can't assign more than one custom icon at a time! "
- "Please drag just one image to set a custom icon."),
+ _("You can't assign more than one custom icon at a time."),
+ _("Please drag just one image to set a custom icon."),
_("More Than One Image"),
window);
break;
@@ -524,15 +524,15 @@ receive_dropped_uri_list (NautilusInformationPanel *information_panel,
} else {
if (eel_is_remote_uri (uris[0])) {
eel_show_error_dialog (
- _("The file that you dropped is not local. "
- "You can only use local images as custom icons."),
+ _("The file that you dropped is not local."),
+ _("You can only use local images as custom icons."),
_("Local Images Only"),
window);
} else {
eel_show_error_dialog (
- _("The file that you dropped is not an image. "
- "You can only use local images as custom icons."),
+ _("The file that you dropped is not an image."),
+ _("You can only use images as custom icons."),
_("Images Only"),
window);
}
@@ -982,7 +982,6 @@ burn_cd_callback (GtkWidget *button, gpointer data)
{
GError *error;
char *argv[] = { "nautilus-cd-burner", NULL};
- char *text;
error = NULL;
if (!g_spawn_async (NULL,
@@ -991,11 +990,9 @@ burn_cd_callback (GtkWidget *button, gpointer data)
NULL, NULL,
NULL,
&error)) {
- text = g_strdup_printf (_("Unable to launch the cd burner application:\n%s"), error->message);
- eel_show_error_dialog (text,
- _("Can't launch cd burner"),
+ eel_show_error_dialog (_("Unable to launch the cd burner application."), error->message,
+ _("Can't Launch CD Burner"),
GTK_WINDOW (gtk_widget_get_toplevel (button)));
- g_free (text);
g_error_free (error);
}
}
diff --git a/src/nautilus-location-bar.c b/src/nautilus-location-bar.c
index fd4092dfd..12fe82b23 100644
--- a/src/nautilus-location-bar.c
+++ b/src/nautilus-location-bar.c
@@ -39,7 +39,6 @@
#include <eel/eel-accessibility.h>
#include <eel/eel-glib-extensions.h>
#include <eel/eel-gtk-macros.h>
-#include <eel/eel-input-event-box.h>
#include <eel/eel-stock-dialogs.h>
#include <eel/eel-string.h>
#include <eel/eel-vfs-extensions.h>
@@ -130,6 +129,7 @@ drag_data_received_callback (GtkWidget *widget,
GdkScreen *screen;
gboolean new_windows_for_extras;
char *prompt;
+ char *detail;
g_assert (NAUTILUS_IS_LOCATION_BAR (widget));
g_assert (data != NULL);
@@ -151,20 +151,24 @@ drag_data_received_callback (GtkWidget *widget,
*/
name_count = g_list_length (names);
if (name_count > 1) {
- prompt = g_strdup_printf (_("Do you want to view these %d locations "
- "in separate windows?"),
- name_count);
+ prompt = g_strdup_printf (_("Do you want to view %d locations?"),
+ name_count);
+ detail = g_strdup_printf (_("This will open %d separate windows."),
+ name_count);
/* eel_run_simple_dialog should really take in pairs
* like gtk_dialog_new_with_buttons() does. */
new_windows_for_extras = eel_run_simple_dialog
(GTK_WIDGET (window),
TRUE,
+ GTK_MESSAGE_QUESTION,
prompt,
+ detail,
_("View in Multiple Windows?"),
- GTK_STOCK_OK, GTK_STOCK_CANCEL,
- NULL) == 0 /* GNOME_OK */;
+ GTK_STOCK_CANCEL, GTK_STOCK_OK,
+ NULL) != 0 /* GNOME_OK */;
g_free (prompt);
+ g_free (detail);
if (!new_windows_for_extras) {
gtk_drag_finish (context, FALSE, FALSE, time);
@@ -365,7 +369,9 @@ nautilus_location_bar_init (NautilusLocationBar *bar)
hbox = gtk_hbox_new (0, FALSE);
- event_box = eel_input_event_box_new ();
+ event_box = gtk_event_box_new ();
+ gtk_event_box_set_visible_window (GTK_EVENT_BOX (event_box), FALSE);
+
gtk_container_set_border_width (GTK_CONTAINER (event_box),
GNOME_PAD_SMALL);
label = gtk_label_new (LOCATION_LABEL);
diff --git a/src/nautilus-location-dialog.c b/src/nautilus-location-dialog.c
index ebbe30f6f..c88755781 100644
--- a/src/nautilus-location-dialog.c
+++ b/src/nautilus-location-dialog.c
@@ -43,8 +43,7 @@ EEL_CLASS_BOILERPLATE (NautilusLocationDialog,
nautilus_location_dialog,
GTK_TYPE_DIALOG)
enum {
- RESPONSE_OPEN,
- RESPONSE_CANCEL
+ RESPONSE_OPEN
};
static void
@@ -96,7 +95,7 @@ response_callback (NautilusLocationDialog *dialog,
break;
case GTK_RESPONSE_NONE :
case GTK_RESPONSE_DELETE_EVENT :
- case RESPONSE_CANCEL :
+ case GTK_RESPONSE_CANCEL :
gtk_widget_destroy (GTK_WIDGET (dialog));
break;
default :
@@ -138,13 +137,16 @@ nautilus_location_dialog_init (NautilusLocationDialog *dialog)
gtk_window_set_title (GTK_WINDOW (dialog), _("Open Location"));
gtk_window_set_default_size (GTK_WINDOW (dialog), 300, -1);
gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
+ gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
+ gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->vbox), 2);
- box = gtk_hbox_new (FALSE, 6);
+ box = gtk_hbox_new (FALSE, 12);
+ gtk_container_set_border_width (GTK_CONTAINER (box), 5);
gtk_widget_show (box);
- label = gtk_label_new (_("Location:"));
+ label = gtk_label_new_with_mnemonic (_("_Location:"));
gtk_widget_show (label);
- gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 6);
+ gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 0);
dialog->details->entry = nautilus_location_entry_new ();
g_signal_connect (dialog->details->entry,
@@ -155,14 +157,14 @@ nautilus_location_dialog_init (NautilusLocationDialog *dialog)
gtk_widget_show (dialog->details->entry);
gtk_box_pack_start (GTK_BOX (box), dialog->details->entry,
- TRUE, TRUE, 6);
+ TRUE, TRUE, 0);
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox),
- box, TRUE, TRUE, 12);
+ box, TRUE, TRUE, 0);
gtk_dialog_add_button (GTK_DIALOG (dialog),
GTK_STOCK_CANCEL,
- RESPONSE_CANCEL);
+ GTK_RESPONSE_CANCEL);
gtk_dialog_add_button (GTK_DIALOG (dialog),
GTK_STOCK_OPEN,
RESPONSE_OPEN);
diff --git a/src/nautilus-location-entry.c b/src/nautilus-location-entry.c
index 623f2fa99..f7e4a4463 100644
--- a/src/nautilus-location-entry.c
+++ b/src/nautilus-location-entry.c
@@ -39,7 +39,6 @@
#include <eel/eel-gtk-macros.h>
#include <eel/eel-stock-dialogs.h>
#include <eel/eel-string.h>
-#include <eel/eel-input-event-box.h>
#include <eel/eel-vfs-extensions.h>
#include <gtk/gtkdnd.h>
#include <gtk/gtksignal.h>
diff --git a/src/nautilus-main.c b/src/nautilus-main.c
index 69c2d4a79..374a03a02 100644
--- a/src/nautilus-main.c
+++ b/src/nautilus-main.c
@@ -130,22 +130,23 @@ nautilus_main_event_loop_quit (void)
static void
register_icons (void)
{
- GnomeIconTheme *icon_theme;
- char *icon;
+ GtkIconTheme *icon_theme;
+ GtkIconInfo *info;
+ const char *icon;
GtkIconSource *source;
GtkIconSet *set;
GtkIconFactory *factory;
icon_theme = nautilus_icon_factory_get_icon_theme ();
- icon = gnome_icon_theme_lookup_icon (icon_theme, "gnome-fs-client", 48,
- NULL, NULL);
- if (icon != NULL) {
+ info = gtk_icon_theme_lookup_icon (icon_theme, "gnome-fs-client", 48,
+ 0);
+ if (info != NULL) {
+ icon = gtk_icon_info_get_filename (info);
factory = gtk_icon_factory_new ();
gtk_icon_factory_add_default (factory);
source = gtk_icon_source_new ();
gtk_icon_source_set_filename (source, icon);
- g_free (icon);
set = gtk_icon_set_new ();
gtk_icon_set_add_source (set, source);
@@ -155,12 +156,12 @@ register_icons (void)
gtk_icon_source_free (source);
+ gtk_icon_info_free (info);
g_object_unref (factory);
}
g_object_unref (icon_theme);
-
}
int
diff --git a/src/nautilus-navigation-bar.c b/src/nautilus-navigation-bar.c
index 8307da47e..65709d395 100644
--- a/src/nautilus-navigation-bar.c
+++ b/src/nautilus-navigation-bar.c
@@ -43,7 +43,7 @@ static guint signals[LAST_SIGNAL];
static void nautilus_navigation_bar_class_init (NautilusNavigationBarClass *class);
static void nautilus_navigation_bar_init (NautilusNavigationBar *bar);
-EEL_CLASS_BOILERPLATE (NautilusNavigationBar, nautilus_navigation_bar, EEL_TYPE_GENEROUS_BIN)
+EEL_CLASS_BOILERPLATE (NautilusNavigationBar, nautilus_navigation_bar, GTK_TYPE_HBOX)
EEL_IMPLEMENT_MUST_OVERRIDE_SIGNAL (nautilus_navigation_bar, get_location)
EEL_IMPLEMENT_MUST_OVERRIDE_SIGNAL (nautilus_navigation_bar, set_location)
diff --git a/src/nautilus-navigation-bar.h b/src/nautilus-navigation-bar.h
index 97e3ccdfa..a5bcd8fc5 100644
--- a/src/nautilus-navigation-bar.h
+++ b/src/nautilus-navigation-bar.h
@@ -29,7 +29,7 @@
#ifndef NAUTILUS_NAVIGATION_BAR_H
#define NAUTILUS_NAVIGATION_BAR_H
-#include <eel/eel-generous-bin.h>
+#include <gtk/gtkhbox.h>
#define NAUTILUS_TYPE_NAVIGATION_BAR (nautilus_navigation_bar_get_type ())
#define NAUTILUS_NAVIGATION_BAR(obj) \
@@ -40,11 +40,11 @@
GTK_CHECK_TYPE (obj, NAUTILUS_TYPE_NAVIGATION_BAR)
typedef struct {
- EelGenerousBin parent;
+ GtkHBox parent;
} NautilusNavigationBar;
typedef struct {
- EelGenerousBinClass parent_class;
+ GtkHBoxClass parent_class;
/* signals */
void (* location_changed) (NautilusNavigationBar *bar,
diff --git a/src/nautilus-navigation-window-menus.c b/src/nautilus-navigation-window-menus.c
index 4d8055887..2c32d0cb5 100644
--- a/src/nautilus-navigation-window-menus.c
+++ b/src/nautilus-navigation-window-menus.c
@@ -174,6 +174,7 @@ forget_history_if_confirmed (NautilusWindow *window)
{
GtkDialog *dialog;
char *prompt;
+ char *detail;
/* Confirm before forgetting history because it's a rare operation that
* is hard to recover from. We don't want people doing it accidentally
@@ -183,22 +184,23 @@ forget_history_if_confirmed (NautilusWindow *window)
/* This is a little joke, shows up occasionally. I only
* implemented this feature so I could use this joke.
*/
- prompt = g_strdup (_("Are you sure you want to forget history? "
- "If you do, you will be doomed to repeat it."));
+ prompt = _("Are you sure you want to forget history?");
+ detail = _("If you do, you will be doomed to repeat it.");
} else {
- prompt = g_strdup (_("Are you sure you want to clear the list "
- "of locations you have visited?"));
+ prompt = _("Are you sure you want to clear the list "
+ "of locations you have visited?");
+ detail = _("If you clear the list of locations,"
+ " they will be permanently deleted.");
}
dialog = eel_create_question_dialog (prompt,
+ detail,
_("Clear History"),
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_CLEAR, RESPONSE_FORGET,
GTK_WINDOW (window));
gtk_widget_show (GTK_WIDGET (dialog));
-
- g_free (prompt);
g_signal_connect (dialog, "response",
G_CALLBACK (forget_history_if_yes), NULL);
@@ -417,14 +419,16 @@ show_bogus_bookmark_window (NautilusWindow *window,
char *uri;
char *uri_for_display;
char *prompt;
+ char *detail;
uri = nautilus_bookmark_get_uri (bookmark);
uri_for_display = eel_format_uri_for_display (uri);
- prompt = g_strdup_printf (_("The location \"%s\" does not exist. Do you "
- "want to remove any bookmarks with this "
- "location from your list?"), uri_for_display);
- dialog = eel_show_yes_no_dialog (prompt,
+ prompt = _("Do you want to remove any bookmarks with the "
+ "non-existing location from your list?");
+ detail = g_strdup_printf (_("The location \"%s\" does not exist."), uri_for_display);
+
+ dialog = eel_show_yes_no_dialog (prompt, detail,
_("Bookmark for Nonexistent Location"),
_("Remove"), GTK_STOCK_CANCEL,
GTK_WINDOW (window));
@@ -439,7 +443,7 @@ show_bogus_bookmark_window (NautilusWindow *window,
g_free (uri);
g_free (uri_for_display);
- g_free (prompt);
+ g_free (detail);
}
static void
diff --git a/src/nautilus-navigation-window-ui.xml b/src/nautilus-navigation-window-ui.xml
index 9fe89ebd2..2fba4df0c 100644
--- a/src/nautilus-navigation-window-ui.xml
+++ b/src/nautilus-navigation-window-ui.xml
@@ -81,6 +81,10 @@
_label="_Computer"
pixtype="stock" pixname="gnome-fs-client"
verb="Go to Computer"/>
+ <menuitem name="Go to Templates"
+ _label="_Templates"
+ _tip="Go to templates folder"
+ verb="Go to Templates"/>
<menuitem name="Go to Trash"
_label="_Trash"
_tip="Go to the trash folder"
diff --git a/src/nautilus-navigation-window.c b/src/nautilus-navigation-window.c
index 12cbbe3bb..d89f1ca72 100644
--- a/src/nautilus-navigation-window.c
+++ b/src/nautilus-navigation-window.c
@@ -46,7 +46,6 @@
#include <eel/eel-debug.h>
#include <eel/eel-gdk-extensions.h>
#include <eel/eel-gdk-pixbuf-extensions.h>
-#include <eel/eel-generous-bin.h>
#include <eel/eel-gtk-extensions.h>
#include <eel/eel-gtk-macros.h>
#include <eel/eel-stock-dialogs.h>
@@ -961,6 +960,11 @@ real_set_content_view_widget (NautilusWindow *nautilus_window,
set_content_view_widget,
(nautilus_window, new_view));
+
+ if (new_view == NULL) {
+ return;
+ }
+
connect_view (window, new_view);
nautilus_horizontal_splitter_pack2 (
@@ -1103,22 +1107,22 @@ static void
report_side_panel_failure_to_user (NautilusWindow *window, NautilusViewFrame *view_frame)
{
char *message;
+ char *detail;
char *label;
label = nautilus_window_get_view_frame_label (view_frame);
if (label == NULL) {
message = g_strdup
- (_("One of the side panels encountered an error and can't continue. "
- "Unfortunately I couldn't tell which one."));
+ (_("One of the side panels encountered an error and can't continue."));
+ detail = _("Unfortunately I couldn't tell which one.");
} else {
message = g_strdup_printf
- (_("The %s side panel encountered an error and can't continue. "
- "If this keeps happening, you might want to turn this panel off."),
- label);
+ (_("The %s side panel encountered an error and can't continue."), label);
+ detail = _("If this keeps happening, you might want to turn this panel off.");
}
- eel_show_error_dialog (message, _("Side Panel Failed"), GTK_WINDOW (window));
+ eel_show_error_dialog (message, detail, _("Side Panel Failed"), GTK_WINDOW (window));
g_free (label);
g_free (message);
@@ -1466,6 +1470,19 @@ nautilus_navigation_window_show (GtkWidget *widget)
GTK_WIDGET_CLASS (parent_class)->show (widget);
}
+static void
+real_get_default_size(NautilusWindow *window, guint *default_width, guint *default_height)
+{
+
+ if(default_width) {
+ *default_width = NAUTILUS_NAVIGATION_WINDOW_DEFAULT_WIDTH;
+ }
+
+ if(default_height) {
+ *default_height = NAUTILUS_NAVIGATION_WINDOW_DEFAULT_HEIGHT;
+ }
+}
+
static void
nautilus_navigation_window_class_init (NautilusNavigationWindowClass *class)
{
@@ -1482,4 +1499,5 @@ nautilus_navigation_window_class_init (NautilusNavigationWindowClass *class)
NAUTILUS_WINDOW_CLASS (class)->set_throbber_active = real_set_throbber_active;
NAUTILUS_WINDOW_CLASS (class)->prompt_for_location = real_prompt_for_location;
NAUTILUS_WINDOW_CLASS (class)->set_title = real_set_title;
+ NAUTILUS_WINDOW_CLASS(class)->get_default_size = real_get_default_size;
}
diff --git a/src/nautilus-property-browser.c b/src/nautilus-property-browser.c
index 7bbb8720a..81cf4fcb0 100644
--- a/src/nautilus-property-browser.c
+++ b/src/nautilus-property-browser.c
@@ -678,7 +678,8 @@ ensure_uri_is_image (const char *uri)
GNOME_VFS_FILE_INFO_GET_MIME_TYPE
| GNOME_VFS_FILE_INFO_FOLLOW_LINKS);
is_image = eel_istr_has_prefix (file_info->mime_type, "image/")
- && eel_strcasecmp (file_info->mime_type, "image/svg") != 0;
+ && eel_strcasecmp (file_info->mime_type, "image/svg") != 0
+ && eel_strcasecmp (file_info->mime_type, "image/svg+xml") != 0;
gnome_vfs_file_info_unref (file_info);
return is_image;
}
@@ -911,7 +912,8 @@ remove_pattern(NautilusPropertyBrowser *property_browser, const char* pattern_na
/* delete the pattern from the pattern directory */
if (gnome_vfs_unlink (pattern_uri) != GNOME_VFS_OK) {
char *message = g_strdup_printf (_("Sorry, but pattern %s couldn't be deleted."), pattern_name);
- eel_show_error_dialog (message, _("Couldn't delete pattern"), GTK_WINDOW (property_browser));
+ char *detail = _("Check that you have permission to delete the pattern.");
+ eel_show_error_dialog (message, detail, _("Couldn't Delete Pattern"), GTK_WINDOW (property_browser));
g_free (message);
}
@@ -940,7 +942,8 @@ remove_emblem (NautilusPropertyBrowser *property_browser, const char* emblem_nam
/* delete the emblem from the emblem directory */
if (gnome_vfs_unlink (emblem_uri) != GNOME_VFS_OK) {
char *message = g_strdup_printf (_("Sorry, but emblem %s couldn't be deleted."), emblem_name);
- eel_show_error_dialog (message, _("Couldn't delete pattern"), GTK_WINDOW (property_browser));
+ char *detail = _("Check that you have permission to delete the emblem.");
+ eel_show_error_dialog (message, detail, _("Couldn't Delete Emblem"), GTK_WINDOW (property_browser));
g_free (message);
}
else {
@@ -1097,12 +1100,15 @@ add_pattern_to_browser (const char *path_name, gpointer *data)
/* make sure that it's a valid path */
if (path_name == NULL || path_name[0] != '/') {
char *message;
+ char *detail;
if (path_name != NULL) {
message = g_strdup_printf (_("Sorry, but \"%s\" is not a valid file name."), path_name);
+ detail = _("Please check the spelling and try again.");
} else {
message = g_strdup (_("Sorry, but you did not supply a valid file name."));
+ detail = _("Please try again.");
}
- eel_show_error_dialog (message, _("Couldn't install pattern"), GTK_WINDOW (property_browser));
+ eel_show_error_dialog (message, detail, _("Couldn't Install Pattern"), GTK_WINDOW (property_browser));
g_free (message);
return;
}
@@ -1113,7 +1119,9 @@ add_pattern_to_browser (const char *path_name, gpointer *data)
/* don't allow the user to change the reset image */
basename = eel_uri_get_basename (path_uri);
if (basename && eel_strcmp (basename, RESET_IMAGE_NAME) == 0) {
- eel_show_error_dialog (_("Sorry, but you can't replace the reset image."), _("Not an Image"), NULL);
+ eel_show_error_dialog (_("Sorry, but you can't replace the reset image."),
+ _("Reset is a special image that cannot be deleted."),
+ _("Not an Image"), NULL);
g_free (path_uri);
g_free (basename);
return;
@@ -1145,7 +1153,7 @@ add_pattern_to_browser (const char *path_name, gpointer *data)
result = eel_copy_uri_simple (path_name, destination_name);
if (result != GNOME_VFS_OK) {
char *message = g_strdup_printf (_("Sorry, but the pattern %s couldn't be installed."), path_name);
- eel_show_error_dialog (message, _("Couldn't install pattern"), GTK_WINDOW (property_browser));
+ eel_show_error_dialog (message, NULL, _("Couldn't Install Pattern"), GTK_WINDOW (property_browser));
g_free (message);
}
@@ -1225,8 +1233,9 @@ add_color_to_browser (GtkWidget *widget, gint which_button, gpointer *data)
color_name = gtk_entry_get_text (GTK_ENTRY (property_browser->details->color_name));
stripped_color_name = g_strstrip (g_strdup (color_name));
if (strlen (stripped_color_name) == 0) {
- eel_show_error_dialog (_("Sorry, but you must specify a non-blank name for the new color."),
- _("Couldn't install color"), GTK_WINDOW (property_browser));
+ eel_show_error_dialog (_("The color cannot be installed."),
+ _("Sorry, but you must specify a non-blank name for the new color."),
+ _("Couldn't Install Color"), GTK_WINDOW (property_browser));
} else {
add_color_to_file (property_browser, color_spec, stripped_color_name);
@@ -1315,8 +1324,8 @@ emblem_dialog_clicked (GtkWidget *dialog, int which_button, NautilusPropertyBrow
property_browser->details->image_path = emblem_path;
} else {
char *message = g_strdup_printf
- (_("Sorry, but '%s' is not a usable image file!"), emblem_path);
- eel_show_error_dialog (message, _("Not an Image"), GTK_WINDOW (property_browser));
+ (_("Sorry, but \"%s\" is not a usable image file."), emblem_path);
+ eel_show_error_dialog (_("The file is not an image."), message, _("Not an Image"), GTK_WINDOW (property_browser));
g_free (message);
g_free (emblem_path);
return;
@@ -1331,8 +1340,9 @@ emblem_dialog_clicked (GtkWidget *dialog, int which_button, NautilusPropertyBrow
if (pixbuf == NULL) {
char *message = g_strdup_printf
- (_("Sorry, but '%s' is not a usable image file!"), property_browser->details->image_path);
- eel_show_error_dialog (message, _("Not an Image"), GTK_WINDOW (property_browser));
+ (_("Sorry, but \"%s\" is not a usable image file."), property_browser->details->image_path);
+ eel_show_error_dialog (_("The file is not an image."), message, _("Not an Image"), GTK_WINDOW (property_browser));
+ g_free (message);
}
new_keyword = gtk_entry_get_text(GTK_ENTRY(property_browser->details->keyword));
diff --git a/src/nautilus-server-connect.c b/src/nautilus-server-connect.c
index 858893c3e..7aba928ab 100644
--- a/src/nautilus-server-connect.c
+++ b/src/nautilus-server-connect.c
@@ -302,11 +302,10 @@ can_connect (const char *uri)
static void
update_icon (GtkEntry *entry, gpointer user_data)
{
- GnomeIconTheme *theme;
+ GtkIconTheme *theme;
GtkWidget *button;
- char *uri_utf8, *uri, *filename;
- const GnomeIconData *icon_data;
- int base_size;
+ char *uri_utf8, *uri;
+ GdkPixbuf *pixbuf;
uri_utf8 = gtk_editable_get_chars (GTK_EDITABLE (entry), 0, -1);
if (uri_utf8 == NULL)
@@ -316,9 +315,8 @@ update_icon (GtkEntry *entry, gpointer user_data)
g_free (uri_utf8);
button = glade_xml_get_widget (xml, "button3");
-
- if (uri == NULL || strcmp (uri, "") == 0)
- {
+
+ if (uri == NULL || strcmp (uri, "") == 0) {
gtk_widget_set_sensitive (button, FALSE);
naut_icon = "gnome-fs-share";
} else {
@@ -337,14 +335,16 @@ update_icon (GtkEntry *entry, gpointer user_data)
}
}
- theme = gnome_icon_theme_new ();
- filename = gnome_icon_theme_lookup_icon (theme, naut_icon,
- ICON_SIZE_STANDARD,
- &icon_data,
- &base_size);
+ theme = gtk_icon_theme_get_default ();
+ pixbuf = gtk_icon_theme_load_icon (theme, naut_icon,
+ ICON_SIZE_STANDARD,
+ 0, NULL);
- gtk_image_set_from_file (GTK_IMAGE (image), filename);
- g_free (filename);
+ if (pixbuf != NULL) {
+ gtk_image_set_from_pixbuf (GTK_IMAGE (image), pixbuf);
+ g_object_unref (pixbuf);
+ }
+
g_free (uri);
}
diff --git a/src/nautilus-spatial-window-ui.xml b/src/nautilus-spatial-window-ui.xml
index aeb8fad4b..686ebd269 100644
--- a/src/nautilus-spatial-window-ui.xml
+++ b/src/nautilus-spatial-window-ui.xml
@@ -5,6 +5,9 @@
<commands>
</commands>
+<keybindings>
+ <accel name="*Alt**Shift*Up" verb="UpCloseCurrent"/>
+</keybindings>
<menu>
<submenu name="File">
<placeholder name="Location Placeholder">
@@ -23,10 +26,10 @@
</placeholder>
<placeholder name="Close Items Placeholder">
<menuitem name="Close With Parents"
- _label="Close _All Parents"
- _tip="Close all Navigation windows"
+ _label="Close P_arent Folders"
+ _tip="Close this folder's parents"
accel="*Control**Shift*w"
- verb="Close With Parents"/>
+ verb="Close Parent Folders"/>
</placeholder>
</submenu>
@@ -41,6 +44,10 @@
_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"
+ verb="Go to Templates"/>
<menuitem name="Go to Trash"
_label="_Trash"
_tip="Go to the trash folder"
diff --git a/src/nautilus-spatial-window.c b/src/nautilus-spatial-window.c
index cf608a71b..a3d84d94d 100644
--- a/src/nautilus-spatial-window.c
+++ b/src/nautilus-spatial-window.c
@@ -46,7 +46,6 @@
#include <eel/eel-debug.h>
#include <eel/eel-gdk-extensions.h>
#include <eel/eel-gdk-pixbuf-extensions.h>
-#include <eel/eel-generous-bin.h>
#include <eel/eel-gtk-extensions.h>
#include <eel/eel-gtk-macros.h>
#include <eel/eel-string.h>
@@ -121,7 +120,7 @@ nautilus_spatial_window_configure_event (GtkWidget *widget,
GTK_WIDGET_CLASS (parent_class)->configure_event (widget, event);
/* Only save the geometry if the user hasn't resized the window
- * for half a second. Otherwise delay the callback another half second.
+ * for a second. Otherwise delay the callback another second.
*/
if (window->details->save_geometry_timeout_id != 0) {
g_source_remove (window->details->save_geometry_timeout_id);
@@ -149,7 +148,7 @@ nautilus_spatial_window_configure_event (GtkWidget *widget,
window->details->last_geometry = geometry_string;
window->details->save_geometry_timeout_id =
- g_timeout_add (500, save_window_geometry_timeout, window);
+ g_timeout_add (1000, save_window_geometry_timeout, window);
}
return FALSE;
@@ -239,14 +238,23 @@ nautilus_spatial_window_show (GtkWidget *widget)
}
static void
-file_menu_close_with_parent_windows_callback (BonoboUIComponent *component,
- gpointer user_data,
- const char *verb)
+file_menu_close_parent_windows_callback (BonoboUIComponent *component,
+ gpointer user_data,
+ const char *verb)
{
- nautilus_application_close_with_parent_windows (NAUTILUS_SPATIAL_WINDOW (user_data));
+ nautilus_application_close_parent_windows (NAUTILUS_SPATIAL_WINDOW (user_data));
}
static void
+go_up_close_current_window_callback (BonoboUIComponent *component,
+ gpointer user_data,
+ const char *verb)
+{
+ nautilus_window_go_up (NAUTILUS_WINDOW (user_data), TRUE);
+}
+
+
+static void
real_prompt_for_location (NautilusWindow *window)
{
GtkWidget *dialog;
@@ -275,7 +283,8 @@ real_merge_menus (NautilusWindow *nautilus_window)
{
NautilusSpatialWindow *window;
BonoboUIVerb verbs [] = {
- BONOBO_UI_VERB ("Close With Parents", file_menu_close_with_parent_windows_callback),
+ BONOBO_UI_VERB ("Close Parent Folders", file_menu_close_parent_windows_callback),
+ BONOBO_UI_VERB ("UpCloseCurrent", go_up_close_current_window_callback),
BONOBO_UI_VERB_END
};
@@ -304,12 +313,22 @@ real_set_content_view_widget (NautilusWindow *window,
GTK_WIDGET (new_view));
}
-static gboolean
-real_delete_event (GtkWidget *window, GdkEventAny *event)
+static void
+real_window_close (NautilusWindow *window)
{
+ nautilus_spatial_window_save_geometry (NAUTILUS_SPATIAL_WINDOW (window));
nautilus_spatial_window_save_scroll_position (NAUTILUS_SPATIAL_WINDOW (window));
+}
- return FALSE;
+static void
+real_get_default_size(NautilusWindow *window, guint *default_width, guint *default_height)
+{
+ if(default_width) {
+ *default_width = NAUTILUS_SPATIAL_WINDOW_DEFAULT_WIDTH;
+ }
+ if(default_height) {
+ *default_height = NAUTILUS_SPATIAL_WINDOW_DEFAULT_HEIGHT;
+ }
}
static void
@@ -319,7 +338,7 @@ nautilus_spatial_window_instance_init (NautilusSpatialWindow *window)
window->affect_spatial_window_on_next_location_change = TRUE;
window->details->content_box =
- gtk_widget_new (EEL_TYPE_GENEROUS_BIN, NULL);
+ gtk_hbox_new (FALSE, 0);
gtk_widget_show (window->details->content_box);
bonobo_window_set_contents (BONOBO_WINDOW (window),
window->details->content_box);
@@ -344,6 +363,7 @@ nautilus_spatial_window_class_init (NautilusSpatialWindowClass *class)
real_merge_menus;
NAUTILUS_WINDOW_CLASS (class)->set_content_view_widget =
real_set_content_view_widget;
- GTK_WIDGET_CLASS (class)->delete_event =
- real_delete_event;
+ NAUTILUS_WINDOW_CLASS (class)->close =
+ real_window_close;
+ NAUTILUS_WINDOW_CLASS(class)->get_default_size = real_get_default_size;
}
diff --git a/src/nautilus-view-frame.c b/src/nautilus-view-frame.c
index a7bb916f6..336350b40 100644
--- a/src/nautilus-view-frame.c
+++ b/src/nautilus-view-frame.c
@@ -130,7 +130,7 @@ static guint signals[LAST_SIGNAL];
EEL_CLASS_BOILERPLATE (NautilusViewFrame,
nautilus_view_frame,
- EEL_TYPE_GENEROUS_BIN)
+ GTK_TYPE_HBOX)
void
nautilus_view_frame_queue_incoming_call (PortableServer_Servant servant,
diff --git a/src/nautilus-view-frame.h b/src/nautilus-view-frame.h
index 12906dd31..39b6340aa 100644
--- a/src/nautilus-view-frame.h
+++ b/src/nautilus-view-frame.h
@@ -35,7 +35,7 @@
#include <bonobo/bonobo-ui-container.h>
#include <bonobo/bonobo-zoomable-frame.h>
-#include <eel/eel-generous-bin.h>
+#include <gtk/gtkhbox.h>
#include <libnautilus-private/nautilus-undo-manager.h>
#include <libnautilus/nautilus-view-component.h>
@@ -48,12 +48,12 @@
typedef struct NautilusViewFrameDetails NautilusViewFrameDetails;
typedef struct {
- EelGenerousBin parent;
+ GtkHBox parent;
NautilusViewFrameDetails *details;
} NautilusViewFrame;
typedef struct {
- EelGenerousBinClass parent_spot;
+ GtkHBoxClass parent_spot;
/* These roughly correspond to CORBA calls, but in some cases they are higher level. */
diff --git a/src/nautilus-window-manage-views.c b/src/nautilus-window-manage-views.c
index 35c59be4a..af9ee03f3 100644
--- a/src/nautilus-window-manage-views.c
+++ b/src/nautilus-window-manage-views.c
@@ -174,25 +174,17 @@ update_title (NautilusWindow *window)
void
nautilus_window_update_icon (NautilusWindow *window)
{
- char *path;
GdkPixbuf *pixbuf;
- GnomeIconTheme *icon_theme;
+ GtkIconTheme *icon_theme;
pixbuf = NULL;
/* Desktop window special icon */
if (NAUTILUS_IS_DESKTOP_WINDOW (window)) {
- icon_theme = nautilus_icon_factory_get_icon_theme();
- path = gnome_icon_theme_lookup_icon (icon_theme,
- "gnome-fs-desktop", 48,
- NULL, NULL);
-
- if (path != NULL) {
- pixbuf = gdk_pixbuf_new_from_file (path, NULL);
-
- g_free (path);
- }
-
+ icon_theme = nautilus_icon_factory_get_icon_theme ();
+ pixbuf = gtk_icon_theme_load_icon (icon_theme,
+ "gnome-fs-desktop", 48,
+ 0, NULL);
g_object_unref(icon_theme);
} else {
@@ -736,11 +728,18 @@ nautilus_window_open_location (NautilusWindow *window,
void
nautilus_window_open_location_with_selection (NautilusWindow *window,
const char *location,
- GList *selection)
+ GList *selection,
+ gboolean close_behind)
{
+ Nautilus_ViewFrame_OpenFlags flags;
+
+ flags = 0;
+ if (close_behind) {
+ flags = Nautilus_ViewFrame_OPEN_FLAG_CLOSE_BEHIND;
+ }
open_location (window, location,
Nautilus_ViewFrame_OPEN_ACCORDING_TO_MODE,
- 0, selection);
+ flags, selection);
}
@@ -800,13 +799,14 @@ view_frame_get_id (NautilusViewFrame *view_frame)
static void
report_content_view_failure_to_user_internal (NautilusWindow *window,
NautilusViewFrame *view_frame,
- const char *message)
+ const char *message,
+ const char *detail)
{
char *label;
label = nautilus_window_get_view_frame_label (view_frame);
message = g_strdup_printf (message, label);
- eel_show_error_dialog (message, _("View Failed"), GTK_WINDOW (window));
+ eel_show_error_dialog (message, detail, _("View Failed"), GTK_WINDOW (window));
g_free (label);
}
@@ -817,8 +817,8 @@ report_current_content_view_failure_to_user (NautilusWindow *window,
report_content_view_failure_to_user_internal
(window,
view_frame,
- _("The %s view encountered an error and can't continue. "
- "You can choose another view or go to a different location."));
+ _("The %s view encountered an error and can't continue."),
+ _("You can choose another view or go to a different location."));
}
static void
@@ -828,7 +828,8 @@ report_nascent_content_view_failure_to_user (NautilusWindow *window,
report_content_view_failure_to_user_internal
(window,
view_frame,
- _("The %s view encountered an error while starting up."));
+ _("The %s view encountered an error while starting up."),
+ _("The location cannot be displayed with this viewer."));
}
static void
@@ -996,8 +997,9 @@ handle_view_failure (NautilusWindow *window,
g_warning ("A view failed. The UI will handle this with a dialog but this should be debugged.");
if (view == window->content_view) {
+ disconnect_view(window, window->content_view);
nautilus_window_set_content_view_widget (window, NULL);
-
+
/* FIXME bugzilla.gnome.org 45039: We need a
* way to report the specific error that
* happens in this case - adapter factory not
@@ -1175,6 +1177,7 @@ determined_initial_view_callback (NautilusDetermineViewHandle *handle,
char *full_uri_for_display;
char *uri_for_display;
char *error_message;
+ char *detail_message;
char *scheme_string;
char *type_string;
char *dialog_title;
@@ -1228,14 +1231,18 @@ determined_initial_view_callback (NautilusDetermineViewHandle *handle,
case NAUTILUS_DETERMINE_VIEW_NOT_FOUND:
error_message = g_strdup_printf
- (_("Couldn't find \"%s\". Please check the spelling and try again."),
+ (_("Couldn't find \"%s\"."),
uri_for_display);
+ detail_message = g_strdup
+ (_("Please check the spelling and try again."));
break;
case NAUTILUS_DETERMINE_VIEW_INVALID_URI:
error_message = g_strdup_printf
- (_("\"%s\" is not a valid location. Please check the spelling and try again."),
+ (_("\"%s\" is not a valid location."),
uri_for_display);
+ detail_message = g_strdup
+ (_("Please check the spelling and try again."));
break;
case NAUTILUS_DETERMINE_VIEW_NO_HANDLER_FOR_TYPE:
@@ -1248,16 +1255,20 @@ determined_initial_view_callback (NautilusDetermineViewHandle *handle,
nautilus_file_unref (file);
if (type_string == NULL) {
error_message = g_strdup_printf
- (_("Couldn't display \"%s\", because Nautilus cannot determine what type of file it is."),
+ (_("Couldn't display \"%s\"."),
uri_for_display);
+ detail_message = g_strdup
+ (_("Nautilus cannot determine what type of file it is."));
} else {
/* FIXME bugzilla.gnome.org 44932:
* Should distinguish URIs with no handlers at all from remote URIs
* with local-only handlers.
*/
- error_message = g_strdup_printf
- (_("Nautilus has no installed viewer capable of displaying \"%s\"."),
- uri_for_display);
+ error_message = g_strdup_printf
+ (_("Couldn't display \"%s\"."),
+ uri_for_display);
+ detail_message = g_strdup
+ (_("Nautilus has no installed viewer capable of displaying the file."));
g_free (type_string);
}
break;
@@ -1268,19 +1279,23 @@ determined_initial_view_callback (NautilusDetermineViewHandle *handle,
*/
scheme_string = eel_str_get_prefix (location, ":");
g_assert (scheme_string != NULL); /* Shouldn't have gotten this error unless there's a : separator. */
- error_message = g_strdup_printf (_("Couldn't display \"%s\", because Nautilus cannot handle %s: locations."),
- uri_for_display, scheme_string);
+ error_message = g_strdup_printf (_("Couldn't display \"%s\"."),
+ uri_for_display);
+ detail_message = g_strdup_printf (_("Nautilus cannot handle %s: locations."),
+ scheme_string);
g_free (scheme_string);
break;
case NAUTILUS_DETERMINE_VIEW_LOGIN_FAILED:
- error_message = g_strdup_printf (_("Couldn't display \"%s\", because the attempt to log in failed."),
- uri_for_display);
+ error_message = g_strdup_printf (_("Couldn't display \"%s\"."),
+ uri_for_display);
+ detail_message = g_strdup (_("The attempt to log in failed."));
break;
case NAUTILUS_DETERMINE_VIEW_ACCESS_DENIED:
- error_message = g_strdup_printf (_("Couldn't display \"%s\", because access was denied."),
+ error_message = g_strdup_printf (_("Couldn't display \"%s\"."),
uri_for_display);
+ detail_message = g_strdup (_("Access was denied."));
break;
case NAUTILUS_DETERMINE_VIEW_HOST_NOT_FOUND:
@@ -1290,24 +1305,25 @@ determined_initial_view_callback (NautilusDetermineViewHandle *handle,
* the proxy is set up wrong.
*/
vfs_uri = gnome_vfs_uri_new (location);
- error_message = g_strdup_printf (_("Couldn't display \"%s\", because no host \"%s\" could be found. "
- "Check that the spelling is correct and that your proxy settings are correct."),
+ error_message = g_strdup_printf (_("Couldn't display \"%s\", because no host \"%s\" could be found."),
uri_for_display,
gnome_vfs_uri_get_host_name (vfs_uri));
+ detail_message = g_strdup (_("Check that the spelling is correct and that your proxy settings are correct."));
gnome_vfs_uri_unref (vfs_uri);
break;
case NAUTILUS_DETERMINE_VIEW_HOST_HAS_NO_ADDRESS:
- error_message = g_strdup_printf (_("Couldn't display \"%s\". "
- "Check that your proxy settings are correct."),
+ error_message = g_strdup_printf (_("Couldn't display \"%s\"."),
uri_for_display);
+ detail_message = g_strdup (_("Check that your proxy settings are correct."));
break;
case NAUTILUS_DETERMINE_VIEW_NO_MASTER_BROWSER:
error_message = g_strdup_printf
- (_("Couldn't display \"%s\", because Nautilus cannot contact the SMB master browser.\n"
- "Check that an SMB server is running in the local network."),
+ (_("Couldn't display \"%s\", because Nautilus cannot contact the SMB master browser."),
uri_for_display);
+ detail_message = g_strdup
+ (_("Check that an SMB server is running in the local network."));
break;
case NAUTILUS_DETERMINE_VIEW_SERVICE_NOT_AVAILABLE:
@@ -1318,8 +1334,9 @@ determined_initial_view_callback (NautilusDetermineViewHandle *handle,
*/
error_message = g_strdup_printf
(_("Searching is unavailable right now, because you either have no index, "
- "or the search service isn't running. "
- "Be sure that you have started the Medusa search service, and if you "
+ "or the search service isn't running."));
+ detail_message = g_strdup
+ (_("Be sure that you have started the Medusa search service, and if you "
"don't have an index, that the Medusa indexer is running."));
dialog_title = g_strdup (_("Searching Unavailable"));
break;
@@ -1328,6 +1345,7 @@ determined_initial_view_callback (NautilusDetermineViewHandle *handle,
default:
error_message = g_strdup_printf (_("Nautilus cannot display \"%s\"."),
uri_for_display);
+ detail_message = g_strdup (_("Please select another viewer and try again."));
}
if (dialog_title == NULL) {
@@ -1339,7 +1357,7 @@ determined_initial_view_callback (NautilusDetermineViewHandle *handle,
* happens when a new window cannot display its initial URI.
*/
- dialog = eel_show_error_dialog (error_message, dialog_title, NULL);
+ dialog = eel_show_error_dialog (error_message, detail_message, dialog_title, NULL);
/* if this is the only window, we don't want to quit, so we redirect it to home */
if (just_one_window ()) {
@@ -1368,7 +1386,7 @@ determined_initial_view_callback (NautilusDetermineViewHandle *handle,
} else {
/* Clean up state of already-showing window */
nautilus_window_allow_stop (window, FALSE);
- eel_show_error_dialog (error_message, dialog_title, GTK_WINDOW (window));
+ eel_show_error_dialog (error_message, detail_message, dialog_title, GTK_WINDOW (window));
/* Leave the location bar showing the bad location that the user
* typed (or maybe achieved by dragging or something). Many times
@@ -1380,6 +1398,7 @@ determined_initial_view_callback (NautilusDetermineViewHandle *handle,
g_free (dialog_title);
g_free (uri_for_display);
g_free (error_message);
+ g_free (detail_message);
}
/*
diff --git a/src/nautilus-window-manage-views.h b/src/nautilus-window-manage-views.h
index b5826beee..8aefc7258 100644
--- a/src/nautilus-window-manage-views.h
+++ b/src/nautilus-window-manage-views.h
@@ -36,7 +36,8 @@ void nautilus_window_open_location (NautilusWi
const char *location);
void nautilus_window_open_location_with_selection (NautilusWindow *window,
const char *location,
- GList *selection);
+ GList *selection,
+ gboolean close_behind);
void nautilus_window_stop_loading (NautilusWindow *window);
void nautilus_window_set_content_view (NautilusWindow *window,
NautilusViewIdentifier *id);
diff --git a/src/nautilus-window-menus.c b/src/nautilus-window-menus.c
index d0b9d6cfb..56956690d 100644
--- a/src/nautilus-window-menus.c
+++ b/src/nautilus-window-menus.c
@@ -349,7 +349,7 @@ go_menu_up_callback (BonoboUIComponent *component,
gpointer user_data,
const char *verb)
{
- nautilus_window_go_up (NAUTILUS_WINDOW (user_data));
+ nautilus_window_go_up (NAUTILUS_WINDOW (user_data), FALSE);
}
static void
@@ -379,6 +379,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)
@@ -658,6 +672,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),
diff --git a/src/nautilus-window-private.h b/src/nautilus-window-private.h
index ade48b2d0..e451c7686 100644
--- a/src/nautilus-window-private.h
+++ b/src/nautilus-window-private.h
@@ -139,8 +139,11 @@ struct _NautilusNavigationWindowDetails {
#define NAUTILUS_WINDOW_MIN_WIDTH 200
#define NAUTILUS_WINDOW_MIN_HEIGHT 200
-#define NAUTILUS_WINDOW_DEFAULT_WIDTH 500
-#define NAUTILUS_WINDOW_DEFAULT_HEIGHT 300
+#define NAUTILUS_SPATIAL_WINDOW_DEFAULT_WIDTH 500
+#define NAUTILUS_SPATIAL_WINDOW_DEFAULT_HEIGHT 300
+
+#define NAUTILUS_NAVIGATION_WINDOW_DEFAULT_WIDTH 800
+#define NAUTILUS_NAVIGATION_WINDOW_DEFAULT_HEIGHT 550
typedef void (*NautilusBookmarkFailedCallback) (NautilusWindow *window,
NautilusBookmark *bookmark);
diff --git a/src/nautilus-window.c b/src/nautilus-window.c
index 187f66a9b..aa0e5bba4 100644
--- a/src/nautilus-window.c
+++ b/src/nautilus-window.c
@@ -44,11 +44,11 @@
#include <eel/eel-debug.h>
#include <eel/eel-gdk-extensions.h>
#include <eel/eel-gdk-pixbuf-extensions.h>
-#include <eel/eel-generous-bin.h>
#include <eel/eel-gtk-extensions.h>
#include <eel/eel-gtk-macros.h>
#include <eel/eel-stock-dialogs.h>
#include <eel/eel-string.h>
+#include <eel/eel-vfs-extensions.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <gdk/gdkx.h>
#include <gtk/gtkmain.h>
@@ -354,7 +354,7 @@ nautilus_window_go_to (NautilusWindow *window, const char *uri)
}
void
-nautilus_window_go_up (NautilusWindow *window)
+nautilus_window_go_up (NautilusWindow *window, gboolean close_behind)
{
GnomeVFSURI *current_uri;
GnomeVFSURI *parent_uri;
@@ -379,7 +379,7 @@ nautilus_window_go_up (NautilusWindow *window)
selection = g_list_prepend (NULL, g_strdup (window->details->location));
- nautilus_window_open_location_with_selection (window, parent_uri_string, selection);
+ nautilus_window_open_location_with_selection (window, parent_uri_string, selection, close_behind);
g_free (parent_uri_string);
eel_g_list_free_deep (selection);
@@ -523,7 +523,8 @@ set_initial_window_geometry (NautilusWindow *window)
{
GdkScreen *screen;
guint max_width_for_screen, max_height_for_screen;
-
+ guint default_width, default_height;
+
screen = gtk_window_get_screen (GTK_WINDOW (window));
/* Don't let GTK determine the minimum size
@@ -550,11 +551,14 @@ set_initial_window_geometry (NautilusWindow *window)
max_width_for_screen),
MIN (NAUTILUS_WINDOW_MIN_HEIGHT,
max_height_for_screen));
-
+
+ EEL_CALL_METHOD (NAUTILUS_WINDOW_CLASS, window,
+ get_default_size, (window, &default_width, &default_height));
+
gtk_window_set_default_size (GTK_WINDOW (window),
- MIN (NAUTILUS_WINDOW_DEFAULT_WIDTH,
+ MIN (default_width,
max_width_for_screen),
- MIN (NAUTILUS_WINDOW_DEFAULT_HEIGHT,
+ MIN (default_height,
max_height_for_screen));
}
@@ -747,6 +751,9 @@ nautilus_window_close (NautilusWindow *window)
{
g_return_if_fail (NAUTILUS_IS_WINDOW (window));
+ EEL_CALL_METHOD (NAUTILUS_WINDOW_CLASS, window,
+ close, (window));
+
gtk_widget_destroy (GTK_WIDGET (window));
}
@@ -1126,27 +1133,29 @@ compute_default_title (const char *text_uri)
{
NautilusFile *file;
char *title;
-
- if (text_uri == NULL) {
+ char *canonical_uri;
+
+ canonical_uri = eel_make_uri_canonical (text_uri);
+
+ if (canonical_uri == NULL) {
title = g_strdup ("");
- } else if (strcmp (text_uri, "computer://") == 0 ||
- strcmp (text_uri, "computer:///") == 0) {
+ } else if (strcmp (canonical_uri, "computer:///") == 0 ) {
title = g_strdup (_("Computer"));
- } else if (strcmp (text_uri, "network://") == 0 ||
- strcmp (text_uri, "network:///") == 0) {
+ } else if (strcmp (canonical_uri, "network:///") == 0 ) {
title = g_strdup (_("Network"));
- } else if (strcmp (text_uri, "fonts://") == 0 ||
- strcmp (text_uri, "fonts:///") == 0) {
+ } else if (strcmp (canonical_uri, "fonts:///") == 0 ) {
title = g_strdup (_("Fonts"));
- } else if (strcmp (text_uri, "burn://") == 0 ||
- strcmp (text_uri, "burn:///") == 0) {
+ } else if (strcmp (canonical_uri, "themes:///") == 0 ) {
+ title = g_strdup (_("Themes"));
+ } else if (strcmp (canonical_uri, "burn:///") == 0 ) {
title = g_strdup (_("CD Creator"));
} else {
file = nautilus_file_get (text_uri);
title = nautilus_file_get_display_name (file);
nautilus_file_unref (file);
}
-
+
+ g_free (canonical_uri);
return title;
}
@@ -1385,11 +1394,18 @@ nautilus_window_set_viewed_file (NautilusWindow *window,
cancel_chose_component_callback (window);
if (window->details->viewed_file != NULL) {
+ if (NAUTILUS_IS_SPATIAL_WINDOW (window)) {
+ nautilus_file_set_has_open_window (window->details->viewed_file,
+ FALSE);
+ }
nautilus_file_monitor_remove (window->details->viewed_file,
window);
}
if (file != NULL) {
+ if (NAUTILUS_IS_SPATIAL_WINDOW (window)) {
+ nautilus_file_set_has_open_window (file, TRUE);
+ }
attributes = NAUTILUS_FILE_ATTRIBUTE_DISPLAY_NAME;
nautilus_file_monitor_add (file, window, attributes);
}
diff --git a/src/nautilus-window.h b/src/nautilus-window.h
index a9be2a192..cd4791600 100644
--- a/src/nautilus-window.h
+++ b/src/nautilus-window.h
@@ -76,6 +76,8 @@ typedef struct {
void (* set_throbber_active) (NautilusWindow *window,
gboolean active);
void (* prompt_for_location) (NautilusWindow *window);
+ void (* get_default_size) (NautilusWindow *window, guint *default_width, guint *default_height);
+ void (* close) (NautilusWindow *window);
} NautilusWindowClass;
typedef enum {
@@ -121,7 +123,8 @@ char * nautilus_window_get_location (NautilusWindow *window
void nautilus_window_go_to (NautilusWindow *window,
const char *location);
void nautilus_window_go_home (NautilusWindow *window);
-void nautilus_window_go_up (NautilusWindow *window);
+void nautilus_window_go_up (NautilusWindow *window,
+ gboolean close_behind);
void nautilus_window_prompt_for_location (NautilusWindow *window);
void nautilus_window_launch_cd_burner (NautilusWindow *window);
void nautilus_window_update_title (NautilusWindow *window);