diff options
author | Darin Adler <darin@src.gnome.org> | 2000-03-08 02:32:00 +0000 |
---|---|---|
committer | Darin Adler <darin@src.gnome.org> | 2000-03-08 02:32:00 +0000 |
commit | f026b4a2cee5417a6660d0fa0b0e71438cc59178 (patch) | |
tree | 6029a39726bd1ed90bc60d6c2e826f33a53b8068 | |
parent | 6c09e03e878e509ded79e082a3f15544b1997422 (diff) | |
download | nautilus-f026b4a2cee5417a6660d0fa0b0e71438cc59178.tar.gz |
Reimplemented the delete command to use NautilusFile instead of
going directly to the file system.
* libnautilus/gnome-icon-container.h,
libnautilus/gnome-icon-container.c
(gnome_icon_container_clear_selected_items),
(gnome_icon_container_remove): Got rid of the call that removes
all the icons in the selection and replaced it with a call that
removes a specific icon.
* libnautilus/nautilus-directory.h,
libnautilus/nautilus-directory.c
(nautilus_directory_initialize_class), (nautilus_file_unref),
(nautilus_file_detach), (nautilus_file_free),
(nautilus_file_delete), (nautilus_file_is_gone): Implemented a
call to delete a file and emit the files_removed signal as needed.
* src/file-manager/fm-directory-view.h,
src/file-manager/fm-directory-view.c
(fm_directory_view_delete_selection),
(fm_directory_view_begin_adding_entries),
(fm_directory_view_add_entry),
(fm_directory_view_done_adding_entries), (display_pending_files),
(add_or_remove_files), (add_files_cb), (remove_files_cb),
(delete_one): Changed the delete implementation to call
nautilus_file_delete and got rid of the explicit call to
delete_selection. The views now will remove their entries in
response to the change in the model.
* src/file-manager/fm-directory-view-icons.c
(fm_directory_view_icons_remove_entry),
(fm_directory_view_icons_delete_selection),
src/file-manager/fm-directory-view-list.c
(fm_directory_view_list_remove_entry),
(fm_directory_view_list_delete_selection): Eliminated the
delete_selection function in favor of the remove_entry function.
-rw-r--r-- | ChangeLog-20000414 | 343 | ||||
-rw-r--r-- | libnautilus-extensions/gnome-icon-container.c | 109 | ||||
-rw-r--r-- | libnautilus-extensions/gnome-icon-container.h | 3 | ||||
-rw-r--r-- | libnautilus-extensions/nautilus-directory.c | 244 | ||||
-rw-r--r-- | libnautilus-extensions/nautilus-directory.h | 3 | ||||
-rw-r--r-- | libnautilus-private/gnome-icon-container.c | 109 | ||||
-rw-r--r-- | libnautilus-private/gnome-icon-container.h | 3 | ||||
-rw-r--r-- | libnautilus-private/nautilus-directory.c | 244 | ||||
-rw-r--r-- | libnautilus-private/nautilus-directory.h | 3 | ||||
-rw-r--r-- | libnautilus/gnome-icon-container.c | 109 | ||||
-rw-r--r-- | libnautilus/gnome-icon-container.h | 3 | ||||
-rw-r--r-- | libnautilus/nautilus-directory.c | 244 | ||||
-rw-r--r-- | libnautilus/nautilus-directory.h | 3 | ||||
-rw-r--r-- | src/file-manager/fm-directory-view-icons.c | 61 | ||||
-rw-r--r-- | src/file-manager/fm-directory-view-list.c | 28 | ||||
-rw-r--r-- | src/file-manager/fm-directory-view.c | 258 | ||||
-rw-r--r-- | src/file-manager/fm-directory-view.h | 18 |
17 files changed, 1071 insertions, 714 deletions
diff --git a/ChangeLog-20000414 b/ChangeLog-20000414 index 1b6745b5b..23122bc48 100644 --- a/ChangeLog-20000414 +++ b/ChangeLog-20000414 @@ -1,3 +1,42 @@ +2000-03-07 Darin Adler <darin@eazel.com> + + Reimplemented the delete command to use NautilusFile instead of + going directly to the file system. + + * libnautilus/gnome-icon-container.h, + libnautilus/gnome-icon-container.c + (gnome_icon_container_clear_selected_items), + (gnome_icon_container_remove): Got rid of the call that removes + all the icons in the selection and replaced it with a call that + removes a specific icon. + + * libnautilus/nautilus-directory.h, + libnautilus/nautilus-directory.c + (nautilus_directory_initialize_class), (nautilus_file_unref), + (nautilus_file_detach), (nautilus_file_free), + (nautilus_file_delete), (nautilus_file_is_gone): Implemented a + call to delete a file and emit the files_removed signal as needed. + + * src/file-manager/fm-directory-view.h, + src/file-manager/fm-directory-view.c + (fm_directory_view_delete_selection), + (fm_directory_view_begin_adding_entries), + (fm_directory_view_add_entry), + (fm_directory_view_done_adding_entries), (display_pending_files), + (add_or_remove_files), (add_files_cb), (remove_files_cb), + (delete_one): Changed the delete implementation to call + nautilus_file_delete and got rid of the explicit call to + delete_selection. The views now will remove their entries in + response to the change in the model. + + * src/file-manager/fm-directory-view-icons.c + (fm_directory_view_icons_remove_entry), + (fm_directory_view_icons_delete_selection), + src/file-manager/fm-directory-view-list.c + (fm_directory_view_list_remove_entry), + (fm_directory_view_list_delete_selection): Eliminated the + delete_selection function in favor of the remove_entry function. + 2000-03-07 Andy Hertzfeld <andy@eazel.com> * libnautilus/gnome-icon-container-dnd.c: @@ -6,7 +45,7 @@ The dragging is a bit too slow, so we might have to limit this to small images, but for now it's there for all of them. - *libnautilus/gnome-icon-container.c: + * libnautilus/gnome-icon-container.c: make the text beneath icons use a sans-serif font (helvetica) at Susan's request. @@ -17,55 +56,55 @@ 2000-03-07 John Sullivan <sullivan@eazel.com> - * src/ntl-view-nautilus.c: - (nautilus_view_try_load_client): Removed recently-added - activate call since Maciej implemented a more general solution. - (destroy_nautilus_view): Removed recently-added - deactivate call since Maciej implemented a more general solution. + * src/ntl-view-nautilus.c: + (nautilus_view_try_load_client): Removed recently-added + activate call since Maciej implemented a more general solution. + (destroy_nautilus_view): Removed recently-added + deactivate call since Maciej implemented a more general solution. 2000-03-07 John Sullivan <sullivan@eazel.com> - Added Stretch/Restore menu items to Settings menu, and made some - other menu mechanism tweaks. - - * src/nautilus-window-menus.c: Gave General Settings an underline - accelerator character. - - * src/file-manager/fm-directory-view.h, - * src/file-manager/fm-directory-view.c: - (fm_directory_view_get_bonobo_ui_handler): New function, exposed - so subclasses can call. - (fm_directory_view_merge_menus), (fm_directory_view_real_merge_menus): - Removed BonoboUIHandler parameter. Updated callers. - * src/file-manager/fm-directory-view-icons.c: - Store react_to_icon_change_idle_id in details. - (fm_directory_view_icons_initialize_class): fill in update_menus - function pointer. - (fm_directory_view_icons_merge_menus): Removed BonoboUIHandler - parameter. - (fm_directory_view-icons_destroy): remove react_to_icon_change_idle_id - if non-zero. - (show_stretch_handles_cb): update menus since stretch item might - have changed state. - (unstretch_icons_cb): update menus since restore item might have - changed state. - (fm_directory_view_icons_compute_menu_item_info): New helper - function used for both context and bonobo menus. - (append_one_context_menu_item): New helper function used for - context menus. - (fm_directory_view_icons_append_selection_context_menu_items), - (fm_directory_view_icons_append_background_context_menu_items): - Use the new helper functions. - (append_bonobo_menu_item), (update_bonobo_menu_item): New helper - functions used for bonobo menus. - (fm_directory_view_icons_merge_menus): include stretch and restore - menu items in Settings menu. - (fm_directory_view_icons_update_menus): update wording and sensitivity - of stretch and restore menu items. - (fm_directory_view_icons_react_to_icon_change_idle_cb): update menus, - since at least Restore item may have changed. - (fm_directory_view_icons_icon_changed_cb): Schedule idle callback - to update menus, since doing it here affects stretching too much. + Added Stretch/Restore menu items to Settings menu, and made some + other menu mechanism tweaks. + + * src/nautilus-window-menus.c: Gave General Settings an underline + accelerator character. + + * src/file-manager/fm-directory-view.h, + * src/file-manager/fm-directory-view.c: + (fm_directory_view_get_bonobo_ui_handler): New function, exposed + so subclasses can call. + (fm_directory_view_merge_menus), (fm_directory_view_real_merge_menus): + Removed BonoboUIHandler parameter. Updated callers. + * src/file-manager/fm-directory-view-icons.c: + Store react_to_icon_change_idle_id in details. + (fm_directory_view_icons_initialize_class): fill in update_menus + function pointer. + (fm_directory_view_icons_merge_menus): Removed BonoboUIHandler + parameter. + (fm_directory_view-icons_destroy): remove react_to_icon_change_idle_id + if non-zero. + (show_stretch_handles_cb): update menus since stretch item might + have changed state. + (unstretch_icons_cb): update menus since restore item might have + changed state. + (fm_directory_view_icons_compute_menu_item_info): New helper + function used for both context and bonobo menus. + (append_one_context_menu_item): New helper function used for + context menus. + (fm_directory_view_icons_append_selection_context_menu_items), + (fm_directory_view_icons_append_background_context_menu_items): + Use the new helper functions. + (append_bonobo_menu_item), (update_bonobo_menu_item): New helper + functions used for bonobo menus. + (fm_directory_view_icons_merge_menus): include stretch and restore + menu items in Settings menu. + (fm_directory_view_icons_update_menus): update wording and sensitivity + of stretch and restore menu items. + (fm_directory_view_icons_react_to_icon_change_idle_cb): update menus, + since at least Restore item may have changed. + (fm_directory_view_icons_icon_changed_cb): Schedule idle callback + to update menus, since doing it here affects stretching too much. 2000-03-07 Maciej Stachowiak <mjs@eazel.com> @@ -75,7 +114,7 @@ bonobo-text-plain for instance. * src/ntl-content-view.c, src/ntl-content-view.h - (nautilus_content_view_set_active): Neew function; intended to be + (nautilus_content_view_set_active): New function; intended to be called when a content view becomes active, which should activate the controls and merge its menu and toolbar items. * ntl-window.c (nautilus_window_real_set_content_view): Call @@ -149,110 +188,110 @@ 2000-03-06 John Sullivan <sullivan@eazel.com> - The file manager now uses Bonobo menu-merging to install - and remove its menu items from the window's menu bar. - I didn't put Zoom In/Zoom Out in the menu bar because - that seems unnecessary once the control works (they're - still in the right-click menu). I haven't yet put - Stretch/Restore in the menu bar, will do so soon. And - now you get a whole bunch of Gtk-CRITICALs when closing - a window because of all the double-destroyed bonobo menu - items (just like the two you used to get). Hope to fix - this soon. Added new "Settings" menu, which needs to be - organized better someday, and will be. - - * components/history/ntl-history-view.c: - (menu_setup): Removed function. - (make_obj): Removed code to set up merged menu. This was - sample code for menu merging; now that we have real menu - merging working elsewhere we don't need this sample. - - * libnautilus/nautilus-string.h, - * libnautilus/nautilus-string.c: - (nautilus_strstrip): New function, strips all occurrences - of a given char from a char *. - (nautilus_self_check_string): Added tests for nautilus_strstrip. - - * src/ntl-view-nautilus.c: - (nautilus_view_try_load_client): Activate the new bonobo control - when it's installed. - (destroy_nautilus_view): Deactivate the bonobo control. - - * src/nautilus-window-menus.c: - edit_menu_info[]: Removed "Preferences..." and preceding separator. - settings_menu_info[]: New menu, added "General Settings..." - (formerly "Preferences...") and "Use Eazel Theme Icons". - main_menu[]: Include settings_menu_info. - (edit_menu_prefs_cb): Renamed to general_settings_cb - (use_eazel_theme_icons_cb): New function, swaps themes. - (update_eazel_theme_menu_item): New function, sets the toggle state - of this menu item based on current theme. - (nautilus_window_initialize_menus): Call update_eazel_theme_menu_item - explicitly, also wire it up to theme change signal. - - * src/ntl-prefs.c: (nautilus_prefs_ui_show): Renamed dialog - from "Preferences" to "General Settings" to match menu item. This - name will probably go away entirely eventually, but may as well - keep it consistent for now. - - * src/file-manager/fm-directory-view.h: (merge_menus): New function - pointer. (update_menus): New function pointer. - (fm_directory_view_update_menus): Prototype for new function. * - src/file-manager/fm-directory-view.c: - (fm_directory_view_initialize_class): Set up merge_menus and - update_menus function pointers. (bonobo_menu_open_cb), - (bonobo_menu_open_in_new_window_cb), (bonobo_menu_delete_cb): New - callback functions with parameters the way Bonobo likes 'em. - (get_bonobo_control): New utility function for getting the - BonoboControl out of an FMDirectoryView. - (bonobo_control_activate_cb): New function, called when the view's - BonoboControl is activated or deactivated. Merges menus on - activate, unsets bonobo container on deactivate. - (fm_directory_view_initialize): Wire up bonobo_control_activate_cb - to "activate" signal of view's bonobo control. - (use_eazel_theme_icons_cb): Removed this function (it's in the - standard Nautilus menus now, not component-dependent). - (delete_one): Added a FIXME comment noting that the view is being - told to delete the entire selection for every selected item. - (fm_directory_view_delete_with_confirm): Moved the guts of - delete_cb into here so it can be conveniently called from both - bonobo menu and right-click menu. (delete_cb): Now just calls - fm_directory_view_delete_with_confirm. - (add_check_menu_item): Removed function, had only been used by - eazel theme icons menu item. - (fm_directory_view_real_append_background_context_menu_items): - Removed eazel theme icons menu item from right-click menu (now - accessible always in the Settings menu). - (compute_menu_item_info): New function, determines current label - and sensitivity for dynamic menu items, common to both bonobo menus - and context menus. Uses nautilus_strstrip to remove underlines used - for accelerators when item is used for context menu. - (append_one_selection_context_menu_item): New helper function, - wraps up common code for constructing a menu item for the - selection-dependent part of the context menu. - (fm_directory_view_real_append_selection_context_menu_items): - Replaced a lot of duplicated code with calls to - append_one_selection_context_menu_item. - (fm_directory_view_real_merge_menus): New funciton. Here lieth the - code to put directory view menu items into the window's menu bar. - (update_one_menu_item): New function, uses compute_menu_item_info - to update the label & sensitivity of one bonobo-style menu item. - (fm_directory_view_real_update_menus): New function, calls - update_one_menu_item on each menu item whose label or sensitivity - is dynamic. - (fm_directory_view_notify_selection_changed): - Call fm_directory_view_update_menus to update menu labels & - sensitivity that depend on the selection. - (fm_directory_view_merge_menus): New function, calls the function pointer. - (fm_directory_view_update_menus): New function, calls the function pointer. - - * src/file-manager/fm-directory-view-icons.c: - (fm_directory_view_icons_initialize_class): Supply function pointer - for merge_menus. - (customize_icon_text_cb): Just added comments about its dual use. - (fm_directory_view_icons_merge_menus): Merge a "Customize Icon Text" - item into the Settings menu. Still need to do the Stretch/Restore items - here. + The file manager now uses Bonobo menu-merging to install + and remove its menu items from the window's menu bar. + I didn't put Zoom In/Zoom Out in the menu bar because + that seems unnecessary once the control works (they're + still in the right-click menu). I haven't yet put + Stretch/Restore in the menu bar, will do so soon. And + now you get a whole bunch of Gtk-CRITICALs when closing + a window because of all the double-destroyed bonobo menu + items (just like the two you used to get). Hope to fix + this soon. Added new "Settings" menu, which needs to be + organized better someday, and will be. + + * components/history/ntl-history-view.c: + (menu_setup): Removed function. + (make_obj): Removed code to set up merged menu. This was + sample code for menu merging; now that we have real menu + merging working elsewhere we don't need this sample. + + * libnautilus/nautilus-string.h, + * libnautilus/nautilus-string.c: + (nautilus_strstrip): New function, strips all occurrences + of a given char from a char *. + (nautilus_self_check_string): Added tests for nautilus_strstrip. + + * src/ntl-view-nautilus.c: + (nautilus_view_try_load_client): Activate the new bonobo control + when it's installed. + (destroy_nautilus_view): Deactivate the bonobo control. + + * src/nautilus-window-menus.c: + edit_menu_info[]: Removed "Preferences..." and preceding separator. + settings_menu_info[]: New menu, added "General Settings..." + (formerly "Preferences...") and "Use Eazel Theme Icons". + main_menu[]: Include settings_menu_info. + (edit_menu_prefs_cb): Renamed to general_settings_cb + (use_eazel_theme_icons_cb): New function, swaps themes. + (update_eazel_theme_menu_item): New function, sets the toggle state + of this menu item based on current theme. + (nautilus_window_initialize_menus): Call update_eazel_theme_menu_item + explicitly, also wire it up to theme change signal. + + * src/ntl-prefs.c: (nautilus_prefs_ui_show): Renamed dialog + from "Preferences" to "General Settings" to match menu item. This + name will probably go away entirely eventually, but may as well + keep it consistent for now. + + * src/file-manager/fm-directory-view.h: (merge_menus): New function + pointer. (update_menus): New function pointer. + (fm_directory_view_update_menus): Prototype for new function. * + src/file-manager/fm-directory-view.c: + (fm_directory_view_initialize_class): Set up merge_menus and + update_menus function pointers. (bonobo_menu_open_cb), + (bonobo_menu_open_in_new_window_cb), (bonobo_menu_delete_cb): New + callback functions with parameters the way Bonobo likes 'em. + (get_bonobo_control): New utility function for getting the + BonoboControl out of an FMDirectoryView. + (bonobo_control_activate_cb): New function, called when the view's + BonoboControl is activated or deactivated. Merges menus on + activate, unsets bonobo container on deactivate. + (fm_directory_view_initialize): Wire up bonobo_control_activate_cb + to "activate" signal of view's bonobo control. + (use_eazel_theme_icons_cb): Removed this function (it's in the + standard Nautilus menus now, not component-dependent). + (delete_one): Added a FIXME comment noting that the view is being + told to delete the entire selection for every selected item. + (fm_directory_view_delete_with_confirm): Moved the guts of + delete_cb into here so it can be conveniently called from both + bonobo menu and right-click menu. (delete_cb): Now just calls + fm_directory_view_delete_with_confirm. + (add_check_menu_item): Removed function, had only been used by + eazel theme icons menu item. + (fm_directory_view_real_append_background_context_menu_items): + Removed eazel theme icons menu item from right-click menu (now + accessible always in the Settings menu). + (compute_menu_item_info): New function, determines current label + and sensitivity for dynamic menu items, common to both bonobo menus + and context menus. Uses nautilus_strstrip to remove underlines used + for accelerators when item is used for context menu. + (append_one_selection_context_menu_item): New helper function, + wraps up common code for constructing a menu item for the + selection-dependent part of the context menu. + (fm_directory_view_real_append_selection_context_menu_items): + Replaced a lot of duplicated code with calls to + append_one_selection_context_menu_item. + (fm_directory_view_real_merge_menus): New funciton. Here lieth the + code to put directory view menu items into the window's menu bar. + (update_one_menu_item): New function, uses compute_menu_item_info + to update the label & sensitivity of one bonobo-style menu item. + (fm_directory_view_real_update_menus): New function, calls + update_one_menu_item on each menu item whose label or sensitivity + is dynamic. + (fm_directory_view_notify_selection_changed): + Call fm_directory_view_update_menus to update menu labels & + sensitivity that depend on the selection. + (fm_directory_view_merge_menus): New function, calls the function pointer. + (fm_directory_view_update_menus): New function, calls the function pointer. + + * src/file-manager/fm-directory-view-icons.c: + (fm_directory_view_icons_initialize_class): Supply function pointer + for merge_menus. + (customize_icon_text_cb): Just added comments about its dual use. + (fm_directory_view_icons_merge_menus): Merge a "Customize Icon Text" + item into the Settings menu. Still need to do the Stretch/Restore items + here. 2000-03-06 Darin Adler <darin@eazel.com> diff --git a/libnautilus-extensions/gnome-icon-container.c b/libnautilus-extensions/gnome-icon-container.c index 7fbd99cf2..20ada54d2 100644 --- a/libnautilus-extensions/gnome-icon-container.c +++ b/libnautilus-extensions/gnome-icon-container.c @@ -71,14 +71,16 @@ /* maximum size allowed for icons at the time they are installed - the user can still stretch them further */ #define MAXIMUM_INITIAL_ICON_SIZE 80 -static void gnome_icon_container_activate_selected_items (GnomeIconContainer *container); -static void gnome_icon_container_initialize_class (GnomeIconContainerClass *class); -static void gnome_icon_container_initialize (GnomeIconContainer *container); -static void update_icon (GnomeIconContainer *container, - GnomeIconContainerIcon *icon); -static void compute_stretch (StretchState *start, - StretchState *current); -static guint icon_get_actual_size (GnomeIconContainerIcon *icon); +static void gnome_icon_container_activate_selected_items (GnomeIconContainer *container); +static void gnome_icon_container_initialize_class (GnomeIconContainerClass *class); +static void gnome_icon_container_initialize (GnomeIconContainer *container); +static void update_icon (GnomeIconContainer *container, + GnomeIconContainerIcon *icon); +static void compute_stretch (StretchState *start, + StretchState *current); +static guint icon_get_actual_size (GnomeIconContainerIcon *icon); +static void remove_icon_from_container (GnomeIconContainer *container, + GnomeIconContainerIcon *icon); NAUTILUS_DEFINE_CLASS_BOILERPLATE (GnomeIconContainer, gnome_icon_container, GNOME_TYPE_CANVAS) @@ -2400,7 +2402,7 @@ gnome_icon_container_clear (GnomeIconContainer *container) GnomeIconContainerDetails *details; GList *p; - g_return_if_fail (container != NULL); + g_return_if_fail (GNOME_IS_ICON_CONTAINER (container)); details = container->details; @@ -2419,8 +2421,8 @@ gnome_icon_container_clear (GnomeIconContainer *container) /* utility routine to remove a single icon from the container */ static void -remove_icon_from_container(GnomeIconContainer *container, - GnomeIconContainerIcon *icon) +remove_icon_from_container (GnomeIconContainer *container, + GnomeIconContainerIcon *icon) { GnomeIconContainerDetails *details; gint icon_x, icon_y; @@ -2458,45 +2460,19 @@ remove_icon_from_container(GnomeIconContainer *container, void gnome_icon_container_activate_selected_items (GnomeIconContainer *container) { - GnomeIconContainerIcon *current_icon; - GList *current_item; + GnomeIconContainerIcon *icon; + GList *p; - g_return_if_fail (container != NULL); + g_return_if_fail (GNOME_IS_ICON_CONTAINER (container)); - for (current_item = container->details->icons; current_item != NULL; current_item = current_item->next) - { - current_icon = (GnomeIconContainerIcon*) current_item->data; - if (current_icon->is_selected) + for (p = container->details->icons; p != NULL; p = p->next) { + icon = p->data; + if (icon->is_selected) { gtk_signal_emit (GTK_OBJECT (container), signals[ACTIVATE], - current_icon->data); - } -} - -/* clear the selected items in the container */ -void -gnome_icon_container_clear_selected_items (GnomeIconContainer *container) -{ - GnomeIconContainerIcon *current_icon; - GnomeIconContainerDetails *details; - GList *current_item, *next_item; - - g_return_if_fail (container != NULL); - - details = container->details; - - set_kbd_current (container, NULL, FALSE); - details->stretch_icon = NULL; - - current_item = details->icons; - while (current_item != NULL) - { - next_item = current_item->next; - current_icon = (GnomeIconContainerIcon*) current_item->data; - if (current_icon->is_selected) - remove_icon_from_container(container, current_icon); - current_item = next_item; - } + icon->data); + } + } } static void @@ -2650,6 +2626,33 @@ gnome_icon_container_add_auto (GnomeIconContainer *container, add_idle (container); } +/** + * gnome_icon_container_remove: + * @container: A GnomeIconContainer. + * @data: Icon from the controller. + * + * Remove the icon with this data. + **/ +gboolean +gnome_icon_container_remove (GnomeIconContainer *container, + NautilusControllerIcon *data) +{ + GnomeIconContainerIcon *icon; + GList *p; + + g_return_val_if_fail (GNOME_IS_ICON_CONTAINER (container), FALSE); + g_return_val_if_fail (data != NULL, FALSE); + + for (p = container->details->icons; p != NULL; p = p->next) { + icon = p->data; + if (icon->data == data) { + remove_icon_from_container (container, icon); + return TRUE; + } + } + return FALSE; +} + /* zooming */ int @@ -2726,7 +2729,7 @@ gnome_icon_container_relayout (GnomeIconContainer *container) guint cols; guint lines; - g_return_if_fail (container != NULL); + g_return_if_fail (GNOME_IS_ICON_CONTAINER (container)); details = container->details; old_grid = details->grid; @@ -2836,7 +2839,7 @@ gnome_icon_container_line_up (GnomeIconContainer *container) guint i, j, k, m; int x, y, dx; - g_return_if_fail (container != NULL); + g_return_if_fail (GNOME_IS_ICON_CONTAINER (container)); details = container->details; grid = details->grid; @@ -2984,20 +2987,18 @@ gnome_icon_container_line_up (GnomeIconContainer *container) GList * gnome_icon_container_get_selection (GnomeIconContainer *container) { - GnomeIconContainerDetails *details; GList *list, *p; - g_return_val_if_fail (container != NULL, FALSE); - - details = container->details; + g_return_val_if_fail (GNOME_IS_ICON_CONTAINER (container), FALSE); list = NULL; - for (p = details->icons; p != NULL; p = p->next) { + for (p = container->details->icons; p != NULL; p = p->next) { GnomeIconContainerIcon *icon; icon = p->data; - if (icon->is_selected) + if (icon->is_selected) { list = g_list_prepend (list, icon->data); + } } return list; diff --git a/libnautilus-extensions/gnome-icon-container.h b/libnautilus-extensions/gnome-icon-container.h index cc29e76c3..548405162 100644 --- a/libnautilus-extensions/gnome-icon-container.h +++ b/libnautilus-extensions/gnome-icon-container.h @@ -73,7 +73,6 @@ void gnome_icon_container_enable_linger_selection (GnomeIconContainer gboolean enable); void gnome_icon_container_clear (GnomeIconContainer *view); -void gnome_icon_container_clear_selected_items (GnomeIconContainer *view); void gnome_icon_container_add (GnomeIconContainer *view, NautilusControllerIcon *icon, int x, @@ -82,6 +81,8 @@ void gnome_icon_container_add (GnomeIconContainer double scale_y); void gnome_icon_container_add_auto (GnomeIconContainer *view, NautilusControllerIcon *icon); +gboolean gnome_icon_container_remove (GnomeIconContainer *view, + NautilusControllerIcon *icon); void gnome_icon_container_relayout (GnomeIconContainer *view); void gnome_icon_container_line_up (GnomeIconContainer *view); diff --git a/libnautilus-extensions/nautilus-directory.c b/libnautilus-extensions/nautilus-directory.c index caa188eed..643c290db 100644 --- a/libnautilus-extensions/nautilus-directory.c +++ b/libnautilus-extensions/nautilus-directory.c @@ -76,6 +76,7 @@ typedef enum { enum { FILES_ADDED, + FILES_REMOVED, LAST_SIGNAL }; @@ -96,7 +97,7 @@ static void nautilus_directory_write_metafile (NautilusDirectory *directory); static void nautilus_directory_request_write_metafile (NautilusDirectory *directory); static void nautilus_directory_remove_write_metafile_idle (NautilusDirectory *directory); -static void nautilus_file_detach (NautilusFile *file); +static void nautilus_file_free (NautilusFile *file); static int nautilus_file_compare_by_type (NautilusFile *file_1, NautilusFile *file_2); static int nautilus_file_compare_for_sort_internal (NautilusFile *file_1, NautilusFile *file_2, @@ -149,6 +150,7 @@ struct NautilusFile NautilusDirectory *directory; GnomeVFSFileInfo *info; + gboolean is_gone; }; static GHashTable* directory_objects; @@ -169,6 +171,13 @@ nautilus_directory_initialize_class (gpointer klass) GTK_SIGNAL_OFFSET (NautilusDirectoryClass, files_added), gtk_marshal_NONE__POINTER, GTK_TYPE_NONE, 1, GTK_TYPE_POINTER); + nautilus_directory_signals[FILES_REMOVED] = + gtk_signal_new ("files_removed", + GTK_RUN_LAST, + object_class->type, + GTK_SIGNAL_OFFSET (NautilusDirectoryClass, files_removed), + gtk_marshal_NONE__POINTER, + GTK_TYPE_NONE, 1, GTK_TYPE_POINTER); gtk_object_class_add_signals (object_class, nautilus_directory_signals, LAST_SIGNAL); } @@ -190,26 +199,26 @@ nautilus_directory_finalize (GtkObject *object) directory = NAUTILUS_DIRECTORY (object); - if (directory->details->write_metafile_idle_id != 0) + if (directory->details->write_metafile_idle_id != 0) { nautilus_directory_write_metafile (directory); + } g_hash_table_remove (directory_objects, directory->details->uri_text); /* Let go of all the files. */ - while (directory->details->files != NULL) { - nautilus_file_detach (directory->details->files->data); - - directory->details->files = g_list_remove_link - (directory->details->files, directory->details->files); - } + g_list_foreach (directory->details->files, (GFunc) nautilus_file_free, NULL); + g_list_free (directory->details->files); g_free (directory->details->uri_text); - if (directory->details->uri != NULL) + if (directory->details->uri != NULL) { gnome_vfs_uri_unref (directory->details->uri); - if (directory->details->metafile_uri != NULL) + } + if (directory->details->metafile_uri != NULL) { gnome_vfs_uri_unref (directory->details->metafile_uri); - if (directory->details->alternate_metafile_uri != NULL) + } + if (directory->details->alternate_metafile_uri != NULL) { gnome_vfs_uri_unref (directory->details->alternate_metafile_uri); + } xmlFreeDoc (directory->details->metafile_tree); g_free (directory->details); @@ -413,22 +422,26 @@ nautilus_directory_write_metafile (NautilusDirectory *directory) At some point, we might want to change this to actually delete the metafile in this case. */ - if (directory->details->metafile_tree == NULL) + if (directory->details->metafile_tree == NULL) { return; + } /* Try the main URI, unless we have already been instructed to use the alternate URI. */ - if (directory->details->use_alternate_metafile) + if (directory->details->use_alternate_metafile) { result = GNOME_VFS_ERROR_ACCESSDENIED; - else + } else { result = nautilus_directory_try_to_write_metafile (directory, directory->details->metafile_uri); + } /* Try the alternate URI if the main one failed. */ - if (result != GNOME_VFS_OK) + if (result != GNOME_VFS_OK) { result = nautilus_directory_try_to_write_metafile (directory, directory->details->alternate_metafile_uri); + } - /* Check for errors. Later this must be reported to the user, not spit out as a warning. */ - if (result != GNOME_VFS_OK) + /* Check for errors. FIXME: Later this must be reported to the user, not spit out as a warning. */ + if (result != GNOME_VFS_OK) { g_warning ("nautilus_directory_write_metafile failed to write metafile - we should report this to the user"); + } } static gboolean @@ -516,21 +529,24 @@ nautilus_make_directory_and_parents (GnomeVFSURI *uri, guint permissions) a possible problem with the parent. */ result = gnome_vfs_make_directory_for_uri (uri, permissions); - if (result != GNOME_VFS_ERROR_NOTFOUND) + if (result != GNOME_VFS_ERROR_NOTFOUND) { return result; + } /* If we can't get a parent, we are done. */ parent_uri = gnome_vfs_uri_get_parent (uri); - if (parent_uri == NULL) + if (parent_uri == NULL) { return result; + } /* If we can get a parent, use a recursive call to create the parent and its parents. */ result = nautilus_make_directory_and_parents (parent_uri, permissions); gnome_vfs_uri_unref (parent_uri); - if (result != GNOME_VFS_OK) + if (result != GNOME_VFS_OK) { return result; + } /* A second try at making the directory after the parents have all been created. @@ -696,9 +712,10 @@ dequeue_pending_idle_cb (gpointer callback_data) static void schedule_dequeue_pending (NautilusDirectory *directory) { - if (directory->details->dequeue_pending_idle_id == 0) + if (directory->details->dequeue_pending_idle_id == 0) { directory->details->dequeue_pending_idle_id = gtk_idle_add (dequeue_pending_idle_cb, directory); + } } static void @@ -727,10 +744,12 @@ static GnomeVFSDirectoryListPosition nautilus_gnome_vfs_directory_list_get_next_position (GnomeVFSDirectoryList *list, GnomeVFSDirectoryListPosition position) { - if (position != GNOME_VFS_DIRECTORY_LIST_POSITION_NONE) + if (position != GNOME_VFS_DIRECTORY_LIST_POSITION_NONE) { return gnome_vfs_directory_list_position_next (position); - if (list == NULL) + } + if (list == NULL) { return GNOME_VFS_DIRECTORY_LIST_POSITION_NONE; + } return gnome_vfs_directory_list_get_first_position (list); } @@ -764,8 +783,9 @@ nautilus_directory_load_cb (GnomeVFSAsyncHandle *handle, } directory->details->directory_load_list_last_handled = last_handled; - if (result != GNOME_VFS_OK) + if (result != GNOME_VFS_OK) { nautilus_directory_load_done (directory, result); + } } void @@ -1182,8 +1202,9 @@ nautilus_file_ref (NautilusFile *file) g_assert (file->directory != NULL); /* Increment the ref count. */ - if (file->ref_count++ != 0) + if (file->ref_count++ != 0) { return; + } /* As soon as someone other than the directory holds a ref, * we need to hold the directory too. */ @@ -1199,20 +1220,25 @@ nautilus_file_unref (NautilusFile *file) g_assert (file->directory != NULL); /* Decrement the ref count. */ - if (--file->ref_count != 0) + if (--file->ref_count != 0) { return; + } /* No references left, so it's time to release our hold on the directory. */ gtk_object_unref (GTK_OBJECT (file->directory)); + if (file->is_gone) { + nautilus_file_free (file); + } } static void -nautilus_file_detach (NautilusFile *file) +nautilus_file_free (NautilusFile *file) { g_assert (file->ref_count == 0); /* Destroy the file object. */ gnome_vfs_file_info_unref (file->info); + g_free (file); } static int @@ -1643,7 +1669,7 @@ nautilus_file_get_owner_as_string (NautilusFile *file) if (password_info == NULL) { - return g_strdup ("unknown owner"); + return g_strdup (_("unknown owner")); } return g_strdup (password_info->pw_name); @@ -1672,7 +1698,7 @@ nautilus_file_get_group_as_string (NautilusFile *file) if (group_info == NULL) { - return g_strdup ("unknown group"); + return g_strdup (_("unknown group")); } return g_strdup (group_info->gr_name); @@ -1689,37 +1715,40 @@ get_directory_item_count_hack (NautilusFile *file, gboolean ignore_invisible_ite char * uri; char * path; - DIR* directory; - int count; - struct dirent * entry; - + DIR* directory; + int count; + struct dirent * entry; + g_assert (nautilus_file_is_directory (file)); - + uri = nautilus_file_get_uri (file); if (nautilus_has_prefix (uri, "file://")) path = uri + 7; else path = uri; - + directory = opendir (path); - + g_free (uri); - - if (!directory) - return 0; + + if (!directory) + return 0; - count = 0; - - while ((entry = readdir(directory)) != NULL) - // Only count invisible items if requested. - if (!ignore_invisible_items || entry->d_name[0] != '.') - count += 1; - - closedir(directory); - - /* This way of getting the count includes . and .., so we subtract those out */ - return count - 2; + count = 0; + + while ((entry = readdir(directory)) != NULL) + // Only count invisible items if requested. + if (!ignore_invisible_items || entry->d_name[0] != '.') + count += 1; + + closedir(directory); + + /* This way of getting the count includes . and .., so we subtract those out */ + if (!ignore_invisible_items) { + count -= 2; + } + return count; } /** @@ -1748,12 +1777,13 @@ nautilus_file_get_size_as_string (NautilusFile *file) int item_count; item_count = get_directory_item_count_hack (file, FALSE); - if (item_count == 0) - return g_strdup ("0 items"); - else if (item_count == 1) - return g_strdup ("1 item"); - else - return g_strdup_printf ("%d items", item_count); + if (item_count == 0) { + return g_strdup (_("0 items")); + } else if (item_count == 1) { + return g_strdup (_("1 item")); + } else { + return g_strdup_printf (_("%d items"), item_count); + } } return gnome_vfs_file_size_to_string (file->info->size); @@ -1777,35 +1807,46 @@ nautilus_file_get_size_as_string (NautilusFile *file) char * nautilus_file_get_string_attribute (NautilusFile *file, const char *attribute_name) { - if (strcmp (attribute_name, "name") == 0) + /* FIXME: Use hash table and switch statement or function pointers for speed? */ + + if (strcmp (attribute_name, "name") == 0) { return nautilus_file_get_name (file); + } - if (strcmp (attribute_name, "type") == 0) + if (strcmp (attribute_name, "type") == 0) { return nautilus_file_get_type_as_string (file); + } - if (strcmp (attribute_name, "size") == 0) + if (strcmp (attribute_name, "size") == 0) { return nautilus_file_get_size_as_string (file); + } - if (strcmp (attribute_name, "date_modified") == 0) + if (strcmp (attribute_name, "date_modified") == 0) { return nautilus_file_get_date_as_string (file, NAUTILUS_DATE_TYPE_MODIFIED); + } - if (strcmp (attribute_name, "date_changed") == 0) + if (strcmp (attribute_name, "date_changed") == 0) { return nautilus_file_get_date_as_string (file, NAUTILUS_DATE_TYPE_CHANGED); + } - if (strcmp (attribute_name, "date_accessed") == 0) - return nautilus_file_get_date_as_string (file, + if (strcmp (attribute_name, "date_accessed") == 0) { + return nautilus_file_get_date_as_string (file, NAUTILUS_DATE_TYPE_ACCESSED); + } - if (strcmp (attribute_name, "permissions") == 0) + if (strcmp (attribute_name, "permissions") == 0) { return nautilus_file_get_permissions_as_string (file); + } - if (strcmp (attribute_name, "owner") == 0) + if (strcmp (attribute_name, "owner") == 0) { return nautilus_file_get_owner_as_string (file); + } - if (strcmp (attribute_name, "group") == 0) + if (strcmp (attribute_name, "group") == 0) { return nautilus_file_get_group_as_string (file); + } return NULL; } @@ -1825,14 +1866,16 @@ nautilus_file_get_type_as_string (NautilusFile *file) { g_return_val_if_fail (file != NULL, NULL); - if (nautilus_file_is_directory (file)) + if (nautilus_file_is_directory (file)) { /* Special-case this so it isn't "special/directory". - * Should this be "folder" instead? + * FIXME: Should this be "folder" instead? */ return g_strdup (_("directory")); + } - if (nautilus_strlen (file->info->mime_type) == 0) + if (nautilus_strlen (file->info->mime_type) == 0) { return g_strdup (_("unknown type")); + } return g_strdup (file->info->mime_type); } @@ -1962,6 +2005,69 @@ nautilus_file_is_executable (NautilusFile *file) } /** + * nautilus_file_delete + * + * Delete this file. + * @file: NautilusFile representing the file in question. + **/ +void +nautilus_file_delete (NautilusFile *file) +{ + char *text_uri; + GnomeVFSResult result; + GList *removed_files; + + g_return_if_fail (file != NULL); + + /* Deleting a file that's already gone is easy. */ + if (file->is_gone) { + return; + } + + /* Do the actual deletion. */ + text_uri = nautilus_file_get_uri (file); + if (nautilus_file_is_directory (file)) { + result = gnome_vfs_remove_directory (text_uri); + } else { + result = gnome_vfs_unlink (text_uri); + } + g_free (text_uri); + + /* Mark the file gone. */ + if (result == GNOME_VFS_OK || result == GNOME_VFS_ERROR_NOTFOUND) { + file->is_gone = TRUE; + + /* Let the directory know it's gone. */ + if (file->directory != NULL) { + g_list_remove (file->directory->details->files, file); + + /* Send out a message. */ + removed_files = g_list_prepend (NULL, file); + gtk_signal_emit (GTK_OBJECT (file->directory), + nautilus_directory_signals[FILES_REMOVED], + removed_files); + g_list_free (removed_files); + } + } +} + +/** + * nautilus_file_is_gone + * + * Check if a file has already been deleted. + * @file: NautilusFile representing the file in question. + * + * Returns: TRUE if the file is already gone. + **/ +gboolean +nautilus_file_is_gone (NautilusFile *file) +{ + g_return_val_if_fail (file != NULL, FALSE); + + return file->is_gone; +} + +/** * nautilus_file_list_ref * * Ref all the files in a list. diff --git a/libnautilus-extensions/nautilus-directory.h b/libnautilus-extensions/nautilus-directory.h index f77ef0183..35058f26b 100644 --- a/libnautilus-extensions/nautilus-directory.h +++ b/libnautilus-extensions/nautilus-directory.h @@ -130,6 +130,7 @@ NautilusFile * nautilus_file_get (const char /* Basic operations on file objects. */ void nautilus_file_ref (NautilusFile *file); void nautilus_file_unref (NautilusFile *file); +void nautilus_file_delete (NautilusFile *file); /* Basic attributes for file objects. */ char * nautilus_file_get_name (NautilusFile *file); @@ -143,6 +144,8 @@ gboolean nautilus_file_is_directory (NautilusFile guint nautilus_file_get_directory_item_count (NautilusFile *file, gboolean ignore_invisible_items); GList * nautilus_file_get_keywords (NautilusFile *file); +void nautilus_file_set_keywords (NautilusFile *file, + GList *keywords); /* Simple getting and setting top-level metadata. */ char * nautilus_file_get_metadata (NautilusFile *file, diff --git a/libnautilus-private/gnome-icon-container.c b/libnautilus-private/gnome-icon-container.c index 7fbd99cf2..20ada54d2 100644 --- a/libnautilus-private/gnome-icon-container.c +++ b/libnautilus-private/gnome-icon-container.c @@ -71,14 +71,16 @@ /* maximum size allowed for icons at the time they are installed - the user can still stretch them further */ #define MAXIMUM_INITIAL_ICON_SIZE 80 -static void gnome_icon_container_activate_selected_items (GnomeIconContainer *container); -static void gnome_icon_container_initialize_class (GnomeIconContainerClass *class); -static void gnome_icon_container_initialize (GnomeIconContainer *container); -static void update_icon (GnomeIconContainer *container, - GnomeIconContainerIcon *icon); -static void compute_stretch (StretchState *start, - StretchState *current); -static guint icon_get_actual_size (GnomeIconContainerIcon *icon); +static void gnome_icon_container_activate_selected_items (GnomeIconContainer *container); +static void gnome_icon_container_initialize_class (GnomeIconContainerClass *class); +static void gnome_icon_container_initialize (GnomeIconContainer *container); +static void update_icon (GnomeIconContainer *container, + GnomeIconContainerIcon *icon); +static void compute_stretch (StretchState *start, + StretchState *current); +static guint icon_get_actual_size (GnomeIconContainerIcon *icon); +static void remove_icon_from_container (GnomeIconContainer *container, + GnomeIconContainerIcon *icon); NAUTILUS_DEFINE_CLASS_BOILERPLATE (GnomeIconContainer, gnome_icon_container, GNOME_TYPE_CANVAS) @@ -2400,7 +2402,7 @@ gnome_icon_container_clear (GnomeIconContainer *container) GnomeIconContainerDetails *details; GList *p; - g_return_if_fail (container != NULL); + g_return_if_fail (GNOME_IS_ICON_CONTAINER (container)); details = container->details; @@ -2419,8 +2421,8 @@ gnome_icon_container_clear (GnomeIconContainer *container) /* utility routine to remove a single icon from the container */ static void -remove_icon_from_container(GnomeIconContainer *container, - GnomeIconContainerIcon *icon) +remove_icon_from_container (GnomeIconContainer *container, + GnomeIconContainerIcon *icon) { GnomeIconContainerDetails *details; gint icon_x, icon_y; @@ -2458,45 +2460,19 @@ remove_icon_from_container(GnomeIconContainer *container, void gnome_icon_container_activate_selected_items (GnomeIconContainer *container) { - GnomeIconContainerIcon *current_icon; - GList *current_item; + GnomeIconContainerIcon *icon; + GList *p; - g_return_if_fail (container != NULL); + g_return_if_fail (GNOME_IS_ICON_CONTAINER (container)); - for (current_item = container->details->icons; current_item != NULL; current_item = current_item->next) - { - current_icon = (GnomeIconContainerIcon*) current_item->data; - if (current_icon->is_selected) + for (p = container->details->icons; p != NULL; p = p->next) { + icon = p->data; + if (icon->is_selected) { gtk_signal_emit (GTK_OBJECT (container), signals[ACTIVATE], - current_icon->data); - } -} - -/* clear the selected items in the container */ -void -gnome_icon_container_clear_selected_items (GnomeIconContainer *container) -{ - GnomeIconContainerIcon *current_icon; - GnomeIconContainerDetails *details; - GList *current_item, *next_item; - - g_return_if_fail (container != NULL); - - details = container->details; - - set_kbd_current (container, NULL, FALSE); - details->stretch_icon = NULL; - - current_item = details->icons; - while (current_item != NULL) - { - next_item = current_item->next; - current_icon = (GnomeIconContainerIcon*) current_item->data; - if (current_icon->is_selected) - remove_icon_from_container(container, current_icon); - current_item = next_item; - } + icon->data); + } + } } static void @@ -2650,6 +2626,33 @@ gnome_icon_container_add_auto (GnomeIconContainer *container, add_idle (container); } +/** + * gnome_icon_container_remove: + * @container: A GnomeIconContainer. + * @data: Icon from the controller. + * + * Remove the icon with this data. + **/ +gboolean +gnome_icon_container_remove (GnomeIconContainer *container, + NautilusControllerIcon *data) +{ + GnomeIconContainerIcon *icon; + GList *p; + + g_return_val_if_fail (GNOME_IS_ICON_CONTAINER (container), FALSE); + g_return_val_if_fail (data != NULL, FALSE); + + for (p = container->details->icons; p != NULL; p = p->next) { + icon = p->data; + if (icon->data == data) { + remove_icon_from_container (container, icon); + return TRUE; + } + } + return FALSE; +} + /* zooming */ int @@ -2726,7 +2729,7 @@ gnome_icon_container_relayout (GnomeIconContainer *container) guint cols; guint lines; - g_return_if_fail (container != NULL); + g_return_if_fail (GNOME_IS_ICON_CONTAINER (container)); details = container->details; old_grid = details->grid; @@ -2836,7 +2839,7 @@ gnome_icon_container_line_up (GnomeIconContainer *container) guint i, j, k, m; int x, y, dx; - g_return_if_fail (container != NULL); + g_return_if_fail (GNOME_IS_ICON_CONTAINER (container)); details = container->details; grid = details->grid; @@ -2984,20 +2987,18 @@ gnome_icon_container_line_up (GnomeIconContainer *container) GList * gnome_icon_container_get_selection (GnomeIconContainer *container) { - GnomeIconContainerDetails *details; GList *list, *p; - g_return_val_if_fail (container != NULL, FALSE); - - details = container->details; + g_return_val_if_fail (GNOME_IS_ICON_CONTAINER (container), FALSE); list = NULL; - for (p = details->icons; p != NULL; p = p->next) { + for (p = container->details->icons; p != NULL; p = p->next) { GnomeIconContainerIcon *icon; icon = p->data; - if (icon->is_selected) + if (icon->is_selected) { list = g_list_prepend (list, icon->data); + } } return list; diff --git a/libnautilus-private/gnome-icon-container.h b/libnautilus-private/gnome-icon-container.h index cc29e76c3..548405162 100644 --- a/libnautilus-private/gnome-icon-container.h +++ b/libnautilus-private/gnome-icon-container.h @@ -73,7 +73,6 @@ void gnome_icon_container_enable_linger_selection (GnomeIconContainer gboolean enable); void gnome_icon_container_clear (GnomeIconContainer *view); -void gnome_icon_container_clear_selected_items (GnomeIconContainer *view); void gnome_icon_container_add (GnomeIconContainer *view, NautilusControllerIcon *icon, int x, @@ -82,6 +81,8 @@ void gnome_icon_container_add (GnomeIconContainer double scale_y); void gnome_icon_container_add_auto (GnomeIconContainer *view, NautilusControllerIcon *icon); +gboolean gnome_icon_container_remove (GnomeIconContainer *view, + NautilusControllerIcon *icon); void gnome_icon_container_relayout (GnomeIconContainer *view); void gnome_icon_container_line_up (GnomeIconContainer *view); diff --git a/libnautilus-private/nautilus-directory.c b/libnautilus-private/nautilus-directory.c index caa188eed..643c290db 100644 --- a/libnautilus-private/nautilus-directory.c +++ b/libnautilus-private/nautilus-directory.c @@ -76,6 +76,7 @@ typedef enum { enum { FILES_ADDED, + FILES_REMOVED, LAST_SIGNAL }; @@ -96,7 +97,7 @@ static void nautilus_directory_write_metafile (NautilusDirectory *directory); static void nautilus_directory_request_write_metafile (NautilusDirectory *directory); static void nautilus_directory_remove_write_metafile_idle (NautilusDirectory *directory); -static void nautilus_file_detach (NautilusFile *file); +static void nautilus_file_free (NautilusFile *file); static int nautilus_file_compare_by_type (NautilusFile *file_1, NautilusFile *file_2); static int nautilus_file_compare_for_sort_internal (NautilusFile *file_1, NautilusFile *file_2, @@ -149,6 +150,7 @@ struct NautilusFile NautilusDirectory *directory; GnomeVFSFileInfo *info; + gboolean is_gone; }; static GHashTable* directory_objects; @@ -169,6 +171,13 @@ nautilus_directory_initialize_class (gpointer klass) GTK_SIGNAL_OFFSET (NautilusDirectoryClass, files_added), gtk_marshal_NONE__POINTER, GTK_TYPE_NONE, 1, GTK_TYPE_POINTER); + nautilus_directory_signals[FILES_REMOVED] = + gtk_signal_new ("files_removed", + GTK_RUN_LAST, + object_class->type, + GTK_SIGNAL_OFFSET (NautilusDirectoryClass, files_removed), + gtk_marshal_NONE__POINTER, + GTK_TYPE_NONE, 1, GTK_TYPE_POINTER); gtk_object_class_add_signals (object_class, nautilus_directory_signals, LAST_SIGNAL); } @@ -190,26 +199,26 @@ nautilus_directory_finalize (GtkObject *object) directory = NAUTILUS_DIRECTORY (object); - if (directory->details->write_metafile_idle_id != 0) + if (directory->details->write_metafile_idle_id != 0) { nautilus_directory_write_metafile (directory); + } g_hash_table_remove (directory_objects, directory->details->uri_text); /* Let go of all the files. */ - while (directory->details->files != NULL) { - nautilus_file_detach (directory->details->files->data); - - directory->details->files = g_list_remove_link - (directory->details->files, directory->details->files); - } + g_list_foreach (directory->details->files, (GFunc) nautilus_file_free, NULL); + g_list_free (directory->details->files); g_free (directory->details->uri_text); - if (directory->details->uri != NULL) + if (directory->details->uri != NULL) { gnome_vfs_uri_unref (directory->details->uri); - if (directory->details->metafile_uri != NULL) + } + if (directory->details->metafile_uri != NULL) { gnome_vfs_uri_unref (directory->details->metafile_uri); - if (directory->details->alternate_metafile_uri != NULL) + } + if (directory->details->alternate_metafile_uri != NULL) { gnome_vfs_uri_unref (directory->details->alternate_metafile_uri); + } xmlFreeDoc (directory->details->metafile_tree); g_free (directory->details); @@ -413,22 +422,26 @@ nautilus_directory_write_metafile (NautilusDirectory *directory) At some point, we might want to change this to actually delete the metafile in this case. */ - if (directory->details->metafile_tree == NULL) + if (directory->details->metafile_tree == NULL) { return; + } /* Try the main URI, unless we have already been instructed to use the alternate URI. */ - if (directory->details->use_alternate_metafile) + if (directory->details->use_alternate_metafile) { result = GNOME_VFS_ERROR_ACCESSDENIED; - else + } else { result = nautilus_directory_try_to_write_metafile (directory, directory->details->metafile_uri); + } /* Try the alternate URI if the main one failed. */ - if (result != GNOME_VFS_OK) + if (result != GNOME_VFS_OK) { result = nautilus_directory_try_to_write_metafile (directory, directory->details->alternate_metafile_uri); + } - /* Check for errors. Later this must be reported to the user, not spit out as a warning. */ - if (result != GNOME_VFS_OK) + /* Check for errors. FIXME: Later this must be reported to the user, not spit out as a warning. */ + if (result != GNOME_VFS_OK) { g_warning ("nautilus_directory_write_metafile failed to write metafile - we should report this to the user"); + } } static gboolean @@ -516,21 +529,24 @@ nautilus_make_directory_and_parents (GnomeVFSURI *uri, guint permissions) a possible problem with the parent. */ result = gnome_vfs_make_directory_for_uri (uri, permissions); - if (result != GNOME_VFS_ERROR_NOTFOUND) + if (result != GNOME_VFS_ERROR_NOTFOUND) { return result; + } /* If we can't get a parent, we are done. */ parent_uri = gnome_vfs_uri_get_parent (uri); - if (parent_uri == NULL) + if (parent_uri == NULL) { return result; + } /* If we can get a parent, use a recursive call to create the parent and its parents. */ result = nautilus_make_directory_and_parents (parent_uri, permissions); gnome_vfs_uri_unref (parent_uri); - if (result != GNOME_VFS_OK) + if (result != GNOME_VFS_OK) { return result; + } /* A second try at making the directory after the parents have all been created. @@ -696,9 +712,10 @@ dequeue_pending_idle_cb (gpointer callback_data) static void schedule_dequeue_pending (NautilusDirectory *directory) { - if (directory->details->dequeue_pending_idle_id == 0) + if (directory->details->dequeue_pending_idle_id == 0) { directory->details->dequeue_pending_idle_id = gtk_idle_add (dequeue_pending_idle_cb, directory); + } } static void @@ -727,10 +744,12 @@ static GnomeVFSDirectoryListPosition nautilus_gnome_vfs_directory_list_get_next_position (GnomeVFSDirectoryList *list, GnomeVFSDirectoryListPosition position) { - if (position != GNOME_VFS_DIRECTORY_LIST_POSITION_NONE) + if (position != GNOME_VFS_DIRECTORY_LIST_POSITION_NONE) { return gnome_vfs_directory_list_position_next (position); - if (list == NULL) + } + if (list == NULL) { return GNOME_VFS_DIRECTORY_LIST_POSITION_NONE; + } return gnome_vfs_directory_list_get_first_position (list); } @@ -764,8 +783,9 @@ nautilus_directory_load_cb (GnomeVFSAsyncHandle *handle, } directory->details->directory_load_list_last_handled = last_handled; - if (result != GNOME_VFS_OK) + if (result != GNOME_VFS_OK) { nautilus_directory_load_done (directory, result); + } } void @@ -1182,8 +1202,9 @@ nautilus_file_ref (NautilusFile *file) g_assert (file->directory != NULL); /* Increment the ref count. */ - if (file->ref_count++ != 0) + if (file->ref_count++ != 0) { return; + } /* As soon as someone other than the directory holds a ref, * we need to hold the directory too. */ @@ -1199,20 +1220,25 @@ nautilus_file_unref (NautilusFile *file) g_assert (file->directory != NULL); /* Decrement the ref count. */ - if (--file->ref_count != 0) + if (--file->ref_count != 0) { return; + } /* No references left, so it's time to release our hold on the directory. */ gtk_object_unref (GTK_OBJECT (file->directory)); + if (file->is_gone) { + nautilus_file_free (file); + } } static void -nautilus_file_detach (NautilusFile *file) +nautilus_file_free (NautilusFile *file) { g_assert (file->ref_count == 0); /* Destroy the file object. */ gnome_vfs_file_info_unref (file->info); + g_free (file); } static int @@ -1643,7 +1669,7 @@ nautilus_file_get_owner_as_string (NautilusFile *file) if (password_info == NULL) { - return g_strdup ("unknown owner"); + return g_strdup (_("unknown owner")); } return g_strdup (password_info->pw_name); @@ -1672,7 +1698,7 @@ nautilus_file_get_group_as_string (NautilusFile *file) if (group_info == NULL) { - return g_strdup ("unknown group"); + return g_strdup (_("unknown group")); } return g_strdup (group_info->gr_name); @@ -1689,37 +1715,40 @@ get_directory_item_count_hack (NautilusFile *file, gboolean ignore_invisible_ite char * uri; char * path; - DIR* directory; - int count; - struct dirent * entry; - + DIR* directory; + int count; + struct dirent * entry; + g_assert (nautilus_file_is_directory (file)); - + uri = nautilus_file_get_uri (file); if (nautilus_has_prefix (uri, "file://")) path = uri + 7; else path = uri; - + directory = opendir (path); - + g_free (uri); - - if (!directory) - return 0; + + if (!directory) + return 0; - count = 0; - - while ((entry = readdir(directory)) != NULL) - // Only count invisible items if requested. - if (!ignore_invisible_items || entry->d_name[0] != '.') - count += 1; - - closedir(directory); - - /* This way of getting the count includes . and .., so we subtract those out */ - return count - 2; + count = 0; + + while ((entry = readdir(directory)) != NULL) + // Only count invisible items if requested. + if (!ignore_invisible_items || entry->d_name[0] != '.') + count += 1; + + closedir(directory); + + /* This way of getting the count includes . and .., so we subtract those out */ + if (!ignore_invisible_items) { + count -= 2; + } + return count; } /** @@ -1748,12 +1777,13 @@ nautilus_file_get_size_as_string (NautilusFile *file) int item_count; item_count = get_directory_item_count_hack (file, FALSE); - if (item_count == 0) - return g_strdup ("0 items"); - else if (item_count == 1) - return g_strdup ("1 item"); - else - return g_strdup_printf ("%d items", item_count); + if (item_count == 0) { + return g_strdup (_("0 items")); + } else if (item_count == 1) { + return g_strdup (_("1 item")); + } else { + return g_strdup_printf (_("%d items"), item_count); + } } return gnome_vfs_file_size_to_string (file->info->size); @@ -1777,35 +1807,46 @@ nautilus_file_get_size_as_string (NautilusFile *file) char * nautilus_file_get_string_attribute (NautilusFile *file, const char *attribute_name) { - if (strcmp (attribute_name, "name") == 0) + /* FIXME: Use hash table and switch statement or function pointers for speed? */ + + if (strcmp (attribute_name, "name") == 0) { return nautilus_file_get_name (file); + } - if (strcmp (attribute_name, "type") == 0) + if (strcmp (attribute_name, "type") == 0) { return nautilus_file_get_type_as_string (file); + } - if (strcmp (attribute_name, "size") == 0) + if (strcmp (attribute_name, "size") == 0) { return nautilus_file_get_size_as_string (file); + } - if (strcmp (attribute_name, "date_modified") == 0) + if (strcmp (attribute_name, "date_modified") == 0) { return nautilus_file_get_date_as_string (file, NAUTILUS_DATE_TYPE_MODIFIED); + } - if (strcmp (attribute_name, "date_changed") == 0) + if (strcmp (attribute_name, "date_changed") == 0) { return nautilus_file_get_date_as_string (file, NAUTILUS_DATE_TYPE_CHANGED); + } - if (strcmp (attribute_name, "date_accessed") == 0) - return nautilus_file_get_date_as_string (file, + if (strcmp (attribute_name, "date_accessed") == 0) { + return nautilus_file_get_date_as_string (file, NAUTILUS_DATE_TYPE_ACCESSED); + } - if (strcmp (attribute_name, "permissions") == 0) + if (strcmp (attribute_name, "permissions") == 0) { return nautilus_file_get_permissions_as_string (file); + } - if (strcmp (attribute_name, "owner") == 0) + if (strcmp (attribute_name, "owner") == 0) { return nautilus_file_get_owner_as_string (file); + } - if (strcmp (attribute_name, "group") == 0) + if (strcmp (attribute_name, "group") == 0) { return nautilus_file_get_group_as_string (file); + } return NULL; } @@ -1825,14 +1866,16 @@ nautilus_file_get_type_as_string (NautilusFile *file) { g_return_val_if_fail (file != NULL, NULL); - if (nautilus_file_is_directory (file)) + if (nautilus_file_is_directory (file)) { /* Special-case this so it isn't "special/directory". - * Should this be "folder" instead? + * FIXME: Should this be "folder" instead? */ return g_strdup (_("directory")); + } - if (nautilus_strlen (file->info->mime_type) == 0) + if (nautilus_strlen (file->info->mime_type) == 0) { return g_strdup (_("unknown type")); + } return g_strdup (file->info->mime_type); } @@ -1962,6 +2005,69 @@ nautilus_file_is_executable (NautilusFile *file) } /** + * nautilus_file_delete + * + * Delete this file. + * @file: NautilusFile representing the file in question. + **/ +void +nautilus_file_delete (NautilusFile *file) +{ + char *text_uri; + GnomeVFSResult result; + GList *removed_files; + + g_return_if_fail (file != NULL); + + /* Deleting a file that's already gone is easy. */ + if (file->is_gone) { + return; + } + + /* Do the actual deletion. */ + text_uri = nautilus_file_get_uri (file); + if (nautilus_file_is_directory (file)) { + result = gnome_vfs_remove_directory (text_uri); + } else { + result = gnome_vfs_unlink (text_uri); + } + g_free (text_uri); + + /* Mark the file gone. */ + if (result == GNOME_VFS_OK || result == GNOME_VFS_ERROR_NOTFOUND) { + file->is_gone = TRUE; + + /* Let the directory know it's gone. */ + if (file->directory != NULL) { + g_list_remove (file->directory->details->files, file); + + /* Send out a message. */ + removed_files = g_list_prepend (NULL, file); + gtk_signal_emit (GTK_OBJECT (file->directory), + nautilus_directory_signals[FILES_REMOVED], + removed_files); + g_list_free (removed_files); + } + } +} + +/** + * nautilus_file_is_gone + * + * Check if a file has already been deleted. + * @file: NautilusFile representing the file in question. + * + * Returns: TRUE if the file is already gone. + **/ +gboolean +nautilus_file_is_gone (NautilusFile *file) +{ + g_return_val_if_fail (file != NULL, FALSE); + + return file->is_gone; +} + +/** * nautilus_file_list_ref * * Ref all the files in a list. diff --git a/libnautilus-private/nautilus-directory.h b/libnautilus-private/nautilus-directory.h index f77ef0183..35058f26b 100644 --- a/libnautilus-private/nautilus-directory.h +++ b/libnautilus-private/nautilus-directory.h @@ -130,6 +130,7 @@ NautilusFile * nautilus_file_get (const char /* Basic operations on file objects. */ void nautilus_file_ref (NautilusFile *file); void nautilus_file_unref (NautilusFile *file); +void nautilus_file_delete (NautilusFile *file); /* Basic attributes for file objects. */ char * nautilus_file_get_name (NautilusFile *file); @@ -143,6 +144,8 @@ gboolean nautilus_file_is_directory (NautilusFile guint nautilus_file_get_directory_item_count (NautilusFile *file, gboolean ignore_invisible_items); GList * nautilus_file_get_keywords (NautilusFile *file); +void nautilus_file_set_keywords (NautilusFile *file, + GList *keywords); /* Simple getting and setting top-level metadata. */ char * nautilus_file_get_metadata (NautilusFile *file, diff --git a/libnautilus/gnome-icon-container.c b/libnautilus/gnome-icon-container.c index 7fbd99cf2..20ada54d2 100644 --- a/libnautilus/gnome-icon-container.c +++ b/libnautilus/gnome-icon-container.c @@ -71,14 +71,16 @@ /* maximum size allowed for icons at the time they are installed - the user can still stretch them further */ #define MAXIMUM_INITIAL_ICON_SIZE 80 -static void gnome_icon_container_activate_selected_items (GnomeIconContainer *container); -static void gnome_icon_container_initialize_class (GnomeIconContainerClass *class); -static void gnome_icon_container_initialize (GnomeIconContainer *container); -static void update_icon (GnomeIconContainer *container, - GnomeIconContainerIcon *icon); -static void compute_stretch (StretchState *start, - StretchState *current); -static guint icon_get_actual_size (GnomeIconContainerIcon *icon); +static void gnome_icon_container_activate_selected_items (GnomeIconContainer *container); +static void gnome_icon_container_initialize_class (GnomeIconContainerClass *class); +static void gnome_icon_container_initialize (GnomeIconContainer *container); +static void update_icon (GnomeIconContainer *container, + GnomeIconContainerIcon *icon); +static void compute_stretch (StretchState *start, + StretchState *current); +static guint icon_get_actual_size (GnomeIconContainerIcon *icon); +static void remove_icon_from_container (GnomeIconContainer *container, + GnomeIconContainerIcon *icon); NAUTILUS_DEFINE_CLASS_BOILERPLATE (GnomeIconContainer, gnome_icon_container, GNOME_TYPE_CANVAS) @@ -2400,7 +2402,7 @@ gnome_icon_container_clear (GnomeIconContainer *container) GnomeIconContainerDetails *details; GList *p; - g_return_if_fail (container != NULL); + g_return_if_fail (GNOME_IS_ICON_CONTAINER (container)); details = container->details; @@ -2419,8 +2421,8 @@ gnome_icon_container_clear (GnomeIconContainer *container) /* utility routine to remove a single icon from the container */ static void -remove_icon_from_container(GnomeIconContainer *container, - GnomeIconContainerIcon *icon) +remove_icon_from_container (GnomeIconContainer *container, + GnomeIconContainerIcon *icon) { GnomeIconContainerDetails *details; gint icon_x, icon_y; @@ -2458,45 +2460,19 @@ remove_icon_from_container(GnomeIconContainer *container, void gnome_icon_container_activate_selected_items (GnomeIconContainer *container) { - GnomeIconContainerIcon *current_icon; - GList *current_item; + GnomeIconContainerIcon *icon; + GList *p; - g_return_if_fail (container != NULL); + g_return_if_fail (GNOME_IS_ICON_CONTAINER (container)); - for (current_item = container->details->icons; current_item != NULL; current_item = current_item->next) - { - current_icon = (GnomeIconContainerIcon*) current_item->data; - if (current_icon->is_selected) + for (p = container->details->icons; p != NULL; p = p->next) { + icon = p->data; + if (icon->is_selected) { gtk_signal_emit (GTK_OBJECT (container), signals[ACTIVATE], - current_icon->data); - } -} - -/* clear the selected items in the container */ -void -gnome_icon_container_clear_selected_items (GnomeIconContainer *container) -{ - GnomeIconContainerIcon *current_icon; - GnomeIconContainerDetails *details; - GList *current_item, *next_item; - - g_return_if_fail (container != NULL); - - details = container->details; - - set_kbd_current (container, NULL, FALSE); - details->stretch_icon = NULL; - - current_item = details->icons; - while (current_item != NULL) - { - next_item = current_item->next; - current_icon = (GnomeIconContainerIcon*) current_item->data; - if (current_icon->is_selected) - remove_icon_from_container(container, current_icon); - current_item = next_item; - } + icon->data); + } + } } static void @@ -2650,6 +2626,33 @@ gnome_icon_container_add_auto (GnomeIconContainer *container, add_idle (container); } +/** + * gnome_icon_container_remove: + * @container: A GnomeIconContainer. + * @data: Icon from the controller. + * + * Remove the icon with this data. + **/ +gboolean +gnome_icon_container_remove (GnomeIconContainer *container, + NautilusControllerIcon *data) +{ + GnomeIconContainerIcon *icon; + GList *p; + + g_return_val_if_fail (GNOME_IS_ICON_CONTAINER (container), FALSE); + g_return_val_if_fail (data != NULL, FALSE); + + for (p = container->details->icons; p != NULL; p = p->next) { + icon = p->data; + if (icon->data == data) { + remove_icon_from_container (container, icon); + return TRUE; + } + } + return FALSE; +} + /* zooming */ int @@ -2726,7 +2729,7 @@ gnome_icon_container_relayout (GnomeIconContainer *container) guint cols; guint lines; - g_return_if_fail (container != NULL); + g_return_if_fail (GNOME_IS_ICON_CONTAINER (container)); details = container->details; old_grid = details->grid; @@ -2836,7 +2839,7 @@ gnome_icon_container_line_up (GnomeIconContainer *container) guint i, j, k, m; int x, y, dx; - g_return_if_fail (container != NULL); + g_return_if_fail (GNOME_IS_ICON_CONTAINER (container)); details = container->details; grid = details->grid; @@ -2984,20 +2987,18 @@ gnome_icon_container_line_up (GnomeIconContainer *container) GList * gnome_icon_container_get_selection (GnomeIconContainer *container) { - GnomeIconContainerDetails *details; GList *list, *p; - g_return_val_if_fail (container != NULL, FALSE); - - details = container->details; + g_return_val_if_fail (GNOME_IS_ICON_CONTAINER (container), FALSE); list = NULL; - for (p = details->icons; p != NULL; p = p->next) { + for (p = container->details->icons; p != NULL; p = p->next) { GnomeIconContainerIcon *icon; icon = p->data; - if (icon->is_selected) + if (icon->is_selected) { list = g_list_prepend (list, icon->data); + } } return list; diff --git a/libnautilus/gnome-icon-container.h b/libnautilus/gnome-icon-container.h index cc29e76c3..548405162 100644 --- a/libnautilus/gnome-icon-container.h +++ b/libnautilus/gnome-icon-container.h @@ -73,7 +73,6 @@ void gnome_icon_container_enable_linger_selection (GnomeIconContainer gboolean enable); void gnome_icon_container_clear (GnomeIconContainer *view); -void gnome_icon_container_clear_selected_items (GnomeIconContainer *view); void gnome_icon_container_add (GnomeIconContainer *view, NautilusControllerIcon *icon, int x, @@ -82,6 +81,8 @@ void gnome_icon_container_add (GnomeIconContainer double scale_y); void gnome_icon_container_add_auto (GnomeIconContainer *view, NautilusControllerIcon *icon); +gboolean gnome_icon_container_remove (GnomeIconContainer *view, + NautilusControllerIcon *icon); void gnome_icon_container_relayout (GnomeIconContainer *view); void gnome_icon_container_line_up (GnomeIconContainer *view); diff --git a/libnautilus/nautilus-directory.c b/libnautilus/nautilus-directory.c index caa188eed..643c290db 100644 --- a/libnautilus/nautilus-directory.c +++ b/libnautilus/nautilus-directory.c @@ -76,6 +76,7 @@ typedef enum { enum { FILES_ADDED, + FILES_REMOVED, LAST_SIGNAL }; @@ -96,7 +97,7 @@ static void nautilus_directory_write_metafile (NautilusDirectory *directory); static void nautilus_directory_request_write_metafile (NautilusDirectory *directory); static void nautilus_directory_remove_write_metafile_idle (NautilusDirectory *directory); -static void nautilus_file_detach (NautilusFile *file); +static void nautilus_file_free (NautilusFile *file); static int nautilus_file_compare_by_type (NautilusFile *file_1, NautilusFile *file_2); static int nautilus_file_compare_for_sort_internal (NautilusFile *file_1, NautilusFile *file_2, @@ -149,6 +150,7 @@ struct NautilusFile NautilusDirectory *directory; GnomeVFSFileInfo *info; + gboolean is_gone; }; static GHashTable* directory_objects; @@ -169,6 +171,13 @@ nautilus_directory_initialize_class (gpointer klass) GTK_SIGNAL_OFFSET (NautilusDirectoryClass, files_added), gtk_marshal_NONE__POINTER, GTK_TYPE_NONE, 1, GTK_TYPE_POINTER); + nautilus_directory_signals[FILES_REMOVED] = + gtk_signal_new ("files_removed", + GTK_RUN_LAST, + object_class->type, + GTK_SIGNAL_OFFSET (NautilusDirectoryClass, files_removed), + gtk_marshal_NONE__POINTER, + GTK_TYPE_NONE, 1, GTK_TYPE_POINTER); gtk_object_class_add_signals (object_class, nautilus_directory_signals, LAST_SIGNAL); } @@ -190,26 +199,26 @@ nautilus_directory_finalize (GtkObject *object) directory = NAUTILUS_DIRECTORY (object); - if (directory->details->write_metafile_idle_id != 0) + if (directory->details->write_metafile_idle_id != 0) { nautilus_directory_write_metafile (directory); + } g_hash_table_remove (directory_objects, directory->details->uri_text); /* Let go of all the files. */ - while (directory->details->files != NULL) { - nautilus_file_detach (directory->details->files->data); - - directory->details->files = g_list_remove_link - (directory->details->files, directory->details->files); - } + g_list_foreach (directory->details->files, (GFunc) nautilus_file_free, NULL); + g_list_free (directory->details->files); g_free (directory->details->uri_text); - if (directory->details->uri != NULL) + if (directory->details->uri != NULL) { gnome_vfs_uri_unref (directory->details->uri); - if (directory->details->metafile_uri != NULL) + } + if (directory->details->metafile_uri != NULL) { gnome_vfs_uri_unref (directory->details->metafile_uri); - if (directory->details->alternate_metafile_uri != NULL) + } + if (directory->details->alternate_metafile_uri != NULL) { gnome_vfs_uri_unref (directory->details->alternate_metafile_uri); + } xmlFreeDoc (directory->details->metafile_tree); g_free (directory->details); @@ -413,22 +422,26 @@ nautilus_directory_write_metafile (NautilusDirectory *directory) At some point, we might want to change this to actually delete the metafile in this case. */ - if (directory->details->metafile_tree == NULL) + if (directory->details->metafile_tree == NULL) { return; + } /* Try the main URI, unless we have already been instructed to use the alternate URI. */ - if (directory->details->use_alternate_metafile) + if (directory->details->use_alternate_metafile) { result = GNOME_VFS_ERROR_ACCESSDENIED; - else + } else { result = nautilus_directory_try_to_write_metafile (directory, directory->details->metafile_uri); + } /* Try the alternate URI if the main one failed. */ - if (result != GNOME_VFS_OK) + if (result != GNOME_VFS_OK) { result = nautilus_directory_try_to_write_metafile (directory, directory->details->alternate_metafile_uri); + } - /* Check for errors. Later this must be reported to the user, not spit out as a warning. */ - if (result != GNOME_VFS_OK) + /* Check for errors. FIXME: Later this must be reported to the user, not spit out as a warning. */ + if (result != GNOME_VFS_OK) { g_warning ("nautilus_directory_write_metafile failed to write metafile - we should report this to the user"); + } } static gboolean @@ -516,21 +529,24 @@ nautilus_make_directory_and_parents (GnomeVFSURI *uri, guint permissions) a possible problem with the parent. */ result = gnome_vfs_make_directory_for_uri (uri, permissions); - if (result != GNOME_VFS_ERROR_NOTFOUND) + if (result != GNOME_VFS_ERROR_NOTFOUND) { return result; + } /* If we can't get a parent, we are done. */ parent_uri = gnome_vfs_uri_get_parent (uri); - if (parent_uri == NULL) + if (parent_uri == NULL) { return result; + } /* If we can get a parent, use a recursive call to create the parent and its parents. */ result = nautilus_make_directory_and_parents (parent_uri, permissions); gnome_vfs_uri_unref (parent_uri); - if (result != GNOME_VFS_OK) + if (result != GNOME_VFS_OK) { return result; + } /* A second try at making the directory after the parents have all been created. @@ -696,9 +712,10 @@ dequeue_pending_idle_cb (gpointer callback_data) static void schedule_dequeue_pending (NautilusDirectory *directory) { - if (directory->details->dequeue_pending_idle_id == 0) + if (directory->details->dequeue_pending_idle_id == 0) { directory->details->dequeue_pending_idle_id = gtk_idle_add (dequeue_pending_idle_cb, directory); + } } static void @@ -727,10 +744,12 @@ static GnomeVFSDirectoryListPosition nautilus_gnome_vfs_directory_list_get_next_position (GnomeVFSDirectoryList *list, GnomeVFSDirectoryListPosition position) { - if (position != GNOME_VFS_DIRECTORY_LIST_POSITION_NONE) + if (position != GNOME_VFS_DIRECTORY_LIST_POSITION_NONE) { return gnome_vfs_directory_list_position_next (position); - if (list == NULL) + } + if (list == NULL) { return GNOME_VFS_DIRECTORY_LIST_POSITION_NONE; + } return gnome_vfs_directory_list_get_first_position (list); } @@ -764,8 +783,9 @@ nautilus_directory_load_cb (GnomeVFSAsyncHandle *handle, } directory->details->directory_load_list_last_handled = last_handled; - if (result != GNOME_VFS_OK) + if (result != GNOME_VFS_OK) { nautilus_directory_load_done (directory, result); + } } void @@ -1182,8 +1202,9 @@ nautilus_file_ref (NautilusFile *file) g_assert (file->directory != NULL); /* Increment the ref count. */ - if (file->ref_count++ != 0) + if (file->ref_count++ != 0) { return; + } /* As soon as someone other than the directory holds a ref, * we need to hold the directory too. */ @@ -1199,20 +1220,25 @@ nautilus_file_unref (NautilusFile *file) g_assert (file->directory != NULL); /* Decrement the ref count. */ - if (--file->ref_count != 0) + if (--file->ref_count != 0) { return; + } /* No references left, so it's time to release our hold on the directory. */ gtk_object_unref (GTK_OBJECT (file->directory)); + if (file->is_gone) { + nautilus_file_free (file); + } } static void -nautilus_file_detach (NautilusFile *file) +nautilus_file_free (NautilusFile *file) { g_assert (file->ref_count == 0); /* Destroy the file object. */ gnome_vfs_file_info_unref (file->info); + g_free (file); } static int @@ -1643,7 +1669,7 @@ nautilus_file_get_owner_as_string (NautilusFile *file) if (password_info == NULL) { - return g_strdup ("unknown owner"); + return g_strdup (_("unknown owner")); } return g_strdup (password_info->pw_name); @@ -1672,7 +1698,7 @@ nautilus_file_get_group_as_string (NautilusFile *file) if (group_info == NULL) { - return g_strdup ("unknown group"); + return g_strdup (_("unknown group")); } return g_strdup (group_info->gr_name); @@ -1689,37 +1715,40 @@ get_directory_item_count_hack (NautilusFile *file, gboolean ignore_invisible_ite char * uri; char * path; - DIR* directory; - int count; - struct dirent * entry; - + DIR* directory; + int count; + struct dirent * entry; + g_assert (nautilus_file_is_directory (file)); - + uri = nautilus_file_get_uri (file); if (nautilus_has_prefix (uri, "file://")) path = uri + 7; else path = uri; - + directory = opendir (path); - + g_free (uri); - - if (!directory) - return 0; + + if (!directory) + return 0; - count = 0; - - while ((entry = readdir(directory)) != NULL) - // Only count invisible items if requested. - if (!ignore_invisible_items || entry->d_name[0] != '.') - count += 1; - - closedir(directory); - - /* This way of getting the count includes . and .., so we subtract those out */ - return count - 2; + count = 0; + + while ((entry = readdir(directory)) != NULL) + // Only count invisible items if requested. + if (!ignore_invisible_items || entry->d_name[0] != '.') + count += 1; + + closedir(directory); + + /* This way of getting the count includes . and .., so we subtract those out */ + if (!ignore_invisible_items) { + count -= 2; + } + return count; } /** @@ -1748,12 +1777,13 @@ nautilus_file_get_size_as_string (NautilusFile *file) int item_count; item_count = get_directory_item_count_hack (file, FALSE); - if (item_count == 0) - return g_strdup ("0 items"); - else if (item_count == 1) - return g_strdup ("1 item"); - else - return g_strdup_printf ("%d items", item_count); + if (item_count == 0) { + return g_strdup (_("0 items")); + } else if (item_count == 1) { + return g_strdup (_("1 item")); + } else { + return g_strdup_printf (_("%d items"), item_count); + } } return gnome_vfs_file_size_to_string (file->info->size); @@ -1777,35 +1807,46 @@ nautilus_file_get_size_as_string (NautilusFile *file) char * nautilus_file_get_string_attribute (NautilusFile *file, const char *attribute_name) { - if (strcmp (attribute_name, "name") == 0) + /* FIXME: Use hash table and switch statement or function pointers for speed? */ + + if (strcmp (attribute_name, "name") == 0) { return nautilus_file_get_name (file); + } - if (strcmp (attribute_name, "type") == 0) + if (strcmp (attribute_name, "type") == 0) { return nautilus_file_get_type_as_string (file); + } - if (strcmp (attribute_name, "size") == 0) + if (strcmp (attribute_name, "size") == 0) { return nautilus_file_get_size_as_string (file); + } - if (strcmp (attribute_name, "date_modified") == 0) + if (strcmp (attribute_name, "date_modified") == 0) { return nautilus_file_get_date_as_string (file, NAUTILUS_DATE_TYPE_MODIFIED); + } - if (strcmp (attribute_name, "date_changed") == 0) + if (strcmp (attribute_name, "date_changed") == 0) { return nautilus_file_get_date_as_string (file, NAUTILUS_DATE_TYPE_CHANGED); + } - if (strcmp (attribute_name, "date_accessed") == 0) - return nautilus_file_get_date_as_string (file, + if (strcmp (attribute_name, "date_accessed") == 0) { + return nautilus_file_get_date_as_string (file, NAUTILUS_DATE_TYPE_ACCESSED); + } - if (strcmp (attribute_name, "permissions") == 0) + if (strcmp (attribute_name, "permissions") == 0) { return nautilus_file_get_permissions_as_string (file); + } - if (strcmp (attribute_name, "owner") == 0) + if (strcmp (attribute_name, "owner") == 0) { return nautilus_file_get_owner_as_string (file); + } - if (strcmp (attribute_name, "group") == 0) + if (strcmp (attribute_name, "group") == 0) { return nautilus_file_get_group_as_string (file); + } return NULL; } @@ -1825,14 +1866,16 @@ nautilus_file_get_type_as_string (NautilusFile *file) { g_return_val_if_fail (file != NULL, NULL); - if (nautilus_file_is_directory (file)) + if (nautilus_file_is_directory (file)) { /* Special-case this so it isn't "special/directory". - * Should this be "folder" instead? + * FIXME: Should this be "folder" instead? */ return g_strdup (_("directory")); + } - if (nautilus_strlen (file->info->mime_type) == 0) + if (nautilus_strlen (file->info->mime_type) == 0) { return g_strdup (_("unknown type")); + } return g_strdup (file->info->mime_type); } @@ -1962,6 +2005,69 @@ nautilus_file_is_executable (NautilusFile *file) } /** + * nautilus_file_delete + * + * Delete this file. + * @file: NautilusFile representing the file in question. + **/ +void +nautilus_file_delete (NautilusFile *file) +{ + char *text_uri; + GnomeVFSResult result; + GList *removed_files; + + g_return_if_fail (file != NULL); + + /* Deleting a file that's already gone is easy. */ + if (file->is_gone) { + return; + } + + /* Do the actual deletion. */ + text_uri = nautilus_file_get_uri (file); + if (nautilus_file_is_directory (file)) { + result = gnome_vfs_remove_directory (text_uri); + } else { + result = gnome_vfs_unlink (text_uri); + } + g_free (text_uri); + + /* Mark the file gone. */ + if (result == GNOME_VFS_OK || result == GNOME_VFS_ERROR_NOTFOUND) { + file->is_gone = TRUE; + + /* Let the directory know it's gone. */ + if (file->directory != NULL) { + g_list_remove (file->directory->details->files, file); + + /* Send out a message. */ + removed_files = g_list_prepend (NULL, file); + gtk_signal_emit (GTK_OBJECT (file->directory), + nautilus_directory_signals[FILES_REMOVED], + removed_files); + g_list_free (removed_files); + } + } +} + +/** + * nautilus_file_is_gone + * + * Check if a file has already been deleted. + * @file: NautilusFile representing the file in question. + * + * Returns: TRUE if the file is already gone. + **/ +gboolean +nautilus_file_is_gone (NautilusFile *file) +{ + g_return_val_if_fail (file != NULL, FALSE); + + return file->is_gone; +} + +/** * nautilus_file_list_ref * * Ref all the files in a list. diff --git a/libnautilus/nautilus-directory.h b/libnautilus/nautilus-directory.h index f77ef0183..35058f26b 100644 --- a/libnautilus/nautilus-directory.h +++ b/libnautilus/nautilus-directory.h @@ -130,6 +130,7 @@ NautilusFile * nautilus_file_get (const char /* Basic operations on file objects. */ void nautilus_file_ref (NautilusFile *file); void nautilus_file_unref (NautilusFile *file); +void nautilus_file_delete (NautilusFile *file); /* Basic attributes for file objects. */ char * nautilus_file_get_name (NautilusFile *file); @@ -143,6 +144,8 @@ gboolean nautilus_file_is_directory (NautilusFile guint nautilus_file_get_directory_item_count (NautilusFile *file, gboolean ignore_invisible_items); GList * nautilus_file_get_keywords (NautilusFile *file); +void nautilus_file_set_keywords (NautilusFile *file, + GList *keywords); /* Simple getting and setting top-level metadata. */ char * nautilus_file_get_metadata (NautilusFile *file, diff --git a/src/file-manager/fm-directory-view-icons.c b/src/file-manager/fm-directory-view-icons.c index 958bbc7cd..561602c4d 100644 --- a/src/file-manager/fm-directory-view-icons.c +++ b/src/file-manager/fm-directory-view-icons.c @@ -72,6 +72,8 @@ static void fm_directory_view_icons_icon_changed_cb FMDirectoryViewIcons *icon_view); static void fm_directory_view_icons_add_entry (FMDirectoryView *view, NautilusFile *file); +static void fm_directory_view_icons_remove_entry (FMDirectoryView *view, + NautilusFile *file); static void fm_directory_view_icons_append_background_context_menu_items (FMDirectoryView *view, GtkMenu *menu); static void fm_directory_view_icons_append_selection_context_menu_items (FMDirectoryView *view, @@ -85,7 +87,6 @@ static void fm_directory_view_icons_bump_zoom_level static gboolean fm_directory_view_icons_can_zoom_in (FMDirectoryView *view); static gboolean fm_directory_view_icons_can_zoom_out (FMDirectoryView *view); static void fm_directory_view_icons_clear (FMDirectoryView *view); -static void fm_directory_view_icons_delete_selection (FMDirectoryView *view); static void fm_directory_view_icons_destroy (GtkObject *view); static void fm_directory_view_icons_done_adding_entries (FMDirectoryView *view); static GList * fm_directory_view_icons_get_selection (FMDirectoryView *view); @@ -140,22 +141,22 @@ fm_directory_view_icons_initialize_class (FMDirectoryViewIconsClass *klass) fm_directory_view_class->clear = fm_directory_view_icons_clear; - fm_directory_view_class->add_entry + fm_directory_view_class->add_entry = fm_directory_view_icons_add_entry; + fm_directory_view_class->remove_entry + = fm_directory_view_icons_remove_entry; fm_directory_view_class->done_adding_entries = fm_directory_view_icons_done_adding_entries; fm_directory_view_class->begin_loading = fm_directory_view_icons_begin_loading; fm_directory_view_class->get_selection - = fm_directory_view_icons_get_selection; + = fm_directory_view_icons_get_selection; fm_directory_view_class->bump_zoom_level = fm_directory_view_icons_bump_zoom_level; fm_directory_view_class->can_zoom_in = fm_directory_view_icons_can_zoom_in; fm_directory_view_class->can_zoom_out = fm_directory_view_icons_can_zoom_out; - fm_directory_view_class->delete_selection - = fm_directory_view_icons_delete_selection; fm_directory_view_class->select_all = fm_directory_view_icons_select_all; fm_directory_view_class->append_selection_context_menu_items @@ -485,8 +486,9 @@ display_icons_not_already_positioned (FMDirectoryViewIcons *view) GList *p; /* FIXME: This will block if there are many files. */ - for (p = view->details->icons_not_positioned; p != NULL; p = p->next) + for (p = view->details->icons_not_positioned; p != NULL; p = p->next) { add_icon_at_free_position (view, p->data); + } nautilus_file_list_free (view->details->icons_not_positioned); view->details->icons_not_positioned = NULL; @@ -521,6 +523,15 @@ fm_directory_view_icons_add_entry (FMDirectoryView *view, NautilusFile *file) } static void +fm_directory_view_icons_remove_entry (FMDirectoryView *view, NautilusFile *file) +{ + if (gnome_icon_container_remove (get_icon_container (FM_DIRECTORY_VIEW_ICONS (view)), + NAUTILUS_CONTROLLER_ICON (file))) { + nautilus_file_unref (file); + } +} + +static void fm_directory_view_icons_done_adding_entries (FMDirectoryView *view) { display_icons_not_already_positioned (FM_DIRECTORY_VIEW_ICONS (view)); @@ -537,13 +548,11 @@ fm_directory_view_icons_begin_loading (FMDirectoryView *view) directory = fm_directory_view_get_model (view); icon_view = FM_DIRECTORY_VIEW_ICONS (view); - fm_directory_view_icons_set_zoom_level ( - icon_view, - nautilus_directory_get_integer_metadata ( - directory, - ICON_VIEW_ZOOM_LEVEL_METADATA_KEY, - icon_view->details->default_zoom_level)); - + fm_directory_view_icons_set_zoom_level + (icon_view, + nautilus_directory_get_integer_metadata (directory, + ICON_VIEW_ZOOM_LEVEL_METADATA_KEY, + icon_view->details->default_zoom_level)); } static NautilusZoomLevel @@ -569,14 +578,15 @@ fm_directory_view_icons_set_zoom_level (FMDirectoryViewIcons *view, new_level <= NAUTILUS_ZOOM_LEVEL_LARGEST); icon_container = get_icon_container (view); - if (gnome_icon_container_get_zoom_level (icon_container) == new_level) + if (gnome_icon_container_get_zoom_level (icon_container) == new_level) { return; + } - nautilus_directory_set_integer_metadata ( - fm_directory_view_get_model (FM_DIRECTORY_VIEW (view)), - ICON_VIEW_ZOOM_LEVEL_METADATA_KEY, - view->details->default_zoom_level, - new_level); + nautilus_directory_set_integer_metadata + (fm_directory_view_get_model (FM_DIRECTORY_VIEW (view)), + ICON_VIEW_ZOOM_LEVEL_METADATA_KEY, + view->details->default_zoom_level, + new_level); gnome_icon_container_set_zoom_level (icon_container, new_level); @@ -664,8 +674,9 @@ fm_directory_view_icons_set_full_icon_text_attribute_names (FMDirectoryViewIcons g_return_if_fail (new_names != NULL); - if (strcmp (new_names, default_icon_text_attribute_names) == 0) + if (strcmp (new_names, default_icon_text_attribute_names) == 0) { return; + } g_free (default_icon_text_attribute_names); default_icon_text_attribute_names = g_strdup (new_names); @@ -729,13 +740,6 @@ fm_directory_view_icons_get_icon_text_attribute_names (FMDirectoryViewIcons *vie return result; } -static void -fm_directory_view_icons_delete_selection(FMDirectoryView *view) -{ - gnome_icon_container_clear_selected_items( - get_icon_container(FM_DIRECTORY_VIEW_ICONS (view))); -} - static GList * fm_directory_view_icons_get_selection (FMDirectoryView *view) { @@ -934,8 +938,9 @@ fm_directory_view_icons_background_changed_cb (NautilusBackground *background, (GTK_WIDGET (get_icon_container (icon_view)))); directory = fm_directory_view_get_model (FM_DIRECTORY_VIEW (icon_view)); - if (directory == NULL) + if (directory == NULL) { return; + } color_spec = nautilus_background_get_color (background); nautilus_directory_set_metadata (directory, diff --git a/src/file-manager/fm-directory-view-list.c b/src/file-manager/fm-directory-view-list.c index f605aca9e..11e9a756e 100644 --- a/src/file-manager/fm-directory-view-list.c +++ b/src/file-manager/fm-directory-view-list.c @@ -94,6 +94,8 @@ static void flist_activate_cb (GtkFList *flist, static void flist_selection_changed_cb (GtkFList *flist, gpointer data); static void fm_directory_view_list_add_entry (FMDirectoryView *view, NautilusFile *file); +static void fm_directory_view_list_remove_entry (FMDirectoryView *view, + NautilusFile *file); static void fm_directory_view_list_background_changed_cb (NautilusBackground *background, FMDirectoryViewList *list_view); @@ -105,7 +107,6 @@ static void fm_directory_view_list_bump_zoom_level (FMDirectoryView *view, static gboolean fm_directory_view_list_can_zoom_in (FMDirectoryView *view); static gboolean fm_directory_view_list_can_zoom_out (FMDirectoryView *view); static void fm_directory_view_list_clear (FMDirectoryView *view); -static void fm_directory_view_list_delete_selection (FMDirectoryView *view); static guint fm_directory_view_list_get_icon_size (FMDirectoryViewList *list_view); static GList *fm_directory_view_list_get_selection (FMDirectoryView *view); static NautilusZoomLevel fm_directory_view_list_get_zoom_level @@ -180,7 +181,7 @@ fm_directory_view_list_initialize_class (gpointer klass) fm_directory_view_class->begin_adding_entries = fm_directory_view_list_begin_adding_entries; fm_directory_view_class->begin_loading = fm_directory_view_list_begin_loading; fm_directory_view_class->add_entry = fm_directory_view_list_add_entry; - fm_directory_view_class->delete_selection = fm_directory_view_list_delete_selection; + fm_directory_view_class->remove_entry = fm_directory_view_list_remove_entry; fm_directory_view_class->done_adding_entries = fm_directory_view_list_done_adding_entries; fm_directory_view_class->get_selection = fm_directory_view_list_get_selection; fm_directory_view_class->bump_zoom_level = fm_directory_view_list_bump_zoom_level; @@ -611,24 +612,19 @@ fm_directory_view_list_add_entry (FMDirectoryView *view, NautilusFile *file) add_to_flist (FM_DIRECTORY_VIEW_LIST (view), file); } -/* remove selected items from the list */ - static void -fm_directory_view_list_delete_selection (FMDirectoryView *view) +fm_directory_view_list_remove_entry (FMDirectoryView *view, NautilusFile *file) { - gint index; - GtkCList *file_list; - GList *selected_list; - + GtkCList *clist; + int row; + g_return_if_fail (FM_IS_DIRECTORY_VIEW_LIST (view)); - file_list = GTK_CLIST (get_flist (FM_DIRECTORY_VIEW_LIST (view))); - selected_list = file_list->selection; - while (selected_list) - { - index = GPOINTER_TO_INT (selected_list->data); - selected_list = selected_list->next; - gtk_clist_remove(file_list, index); + clist = GTK_CLIST (get_flist (FM_DIRECTORY_VIEW_LIST (view))); + row = gtk_clist_find_row_from_data (clist, file); + if (row != -1) { + gtk_clist_remove (clist, row); + nautilus_file_unref (file); } } diff --git a/src/file-manager/fm-directory-view.c b/src/file-manager/fm-directory-view.c index b4ee4fd0e..ce8dfa3a2 100644 --- a/src/file-manager/fm-directory-view.c +++ b/src/file-manager/fm-directory-view.c @@ -56,12 +56,13 @@ enum { ADD_ENTRY, + APPEND_BACKGROUND_CONTEXT_MENU_ITEMS, + APPEND_SELECTION_CONTEXT_MENU_ITEMS, BEGIN_ADDING_ENTRIES, + BEGIN_LOADING, CLEAR, DONE_ADDING_ENTRIES, - BEGIN_LOADING, - APPEND_SELECTION_CONTEXT_MENU_ITEMS, - APPEND_BACKGROUND_CONTEXT_MENU_ITEMS, + REMOVE_ENTRY, LAST_SIGNAL }; @@ -78,8 +79,10 @@ struct _FMDirectoryViewDetails guint display_pending_idle_id; guint add_files_handler_id; + guint remove_files_handler_id; - GList *pending_list; + GList *pending_files_added; + GList *pending_files_removed; gboolean loading; }; @@ -130,13 +133,13 @@ static void disconnect_model_handlers (FMDirectoryView *view); NAUTILUS_DEFINE_CLASS_BOILERPLATE (FMDirectoryView, fm_directory_view, GTK_TYPE_SCROLLED_WINDOW) NAUTILUS_IMPLEMENT_MUST_OVERRIDE_SIGNAL (fm_directory_view, add_entry) -NAUTILUS_IMPLEMENT_MUST_OVERRIDE_SIGNAL (fm_directory_view, clear) -NAUTILUS_IMPLEMENT_MUST_OVERRIDE_SIGNAL (fm_directory_view, delete_selection) -NAUTILUS_IMPLEMENT_MUST_OVERRIDE_SIGNAL (fm_directory_view, get_selection) -NAUTILUS_IMPLEMENT_MUST_OVERRIDE_SIGNAL (fm_directory_view, select_all) NAUTILUS_IMPLEMENT_MUST_OVERRIDE_SIGNAL (fm_directory_view, bump_zoom_level) NAUTILUS_IMPLEMENT_MUST_OVERRIDE_SIGNAL (fm_directory_view, can_zoom_in) NAUTILUS_IMPLEMENT_MUST_OVERRIDE_SIGNAL (fm_directory_view, can_zoom_out) +NAUTILUS_IMPLEMENT_MUST_OVERRIDE_SIGNAL (fm_directory_view, clear) +NAUTILUS_IMPLEMENT_MUST_OVERRIDE_SIGNAL (fm_directory_view, get_selection) +NAUTILUS_IMPLEMENT_MUST_OVERRIDE_SIGNAL (fm_directory_view, remove_entry) +NAUTILUS_IMPLEMENT_MUST_OVERRIDE_SIGNAL (fm_directory_view, select_all) static void fm_directory_view_initialize_class (FMDirectoryViewClass *klass) @@ -168,6 +171,13 @@ fm_directory_view_initialize_class (FMDirectoryViewClass *klass) GTK_SIGNAL_OFFSET (FMDirectoryViewClass, add_entry), gtk_marshal_NONE__BOXED, GTK_TYPE_NONE, 1, GTK_TYPE_BOXED); + fm_directory_view_signals[REMOVE_ENTRY] = + gtk_signal_new ("remove_entry", + GTK_RUN_LAST, + object_class->type, + GTK_SIGNAL_OFFSET (FMDirectoryViewClass, remove_entry), + gtk_marshal_NONE__BOXED, + GTK_TYPE_NONE, 1, GTK_TYPE_BOXED); fm_directory_view_signals[DONE_ADDING_ENTRIES] = gtk_signal_new ("done_adding_entries", GTK_RUN_LAST, @@ -205,13 +215,13 @@ fm_directory_view_initialize_class (FMDirectoryViewClass *klass) /* Function pointers that subclasses must override */ NAUTILUS_ASSIGN_MUST_OVERRIDE_SIGNAL (klass, fm_directory_view, add_entry); - NAUTILUS_ASSIGN_MUST_OVERRIDE_SIGNAL (klass, fm_directory_view, clear); - NAUTILUS_ASSIGN_MUST_OVERRIDE_SIGNAL (klass, fm_directory_view, delete_selection); - NAUTILUS_ASSIGN_MUST_OVERRIDE_SIGNAL (klass, fm_directory_view, get_selection); - NAUTILUS_ASSIGN_MUST_OVERRIDE_SIGNAL (klass, fm_directory_view, select_all); NAUTILUS_ASSIGN_MUST_OVERRIDE_SIGNAL (klass, fm_directory_view, bump_zoom_level); NAUTILUS_ASSIGN_MUST_OVERRIDE_SIGNAL (klass, fm_directory_view, can_zoom_in); NAUTILUS_ASSIGN_MUST_OVERRIDE_SIGNAL (klass, fm_directory_view, can_zoom_out); + NAUTILUS_ASSIGN_MUST_OVERRIDE_SIGNAL (klass, fm_directory_view, clear); + NAUTILUS_ASSIGN_MUST_OVERRIDE_SIGNAL (klass, fm_directory_view, get_selection); + NAUTILUS_ASSIGN_MUST_OVERRIDE_SIGNAL (klass, fm_directory_view, remove_entry); + NAUTILUS_ASSIGN_MUST_OVERRIDE_SIGNAL (klass, fm_directory_view, select_all); } static void @@ -353,8 +363,9 @@ fm_directory_view_destroy (GtkObject *object) gtk_object_unref (GTK_OBJECT (view->details->model)); } - if (view->details->display_selection_idle_id != 0) + if (view->details->display_selection_idle_id != 0) { gtk_idle_remove (view->details->display_selection_idle_id); + } unschedule_display_of_pending_files (view); @@ -595,29 +606,49 @@ zoom_out_cb (GtkMenuItem *item, FMDirectoryView *directory_view) static gboolean display_pending_files (FMDirectoryView *view) { - GList *pending_list; - GList *p; + GList *files_added, *files_removed, *p; + NautilusFile *file; if (view->details->model != NULL && nautilus_directory_are_all_files_seen (view->details->model)) { stop_load (view, FALSE); } - pending_list = view->details->pending_list; - if (pending_list == NULL) { + files_added = view->details->pending_files_added; + files_removed = view->details->pending_files_removed; + if (files_added == NULL && files_removed == NULL) { return FALSE; } - view->details->pending_list = NULL; + view->details->pending_files_added = NULL; + view->details->pending_files_removed = NULL; + + gtk_signal_emit (GTK_OBJECT (view), + fm_directory_view_signals[BEGIN_ADDING_ENTRIES]); - fm_directory_view_begin_adding_entries (view); + for (p = files_added; p != NULL; p = p->next) { + file = p->data; + + if (!nautilus_file_is_gone (file)) { + gtk_signal_emit (GTK_OBJECT (view), + fm_directory_view_signals[ADD_ENTRY], + file); + } + } - for (p = pending_list; p != NULL; p = p->next) { - fm_directory_view_add_entry (view, p->data); + for (p = files_removed; p != NULL; p = p->next) { + file = p->data; + + g_assert (nautilus_file_is_gone (file)); + gtk_signal_emit (GTK_OBJECT (view), + fm_directory_view_signals[REMOVE_ENTRY], + file); } - fm_directory_view_done_adding_entries (view); + gtk_signal_emit (GTK_OBJECT (view), + fm_directory_view_signals[DONE_ADDING_ENTRIES]); - nautilus_file_list_free (pending_list); + nautilus_file_list_free (files_added); + nautilus_file_list_free (files_removed); return TRUE; } @@ -740,6 +771,26 @@ unschedule_display_of_pending_files (FMDirectoryView *view) } static void +add_or_remove_files (FMDirectoryView *view, + GList *files, + GList **pending_list) +{ + /* Put the files on the pending list. */ + nautilus_file_list_ref (files); + *pending_list = g_list_concat (*pending_list, g_list_copy (files)); + + /* If we haven't see all the files yet, then we'll wait for the + * timeout to fire. If we have seen all the files, then we'll use + * an idle instead. + */ + if (nautilus_directory_are_all_files_seen (view->details->model)) { + schedule_idle_display_of_pending_files (view); + } else { + schedule_timeout_display_of_pending_files (view); + } +} + +static void add_files_cb (NautilusDirectory *directory, GList *files, gpointer callback_data) @@ -753,91 +804,43 @@ add_files_cb (NautilusDirectory *directory, g_assert (directory == view->details->model); - /* Put the files on the pending list. */ - nautilus_file_list_ref (files); - view->details->pending_list = g_list_concat - (view->details->pending_list, g_list_copy (files)); - - /* If we haven't see all the files yet, then we'll wait for the - timeout to fire. If we have seen all the files, then we'll use - an idle instead. - */ - if (nautilus_directory_are_all_files_seen (view->details->model)) { - schedule_idle_display_of_pending_files (view); - } else { - schedule_timeout_display_of_pending_files (view); - } + add_or_remove_files (view, files, &view->details->pending_files_added); } - -/** - * fm_directory_view_clear: - * - * Emit the signal to clear the contents of the view. Subclasses must - * override the signal handler for this signal. This is normally called - * only by FMDirectoryView. - * @view: FMDirectoryView to empty. - * - **/ -void -fm_directory_view_clear (FMDirectoryView *view) +static void +remove_files_cb (NautilusDirectory *directory, + GList *files, + gpointer callback_data) { - g_return_if_fail (FM_IS_DIRECTORY_VIEW (view)); + FMDirectoryView *view; - gtk_signal_emit (GTK_OBJECT (view), fm_directory_view_signals[CLEAR]); -} + g_assert (NAUTILUS_IS_DIRECTORY (directory)); + g_assert (files != NULL); -/** - * fm_directory_view_begin_adding_entries: - * - * Emit the signal to prepare for adding a set of entries to the view. - * Subclasses might want to override the signal handler for this signal. - * This is normally called only by FMDirectoryView. - * @view: FMDirectoryView that will soon have new entries added. - * - **/ -void -fm_directory_view_begin_adding_entries (FMDirectoryView *view) -{ - g_return_if_fail (FM_IS_DIRECTORY_VIEW (view)); + view = FM_DIRECTORY_VIEW (callback_data); + + g_assert (directory == view->details->model); - gtk_signal_emit (GTK_OBJECT (view), fm_directory_view_signals[BEGIN_ADDING_ENTRIES]); + add_or_remove_files (view, files, &view->details->pending_files_removed); } + + /** - * fm_directory_view_add_entry: + * fm_directory_view_clear: * - * Emit the signal to add one entry to the view. Subclasses must + * Emit the signal to clear the contents of the view. Subclasses must * override the signal handler for this signal. This is normally called * only by FMDirectoryView. - * @view: FMDirectoryView to add entry to. - * @file: NautilusFile describing entry to add. - * - **/ -void -fm_directory_view_add_entry (FMDirectoryView *view, NautilusFile *file) -{ - g_return_if_fail (FM_IS_DIRECTORY_VIEW (view)); - g_return_if_fail (NAUTILUS_IS_FILE (file)); - - gtk_signal_emit (GTK_OBJECT (view), fm_directory_view_signals[ADD_ENTRY], file); -} - -/** - * fm_directory_view_done_adding_entries: - * - * Emit the signal to clean up after adding a set of entries to the view. - * Subclasses might want to override the signal handler for this signal. - * This is normally called only by FMDirectoryView. - * @view: FMDirectoryView that has just had new entries added. + * @view: FMDirectoryView to empty. * **/ void -fm_directory_view_done_adding_entries (FMDirectoryView *view) +fm_directory_view_clear (FMDirectoryView *view) { g_return_if_fail (FM_IS_DIRECTORY_VIEW (view)); - gtk_signal_emit (GTK_OBJECT (view), fm_directory_view_signals[DONE_ADDING_ENTRIES]); + gtk_signal_emit (GTK_OBJECT (view), fm_directory_view_signals[CLEAR]); } /** @@ -905,15 +908,6 @@ fm_directory_view_can_zoom_out (FMDirectoryView *view) return (* FM_DIRECTORY_VIEW_CLASS (GTK_OBJECT (view)->klass)->can_zoom_out) (view); } -/* fm_directory_view_delete_selection invokes the subclass to delete its selected items */ -void -fm_directory_view_delete_selection (FMDirectoryView *view) -{ - g_return_if_fail (FM_IS_DIRECTORY_VIEW (view)); - - return (* FM_DIRECTORY_VIEW_CLASS (GTK_OBJECT (view)->klass)->delete_selection) (view); -} - /** * fm_directory_view_get_selection: * @@ -990,47 +984,30 @@ fm_directory_view_get_model (FMDirectoryView *view) /* handle the delete command */ /* FIXME: need to handle errors better, and provide feedback for long deletes */ - static void delete_one (gpointer data, gpointer user_data) { - GnomeVFSResult result; NautilusFile *file; - gchar *text_uri; + GtkWidget *error_box; + char *text_uri, *message; g_assert (NAUTILUS_IS_FILE (data)); g_assert (FM_IS_DIRECTORY_VIEW (user_data)); - file = NAUTILUS_FILE(data); - text_uri = nautilus_file_get_uri(file); + file = NAUTILUS_FILE (data); - /* use vfs to actually delete the file or directory */ + nautilus_file_delete (file); - if (nautilus_file_is_directory(file)) - result = gnome_vfs_remove_directory(text_uri); - else - result = gnome_vfs_unlink(text_uri); - - /* remove the file from the model */ - /* FIXME: need to do this soon - nautilus_directory doesn't have anything for this yet? */ - - /* report errors if necessary, or remove the file from the views */ - if (result == GNOME_VFS_OK) - { - /* invoke a method of the view to delete from the model and container */ - /* FIXME: Deleting the entire selection is being called once per selected item! */ - fm_directory_view_delete_selection(FM_DIRECTORY_VIEW(user_data)); - } else - { - GtkWidget *error_box; - gchar *message = g_strdup_printf("Sorry, but %s could not be deleted", text_uri); - error_box = gnome_message_box_new(message, GNOME_MESSAGE_BOX_WARNING, - GNOME_STOCK_BUTTON_OK, NULL); - g_free(message); + /* report errors if necessary */ + if (!nautilus_file_is_gone (file)) { + text_uri = nautilus_file_get_uri (file); + message = g_strdup_printf (_("Sorry, but %s could not be deleted"), + text_uri); + g_free (text_uri); + error_box = gnome_message_box_new (message, GNOME_MESSAGE_BOX_WARNING, + GNOME_STOCK_BUTTON_OK, NULL); + g_free (message); } - - g_free(text_uri); - } static gboolean @@ -1105,9 +1082,9 @@ fm_directory_view_delete_with_confirm (FMDirectoryView *view, GList *files) static void delete_cb (GtkMenuItem *item, GList *files) { - fm_directory_view_delete_with_confirm (FM_DIRECTORY_VIEW (gtk_object_get_data (GTK_OBJECT (item), - "directory_view")), - files); + fm_directory_view_delete_with_confirm + (FM_DIRECTORY_VIEW (gtk_object_get_data (GTK_OBJECT (item), "directory_view")), + files); } /* handle the open command */ @@ -1257,7 +1234,7 @@ fm_directory_view_real_append_selection_context_menu_items (FMDirectoryView *vie item_count, "directory_view", view, - (GtkDestroyNotify)gtk_object_unref, + (GtkDestroyNotify) gtk_object_unref, TRUE, open_cb, files->data); @@ -1267,7 +1244,7 @@ fm_directory_view_real_append_selection_context_menu_items (FMDirectoryView *vie item_count, "directory_view", view, - (GtkDestroyNotify)gtk_object_unref, + (GtkDestroyNotify) gtk_object_unref, TRUE, open_in_new_window_cb, files); @@ -1277,7 +1254,7 @@ fm_directory_view_real_append_selection_context_menu_items (FMDirectoryView *vie item_count, "directory_view", view, - (GtkDestroyNotify)gtk_object_unref, + (GtkDestroyNotify) gtk_object_unref, TRUE, delete_cb, files); @@ -1597,6 +1574,11 @@ fm_directory_view_load_uri (FMDirectoryView *view, "files_added", GTK_SIGNAL_FUNC (add_files_cb), view); + view->details->remove_files_handler_id = gtk_signal_connect + (GTK_OBJECT (view->details->model), + "files_removed", + GTK_SIGNAL_FUNC (remove_files_cb), + view); } @@ -1626,6 +1608,12 @@ disconnect_model_handlers (FMDirectoryView *view) view->details->add_files_handler_id); view->details->add_files_handler_id = 0; } + + if (view->details->remove_files_handler_id != 0) { + gtk_signal_disconnect (GTK_OBJECT (view->details->model), + view->details->remove_files_handler_id); + view->details->remove_files_handler_id = 0; + } } /** diff --git a/src/file-manager/fm-directory-view.h b/src/file-manager/fm-directory-view.h index 24e57b243..b18c274f7 100644 --- a/src/file-manager/fm-directory-view.h +++ b/src/file-manager/fm-directory-view.h @@ -68,6 +68,12 @@ struct _FMDirectoryViewClass { void (* add_entry) (FMDirectoryView *view, NautilusFile *file); + /* The 'remove_entry' signal is emitted to remove one entry from the view. + * It must be replaced by each subclass. + */ + void (* remove_entry) (FMDirectoryView *view, + NautilusFile *file); + /* The 'done_adding_entries' signal is emitted after a set of entries * are added to the view. It can be replaced by a subclass to do any * necessary cleanup (typically, cleanup for code in begin_adding_entries). @@ -110,13 +116,8 @@ struct _FMDirectoryViewClass { * with a function that returns a newly-allocated GList of * NautilusFile pointers. */ - GList * - (* get_selection) (FMDirectoryView *view); + GList * (* get_selection) (FMDirectoryView *view); - /* delete_selection tells the view to delete it's selected items. It's not responsible - for deleting the actual files, just the entry corresponding to them */ - void (* delete_selection) (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, @@ -161,7 +162,6 @@ void fm_directory_view_load_uri (FMDir const char *uri); /* Functions callable from the user interface and elsewhere. */ -void fm_directory_view_delete_selection (FMDirectoryView *view); GList * fm_directory_view_get_selection (FMDirectoryView *view); void fm_directory_view_stop (FMDirectoryView *view); gboolean fm_directory_view_can_zoom_in (FMDirectoryView *view); @@ -175,10 +175,6 @@ void fm_directory_view_select_all (FMDir * that observers might want to connect with. */ void fm_directory_view_clear (FMDirectoryView *view); -void fm_directory_view_begin_adding_entries (FMDirectoryView *view); -void fm_directory_view_add_entry (FMDirectoryView *view, - NautilusFile *file); -void fm_directory_view_done_adding_entries (FMDirectoryView *view); void fm_directory_view_begin_loading (FMDirectoryView *view); /* Hooks for subclasses to call. These are normally called only by |