summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog296
-rw-r--r--Makefile.am1
-rw-r--r--configure.in9
-rw-r--r--libnautilus-extension/Makefile.am50
-rw-r--r--libnautilus-extension/libnautilus-extension.pc.in11
-rw-r--r--libnautilus-extension/nautilus-column-provider.c72
-rw-r--r--libnautilus-extension/nautilus-column-provider.h60
-rw-r--r--libnautilus-extension/nautilus-column.c237
-rw-r--r--libnautilus-extension/nautilus-column.h71
-rw-r--r--libnautilus-extension/nautilus-extension-i18n.h24
-rw-r--r--libnautilus-extension/nautilus-extension-types.c57
-rw-r--r--libnautilus-extension/nautilus-extension-types.h67
-rw-r--r--libnautilus-extension/nautilus-file-info.c202
-rw-r--r--libnautilus-extension/nautilus-file-info.h113
-rw-r--r--libnautilus-extension/nautilus-info-provider.c120
-rw-r--r--libnautilus-extension/nautilus-info-provider.h82
-rw-r--r--libnautilus-extension/nautilus-menu-item.c274
-rw-r--r--libnautilus-extension/nautilus-menu-item.h77
-rw-r--r--libnautilus-extension/nautilus-menu-provider.c110
-rw-r--r--libnautilus-extension/nautilus-menu-provider.h77
-rw-r--r--libnautilus-extension/nautilus-property-page-provider.c74
-rw-r--r--libnautilus-extension/nautilus-property-page-provider.h63
-rw-r--r--libnautilus-extension/nautilus-property-page.c221
-rw-r--r--libnautilus-extension/nautilus-property-page.h70
-rw-r--r--libnautilus-private/Makefile.am11
-rw-r--r--libnautilus-private/apps_nautilus_preferences.schemas.in30
-rw-r--r--libnautilus-private/nautilus-bonobo-extensions.c161
-rw-r--r--libnautilus-private/nautilus-bonobo-extensions.h153
-rw-r--r--libnautilus-private/nautilus-column-chooser.c652
-rw-r--r--libnautilus-private/nautilus-column-chooser.h61
-rw-r--r--libnautilus-private/nautilus-column-utilities.c228
-rw-r--r--libnautilus-private/nautilus-column-utilities.h38
-rw-r--r--libnautilus-private/nautilus-directory-async.c231
-rw-r--r--libnautilus-private/nautilus-directory-private.h7
-rw-r--r--libnautilus-private/nautilus-directory.c3
-rw-r--r--libnautilus-private/nautilus-file-attributes.h1
-rw-r--r--libnautilus-private/nautilus-file-private.h29
-rw-r--r--libnautilus-private/nautilus-file.c386
-rw-r--r--libnautilus-private/nautilus-file.h5
-rw-r--r--libnautilus-private/nautilus-global-preferences.c16
-rw-r--r--libnautilus-private/nautilus-global-preferences.h2
-rw-r--r--libnautilus-private/nautilus-marshal.list1
-rw-r--r--libnautilus-private/nautilus-metadata.h3
-rw-r--r--libnautilus-private/nautilus-module.c258
-rw-r--r--libnautilus-private/nautilus-module.h42
-rw-r--r--src/file-manager/Makefile.am2
-rw-r--r--src/file-manager/fm-bonobo-provider.c629
-rw-r--r--src/file-manager/fm-bonobo-provider.h51
-rw-r--r--src/file-manager/fm-directory-view.c409
-rw-r--r--src/file-manager/fm-list-model.c254
-rw-r--r--src/file-manager/fm-list-model.h17
-rw-r--r--src/file-manager/fm-list-view.c550
-rw-r--r--src/file-manager/fm-properties-window.c254
-rw-r--r--src/file-manager/nautilus-directory-view-ui.xml5
-rw-r--r--src/file-manager/nautilus-list-view-ui.xml16
-rw-r--r--src/nautilus-application.c7
-rw-r--r--src/nautilus-file-management-properties-main.c3
-rw-r--r--src/nautilus-file-management-properties.c268
-rw-r--r--src/nautilus-file-management-properties.glade138
-rw-r--r--src/nautilus-navigation-window-ui.xml10
-rw-r--r--src/nautilus-navigation-window.c14
-rw-r--r--src/nautilus-shell-ui.xml13
-rw-r--r--src/nautilus-window-manage-views.c18
-rw-r--r--src/nautilus-window-menus.c76
-rw-r--r--src/nautilus-window-private.h2
-rw-r--r--src/nautilus-window-toolbars.c62
-rw-r--r--src/nautilus-window.c49
-rw-r--r--src/nautilus-window.h1
68 files changed, 6565 insertions, 1039 deletions
diff --git a/ChangeLog b/ChangeLog
index 00344ab7c..e007583da 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,299 @@
+2004-01-11 Dave Camp <dave@ximian.com>
+
+ * Merged from nautilus-extensions-branch.
+
+2004-01-11 Dave Camp <dave@ximian.com>
+
+ * libnautilus-extension/nautilus-column.c:
+ * libnautilus-extension/nautilus-column.h:
+ * libnautilus-extension/nautilus-menu-item.c:
+ * libnautilus-extension/nautilus-menu-item.h:
+ * libnautilus-extension/nautilus-property-page.c:
+ * libnautilus-extension/nautilus-property-page.h:
+ * libnautilus-private/nautilus-bonobo-extensions.c:
+ (get_extension_menu_item_xml),
+ (nautilus_bonobo_add_extension_item_command),
+ (get_extension_toolbar_item_xml):
+ * libnautilus-private/nautilus-column-chooser.c: (populate_tree),
+ (get_column_iter):
+ * libnautilus-private/nautilus-column-utilities.c:
+ (column_compare):
+ * src/file-manager/fm-list-model.c: (fm_list_model_get_value),
+ (fm_list_model_get_sort_column_id_from_attribute),
+ (fm_list_model_get_attribute_from_sort_column_id),
+ (fm_list_model_get_column_number):
+ * src/file-manager/fm-list-view.c: (apply_column_order):
+ * src/file-manager/fm-properties-window.c:
+ (append_extension_pages):
+ * src/nautilus-file-management-properties.c:
+ (create_icon_caption_menu): Removed the piles of accessors,
+ use gobject properties instead.
+
+2004-01-10 Dave Camp <dave@ximian.com>
+
+ * libnautilus-extension/Makefile.am:
+ * libnautilus-extension/nautilus-column-provider.c:
+ (nautilus_column_provider_base_init),
+ (nautilus_column_provider_get_type),
+ (nautilus_column_provider_get_columns):
+ * libnautilus-extension/nautilus-column-provider.h:
+ * libnautilus-extension/nautilus-column.c: (nautilus_column_new),
+ (nautilus_column_get_name), (nautilus_column_get_attribute),
+ (nautilus_column_set_attribute), (nautilus_column_get_label),
+ (nautilus_column_set_label), (nautilus_column_get_description),
+ (nautilus_column_set_description), (nautilus_column_get_property),
+ (nautilus_column_set_property), (nautilus_column_finalize),
+ (nautilus_column_instance_init), (nautilus_column_class_init),
+ (nautilus_column_get_type):
+ * libnautilus-extension/nautilus-column.h:
+ * libnautilus-extension/nautilus-file-info.c:
+ (nautilus_file_info_get_string_attribute),
+ (nautilus_file_info_add_string_attribute):
+ * libnautilus-extension/nautilus-file-info.h:
+ * libnautilus-private/Makefile.am:
+ * libnautilus-private/apps_nautilus_preferences.schemas.in:
+ * libnautilus-private/nautilus-column-chooser.c:
+ (nautilus_column_chooser_class_init), (update_buttons),
+ (list_changed), (visible_toggled_callback),
+ (selection_changed_callback), (row_deleted_callback),
+ (add_tree_view), (set_selection_visible),
+ (move_up_clicked_callback), (move_down_clicked_callback),
+ (show_clicked_callback), (hide_clicked_callback),
+ (use_default_clicked_callback), (add_buttons), (populate_tree),
+ (nautilus_column_chooser_init), (nautilus_column_chooser_destroy),
+ (nautilus_column_chooser_finalize), (set_visible_columns),
+ (get_column_names), (get_column_iter), (set_column_order),
+ (nautilus_column_chooser_set_settings),
+ (nautilus_column_chooser_get_settings),
+ (nautilus_column_chooser_new):
+ * libnautilus-private/nautilus-column-chooser.h:
+ * libnautilus-private/nautilus-column-utilities.c:
+ (get_builtin_columns), (get_extension_columns),
+ (nautilus_get_all_columns), (nautilus_column_list_copy),
+ (nautilus_column_list_free), (column_compare),
+ (nautilus_sort_columns):
+ * libnautilus-private/nautilus-column-utilities.h:
+ * libnautilus-private/nautilus-file-private.h:
+ * libnautilus-private/nautilus-file.c:
+ (nautilus_file_instance_init), (finalize),
+ (nautilus_file_compare_for_sort_internal),
+ (nautilus_file_compare_for_sort),
+ (nautilus_file_compare_for_sort_by_attribute),
+ (nautilus_file_get_string_attribute),
+ (nautilus_file_invalidate_extension_info_internal),
+ (nautilus_file_add_string_attribute),
+ (nautilus_file_info_providers_done),
+ (nautilus_file_info_iface_init):
+ * libnautilus-private/nautilus-file.h:
+ * libnautilus-private/nautilus-global-preferences.c:
+ * libnautilus-private/nautilus-global-preferences.h:
+ * libnautilus-private/nautilus-metadata.h:
+ * src/file-manager/Makefile.am:
+ * src/file-manager/fm-list-model.c: (fm_list_model_get_n_columns),
+ (fm_list_model_get_column_type), (fm_list_model_get_value),
+ (fm_list_model_compare_func), (fm_list_model_get_sort_column_id),
+ (fm_list_model_set_sort_column_id),
+ (fm_list_model_get_sort_column_id_from_attribute),
+ (fm_list_model_get_attribute_from_sort_column_id),
+ (fm_list_model_add_column), (fm_list_model_get_column_number),
+ (fm_list_model_finalize), (fm_list_model_init):
+ * src/file-manager/fm-list-model.h:
+ * src/file-manager/fm-list-view.c: (sort_column_changed_callback),
+ (apply_visible_columns_foreach), (apply_visible_columns),
+ (apply_column_order), (create_and_set_up_tree_view),
+ (get_visible_columns),
+ (set_visible_columns_from_metadata_and_preferences),
+ (get_column_order),
+ (set_column_order_from_metadata_and_preferences),
+ (set_sort_order_from_metadata_and_preferences),
+ (fm_list_view_begin_loading), (column_editor_response_callback),
+ (column_chooser_changed_callback),
+ (column_chooser_set_from_settings),
+ (column_chooser_use_default_callback), (create_column_editor),
+ (visible_columns_callback), (fm_list_view_merge_menus),
+ (fm_list_view_update_menus), (fm_list_view_reset_to_defaults),
+ (fm_list_view_scale_font_size),
+ (default_visible_columns_changed_callback),
+ (default_column_order_changed_callback), (fm_list_view_dispose),
+ (fm_list_view_finalize), (fm_list_view_class_init),
+ (fm_list_view_instance_init):
+ * src/nautilus-file-management-properties-main.c: (main):
+ * src/nautilus-file-management-properties.c:
+ (columns_changed_callback), (create_icon_caption_menu),
+ (icon_captions_changed_callback), (update_caption_option_menu),
+ (update_icon_captions_from_gconf),
+ (nautilus_file_management_properties_dialog_setup_icon_caption_page
+ ), (set_columns_from_gconf), (use_default_callback),
+ (nautilus_file_management_properties_dialog_setup_list_column_page)
+ , (nautilus_file_management_properties_dialog_setup):
+ * src/nautilus-file-management-properties.glade:
+
+ Added the ability to export column descriptions from extensions,
+ added column editing to the list view.
+
+2003-12-10 Dave Camp <dave@ximian.com>
+
+ * libnautilus-extension/nautilus-file-info.c:
+ (nautilus_file_info_get_uri_scheme):
+ * libnautilus-extension/nautilus-file-info.h:
+ * libnautilus-private/nautilus-file.c:
+ (nautilus_file_info_iface_init): Added a
+ nautilus_file_info_get_uri_scheme convenience function.
+ * libnautilus-extension/nautilus-menu-item.h:
+ * libnautilus-extension/nautilus-menu-item.c:
+ (nautilus_menu_item_get_property),
+ (nautilus_menu_item_set_property),
+ (nautilus_menu_item_class_init): Added a priority text property.
+ * libnautilus-extension/nautilus-menu-provider.h:
+ * libnautilus-extension/nautilus-menu-provider.c:
+ (nautilus_menu_provider_get_file_items): Pass in the GtkWindow,
+ so that callbacks can parent dialogs appropriately.
+ (nautilus_menu_provider_get_background_items),
+ (nautilus_menu_provider_get_toolbar_items): New functions.
+ * libnautilus-private/nautilus-bonobo-extensions.h:
+ * libnautilus-private/nautilus-bonobo-extensions.c:
+ (get_extension_menu_item_xml), (extension_action_callback),
+ (nautilus_bonobo_add_extension_item_command),
+ (nautilus_bonobo_add_extension_item),
+ (get_extension_toolbar_item_xml),
+ (nautilus_bonobo_add_extension_toolbar_item): Move the extension
+ menu/toolbar stuff here.
+ * src/file-manager/fm-bonobo-provider.c:
+ (fm_bonobo_provider_get_file_items): Updated for new API.
+ * src/file-manager/fm-directory-view.c: (add_extension_menu_items),
+ (get_all_extension_menu_items), (reset_extension_actions_menu): Use
+ new nautilus-bonobo-extensions helpers.
+ * src/nautilus-shell-ui.xml:
+ * src/file-manager/nautilus-directory-view-ui.xml:
+ * src/nautilus-navigation-window-ui.xml: Move stuff around.
+ * src/nautilus-window.c: (ui_idle_handler), (real_merge_menus_2),
+ (nautilus_window_constructed), (nautilus_window_class_init):
+ * src/nautilus-window.h:
+ * src/nautilus-navigation-window.c: (real_merge_menus_2),
+ (nautilus_navigation_window_class_init): Move part two of the
+ menu merging to a virtual function.
+ * src/nautilus-window-manage-views.c: (update_for_new_location):
+ * src/nautilus-window-menus.c:
+ (nautilus_window_initialize_menus_part_1), (get_extension_menus),
+ (nautilus_window_load_extension_menus): Load background menu items
+ from the extensions.
+ * src/nautilus-window-private.h:
+ * src/nautilus-window-toolbars.c: (get_extension_toolbar_items),
+ (nautilus_navigation_window_load_extension_toolbar_items):
+ Load toolbar items from the extensions
+
+2003-11-28 Dave Camp <dave@ximian.com>
+
+ * libnautilus-extension/Makefile.am:
+ * libnautilus-extension/nautilus-extension-i18n.h: New file.
+ * libnautilus-extension/nautilus-info-provider.h:
+ * libnautilus-extension/nautilus-file-info.h:
+ * libnautilus-extension/nautilus-file-info.c:
+ (nautilus_file_info_list_copy), (nautilus_file_info_list_free): New
+ functions.
+ * libnautilus-extension/nautilus-menu-item.c:
+ * libnautilus-extension/nautilus-menu-item.h:
+ * libnautilus-extension/nautilus-menu-provider.c:
+ * libnautilus-extension/nautilus-menu-provider.h: New files,
+ allow extensions to provide context menu items.
+ * libnautilus-extension/nautilus-property-page-provider.c:
+ * libnautilus-extension/nautilus-property-page-provider.h:
+ * libnautilus-extension/nautilus-property-page.c:
+ * libnautilus-extension/nautilus-property-page.h: New files,
+ allow extensions to provider property pages.
+ * libnautilus-private/nautilus-module.h:
+ * libnautilus-private/nautilus-module.c: (add_module_objects),
+ (nautilus_module_load_file),
+ (nautilus_module_get_extensions_for_type),
+ (nautilus_module_extension_list_free), (nautilus_module_add_type):
+ New functions.
+ * src/file-manager/Makefile.am:
+ * src/file-manager/fm-bonobo-provider.c:
+ (bonobo_mime_action_data_new), (bonobo_mime_action_data_free),
+ (bonobo_mime_action_activate_callback),
+ (bonobo_mime_action_callback),
+ (bonobo_mime_action_menu_data_destroy_callback),
+ (no_locale_at_end), (get_bonobo_menu_verb_names),
+ (can_handle_multiple_files), (get_menu_items_for_server),
+ (fm_bonobo_provider_get_file_items),
+ (fm_bonobo_provider_menu_provider_iface_init),
+ (bonobo_page_error_message), (get_uri_list),
+ (bonobo_page_activate_callback), (fm_bonobo_provider_get_pages),
+ (fm_bonobo_provider_property_page_provider_iface_init),
+ (fm_bonobo_provider_instance_init),
+ (fm_bonobo_provider_class_init), (fm_bonobo_provider_get_type):
+ * src/file-manager/fm-bonobo-provider.h: Moved the bonobo context
+ menu and property pages here. Export them through the extension
+ interface.
+ * src/file-manager/fm-directory-view.c:
+ (extension_action_callback), (add_extension_menu_items),
+ (get_all_extension_menu_items), (reset_extension_actions_menu),
+ (real_update_menus): Get context menu items from extensions.
+ * src/file-manager/fm-properties-window.c: (clear_extension_pages),
+ (refresh_extension_pages), (properties_window_update),
+ (append_extension_pages), (create_properties_window): Get property
+ pages from extensions.
+ * src/nautilus-application.c: (finish_startup): Add the
+ bonobo provider to the extension manager.
+
+2003-11-20 Dave Camp <dave@ximian.com>
+
+ * Makefile.am:
+ * configure.in:
+ * libnautilus-extension/Makefile.am:
+ * libnautilus-extension/libnautilus-extension.pc.in:
+ * libnautilus-extension/nautilus-extension-types.c:
+ * libnautilus-extension/nautilus-extension-types.h:
+ * libnautilus-extension/nautilus-file-info.c:
+ * libnautilus-extension/nautilus-file-info.h:
+ * libnautilus-extension/nautilus-info-provider.c:
+ * libnautilus-extension/nautilus-info-provider.h:
+ New library for nautilus extensions.
+
+ * libnautilus-private/nautilus-marshal.list:
+ * libnautilus-private/Makefile.am:
+ * libnautilus-private/nautilus-directory-async.c:
+ (nautilus_directory_set_up_request), (lacks_extension_info),
+ (wants_extension_info), (extension_info_cancel),
+ (extension_info_stop), (finish_info_provider),
+ (info_provider_idle_callback), (info_provider_callback),
+ (extension_info_start), (start_or_stop_io),
+ (nautilus_directory_cancel), (cancel_loading_attributes),
+ (file_needs_extension_work_done), (file_needs_work_done),
+ (nautilus_directory_remove_file_from_work_queue),
+ (move_file_to_low_priority_queue), (move_file_to_extension_queue):
+ * libnautilus-private/nautilus-directory-private.h:
+ * libnautilus-private/nautilus-directory.c:
+ (nautilus_directory_init), (nautilus_directory_finalize),
+ (nautilus_directory_notify_files_changed):
+ Add a third queue for extension info, that runs after the high
+ and low priority queues.
+
+ * libnautilus-private/nautilus-file-attributes.h:
+ * libnautilus-private/nautilus-file-operations.c:
+ * libnautilus-private/nautilus-file-private.h:
+ * libnautilus-private/nautilus-file.c:
+ (nautilus_file_invalidate_extension_info_internal),
+ (nautilus_file_invalidate_attributes_internal):
+
+ * libnautilus-private/nautilus-file.c:
+ (nautilus_file_get_type), (nautilus_file_instance_init),
+ (nautilus_file_get_keywords), (nautilus_file_get_type),
+ (nautilus_file_class_init), (nautilus_file_get_vfs_file_info),
+ (nautilus_file_add_emblem), (nautilus_file_info_providers_done),
+ (nautilus_file_info_iface_init): Implement the NautilusFileInfo
+ interface for extensions to use.
+
+ * libnautilus-private/nautilus-module.c: (nautilus_module_load),
+ * libnautilus-private/nautilus-module.h:
+ Module loading code.
+
+ * src/file-manager/fm-directory-view.c: (finish_loading):
+ Request extension info.
+
+ * src/nautilus-application.c: (finish_startup): Initialize the
+ module interface.
+
2004-01-11 Alexander Larsson <alexl@redhat.com>
* libnautilus-private/nautilus-file.c (nautilus_file_get_activation_uri):
diff --git a/Makefile.am b/Makefile.am
index fe4e9e70a..321f8665e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -16,6 +16,7 @@ DESKTOP_SETTINGS_FILES= \
SUBDIRS = \
libnautilus \
+ libnautilus-extension \
cut-n-paste-code \
libbackground \
libnautilus-private \
diff --git a/configure.in b/configure.in
index f3198853d..6e1cf0122 100644
--- a/configure.in
+++ b/configure.in
@@ -325,6 +325,13 @@ AC_SUBST(LIBNAUTILUS_LIBS)
LIBNAUTILUS_IDL_INCLUDES="`$PKG_CONFIG --variable=idldir $LIBNAUTILUS_MODULES | $srcdir/add-include-prefix`"
AC_SUBST(LIBNAUTILUS_IDL_INCLUDES)
+dnl libnautilus-extension
+LIBNAUTILUS_EXTENSION_MODULES="glib-2.0 gtk+-2.0 gnome-vfs-2.0"
+LIBNAUTILUS_EXTENSION_CFLAGS="`$PKG_CONFIG --cflags $LIBNAUTILUS_EXTENSION_MODULES`"
+AC_SUBST(LIBNAUTILUS_EXTENSION_CFLAGS)
+LIBNAUTILUS_EXTENSION_LIBS="`$PKG_CONFIG --libs $LIBNAUTILUS_EXTENSION_MODULES`"
+AC_SUBST(LIBNAUTILUS_EXTENSION_LIBS)
+
dnl core nautilus (must list bonobo-activation and libbonobo because idldir does not respect "requires")
CORE_MODULES="eel-2.0 librsvg-2.0 bonobo-activation-2.0 libbonobo-2.0 libbonoboui-2.0 esound gnome-desktop-2.0 $EXTRA_CORE_MODULES"
CORE_CFLAGS="`$PKG_CONFIG --cflags $CORE_MODULES` $x_cflags"
@@ -408,6 +415,8 @@ libnautilus-adapter/Makefile
libnautilus-private/Makefile
libnautilus/Makefile
libnautilus/libnautilus.pc
+libnautilus-extension/Makefile
+libnautilus-extension/libnautilus-extension.pc
nautilus.spec
po/Makefile.in
src/Makefile
diff --git a/libnautilus-extension/Makefile.am b/libnautilus-extension/Makefile.am
new file mode 100644
index 000000000..743f691d8
--- /dev/null
+++ b/libnautilus-extension/Makefile.am
@@ -0,0 +1,50 @@
+include $(top_srcdir)/Makefile.shared
+
+lib_LTLIBRARIES=libnautilus-extension.la
+
+INCLUDES=\
+ -I$(top_srcdir) \
+ -I$(top_builddir) \
+ $(LIBNAUTILUS_EXTENSION_CFLAGS) \
+ $(DISABLE_DEPRECATED_CFLAGS) \
+ -DDATADIR=\""$(datadir)"\" \
+ $(NULL)
+
+libnautilus_extension_la_LDFLAGS=\
+ -version-info 1:0:0 \
+ $(LIBNAUTILUS_EXTENSION_LIBS) \
+ -no-undefined \
+ $(NULL)
+
+libnautilus_extension_includedir=$(includedir)/nautilus/libnautilus-extension
+
+libnautilus_extension_include_HEADERS= \
+ nautilus-column.h \
+ nautilus-column-provider.h \
+ nautilus-extension-types.h \
+ nautilus-file-info.h \
+ nautilus-menu-item.h \
+ nautilus-menu-provider.h \
+ nautilus-property-page.h \
+ nautilus-property-page-provider.h \
+ nautilus-info-provider.h \
+ $(NULL)
+
+libnautilus_extension_la_SOURCES= \
+ nautilus-column.c \
+ nautilus-column-provider.c \
+ nautilus-extension-types.c \
+ nautilus-file-info.c \
+ nautilus-menu-item.c \
+ nautilus-menu-provider.c \
+ nautilus-property-page.c \
+ nautilus-property-page-provider.c \
+ nautilus-info-provider.c \
+ $(NULL)
+
+pkgconfigdir=$(libdir)/pkgconfig
+pkgconfig_DATA=libnautilus-extension.pc
+
+EXTRA_DIST = \
+ libnautilus-extension.pc.in \
+ $(NULL)
diff --git a/libnautilus-extension/libnautilus-extension.pc.in b/libnautilus-extension/libnautilus-extension.pc.in
new file mode 100644
index 000000000..5286e9b9b
--- /dev/null
+++ b/libnautilus-extension/libnautilus-extension.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: libnautilus-extension
+Description: A library to create Nautilus view extensions
+Version: @VERSION@
+Requires: glib-2.0 gtk+-2.0 gnome-vfs-2.0
+Libs: -L${libdir} -lnautilus-extension
+Cflags: -I${includedir}/nautilus
diff --git a/libnautilus-extension/nautilus-column-provider.c b/libnautilus-extension/nautilus-column-provider.c
new file mode 100644
index 000000000..eff660ad0
--- /dev/null
+++ b/libnautilus-extension/nautilus-column-provider.c
@@ -0,0 +1,72 @@
+/*
+ * nautilus-column-provider.c - Interface for Nautilus extensions
+ * that provide column specifications.
+ *
+ * Copyright (C) 2003 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Author: Dave Camp <dave@ximian.com>
+ *
+ */
+
+#include <config.h>
+#include "nautilus-column-provider.h"
+
+#include <glib-object.h>
+
+static void
+nautilus_column_provider_base_init (gpointer g_class)
+{
+}
+
+GType
+nautilus_column_provider_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type) {
+ static const GTypeInfo info = {
+ sizeof (NautilusColumnProviderIface),
+ nautilus_column_provider_base_init,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ 0,
+ 0,
+ NULL
+ };
+
+ type = g_type_register_static (G_TYPE_INTERFACE,
+ "NautilusColumnProvider",
+ &info, 0);
+ g_type_interface_add_prerequisite (type, G_TYPE_OBJECT);
+ }
+
+ return type;
+}
+
+GList *
+nautilus_column_provider_get_columns (NautilusColumnProvider *provider)
+{
+ g_return_val_if_fail (NAUTILUS_IS_COLUMN_PROVIDER (provider), NULL);
+ g_return_val_if_fail (NAUTILUS_COLUMN_PROVIDER_GET_IFACE (provider)->get_columns != NULL, NULL);
+
+ return NAUTILUS_COLUMN_PROVIDER_GET_IFACE (provider)->get_columns
+ (provider);
+}
+
+
diff --git a/libnautilus-extension/nautilus-column-provider.h b/libnautilus-extension/nautilus-column-provider.h
new file mode 100644
index 000000000..630e88ac4
--- /dev/null
+++ b/libnautilus-extension/nautilus-column-provider.h
@@ -0,0 +1,60 @@
+/*
+ * nautilus-column-provider.h - Interface for Nautilus extensions that
+ * provide column descriptions.
+ *
+ * Copyright (C) 2003 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Author: Dave Camp <dave@ximian.com>
+ *
+ */
+
+/* This interface is implemented by Nautilus extensions that want to
+ * add columns to the list view and details to the icon view.
+ * Extensions are asked for a list of columns to display. Each
+ * returned column refers to a string attribute which can be filled in
+ * by NautilusInfoProvider */
+
+#ifndef NAUTILUS_COLUMN_PROVIDER_H
+#define NAUTILUS_COLUMN_PROVIDER_H
+
+#include <glib-object.h>
+#include "nautilus-extension-types.h"
+#include "nautilus-column.h"
+
+G_BEGIN_DECLS
+
+#define NAUTILUS_TYPE_COLUMN_PROVIDER (nautilus_column_provider_get_type ())
+#define NAUTILUS_COLUMN_PROVIDER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NAUTILUS_TYPE_COLUMN_PROVIDER, NautilusColumnProvider))
+#define NAUTILUS_IS_COLUMN_PROVIDER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NAUTILUS_TYPE_COLUMN_PROVIDER))
+#define NAUTILUS_COLUMN_PROVIDER_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), NAUTILUS_TYPE_COLUMN_PROVIDER, NautilusColumnProviderIface))
+
+typedef struct _NautilusColumnProvider NautilusColumnProvider;
+typedef struct _NautilusColumnProviderIface NautilusColumnProviderIface;
+
+struct _NautilusColumnProviderIface {
+ GTypeInterface g_iface;
+
+ GList *(*get_columns) (NautilusColumnProvider *provider);
+};
+
+/* Interface Functions */
+GType nautilus_column_provider_get_type (void);
+GList *nautilus_column_provider_get_columns (NautilusColumnProvider *provider);
+
+G_END_DECLS
+
+#endif
diff --git a/libnautilus-extension/nautilus-column.c b/libnautilus-extension/nautilus-column.c
new file mode 100644
index 000000000..1679f0ca8
--- /dev/null
+++ b/libnautilus-extension/nautilus-column.c
@@ -0,0 +1,237 @@
+/*
+ * nautilus-column.c - Info columns exported by NautilusColumnProvider
+ * objects.
+ *
+ * Copyright (C) 2003 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Author: Dave Camp <dave@ximian.com>
+ *
+ */
+
+#include <config.h>
+#include "nautilus-column.h"
+#include "nautilus-extension-i18n.h"
+
+enum {
+ PROP_0,
+ PROP_NAME,
+ PROP_ATTRIBUTE,
+ PROP_LABEL,
+ PROP_DESCRIPTION,
+ PROP_XALIGN,
+ LAST_PROP
+};
+
+struct _NautilusColumnDetails {
+ char *name;
+ char *attribute;
+ char *label;
+ char *description;
+ float xalign;
+};
+
+NautilusColumn *
+nautilus_column_new (const char *name,
+ const char *attribute,
+ const char *label,
+ const char *description)
+{
+ NautilusColumn *column;
+
+ g_return_val_if_fail (name != NULL, NULL);
+ g_return_val_if_fail (attribute != NULL, NULL);
+ g_return_val_if_fail (label != NULL, NULL);
+ g_return_val_if_fail (description != NULL, NULL);
+
+ column = g_object_new (NAUTILUS_TYPE_COLUMN,
+ "name", name,
+ "attribute", attribute,
+ "label", label,
+ "description", description,
+ NULL);
+
+ return column;
+}
+
+static void
+nautilus_column_get_property (GObject *object,
+ guint param_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ NautilusColumn *column;
+
+ column = NAUTILUS_COLUMN (object);
+
+ switch (param_id) {
+ case PROP_NAME :
+ g_value_set_string (value, column->details->name);
+ break;
+ case PROP_ATTRIBUTE :
+ g_value_set_string (value, column->details->attribute);
+ break;
+ case PROP_LABEL :
+ g_value_set_string (value, column->details->label);
+ break;
+ case PROP_DESCRIPTION :
+ g_value_set_string (value, column->details->description);
+ break;
+ case PROP_XALIGN :
+ g_value_set_float (value, column->details->xalign);
+ break;
+ default :
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+ break;
+ }
+}
+
+static void
+nautilus_column_set_property (GObject *object,
+ guint param_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ NautilusColumn *column;
+
+ column = NAUTILUS_COLUMN (object);
+
+ switch (param_id) {
+ case PROP_NAME :
+ g_free (column->details->name);
+ column->details->name = g_strdup (g_value_get_string (value));
+ g_object_notify (object, "name");
+ break;
+ case PROP_ATTRIBUTE :
+ g_free (column->details->attribute);
+ column->details->attribute = g_strdup (g_value_get_string (value));
+ g_object_notify (object, "attribute");
+ break;
+ case PROP_LABEL :
+ g_free (column->details->label);
+ column->details->label = g_strdup (g_value_get_string (value));
+ g_object_notify (object, "label");
+ break;
+ case PROP_DESCRIPTION :
+ g_free (column->details->description);
+ column->details->description = g_strdup (g_value_get_string (value));
+ g_object_notify (object, "description");
+ break;
+ case PROP_XALIGN :
+ column->details->xalign = g_value_get_float (value);
+ g_object_notify (object, "xalign");
+ break;
+ default :
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+ break;
+ }
+}
+
+static void
+nautilus_column_finalize (GObject *object)
+{
+ NautilusColumn *column;
+
+ column = NAUTILUS_COLUMN (object);
+
+ g_free (column->details->name);
+ g_free (column->details->attribute);
+ g_free (column->details->label);
+ g_free (column->details->description);
+
+ g_free (column->details);
+}
+
+static void
+nautilus_column_instance_init (NautilusColumn *column)
+{
+ column->details = g_new0 (NautilusColumnDetails, 1);
+ column->details->xalign = 0.0;
+}
+
+static void
+nautilus_column_class_init (NautilusColumnClass *class)
+{
+ G_OBJECT_CLASS (class)->finalize = nautilus_column_finalize;
+ G_OBJECT_CLASS (class)->get_property = nautilus_column_get_property;
+ G_OBJECT_CLASS (class)->set_property = nautilus_column_set_property;
+
+ g_object_class_install_property (G_OBJECT_CLASS (class),
+ PROP_NAME,
+ g_param_spec_string ("name",
+ _("Name"),
+ _("Name of the column"),
+ NULL,
+ G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE | G_PARAM_READABLE));
+ g_object_class_install_property (G_OBJECT_CLASS (class),
+ PROP_ATTRIBUTE,
+ g_param_spec_string ("attribute",
+ _("Attribute"),
+ _("The attribute name to display"),
+ NULL,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (G_OBJECT_CLASS (class),
+ PROP_LABEL,
+ g_param_spec_string ("label",
+ _("Label"),
+ _("Label to display in the column"),
+ NULL,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (G_OBJECT_CLASS (class),
+ PROP_DESCRIPTION,
+ g_param_spec_string ("description",
+ _("Description"),
+ _("A user-visible description of the column"),
+ NULL,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (G_OBJECT_CLASS (class),
+ PROP_XALIGN,
+ g_param_spec_float ("xalign",
+ _("xalign"),
+ _("The x-alignment of the column"),
+ 0.0,
+ 1.0,
+ 0.0,
+ G_PARAM_READWRITE));
+}
+
+GType
+nautilus_column_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type) {
+ static const GTypeInfo info = {
+ sizeof (NautilusColumnClass),
+ NULL,
+ NULL,
+ (GClassInitFunc)nautilus_column_class_init,
+ NULL,
+ NULL,
+ sizeof (NautilusColumn),
+ 0,
+ (GInstanceInitFunc)nautilus_column_instance_init
+ };
+
+ type = g_type_register_static
+ (G_TYPE_OBJECT,
+ "NautilusColumn",
+ &info, 0);
+ }
+
+ return type;
+}
diff --git a/libnautilus-extension/nautilus-column.h b/libnautilus-extension/nautilus-column.h
new file mode 100644
index 000000000..8ad627a9b
--- /dev/null
+++ b/libnautilus-extension/nautilus-column.h
@@ -0,0 +1,71 @@
+/*
+ * nautilus-column.h - Info columns exported by
+ * NautilusColumnProvider objects.
+ *
+ * Copyright (C) 2003 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Author: Dave Camp <dave@ximian.com>
+ *
+ */
+
+#ifndef NAUTILUS_COLUMN_H
+#define NAUTILUS_COLUMN_H
+
+#include <glib-object.h>
+#include "nautilus-extension-types.h"
+
+G_BEGIN_DECLS
+
+#define NAUTILUS_TYPE_COLUMN (nautilus_column_get_type())
+#define NAUTILUS_COLUMN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NAUTILUS_TYPE_COLUMN, NautilusColumn))
+#define NAUTILUS_COLUMN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_COLUMN, NautilusColumnClass))
+#define NAUTILUS_INFO_IS_COLUMN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NAUTILUS_TYPE_COLUMN))
+#define NAUTILUS_INFO_IS_COLUMN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NAUTILUS_TYPE_COLUMN))
+#define NAUTILUS_COLUMN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), NAUTILUS_TYPE_COLUMN, NautilusColumnClass))
+
+typedef struct _NautilusColumn NautilusColumn;
+typedef struct _NautilusColumnDetails NautilusColumnDetails;
+typedef struct _NautilusColumnClass NautilusColumnClass;
+
+struct _NautilusColumn {
+ GObject parent;
+
+ NautilusColumnDetails *details;
+};
+
+struct _NautilusColumnClass {
+ GObjectClass parent;
+};
+
+GType nautilus_column_get_type (void);
+NautilusColumn * nautilus_column_new (const char *name,
+ const char *attribute,
+ const char *label,
+ const char *description);
+
+/* NautilusColumn has the following properties:
+ * name (string) - the identifier for the column
+ * attribute (string) - the file attribute to be displayed in the
+ * column
+ * label (string) - the user-visible label for the column
+ * description (string) - a user-visible description of the column
+ * xalign (float) - x-alignment of the column
+ */
+
+G_END_DECLS
+
+#endif
diff --git a/libnautilus-extension/nautilus-extension-i18n.h b/libnautilus-extension/nautilus-extension-i18n.h
new file mode 100644
index 000000000..97fa0ab4c
--- /dev/null
+++ b/libnautilus-extension/nautilus-extension-i18n.h
@@ -0,0 +1,24 @@
+#ifndef NAUTILUS_EXTENSION_I18N_H
+#define NAUTILUS_EXTENSION_I18N_H
+
+#include "config.h"
+
+#ifdef ENABLE_NLS
+#include<libintl.h>
+#define _(String) dgettext(GETTEXT_PACKAGE,String)
+#ifdef gettext_noop
+#define N_(String) gettext_noop(String)
+#else
+#define N_(String) (String)
+#endif
+#else /* NLS is disabled */
+#define _(String) (String)
+#define N_(String) (String)
+#define textdomain(String) (String)
+#define gettext(String) (String)
+#define dgettext(Domain,String) (String)
+#define dcgettext(Domain,String,Type) (String)
+#define bindtextdomain(Domain,Directory) (Domain)
+#endif
+
+#endif
diff --git a/libnautilus-extension/nautilus-extension-types.c b/libnautilus-extension/nautilus-extension-types.c
new file mode 100644
index 000000000..ee815fc10
--- /dev/null
+++ b/libnautilus-extension/nautilus-extension-types.c
@@ -0,0 +1,57 @@
+/*
+ * nautilus-extension-types.c - Type definitions for Nautilus extensions
+ *
+ * Copyright (C) 2003 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Author: Dave Camp <dave@ximian.com>
+ *
+ */
+
+#include <config.h>
+#include "nautilus-extension-types.h"
+
+
+GType
+nautilus_operation_result_get_type (void)
+{
+ static GType type = 0;
+ if (type == 0) {
+ static const GEnumValue values[] = {
+ {
+ NAUTILUS_OPERATION_COMPLETE,
+ "NAUTILUS_OPERATION_COMPLETE",
+ "complete",
+ },
+ {
+ NAUTILUS_OPERATION_FAILED,
+ "NAUTILUS_OPERATION_FAILED",
+ "failed",
+ },
+ {
+ NAUTILUS_OPERATION_IN_PROGRESS,
+ "NAUTILUS_OPERATION_IN_PROGRESS",
+ "in_progress",
+ },
+ { 0, NULL, NULL }
+ };
+
+ type = g_enum_register_static ("NautilusOperationResult",
+ values);
+ }
+
+ return type;
+}
diff --git a/libnautilus-extension/nautilus-extension-types.h b/libnautilus-extension/nautilus-extension-types.h
new file mode 100644
index 000000000..806d17118
--- /dev/null
+++ b/libnautilus-extension/nautilus-extension-types.h
@@ -0,0 +1,67 @@
+/*
+ * nautilus-info-provider.h - Type definitions for Nautilus extensions
+ *
+ * Copyright (C) 2003 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Author: Dave Camp <dave@ximian.com>
+ *
+ */
+
+/* This interface is implemented by Nautilus extensions that want to
+ * provide information about files. Extensions are called when Nautilus
+ * needs information about a file. They are passed a NautilusFileInfo
+ * object which should be filled with relevant information */
+
+#ifndef NAUTILUS_EXTENSION_TYPES_H
+#define NAUTILUS_EXTENSION_TYPES_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define NAUTILUS_TYPE_OPERATION_RESULT (nautilus_operation_result_get_type ())
+
+/* Handle for asynchronous interfaces. These are opaque handles that must
+ * be unique within an extension object. These are returned by operations
+ * that return NAUTILUS_OPERATION_IN_PROGRESS */
+typedef struct _NautilusOperationHandle NautilusOperationHandle;
+
+typedef enum {
+ /* Returned if the call succeeded, and the extension is done
+ * with the request */
+ NAUTILUS_OPERATION_COMPLETE,
+
+ /* Returned if the call failed */
+ NAUTILUS_OPERATION_FAILED,
+
+ /* Returned if the extension has begun an async operation.
+ * If this is returned, the extension must set the handle
+ * parameter and call the callback closure when the
+ * operation is complete. */
+ NAUTILUS_OPERATION_IN_PROGRESS,
+} NautilusOperationResult;
+
+GType nautilus_operation_result_get_type (void);
+
+void nautilus_module_initialize (GTypeModule *module);
+void nautilus_module_shutdown (void);
+void nautilus_module_list_types (const GType **types,
+ int *num_types);
+
+G_END_DECLS
+
+#endif
diff --git a/libnautilus-extension/nautilus-file-info.c b/libnautilus-extension/nautilus-file-info.c
new file mode 100644
index 000000000..e245de9d7
--- /dev/null
+++ b/libnautilus-extension/nautilus-file-info.c
@@ -0,0 +1,202 @@
+/*
+ * nautilus-file-info.c - Information about a file
+ *
+ * Copyright (C) 2003 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <config.h>
+#include "nautilus-file-info.h"
+
+
+GList *
+nautilus_file_info_list_copy (GList *files)
+{
+ GList *ret;
+ GList *l;
+
+ ret = g_list_copy (files);
+ for (l = ret; l != NULL; l = l->next) {
+ g_object_ref (G_OBJECT (l->data));
+ }
+
+ return ret;
+}
+
+void
+nautilus_file_info_list_free (GList *files)
+{
+ GList *l;
+
+ for (l = files; l != NULL; l = l->next) {
+ g_object_unref (G_OBJECT (l->data));
+ }
+
+ g_list_free (files);
+}
+
+static void
+nautilus_file_info_base_init (gpointer g_class)
+{
+}
+
+GType
+nautilus_file_info_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type) {
+ static const GTypeInfo info = {
+ sizeof (NautilusFileInfoIface),
+ nautilus_file_info_base_init,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ 0,
+ 0,
+ NULL
+ };
+
+ type = g_type_register_static (G_TYPE_INTERFACE,
+ "NautilusFileInfo",
+ &info, 0);
+ g_type_interface_add_prerequisite (type, G_TYPE_OBJECT);
+ }
+
+ return type;
+}
+
+gboolean
+nautilus_file_info_is_gone (NautilusFileInfo *file)
+{
+ g_return_val_if_fail (NAUTILUS_IS_FILE_INFO (file), FALSE);
+ g_return_val_if_fail (NAUTILUS_FILE_INFO_GET_IFACE (file)->is_gone != NULL, FALSE);
+
+ return NAUTILUS_FILE_INFO_GET_IFACE (file)->is_gone (file);
+}
+
+char *
+nautilus_file_info_get_name (NautilusFileInfo *file)
+{
+ g_return_val_if_fail (NAUTILUS_IS_FILE_INFO (file), NULL);
+ g_return_val_if_fail (NAUTILUS_FILE_INFO_GET_IFACE (file)->get_name != NULL, NULL);
+
+ return NAUTILUS_FILE_INFO_GET_IFACE (file)->get_name (file);
+}
+
+char *
+nautilus_file_info_get_uri (NautilusFileInfo *file)
+{
+ g_return_val_if_fail (NAUTILUS_IS_FILE_INFO (file), NULL);
+ g_return_val_if_fail (NAUTILUS_FILE_INFO_GET_IFACE (file)->get_uri != NULL, NULL);
+
+ return NAUTILUS_FILE_INFO_GET_IFACE (file)->get_uri (file);
+}
+
+char *
+nautilus_file_info_get_parent_uri (NautilusFileInfo *file)
+{
+ g_return_val_if_fail (NAUTILUS_IS_FILE_INFO (file), NULL);
+ g_return_val_if_fail (NAUTILUS_FILE_INFO_GET_IFACE (file)->get_uri != NULL, NULL);
+
+ return NAUTILUS_FILE_INFO_GET_IFACE (file)->get_parent_uri (file);
+}
+
+char *
+nautilus_file_info_get_uri_scheme (NautilusFileInfo *file)
+{
+ g_return_val_if_fail (NAUTILUS_IS_FILE_INFO (file), NULL);
+ g_return_val_if_fail (NAUTILUS_FILE_INFO_GET_IFACE (file)->get_uri_scheme != NULL, NULL);
+
+ return NAUTILUS_FILE_INFO_GET_IFACE (file)->get_uri_scheme (file);
+}
+
+char *
+nautilus_file_info_get_mime_type (NautilusFileInfo *file)
+{
+ g_return_val_if_fail (NAUTILUS_IS_FILE_INFO (file), NULL);
+ g_return_val_if_fail (NAUTILUS_FILE_INFO_GET_IFACE (file)->get_mime_type != NULL, NULL);
+
+ return NAUTILUS_FILE_INFO_GET_IFACE (file)->get_mime_type (file);
+}
+
+gboolean
+nautilus_file_info_is_mime_type (NautilusFileInfo *file,
+ const char *mime_type)
+{
+ g_return_val_if_fail (NAUTILUS_IS_FILE_INFO (file), FALSE);
+ g_return_val_if_fail (mime_type != NULL, FALSE);
+ g_return_val_if_fail (NAUTILUS_FILE_INFO_GET_IFACE (file)->is_mime_type != NULL, FALSE);
+
+ return NAUTILUS_FILE_INFO_GET_IFACE (file)->is_mime_type (file,
+ mime_type);
+}
+
+gboolean
+nautilus_file_info_is_directory (NautilusFileInfo *file)
+{
+ g_return_val_if_fail (NAUTILUS_IS_FILE_INFO (file), FALSE);
+ g_return_val_if_fail (NAUTILUS_FILE_INFO_GET_IFACE (file)->is_directory != NULL, FALSE);
+
+ return NAUTILUS_FILE_INFO_GET_IFACE (file)->is_directory (file);
+}
+
+GnomeVFSFileInfo *
+nautilus_file_info_get_vfs_file_info (NautilusFileInfo *file)
+{
+ g_return_val_if_fail (NAUTILUS_IS_FILE_INFO (file), NULL);
+ g_return_val_if_fail (NAUTILUS_FILE_INFO_GET_IFACE (file)->get_vfs_file_info != NULL, NULL);
+
+ return NAUTILUS_FILE_INFO_GET_IFACE (file)->get_vfs_file_info (file);
+}
+
+void
+nautilus_file_info_add_emblem (NautilusFileInfo *file,
+ const char *emblem_name)
+{
+ g_return_if_fail (NAUTILUS_IS_FILE_INFO (file));
+ g_return_if_fail (NAUTILUS_FILE_INFO_GET_IFACE (file)->get_vfs_file_info != NULL);
+
+ NAUTILUS_FILE_INFO_GET_IFACE (file)->add_emblem (file, emblem_name);
+}
+
+char *
+nautilus_file_info_get_string_attribute (NautilusFileInfo *file,
+ const char *attribute_name)
+{
+ g_return_val_if_fail (NAUTILUS_IS_FILE_INFO (file), NULL);
+ g_return_val_if_fail (NAUTILUS_FILE_INFO_GET_IFACE (file)->get_string_attribute != NULL, NULL);
+ g_return_val_if_fail (attribute_name != NULL, NULL);
+
+ return NAUTILUS_FILE_INFO_GET_IFACE (file)->get_string_attribute
+ (file, attribute_name);
+}
+
+void
+nautilus_file_info_add_string_attribute (NautilusFileInfo *file,
+ const char *attribute_name,
+ const char *value)
+{
+ g_return_if_fail (NAUTILUS_IS_FILE_INFO (file));
+ g_return_if_fail (NAUTILUS_FILE_INFO_GET_IFACE (file)->add_string_attribute != NULL);
+ g_return_if_fail (attribute_name != NULL);
+ g_return_if_fail (value != NULL);
+
+ NAUTILUS_FILE_INFO_GET_IFACE (file)->add_string_attribute
+ (file, attribute_name, value);
+}
diff --git a/libnautilus-extension/nautilus-file-info.h b/libnautilus-extension/nautilus-file-info.h
new file mode 100644
index 000000000..49d7d588b
--- /dev/null
+++ b/libnautilus-extension/nautilus-file-info.h
@@ -0,0 +1,113 @@
+/*
+ * nautilus-file-info.h - Information about a file
+ *
+ * Copyright (C) 2003 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+/* NautilusFileInfo is an interface to the NautilusFile object. It
+ * provides access to the asynchronous data in the NautilusFile.
+ * Extensions are passed objects of this type for operations. */
+
+#ifndef NAUTILUS_FILE_INFO_H
+#define NAUTILUS_FILE_INFO_H
+
+#include <glib-object.h>
+#include <libgnomevfs/gnome-vfs-file-info.h>
+
+G_BEGIN_DECLS
+
+#define NAUTILUS_TYPE_FILE_INFO (nautilus_file_info_get_type ())
+#define NAUTILUS_FILE_INFO(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NAUTILUS_TYPE_FILE_INFO, NautilusFileInfo))
+#define NAUTILUS_IS_FILE_INFO(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NAUTILUS_TYPE_FILE_INFO))
+#define NAUTILUS_FILE_INFO_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), NAUTILUS_TYPE_FILE_INFO, NautilusFileInfoIface))
+
+
+#ifndef NAUTILUS_FILE_DEFINED
+#define NAUTILUS_FILE_DEFINED
+/* Using NautilusFile for the vtable to make implementing this in
+ * NautilusFile easier */
+typedef struct NautilusFile NautilusFile;
+#endif
+
+typedef NautilusFile NautilusFileInfo;
+typedef struct _NautilusFileInfoIface NautilusFileInfoIface;
+
+
+struct _NautilusFileInfoIface
+{
+ gboolean (*is_gone) (NautilusFileInfo *file);
+
+ char * (*get_name) (NautilusFileInfo *file);
+ char * (*get_uri) (NautilusFileInfo *file);
+ char * (*get_parent_uri) (NautilusFileInfo *file);
+ char * (*get_uri_scheme) (NautilusFileInfo *file);
+
+ char * (*get_mime_type) (NautilusFileInfo *file);
+ gboolean (*is_mime_type) (NautilusFileInfo *file,
+ const char *mime_Type);
+ gboolean (*is_directory) (NautilusFileInfo *file);
+
+ GnomeVFSFileInfo *(*get_vfs_file_info) (NautilusFileInfo *file);
+
+ void (*add_emblem) (NautilusFileInfo *file,
+ const char *emblem_name);
+ char * (*get_string_attribute) (NautilusFileInfo *file,
+ const char *attribute_name);
+ void (*add_string_attribute) (NautilusFileInfo *file,
+ const char *attribute_name,
+ const char *value);
+};
+
+GList *nautilus_file_info_list_copy (GList *files);
+void nautilus_file_info_list_free (GList *files);
+GType nautilus_file_info_get_type (void);
+
+/* Return true if the file has been deleted */
+gboolean nautilus_file_info_is_gone (NautilusFileInfo *file);
+
+/* Name and Location */
+char * nautilus_file_info_get_name (NautilusFileInfo *file);
+char * nautilus_file_info_get_uri (NautilusFileInfo *file);
+char * nautilus_file_info_get_parent_uri (NautilusFileInfo *file);
+char * nautilus_file_info_get_uri_scheme (NautilusFileInfo *file);
+
+/* File Type */
+char * nautilus_file_info_get_mime_type (NautilusFileInfo *file);
+gboolean nautilus_file_info_is_mime_type (NautilusFileInfo *file,
+ const char *mime_type);
+gboolean nautilus_file_info_is_directory (NautilusFileInfo *file);
+
+
+
+/* Other File Info */
+GnomeVFSFileInfo *nautilus_file_info_get_vfs_file_info (NautilusFileInfo *file);
+
+
+
+/* Modifying the NautilusFileInfo */
+void nautilus_file_info_add_emblem (NautilusFileInfo *file,
+ const char *emblem_name);
+char * nautilus_file_info_get_string_attribute (NautilusFileInfo *file,
+ const char *attribute_name);
+void nautilus_file_info_add_string_attribute (NautilusFileInfo *file,
+ const char *attribute_name,
+ const char *value);
+
+G_END_DECLS
+
+#endif
diff --git a/libnautilus-extension/nautilus-info-provider.c b/libnautilus-extension/nautilus-info-provider.c
new file mode 100644
index 000000000..942245190
--- /dev/null
+++ b/libnautilus-extension/nautilus-info-provider.c
@@ -0,0 +1,120 @@
+/*
+ * nautilus-info-provider.c - Interface for Nautilus extensions that
+ * provide info about files.
+ *
+ * Copyright (C) 2003 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Author: Dave Camp <dave@ximian.com>
+ *
+ */
+
+#include <config.h>
+#include "nautilus-info-provider.h"
+
+#include <glib-object.h>
+
+static void
+nautilus_info_provider_base_init (gpointer g_class)
+{
+}
+
+GType
+nautilus_info_provider_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type) {
+ static const GTypeInfo info = {
+ sizeof (NautilusInfoProviderIface),
+ nautilus_info_provider_base_init,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ 0,
+ 0,
+ NULL
+ };
+
+ type = g_type_register_static (G_TYPE_INTERFACE,
+ "NautilusInfoProvider",
+ &info, 0);
+ g_type_interface_add_prerequisite (type, G_TYPE_OBJECT);
+ }
+
+ return type;
+}
+
+NautilusOperationResult
+nautilus_info_provider_update_file_info (NautilusInfoProvider *provider,
+ NautilusFileInfo *file,
+ GClosure *update_complete,
+ NautilusOperationHandle **handle)
+{
+ g_return_val_if_fail (NAUTILUS_IS_INFO_PROVIDER (provider),
+ NAUTILUS_OPERATION_FAILED);
+ g_return_val_if_fail (NAUTILUS_INFO_PROVIDER_GET_IFACE (provider)->update_file_info != NULL,
+ NAUTILUS_OPERATION_FAILED);
+ g_return_val_if_fail (update_complete != NULL,
+ NAUTILUS_OPERATION_FAILED);
+ g_return_val_if_fail (handle != NULL, NAUTILUS_OPERATION_FAILED);
+
+ return NAUTILUS_INFO_PROVIDER_GET_IFACE (provider)->update_file_info
+ (provider, file, update_complete, handle);
+}
+
+void
+nautilus_info_provider_cancel_update (NautilusInfoProvider *provider,
+ NautilusOperationHandle *handle)
+{
+ g_return_if_fail (NAUTILUS_IS_INFO_PROVIDER (provider));
+ g_return_if_fail (NAUTILUS_INFO_PROVIDER_GET_IFACE (provider)->cancel_update != NULL);
+ g_return_if_fail (NAUTILUS_INFO_PROVIDER_GET_IFACE (provider)->cancel_update != NULL);
+ g_return_if_fail (handle != NULL);
+
+ NAUTILUS_INFO_PROVIDER_GET_IFACE (provider)->cancel_update (provider,
+ handle);
+}
+
+void
+nautilus_info_provider_update_complete_invoke (GClosure *update_complete,
+ NautilusInfoProvider *provider,
+ NautilusOperationHandle *handle,
+ NautilusOperationResult result)
+{
+ GValue args[3] = { { 0, } };
+ GValue return_val = { 0, };
+
+ g_return_if_fail (update_complete != NULL);
+ g_return_if_fail (NAUTILUS_IS_INFO_PROVIDER (provider));
+
+ g_value_init (&args[0], NAUTILUS_TYPE_INFO_PROVIDER);
+ g_value_init (&args[1], G_TYPE_POINTER);
+ g_value_init (&args[2], NAUTILUS_TYPE_OPERATION_RESULT);
+
+ g_value_set_object (&args[0], provider);
+ g_value_set_pointer (&args[1], handle);
+ g_value_set_enum (&args[2], result);
+
+ g_closure_invoke (update_complete, &return_val, 3, args, NULL);
+
+ g_value_unset (&args[0]);
+ g_value_unset (&args[1]);
+ g_value_unset (&args[2]);
+}
+
+
diff --git a/libnautilus-extension/nautilus-info-provider.h b/libnautilus-extension/nautilus-info-provider.h
new file mode 100644
index 000000000..ded7748d0
--- /dev/null
+++ b/libnautilus-extension/nautilus-info-provider.h
@@ -0,0 +1,82 @@
+/*
+ * nautilus-info-provider.h - Interface for Nautilus extensions that
+ * provide info about files.
+ *
+ * Copyright (C) 2003 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Author: Dave Camp <dave@ximian.com>
+ *
+ */
+
+/* This interface is implemented by Nautilus extensions that want to
+ * provide information about files. Extensions are called when Nautilus
+ * needs information about a file. They are passed a NautilusFileInfo
+ * object which should be filled with relevant information */
+
+#ifndef NAUTILUS_INFO_PROVIDER_H
+#define NAUTILUS_INFO_PROVIDER_H
+
+#include <glib-object.h>
+#include "nautilus-extension-types.h"
+#include "nautilus-file-info.h"
+
+G_BEGIN_DECLS
+
+#define NAUTILUS_TYPE_INFO_PROVIDER (nautilus_info_provider_get_type ())
+#define NAUTILUS_INFO_PROVIDER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NAUTILUS_TYPE_INFO_PROVIDER, NautilusInfoProvider))
+#define NAUTILUS_IS_INFO_PROVIDER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NAUTILUS_TYPE_INFO_PROVIDER))
+#define NAUTILUS_INFO_PROVIDER_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), NAUTILUS_TYPE_INFO_PROVIDER, NautilusInfoProviderIface))
+
+typedef struct _NautilusInfoProvider NautilusInfoProvider;
+typedef struct _NautilusInfoProviderIface NautilusInfoProviderIface;
+
+typedef void (*NautilusInfoProviderUpdateComplete) (NautilusInfoProvider *provider,
+ NautilusOperationHandle *handle,
+ NautilusOperationResult result,
+ gpointer user_data);
+
+struct _NautilusInfoProviderIface {
+ GTypeInterface g_iface;
+
+ NautilusOperationResult (*update_file_info) (NautilusInfoProvider *provider,
+ NautilusFileInfo *file,
+ GClosure *update_complete,
+ NautilusOperationHandle **handle);
+ void (*cancel_update) (NautilusInfoProvider *provider,
+ NautilusOperationHandle *handle);
+};
+
+/* Interface Functions */
+GType nautilus_info_provider_get_type (void);
+NautilusOperationResult nautilus_info_provider_update_file_info (NautilusInfoProvider *provider,
+ NautilusFileInfo *file,
+ GClosure *update_complete,
+ NautilusOperationHandle **handle);
+void nautilus_info_provider_cancel_update (NautilusInfoProvider *provider,
+ NautilusOperationHandle *handle);
+
+
+
+/* Helper functions for implementations */
+void nautilus_info_provider_update_complete_invoke (GClosure *update_complete,
+ NautilusInfoProvider *provider,
+ NautilusOperationHandle *handle,
+ NautilusOperationResult result);
+
+G_END_DECLS
+
+#endif
diff --git a/libnautilus-extension/nautilus-menu-item.c b/libnautilus-extension/nautilus-menu-item.c
new file mode 100644
index 000000000..83a26e26e
--- /dev/null
+++ b/libnautilus-extension/nautilus-menu-item.c
@@ -0,0 +1,274 @@
+/*
+ * nautilus-menu-item.c - Menu items exported by NautilusMenuProvider
+ * objects.
+ *
+ * Copyright (C) 2003 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Author: Dave Camp <dave@ximian.com>
+ *
+ */
+
+#include <config.h>
+#include "nautilus-menu-item.h"
+#include "nautilus-extension-i18n.h"
+
+enum {
+ ACTIVATE,
+ LAST_SIGNAL
+};
+
+enum {
+ PROP_0,
+ PROP_NAME,
+ PROP_LABEL,
+ PROP_TIP,
+ PROP_ICON,
+ PROP_SENSITIVE,
+ PROP_PRIORITY,
+ LAST_PROP
+};
+
+struct _NautilusMenuItemDetails {
+ char *name;
+ char *label;
+ char *tip;
+ char *icon;
+ gboolean sensitive;
+ gboolean priority;
+};
+
+static guint signals[LAST_SIGNAL];
+
+NautilusMenuItem *
+nautilus_menu_item_new (const char *name,
+ const char *label,
+ const char *tip,
+ const char *icon)
+{
+ NautilusMenuItem *item;
+
+ g_return_val_if_fail (name != NULL, NULL);
+ g_return_val_if_fail (label != NULL, NULL);
+ g_return_val_if_fail (tip != NULL, NULL);
+
+ item = g_object_new (NAUTILUS_TYPE_MENU_ITEM,
+ "name", name,
+ "label", label,
+ "tip", tip,
+ "icon", icon,
+ NULL);
+
+ return item;
+}
+
+void
+nautilus_menu_item_activate (NautilusMenuItem *item)
+{
+ g_signal_emit (item, signals[ACTIVATE], 0);
+}
+
+static void
+nautilus_menu_item_get_property (GObject *object,
+ guint param_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ NautilusMenuItem *item;
+
+ item = NAUTILUS_MENU_ITEM (object);
+
+ switch (param_id) {
+ case PROP_NAME :
+ g_value_set_string (value, item->details->name);
+ break;
+ case PROP_LABEL :
+ g_value_set_string (value, item->details->label);
+ break;
+ case PROP_TIP :
+ g_value_set_string (value, item->details->tip);
+ break;
+ case PROP_ICON :
+ g_value_set_string (value, item->details->icon);
+ break;
+ case PROP_SENSITIVE :
+ g_value_set_boolean (value, item->details->sensitive);
+ break;
+ case PROP_PRIORITY :
+ g_value_set_boolean (value, item->details->priority);
+ break;
+ default :
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+ break;
+ }
+}
+
+static void
+nautilus_menu_item_set_property (GObject *object,
+ guint param_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ NautilusMenuItem *item;
+
+ item = NAUTILUS_MENU_ITEM (object);
+
+ switch (param_id) {
+ case PROP_NAME :
+ g_free (item->details->name);
+ item->details->name = g_strdup (g_value_get_string (value));
+ g_object_notify (object, "name");
+ break;
+ case PROP_LABEL :
+ g_free (item->details->label);
+ item->details->label = g_strdup (g_value_get_string (value));
+ g_object_notify (object, "label");
+ break;
+ case PROP_TIP :
+ g_free (item->details->tip);
+ item->details->tip = g_strdup (g_value_get_string (value));
+ g_object_notify (object, "tip");
+ break;
+ case PROP_ICON :
+ g_free (item->details->icon);
+ item->details->icon = g_strdup (g_value_get_string (value));
+ g_object_notify (object, "icon");
+ break;
+ case PROP_SENSITIVE :
+ item->details->sensitive = g_value_get_boolean (value);
+ g_object_notify (object, "sensitive");
+ break;
+ case PROP_PRIORITY :
+ item->details->priority = g_value_get_boolean (value);
+ g_object_notify (object, "priority");
+ break;
+ default :
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+ break;
+ }
+}
+
+static void
+nautilus_menu_item_finalize (GObject *object)
+{
+ NautilusMenuItem *item;
+
+ item = NAUTILUS_MENU_ITEM (object);
+
+ g_free (item->details->name);
+ g_free (item->details->label);
+ g_free (item->details->tip);
+ g_free (item->details->icon);
+
+ g_free (item->details);
+}
+
+static void
+nautilus_menu_item_instance_init (NautilusMenuItem *item)
+{
+ item->details = g_new0 (NautilusMenuItemDetails, 1);
+ item->details->sensitive = TRUE;
+}
+
+static void
+nautilus_menu_item_class_init (NautilusMenuItemClass *class)
+{
+ G_OBJECT_CLASS (class)->finalize = nautilus_menu_item_finalize;
+ G_OBJECT_CLASS (class)->get_property = nautilus_menu_item_get_property;
+ G_OBJECT_CLASS (class)->set_property = nautilus_menu_item_set_property;
+
+ signals[ACTIVATE] =
+ g_signal_new ("activate",
+ G_TYPE_FROM_CLASS (class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (NautilusMenuItemClass,
+ activate),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ g_object_class_install_property (G_OBJECT_CLASS (class),
+ PROP_NAME,
+ g_param_spec_string ("name",
+ _("Name"),
+ _("Name of the item"),
+ NULL,
+ G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE | G_PARAM_READABLE));
+ g_object_class_install_property (G_OBJECT_CLASS (class),
+ PROP_LABEL,
+ g_param_spec_string ("label",
+ _("Label"),
+ _("Label to display to the user"),
+ NULL,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (G_OBJECT_CLASS (class),
+ PROP_TIP,
+ g_param_spec_string ("tip",
+ _("Tip"),
+ _("Tooltip for the menu item"),
+ NULL,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (G_OBJECT_CLASS (class),
+ PROP_ICON,
+ g_param_spec_string ("icon",
+ _("Icon"),
+ _("Name of the icon to display in the menu item"),
+ NULL,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (G_OBJECT_CLASS (class),
+ PROP_SENSITIVE,
+ g_param_spec_boolean ("sensitive",
+ _("Sensitive"),
+ _("Whether the menu item is sensitive"),
+ TRUE,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (G_OBJECT_CLASS (class),
+ PROP_PRIORITY,
+ g_param_spec_boolean ("priority",
+ _("Priority"),
+ _("Show priority text in toolbars"),
+ TRUE,
+ G_PARAM_READWRITE));
+}
+
+GType
+nautilus_menu_item_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type) {
+ static const GTypeInfo info = {
+ sizeof (NautilusMenuItemClass),
+ NULL,
+ NULL,
+ (GClassInitFunc)nautilus_menu_item_class_init,
+ NULL,
+ NULL,
+ sizeof (NautilusMenuItem),
+ 0,
+ (GInstanceInitFunc)nautilus_menu_item_instance_init
+ };
+
+ type = g_type_register_static
+ (G_TYPE_OBJECT,
+ "NautilusMenuItem",
+ &info, 0);
+ }
+
+ return type;
+}
+
diff --git a/libnautilus-extension/nautilus-menu-item.h b/libnautilus-extension/nautilus-menu-item.h
new file mode 100644
index 000000000..be443d0b3
--- /dev/null
+++ b/libnautilus-extension/nautilus-menu-item.h
@@ -0,0 +1,77 @@
+/*
+ * nautilus-menu-item.h - Menu items exported by NautilusMenuProvider
+ * objects.
+ *
+ * Copyright (C) 2003 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Author: Dave Camp <dave@ximian.com>
+ *
+ */
+
+#ifndef NAUTILUS_MENU_ITEM_H
+#define NAUTILUS_MENU_ITEM_H
+
+#include <glib-object.h>
+#include "nautilus-extension-types.h"
+
+G_BEGIN_DECLS
+
+#define NAUTILUS_TYPE_MENU_ITEM (nautilus_menu_item_get_type())
+#define NAUTILUS_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NAUTILUS_TYPE_MENU_ITEM, NautilusMenuItem))
+#define NAUTILUS_MENU_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_MENU_ITEM, NautilusMenuItemClass))
+#define NAUTILUS_MENU_IS_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NAUTILUS_TYPE_MENU_ITEM))
+#define NAUTILUS_MENU_IS_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NAUTILUS_TYPE_MENU_ITEM))
+#define NAUTILUS_MENU_ITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), NAUTILUS_TYPE_MENU_ITEM, NautilusMenuItemClass))
+
+typedef struct _NautilusMenuItem NautilusMenuItem;
+typedef struct _NautilusMenuItemDetails NautilusMenuItemDetails;
+typedef struct _NautilusMenuItemClass NautilusMenuItemClass;
+
+struct _NautilusMenuItem {
+ GObject parent;
+
+ NautilusMenuItemDetails *details;
+};
+
+struct _NautilusMenuItemClass {
+ GObjectClass parent;
+
+ void (*activate) (NautilusMenuItem *item);
+};
+
+GType nautilus_menu_item_get_type (void);
+NautilusMenuItem *nautilus_menu_item_new (const char *name,
+ const char *label,
+ const char *tip,
+ const char *icon);
+
+void nautilus_menu_item_activate (NautilusMenuItem *item);
+
+/* NautilusMenuItem has the following properties:
+ * name (string) - the identifier for the menu item
+ * label (string) - the user-visible label of the menu item
+ * tip (string) - the tooltip of the menu item
+ * icon (string) - the name of the icon to display in the menu item
+ * sensitive (boolean) - whether the menu item is sensitive or not
+ * priority (boolean) - used for toolbar items, whether to show priority
+ * text.
+ */
+
+
+G_END_DECLS
+
+#endif
diff --git a/libnautilus-extension/nautilus-menu-provider.c b/libnautilus-extension/nautilus-menu-provider.c
new file mode 100644
index 000000000..956c5ec0e
--- /dev/null
+++ b/libnautilus-extension/nautilus-menu-provider.c
@@ -0,0 +1,110 @@
+/*
+ * nautilus-property-page-provider.c - Interface for Nautilus extensions
+ * that provide context menu items
+ * for files.
+ *
+ * Copyright (C) 2003 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Author: Dave Camp <dave@ximian.com>
+ *
+ */
+
+#include <config.h>
+#include "nautilus-menu-provider.h"
+
+#include <glib-object.h>
+
+static void
+nautilus_menu_provider_base_init (gpointer g_class)
+{
+}
+
+GType
+nautilus_menu_provider_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type) {
+ static const GTypeInfo info = {
+ sizeof (NautilusMenuProviderIface),
+ nautilus_menu_provider_base_init,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ 0,
+ 0,
+ NULL
+ };
+
+ type = g_type_register_static (G_TYPE_INTERFACE,
+ "NautilusMenuProvider",
+ &info, 0);
+ g_type_interface_add_prerequisite (type, G_TYPE_OBJECT);
+ }
+
+ return type;
+}
+
+GList *
+nautilus_menu_provider_get_file_items (NautilusMenuProvider *provider,
+ GtkWidget *window,
+ GList *files)
+{
+ g_return_val_if_fail (NAUTILUS_IS_MENU_PROVIDER (provider), NULL);
+
+ if (NAUTILUS_MENU_PROVIDER_GET_IFACE (provider)->get_file_items) {
+ return NAUTILUS_MENU_PROVIDER_GET_IFACE (provider)->get_file_items
+ (provider, window, files);
+ } else {
+ return NULL;
+ }
+}
+
+GList *
+nautilus_menu_provider_get_background_items (NautilusMenuProvider *provider,
+ GtkWidget *window,
+ NautilusFileInfo *current_folder)
+{
+ g_return_val_if_fail (NAUTILUS_IS_MENU_PROVIDER (provider), NULL);
+ g_return_val_if_fail (NAUTILUS_IS_FILE_INFO (current_folder), NULL);
+
+ if (NAUTILUS_MENU_PROVIDER_GET_IFACE (provider)->get_background_items) {
+ return NAUTILUS_MENU_PROVIDER_GET_IFACE (provider)->get_background_items
+ (provider, window, current_folder);
+ } else {
+ return NULL;
+ }
+}
+
+GList *
+nautilus_menu_provider_get_toolbar_items (NautilusMenuProvider *provider,
+ GtkWidget *window,
+ NautilusFileInfo *current_folder)
+{
+ g_return_val_if_fail (NAUTILUS_IS_MENU_PROVIDER (provider), NULL);
+ g_return_val_if_fail (NAUTILUS_IS_FILE_INFO (current_folder), NULL);
+
+ if (NAUTILUS_MENU_PROVIDER_GET_IFACE (provider)->get_toolbar_items) {
+ return NAUTILUS_MENU_PROVIDER_GET_IFACE (provider)->get_toolbar_items
+ (provider, window, current_folder);
+ } else {
+ return NULL;
+ }
+}
+
+
diff --git a/libnautilus-extension/nautilus-menu-provider.h b/libnautilus-extension/nautilus-menu-provider.h
new file mode 100644
index 000000000..a7a9a2470
--- /dev/null
+++ b/libnautilus-extension/nautilus-menu-provider.h
@@ -0,0 +1,77 @@
+/*
+ * nautilus-menu-provider.h - Interface for Nautilus extensions that
+ * provide context menu items.
+ *
+ * Copyright (C) 2003 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Author: Dave Camp <dave@ximian.com>
+ *
+ */
+
+/* This interface is implemented by Nautilus extensions that want to
+ * add context menu entries to files. Extensions are called when
+ * Nautilus constructs the context menu for a file. They are passed a
+ * list of NautilusFileInfo objects which holds the current selection */
+
+#ifndef NAUTILUS_MENU_PROVIDER_H
+#define NAUTILUS_MENU_PROVIDER_H
+
+#include <glib-object.h>
+#include <gtk/gtkwidget.h>
+#include "nautilus-extension-types.h"
+#include "nautilus-file-info.h"
+#include "nautilus-menu-item.h"
+
+G_BEGIN_DECLS
+
+#define NAUTILUS_TYPE_MENU_PROVIDER (nautilus_menu_provider_get_type ())
+#define NAUTILUS_MENU_PROVIDER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NAUTILUS_TYPE_MENU_PROVIDER, NautilusMenuProvider))
+#define NAUTILUS_IS_MENU_PROVIDER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NAUTILUS_TYPE_MENU_PROVIDER))
+#define NAUTILUS_MENU_PROVIDER_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), NAUTILUS_TYPE_MENU_PROVIDER, NautilusMenuProviderIface))
+
+typedef struct _NautilusMenuProvider NautilusMenuProvider;
+typedef struct _NautilusMenuProviderIface NautilusMenuProviderIface;
+
+struct _NautilusMenuProviderIface {
+ GTypeInterface g_iface;
+
+ GList *(*get_file_items) (NautilusMenuProvider *provider,
+ GtkWidget *window,
+ GList *files);
+ GList *(*get_background_items) (NautilusMenuProvider *provider,
+ GtkWidget *window,
+ NautilusFileInfo *current_folder);
+ GList *(*get_toolbar_items) (NautilusMenuProvider *provider,
+ GtkWidget *window,
+ NautilusFileInfo *current_folder);
+};
+
+/* Interface Functions */
+GType nautilus_menu_provider_get_type (void);
+GList *nautilus_menu_provider_get_file_items (NautilusMenuProvider *provider,
+ GtkWidget *window,
+ GList *files);
+GList *nautilus_menu_provider_get_background_items (NautilusMenuProvider *provider,
+ GtkWidget *window,
+ NautilusFileInfo *current_folder);
+GList *nautilus_menu_provider_get_toolbar_items (NautilusMenuProvider *provider,
+ GtkWidget *window,
+ NautilusFileInfo *current_folder);
+
+G_END_DECLS
+
+#endif
diff --git a/libnautilus-extension/nautilus-property-page-provider.c b/libnautilus-extension/nautilus-property-page-provider.c
new file mode 100644
index 000000000..90e6b5594
--- /dev/null
+++ b/libnautilus-extension/nautilus-property-page-provider.c
@@ -0,0 +1,74 @@
+/*
+ * nautilus-property-page-provider.c - Interface for Nautilus extensions
+ * that provide property pages for
+ * files.
+ *
+ * Copyright (C) 2003 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Author: Dave Camp <dave@ximian.com>
+ *
+ */
+
+#include <config.h>
+#include "nautilus-property-page-provider.h"
+
+#include <glib-object.h>
+
+static void
+nautilus_property_page_provider_base_init (gpointer g_class)
+{
+}
+
+GType
+nautilus_property_page_provider_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type) {
+ static const GTypeInfo info = {
+ sizeof (NautilusPropertyPageProviderIface),
+ nautilus_property_page_provider_base_init,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ 0,
+ 0,
+ NULL
+ };
+
+ type = g_type_register_static (G_TYPE_INTERFACE,
+ "NautilusPropertyPageProvider",
+ &info, 0);
+ g_type_interface_add_prerequisite (type, G_TYPE_OBJECT);
+ }
+
+ return type;
+}
+
+GList *
+nautilus_property_page_provider_get_pages (NautilusPropertyPageProvider *provider,
+ GList *files)
+{
+ g_return_val_if_fail (NAUTILUS_IS_PROPERTY_PAGE_PROVIDER (provider), NULL);
+ g_return_val_if_fail (NAUTILUS_PROPERTY_PAGE_PROVIDER_GET_IFACE (provider)->get_pages != NULL, NULL);
+
+ return NAUTILUS_PROPERTY_PAGE_PROVIDER_GET_IFACE (provider)->get_pages
+ (provider, files);
+}
+
+
diff --git a/libnautilus-extension/nautilus-property-page-provider.h b/libnautilus-extension/nautilus-property-page-provider.h
new file mode 100644
index 000000000..56eada183
--- /dev/null
+++ b/libnautilus-extension/nautilus-property-page-provider.h
@@ -0,0 +1,63 @@
+/*
+ * nautilus-property-page-provider.h - Interface for Nautilus extensions
+ * that provide property pages.
+ *
+ * Copyright (C) 2003 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Author: Dave Camp <dave@ximian.com>
+ *
+ */
+
+/* This interface is implemented by Nautilus extensions that want to
+ * add property page to property dialogs. Extensions are called when
+ * Nautilus needs property pages for a selection. They are passed a
+ * list of NautilusFileInfo objects for which information should
+ * be displayed */
+
+#ifndef NAUTILUS_PROPERTY_PAGE_PROVIDER_H
+#define NAUTILUS_PROPERTY_PAGE_PROVIDER_H
+
+#include <glib-object.h>
+#include "nautilus-extension-types.h"
+#include "nautilus-file-info.h"
+#include "nautilus-property-page.h"
+
+G_BEGIN_DECLS
+
+#define NAUTILUS_TYPE_PROPERTY_PAGE_PROVIDER (nautilus_property_page_provider_get_type ())
+#define NAUTILUS_PROPERTY_PAGE_PROVIDER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NAUTILUS_TYPE_PROPERTY_PAGE_PROVIDER, NautilusPropertyPageProvider))
+#define NAUTILUS_IS_PROPERTY_PAGE_PROVIDER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NAUTILUS_TYPE_PROPERTY_PAGE_PROVIDER))
+#define NAUTILUS_PROPERTY_PAGE_PROVIDER_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), NAUTILUS_TYPE_PROPERTY_PAGE_PROVIDER, NautilusPropertyPageProviderIface))
+
+typedef struct _NautilusPropertyPageProvider NautilusPropertyPageProvider;
+typedef struct _NautilusPropertyPageProviderIface NautilusPropertyPageProviderIface;
+
+struct _NautilusPropertyPageProviderIface {
+ GTypeInterface g_iface;
+
+ GList *(*get_pages) (NautilusPropertyPageProvider *provider,
+ GList *files);
+};
+
+/* Interface Functions */
+GType nautilus_property_page_provider_get_type (void);
+GList *nautilus_property_page_provider_get_pages (NautilusPropertyPageProvider *provider,
+ GList *files);
+
+G_END_DECLS
+
+#endif
diff --git a/libnautilus-extension/nautilus-property-page.c b/libnautilus-extension/nautilus-property-page.c
new file mode 100644
index 000000000..e27a82b44
--- /dev/null
+++ b/libnautilus-extension/nautilus-property-page.c
@@ -0,0 +1,221 @@
+/*
+ * nautilus-property-page.h - Property pages exported by
+ * NautilusPropertyProvider objects.
+ *
+ * Copyright (C) 2003 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Author: Dave Camp <dave@ximian.com>
+ *
+ */
+
+#include <config.h>
+#include "nautilus-property-page.h"
+
+#include "nautilus-extension-i18n.h"
+
+enum {
+ PROP_0,
+ PROP_NAME,
+ PROP_LABEL,
+ PROP_PAGE,
+ LAST_PROP
+};
+
+
+struct _NautilusPropertyPageDetails {
+ char *name;
+ GtkWidget *label;
+ GtkWidget *page;
+};
+
+NautilusPropertyPage *
+nautilus_property_page_new (const char *name,
+ GtkWidget *label,
+ GtkWidget *page_widget)
+{
+ NautilusPropertyPage *page;
+
+ g_return_val_if_fail (name != NULL, NULL);
+ g_return_val_if_fail (label != NULL && GTK_IS_WIDGET (label), NULL);
+ g_return_val_if_fail (page_widget != NULL && GTK_IS_WIDGET (page_widget),
+ NULL);
+
+ page = g_object_new (NAUTILUS_TYPE_PROPERTY_PAGE,
+ "name", name,
+ "label", label,
+ "page", page_widget,
+ NULL);
+
+ return page;
+}
+
+static void
+nautilus_property_page_get_property (GObject *object,
+ guint param_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ NautilusPropertyPage *page;
+
+ page = NAUTILUS_PROPERTY_PAGE (object);
+
+ switch (param_id) {
+ case PROP_NAME :
+ g_value_set_string (value, page->details->name);
+ break;
+ case PROP_LABEL :
+ g_value_set_object (value, page->details->label);
+ break;
+ case PROP_PAGE :
+ g_value_set_object (value, page->details->page);
+ break;
+ default :
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+ break;
+ }
+}
+
+static void
+nautilus_property_page_set_property (GObject *object,
+ guint param_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ NautilusPropertyPage *page;
+
+ page = NAUTILUS_PROPERTY_PAGE (object);
+
+ switch (param_id) {
+ case PROP_NAME :
+ g_free (page->details->name);
+ page->details->name = g_strdup (g_value_get_string (value));
+ g_object_notify (object, "name");
+ break;
+ case PROP_LABEL :
+ if (page->details->label) {
+ g_object_unref (page->details->label);
+ }
+
+ page->details->label = g_object_ref (g_value_get_object (value));
+ g_object_notify (object, "label");
+ break;
+ case PROP_PAGE :
+ if (page->details->page) {
+ g_object_unref (page->details->page);
+ }
+
+ page->details->page = g_object_ref (g_value_get_object (value));
+ g_object_notify (object, "page");
+ break;
+ default :
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+ break;
+ }
+}
+
+static void
+nautilus_property_page_dispose (GObject *object)
+{
+ NautilusPropertyPage *page;
+
+ page = NAUTILUS_PROPERTY_PAGE (object);
+
+ if (page->details->label) {
+ g_object_unref (page->details->label);
+ page->details->label = NULL;
+ }
+ if (page->details->page) {
+ g_object_unref (page->details->page);
+ page->details->page = NULL;
+ }
+}
+
+static void
+nautilus_property_page_finalize (GObject *object)
+{
+ NautilusPropertyPage *page;
+
+ page = NAUTILUS_PROPERTY_PAGE (object);
+
+ g_free (page->details->name);
+
+ g_free (page->details);
+}
+
+static void
+nautilus_property_page_instance_init (NautilusPropertyPage *page)
+{
+ page->details = g_new0 (NautilusPropertyPageDetails, 1);
+}
+
+static void
+nautilus_property_page_class_init (NautilusPropertyPageClass *class)
+{
+ G_OBJECT_CLASS (class)->finalize = nautilus_property_page_finalize;
+ G_OBJECT_CLASS (class)->dispose = nautilus_property_page_dispose;
+ G_OBJECT_CLASS (class)->get_property = nautilus_property_page_get_property;
+ G_OBJECT_CLASS (class)->set_property = nautilus_property_page_set_property;
+
+ g_object_class_install_property (G_OBJECT_CLASS (class),
+ PROP_NAME,
+ g_param_spec_string ("name",
+ _("Name"),
+ _("Name of the page"),
+ NULL,
+ G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE | G_PARAM_READABLE));
+ g_object_class_install_property (G_OBJECT_CLASS (class),
+ PROP_LABEL,
+ g_param_spec_object ("label",
+ _("Label"),
+ _("Label widget to display in the notebook tab"),
+ GTK_TYPE_WIDGET,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (G_OBJECT_CLASS (class),
+ PROP_PAGE,
+ g_param_spec_object ("page",
+ _("Page"),
+ _("Widget for the property page"),
+ GTK_TYPE_WIDGET,
+ G_PARAM_READWRITE));
+}
+
+GType
+nautilus_property_page_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type) {
+ static const GTypeInfo info = {
+ sizeof (NautilusPropertyPageClass),
+ NULL,
+ NULL,
+ (GClassInitFunc)nautilus_property_page_class_init,
+ NULL,
+ NULL,
+ sizeof (NautilusPropertyPage),
+ 0,
+ (GInstanceInitFunc)nautilus_property_page_instance_init
+ };
+
+ type = g_type_register_static
+ (G_TYPE_OBJECT,
+ "NautilusPropertPage",
+ &info, 0);
+ }
+
+ return type;
+}
diff --git a/libnautilus-extension/nautilus-property-page.h b/libnautilus-extension/nautilus-property-page.h
new file mode 100644
index 000000000..944bd2390
--- /dev/null
+++ b/libnautilus-extension/nautilus-property-page.h
@@ -0,0 +1,70 @@
+/*
+ * nautilus-property-page.h - Property pages exported by
+ * NautilusPropertyProvider objects.
+ *
+ * Copyright (C) 2003 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Author: Dave Camp <dave@ximian.com>
+ *
+ */
+
+#ifndef NAUTILUS_PROPERTY_PAGE_H
+#define NAUTILUS_PROPERTY_PAGE_H
+
+#include <glib-object.h>
+#include <gtk/gtkwidget.h>
+#include "nautilus-extension-types.h"
+
+G_BEGIN_DECLS
+
+#define NAUTILUS_TYPE_PROPERTY_PAGE (nautilus_property_page_get_type())
+#define NAUTILUS_PROPERTY_PAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NAUTILUS_TYPE_PROPERTY_PAGE, NautilusPropertyPage))
+#define NAUTILUS_PROPERTY_PAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_PROPERTY_PAGE, NautilusPropertyPageClass))
+#define NAUTILUS_PROPERTY_IS_PAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NAUTILUS_TYPE_PROPERTY_PAGE))
+#define NAUTILUS_PROPERTY_IS_PAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NAUTILUS_TYPE_PROPERTY_PAGE))
+#define NAUTILUS_PROPERTY_PAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), NAUTILUS_TYPE_PROPERTY_PAGE, NautilusPropertyPageClass))
+
+typedef struct _NautilusPropertyPage NautilusPropertyPage;
+typedef struct _NautilusPropertyPageDetails NautilusPropertyPageDetails;
+typedef struct _NautilusPropertyPageClass NautilusPropertyPageClass;
+
+struct _NautilusPropertyPage
+{
+ GObject parent;
+
+ NautilusPropertyPageDetails *details;
+};
+
+struct _NautilusPropertyPageClass
+{
+ GObjectClass parent;
+};
+
+GType nautilus_property_page_get_type (void);
+NautilusPropertyPage *nautilus_property_page_new (const char *name,
+ GtkWidget *label,
+ GtkWidget *page);
+
+/* NautilusPropertyPage has the following properties:
+ * name (string) - the identifier for the property page
+ * label (widget) - the user-visible label of the property page
+ * page (widget) - the property page to display
+ */
+
+G_END_DECLS
+
+#endif
diff --git a/libnautilus-private/Makefile.am b/libnautilus-private/Makefile.am
index d6e826190..430176ca7 100644
--- a/libnautilus-private/Makefile.am
+++ b/libnautilus-private/Makefile.am
@@ -2,7 +2,9 @@ include $(top_srcdir)/Makefile.shared
lib_LTLIBRARIES=libnautilus-private.la
-libnautilus_private_la_LIBADD = ../libnautilus/libnautilus.la
+libnautilus_private_la_LIBADD = \
+ ../libnautilus/libnautilus.la \
+ ../libnautilus-extension/libnautilus-extension.la
INCLUDES = \
-I$(top_srcdir) \
@@ -13,6 +15,7 @@ INCLUDES = \
-DDATADIR=\""$(datadir)"\" \
-DSYSCONFDIR=\""$(sysconfdir)"\" \
-DNAUTILUS_DATADIR=\""$(datadir)/nautilus"\" \
+ -DNAUTILUS_EXTENSIONDIR=\""$(libdir)/nautilus/extensions-1.0"\" \
$(NULL)
dependency_static_libs = \
@@ -52,6 +55,10 @@ libnautilus_private_la_SOURCES = \
nautilus-cell-renderer-pixbuf-emblem.c \
nautilus-cell-renderer-pixbuf-emblem.h \
nautilus-cdrom-extensions.h \
+ nautilus-column-chooser.c \
+ nautilus-column-chooser.h \
+ nautilus-column-utilities.c \
+ nautilus-column-utilities.h \
nautilus-customization-data.c \
nautilus-customization-data.h \
nautilus-default-file-icon.c \
@@ -140,6 +147,8 @@ libnautilus_private_la_SOURCES = \
nautilus-metafile.h \
nautilus-mime-actions.c \
nautilus-mime-actions.h \
+ nautilus-module.c \
+ nautilus-module.h \
nautilus-monitor.c \
nautilus-monitor.h \
nautilus-program-chooser.c \
diff --git a/libnautilus-private/apps_nautilus_preferences.schemas.in b/libnautilus-private/apps_nautilus_preferences.schemas.in
index 3671bc39b..8bea57ce7 100644
--- a/libnautilus-private/apps_nautilus_preferences.schemas.in
+++ b/libnautilus-private/apps_nautilus_preferences.schemas.in
@@ -584,6 +584,36 @@
</schema>
<schema>
+ <key>/schemas/apps/nautilus/list_view/default_visible_columns</key>
+ <applyto>/apps/nautilus/list_view/default_visible_columns</applyto>
+ <owner>nautilus</owner>
+ <type>list</type>
+ <list_type>string</list_type>
+ <default>[name,size,type,date_modified]</default>
+ <locale name="C">
+ <short>Default list of columns visible in the list view</short>
+ <long>
+ Default list of columns visible in the list view.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/nautilus/list_view/default_column_order</key>
+ <applyto>/apps/nautilus/list_view/default_column_order</applyto>
+ <owner>nautilus</owner>
+ <type>list</type>
+ <list_type>string</list_type>
+ <default>[name,size,type,date_modified]</default>
+ <locale name="C">
+ <short>Default column order in the list view</short>
+ <long>
+ Default column order in the list view.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
<key>/schemas/apps/nautilus/preferences/hide_built_in_bookmarks</key>
<applyto>/apps/nautilus/preferences/hide_built_in_bookmarks</applyto>
<owner>nautilus</owner>
diff --git a/libnautilus-private/nautilus-bonobo-extensions.c b/libnautilus-private/nautilus-bonobo-extensions.c
index 6a363ce77..c9d1946a4 100644
--- a/libnautilus-private/nautilus-bonobo-extensions.c
+++ b/libnautilus-private/nautilus-bonobo-extensions.c
@@ -28,6 +28,8 @@
#include <config.h>
#include "nautilus-bonobo-extensions.h"
+#include "nautilus-icon-factory.h"
+
#include <eel/eel-string.h>
#include <eel/eel-gnome-extensions.h>
#include <eel/eel-debug.h>
@@ -487,6 +489,165 @@ nautilus_bonobo_set_label_for_toolitem_and_command (BonoboUIComponent *ui,
g_free (label_no_underscore);
}
+static char *
+get_extension_menu_item_xml (NautilusMenuItem *item)
+{
+ GString *ui_xml;
+ char *pixbuf_data;
+ GdkPixbuf *pixbuf;
+ char *name;
+ char *icon;
+
+ ui_xml = g_string_new ("");
+
+ g_object_get (G_OBJECT (item), "name", &name, "icon", &icon, NULL);
+
+ g_string_append_printf (ui_xml,
+ "<menuitem name=\"%s\" verb=\"%s\"",
+ name, name);
+
+ if (icon) {
+ pixbuf = nautilus_icon_factory_get_pixbuf_from_name
+ (icon,
+ NULL,
+ NAUTILUS_ICON_SIZE_FOR_MENUS,
+ NULL);
+ if (pixbuf) {
+ pixbuf_data = bonobo_ui_util_pixbuf_to_xml (pixbuf);
+ g_string_append_printf (ui_xml, " pixtype=\"pixbuf\" pixname=\"%s\"", pixbuf_data);
+ g_free (pixbuf_data);
+ g_object_unref (pixbuf);
+ }
+ }
+ g_string_append (ui_xml, "/>");
+
+ g_free (name);
+ g_free (icon);
+
+ return g_string_free (ui_xml, FALSE);
+}
+
+static void
+extension_action_callback (BonoboUIComponent *component,
+ gpointer callback_data, const char *path)
+{
+ nautilus_menu_item_activate (NAUTILUS_MENU_ITEM (callback_data));
+}
+
+void
+nautilus_bonobo_add_extension_item_command (BonoboUIComponent *ui,
+ NautilusMenuItem *item)
+{
+ GString *ui_xml;
+ GClosure *closure;
+ char *name;
+ char *label;
+ char *tip;
+ char *sensitive;
+
+ ui_xml = g_string_new ("<Root><commands>");
+
+ g_object_get (G_OBJECT (item),
+ "name", &name, "label", &label,
+ "tip", &tip, "sensitive", &sensitive,
+ NULL);
+
+ g_string_append_printf (ui_xml,
+ "<cmd name=\"%s\" label=\"%s\" tip=\"%s\" sensitive=\"%s\"/>",
+ name, label, tip, sensitive ? "1" : "0");
+
+ ui_xml = g_string_append (ui_xml, "</commands></Root>");
+
+ bonobo_ui_component_set (ui, "/", ui_xml->str, NULL);
+ g_string_free (ui_xml, TRUE);
+
+
+ closure = g_cclosure_new
+ (G_CALLBACK (extension_action_callback),
+ g_object_ref (item),
+ (GClosureNotify)g_object_unref);
+
+ bonobo_ui_component_add_verb_full (ui, name, closure);
+
+ g_free (name);
+ g_free (label);
+ g_free (tip);
+}
+
+void
+nautilus_bonobo_add_extension_item (BonoboUIComponent *ui,
+ const char *path,
+ NautilusMenuItem *item)
+{
+ char *item_xml;
+
+ item_xml = get_extension_menu_item_xml (item);
+
+ bonobo_ui_component_set (ui, path, item_xml, NULL);
+
+ g_free (item_xml);
+}
+
+static char *
+get_extension_toolbar_item_xml (NautilusMenuItem *item)
+{
+ GString *ui_xml;
+ char *pixbuf_data;
+ GdkPixbuf *pixbuf;
+ char *name;
+ char *icon;
+ gboolean priority;
+
+ ui_xml = g_string_new ("");
+
+
+ g_object_get (item,
+ "name", &name, "priority", &priority,
+ "icon", &icon,
+ NULL);
+ g_string_append_printf (ui_xml,
+ "<toolitem name=\"%s\" verb=\"%s\"",
+ name, name);
+
+ if (priority) {
+ g_string_append (ui_xml, " priority=\"1\"");
+ }
+
+ if (icon) {
+ pixbuf = nautilus_icon_factory_get_pixbuf_from_name
+ (icon,
+ NULL,
+ NAUTILUS_ICON_SIZE_FOR_MENUS,
+ NULL);
+ if (pixbuf) {
+ pixbuf_data = bonobo_ui_util_pixbuf_to_xml (pixbuf);
+ g_string_append_printf (ui_xml, " pixtype=\"pixbuf\" pixname=\"%s\"", pixbuf_data);
+ g_free (pixbuf_data);
+ g_object_unref (pixbuf);
+ }
+ }
+ g_string_append (ui_xml, "/>");
+
+ g_free (name);
+ g_free (icon);
+
+ return g_string_free (ui_xml, FALSE);
+}
+
+void
+nautilus_bonobo_add_extension_toolbar_item (BonoboUIComponent *ui,
+ const char *path,
+ NautilusMenuItem *item)
+{
+ char *item_xml;
+
+ item_xml = get_extension_toolbar_item_xml (item);
+
+ bonobo_ui_component_set (ui, path, item_xml, NULL);
+
+ g_free (item_xml);
+}
+
static void
activation_handle_done (NautilusBonoboActivationHandle *handle)
{
diff --git a/libnautilus-private/nautilus-bonobo-extensions.h b/libnautilus-private/nautilus-bonobo-extensions.h
index 3f3396192..f780761d6 100644
--- a/libnautilus-private/nautilus-bonobo-extensions.h
+++ b/libnautilus-private/nautilus-bonobo-extensions.h
@@ -32,6 +32,8 @@
#include <bonobo/bonobo-generic-factory.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <libnautilus-extension/nautilus-menu-item.h>
+
typedef struct NautilusBonoboActivationHandle NautilusBonoboActivationHandle;
typedef void (*NautilusBonoboActivationCallback) (NautilusBonoboActivationHandle *handle,
@@ -41,78 +43,87 @@ typedef void (*NautilusBonoboActivationCallback) (NautilusBonoboActivationHandle
typedef CORBA_Object (*NautilusBonoboCreateObject) (const char *iid,
gpointer callback_data);
-void nautilus_bonobo_set_accelerator (BonoboUIComponent *ui,
- const char *path,
- const char *accelerator);
-char * nautilus_bonobo_get_label (BonoboUIComponent *ui,
- const char *path);
-void nautilus_bonobo_set_label (BonoboUIComponent *ui,
- const char *path,
- const char *label);
-void nautilus_bonobo_set_tip (BonoboUIComponent *ui,
- const char *path,
- const char *tip);
-void nautilus_bonobo_set_sensitive (BonoboUIComponent *ui,
- const char *path,
- gboolean sensitive);
-void nautilus_bonobo_set_toggle_state (BonoboUIComponent *ui,
- const char *path,
- gboolean state);
-void nautilus_bonobo_set_hidden (BonoboUIComponent *ui,
- const char *path,
- gboolean hidden);
-gboolean nautilus_bonobo_get_hidden (BonoboUIComponent *ui,
- const char *path);
-void nautilus_bonobo_add_numbered_menu_item (BonoboUIComponent *ui,
- const char *container_path,
- guint index,
- const char *label,
- GdkPixbuf *pixbuf);
-void nautilus_bonobo_add_numbered_toggle_menu_item (BonoboUIComponent *ui,
- const char *container_path,
- guint index,
- const char *label);
-void nautilus_bonobo_add_numbered_radio_menu_item (BonoboUIComponent *ui,
- const char *container_path,
- guint index,
- const char *label,
- const char *radio_group_name);
-char * nautilus_bonobo_get_numbered_menu_item_command (BonoboUIComponent *ui,
- const char *container_path,
- guint index);
-char * nautilus_bonobo_get_numbered_menu_item_path (BonoboUIComponent *ui,
- const char *container_path,
- guint index);
+void nautilus_bonobo_set_accelerator (BonoboUIComponent *ui,
+ const char *path,
+ const char *accelerator);
+char * nautilus_bonobo_get_label (BonoboUIComponent *ui,
+ const char *path);
+void nautilus_bonobo_set_label (BonoboUIComponent *ui,
+ const char *path,
+ const char *label);
+void nautilus_bonobo_set_tip (BonoboUIComponent *ui,
+ const char *path,
+ const char *tip);
+void nautilus_bonobo_set_sensitive (BonoboUIComponent *ui,
+ const char *path,
+ gboolean sensitive);
+void nautilus_bonobo_set_toggle_state (BonoboUIComponent *ui,
+ const char *path,
+ gboolean state);
+void nautilus_bonobo_set_hidden (BonoboUIComponent *ui,
+ const char *path,
+ gboolean hidden);
+gboolean nautilus_bonobo_get_hidden (BonoboUIComponent *ui,
+ const char *path);
+void nautilus_bonobo_add_numbered_menu_item (BonoboUIComponent *ui,
+ const char *container_path,
+ guint index,
+ const char *label,
+ GdkPixbuf *pixbuf);
+void nautilus_bonobo_add_numbered_toggle_menu_item (BonoboUIComponent *ui,
+ const char *container_path,
+ guint index,
+ const char *label);
+void nautilus_bonobo_add_numbered_radio_menu_item (BonoboUIComponent *ui,
+ const char *container_path,
+ guint index,
+ const char *label,
+ const char *radio_group_name);
+char * nautilus_bonobo_get_numbered_menu_item_command (BonoboUIComponent *ui,
+ const char *container_path,
+ guint index);
+char * nautilus_bonobo_get_numbered_menu_item_path (BonoboUIComponent *ui,
+ const char *container_path,
+ guint index);
+
guint nautilus_bonobo_get_numbered_menu_item_index_from_command
- (const char *command);
+(const char *command);
char * nautilus_bonobo_get_numbered_menu_item_container_path_from_command
- (const char *command);
-void nautilus_bonobo_add_submenu (BonoboUIComponent *ui,
- const char *container_path,
- const char *label,
- GdkPixbuf *pixbuf);
-void nautilus_bonobo_add_menu_separator (BonoboUIComponent *ui,
- const char *path);
-void nautilus_bonobo_remove_menu_items_and_commands (BonoboUIComponent *ui,
- const char *container_path);
-void nautilus_bonobo_set_label_for_toolitem_and_command (BonoboUIComponent *ui,
- const char *toolitem_path,
- const char *command_path,
- const char *label_with_underscore);
-void nautilus_bonobo_set_icon (BonoboUIComponent *ui,
- const char *path,
- const char *icon_relative_path);
-
-void nautilus_bonobo_register_activation_shortcut (const char *iid,
- NautilusBonoboCreateObject create_object_callback,
- gpointer callback_data);
-void nautilus_bonobo_unregister_activation_shortcut (const char *iid);
-NautilusBonoboActivationHandle *nautilus_bonobo_activate_from_id (const char *iid,
- NautilusBonoboActivationCallback callback,
- gpointer callback_data);
-void nautilus_bonobo_activate_cancel (NautilusBonoboActivationHandle *handle);
-
-Bonobo_RegistrationResult nautilus_bonobo_activation_register_for_display (const char *iid,
- Bonobo_Unknown ref);
+(const char *command);
+void nautilus_bonobo_add_submenu (BonoboUIComponent *ui,
+ const char *container_path,
+ const char *label,
+ GdkPixbuf *pixbuf);
+void nautilus_bonobo_add_menu_separator (BonoboUIComponent *ui,
+ const char *path);
+void nautilus_bonobo_remove_menu_items_and_commands (BonoboUIComponent *ui,
+ const char *container_path);
+void nautilus_bonobo_set_label_for_toolitem_and_command (BonoboUIComponent *ui,
+ const char *toolitem_path,
+ const char *command_path,
+ const char *label_with_underscore);
+void nautilus_bonobo_set_icon (BonoboUIComponent *ui,
+ const char *path,
+ const char *icon_relative_path);
+void nautilus_bonobo_add_extension_item_command (BonoboUIComponent *ui,
+ NautilusMenuItem *item);
+void nautilus_bonobo_add_extension_item (BonoboUIComponent *ui,
+ const char *path,
+ NautilusMenuItem *item);
+void nautilus_bonobo_add_extension_toolbar_item (BonoboUIComponent *ui,
+ const char *path,
+ NautilusMenuItem *item);
+void nautilus_bonobo_register_activation_shortcut (const char *iid,
+ NautilusBonoboCreateObject create_object_callback,
+ gpointer callback_data);
+void nautilus_bonobo_unregister_activation_shortcut (const char *iid);
+NautilusBonoboActivationHandle *nautilus_bonobo_activate_from_id (const char *iid,
+ NautilusBonoboActivationCallback callback,
+ gpointer callback_data);
+void nautilus_bonobo_activate_cancel (NautilusBonoboActivationHandle *handle);
+Bonobo_RegistrationResult nautilus_bonobo_activation_register_for_display (const char *iid,
+ Bonobo_Unknown ref);
+
+
#endif /* NAUTILUS_BONOBO_EXTENSIONS_H */
diff --git a/libnautilus-private/nautilus-column-chooser.c b/libnautilus-private/nautilus-column-chooser.c
new file mode 100644
index 000000000..74f0ee3e3
--- /dev/null
+++ b/libnautilus-private/nautilus-column-chooser.c
@@ -0,0 +1,652 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+
+/* nautilus-column-chooser.h - A column chooser widget
+
+ Copyright (C) 2004 Novell, Inc.
+
+ The Gnome Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The Gnome Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the Gnome Library; see the column COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Authors: Dave Camp <dave@ximian.com>
+*/
+
+#include <config.h>
+#include "nautilus-column-chooser.h"
+
+#include <string.h>
+#include <eel/eel-glib-extensions.h>
+#include <eel/eel-gtk-macros.h>
+#include <gtk/gtkbutton.h>
+#include <gtk/gtkcellrenderertext.h>
+#include <gtk/gtkcellrenderertoggle.h>
+#include <gtk/gtkliststore.h>
+#include <gtk/gtkhseparator.h>
+#include <gtk/gtkscrolledwindow.h>
+#include <gtk/gtktreeselection.h>
+#include <gtk/gtktreeview.h>
+#include <gtk/gtkvbox.h>
+#include <libgnome/gnome-i18n.h>
+
+#include "nautilus-column-utilities.h"
+
+struct _NautilusColumnChooserDetails
+{
+ GtkTreeView *view;
+ GtkListStore *store;
+
+ GtkWidget *move_up_button;
+ GtkWidget *move_down_button;
+ GtkWidget *show_button;
+ GtkWidget *hide_button;
+ GtkWidget *use_default_button;
+};
+
+enum {
+ COLUMN_VISIBLE,
+ COLUMN_LABEL,
+ COLUMN_NAME,
+ NUM_COLUMNS
+};
+
+enum {
+ CHANGED,
+ USE_DEFAULT,
+ LAST_SIGNAL
+};
+static guint signals[LAST_SIGNAL];
+
+static void nautilus_column_chooser_class_init (NautilusColumnChooserClass *chooser_class);
+static void nautilus_column_chooser_init (NautilusColumnChooser *chooser);
+static void nautilus_column_chooser_destroy (GtkObject *object);
+static void nautilus_column_chooser_finalize (GObject *object);
+
+EEL_CLASS_BOILERPLATE (NautilusColumnChooser, nautilus_column_chooser, GTK_TYPE_HBOX);
+
+static void
+nautilus_column_chooser_class_init (NautilusColumnChooserClass *chooser_class)
+{
+ G_OBJECT_CLASS (chooser_class)->finalize = nautilus_column_chooser_finalize;
+ GTK_OBJECT_CLASS (chooser_class)->destroy = nautilus_column_chooser_destroy;
+
+ signals[CHANGED] = g_signal_new
+ ("changed",
+ G_TYPE_FROM_CLASS (chooser_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (NautilusColumnChooserClass,
+ changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ signals[USE_DEFAULT] = g_signal_new
+ ("use_default",
+ G_TYPE_FROM_CLASS (chooser_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (NautilusColumnChooserClass,
+ use_default),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ g_type_class_add_private (chooser_class, sizeof (NautilusColumnChooserDetails));
+}
+
+static void
+update_buttons (NautilusColumnChooser *chooser)
+{
+ GtkTreeSelection *selection;
+ GtkTreeIter iter;
+
+ selection = gtk_tree_view_get_selection (chooser->details->view);
+
+ if (gtk_tree_selection_get_selected (selection, NULL, &iter)) {
+ gboolean visible;
+ gboolean top;
+ gboolean bottom;
+ GtkTreePath *first;
+ GtkTreePath *path;
+
+ gtk_tree_model_get (GTK_TREE_MODEL (chooser->details->store),
+ &iter,
+ COLUMN_VISIBLE, &visible,
+ -1);
+
+ path = gtk_tree_model_get_path (GTK_TREE_MODEL (chooser->details->store),
+ &iter);
+ first = gtk_tree_path_new_first ();
+
+ top = (gtk_tree_path_compare (path, first) == 0);
+
+ gtk_tree_path_free (path);
+ gtk_tree_path_free (first);
+
+ bottom = !gtk_tree_model_iter_next (GTK_TREE_MODEL (chooser->details->store),
+ &iter);
+
+ gtk_widget_set_sensitive (chooser->details->move_up_button,
+ !top);
+ gtk_widget_set_sensitive (chooser->details->move_down_button,
+ !bottom);
+ gtk_widget_set_sensitive (chooser->details->show_button,
+ !visible);
+ gtk_widget_set_sensitive (chooser->details->hide_button,
+ visible);
+ } else {
+ gtk_widget_set_sensitive (chooser->details->move_up_button,
+ FALSE);
+ gtk_widget_set_sensitive (chooser->details->move_down_button,
+ FALSE);
+ gtk_widget_set_sensitive (chooser->details->show_button,
+ FALSE);
+ gtk_widget_set_sensitive (chooser->details->hide_button,
+ FALSE);
+ }
+}
+
+static void
+list_changed (NautilusColumnChooser *chooser)
+{
+ update_buttons (chooser);
+ g_signal_emit (chooser, signals[CHANGED], 0);
+}
+
+static void
+visible_toggled_callback (GtkCellRendererToggle *cell,
+ char *path_string,
+ gpointer user_data)
+{
+ NautilusColumnChooser *chooser;
+ GtkTreePath *path;
+ GtkTreeIter iter;
+ gboolean visible;
+
+ chooser = NAUTILUS_COLUMN_CHOOSER (user_data);
+
+ path = gtk_tree_path_new_from_string (path_string);
+ gtk_tree_model_get_iter (GTK_TREE_MODEL (chooser->details->store),
+ &iter, path);
+ gtk_tree_model_get (GTK_TREE_MODEL (chooser->details->store),
+ &iter, COLUMN_VISIBLE, &visible, -1);
+ gtk_list_store_set (chooser->details->store,
+ &iter, COLUMN_VISIBLE, !visible, -1);
+ gtk_tree_path_free (path);
+ list_changed (chooser);
+}
+
+static void
+selection_changed_callback (GtkTreeSelection *selection, gpointer user_data)
+{
+ update_buttons (NAUTILUS_COLUMN_CHOOSER (user_data));
+}
+
+static void
+row_deleted_callback (GtkTreeModel *model,
+ GtkTreePath *path,
+ gpointer user_data)
+{
+ list_changed (NAUTILUS_COLUMN_CHOOSER (user_data));
+}
+
+static void
+add_tree_view (NautilusColumnChooser *chooser)
+{
+ GtkWidget *scrolled;
+ GtkWidget *view;
+ GtkListStore *store;
+ GtkCellRenderer *cell;
+ GtkTreeSelection *selection;
+
+ view = gtk_tree_view_new ();
+ gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (view), FALSE);
+
+ store = gtk_list_store_new (NUM_COLUMNS,
+ G_TYPE_BOOLEAN,
+ G_TYPE_STRING,
+ G_TYPE_STRING);
+
+ gtk_tree_view_set_model (GTK_TREE_VIEW (view),
+ GTK_TREE_MODEL (store));
+ g_object_unref (store);
+
+ gtk_tree_view_set_reorderable (GTK_TREE_VIEW (view), TRUE);
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (view));
+ g_signal_connect (selection, "changed",
+ G_CALLBACK (selection_changed_callback), chooser);
+
+ cell = gtk_cell_renderer_toggle_new ();
+
+ g_signal_connect (G_OBJECT (cell), "toggled",
+ G_CALLBACK (visible_toggled_callback), chooser);
+
+ gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (view),
+ -1, NULL,
+ cell,
+ "active", COLUMN_VISIBLE,
+ NULL);
+
+ cell = gtk_cell_renderer_text_new ();
+
+ gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (view),
+ -1, NULL,
+ cell,
+ "text", COLUMN_LABEL,
+ NULL);
+
+ chooser->details->view = GTK_TREE_VIEW (view);
+ chooser->details->store = store;
+
+ gtk_widget_show (view);
+
+ scrolled = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled),
+ GTK_SHADOW_IN);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),
+ GTK_POLICY_AUTOMATIC,
+ GTK_POLICY_AUTOMATIC);
+ gtk_widget_show (GTK_WIDGET (scrolled));
+
+ gtk_container_add (GTK_CONTAINER (scrolled), view);
+ gtk_box_pack_start (GTK_BOX (chooser), scrolled, TRUE, TRUE, 0);
+}
+
+static void
+set_selection_visible (NautilusColumnChooser *chooser, gboolean visible)
+{
+ GtkTreeIter iter;
+ GtkTreeSelection *selection;
+
+ selection = gtk_tree_view_get_selection (chooser->details->view);
+
+ if (gtk_tree_selection_get_selected (selection, NULL, &iter)) {
+ gtk_list_store_set (chooser->details->store,
+ &iter,
+ COLUMN_VISIBLE, visible,
+ -1);
+ }
+
+ list_changed (chooser);
+}
+
+static void
+move_up_clicked_callback (GtkWidget *button, gpointer user_data)
+{
+ NautilusColumnChooser *chooser;
+ GtkTreeIter iter;
+ GtkTreeSelection *selection;
+
+ chooser = NAUTILUS_COLUMN_CHOOSER (user_data);
+
+ selection = gtk_tree_view_get_selection (chooser->details->view);
+
+ if (gtk_tree_selection_get_selected (selection, NULL, &iter)) {
+ GtkTreePath *path;
+ GtkTreeIter prev;
+
+ path = gtk_tree_model_get_path (GTK_TREE_MODEL (chooser->details->store), &iter);
+ gtk_tree_path_prev (path);
+ if (gtk_tree_model_get_iter (GTK_TREE_MODEL (chooser->details->store), &prev, path)) {
+ gtk_list_store_move_before (chooser->details->store,
+ &iter,
+ &prev);
+ }
+ gtk_tree_path_free (path);
+ }
+
+ list_changed (chooser);
+}
+
+static void
+move_down_clicked_callback (GtkWidget *button, gpointer user_data)
+{
+ NautilusColumnChooser *chooser;
+ GtkTreeIter iter;
+ GtkTreeSelection *selection;
+
+ chooser = NAUTILUS_COLUMN_CHOOSER (user_data);
+
+ selection = gtk_tree_view_get_selection (chooser->details->view);
+
+ if (gtk_tree_selection_get_selected (selection, NULL, &iter)) {
+ GtkTreeIter next;
+
+ next = iter;
+
+ if (gtk_tree_model_iter_next (GTK_TREE_MODEL (chooser->details->store), &next)) {
+ gtk_list_store_move_after (chooser->details->store,
+ &iter,
+ &next);
+ }
+ }
+
+ list_changed (chooser);
+}
+
+static void
+show_clicked_callback (GtkWidget *button, gpointer user_data)
+{
+ set_selection_visible (NAUTILUS_COLUMN_CHOOSER (user_data), TRUE);
+}
+
+static void
+hide_clicked_callback (GtkWidget *button, gpointer user_data)
+{
+ set_selection_visible (NAUTILUS_COLUMN_CHOOSER (user_data), FALSE);
+}
+
+static void
+use_default_clicked_callback (GtkWidget *button, gpointer user_data)
+{
+ g_signal_emit (NAUTILUS_COLUMN_CHOOSER (user_data),
+ signals[USE_DEFAULT], 0);
+}
+
+static void
+add_buttons (NautilusColumnChooser *chooser)
+{
+ GtkWidget *box;
+ GtkWidget *separator;
+
+ box = gtk_vbox_new (FALSE, 8);
+ gtk_widget_show (box);
+
+ chooser->details->move_up_button = gtk_button_new_with_mnemonic ("Move _Up");
+ g_signal_connect (chooser->details->move_up_button,
+ "clicked", G_CALLBACK (move_up_clicked_callback),
+ chooser);
+ gtk_widget_show (chooser->details->move_up_button);
+ gtk_widget_set_sensitive (chooser->details->move_up_button, FALSE);
+ gtk_box_pack_start (GTK_BOX (box), chooser->details->move_up_button,
+ FALSE, FALSE, 0);
+
+ chooser->details->move_down_button = gtk_button_new_with_mnemonic ("Move _Down");
+ g_signal_connect (chooser->details->move_down_button,
+ "clicked", G_CALLBACK (move_down_clicked_callback),
+ chooser);
+ gtk_widget_show (chooser->details->move_down_button);
+ gtk_widget_set_sensitive (chooser->details->move_down_button, FALSE);
+ gtk_box_pack_start (GTK_BOX (box), chooser->details->move_down_button,
+ FALSE, FALSE, 0);
+
+ chooser->details->show_button = gtk_button_new_with_mnemonic ("_Show");
+ g_signal_connect (chooser->details->show_button,
+ "clicked", G_CALLBACK (show_clicked_callback),
+ chooser);
+
+ gtk_widget_set_sensitive (chooser->details->show_button, FALSE);
+ gtk_widget_show (chooser->details->show_button);
+ gtk_box_pack_start (GTK_BOX (box), chooser->details->show_button,
+ FALSE, FALSE, 0);
+
+ chooser->details->hide_button = gtk_button_new_with_mnemonic ("_Hide");
+ g_signal_connect (chooser->details->hide_button,
+ "clicked", G_CALLBACK (hide_clicked_callback),
+ chooser);
+ gtk_widget_set_sensitive (chooser->details->hide_button, FALSE);
+ gtk_widget_show (chooser->details->hide_button);
+ gtk_box_pack_start (GTK_BOX (box), chooser->details->hide_button,
+ FALSE, FALSE, 0);
+
+ separator = gtk_hseparator_new ();
+ gtk_widget_show (separator);
+ gtk_box_pack_start (GTK_BOX (box), separator, FALSE, FALSE, 0);
+
+ chooser->details->use_default_button = gtk_button_new_with_mnemonic ("_Use Default");
+ g_signal_connect (chooser->details->use_default_button,
+ "clicked", G_CALLBACK (use_default_clicked_callback),
+ chooser);
+ gtk_widget_show (chooser->details->use_default_button);
+ gtk_box_pack_start (GTK_BOX (box), chooser->details->use_default_button,
+ FALSE, FALSE, 0);
+
+ gtk_box_pack_start (GTK_BOX (chooser), box,
+ FALSE, FALSE, 0);
+}
+
+static void
+populate_tree (NautilusColumnChooser *chooser)
+{
+ GList *columns;
+ GList *l;
+
+ columns = nautilus_get_all_columns ();
+
+ for (l = columns; l != NULL; l = l->next) {
+ GtkTreeIter iter;
+ NautilusColumn *column;
+ char *name;
+ char *label;
+
+ column = NAUTILUS_COLUMN (l->data);
+
+ g_object_get (G_OBJECT (column),
+ "name", &name, "label", &label,
+ NULL);
+
+ gtk_list_store_append (chooser->details->store, &iter);
+ gtk_list_store_set (chooser->details->store, &iter,
+ COLUMN_VISIBLE, FALSE,
+ COLUMN_LABEL, label,
+ COLUMN_NAME, name,
+ -1);
+
+ g_free (name);
+ g_free (label);
+ }
+
+ nautilus_column_list_free (columns);
+}
+
+static void
+nautilus_column_chooser_init (NautilusColumnChooser *chooser)
+{
+ chooser->details = G_TYPE_INSTANCE_GET_PRIVATE ((chooser), NAUTILUS_TYPE_COLUMN_CHOOSER, NautilusColumnChooserDetails);
+
+ g_object_set (G_OBJECT (chooser),
+ "homogeneous", FALSE,
+ "spacing", 8,
+ NULL);
+
+ add_tree_view (chooser);
+ add_buttons (chooser);
+
+ populate_tree (chooser);
+
+ g_signal_connect (chooser->details->store, "row_deleted",
+ G_CALLBACK (row_deleted_callback), chooser);
+}
+
+static void
+nautilus_column_chooser_destroy (GtkObject *object)
+{
+ NautilusColumnChooser *chooser;
+
+ chooser = NAUTILUS_COLUMN_CHOOSER (object);
+}
+
+static void
+nautilus_column_chooser_finalize (GObject *object)
+{
+}
+
+static void
+set_visible_columns (NautilusColumnChooser *chooser,
+ GList *visible_columns)
+{
+ GtkTreeIter iter;
+
+ if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (chooser->details->store),
+ &iter)) {
+ do {
+ char *name;
+ gboolean visible;
+
+ gtk_tree_model_get (GTK_TREE_MODEL (chooser->details->store),
+ &iter,
+ COLUMN_NAME, &name,
+ -1);
+
+ visible = (eel_g_str_list_index (visible_columns, name) != -1);
+
+ gtk_list_store_set (chooser->details->store,
+ &iter,
+ COLUMN_VISIBLE, visible,
+ -1);
+ g_free (name);
+
+ } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (chooser->details->store), &iter));
+ }
+}
+
+static GList *
+get_column_names (NautilusColumnChooser *chooser, gboolean only_visible)
+{
+
+ GList *ret;
+ GtkTreeIter iter;
+
+ ret = NULL;
+ if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (chooser->details->store),
+ &iter)) {
+ do {
+ char *name;
+ gboolean visible;
+ gtk_tree_model_get (GTK_TREE_MODEL (chooser->details->store),
+ &iter,
+ COLUMN_VISIBLE, &visible,
+ COLUMN_NAME, &name,
+ -1);
+ if (!only_visible || visible) {
+ /* give ownership to the list */
+ ret = g_list_prepend (ret, name);
+ }
+
+ } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (chooser->details->store), &iter));
+ }
+
+ return g_list_reverse (ret);
+}
+
+static gboolean
+get_column_iter (NautilusColumnChooser *chooser,
+ NautilusColumn *column,
+ GtkTreeIter *iter)
+{
+ char *column_name;
+
+ g_object_get (NAUTILUS_COLUMN (column), "name", &column_name, NULL);
+
+ if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (chooser->details->store),
+ iter)) {
+ do {
+ char *name;
+
+
+ gtk_tree_model_get (GTK_TREE_MODEL (chooser->details->store),
+ iter,
+ COLUMN_NAME, &name,
+ -1);
+ if (!strcmp (name, column_name)) {
+ g_free (column_name);
+ g_free (name);
+ return TRUE;
+ }
+
+ g_free (name);
+ } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (chooser->details->store), iter));
+ }
+ g_free (column_name);
+ return FALSE;
+}
+
+static void
+set_column_order (NautilusColumnChooser *chooser,
+ GList *column_order)
+
+{
+ GList *columns;
+ GList *l;
+ GtkTreePath *path;
+
+ columns = nautilus_get_all_columns ();
+ columns = nautilus_sort_columns (columns, column_order);
+
+ g_signal_handlers_block_by_func (chooser->details->store,
+ G_CALLBACK (row_deleted_callback),
+ chooser);
+
+ path = gtk_tree_path_new_first ();
+ for (l = columns; l != NULL; l = l->next) {
+ GtkTreeIter iter;
+
+ if (get_column_iter (chooser, NAUTILUS_COLUMN (l->data), &iter)) {
+ GtkTreeIter before;
+ if (path) {
+ gtk_tree_model_get_iter (GTK_TREE_MODEL (chooser->details->store),
+ &before, path);
+ gtk_list_store_move_after (chooser->details->store,
+ &iter, &before);
+ gtk_tree_path_next (path);
+
+ } else {
+ gtk_list_store_move_after (chooser->details->store,
+ &iter, NULL);
+ }
+ }
+ }
+ gtk_tree_path_free (path);
+ g_signal_handlers_unblock_by_func (chooser->details->store,
+ G_CALLBACK (row_deleted_callback),
+ chooser);
+
+ nautilus_column_list_free (columns);
+}
+
+void
+nautilus_column_chooser_set_settings (NautilusColumnChooser *chooser,
+ GList *visible_columns,
+ GList *column_order)
+{
+ g_return_if_fail (NAUTILUS_IS_COLUMN_CHOOSER (chooser));
+ g_return_if_fail (visible_columns != NULL);
+ g_return_if_fail (column_order != NULL);
+
+ set_visible_columns (chooser, visible_columns);
+ set_column_order (chooser, column_order);
+
+ list_changed (chooser);
+}
+
+void
+nautilus_column_chooser_get_settings (NautilusColumnChooser *chooser,
+ GList **visible_columns,
+ GList **column_order)
+{
+ g_return_if_fail (NAUTILUS_IS_COLUMN_CHOOSER (chooser));
+ g_return_if_fail (visible_columns != NULL);
+ g_return_if_fail (column_order != NULL);
+
+ *visible_columns = get_column_names (chooser, TRUE);
+ *column_order = get_column_names (chooser, FALSE);
+}
+
+GtkWidget *
+nautilus_column_chooser_new (void)
+{
+ return g_object_new (NAUTILUS_TYPE_COLUMN_CHOOSER, NULL);
+}
+
+
+
diff --git a/libnautilus-private/nautilus-column-chooser.h b/libnautilus-private/nautilus-column-chooser.h
new file mode 100644
index 000000000..677f15280
--- /dev/null
+++ b/libnautilus-private/nautilus-column-chooser.h
@@ -0,0 +1,61 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+
+/* nautilus-column-choose.h - A column chooser widget
+
+ Copyright (C) 2004 Novell, Inc.
+
+ The Gnome Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The Gnome Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the Gnome Library; see the column COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Authors: Dave Camp <dave@ximian.com>
+*/
+
+#ifndef NAUTILUS_COLUMN_CHOOSER_H
+#define NAUTILUS_COLUMN_CHOOSER_H
+
+#include <gtk/gtkhbox.h>
+
+#define NAUTILUS_TYPE_COLUMN_CHOOSER (nautilus_column_chooser_get_type ())
+#define NAUTILUS_COLUMN_CHOOSER(obj) (GTK_CHECK_CAST ((obj), NAUTILUS_TYPE_COLUMN_CHOOSER, NautilusColumnChooser))
+#define NAUTILUS_COLUMN_CHOOSER_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_COLUMN_CHOOSER, NautilusColumnChooserClass))
+#define NAUTILUS_IS_COLUMN_CHOOSER(obj) (GTK_CHECK_TYPE ((obj), NAUTILUS_TYPE_COLUMN_CHOOSER))
+#define NAUTILUS_IS_COLUMN_CHOOSER_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), NAUTILUS_TYPE_COLUMN_CHOOSER))
+
+typedef struct _NautilusColumnChooserDetails NautilusColumnChooserDetails;
+
+typedef struct {
+ GtkHBox parent;
+
+ NautilusColumnChooserDetails *details;
+} NautilusColumnChooser;
+
+typedef struct {
+ GtkHBoxClass parent_slot;
+
+ void (*changed) (NautilusColumnChooser *chooser);
+ void (*use_default) (NautilusColumnChooser *chooser);
+} NautilusColumnChooserClass;
+
+GType nautilus_column_chooser_get_type (void);
+GtkWidget *nautilus_column_chooser_new (void);
+void nautilus_column_chooser_set_settings (NautilusColumnChooser *chooser,
+ GList *visible_columns,
+ GList *column_order);
+void nautilus_column_chooser_get_settings (NautilusColumnChooser *chooser,
+ GList **visible_columns,
+ GList **column_order);
+
+
+#endif /* NAUTILUS_COLUMN_CHOOSER_H */
diff --git a/libnautilus-private/nautilus-column-utilities.c b/libnautilus-private/nautilus-column-utilities.c
new file mode 100644
index 000000000..a233db721
--- /dev/null
+++ b/libnautilus-private/nautilus-column-utilities.c
@@ -0,0 +1,228 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+
+/* nautilus-column-utilities.h - Utilities related to column specifications
+
+ Copyright (C) 2004 Novell, Inc.
+
+ The Gnome Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The Gnome Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the Gnome Library; see the column COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Authors: Dave Camp <dave@ximian.com>
+*/
+
+#include <config.h>
+#include "nautilus-column-utilities.h"
+
+#include <string.h>
+#include <eel/eel-glib-extensions.h>
+#include <libgnome/gnome-i18n.h>
+#include <libnautilus-extension/nautilus-column-provider.h>
+#include <libnautilus-private/nautilus-module.h>
+
+static GList *
+get_builtin_columns (void)
+{
+ GList *columns;
+
+ columns = g_list_append (NULL,
+ g_object_new (NAUTILUS_TYPE_COLUMN,
+ "name", "name",
+ "attribute", "name",
+ "label", _("Name"),
+ "description", _("The name and icon of the file."),
+ NULL));
+ columns = g_list_append (columns,
+ g_object_new (NAUTILUS_TYPE_COLUMN,
+ "name", "size",
+ "attribute", "size",
+ "label", _("Size"),
+ "description", _("The size of the file."),
+ "xalign", 1.0,
+ NULL));
+ columns = g_list_append (columns,
+ g_object_new (NAUTILUS_TYPE_COLUMN,
+ "name", "type",
+ "attribute", "type",
+ "label", _("Type"),
+ "description", _("The type of the file."),
+ NULL));
+ columns = g_list_append (columns,
+ g_object_new (NAUTILUS_TYPE_COLUMN,
+ "name", "date_modified",
+ "attribute", "date_modified",
+ "label", _("Date Modified"),
+ "description", _("The date the file was modified."),
+ NULL));
+
+ columns = g_list_append (columns,
+ g_object_new (NAUTILUS_TYPE_COLUMN,
+ "name", "date_accessed",
+ "attribute", "date_accessed",
+ "label", _("Date Accessed"),
+ "description", _("The date the file was accessed."),
+ NULL));
+
+ columns = g_list_append (columns,
+ g_object_new (NAUTILUS_TYPE_COLUMN,
+ "name", "owner",
+ "attribute", "owner",
+ "label", _("Owner"),
+ "description", _("The owner of the file."),
+ NULL));
+
+ columns = g_list_append (columns,
+ g_object_new (NAUTILUS_TYPE_COLUMN,
+ "name", "group",
+ "attribute", "group",
+ "label", _("Group"),
+ "description", _("The group of the file."),
+ NULL));
+
+ columns = g_list_append (columns,
+ g_object_new (NAUTILUS_TYPE_COLUMN,
+ "name", "permissions",
+ "attribute", "permissions",
+ "label", _("Permissions"),
+ "description", _("The permissions of the file."),
+ NULL));
+
+ columns = g_list_append (columns,
+ g_object_new (NAUTILUS_TYPE_COLUMN,
+ "name", "octal_permissions",
+ "attribute", "octal_permissions",
+ "label", _("Octal Permissions"),
+ "description", _("The permissions of the file, in octal notation."),
+ NULL));
+
+ columns = g_list_append (columns,
+ g_object_new (NAUTILUS_TYPE_COLUMN,
+ "name", "mime_type",
+ "attribute", "mime_type",
+ "label", _("MIME Type"),
+ "description", _("The mime type of the file."),
+ NULL));
+ return columns;
+}
+
+static GList *
+get_extension_columns (void)
+{
+ GList *columns;
+ GList *providers;
+ GList *l;
+
+ providers = nautilus_module_get_extensions_for_type (NAUTILUS_TYPE_COLUMN_PROVIDER);
+
+ columns = NULL;
+
+ for (l = providers; l != NULL; l = l->next) {
+ NautilusColumnProvider *provider;
+ GList *provider_columns;
+
+ provider = NAUTILUS_COLUMN_PROVIDER (l->data);
+ provider_columns = nautilus_column_provider_get_columns (provider);
+ columns = g_list_concat (columns, provider_columns);
+ }
+
+ nautilus_module_extension_list_free (providers);
+
+ return columns;
+}
+
+GList *
+nautilus_get_all_columns (void)
+{
+ static GList *columns = NULL;
+
+ if (!columns) {
+ columns = g_list_concat (get_builtin_columns (),
+ get_extension_columns ());
+ }
+
+ return nautilus_column_list_copy (columns);
+}
+
+GList *
+nautilus_column_list_copy (GList *columns)
+{
+ GList *ret;
+ GList *l;
+
+ ret = g_list_copy (columns);
+
+ for (l = ret; l != NULL; l = l->next) {
+ g_object_ref (l->data);
+ }
+
+ return ret;
+}
+
+void
+nautilus_column_list_free (GList *columns)
+{
+ GList *l;
+
+ for (l = columns; l != NULL; l = l->next) {
+ g_object_unref (l->data);
+ }
+
+ g_list_free (columns);
+}
+
+static int
+column_compare (NautilusColumn *a, NautilusColumn *b, GList *column_order)
+{
+ int index_a;
+ int index_b;
+ char *name;
+
+ g_object_get (G_OBJECT (a), "name", &name, NULL);
+ index_a = eel_g_str_list_index (column_order, name);
+ g_free (name);
+
+ g_object_get (G_OBJECT (b), "name", &name, NULL);
+ index_b = eel_g_str_list_index (column_order, name);
+ g_free (name);
+
+ if (index_a == index_b) {
+ int ret;
+ char *label_a;
+ char *label_b;
+
+ g_object_get (G_OBJECT (a), "label", &label_a, NULL);
+ g_object_get (G_OBJECT (b), "label", &label_b, NULL);
+ ret = strcmp (label_a, label_b);
+ g_free (a);
+ g_free (b);
+
+ return ret;
+ } else if (index_a == -1) {
+ return 1;
+ } else if (index_b == -1) {
+ return -1;
+ } else {
+ return index_a - index_b;
+ }
+}
+
+GList *
+nautilus_sort_columns (GList *columns,
+ GList *column_order)
+{
+ return g_list_sort_with_data (columns,
+ (GCompareDataFunc)column_compare,
+ column_order);
+}
+
diff --git a/libnautilus-private/nautilus-column-utilities.h b/libnautilus-private/nautilus-column-utilities.h
new file mode 100644
index 000000000..48611db6c
--- /dev/null
+++ b/libnautilus-private/nautilus-column-utilities.h
@@ -0,0 +1,38 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+
+/* nautilus-column-utilities.h - Utilities related to column specifications
+
+ Copyright (C) 2004 Novell, Inc.
+
+ The Gnome Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The Gnome Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the Gnome Library; see the column COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Authors: Dave Camp <dave@ximian.com>
+*/
+
+#ifndef NAUTILUS_COLUMN_UTILITIES_H
+#define NAUTILUS_COLUMN_UTILITIES_H
+
+#include <libnautilus-extension/nautilus-column.h>
+
+GList *nautilus_get_all_columns (void);
+GList *nautilus_column_list_copy (GList *columns);
+void nautilus_column_list_free (GList *columns);
+
+GList *nautilus_sort_columns (GList *columns,
+ GList *column_order);
+
+
+#endif /* NAUTILUS_COLUMN_UTILITIES_H */
diff --git a/libnautilus-private/nautilus-directory-async.c b/libnautilus-private/nautilus-directory-async.c
index 343dd4db3..ab6394dd7 100644
--- a/libnautilus-private/nautilus-directory-async.c
+++ b/libnautilus-private/nautilus-directory-async.c
@@ -32,6 +32,7 @@
#include "nautilus-file-utilities.h"
#include "nautilus-global-preferences.h"
#include "nautilus-link.h"
+#include "nautilus-marshal.h"
#include "nautilus-metafile.h"
#include "nautilus-search-uri.h"
#include <eel/eel-glib-extensions.h>
@@ -94,6 +95,13 @@ typedef struct {
Request request;
} Monitor;
+typedef struct {
+ NautilusDirectory *directory;
+ NautilusInfoProvider *provider;
+ NautilusOperationHandle *handle;
+ NautilusOperationResult result;
+} InfoProviderResponse;
+
typedef gboolean (* RequestCheck) (const Request *);
typedef gboolean (* FileCheck) (NautilusFile *);
@@ -127,8 +135,12 @@ static gboolean file_needs_high_priority_work_done (NautilusDirectory *directory
NautilusFile *file);
static gboolean file_needs_low_priority_work_done (NautilusDirectory *directory,
NautilusFile *file);
+static gboolean file_needs_extension_work_done (NautilusDirectory *directory,
+ NautilusFile *file);
static void move_file_to_low_priority_queue (NautilusDirectory *directory,
NautilusFile *file);
+static void move_file_to_extension_queue (NautilusDirectory *directory,
+ NautilusFile *file);
void
@@ -571,6 +583,8 @@ nautilus_directory_set_up_request (Request *request,
request->metafile |= (file_attributes &
NAUTILUS_FILE_ATTRIBUTE_METADATA) != FALSE;
+
+ request->extension_info = (file_attributes & NAUTILUS_FILE_ATTRIBUTE_EXTENSION_INFO) != FALSE;
}
static void
@@ -1748,6 +1762,17 @@ wants_link_info (const Request *request)
return request->link_info;
}
+static gboolean
+lacks_extension_info (NautilusFile *file)
+{
+ return file->details->pending_info_providers != NULL;
+}
+
+static gboolean
+wants_extension_info (const Request *request)
+{
+ return request->extension_info;
+}
static gboolean
has_problem (NautilusDirectory *directory, NautilusFile *file, FileCheck problem)
@@ -3136,6 +3161,153 @@ link_info_start (NautilusDirectory *directory,
}
static void
+extension_info_cancel (NautilusDirectory *directory)
+{
+ if (directory->details->extension_info_in_progress != NULL) {
+ nautilus_info_provider_cancel_update
+ (directory->details->extension_info_provider,
+ directory->details->extension_info_in_progress);
+
+ directory->details->extension_info_in_progress = NULL;
+ directory->details->extension_info_file = NULL;
+ directory->details->extension_info_provider = NULL;
+
+ async_job_end (directory, "extension info");
+ }
+}
+
+static void
+extension_info_stop (NautilusDirectory *directory)
+{
+ if (directory->details->extension_info_in_progress != NULL) {
+ NautilusFile *file;
+
+ file = directory->details->extension_info_file;
+ if (file != NULL) {
+ g_assert (NAUTILUS_IS_FILE (file));
+ g_assert (file->details->directory == directory);
+ if (is_needy (file, lacks_extension_info, wants_extension_info)) {
+ return;
+ }
+ }
+
+ /* The info is not wanted, so stop it. */
+ extension_info_cancel (directory);
+ }
+}
+
+static void
+finish_info_provider (NautilusDirectory *directory,
+ NautilusFile *file,
+ NautilusInfoProvider *provider)
+{
+ file->details->pending_info_providers =
+ g_list_remove (file->details->pending_info_providers,
+ provider);
+ g_object_unref (provider);
+
+ nautilus_directory_async_state_changed (directory);
+
+ if (file->details->pending_info_providers == NULL) {
+ nautilus_file_info_providers_done (file);
+ }
+}
+
+
+static gboolean
+info_provider_idle_callback (gpointer user_data)
+{
+ InfoProviderResponse *response;
+ NautilusDirectory *directory;
+
+ response = user_data;
+ directory = response->directory;
+
+ if (response->handle != directory->details->extension_info_in_progress
+ || response->provider != directory->details->extension_info_provider) {
+ g_warning ("Unexpected plugin response. This probably indicates a bug in a Nautilus extension: handle=%p", response->handle);
+ } else {
+ NautilusFile *file;
+ async_job_end (directory, "extension info");
+
+ file = directory->details->extension_info_file;
+
+ directory->details->extension_info_file = NULL;
+ directory->details->extension_info_provider = NULL;
+ directory->details->extension_info_in_progress = NULL;
+
+ finish_info_provider (directory, file, response->provider);
+ }
+
+ return FALSE;
+}
+
+static void
+info_provider_callback (NautilusInfoProvider *provider,
+ NautilusOperationHandle *handle,
+ NautilusOperationResult result,
+ gpointer user_data)
+{
+ InfoProviderResponse *response;
+
+ response = g_new0 (InfoProviderResponse, 1);
+ response->provider = provider;
+ response->handle = handle;
+ response->result = result;
+ response->directory = NAUTILUS_DIRECTORY (user_data);
+
+ g_idle_add (info_provider_idle_callback, response);
+}
+
+static void
+extension_info_start (NautilusDirectory *directory,
+ NautilusFile *file)
+{
+ NautilusInfoProvider *provider;
+ NautilusOperationResult result;
+ NautilusOperationHandle *handle;
+ GClosure *update_complete;
+
+ if (directory->details->extension_info_in_progress != NULL) {
+ return;
+ }
+
+ if (!is_needy (file, lacks_extension_info, wants_extension_info)) {
+ return;
+ }
+
+ if (!async_job_start (directory, "extension info")) {
+ return;
+ }
+
+ provider = file->details->pending_info_providers->data;
+
+ update_complete = g_cclosure_new (G_CALLBACK (info_provider_callback),
+ directory,
+ NULL);
+ g_closure_set_marshal (update_complete,
+ nautilus_marshal_VOID__POINTER_ENUM);
+
+ result = nautilus_info_provider_update_file_info
+ (provider,
+ NAUTILUS_FILE_INFO (file),
+ update_complete,
+ &handle);
+
+ g_closure_unref (update_complete);
+
+ if (result == NAUTILUS_OPERATION_COMPLETE ||
+ result == NAUTILUS_OPERATION_FAILED) {
+ finish_info_provider (directory, file, provider);
+ async_job_end (directory, "extension info");
+ } else {
+ directory->details->extension_info_in_progress = handle;
+ directory->details->extension_info_provider = provider;
+ directory->details->extension_info_file = file;
+ }
+}
+
+static void
start_or_stop_io (NautilusDirectory *directory)
{
NautilusFile *file;
@@ -3150,6 +3322,7 @@ start_or_stop_io (NautilusDirectory *directory)
mime_list_stop (directory);
top_left_stop (directory);
link_info_stop (directory);
+ extension_info_stop (directory);
/* Take files that are all done off the queue. */
while (!nautilus_file_queue_is_empty (directory->details->high_priority_queue)) {
@@ -3177,6 +3350,20 @@ start_or_stop_io (NautilusDirectory *directory)
top_left_start (directory, file);
return;
} else {
+ move_file_to_extension_queue (directory, file);
+
+ }
+ }
+
+ /* Low priority queue must be empty */
+ while (!nautilus_file_queue_is_empty (directory->details->extension_queue)) {
+ file = nautilus_file_queue_head (directory->details->extension_queue);
+
+ if (file_needs_extension_work_done (directory, file)) {
+ /* Start getting attributes if possible */
+ extension_info_start (directory, file);
+ return;
+ } else {
nautilus_directory_remove_file_from_work_queue (directory, file);
}
@@ -3228,6 +3415,7 @@ nautilus_directory_cancel (NautilusDirectory *directory)
link_info_cancel (directory);
mime_list_cancel (directory);
top_left_cancel (directory);
+ extension_info_cancel (directory);
/* We aren't waiting for anything any more. */
if (waiting_directories != NULL) {
@@ -3322,6 +3510,10 @@ cancel_loading_attributes (NautilusDirectory *directory,
if (request.link_info) {
link_info_cancel (directory);
}
+
+ if (request.extension_info) {
+ extension_info_cancel (directory);
+ }
/* FIXME bugzilla.gnome.org 45064: implement cancelling metadata when we
implement invalidating metadata */
@@ -3407,11 +3599,23 @@ file_needs_low_priority_work_done (NautilusDirectory *directory,
}
static gboolean
+file_needs_extension_work_done (NautilusDirectory *directory,
+ NautilusFile *file)
+{
+ if (is_needy (file, lacks_extension_info, wants_extension_info)) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean
file_needs_work_done (NautilusDirectory *directory,
NautilusFile *file)
{
return (file_needs_high_priority_work_done (directory, file) ||
- file_needs_low_priority_work_done (directory, file));
+ file_needs_low_priority_work_done (directory, file) ||
+ file_needs_extension_work_done (directory, file));
}
@@ -3451,6 +3655,8 @@ nautilus_directory_remove_file_from_work_queue (NautilusDirectory *directory,
file);
nautilus_file_queue_remove (directory->details->low_priority_queue,
file);
+ nautilus_file_queue_remove (directory->details->extension_queue,
+ file);
}
@@ -3458,15 +3664,32 @@ static void
move_file_to_low_priority_queue (NautilusDirectory *directory,
NautilusFile *file)
{
+ /* Must add before removing to avoid ref underflow */
+ nautilus_file_queue_enqueue (directory->details->low_priority_queue,
+ file);
+ nautilus_file_queue_remove (directory->details->high_priority_queue,
+ file);
+
if (!file_needs_low_priority_work_done (directory, file)) {
- nautilus_file_queue_remove (directory->details->high_priority_queue,
+ move_file_to_extension_queue (directory, file);
+
+ return;
+ }
+}
+
+static void
+move_file_to_extension_queue (NautilusDirectory *directory,
+ NautilusFile *file)
+{
+ if (!file_needs_extension_work_done (directory, file)) {
+ nautilus_file_queue_remove (directory->details->low_priority_queue,
file);
return;
}
/* Must add before removing to avoid ref underflow */
- nautilus_file_queue_enqueue (directory->details->low_priority_queue,
+ nautilus_file_queue_enqueue (directory->details->extension_queue,
file);
- nautilus_file_queue_remove (directory->details->high_priority_queue,
+ nautilus_file_queue_remove (directory->details->low_priority_queue,
file);
}
diff --git a/libnautilus-private/nautilus-directory-private.h b/libnautilus-private/nautilus-directory-private.h
index fc4cd5d72..9dc3bae98 100644
--- a/libnautilus-private/nautilus-directory-private.h
+++ b/libnautilus-private/nautilus-directory-private.h
@@ -33,6 +33,7 @@
#include <libnautilus-private/nautilus-metafile-server.h>
#include <libnautilus-private/nautilus-monitor.h>
#include <libnautilus/nautilus-idle-queue.h>
+#include <libnautilus-extension/nautilus-info-provider.h>
#include <libxml/tree.h>
typedef struct LinkInfoReadState LinkInfoReadState;
@@ -53,6 +54,7 @@ struct NautilusDirectoryDetails
/* Queues of files needing some I/O done. */
NautilusFileQueue *high_priority_queue;
NautilusFileQueue *low_priority_queue;
+ NautilusFileQueue *extension_queue;
/* These lists are going to be pretty short. If we think they
* are going to get big, we can use hash tables instead.
@@ -100,6 +102,10 @@ struct NautilusDirectoryDetails
NautilusFile *get_info_file;
GnomeVFSAsyncHandle *get_info_in_progress;
+ NautilusFile *extension_info_file;
+ NautilusInfoProvider *extension_info_provider;
+ NautilusOperationHandle *extension_info_in_progress;
+
TopLeftTextReadState *top_left_read_state;
LinkInfoReadState *link_info_read_state;
@@ -119,6 +125,7 @@ typedef struct {
gboolean metafile;
gboolean mime_list;
gboolean top_left_text;
+ gboolean extension_info;
} Request;
NautilusDirectory *nautilus_directory_get_existing (const char *uri);
diff --git a/libnautilus-private/nautilus-directory.c b/libnautilus-private/nautilus-directory.c
index 0ee12c3ac..9a8e5913f 100644
--- a/libnautilus-private/nautilus-directory.c
+++ b/libnautilus-private/nautilus-directory.c
@@ -135,6 +135,7 @@ nautilus_directory_init (gpointer object, gpointer klass)
directory->details->file_hash = g_hash_table_new (g_str_hash, g_str_equal);
directory->details->high_priority_queue = nautilus_file_queue_new ();
directory->details->low_priority_queue = nautilus_file_queue_new ();
+ directory->details->extension_queue = nautilus_file_queue_new ();
directory->details->idle_queue = nautilus_idle_queue_new ();
directory->details->hidden_file_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
@@ -209,6 +210,7 @@ nautilus_directory_finalize (GObject *object)
nautilus_file_queue_destroy (directory->details->high_priority_queue);
nautilus_file_queue_destroy (directory->details->low_priority_queue);
+ nautilus_file_queue_destroy (directory->details->extension_queue);
nautilus_idle_queue_destroy (directory->details->idle_queue);
g_assert (directory->details->directory_load_in_progress == NULL);
g_assert (directory->details->count_in_progress == NULL);
@@ -1023,6 +1025,7 @@ nautilus_directory_notify_files_changed (GList *uris)
file->details->file_info_is_up_to_date = FALSE;
file->details->top_left_text_is_up_to_date = FALSE;
file->details->link_info_is_up_to_date = FALSE;
+ nautilus_file_invalidate_extension_info_internal (file);
hash_table_list_prepend (changed_lists,
file->details->directory,
diff --git a/libnautilus-private/nautilus-file-attributes.h b/libnautilus-private/nautilus-file-attributes.h
index 38e1da94f..ba02bd426 100644
--- a/libnautilus-private/nautilus-file-attributes.h
+++ b/libnautilus-private/nautilus-file-attributes.h
@@ -43,6 +43,7 @@ typedef enum {
NAUTILUS_FILE_ATTRIBUTE_TOP_LEFT_TEXT = 1 << 10,
NAUTILUS_FILE_ATTRIBUTE_DISPLAY_NAME = 1 << 11,
NAUTILUS_FILE_ATTRIBUTE_VOLUMES = 1 << 12,
+ NAUTILUS_FILE_ATTRIBUTE_EXTENSION_INFO = 1 << 13,
} NautilusFileAttributes;
#endif /* NAUTILUS_FILE_ATTRIBUTES_H */
diff --git a/libnautilus-private/nautilus-file-private.h b/libnautilus-private/nautilus-file-private.h
index 36f94e5e6..9f3b1da37 100644
--- a/libnautilus-private/nautilus-file-private.h
+++ b/libnautilus-private/nautilus-file-private.h
@@ -93,7 +93,18 @@ struct NautilusFileDetails
/* We use this to cache automatic emblems and emblem keywords
to speed up compare_by_emblems. */
NautilusFileSortByEmblemCache *compare_by_emblem_cache;
-
+
+ /* NautilusInfoProviders that need to be run for this file */
+ GList *pending_info_providers;
+
+ /* Emblems provided by extensions */
+ GList *extension_emblems;
+ GList *pending_extension_emblems;
+
+ /* Attributes provided by extensions */
+ GHashTable *extension_attributes;
+ GHashTable *pending_extension_attributes;
+
/* boolean fields: bitfield to save space, since there can be
many NautilusFile objects. */
@@ -173,13 +184,15 @@ gboolean nautilus_file_should_get_top_left_text (NautilusFile
/* Mark specified attributes for this file out of date without canceling current
* I/O or kicking off new I/O.
*/
-void nautilus_file_invalidate_attributes_internal (NautilusFile *file,
- NautilusFileAttributes file_attributes);
-NautilusFileAttributes nautilus_file_get_all_attributes (void);
-gboolean nautilus_file_is_self_owned (NautilusFile *file);
-void nautilus_file_invalidate_count_and_mime_list (NautilusFile *file);
-gboolean nautilus_file_rename_in_progress (NautilusFile *file);
-GnomeVFSFileInfo * nautilus_file_peek_vfs_file_info (NautilusFile *file);
+void nautilus_file_invalidate_attributes_internal (NautilusFile *file,
+ NautilusFileAttributes file_attributes);
+NautilusFileAttributes nautilus_file_get_all_attributes (void);
+gboolean nautilus_file_is_self_owned (NautilusFile *file);
+void nautilus_file_invalidate_count_and_mime_list (NautilusFile *file);
+gboolean nautilus_file_rename_in_progress (NautilusFile *file);
+GnomeVFSFileInfo * nautilus_file_peek_vfs_file_info (NautilusFile *file);
+void nautilus_file_invalidate_extension_info_internal (NautilusFile *file);
+void nautilus_file_info_providers_done (NautilusFile *file);
/* Thumbnailing: */
diff --git a/libnautilus-private/nautilus-file.c b/libnautilus-private/nautilus-file.c
index dc6141723..1ea79d4c0 100644
--- a/libnautilus-private/nautilus-file.c
+++ b/libnautilus-private/nautilus-file.c
@@ -39,6 +39,7 @@
#include "nautilus-link.h"
#include "nautilus-link-desktop-file.h"
#include "nautilus-metadata.h"
+#include "nautilus-module.h"
#include "nautilus-thumbnails.h"
#include "nautilus-trash-directory.h"
#include "nautilus-trash-file.h"
@@ -59,6 +60,7 @@
#include <libgnomevfs/gnome-vfs-volume.h>
#include <libgnomevfs/gnome-vfs-volume-monitor.h>
#include <libgnomevfs/gnome-vfs-drive.h>
+#include <libnautilus-extension/nautilus-file-info.h>
#include <libxml/parser.h>
#include <pwd.h>
#include <stdlib.h>
@@ -110,24 +112,62 @@ enum {
static guint signals[LAST_SIGNAL];
-static GHashTable *symbolic_links;
-
-static char * nautilus_file_get_owner_as_string (NautilusFile *file,
- gboolean include_real_name);
-static char * nautilus_file_get_type_as_string (NautilusFile *file);
-static gboolean update_info_and_name (NautilusFile *file,
- GnomeVFSFileInfo *info);
-static char * nautilus_file_get_display_name_nocopy (NautilusFile *file);
-static char * nautilus_file_get_display_name_collation_key (NautilusFile *file);
+static GObjectClass *parent_class = NULL;
+static GHashTable *symbolic_links;
-GNOME_CLASS_BOILERPLATE (NautilusFile, nautilus_file,
- GObject, G_TYPE_OBJECT)
+static void nautilus_file_instance_init (NautilusFile *file);
+static void nautilus_file_class_init (NautilusFileClass *class);
+static void nautilus_file_info_iface_init (NautilusFileInfoIface *iface);
+static char * nautilus_file_get_owner_as_string (NautilusFile *file,
+ gboolean include_real_name);
+static char * nautilus_file_get_type_as_string (NautilusFile *file);
+static gboolean update_info_and_name (NautilusFile *file,
+ GnomeVFSFileInfo *info);
+static char * nautilus_file_get_display_name_nocopy (NautilusFile *file);
+static char * nautilus_file_get_display_name_collation_key (NautilusFile *file);
+
+GType
+nautilus_file_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type) {
+ static const GTypeInfo info = {
+ sizeof (NautilusFileClass),
+ NULL,
+ NULL,
+ (GClassInitFunc) nautilus_file_class_init,
+ NULL,
+ NULL,
+ sizeof (NautilusFile),
+ 0,
+ (GInstanceInitFunc) nautilus_file_instance_init,
+ };
+
+ static const GInterfaceInfo file_info_iface_info = {
+ (GInterfaceInitFunc) nautilus_file_info_iface_init,
+ NULL,
+ NULL
+ };
+
+ type = g_type_register_static (G_TYPE_OBJECT,
+ "NautilusFile",
+ &info, 0);
+ g_type_add_interface_static (type,
+ NAUTILUS_TYPE_FILE_INFO,
+ &file_info_iface_info);
+ }
+
+ return type;
+}
static void
nautilus_file_instance_init (NautilusFile *file)
{
file->details = G_TYPE_INSTANCE_GET_PRIVATE ((file), NAUTILUS_TYPE_FILE, NautilusFileDetails);
+
+ nautilus_file_invalidate_extension_info_internal (file);
}
static NautilusFile *
@@ -459,10 +499,20 @@ finalize (GObject *object)
eel_g_list_free_deep (file->details->mime_list);
+ eel_g_list_free_deep (file->details->pending_extension_emblems);
+ eel_g_list_free_deep (file->details->extension_emblems);
+
+ if (file->details->pending_extension_attributes) {
+ g_hash_table_destroy (file->details->pending_extension_attributes);
+ }
+
+ if (file->details->extension_attributes) {
+ g_hash_table_destroy (file->details->extension_attributes);
+ }
+
G_OBJECT_CLASS (parent_class)->finalize (object);
}
-
NautilusFile *
nautilus_file_ref (NautilusFile *file)
{
@@ -2040,16 +2090,27 @@ compare_by_full_path (NautilusFile *file_1, NautilusFile *file_2)
static int
nautilus_file_compare_for_sort_internal (NautilusFile *file_1,
NautilusFile *file_2,
- NautilusFileSortType sort_type)
+ gboolean directories_first)
{
int compare;
GnomeVFSDrive *drive1, *drive2;
GnomeVFSVolume *volume1, *volume2;
- if (file_1 == file_2) {
- return 0;
+ gboolean is_directory_1, is_directory_2;
+
+ if (directories_first) {
+ is_directory_1 = nautilus_file_is_directory (file_1);
+ is_directory_2 = nautilus_file_is_directory (file_2);
+
+ if (is_directory_1 && !is_directory_2) {
+ return -1;
+ }
+
+ if (is_directory_2 && !is_directory_1) {
+ return +1;
+ }
}
-
+
/* Always sort drives/volumes separately: */
if (file_1->details->has_drive != file_2->details->has_drive) {
if (file_1->details->has_drive) {
@@ -2082,53 +2143,8 @@ nautilus_file_compare_for_sort_internal (NautilusFile *file_1,
return compare;
}
}
-
- switch (sort_type) {
- case NAUTILUS_FILE_SORT_BY_DISPLAY_NAME:
- compare = compare_by_display_name (file_1, file_2);
- if (compare != 0) {
- return compare;
- }
- return compare_by_directory_name (file_1, file_2);
- case NAUTILUS_FILE_SORT_BY_DIRECTORY:
- return compare_by_full_path (file_1, file_2);
- case NAUTILUS_FILE_SORT_BY_SIZE:
- /* Compare directory sizes ourselves, then if necessary
- * use GnomeVFS to compare file sizes.
- */
- compare = compare_by_size (file_1, file_2);
- if (compare != 0) {
- return compare;
- }
- return compare_by_full_path (file_1, file_2);
- case NAUTILUS_FILE_SORT_BY_TYPE:
- /* GnomeVFS doesn't know about our special text for certain
- * mime types, so we handle the mime-type sorting ourselves.
- */
- compare = compare_by_type (file_1, file_2);
- if (compare != 0) {
- return compare;
- }
- return compare_by_full_path (file_1, file_2);
- case NAUTILUS_FILE_SORT_BY_MTIME:
- compare = compare_by_modification_time (file_1, file_2);
- if (compare != 0) {
- return compare;
- }
- return compare_by_full_path (file_1, file_2);
- case NAUTILUS_FILE_SORT_BY_EMBLEMS:
- /* GnomeVFS doesn't know squat about our emblems, so
- * we handle comparing them here, before falling back
- * to tie-breakers.
- */
- compare = compare_by_emblems (file_1, file_2);
- if (compare != 0) {
- return compare;
- }
- return compare_by_full_path (file_1, file_2);
- default:
- g_return_val_if_reached (0);
- }
+
+ return 0;
}
/**
@@ -2154,27 +2170,135 @@ nautilus_file_compare_for_sort (NautilusFile *file_1,
gboolean reversed)
{
int result;
- gboolean is_directory_1, is_directory_2;
- if (directories_first) {
- is_directory_1 = nautilus_file_is_directory (file_1);
- is_directory_2 = nautilus_file_is_directory (file_2);
-
- if (is_directory_1 && !is_directory_2) {
- return -1;
+ if (file_1 == file_2) {
+ return 0;
+ }
+
+ result = nautilus_file_compare_for_sort_internal (file_1, file_2, directories_first);
+
+ if (result == 0) {
+ switch (sort_type) {
+ case NAUTILUS_FILE_SORT_BY_DISPLAY_NAME:
+ result = compare_by_display_name (file_1, file_2);
+ if (result == 0) {
+ result = compare_by_directory_name (file_1, file_2);
+ }
+ break;
+ case NAUTILUS_FILE_SORT_BY_DIRECTORY:
+ result = compare_by_full_path (file_1, file_2);
+ break;
+ case NAUTILUS_FILE_SORT_BY_SIZE:
+ /* Compare directory sizes ourselves, then if necessary
+ * use GnomeVFS to compare file sizes.
+ */
+ result = compare_by_size (file_1, file_2);
+ if (result == 0) {
+ result = compare_by_full_path (file_1, file_2);
+ }
+ break;
+ case NAUTILUS_FILE_SORT_BY_TYPE:
+ /* GnomeVFS doesn't know about our special text for certain
+ * mime types, so we handle the mime-type sorting ourselves.
+ */
+ result = compare_by_type (file_1, file_2);
+ if (result == 0) {
+ result = compare_by_full_path (file_1, file_2);
+ }
+ break;
+ case NAUTILUS_FILE_SORT_BY_MTIME:
+ result = compare_by_modification_time (file_1, file_2);
+ if (result == 0) {
+ result = compare_by_full_path (file_1, file_2);
+ }
+ break;
+ case NAUTILUS_FILE_SORT_BY_EMBLEMS:
+ /* GnomeVFS doesn't know squat about our emblems, so
+ * we handle comparing them here, before falling back
+ * to tie-breakers.
+ */
+ result = compare_by_emblems (file_1, file_2);
+ if (result == 0) {
+ result = compare_by_full_path (file_1, file_2);
+ }
+ default:
+ g_return_val_if_reached (0);
}
+ }
- if (is_directory_2 && !is_directory_1) {
- return +1;
- }
+ if (reversed) {
+ result = -result;
}
- result = nautilus_file_compare_for_sort_internal (file_1, file_2, sort_type);
+ return result;
+}
+
+int
+nautilus_file_compare_for_sort_by_attribute (NautilusFile *file_1,
+ NautilusFile *file_2,
+ const char *attribute,
+ gboolean directories_first,
+ gboolean reversed)
+{
+ int result;
+
+ if (file_1 == file_2) {
+ return 0;
+ }
+
+ /* Convert certain attributes into NautilusFileSortTypes and use
+ * nautilus_file_compare_for_sort()
+ */
+ if (attribute == NULL || !strcmp (attribute, "name")) {
+ return nautilus_file_compare_for_sort (file_1, file_2,
+ NAUTILUS_FILE_SORT_BY_DISPLAY_NAME,
+ directories_first,
+ reversed);
+ } else if (!strcmp (attribute, "size")) {
+ return nautilus_file_compare_for_sort (file_1, file_2,
+ NAUTILUS_FILE_SORT_BY_SIZE,
+ directories_first,
+ reversed);
+ } else if (!strcmp (attribute, "type")) {
+ return nautilus_file_compare_for_sort (file_1, file_2,
+ NAUTILUS_FILE_SORT_BY_TYPE,
+ directories_first,
+ reversed);
+ } else if (!strcmp (attribute, "modification_date") || !strcmp (attribute, "date_modified")) {
+ return nautilus_file_compare_for_sort (file_1, file_2,
+ NAUTILUS_FILE_SORT_BY_MTIME,
+ directories_first,
+ reversed);
+ } else if (!strcmp (attribute, "emblems")) {
+ return nautilus_file_compare_for_sort (file_1, file_2,
+ NAUTILUS_FILE_SORT_BY_EMBLEMS,
+ directories_first,
+ reversed);
+ }
+
+ /* it is a normal attribute, compare by strings */
+
+ result = nautilus_file_compare_for_sort_internal (file_1, file_2, directories_first);
+
+ if (result == 0) {
+ char *value_1;
+ char *value_2;
+
+ value_1 = nautilus_file_get_string_attribute (file_1,
+ attribute);
+ value_2 = nautilus_file_get_string_attribute (file_2,
+ attribute);
+
+ result = strcmp (value_1, value_2);
+
+ g_free (value_1);
+ g_free (value_2);
+ }
if (reversed) {
result = -result;
}
-
+
return result;
}
@@ -4318,6 +4442,8 @@ nautilus_file_get_deep_directory_count_as_string (NautilusFile *file)
char *
nautilus_file_get_string_attribute (NautilusFile *file, const char *attribute_name)
{
+ char *extension_attribute;
+
/* FIXME bugzilla.gnome.org 40646:
* Use hash table and switch statement or function pointers for speed?
*/
@@ -4389,7 +4515,18 @@ nautilus_file_get_string_attribute (NautilusFile *file, const char *attribute_na
if (strcmp (attribute_name, "free_space") == 0) {
return nautilus_file_get_volume_free_space (file);
}
- return NULL;
+
+ extension_attribute = NULL;
+
+ if (file->details->pending_extension_attributes) {
+ extension_attribute = g_hash_table_lookup (file->details->pending_extension_attributes, attribute_name);
+ }
+
+ if (extension_attribute == NULL && file->details->extension_attributes) {
+ extension_attribute = g_hash_table_lookup (file->details->extension_attributes, attribute_name);
+ }
+
+ return g_strdup (extension_attribute);
}
/**
@@ -4689,7 +4826,10 @@ nautilus_file_get_keywords (NautilusFile *file)
/* Put all the keywords into a list. */
keywords = nautilus_file_get_metadata_list
(file, "keyword", "name");
-
+
+ keywords = g_list_concat (keywords, eel_g_str_list_copy (file->details->extension_emblems));
+ keywords = g_list_concat (keywords, eel_g_str_list_copy (file->details->pending_extension_emblems));
+
return sort_keyword_list_and_remove_duplicates (keywords);
}
@@ -5274,7 +5414,6 @@ invalidate_directory_count (NautilusFile *file)
file->details->directory_count_is_up_to_date = FALSE;
}
-
static void
invalidate_deep_counts (NautilusFile *file)
{
@@ -5306,6 +5445,19 @@ invalidate_link_info (NautilusFile *file)
}
void
+nautilus_file_invalidate_extension_info_internal (NautilusFile *file)
+{
+ file->details->pending_info_providers =
+ nautilus_module_get_extensions_for_type (NAUTILUS_TYPE_INFO_PROVIDER);
+ if (!file->details->pending_extension_attributes) {
+ file->details->pending_extension_attributes =
+ g_hash_table_new_full (g_str_hash, g_str_equal,
+ (GDestroyNotify)g_free,
+ (GDestroyNotify)g_free);
+ }
+}
+
+void
nautilus_file_invalidate_attributes_internal (NautilusFile *file,
NautilusFileAttributes file_attributes)
{
@@ -5343,6 +5495,9 @@ nautilus_file_invalidate_attributes_internal (NautilusFile *file,
if (request.link_info) {
invalidate_link_info (file);
}
+ if (request.extension_info) {
+ nautilus_file_invalidate_extension_info_internal (file);
+ }
/* FIXME bugzilla.gnome.org 45075: implement invalidating metadata */
}
@@ -5633,6 +5788,8 @@ nautilus_extract_top_left_text (const char *text,
static void
nautilus_file_class_init (NautilusFileClass *class)
{
+ parent_class = g_type_class_peek_parent (class);
+
G_OBJECT_CLASS (class)->finalize = finalize;
signals[CHANGED] =
@@ -5656,6 +5813,79 @@ nautilus_file_class_init (NautilusFileClass *class)
g_type_class_add_private (class, sizeof (NautilusFileDetails));
}
+static GnomeVFSFileInfo *
+nautilus_file_get_vfs_file_info (NautilusFile *file)
+{
+ return gnome_vfs_file_info_dup (file->details->info);
+}
+
+static void
+nautilus_file_add_emblem (NautilusFile *file,
+ const char *emblem_name)
+{
+ if (file->details->pending_info_providers) {
+ file->details->pending_extension_emblems = g_list_prepend (file->details->pending_extension_emblems,
+ g_strdup (emblem_name));
+ } else {
+ file->details->extension_emblems = g_list_prepend (file->details->extension_emblems,
+ g_strdup (emblem_name));
+ }
+
+ nautilus_file_changed (file);
+}
+
+static void
+nautilus_file_add_string_attribute (NautilusFile *file,
+ const char *attribute_name,
+ const char *value)
+{
+ if (file->details->pending_info_providers) {
+ g_hash_table_insert (file->details->pending_extension_attributes,
+ g_strdup (attribute_name),
+ g_strdup (value));
+ } else {
+ g_hash_table_insert (file->details->extension_attributes,
+ g_strdup (attribute_name),
+ g_strdup (value));
+ }
+
+ nautilus_file_changed (file);
+}
+
+void
+nautilus_file_info_providers_done (NautilusFile *file)
+{
+ eel_g_list_free_deep (file->details->extension_emblems);
+ file->details->extension_emblems = file->details->pending_extension_emblems;
+ file->details->pending_extension_emblems = NULL;
+
+ if (file->details->extension_attributes) {
+ g_hash_table_destroy (file->details->extension_attributes);
+ }
+
+ file->details->extension_attributes = file->details->pending_extension_attributes;
+ file->details->pending_extension_attributes = NULL;
+
+ nautilus_file_changed (file);
+}
+
+static void
+nautilus_file_info_iface_init (NautilusFileInfoIface *iface)
+{
+ iface->is_gone = nautilus_file_is_gone;
+ iface->get_name = nautilus_file_get_name;
+ iface->get_uri = nautilus_file_get_uri;
+ iface->get_parent_uri = nautilus_file_get_parent_uri;
+ iface->get_uri_scheme = nautilus_file_get_uri_scheme;
+ iface->get_mime_type = nautilus_file_get_mime_type;
+ iface->is_mime_type = nautilus_file_is_mime_type;
+ iface->is_directory = nautilus_file_is_directory;
+ iface->get_vfs_file_info = nautilus_file_get_vfs_file_info;
+ iface->add_emblem = nautilus_file_add_emblem;
+ iface->get_string_attribute = nautilus_file_get_string_attribute;
+ iface->add_string_attribute = nautilus_file_add_string_attribute;
+}
+
#if !defined (NAUTILUS_OMIT_SELF_CHECK)
void
diff --git a/libnautilus-private/nautilus-file.h b/libnautilus-private/nautilus-file.h
index 22971972e..c945fd391 100644
--- a/libnautilus-private/nautilus-file.h
+++ b/libnautilus-private/nautilus-file.h
@@ -286,6 +286,11 @@ int nautilus_file_compare_for_sort (Nautilu
NautilusFileSortType sort_type,
gboolean directories_first,
gboolean reversed);
+int nautilus_file_compare_for_sort_by_attribute (NautilusFile *file_1,
+ NautilusFile *file_2,
+ const char *attribute,
+ gboolean directories_first,
+ gboolean reversed);
int nautilus_file_compare_display_name (NautilusFile *file_1,
const char *pattern);
diff --git a/libnautilus-private/nautilus-global-preferences.c b/libnautilus-private/nautilus-global-preferences.c
index 29fb25dc4..1342ce774 100644
--- a/libnautilus-private/nautilus-global-preferences.c
+++ b/libnautilus-private/nautilus-global-preferences.c
@@ -213,21 +213,6 @@ static EelEnumerationEntry standard_font_size_entries[] = {
{ NULL }
};
-static EelEnumerationEntry icon_captions_enum_entries[] = {
- { "size", N_("size"), 0 },
- { "type", N_("type"), 1 },
- { "date_modified", N_("date modified"), 2 },
- { "date_changed", N_("date changed"), 3 },
- { "date_accessed", N_("date accessed"), 4 },
- { "owner", N_("owner"), 5 },
- { "group", N_("group"), 6 },
- { "permissions", N_("permissions"), 7 },
- { "octal_permissions", N_("octal permissions"), 8 },
- { "mime_type", N_("MIME type"), 9 },
- { "none", N_("none"), 10 },
- { NULL }
-};
-
/* These enumerations are used in the preferences dialog to
* populate widgets and route preferences changes between the
* storage (GConf) and the displayed values.
@@ -240,7 +225,6 @@ static EelEnumerationInfo enumerations[] = {
{ "default_zoom_level", default_zoom_level_enum_entries },
{ "executable_text_activation", executable_text_activation_enum_entries },
{ "file_size", file_size_enum_entries },
- { "icon_captions", icon_captions_enum_entries },
{ "search_bar_type", search_bar_type_enum_entries },
{ "speed_tradeoff", speed_tradeoff_enum_entries },
{ "standard_font_size", standard_font_size_entries },
diff --git a/libnautilus-private/nautilus-global-preferences.h b/libnautilus-private/nautilus-global-preferences.h
index 176f01ce3..754b1d4f5 100644
--- a/libnautilus-private/nautilus-global-preferences.h
+++ b/libnautilus-private/nautilus-global-preferences.h
@@ -123,6 +123,8 @@ enum
#define NAUTILUS_PREFERENCES_LIST_VIEW_DEFAULT_SORT_IN_REVERSE_ORDER "list_view/default_sort_in_reverse_order"
#define NAUTILUS_PREFERENCES_LIST_VIEW_DEFAULT_SORT_ORDER "list_view/default_sort_order"
#define NAUTILUS_PREFERENCES_LIST_VIEW_DEFAULT_ZOOM_LEVEL "list_view/default_zoom_level"
+#define NAUTILUS_PREFERENCES_LIST_VIEW_DEFAULT_VISIBLE_COLUMNS "list_view/default_visible_columns"
+#define NAUTILUS_PREFERENCES_LIST_VIEW_DEFAULT_COLUMN_ORDER "list_view/default_column_order"
/* News panel */
#define NAUTILUS_PREFERENCES_NEWS_MAX_ITEMS "news/max_items"
diff --git a/libnautilus-private/nautilus-marshal.list b/libnautilus-private/nautilus-marshal.list
index c0d617827..3261b785f 100644
--- a/libnautilus-private/nautilus-marshal.list
+++ b/libnautilus-private/nautilus-marshal.list
@@ -13,3 +13,4 @@ VOID:POINTER,STRING
VOID:STRING,STRING
VOID:POINTER,POINTER,POINTER,INT,INT,INT
VOID:POINTER,STRING,UINT,INT,INT
+VOID:POINTER,ENUM
diff --git a/libnautilus-private/nautilus-metadata.h b/libnautilus-private/nautilus-metadata.h
index 06a4014a7..710d82c0f 100644
--- a/libnautilus-private/nautilus-metadata.h
+++ b/libnautilus-private/nautilus-metadata.h
@@ -58,6 +58,9 @@
#define NAUTILUS_METADATA_KEY_LIST_VIEW_ZOOM_LEVEL "list_view_zoom_level"
#define NAUTILUS_METADATA_KEY_LIST_VIEW_SORT_COLUMN "list_view_sort_column"
#define NAUTILUS_METADATA_KEY_LIST_VIEW_SORT_REVERSED "list_view_sort_reversed"
+#define NAUTILUS_METADATA_KEY_LIST_VIEW_VISIBLE_COLUMNS "list_view_visible_columns"
+#define NAUTILUS_METADATA_KEY_LIST_VIEW_COLUMN_ORDER "list_view_column_order"
+#define NAUTILUS_METADATA_SUBKEY_COLUMNS "columns"
#define NAUTILUS_METADATA_KEY_WINDOW_GEOMETRY "window_geometry"
#define NAUTILUS_METADATA_KEY_WINDOW_SCROLL_POSITION "window_scroll_position"
diff --git a/libnautilus-private/nautilus-module.c b/libnautilus-private/nautilus-module.c
new file mode 100644
index 000000000..0edd200c2
--- /dev/null
+++ b/libnautilus-private/nautilus-module.c
@@ -0,0 +1,258 @@
+/*
+ * nautilus-module.h - Interface to nautilus extensions
+ *
+ * Copyright (C) 2003 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Author: Dave Camp <dave@ximian.com>
+ *
+ */
+
+#include <config.h>
+#include "nautilus-module.h"
+
+#include <eel/eel-gtk-macros.h>
+#include <gmodule.h>
+#include <libgnome/gnome-macros.h>
+
+#define NAUTILUS_TYPE_MODULE (nautilus_module_get_type ())
+#define NAUTILUS_MODULE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NAUTILUS_TYPE_MODULE, NautilusModule))
+#define NAUTILUS_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_MODULE, NautilusModule))
+#define NAUTILUS_IS_MODULE(obj) (G_TYPE_INSTANCE_CHECK_TYPE ((obj), NAUTILUS_TYPE_MODULE))
+#define NAUTILUS_IS_MODULE_CLASS(klass) (G_TYPE_CLASS_CHECK_CLASS_TYPE ((klass), NAUTILUS_TYPE_MODULE))
+
+typedef struct _NautilusModule NautilusModule;
+typedef struct _NautilusModuleClass NautilusModuleClass;
+
+struct _NautilusModule {
+ GTypeModule parent;
+
+ GModule *library;
+
+ char *path;
+
+ void (*initialize) (GTypeModule *module);
+ void (*shutdown) (void);
+
+ void (*list_types) (const GType **types,
+ int *num_types);
+
+};
+
+struct _NautilusModuleClass {
+ GTypeModuleClass parent;
+};
+
+static GType nautilus_module_get_type (void);
+
+static GList *module_objects = NULL;
+
+GNOME_CLASS_BOILERPLATE (NautilusModule,
+ nautilus_module,
+ GTypeModule,
+ G_TYPE_TYPE_MODULE);
+
+static gboolean
+nautilus_module_load (GTypeModule *gmodule)
+{
+ NautilusModule *module;
+
+ module = NAUTILUS_MODULE (gmodule);
+
+ module->library = g_module_open (module->path, 0);
+
+ if (!module->library) {
+ g_warning (g_module_error ());
+ return FALSE;
+ }
+
+ if (!g_module_symbol (module->library,
+ "nautilus_module_initialize",
+ (gpointer *)&module->initialize) ||
+ !g_module_symbol (module->library,
+ "nautilus_module_shutdown",
+ (gpointer *)&module->shutdown) ||
+ !g_module_symbol (module->library,
+ "nautilus_module_list_types",
+ (gpointer *)&module->list_types)) {
+
+ g_warning (g_module_error ());
+ g_module_close (module->library);
+
+ return FALSE;
+ }
+
+ module->initialize (gmodule);
+
+ return TRUE;
+}
+
+static void
+nautilus_module_unload (GTypeModule *gmodule)
+{
+ NautilusModule *module;
+
+ module = NAUTILUS_MODULE (gmodule);
+
+ module->shutdown ();
+
+ g_module_close (module->library);
+
+ module->initialize = NULL;
+ module->shutdown = NULL;
+ module->list_types = NULL;
+}
+
+static void
+nautilus_module_finalize (GObject *object)
+{
+ NautilusModule *module;
+
+ module = NAUTILUS_MODULE (object);
+
+ g_free (module->path);
+
+ EEL_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
+}
+
+static void
+nautilus_module_instance_init (NautilusModule *module)
+{
+}
+
+static void
+nautilus_module_class_init (NautilusModuleClass *class)
+{
+ G_OBJECT_CLASS (class)->finalize = nautilus_module_finalize;
+ G_TYPE_MODULE_CLASS (class)->load = nautilus_module_load;
+ G_TYPE_MODULE_CLASS (class)->unload = nautilus_module_unload;
+}
+
+static void
+module_object_weak_notify (gpointer user_data, GObject *object)
+{
+ module_objects = g_list_remove (module_objects, object);
+}
+
+static void
+add_module_objects (NautilusModule *module)
+{
+ const GType *types;
+ int num_types;
+ int i;
+
+ module->list_types (&types, &num_types);
+
+ for (i = 0; i < num_types; i++) {
+ nautilus_module_add_type (types[i]);
+ }
+}
+
+static NautilusModule *
+nautilus_module_load_file (const char *filename)
+{
+ NautilusModule *module;
+
+ module = g_object_new (NAUTILUS_TYPE_MODULE, NULL);
+ module->path = g_strdup (filename);
+
+ if (g_type_module_use (G_TYPE_MODULE (module))) {
+ add_module_objects (module);
+ g_type_module_unuse (G_TYPE_MODULE (module));
+ return module;
+ } else {
+ g_object_unref (module);
+ return NULL;
+ }
+}
+
+static void
+load_module_dir (const char *dirname)
+{
+ GDir *dir;
+
+ dir = g_dir_open (dirname, 0, NULL);
+
+ if (dir) {
+ const char *name;
+
+ while ((name = g_dir_read_name (dir))) {
+ if (g_str_has_suffix (name, "." G_MODULE_SUFFIX)) {
+ char *filename;
+
+ filename = g_build_filename (dirname,
+ name,
+ NULL);
+ nautilus_module_load_file (filename);
+ }
+ }
+
+ g_dir_close (dir);
+ }
+}
+
+void
+nautilus_module_init (void)
+{
+ static gboolean initialized = FALSE;
+
+ if (!initialized) {
+ initialized = TRUE;
+
+ load_module_dir (NAUTILUS_EXTENSIONDIR);
+ }
+}
+
+GList *
+nautilus_module_get_extensions_for_type (GType type)
+{
+ GList *l;
+ GList *ret = NULL;
+
+ for (l = module_objects; l != NULL; l = l->next) {
+ if (G_TYPE_CHECK_INSTANCE_TYPE (G_OBJECT (l->data),
+ type)) {
+ g_object_ref (l->data);
+ ret = g_list_prepend (ret, l->data);
+ }
+ }
+
+ return ret;
+}
+
+void
+nautilus_module_extension_list_free (GList *extensions)
+{
+ GList *l;
+
+ for (l = extensions; l != NULL; l = l->next) {
+ g_object_unref (l->data);
+ }
+ g_list_free (extensions);
+}
+
+void
+nautilus_module_add_type (GType type)
+{
+ GObject *object;
+
+ object = g_object_new (type, NULL);
+ g_object_weak_ref (object,
+ (GWeakNotify)module_object_weak_notify,
+ NULL);
+
+ module_objects = g_list_prepend (module_objects, object);
+}
diff --git a/libnautilus-private/nautilus-module.h b/libnautilus-private/nautilus-module.h
new file mode 100644
index 000000000..8c26b73e1
--- /dev/null
+++ b/libnautilus-private/nautilus-module.h
@@ -0,0 +1,42 @@
+/*
+ * nautilus-module.h - Interface to nautilus extensions
+ *
+ * Copyright (C) 2003 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Author: Dave Camp <dave@ximian.com>
+ *
+ */
+
+#ifndef NAUTILUS_MODULE_H
+#define NAUTILUS_MODULE_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+void nautilus_module_init (void);
+GList *nautilus_module_get_extensions_for_type (GType type);
+void nautilus_module_extension_list_free (GList *list);
+
+
+/* Add a type to the module interface - allows nautilus to add its own modules
+ * without putting them in separate shared libraries */
+void nautilus_module_add_type (GType type);
+
+G_END_DECLS
+
+#endif
diff --git a/src/file-manager/Makefile.am b/src/file-manager/Makefile.am
index 614dcaa03..a45a4ad5b 100644
--- a/src/file-manager/Makefile.am
+++ b/src/file-manager/Makefile.am
@@ -15,6 +15,7 @@ INCLUDES = \
libnautilus_file_manager_la_SOURCES= \
+ fm-bonobo-provider.c \
fm-desktop-icon-view.c \
fm-directory-view.c \
fm-error-reporting.c \
@@ -27,6 +28,7 @@ libnautilus_file_manager_la_SOURCES= \
nautilus-indexing-info.c \
fm-tree-model.c \
fm-tree-view.c \
+ fm-bonobo-provider.h \
fm-desktop-icon-view.h \
fm-directory-view.h \
fm-error-reporting.h \
diff --git a/src/file-manager/fm-bonobo-provider.c b/src/file-manager/fm-bonobo-provider.c
new file mode 100644
index 000000000..fcc985f71
--- /dev/null
+++ b/src/file-manager/fm-bonobo-provider.c
@@ -0,0 +1,629 @@
+/*
+ * fm-bonobo-provider.h - Bonobo API support
+ *
+ * Copyright (C) 2002 James Willcox
+ * 2003 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Authors: James Willcox <james@gnome.org>
+ * Dave Camp <dave@ximian.com>
+ *
+ */
+
+/* This object exports the bonobo context menus and property pages
+ * using the new extension interface. */
+
+#include <config.h>
+#include "fm-bonobo-provider.h"
+
+#include <string.h>
+
+#include <bonobo/bonobo-control.h>
+#include <bonobo/bonobo-exception.h>
+#include <bonobo/bonobo-property-bag-client.h>
+#include <bonobo/bonobo-ui-util.h>
+#include <bonobo/bonobo-widget.h>
+#include <bonobo/bonobo-window.h>
+#include <bonobo/bonobo-zoomable.h>
+#include <eel/eel-glib-extensions.h>
+#include <gtk/gtkhbox.h>
+#include <gtk/gtkimage.h>
+#include <gtk/gtklabel.h>
+#include <gtk/gtkmessagedialog.h>
+#include <gtk/gtkstock.h>
+#include <gtk/gtkvbox.h>
+#include <libgnome/gnome-i18n.h>
+#include <libgnomeui/gnome-uidefs.h>
+#include <libnautilus-extension/nautilus-extension-types.h>
+#include <libnautilus-extension/nautilus-file-info.h>
+#include <libnautilus-extension/nautilus-menu-provider.h>
+#include <libnautilus-extension/nautilus-property-page-provider.h>
+#include <libnautilus-private/nautilus-mime-actions.h>
+#include <libnautilus-private/nautilus-view-identifier.h>
+
+typedef struct {
+ char *id;
+ char *verb;
+ CORBA_sequence_CORBA_string *uri_list;
+} BonoboMimeActionData;
+
+
+typedef struct {
+ GList *files;
+ GtkWidget *vbox;
+ char *view_name;
+} ActivationData;
+
+static void fm_bonobo_provider_instance_init (FMBonoboProvider *provider);
+static void fm_bonobo_provider_class_init (FMBonoboProviderClass *class);
+
+static GObjectClass *parent_class;
+
+static BonoboMimeActionData *
+bonobo_mime_action_data_new (const char *id, const char *verb, GList *files)
+{
+ BonoboMimeActionData *data;
+ CORBA_sequence_CORBA_string *uri_list;
+ int i;
+
+ data = g_new (BonoboMimeActionData, 1);
+ data->id = g_strdup (id);
+ data->verb = g_strdup (verb);
+
+ /* convert the GList of files into a CORBA sequence */
+
+ uri_list = CORBA_sequence_CORBA_string__alloc ();
+ uri_list->_maximum = g_list_length (files);
+ uri_list->_length = uri_list->_maximum;
+ uri_list->_buffer = CORBA_sequence_CORBA_string_allocbuf (uri_list->_length);
+
+ for (i=0; files; files = files->next, i++)
+ {
+ NautilusFile *file;
+ char *uri;
+
+ file = files->data;
+ uri = nautilus_file_get_uri (file);
+
+ uri_list->_buffer[i] = CORBA_string_dup ((char*)uri);
+
+ g_free (uri);
+ }
+
+ CORBA_sequence_set_release (uri_list, CORBA_TRUE);
+ data->uri_list = uri_list;
+
+
+ return data;
+}
+
+static void
+bonobo_mime_action_data_free (BonoboMimeActionData *data)
+{
+ g_free (data->id);
+ g_free (data->verb);
+ g_free (data);
+}
+
+static void
+bonobo_mime_action_activate_callback (CORBA_Object obj,
+ const char *error_reason,
+ gpointer user_data)
+{
+ Bonobo_Listener listener;
+ CORBA_Environment ev;
+ BonoboMimeActionData *data;
+ CORBA_any any;
+
+ data = user_data;
+
+ if (obj == CORBA_OBJECT_NIL) {
+ GtkWidget *dialog;
+
+ /* FIXME: make an error message that is not so lame */
+ dialog = gtk_message_dialog_new (NULL, 0, GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_OK,
+ _("Could not complete specified action: %s"), error_reason);
+ g_signal_connect (dialog, "response",
+ G_CALLBACK (gtk_widget_destroy), NULL);
+ gtk_widget_show (dialog);
+ return;
+ }
+
+ CORBA_exception_init (&ev);
+
+ listener = Bonobo_Unknown_queryInterface (obj,
+ "IDL:Bonobo/Listener:1.0",
+ &ev);
+
+ if (!BONOBO_EX (&ev)) {
+ any._type = TC_CORBA_sequence_CORBA_string;
+ any._value = data->uri_list;
+ Bonobo_Listener_event (listener, data->verb, &any, &ev);
+ bonobo_object_release_unref (listener, &ev);
+ } else {
+ GtkWidget *dialog;
+
+ /* FIXME: make an error message that is not so lame */
+ dialog = gtk_message_dialog_new (NULL, 0, GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_OK,
+ _("Could not complete specified action."));
+ g_signal_connect (dialog, "response",
+ G_CALLBACK (gtk_widget_destroy), NULL);
+ gtk_widget_show (dialog);
+ }
+
+}
+
+static void
+bonobo_mime_action_callback (NautilusMenuItem *item,
+ gpointer callback_data)
+{
+ BonoboMimeActionData *data;
+
+ data = callback_data;
+
+ bonobo_activation_activate_from_id_async (data->id, 0,
+ bonobo_mime_action_activate_callback,
+ data, NULL);
+
+}
+
+static void
+bonobo_mime_action_menu_data_destroy_callback (gpointer data, GClosure *closure)
+{
+ bonobo_mime_action_data_free ((BonoboMimeActionData *)data);
+}
+
+static gboolean
+no_locale_at_end (const char *str)
+{
+ int len;
+
+ len = strlen (str);
+ if (len > 3 &&
+ str[len-3] == '-' &&
+ g_ascii_isalpha (str[len-2]) &&
+ g_ascii_isalpha (str[len-1])) {
+ return FALSE;
+ }
+ if (len > 6 &&
+ str[len-6] == '-' &&
+ g_ascii_isalpha (str[len-5]) &&
+ g_ascii_isalpha (str[len-4]) &&
+ str[len-3] == '_' &&
+ g_ascii_isalpha (str[len-2]) &&
+ g_ascii_isalpha (str[len-1])) {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static GList *
+get_bonobo_menu_verb_names (Bonobo_ServerInfo *info)
+{
+ GList *l;
+ unsigned int i;
+ int offset;
+
+ offset = strlen ("nautilusverb:");
+
+ l = NULL;
+ for (i = 0; i < info->props._length; i++) {
+
+ /* look for properties that start with "nautilusverb:". The
+ * part following the colon is the verb name
+ */
+ if (strstr (info->props._buffer[i].name, "nautilusverb:") &&
+ no_locale_at_end (info->props._buffer[i].name)) {
+ l = g_list_prepend (l,
+ g_strdup (&info->props._buffer[i].name[offset]));
+ }
+ }
+
+ return l;
+}
+
+static gboolean
+can_handle_multiple_files (Bonobo_ServerInfo *info)
+{
+ Bonobo_ActivationProperty *prop;
+
+ prop = bonobo_server_info_prop_find (info, "nautilus:can_handle_multiple_files");
+ return prop->v._u.value_boolean;
+}
+
+static GList *
+get_menu_items_for_server (Bonobo_ServerInfo *info,
+ GList *verb_names,
+ GList *files)
+{
+ GList *items;
+ GList *l;
+ const GList *langs;
+ GSList *langs_cpy;
+
+ langs = gnome_i18n_get_language_list ("LANG");
+ langs_cpy = NULL;
+ /* copy it to a singly linked list since bonobo wants that...sigh */
+ for (; langs; langs = langs->next) {
+ langs_cpy = g_slist_append (langs_cpy, langs->data);
+ }
+
+ items = NULL;
+
+ /* build the commands */
+ for (l = verb_names; l; l = l->next) {
+ NautilusMenuItem *item;
+ BonoboMimeActionData *data;
+ char *verb;
+ char *prop_name;
+ const char *label;
+ const char *icon_name;
+ GClosure *closure;
+
+ verb = l->data;
+
+ prop_name = g_strdup_printf ("nautilusverb:%s", verb);
+ label = bonobo_server_info_prop_lookup (info, prop_name,
+ langs_cpy);
+ g_free (prop_name);
+
+ prop_name = g_strdup_printf ("nautilusverbicon:%s", verb);
+ icon_name = bonobo_server_info_prop_lookup (info, prop_name,
+ langs_cpy);
+ g_free (prop_name);
+ if (!icon_name) {
+ icon_name = bonobo_server_info_prop_lookup (info, "nautilus:icon",
+ langs_cpy);
+ }
+
+ data = bonobo_mime_action_data_new (info->iid,
+ verb, files);
+ closure = g_cclosure_new
+ (G_CALLBACK (bonobo_mime_action_callback),
+ data,
+ bonobo_mime_action_menu_data_destroy_callback);
+
+ item = nautilus_menu_item_new (verb,
+ label,
+ "", /* no tip for bonobo items */
+ icon_name);
+ g_signal_connect_data (item, "activate",
+ G_CALLBACK (bonobo_mime_action_callback),
+ data,
+ bonobo_mime_action_menu_data_destroy_callback,
+ 0);
+ items = g_list_prepend (items, item);
+ }
+ items = g_list_reverse (items);
+
+ g_slist_free (langs_cpy);
+
+ /* if it doesn't handle multiple files, disable the menu items */
+ if ((g_list_length (files) > 1) &&
+ (can_handle_multiple_files (info) == FALSE)) {
+ GList *l;
+
+ for (l = items; l != NULL; l = l->next) {
+ g_object_set (l->data, "sensitive", FALSE, NULL);
+ }
+ }
+
+ return items;
+}
+
+static GList *
+fm_bonobo_provider_get_file_items (NautilusMenuProvider *provider,
+ GtkWidget *window,
+ GList *selection)
+{
+ GList *components;
+ GList *items;
+ GList *l;
+
+ components = nautilus_mime_get_popup_components_for_files (selection);
+
+ items = NULL;
+ for (l = components; l; l = l->next) {
+ Bonobo_ServerInfo *info;
+ GList *verb_names;
+
+ info = l->data;
+ verb_names = get_bonobo_menu_verb_names (info);
+ items = g_list_concat (items,
+ get_menu_items_for_server (info, verb_names, selection));
+ eel_g_list_free_deep (verb_names);
+
+ }
+
+ if (components != NULL) {
+ gnome_vfs_mime_component_list_free (components);
+ }
+
+ return items;
+}
+
+static void
+fm_bonobo_provider_menu_provider_iface_init (NautilusMenuProviderIface *iface)
+{
+ iface->get_file_items = fm_bonobo_provider_get_file_items;
+}
+
+static GtkWidget *
+bonobo_page_error_message (const char *view_name,
+ const char *msg)
+{
+ GtkWidget *hbox;
+ GtkWidget *label;
+ GtkWidget *image;
+
+ hbox = gtk_hbox_new (FALSE, GNOME_PAD);
+ image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_ERROR,
+ GTK_ICON_SIZE_DIALOG);
+
+ msg = g_strdup_printf ("There was an error while trying to create the view named `%s': %s", view_name, msg);
+ label = gtk_label_new (msg);
+
+ gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+
+ gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+ gtk_widget_show_all (hbox);
+
+ return hbox;
+}
+
+static CORBA_sequence_CORBA_string *
+get_uri_list (GList *file_list)
+{
+ CORBA_sequence_CORBA_string *uri_list;
+ GList *l;
+ int i;
+
+ uri_list = CORBA_sequence_CORBA_string__alloc ();
+ uri_list->_maximum = g_list_length (file_list);
+ uri_list->_length = uri_list->_maximum;
+ uri_list->_buffer = CORBA_sequence_CORBA_string_allocbuf (uri_list->_length);
+ for (i = 0, l = file_list; l != NULL; i++, l = l->next) {
+ char *uri;
+
+ uri = nautilus_file_get_uri (NAUTILUS_FILE (l->data));
+ uri_list->_buffer[i] = CORBA_string_dup (uri);
+ g_free (uri);
+ }
+
+ return uri_list;
+}
+
+static void
+bonobo_page_activate_callback (CORBA_Object obj,
+ const char *error_reason,
+ gpointer user_data)
+{
+ ActivationData *data;
+ GtkWidget *widget;
+ CORBA_Environment ev;
+
+ data = (ActivationData *)user_data;
+
+ CORBA_exception_init (&ev);
+ widget = NULL;
+
+ if (obj != CORBA_OBJECT_NIL) {
+ Bonobo_Control control;
+ Bonobo_PropertyBag pb;
+ GList *keys;
+
+ control = Bonobo_Unknown_queryInterface
+ (obj, "IDL:Bonobo/Control:1.0", &ev);
+
+ pb = Bonobo_Control_getProperties (control, &ev);
+
+ if (!BONOBO_EX (&ev)) {
+ gboolean new_property;
+
+ keys = bonobo_pbclient_get_keys (pb, NULL);
+ new_property = FALSE;
+ if (g_list_find_custom (keys, "uris", (GCompareFunc)strcmp)) {
+ new_property = TRUE;
+ }
+ bonobo_pbclient_free_keys (keys);
+
+ if (new_property) {
+ /* Set the 'uris' property. */
+ CORBA_sequence_CORBA_string *uri_list;
+ BonoboArg *arg;
+
+ uri_list = get_uri_list (data->files);
+ arg = bonobo_arg_new (TC_CORBA_sequence_CORBA_string);
+ arg->_value = uri_list;
+ bonobo_pbclient_set_value_async (pb, "uris", arg, &ev);
+ bonobo_arg_release (arg);
+ } else {
+ /* Set the 'URI' property. */
+ BonoboArg *arg;
+ char *uri;
+
+ if (data->files->next != NULL) {
+ g_warning ("Multifile property page does not support the 'uris' property");
+ bonobo_object_release_unref (pb, NULL);
+ bonobo_object_release_unref (control, NULL);
+ return;
+ }
+
+ uri = nautilus_file_info_get_uri (NAUTILUS_FILE_INFO (data->files->data));
+
+ arg = bonobo_arg_new (BONOBO_ARG_STRING);
+ BONOBO_ARG_SET_STRING (arg, uri);
+ bonobo_pbclient_set_value_async (pb, "URI", arg, &ev);
+ bonobo_arg_release (arg);
+ g_free (uri);
+ }
+
+ bonobo_object_release_unref (pb, NULL);
+
+ if (!BONOBO_EX (&ev)) {
+ widget = bonobo_widget_new_control_from_objref
+ (control, CORBA_OBJECT_NIL);
+ bonobo_object_release_unref (control, &ev);
+ }
+ }
+ }
+
+ if (widget == NULL) {
+ widget = bonobo_page_error_message (data->view_name,
+ error_reason);
+ }
+
+ gtk_container_add (GTK_CONTAINER (data->vbox), widget);
+ gtk_widget_show (widget);
+
+ g_free (data->view_name);
+ g_free (data);
+}
+
+static GList *
+fm_bonobo_provider_get_pages (NautilusPropertyPageProvider *provider,
+ GList *files)
+{
+ GList *all_components, *l;
+ GList *components;
+ CORBA_Environment ev;
+ GList *pages;
+
+ /* find all the property pages for this file */
+ all_components = nautilus_mime_get_property_components_for_files
+ (files);
+
+ /* filter out property pages that don't support multiple files */
+ if (files->next) {
+ components = NULL;
+ for (l = all_components; l != NULL; l = l->next) {
+ if (can_handle_multiple_files (l->data)) {
+ components = g_list_prepend (components,
+ l->data);
+ }
+ }
+ components = g_list_reverse (components);
+ g_list_free (all_components);
+ } else {
+ components = all_components;
+ }
+
+ CORBA_exception_init (&ev);
+
+ pages = NULL;
+
+ l = components;
+ while (l != NULL) {
+ NautilusViewIdentifier *view_id;
+ Bonobo_ServerInfo *server;
+ ActivationData *data;
+ GtkWidget *vbox;
+ NautilusPropertyPage *page;
+
+ server = l->data;
+ l = l->next;
+
+ view_id = nautilus_view_identifier_new_from_property_page (server);
+ vbox = gtk_vbox_new (FALSE, 0);
+ gtk_container_set_border_width (GTK_CONTAINER (vbox),
+ GNOME_PAD);
+ gtk_widget_show (vbox);
+
+ page = nautilus_property_page_new (view_id->iid,
+ gtk_label_new (view_id->name),
+ vbox);
+
+ pages = g_list_prepend (pages, page);
+
+ data = g_new (ActivationData, 1);
+ data->files = nautilus_file_info_list_copy (files);
+ data->vbox = vbox;
+ data->view_name = g_strdup (view_id->name);
+
+ bonobo_activation_activate_from_id_async
+ (view_id->iid,
+ 0, bonobo_page_activate_callback,
+ data, &ev);
+ }
+
+ return g_list_reverse (pages);
+}
+
+static void
+fm_bonobo_provider_property_page_provider_iface_init (NautilusPropertyPageProviderIface *iface)
+{
+ iface->get_pages = fm_bonobo_provider_get_pages;
+}
+
+static void
+fm_bonobo_provider_instance_init (FMBonoboProvider *provider)
+{
+}
+
+static void
+fm_bonobo_provider_class_init (FMBonoboProviderClass *class)
+{
+ parent_class = g_type_class_peek_parent (class);
+}
+
+GType
+fm_bonobo_provider_get_type (void)
+{
+ static GType provider_type = 0;
+
+ if (!provider_type) {
+ static const GTypeInfo type_info = {
+ sizeof (FMBonoboProviderClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) fm_bonobo_provider_class_init,
+ NULL,
+ NULL,
+ sizeof (FMBonoboProvider),
+ 0,
+ (GInstanceInitFunc) fm_bonobo_provider_instance_init,
+ };
+
+ static const GInterfaceInfo menu_provider_iface_info = {
+ (GInterfaceInitFunc) fm_bonobo_provider_menu_provider_iface_init,
+ NULL,
+ NULL
+ };
+
+ static const GInterfaceInfo property_page_provider_iface_info = {
+ (GInterfaceInitFunc) fm_bonobo_provider_property_page_provider_iface_init,
+ NULL,
+ NULL
+ };
+
+ provider_type = g_type_register_static (G_TYPE_OBJECT,
+ "FMBonoboProvider",
+ &type_info, 0);
+
+ g_type_add_interface_static (provider_type,
+ NAUTILUS_TYPE_MENU_PROVIDER,
+ &menu_provider_iface_info);
+ g_type_add_interface_static (provider_type,
+ NAUTILUS_TYPE_PROPERTY_PAGE_PROVIDER,
+ &property_page_provider_iface_info);
+ }
+
+ return provider_type;
+}
+
diff --git a/src/file-manager/fm-bonobo-provider.h b/src/file-manager/fm-bonobo-provider.h
new file mode 100644
index 000000000..10d7be1c0
--- /dev/null
+++ b/src/file-manager/fm-bonobo-provider.h
@@ -0,0 +1,51 @@
+/*
+ * fm-bonobo-provider.h - Bonobo API support
+ *
+ * Copyright (C) 2002 James Willcox
+ * 2003 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Authors: Dave Camp <dave@ximian.com>
+ * James Willcox <james@gnome.org>
+ *
+ */
+
+#ifndef FM_BONOBO_PROVIDER_H
+#define FM_BONOBO_PROVIDER_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define FM_TYPE_BONOBO_PROVIDER (fm_bonobo_provider_get_type ())
+#define FM_BONOBO_PROVIDER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), FM_TYPE_BONOBO_PROVIDER, FMBonoboProvider))
+#define FM_IS_BONOBO_PROVIDER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), FM_TYPE_BONOBO_PROVIDER))
+typedef struct _FMBonoboProvider FMBonoboProvider;
+typedef struct _FMBonoboProviderClass FMBonoboProviderClass;
+
+struct _FMBonoboProvider {
+ GObject parent_slot;
+};
+
+struct _FMBonoboProviderClass {
+ GObjectClass parent_slot;
+};
+
+GType fm_bonobo_provider_get_type (void);
+
+G_END_DECLS
+
+#endif
diff --git a/src/file-manager/fm-directory-view.c b/src/file-manager/fm-directory-view.c
index 4de21aff9..336a8fad7 100644
--- a/src/file-manager/fm-directory-view.c
+++ b/src/file-manager/fm-directory-view.c
@@ -69,6 +69,7 @@
#include <libgnomevfs/gnome-vfs-utils.h>
#include <libnautilus-private/nautilus-recent.h>
#include <libegg/egg-screen-exec.h>
+#include <libnautilus-extension/nautilus-menu-provider.h>
#include <libnautilus-private/nautilus-bonobo-extensions.h>
#include <libnautilus-private/nautilus-desktop-icon-file.h>
#include <libnautilus-private/nautilus-desktop-directory.h>
@@ -83,6 +84,7 @@
#include <libnautilus-private/nautilus-link.h>
#include <libnautilus-private/nautilus-metadata.h>
#include <libnautilus-private/nautilus-mime-actions.h>
+#include <libnautilus-private/nautilus-module.h>
#include <libnautilus-private/nautilus-program-choosing.h>
#include <libnautilus-private/nautilus-trash-directory.h>
#include <libnautilus-private/nautilus-trash-monitor.h>
@@ -157,7 +159,8 @@
#define FM_DIRECTORY_VIEW_MENU_PATH_NEW_DOCUMENTS_SEPARATOR "/menu/File/New Items Placeholder/New Documents/After New Documents"
#define FM_DIRECTORY_VIEW_MENU_PATH_CUT_FILES "/menu/Edit/Cut"
#define FM_DIRECTORY_VIEW_MENU_PATH_COPY_FILES "/menu/Edit/Copy"
-#define FM_DIRECTORY_VIEW_MENU_PATH_PASTE_FILES "/menu/File/Paste"
+#define FM_DIRECTORY_VIEW_MENU_PATH_PASTE_FILES "/menu/Edit/Paste"
+#define FM_DIRECTORY_VIEW_MENU_PATH_EXTENSION_ACTIONS_PLACEHOLDER "/menu/Edit/Extension Actions"
#define FM_DIRECTORY_VIEW_POPUP_PATH_BACKGROUND "/popups/background"
#define FM_DIRECTORY_VIEW_POPUP_PATH_SELECTION "/popups/selection"
@@ -177,7 +180,7 @@
#define FM_DIRECTORY_VIEW_POPUP_PATH_SCRIPTS_SEPARATOR "/popups/selection/Open Placeholder/Scripts/After Scripts"
#define FM_DIRECTORY_VIEW_POPUP_PATH_OPEN_WITH "/popups/selection/Open Placeholder/Open With"
#define FM_DIRECTORY_VIEW_POPUP_PATH_SCRIPTS "/popups/selection/Open Placeholder/Scripts"
-#define FM_DIRECTORY_VIEW_POPUP_PATH_MIME_ACTIONS "/popups/selection/Mime Actions"
+#define FM_DIRECTORY_VIEW_POPUP_PATH_EXTENSION_ACTIONS "/popups/selection/Extension Actions"
#define MAX_MENU_LEVELS 5
@@ -286,12 +289,6 @@ typedef struct {
gboolean cancelled;
} ActivateParameters;
-typedef struct {
- char *id;
- char *verb;
- CORBA_sequence_CORBA_string *uri_list;
-} BonoboMimeActionData;
-
enum {
GNOME_COPIED_FILES
};
@@ -3846,308 +3843,27 @@ reset_bonobo_open_with_menu (FMDirectoryView *view, GList *selection)
sensitive);
}
-static BonoboMimeActionData *
-bonobo_mime_action_data_new (const char *id, const char *verb, GList *files)
-{
- BonoboMimeActionData *data;
- CORBA_sequence_CORBA_string *uri_list;
- int i;
-
- data = g_new (BonoboMimeActionData, 1);
- data->id = g_strdup (id);
- data->verb = g_strdup (verb);
-
-
- /* convert the GList of files into a CORBA sequence */
-
- uri_list = CORBA_sequence_CORBA_string__alloc ();
- uri_list->_maximum = g_list_length (files);
- uri_list->_length = uri_list->_maximum;
- uri_list->_buffer = CORBA_sequence_CORBA_string_allocbuf (uri_list->_length);
-
- for (i=0; files; files = files->next, i++)
- {
- NautilusFile *file;
- char *uri;
-
- file = files->data;
- uri = nautilus_file_get_uri (file);
-
- uri_list->_buffer[i] = CORBA_string_dup ((char*)uri);
-
- g_free (uri);
- }
-
- CORBA_sequence_set_release (uri_list, CORBA_TRUE);
- data->uri_list = uri_list;
-
-
- return data;
-}
-
static void
-bonobo_mime_action_data_free (BonoboMimeActionData *data)
-{
- g_free (data->id);
- g_free (data->verb);
- g_free (data);
-}
-
-
-static void
-bonobo_mime_action_activate_callback (CORBA_Object obj,
- const char *error_reason,
- gpointer user_data)
-{
- Bonobo_Listener listener;
- CORBA_Environment ev;
- BonoboMimeActionData *data;
- CORBA_any any;
-
- data = user_data;
-
- if (obj == CORBA_OBJECT_NIL) {
- GtkWidget *dialog;
-
- /* FIXME: make an error message that is not so lame */
- dialog = gtk_message_dialog_new (NULL, 0, GTK_MESSAGE_ERROR,
- GTK_BUTTONS_OK,
- _("Could not complete specified action: %s"), error_reason);
- g_signal_connect (dialog, "response",
- G_CALLBACK (gtk_widget_destroy), NULL);
- gtk_widget_show (dialog);
- return;
- }
-
- CORBA_exception_init (&ev);
-
- listener = Bonobo_Unknown_queryInterface (obj,
- "IDL:Bonobo/Listener:1.0",
- &ev);
-
- if (!BONOBO_EX (&ev)) {
- any._type = TC_CORBA_sequence_CORBA_string;
- any._value = data->uri_list;
- Bonobo_Listener_event (listener, data->verb, &any, &ev);
- bonobo_object_release_unref (listener, &ev);
- } else {
- GtkWidget *dialog;
-
- /* FIXME: make an error message that is not so lame */
- dialog = gtk_message_dialog_new (NULL, 0, GTK_MESSAGE_ERROR,
- GTK_BUTTONS_OK,
- _("Could not complete specified action."));
- g_signal_connect (dialog, "response",
- G_CALLBACK (gtk_widget_destroy), NULL);
- gtk_widget_show (dialog);
- }
-
-}
-
-
-static void
-bonobo_mime_action_callback (BonoboUIComponent *component,
- gpointer callback_data, const char *path)
-{
- BonoboMimeActionData *data;
-
- data = callback_data;
-
- bonobo_activation_activate_from_id_async (data->id, 0,
- bonobo_mime_action_activate_callback,
- data, NULL);
-
-}
-
-static void
-bonobo_mime_action_menu_data_destroy_callback (gpointer data, GClosure *closure)
-{
- bonobo_mime_action_data_free ((BonoboMimeActionData *)data);
-}
-
-static gboolean
-can_handle_multiple_files (Bonobo_ServerInfo *info)
-{
- Bonobo_ActivationProperty *prop;
-
- prop = bonobo_server_info_prop_find (info, "nautilus:can_handle_multiple_files");
- return prop->v._u.value_boolean;
-}
-
-static void
-add_bonobo_menu_ui_and_verbs (FMDirectoryView *view, GList *files,
- Bonobo_ServerInfo *info, GList *verb_names)
+add_extension_menu_items (FMDirectoryView *view,
+ GList *files,
+ GList *menu_items)
{
GList *l;
- GString *ui_xml;
- const GList *langs;
- GSList *langs_cpy;
- char *ui_xml_str;
-
- g_return_if_fail (verb_names != NULL);
-
- langs = gnome_i18n_get_language_list ("LANG");
- langs_cpy = NULL;
- /* copy it to a singly linked list since bonobo wants that...sigh */
- for (; langs; langs = langs->next) {
- langs_cpy = g_slist_append (langs_cpy, langs->data);
- }
-
- ui_xml = g_string_new ("<Root><commands>");
-
- /* build the commands */
- for (l = verb_names; l; l = l->next) {
- const char *label;
- char *prop_name;
- char *verb;
-
- verb = l->data;
-
- prop_name = g_strdup_printf ("nautilusverb:%s", verb);
- label = bonobo_server_info_prop_lookup (info, prop_name,
- langs_cpy);
- g_free (prop_name);
-
- g_string_append_printf (ui_xml, "<cmd name=\"%s\" label=\"%s\"/>", verb, label);
- }
-
- ui_xml = g_string_append (ui_xml, "</commands><popups><popup name=\"selection\"><placeholder name=\"Mime Actions\"><separator/>");
-
- /* build the UI */
- for (l = verb_names; l; l = l->next) {
- char *verb = l->data;
- char *icon_attribute_name;
- const char *icon_name;
- char *pixbuf_data;
- GdkPixbuf *pixbuf;
-
- g_string_append_printf (ui_xml,
- "<menuitem name=\"%s\" verb=\"%s\"",
- verb, verb);
-
- icon_attribute_name = g_strdup_printf ("nautilusverbicon:%s",
- verb);
- icon_name = bonobo_server_info_prop_lookup (info,
- icon_attribute_name,
- langs_cpy);
- g_free (icon_attribute_name);
- if (!icon_name) {
- icon_name = bonobo_server_info_prop_lookup (info, "nautilus:icon",
- langs_cpy);
- }
-
- if (icon_name) {
- pixbuf = nautilus_icon_factory_get_pixbuf_from_name
- (icon_name,
- NULL,
- NAUTILUS_ICON_SIZE_FOR_MENUS,
- NULL);
- if (pixbuf) {
- pixbuf_data = bonobo_ui_util_pixbuf_to_xml (pixbuf);
- g_string_append_printf (ui_xml, " pixtype=\"pixbuf\" pixname=\"%s\"", pixbuf_data);
- g_free (pixbuf_data);
- g_object_unref (pixbuf);
- }
- }
- g_string_append (ui_xml, "/>");
- }
-
- g_slist_free (langs_cpy);
-
- ui_xml = g_string_append (ui_xml, "</placeholder></popup></popups></Root>");
- ui_xml_str = g_string_free (ui_xml, FALSE);
-
- bonobo_ui_component_set (view->details->ui, "/",
- ui_xml_str, NULL);
- g_free (ui_xml_str);
-
- /* if it doesn't handle multiple files, disable the menu items */
- if ((g_list_length (files) > 1) &&
- (can_handle_multiple_files (info) == FALSE)) {
-
- for (; verb_names; verb_names = verb_names->next) {
- char *path = g_strdup_printf ("/commands/%s",
- (char *)verb_names->data);
- bonobo_ui_component_set_prop (view->details->ui,
- path,
- "sensitive",
- "0", NULL);
- g_free (path);
- }
-
- /* no reason to continue */
- return;
- }
-
- /* add the verbs */
- for (l = verb_names; l; l = l->next) {
- const char *verb;
- BonoboMimeActionData *data;
- GClosure *closure;
-
- verb = l->data;
+ for (l = menu_items; l; l = l->next) {
+ NautilusMenuItem *item;
- data = bonobo_mime_action_data_new (info->iid,
- verb, files);
- closure = g_cclosure_new
- (G_CALLBACK (bonobo_mime_action_callback),
- data,
- bonobo_mime_action_menu_data_destroy_callback);
- bonobo_ui_component_add_verb_full
- (view->details->ui,
- data->verb,
- closure);
- }
-
-}
-
-static gboolean
-no_locale_at_end (const char *str)
-{
- int len;
-
- len = strlen (str);
- if (len > 3 &&
- str[len-3] == '-' &&
- g_ascii_isalpha (str[len-2]) &&
- g_ascii_isalpha (str[len-1])) {
- return FALSE;
- }
- if (len > 6 &&
- str[len-6] == '-' &&
- g_ascii_isalpha (str[len-5]) &&
- g_ascii_isalpha (str[len-4]) &&
- str[len-3] == '_' &&
- g_ascii_isalpha (str[len-2]) &&
- g_ascii_isalpha (str[len-1])) {
- return FALSE;
- }
- return TRUE;
-}
-
-static GList *
-get_bonobo_menu_verb_names (Bonobo_ServerInfo *info)
-{
- GList *l;
- unsigned int i;
- int offset;
-
- offset = strlen ("nautilusverb:");
-
- l = NULL;
- for (i = 0; i < info->props._length; i++) {
-
- /* look for properties that start with "nautilusverb:". The
- * part following the colon is the verb name
- */
- if (strstr (info->props._buffer[i].name, "nautilusverb:") &&
- no_locale_at_end (info->props._buffer[i].name)) {
- l = g_list_prepend (l,
- g_strdup (&info->props._buffer[i].name[offset]));
- }
+ item = NAUTILUS_MENU_ITEM (l->data);
+
+ nautilus_bonobo_add_extension_item_command (view->details->ui,
+ item);
+
+ nautilus_bonobo_add_extension_item (view->details->ui,
+ FM_DIRECTORY_VIEW_POPUP_PATH_EXTENSION_ACTIONS,
+ item);
+ nautilus_bonobo_add_extension_item (view->details->ui,
+ FM_DIRECTORY_VIEW_MENU_PATH_EXTENSION_ACTIONS_PLACEHOLDER,
+ item);
}
-
- return l;
}
static gboolean
@@ -4191,46 +3907,62 @@ get_unique_files (GList *selection)
return g_list_reverse (result);
}
-static void
-reset_bonobo_mime_actions_menu (FMDirectoryView *view, GList *selection)
+static GList *
+get_all_extension_menu_items (GtkWidget *window,
+ GList *selection)
{
- gboolean sensitive;
- GList *components, *l, *unique_selection;
-
- /* Clear any previous inserted items in the mime actions placeholder */
- nautilus_bonobo_remove_menu_items_and_commands
- (view->details->ui, FM_DIRECTORY_VIEW_POPUP_PATH_MIME_ACTIONS);
+ GList *items;
+ GList *providers;
+ GList *l;
+
+ providers = nautilus_module_get_extensions_for_type (NAUTILUS_TYPE_MENU_PROVIDER);
+ items = NULL;
- sensitive = TRUE;
+ for (l = providers; l != NULL; l = l->next) {
+ NautilusMenuProvider *provider;
+ GList *file_items;
- /* only query for the unique files so we can reduce oaf traffic */
- unique_selection = get_unique_files (selection);
+ provider = NAUTILUS_MENU_PROVIDER (l->data);
+ file_items = nautilus_menu_provider_get_file_items (provider,
+ window,
+ selection);
+ items = g_list_concat (items, file_items);
+ }
- components = nautilus_mime_get_popup_components_for_files (unique_selection);
- g_list_free (unique_selection);
+ nautilus_module_extension_list_free (providers);
- for (l = components; l; l = l->next) {
- Bonobo_ServerInfo *info;
- GList *verb_names;
+ return items;
+}
- info = l->data;
- verb_names = get_bonobo_menu_verb_names (info);
-
- add_bonobo_menu_ui_and_verbs (view, selection, info,
- verb_names);
- eel_g_list_free_deep (verb_names);
-
- }
+static void
+reset_extension_actions_menu (FMDirectoryView *view, GList *selection)
+{
+ GList *unique_selection;
+ GList *items;
+ GList *l;
- if (components != NULL) {
- gnome_vfs_mime_component_list_free (components);
- } else {
- sensitive = FALSE;
+ /* Clear any previous inserted items in the extension actions placeholder */
+ nautilus_bonobo_remove_menu_items_and_commands
+ (view->details->ui, FM_DIRECTORY_VIEW_POPUP_PATH_EXTENSION_ACTIONS);
+ nautilus_bonobo_remove_menu_items_and_commands
+ (view->details->ui, FM_DIRECTORY_VIEW_MENU_PATH_EXTENSION_ACTIONS_PLACEHOLDER);
+
+ /* only query for the unique files */
+ unique_selection = get_unique_files (selection);
+ items = get_all_extension_menu_items (gtk_widget_get_toplevel (GTK_WIDGET (view)),
+ selection);
+
+ if (items) {
+ add_extension_menu_items (view, unique_selection, items);
+
+ for (l = items; l != NULL; l = l->next) {
+ g_object_unref (l->data);
+ }
+
+ g_list_free (items);
}
- nautilus_bonobo_set_sensitive (view->details->ui,
- FM_DIRECTORY_VIEW_POPUP_PATH_MIME_ACTIONS,
- sensitive);
+ g_list_free (unique_selection);
}
static char *
@@ -5593,7 +5325,7 @@ real_update_menus (FMDirectoryView *view)
/* Broken into its own function just for convenience */
reset_bonobo_open_with_menu (view, selection);
- reset_bonobo_mime_actions_menu (view, selection);
+ reset_extension_actions_menu (view, selection);
if (all_selected_items_in_trash (view)) {
label = _("_Delete from Trash");
@@ -6459,7 +6191,8 @@ finish_loading (FMDirectoryView *view)
attributes |= NAUTILUS_FILE_ATTRIBUTE_DIRECTORY_ITEM_COUNT |
NAUTILUS_FILE_ATTRIBUTE_METADATA |
NAUTILUS_FILE_ATTRIBUTE_MIME_TYPE |
- NAUTILUS_FILE_ATTRIBUTE_DISPLAY_NAME;
+ NAUTILUS_FILE_ATTRIBUTE_DISPLAY_NAME |
+ NAUTILUS_FILE_ATTRIBUTE_EXTENSION_INFO;
nautilus_directory_file_monitor_add (view->details->model,
&view->details->model,
diff --git a/src/file-manager/fm-list-model.c b/src/file-manager/fm-list-model.c
index 77d959c0f..89be75f06 100644
--- a/src/file-manager/fm-list-model.c
+++ b/src/file-manager/fm-list-model.c
@@ -4,6 +4,7 @@
Copyright (C) 2001, 2002 Anders Carlsson
Copyright (C) 2003, Soeren Sandmann
+ Copyright (C) 2004, Novell, Inc.
The Gnome Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
@@ -20,7 +21,7 @@
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
- Authors: Anders Carlsson <andersca@gnu.org>, Soeren Sandmann (sandmann@daimi.au.dk)
+ Authors: Anders Carlsson <andersca@gnu.org>, Soeren Sandmann (sandmann@daimi.au.dk), Dave Camp <dave@ximian.com>
*/
#include <config.h>
@@ -48,7 +49,7 @@ struct FMListModelDetails {
int stamp;
- int sort_column_id;
+ char *sort_attribute;
GtkSortType order;
gboolean sort_directories_first;
@@ -56,6 +57,8 @@ struct FMListModelDetails {
GtkTreeView *drag_view;
int drag_begin_x;
int drag_begin_y;
+
+ GPtrArray *columns;
};
typedef struct {
@@ -64,11 +67,6 @@ typedef struct {
GList *path_list;
} DragDataGetInfo;
-typedef struct {
- const char *attribute_name;
- int sort_column_id;
-} AttributeEntry;
-
static GtkTargetEntry drag_types [] = {
{ NAUTILUS_ICON_DND_GNOME_ICON_LIST_TYPE, 0, NAUTILUS_ICON_DND_GNOME_ICON_LIST },
{ NAUTILUS_ICON_DND_URI_LIST_TYPE, 0, NAUTILUS_ICON_DND_URI_LIST },
@@ -76,24 +74,6 @@ static GtkTargetEntry drag_types [] = {
{ NAUTILUS_ICON_DND_TEXT_TYPE, 0, NAUTILUS_ICON_DND_TEXT }
};
-/*
- * Do not change the order of the type and size attributes, they
- * have to be in this order so that the column_id to attribute mapping
- * works. This is needed to store the sorting preferences. This duplicate
- * entry is here to allow the ordering by icon (i think...)
- */
-
-static const AttributeEntry attributes[] = {
- { "name", FM_LIST_MODEL_NAME_COLUMN },
- { "type", FM_LIST_MODEL_TYPE_COLUMN },
-#ifdef GNOME2_CONVERSION_COMPLETE
- { "emblems", FM_LIST_MODEL_EMBLEMS_COLUMN },
-#endif
- { "size", FM_LIST_MODEL_SIZE_COLUMN },
- { "icon", FM_LIST_MODEL_TYPE_COLUMN },
- { "date_modified", FM_LIST_MODEL_DATE_MODIFIED_COLUMN },
-};
-
static GtkTargetList *drag_target_list = NULL;
static guint
@@ -105,7 +85,7 @@ fm_list_model_get_flags (GtkTreeModel *tree_model)
static int
fm_list_model_get_n_columns (GtkTreeModel *tree_model)
{
- return FM_LIST_MODEL_NUM_COLUMNS;
+ return FM_LIST_MODEL_NUM_COLUMNS + FM_LIST_MODEL (tree_model)->details->columns->len;
}
static GType
@@ -114,11 +94,6 @@ fm_list_model_get_column_type (GtkTreeModel *tree_model, int index)
switch (index) {
case FM_LIST_MODEL_FILE_COLUMN:
return NAUTILUS_TYPE_FILE;
- case FM_LIST_MODEL_NAME_COLUMN:
- case FM_LIST_MODEL_SIZE_COLUMN:
- case FM_LIST_MODEL_TYPE_COLUMN:
- case FM_LIST_MODEL_DATE_MODIFIED_COLUMN:
- return G_TYPE_STRING;
case FM_LIST_MODEL_SMALLEST_ICON_COLUMN:
case FM_LIST_MODEL_SMALLER_ICON_COLUMN:
case FM_LIST_MODEL_SMALL_ICON_COLUMN:
@@ -137,7 +112,11 @@ fm_list_model_get_column_type (GtkTreeModel *tree_model, int index)
case FM_LIST_MODEL_FILE_NAME_IS_EDITABLE_COLUMN:
return G_TYPE_BOOLEAN;
default:
- return G_TYPE_INVALID;
+ if (index < FM_LIST_MODEL_NUM_COLUMNS + FM_LIST_MODEL (tree_model)->details->columns->len) {
+ return G_TYPE_STRING;
+ } else {
+ return G_TYPE_INVALID;
+ }
}
}
@@ -215,12 +194,6 @@ fm_list_model_get_value (GtkTreeModel *tree_model, GtkTreeIter *iter, int column
g_value_set_object (value, file);
break;
- case FM_LIST_MODEL_NAME_COLUMN:
- g_value_init (value, G_TYPE_STRING);
-
- str = nautilus_file_get_string_attribute_with_default (file, "name");
- g_value_set_string_take_ownership (value, str);
- break;
case FM_LIST_MODEL_SMALLEST_ICON_COLUMN:
case FM_LIST_MODEL_SMALLER_ICON_COLUMN:
case FM_LIST_MODEL_SMALL_ICON_COLUMN:
@@ -308,31 +281,28 @@ fm_list_model_get_value (GtkTreeModel *tree_model, GtkTreeIter *iter, int column
g_object_unref (icon);
}
break;
- case FM_LIST_MODEL_SIZE_COLUMN:
- g_value_init (value, G_TYPE_STRING);
-
- str = nautilus_file_get_string_attribute_with_default (file, "size");
- g_value_set_string_take_ownership (value, str);
- break;
- case FM_LIST_MODEL_TYPE_COLUMN:
- g_value_init (value, G_TYPE_STRING);
-
- str = nautilus_file_get_string_attribute_with_default (file, "type");
- g_value_set_string_take_ownership (value, str);
- break;
- case FM_LIST_MODEL_DATE_MODIFIED_COLUMN:
- g_value_init (value, G_TYPE_STRING);
-
- str = nautilus_file_get_string_attribute_with_default (file, "date_modified");
- g_value_set_string_take_ownership (value, str);
- break;
case FM_LIST_MODEL_FILE_NAME_IS_EDITABLE_COLUMN:
g_value_init (value, G_TYPE_BOOLEAN);
-
- g_value_set_boolean (value, nautilus_file_can_rename (file));
- break;
- default:
- g_assert_not_reached ();
+
+ g_value_set_boolean (value, nautilus_file_can_rename (file));
+ break;
+ default:
+ if (column < FM_LIST_MODEL_NUM_COLUMNS + model->details->columns->len) {
+ NautilusColumn *nautilus_column;
+ char *attribute;
+ nautilus_column = model->details->columns->pdata[column - FM_LIST_MODEL_NUM_COLUMNS];
+
+ g_value_init (value, G_TYPE_STRING);
+ g_object_get (nautilus_column,
+ "attribute", &attribute,
+ NULL);
+ str = nautilus_file_get_string_attribute_with_default (file,
+ attribute);
+ g_value_set_string_take_ownership (value, str);
+ g_free (attribute);
+ } else {
+ g_assert_not_reached ();
+ }
}
}
@@ -460,10 +430,10 @@ fm_list_model_compare_func (gconstpointer a,
file1 = (NautilusFile *)a;
file2 = (NautilusFile *)b;
- result = nautilus_file_compare_for_sort (file1, file2,
- fm_list_model_get_sort_type_from_sort_column_id (model->details->sort_column_id),
- model->details->sort_directories_first,
- (model->details->order == GTK_SORT_DESCENDING));
+ result = nautilus_file_compare_for_sort_by_attribute (file1, file2,
+ model->details->sort_attribute,
+ model->details->sort_directories_first,
+ (model->details->order == GTK_SORT_DESCENDING));
return result;
}
@@ -514,21 +484,26 @@ fm_list_model_sort (FMListModel *model)
g_free (new_order);
}
+
static gboolean
fm_list_model_get_sort_column_id (GtkTreeSortable *sortable,
gint *sort_column_id,
GtkSortType *order)
{
FMListModel *model;
-
+ int id;
+
model = (FMListModel *)sortable;
-
- if (model->details->sort_column_id == -1) {
+
+ id = fm_list_model_get_sort_column_id_from_attribute
+ (model, model->details->sort_attribute);
+
+ if (id == -1) {
return FALSE;
}
-
+
if (sort_column_id != NULL) {
- *sort_column_id = model->details->sort_column_id;
+ *sort_column_id = id;
}
if (order != NULL) {
@@ -545,19 +520,15 @@ fm_list_model_set_sort_column_id (GtkTreeSortable *sortable, gint sort_column_id
model = (FMListModel *)sortable;
- if ((model->details->sort_column_id == sort_column_id) &&
- (model->details->order == order)) {
- return;
- }
+ g_free (model->details->sort_attribute);
+ model->details->sort_attribute = fm_list_model_get_attribute_from_sort_column_id (model, sort_column_id);
- model->details->sort_column_id = sort_column_id;
model->details->order = order;
fm_list_model_sort (model);
gtk_tree_sortable_sort_column_changed (sortable);
}
-
static gboolean
fm_list_model_has_default_sort_func (GtkTreeSortable *sortable)
{
@@ -802,7 +773,8 @@ fm_list_model_set_should_sort_directories_first (FMListModel *model, gboolean so
}
int
-fm_list_model_get_sort_column_id_from_attribute (const char *attribute)
+fm_list_model_get_sort_column_id_from_attribute (FMListModel *model,
+ const char *attribute)
{
guint i;
@@ -810,67 +782,51 @@ fm_list_model_get_sort_column_id_from_attribute (const char *attribute)
return -1;
}
- for (i = 0; i < G_N_ELEMENTS (attributes); i++) {
- if (strcmp (attributes[i].attribute_name, attribute) == 0) {
- return attributes[i].sort_column_id;
- }
+ /* Hack - the preferences dialog sets modification_date for some
+ * rather than date_modified for some reason. Make sure that
+ * works. */
+ if (!strcmp (attribute, "modification_date")) {
+ attribute = "date_modified";
}
+ for (i = 0; i < model->details->columns->len; i++) {
+ NautilusColumn *column;
+ char *column_attribute;
+
+ column =
+ NAUTILUS_COLUMN (model->details->columns->pdata[i]);
+ g_object_get (G_OBJECT (column),
+ "attribute", &column_attribute,
+ NULL);
+ if (!strcmp (column_attribute, attribute)) {
+ g_free (column_attribute);
+ return FM_LIST_MODEL_NUM_COLUMNS + i;
+ }
+ g_free (column_attribute);
+ }
+
return -1;
}
char *
-fm_list_model_get_attribute_from_sort_column_id (int sort_column_id)
+fm_list_model_get_attribute_from_sort_column_id (FMListModel *model,
+ int sort_column_id)
{
- guint i;
-
- for (i = 0; i < G_N_ELEMENTS (attributes); i++) {
- if (attributes[i].sort_column_id == sort_column_id) {
- return g_strdup (attributes[i].attribute_name);
- }
- }
-
- g_warning ("unknown sort column id: %d", sort_column_id);
- return g_strdup ("name");
-}
+ NautilusColumn *column;
+ int index;
+ char *attribute;
+
+ index = sort_column_id - FM_LIST_MODEL_NUM_COLUMNS;
-int
-fm_list_model_get_sort_column_id_from_sort_type (NautilusFileSortType sort_type)
-{
- switch (sort_type) {
- case NAUTILUS_FILE_SORT_NONE:
- return -1;
- case NAUTILUS_FILE_SORT_BY_DISPLAY_NAME:
- return FM_LIST_MODEL_NAME_COLUMN;
- case NAUTILUS_FILE_SORT_BY_TYPE:
- return FM_LIST_MODEL_TYPE_COLUMN;
- case NAUTILUS_FILE_SORT_BY_SIZE:
- return FM_LIST_MODEL_SIZE_COLUMN;
- case NAUTILUS_FILE_SORT_BY_MTIME:
- return FM_LIST_MODEL_DATE_MODIFIED_COLUMN;
- case NAUTILUS_FILE_SORT_BY_EMBLEMS:
- case NAUTILUS_FILE_SORT_BY_DIRECTORY:
- break;
+ if (index < 0 || index >= model->details->columns->len) {
+ g_warning ("unknown sort column id: %d", sort_column_id);
+ return NULL;
}
- g_return_val_if_reached (-1);
-}
+ column = NAUTILUS_COLUMN (model->details->columns->pdata[index]);
+ g_object_get (G_OBJECT (column), "attribute", &attribute, NULL);
-NautilusFileSortType
-fm_list_model_get_sort_type_from_sort_column_id (int sort_column_id)
-{
- switch (sort_column_id) {
- case FM_LIST_MODEL_NAME_COLUMN:
- return NAUTILUS_FILE_SORT_BY_DISPLAY_NAME;
- case FM_LIST_MODEL_TYPE_COLUMN:
- return NAUTILUS_FILE_SORT_BY_TYPE;
- case FM_LIST_MODEL_SIZE_COLUMN:
- return NAUTILUS_FILE_SORT_BY_SIZE;
- case FM_LIST_MODEL_DATE_MODIFIED_COLUMN:
- return NAUTILUS_FILE_SORT_BY_MTIME;
- }
-
- g_return_val_if_reached (NAUTILUS_FILE_SORT_NONE);
+ return attribute;
}
NautilusZoomLevel
@@ -988,15 +944,56 @@ fm_list_model_get_drag_types (GtkTargetEntry **entries,
*num_entries = G_N_ELEMENTS (drag_types);
}
+int
+fm_list_model_add_column (FMListModel *model,
+ NautilusColumn *column)
+{
+ g_ptr_array_add (model->details->columns, column);
+ g_object_ref (column);
+
+ return FM_LIST_MODEL_NUM_COLUMNS + (model->details->columns->len - 1);
+}
+
+int
+fm_list_model_get_column_number (FMListModel *model,
+ const char *column_name)
+{
+ int i;
+
+ for (i = 0; i < model->details->columns->len; i++) {
+ NautilusColumn *column;
+ char *name;
+
+ column = model->details->columns->pdata[i];
+
+ g_object_get (G_OBJECT (column), "name", &name, NULL);
+
+ if (!strcmp (name, column_name)) {
+ g_free (name);
+ return FM_LIST_MODEL_NUM_COLUMNS + i;
+ }
+ g_free (name);
+ }
+
+ return -1;
+}
+
static void
fm_list_model_finalize (GObject *object)
{
FMListModel *model;
+ int i;
model = FM_LIST_MODEL (object);
+ for (i = 0; i < model->details->columns->len; i++) {
+ g_object_unref (model->details->columns->pdata[i]);
+ }
+ g_ptr_array_free (model->details->columns, TRUE);
+
g_sequence_free (model->details->files);
g_hash_table_destroy (model->details->reverse_map);
+ g_free (model->details->sort_attribute);
g_free (model->details);
EEL_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
@@ -1009,7 +1006,8 @@ fm_list_model_init (FMListModel *model)
model->details->files = g_sequence_new ((GDestroyNotify)nautilus_file_unref);
model->details->reverse_map = g_hash_table_new (g_direct_hash, g_direct_equal);
model->details->stamp = g_random_int ();
- model->details->sort_column_id = -1;
+ model->details->sort_attribute = NULL;
+ model->details->columns = g_ptr_array_new ();
}
static void
diff --git a/src/file-manager/fm-list-model.h b/src/file-manager/fm-list-model.h
index 033a568f5..d4a89a74e 100644
--- a/src/file-manager/fm-list-model.h
+++ b/src/file-manager/fm-list-model.h
@@ -27,6 +27,7 @@
#include <gdk/gdkdnd.h>
#include <libnautilus-private/nautilus-file.h>
#include <libnautilus-private/nautilus-icon-factory.h>
+#include <libnautilus-extension/nautilus-column.h>
#ifndef FM_LIST_MODEL_H
#define FM_LIST_MODEL_H
@@ -54,9 +55,6 @@ enum {
FM_LIST_MODEL_LARGER_EMBLEM_COLUMN,
FM_LIST_MODEL_LARGEST_EMBLEM_COLUMN,
FM_LIST_MODEL_NAME_COLUMN,
- FM_LIST_MODEL_SIZE_COLUMN,
- FM_LIST_MODEL_TYPE_COLUMN,
- FM_LIST_MODEL_DATE_MODIFIED_COLUMN,
FM_LIST_MODEL_FILE_NAME_IS_EDITABLE_COLUMN,
FM_LIST_MODEL_NUM_COLUMNS
};
@@ -88,11 +86,11 @@ gboolean fm_list_model_get_tree_iter_from_file (FMListModel *
void fm_list_model_set_should_sort_directories_first (FMListModel *model,
gboolean sort_directories_first);
-int fm_list_model_get_sort_column_id_from_attribute (const char *attribute);
-char *fm_list_model_get_attribute_from_sort_column_id (int sort_column_id);
+int fm_list_model_get_sort_column_id_from_attribute (FMListModel *model,
-int fm_list_model_get_sort_column_id_from_sort_type (NautilusFileSortType sort_type);
-NautilusFileSortType fm_list_model_get_sort_type_from_sort_column_id (int sort_column_id);
+ const char *attribute);
+char *fm_list_model_get_attribute_from_sort_column_id (FMListModel *model,
+ int sort_column_id);
NautilusZoomLevel fm_list_model_get_zoom_level_from_column_id (int column);
int fm_list_model_get_column_id_from_zoom_level (NautilusZoomLevel zoom_level);
@@ -111,4 +109,9 @@ void fm_list_model_set_drag_view (FMListModel *model,
void fm_list_model_get_drag_types (GtkTargetEntry **entries,
int *num_entries);
+
+int fm_list_model_add_column (FMListModel *model,
+ NautilusColumn *column);
+int fm_list_model_get_column_number (FMListModel *model,
+ const char *column_name);
#endif /* FM_LIST_MODEL_H */
diff --git a/src/file-manager/fm-list-view.c b/src/file-manager/fm-list-view.c
index 5f909aa8c..4d7b72a1c 100644
--- a/src/file-manager/fm-list-view.c
+++ b/src/file-manager/fm-list-view.c
@@ -31,19 +31,29 @@
#include <string.h>
#include "fm-error-reporting.h"
#include "fm-list-model.h"
+#include <string.h>
+#include <bonobo/bonobo-ui-util.h>
#include <eel/eel-cell-renderer-pixbuf-list.h>
#include <eel/eel-vfs-extensions.h>
#include <eel/eel-glib-extensions.h>
+#include <eel/eel-gtk-macros.h>
#include <gdk/gdkkeysyms.h>
+#include <gtk/gtkdialog.h>
#include <gtk/gtkcellrendererpixbuf.h>
#include <gtk/gtkcellrenderertext.h>
#include <gtk/gtkentry.h>
+#include <gtk/gtklabel.h>
+#include <gtk/gtkvbox.h>
+#include <gtk/gtkstock.h>
#include <gtk/gtktreeselection.h>
#include <gtk/gtktreeview.h>
#include <libegg/eggtreemultidnd.h>
#include <libgnome/gnome-i18n.h>
#include <libgnome/gnome-macros.h>
#include <libgnomevfs/gnome-vfs-utils.h>
+#include <libnautilus-extension/nautilus-column-provider.h>
+#include <libnautilus-private/nautilus-column-chooser.h>
+#include <libnautilus-private/nautilus-column-utilities.h>
#include <libnautilus-private/nautilus-directory-background.h>
#include <libnautilus-private/nautilus-dnd.h>
#include <libnautilus-private/nautilus-file-dnd.h>
@@ -51,6 +61,7 @@
#include <libnautilus-private/nautilus-icon-dnd.h>
#include <libnautilus-private/nautilus-icon-factory.h>
#include <libnautilus-private/nautilus-metadata.h>
+#include <libnautilus-private/nautilus-module.h>
#include <libnautilus-private/nautilus-tree-view-drag-dest.h>
#include <libnautilus/nautilus-scroll-positionable.h>
#include <libnautilus-private/nautilus-cell-renderer-pixbuf-emblem.h>
@@ -71,9 +82,7 @@ struct FMListViewDetails {
GtkCellRendererPixbuf *pixbuf_cell;
GtkCellRendererText *file_name_cell;
- GtkCellRendererText *size_cell;
- GtkCellRendererText *type_cell;
- GtkCellRendererText *date_modified_cell;
+ GList *cells;
NautilusZoomLevel zoom_level;
@@ -90,10 +99,17 @@ struct FMListViewDetails {
int drag_y;
gboolean drag_started;
+
gboolean row_selected_on_button_down;
/* typeahead selection state */
TypeSelectState *type_select_state;
+
+ BonoboUIComponent *ui;
+ gboolean menus_ready;
+
+ GHashTable *columns;
+ GtkWidget *column_editor;
};
/*
@@ -104,9 +120,11 @@ struct FMListViewDetails {
#define LIST_VIEW_MINIMUM_ROW_HEIGHT 28
static int click_policy_auto_value;
-static NautilusFileSortType default_sort_order_auto_value;
+static char * default_sort_order_auto_value;
static gboolean default_sort_reversed_auto_value;
static NautilusZoomLevel default_zoom_level_auto_value;
+static GList * default_visible_columns_auto_value;
+static GList * default_column_order_auto_value;
static GList * fm_list_view_get_selection (FMDirectoryView *view);
static void fm_list_view_set_zoom_level (FMListView *view,
@@ -765,9 +783,9 @@ sort_column_changed_callback (GtkTreeSortable *sortable,
gtk_tree_sortable_get_sort_column_id (sortable, &sort_column_id, &reversed);
- sort_attr = fm_list_model_get_attribute_from_sort_column_id (sort_column_id);
- sort_column_id = fm_list_model_get_sort_column_id_from_sort_type (default_sort_order_auto_value);
- default_sort_attr = fm_list_model_get_attribute_from_sort_column_id (sort_column_id);
+ sort_attr = fm_list_model_get_attribute_from_sort_column_id (view->details->model, sort_column_id);
+ sort_column_id = fm_list_model_get_sort_column_id_from_attribute (view->details->model, default_sort_order_auto_value);
+ default_sort_attr = fm_list_model_get_attribute_from_sort_column_id (view->details->model, sort_column_id);
nautilus_file_set_metadata (file, NAUTILUS_METADATA_KEY_LIST_VIEW_SORT_COLUMN,
default_sort_attr, sort_attr);
g_free (default_sort_attr);
@@ -877,6 +895,60 @@ move_copy_items_callback (NautilusTreeViewDragDest *dest,
}
static void
+apply_visible_columns_foreach (gpointer key, gpointer value, gpointer user_data)
+{
+ gboolean visible;
+
+ visible = (eel_g_str_list_index (user_data, key) != -1);
+
+ gtk_tree_view_column_set_visible (GTK_TREE_VIEW_COLUMN (value),
+ visible);
+}
+
+static void
+apply_visible_columns (FMListView *list_view, GList *visible_columns)
+{
+ g_hash_table_foreach (list_view->details->columns,
+ apply_visible_columns_foreach,
+ visible_columns);
+
+}
+
+static void
+apply_column_order (FMListView *list_view, GList *column_order)
+{
+ GList *columns;
+ GtkTreeViewColumn *last_view_column;
+ GList *l;
+
+ columns = nautilus_get_all_columns ();
+ columns = nautilus_sort_columns (columns, column_order);
+
+ last_view_column = NULL;
+ for (l = columns; l != NULL; l = l->next) {
+ GtkTreeViewColumn *view_column;
+ char *name;
+
+ g_object_get (G_OBJECT (l->data), "name", &name, NULL);
+
+ view_column = g_hash_table_lookup (list_view->details->columns,
+ name);
+
+ g_free (name);
+
+ if (view_column) {
+ gtk_tree_view_move_column_after
+ (list_view->details->tree_view,
+ view_column,
+ last_view_column);
+
+ last_view_column = view_column;
+ }
+ }
+ nautilus_column_list_free (columns);
+}
+
+static void
create_and_set_up_tree_view (FMListView *view)
{
GtkCellRenderer *cell;
@@ -884,8 +956,14 @@ create_and_set_up_tree_view (FMListView *view)
GtkTargetEntry *drag_types;
AtkObject *atk_obj;
int num_drag_types;
-
+ GList *nautilus_columns;
+ GList *l;
+
view->details->tree_view = GTK_TREE_VIEW (gtk_tree_view_new ());
+ view->details->columns = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ (GDestroyNotify)g_free,
+ NULL);
fm_list_model_get_drag_types (&drag_types, &num_drag_types);
@@ -938,70 +1016,91 @@ create_and_set_up_tree_view (FMListView *view)
gtk_tree_selection_set_mode (gtk_tree_view_get_selection (view->details->tree_view), GTK_SELECTION_MULTIPLE);
gtk_tree_view_set_rules_hint (view->details->tree_view, TRUE);
- /* Create the file name column */
- cell = nautilus_cell_renderer_pixbuf_emblem_new ();
- view->details->pixbuf_cell = (GtkCellRendererPixbuf *)cell;
-
- view->details->file_name_column = gtk_tree_view_column_new ();
- gtk_tree_view_column_set_sort_column_id (view->details->file_name_column, FM_LIST_MODEL_NAME_COLUMN);
- gtk_tree_view_column_set_title (view->details->file_name_column, _("File name"));
- gtk_tree_view_column_set_resizable (view->details->file_name_column, TRUE);
+ nautilus_columns = nautilus_get_all_columns ();
- gtk_tree_view_column_pack_start (view->details->file_name_column, cell, FALSE);
- gtk_tree_view_column_set_attributes (view->details->file_name_column,
- cell,
- "pixbuf", FM_LIST_MODEL_SMALLEST_ICON_COLUMN,
- "pixbuf_emblem", FM_LIST_MODEL_SMALLEST_EMBLEM_COLUMN,
- NULL);
+ for (l = nautilus_columns; l != NULL; l = l->next) {
+ NautilusColumn *nautilus_column;
+ int column_num;
+ char *name;
+ char *label;
+ float xalign;
- cell = gtk_cell_renderer_text_new ();
- view->details->file_name_cell = (GtkCellRendererText *)cell;
- g_signal_connect (cell, "edited", G_CALLBACK (cell_renderer_edited), view);
+ nautilus_column = NAUTILUS_COLUMN (l->data);
- gtk_tree_view_column_pack_start (view->details->file_name_column, cell, TRUE);
- gtk_tree_view_column_set_attributes (view->details->file_name_column, cell,
- "text", FM_LIST_MODEL_NAME_COLUMN, NULL);
- gtk_tree_view_append_column (view->details->tree_view, view->details->file_name_column);
+ g_object_get (nautilus_column,
+ "name", &name,
+ "label", &label,
+ "xalign", &xalign, NULL);
- /* Create the size column */
- cell = gtk_cell_renderer_text_new ();
- view->details->size_cell = (GtkCellRendererText *)cell;
- g_object_set (G_OBJECT (cell),
- "xalign", 1.0,
- NULL);
- column = gtk_tree_view_column_new_with_attributes (_("Size"),
- cell,
- "text", FM_LIST_MODEL_SIZE_COLUMN,
- NULL);
- gtk_tree_view_column_set_resizable (column, TRUE);
- gtk_tree_view_column_set_sort_column_id (column, FM_LIST_MODEL_SIZE_COLUMN);
- gtk_tree_view_append_column (view->details->tree_view, column);
-
- /* Create the type column */
- cell = gtk_cell_renderer_text_new ();
- view->details->type_cell = (GtkCellRendererText *)cell;
- column = gtk_tree_view_column_new_with_attributes (_("Type"),
- cell,
- "text", FM_LIST_MODEL_TYPE_COLUMN,
- NULL);
- gtk_tree_view_column_set_resizable (column, TRUE);
- gtk_tree_view_column_set_sort_column_id (column, FM_LIST_MODEL_TYPE_COLUMN);
- gtk_tree_view_append_column (view->details->tree_view, column);
-
- /* Create the date modified column */
- cell = gtk_cell_renderer_text_new ();
- view->details->date_modified_cell = (GtkCellRendererText *)cell;
- column = gtk_tree_view_column_new_with_attributes (_("Date Modified"),
- cell,
- "text", FM_LIST_MODEL_DATE_MODIFIED_COLUMN,
- NULL);
- gtk_tree_view_column_set_resizable (column, TRUE);
- gtk_tree_view_column_set_sort_column_id (column, FM_LIST_MODEL_DATE_MODIFIED_COLUMN);
- gtk_tree_view_append_column (view->details->tree_view, column);
+ column_num = fm_list_model_add_column (view->details->model,
+ nautilus_column);
+
+ /* Created the name column specially, because it
+ * has the icon in it.*/
+ if (!strcmp (name, "name")) {
+ /* Create the file name column */
+ cell = nautilus_cell_renderer_pixbuf_emblem_new ();
+ view->details->pixbuf_cell = (GtkCellRendererPixbuf *)cell;
+
+ view->details->file_name_column = gtk_tree_view_column_new ();
+
+ g_hash_table_insert (view->details->columns,
+ g_strdup ("name"),
+ view->details->file_name_column);
+
+ gtk_tree_view_column_set_sort_column_id (view->details->file_name_column, column_num);
+ gtk_tree_view_column_set_title (view->details->file_name_column, _("File name"));
+ gtk_tree_view_column_set_resizable (view->details->file_name_column, TRUE);
+
+ gtk_tree_view_column_pack_start (view->details->file_name_column, cell, FALSE);
+ gtk_tree_view_column_set_attributes (view->details->file_name_column,
+ cell,
+ "pixbuf", FM_LIST_MODEL_SMALLEST_ICON_COLUMN,
+ "pixbuf_emblem", FM_LIST_MODEL_SMALLEST_EMBLEM_COLUMN,
+ NULL);
+
+ cell = gtk_cell_renderer_text_new ();
+ view->details->file_name_cell = (GtkCellRendererText *)cell;
+ g_signal_connect (cell, "edited", G_CALLBACK (cell_renderer_edited), view);
+
+ gtk_tree_view_column_pack_start (view->details->file_name_column, cell, TRUE);
+ gtk_tree_view_column_set_attributes (view->details->file_name_column, cell,
+ "text",
+ column_num, NULL);
+ gtk_tree_view_append_column (view->details->tree_view, view->details->file_name_column);
+ } else {
+ cell = gtk_cell_renderer_text_new ();
+ g_object_set (cell, "xalign", xalign, NULL);
+ view->details->cells = g_list_append (view->details->cells,
+ cell);
+ column = gtk_tree_view_column_new_with_attributes (label,
+ cell,
+ "text", column_num,
+ NULL);
+ gtk_tree_view_column_set_sort_column_id (column, column_num);
+ g_hash_table_insert (view->details->columns,
+ g_strdup (name),
+ column);
+
+ gtk_tree_view_column_set_resizable (column, TRUE);
+ gtk_tree_view_column_set_visible (column, TRUE);
+ gtk_tree_view_append_column (view->details->tree_view, column);
+ }
+ g_free (name);
+ g_free (label);
+ }
+ nautilus_column_list_free (nautilus_columns);
+
+ /* Apply the default column order and visible columns, to get it
+ * right most of the time. The metadata will be checked when a
+ * folder is loaded */
+ apply_visible_columns (view, default_visible_columns_auto_value);
+ apply_column_order (view, default_column_order_auto_value);
gtk_widget_show (GTK_WIDGET (view->details->tree_view));
gtk_container_add (GTK_CONTAINER (view), GTK_WIDGET (view->details->tree_view));
+
atk_obj = gtk_widget_get_accessible (GTK_WIDGET (view->details->tree_view));
atk_object_set_name (atk_obj, _("List View"));
}
@@ -1012,6 +1111,66 @@ fm_list_view_add_file (FMDirectoryView *view, NautilusFile *file)
fm_list_model_add_file (FM_LIST_VIEW (view)->details->model, file);
}
+static GList *
+get_visible_columns (FMListView *list_view)
+{
+ NautilusFile *file;
+ GList *visible_columns;
+
+ file = fm_directory_view_get_directory_as_file (FM_DIRECTORY_VIEW (list_view));
+
+ visible_columns = nautilus_file_get_metadata_list
+ (file,
+ NAUTILUS_METADATA_KEY_LIST_VIEW_VISIBLE_COLUMNS,
+ NAUTILUS_METADATA_SUBKEY_COLUMNS);
+
+ if (!visible_columns) {
+ visible_columns = eel_g_str_list_copy (default_visible_columns_auto_value);
+ }
+
+ return visible_columns;
+}
+
+static void
+set_visible_columns_from_metadata_and_preferences (FMListView *list_view)
+{
+ GList *visible_columns;
+
+ visible_columns = get_visible_columns (list_view);
+ apply_visible_columns (list_view, visible_columns);
+ eel_g_list_free_deep (visible_columns);
+}
+
+static GList *
+get_column_order (FMListView *list_view)
+{
+ NautilusFile *file;
+ GList *column_order;
+
+ file = fm_directory_view_get_directory_as_file (FM_DIRECTORY_VIEW (list_view));
+
+ column_order = nautilus_file_get_metadata_list
+ (file,
+ NAUTILUS_METADATA_KEY_LIST_VIEW_COLUMN_ORDER,
+ NAUTILUS_METADATA_SUBKEY_COLUMNS);
+
+ if (!column_order) {
+ column_order = eel_g_str_list_copy (default_column_order_auto_value);
+ }
+
+ return column_order;
+}
+
+static void
+set_column_order_from_metadata_and_preferences (FMListView *list_view)
+{
+ GList *column_order;
+
+ column_order = get_column_order (list_view);
+ apply_column_order (list_view, column_order);
+ eel_g_list_free_deep (column_order);
+}
+
static void
set_sort_order_from_metadata_and_preferences (FMListView *list_view)
{
@@ -1024,11 +1183,10 @@ set_sort_order_from_metadata_and_preferences (FMListView *list_view)
sort_attribute = nautilus_file_get_metadata (file,
NAUTILUS_METADATA_KEY_LIST_VIEW_SORT_COLUMN,
NULL);
- sort_column_id = fm_list_model_get_sort_column_id_from_attribute (sort_attribute);
+ sort_column_id = fm_list_model_get_sort_column_id_from_attribute (list_view->details->model, sort_attribute);
g_free (sort_attribute);
-
if (sort_column_id == -1) {
- sort_column_id = fm_list_model_get_sort_column_id_from_sort_type (default_sort_order_auto_value);
+ sort_column_id = fm_list_model_get_sort_column_id_from_attribute (list_view->details->model, default_sort_order_auto_value);
}
sort_reversed = nautilus_file_get_boolean_metadata (file,
@@ -1098,6 +1256,8 @@ fm_list_view_begin_loading (FMDirectoryView *view)
set_sort_order_from_metadata_and_preferences (list_view);
set_zoom_level_from_metadata_and_preferences (list_view);
+ set_visible_columns_from_metadata_and_preferences (list_view);
+ set_column_order_from_metadata_and_preferences (list_view);
}
static void
@@ -1263,6 +1423,195 @@ fm_list_view_reveal_selection (FMDirectoryView *view)
nautilus_file_list_free (selection);
}
+static void
+column_editor_response_callback (GtkWidget *dialog,
+ int response_id,
+ gpointer user_data)
+{
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+}
+
+static void
+column_chooser_changed_callback (NautilusColumnChooser *chooser,
+ FMListView *view)
+{
+ NautilusFile *file;
+ GList *visible_columns;
+ GList *column_order;
+
+ file = fm_directory_view_get_directory_as_file (FM_DIRECTORY_VIEW (view));
+
+ nautilus_column_chooser_get_settings (chooser,
+ &visible_columns,
+ &column_order);
+
+ nautilus_file_set_metadata_list (file, NAUTILUS_METADATA_KEY_LIST_VIEW_VISIBLE_COLUMNS, NAUTILUS_METADATA_SUBKEY_COLUMNS, visible_columns);
+ nautilus_file_set_metadata_list (file, NAUTILUS_METADATA_KEY_LIST_VIEW_COLUMN_ORDER, NAUTILUS_METADATA_SUBKEY_COLUMNS, column_order);
+
+ eel_g_list_free_deep (visible_columns);
+ eel_g_list_free_deep (column_order);
+
+ set_visible_columns_from_metadata_and_preferences (view);
+ set_column_order_from_metadata_and_preferences (view);
+}
+
+static void
+column_chooser_set_from_settings (NautilusColumnChooser *chooser,
+ FMListView *view)
+{
+ GList *visible_columns;
+ GList *column_order;
+
+ g_signal_handlers_block_by_func
+ (chooser, G_CALLBACK (column_chooser_changed_callback), view);
+
+ visible_columns = get_visible_columns (view);
+ column_order = get_column_order (view);
+
+ nautilus_column_chooser_set_settings (chooser,
+ visible_columns,
+ column_order);
+
+ eel_g_list_free_deep (visible_columns);
+ eel_g_list_free_deep (column_order);
+
+ g_signal_handlers_unblock_by_func
+ (chooser, G_CALLBACK (column_chooser_changed_callback), view);
+}
+
+static void
+column_chooser_use_default_callback (NautilusColumnChooser *chooser,
+ FMListView *view)
+{
+ NautilusFile *file;
+
+ file = fm_directory_view_get_directory_as_file
+ (FM_DIRECTORY_VIEW (view));
+
+ nautilus_file_set_metadata_list (file, NAUTILUS_METADATA_KEY_LIST_VIEW_COLUMN_ORDER, NAUTILUS_METADATA_SUBKEY_COLUMNS, NULL);
+ nautilus_file_set_metadata_list (file, NAUTILUS_METADATA_KEY_LIST_VIEW_VISIBLE_COLUMNS, NAUTILUS_METADATA_SUBKEY_COLUMNS, NULL);
+
+ set_visible_columns_from_metadata_and_preferences (FM_LIST_VIEW (view));
+ set_column_order_from_metadata_and_preferences (FM_LIST_VIEW (view));
+ column_chooser_set_from_settings (chooser, view);
+}
+
+static GtkWidget *
+create_column_editor (FMListView *view)
+{
+ GtkWidget *window;
+ GtkWidget *label;
+ GtkWidget *box;
+ GtkWidget *column_chooser;
+ NautilusFile *file;
+ char *title;
+ char *name;
+
+ file = fm_directory_view_get_directory_as_file (FM_DIRECTORY_VIEW (view));
+ name = nautilus_file_get_display_name (file);
+ title = g_strdup_printf (_("%s Visible Columns"), name);
+ g_free (name);
+
+ window = gtk_dialog_new_with_buttons (title,
+ GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (view))),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_STOCK_CLOSE, GTK_RESPONSE_CANCEL,
+ NULL);
+ g_free (title);
+ g_signal_connect (window, "response",
+ G_CALLBACK (column_editor_response_callback), NULL);
+
+ gtk_window_set_default_size (GTK_WINDOW (window), 300, 400);
+
+ box = gtk_vbox_new (FALSE, 6);
+ gtk_container_set_border_width (GTK_CONTAINER (box), 12);
+ gtk_widget_show (box);
+ gtk_container_add (GTK_CONTAINER (GTK_DIALOG (window)->vbox), box);
+
+ label = gtk_label_new (_("Choose the order of information to appear in this folder."));
+ gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+ gtk_widget_show (label);
+ gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 0);
+
+ column_chooser = nautilus_column_chooser_new ();
+ gtk_widget_show (column_chooser);
+ gtk_box_pack_start (GTK_BOX (box), column_chooser, TRUE, TRUE, 0);
+
+ g_signal_connect (column_chooser, "changed",
+ G_CALLBACK (column_chooser_changed_callback),
+ view);
+ g_signal_connect (column_chooser, "use_default",
+ G_CALLBACK (column_chooser_use_default_callback),
+ view);
+
+ column_chooser_set_from_settings
+ (NAUTILUS_COLUMN_CHOOSER (column_chooser), view);
+
+ return window;
+}
+
+static void
+visible_columns_callback (BonoboUIComponent *component,
+ gpointer callback_data,
+ const char *verb)
+{
+ FMListView *list_view;
+
+ list_view = FM_LIST_VIEW (callback_data);
+
+ if (list_view->details->column_editor) {
+ gtk_window_present (GTK_WINDOW (list_view->details->column_editor));
+ } else {
+ list_view->details->column_editor = create_column_editor (list_view);
+ eel_add_weak_pointer (&list_view->details->column_editor);
+
+ gtk_widget_show (list_view->details->column_editor);
+ }
+}
+
+static void
+fm_list_view_merge_menus (FMDirectoryView *view)
+{
+ FMListView *list_view;
+ Bonobo_UIContainer ui_container;
+ BonoboUIVerb verbs [] = {
+ BONOBO_UI_VERB ("Visible Columns", visible_columns_callback),
+ BONOBO_UI_VERB_END
+ };
+
+ EEL_CALL_PARENT (FM_DIRECTORY_VIEW_CLASS, merge_menus, (view));
+
+ list_view = FM_LIST_VIEW (view);
+
+ list_view->details->ui = bonobo_ui_component_new ("List View");
+ ui_container = fm_directory_view_get_bonobo_ui_container (view);
+ bonobo_ui_component_set_container (list_view->details->ui,
+ ui_container, NULL);
+ bonobo_object_release_unref (ui_container, NULL);
+ bonobo_ui_util_set_ui (list_view->details->ui,
+ DATADIR,
+ "nautilus-list-view-ui.xml",
+ "nautilus", NULL);
+
+ bonobo_ui_component_add_verb_list_with_data (list_view->details->ui, verbs, view);
+
+ list_view->details->menus_ready = TRUE;
+}
+
+static void
+fm_list_view_update_menus (FMDirectoryView *view)
+{
+ FMListView *list_view;
+
+ list_view = FM_LIST_VIEW (view);
+
+ /* don't update if the menus aren't ready */
+ if (!list_view->details->menus_ready) {
+ return;
+ }
+
+ EEL_CALL_PARENT (FM_DIRECTORY_VIEW_CLASS, update_menus, (view));
+}
/* Reset sort criteria and zoom level to match defaults */
static void
@@ -1275,13 +1624,17 @@ fm_list_view_reset_to_defaults (FMDirectoryView *view)
nautilus_file_set_metadata (file, NAUTILUS_METADATA_KEY_LIST_VIEW_SORT_COLUMN, NULL, NULL);
nautilus_file_set_metadata (file, NAUTILUS_METADATA_KEY_LIST_VIEW_SORT_REVERSED, NULL, NULL);
nautilus_file_set_metadata (file, NAUTILUS_METADATA_KEY_LIST_VIEW_ZOOM_LEVEL, NULL, NULL);
+ nautilus_file_set_metadata_list (file, NAUTILUS_METADATA_KEY_LIST_VIEW_COLUMN_ORDER, NAUTILUS_METADATA_SUBKEY_COLUMNS, NULL);
+ nautilus_file_set_metadata_list (file, NAUTILUS_METADATA_KEY_LIST_VIEW_VISIBLE_COLUMNS, NAUTILUS_METADATA_SUBKEY_COLUMNS, NULL);
gtk_tree_sortable_set_sort_column_id
(GTK_TREE_SORTABLE (FM_LIST_VIEW (view)->details->model),
- fm_list_model_get_sort_column_id_from_sort_type (default_sort_order_auto_value),
+ fm_list_model_get_sort_column_id_from_attribute (FM_LIST_VIEW (view)->details->model, default_sort_order_auto_value),
default_sort_reversed_auto_value ? GTK_SORT_DESCENDING : GTK_SORT_ASCENDING);
fm_list_view_set_zoom_level (FM_LIST_VIEW (view), get_default_zoom_level (), FALSE);
+ set_visible_columns_from_metadata_and_preferences (FM_LIST_VIEW (view));
+ set_column_order_from_metadata_and_preferences (FM_LIST_VIEW (view));
}
static void
@@ -1289,6 +1642,7 @@ fm_list_view_scale_font_size (FMListView *view,
NautilusZoomLevel new_level,
gboolean update_size_table)
{
+ GList *l;
static gboolean first_time = TRUE;
static double pango_scale[7];
int default_zoom_level, i;
@@ -1313,15 +1667,11 @@ fm_list_view_scale_font_size (FMListView *view,
g_object_set (G_OBJECT (view->details->file_name_cell),
"scale", pango_scale[new_level],
NULL);
- g_object_set (G_OBJECT (view->details->size_cell),
- "scale", pango_scale[new_level],
- NULL);
- g_object_set (G_OBJECT (view->details->type_cell),
- "scale", pango_scale[new_level],
- NULL);
- g_object_set (G_OBJECT (view->details->date_modified_cell),
- "scale", pango_scale[new_level],
- NULL);
+ for (l = view->details->cells; l != NULL; l = l->next) {
+ g_object_set (G_OBJECT (l->data),
+ "scale", pango_scale[new_level],
+ NULL);
+ }
}
static void
@@ -1526,6 +1876,26 @@ default_zoom_level_changed_callback (gpointer callback_data)
}
static void
+default_visible_columns_changed_callback (gpointer callback_data)
+{
+ FMListView *list_view;
+
+ list_view = FM_LIST_VIEW (callback_data);
+
+ set_visible_columns_from_metadata_and_preferences (list_view);
+}
+
+static void
+default_column_order_changed_callback (gpointer callback_data)
+{
+ FMListView *list_view;
+
+ list_view = FM_LIST_VIEW (callback_data);
+
+ set_column_order_from_metadata_and_preferences (list_view);
+}
+
+static void
fm_list_view_sort_directories_first_changed (FMDirectoryView *view)
{
FMListView *list_view;
@@ -1552,7 +1922,7 @@ fm_list_view_dispose (GObject *object)
g_object_unref (list_view->details->drag_dest);
list_view->details->drag_dest = NULL;
}
-
+
G_OBJECT_CLASS (parent_class)->dispose (object);
}
@@ -1570,10 +1940,18 @@ fm_list_view_finalize (GObject *object)
gtk_tree_path_free (list_view->details->double_click_path[1]);
}
+ if (list_view->details->ui != NULL) {
+ bonobo_ui_component_unset_container (list_view->details->ui, NULL);
+ bonobo_object_unref (list_view->details->ui);
+ }
+
gtk_target_list_unref (list_view->details->source_target_list);
fm_list_view_flush_typeselect_state (list_view);
+ g_list_free (list_view->details->cells);
+ g_hash_table_destroy (list_view->details->columns);
+
g_free (list_view->details);
G_OBJECT_CLASS (parent_class)->finalize (object);
@@ -1682,6 +2060,8 @@ fm_list_view_class_init (FMListViewClass *class)
fm_directory_view_class->get_item_count = fm_list_view_get_item_count;
fm_directory_view_class->is_empty = fm_list_view_is_empty;
fm_directory_view_class->remove_file = fm_list_view_remove_file;
+ fm_directory_view_class->merge_menus = fm_list_view_merge_menus;
+ fm_directory_view_class->update_menus = fm_list_view_update_menus;
fm_directory_view_class->reset_to_defaults = fm_list_view_reset_to_defaults;
fm_directory_view_class->restore_default_zoom_level = fm_list_view_restore_default_zoom_level;
fm_directory_view_class->reveal_selection = fm_list_view_reveal_selection;
@@ -1694,12 +2074,16 @@ fm_list_view_class_init (FMListViewClass *class)
eel_preferences_add_auto_enum (NAUTILUS_PREFERENCES_CLICK_POLICY,
&click_policy_auto_value);
- eel_preferences_add_auto_enum (NAUTILUS_PREFERENCES_LIST_VIEW_DEFAULT_SORT_ORDER,
- (int *) &default_sort_order_auto_value);
+ eel_preferences_add_auto_string (NAUTILUS_PREFERENCES_LIST_VIEW_DEFAULT_SORT_ORDER,
+ (const char **) &default_sort_order_auto_value);
eel_preferences_add_auto_boolean (NAUTILUS_PREFERENCES_LIST_VIEW_DEFAULT_SORT_IN_REVERSE_ORDER,
&default_sort_reversed_auto_value);
eel_preferences_add_auto_enum (NAUTILUS_PREFERENCES_LIST_VIEW_DEFAULT_ZOOM_LEVEL,
(int *) &default_zoom_level_auto_value);
+ eel_preferences_add_auto_string_glist (NAUTILUS_PREFERENCES_LIST_VIEW_DEFAULT_VISIBLE_COLUMNS,
+ (const GList **) &default_visible_columns_auto_value);
+ eel_preferences_add_auto_string_glist (NAUTILUS_PREFERENCES_LIST_VIEW_DEFAULT_COLUMN_ORDER,
+ (const GList **) &default_column_order_auto_value);
}
static void
@@ -1726,6 +2110,12 @@ fm_list_view_instance_init (FMListView *list_view)
eel_preferences_add_callback_while_alive (NAUTILUS_PREFERENCES_LIST_VIEW_DEFAULT_ZOOM_LEVEL,
default_zoom_level_changed_callback,
list_view, G_OBJECT (list_view));
+ eel_preferences_add_callback_while_alive (NAUTILUS_PREFERENCES_LIST_VIEW_DEFAULT_VISIBLE_COLUMNS,
+ default_visible_columns_changed_callback,
+ list_view, G_OBJECT (list_view));
+ eel_preferences_add_callback_while_alive (NAUTILUS_PREFERENCES_LIST_VIEW_DEFAULT_COLUMN_ORDER,
+ default_column_order_changed_callback,
+ list_view, G_OBJECT (list_view));
fm_list_view_click_policy_changed (FM_DIRECTORY_VIEW (list_view));
diff --git a/src/file-manager/fm-properties-window.c b/src/file-manager/fm-properties-window.c
index c013319d5..bf2de856f 100644
--- a/src/file-manager/fm-properties-window.c
+++ b/src/file-manager/fm-properties-window.c
@@ -62,6 +62,7 @@
#include <libgnomeui/gnome-dialog.h>
#include <libgnomeui/gnome-uidefs.h>
#include <libgnomevfs/gnome-vfs.h>
+#include <libnautilus-extension/nautilus-property-page-provider.h>
#include <libnautilus-private/nautilus-customization-data.h>
#include <libnautilus-private/nautilus-entry.h>
#include <libnautilus-private/nautilus-file-attributes.h>
@@ -71,6 +72,7 @@
#include <libnautilus-private/nautilus-emblem-utils.h>
#include <libnautilus-private/nautilus-link.h>
#include <libnautilus-private/nautilus-metadata.h>
+#include <libnautilus-private/nautilus-module.h>
#include <libnautilus-private/nautilus-undo-signal-handlers.h>
#include <libnautilus-private/nautilus-mime-actions.h>
#include <libnautilus-private/nautilus-view-identifier.h>
@@ -156,13 +158,6 @@ typedef struct {
GHashTable *pending_files;
} StartupData;
-typedef struct {
- FMPropertiesWindow *window;
- GtkWidget *vbox;
- char *view_name;
-} ActivationData;
-
-
/* drag and drop definitions */
enum {
@@ -204,7 +199,7 @@ static void remove_pending (StartupData *data
gboolean cancel_call_when_ready,
gboolean cancel_timed_wait,
gboolean cancel_destroy_handler);
-static void append_bonobo_pages (FMPropertiesWindow *window);
+static void append_extension_pages (FMPropertiesWindow *window);
GNOME_CLASS_BOILERPLATE (FMPropertiesWindow, fm_properties_window,
GtkWindow, GTK_TYPE_WINDOW);
@@ -929,7 +924,7 @@ update_properties_window_title (FMPropertiesWindow *window)
}
static void
-clear_bonobo_pages (FMPropertiesWindow *window)
+clear_extension_pages (FMPropertiesWindow *window)
{
int i;
int num_pages;
@@ -938,11 +933,11 @@ clear_bonobo_pages (FMPropertiesWindow *window)
num_pages = gtk_notebook_get_n_pages
(GTK_NOTEBOOK (window->details->notebook));
- for (i=0; i < num_pages; i++) {
+ for (i = 0; i < num_pages; i++) {
page = gtk_notebook_get_nth_page
(GTK_NOTEBOOK (window->details->notebook), i);
- if (g_object_get_data (G_OBJECT (page), "is-bonobo-page")) {
+ if (g_object_get_data (G_OBJECT (page), "is-extension-page")) {
gtk_notebook_remove_page
(GTK_NOTEBOOK (window->details->notebook), i);
num_pages--;
@@ -952,10 +947,10 @@ clear_bonobo_pages (FMPropertiesWindow *window)
}
static void
-refresh_bonobo_pages (FMPropertiesWindow *window)
+refresh_extension_pages (FMPropertiesWindow *window)
{
- clear_bonobo_pages (window);
- append_bonobo_pages (window);
+ clear_extension_pages (window);
+ append_extension_pages (window);
}
static void
@@ -1086,7 +1081,7 @@ properties_window_update (FMPropertiesWindow *window,
window->details->mime_list = mime_list;
} else {
if (!mime_list_equal (window->details->mime_list, mime_list)) {
- refresh_bonobo_pages (window);
+ refresh_extension_pages (window);
}
eel_g_list_free_deep (window->details->mime_list);
@@ -3041,209 +3036,52 @@ create_permissions_page (FMPropertiesWindow *window)
}
}
-static GtkWidget *
-bonobo_page_error_message (const char *view_name,
- const char *msg)
-{
- GtkWidget *hbox;
- GtkWidget *label;
- GtkWidget *image;
-
- hbox = gtk_hbox_new (FALSE, GNOME_PAD);
- image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_ERROR,
- GTK_ICON_SIZE_DIALOG);
-
- msg = g_strdup_printf ("There was an error while trying to create the view named `%s': %s", view_name, msg);
- label = gtk_label_new (msg);
-
- gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
-
- gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0);
- gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
- gtk_widget_show_all (hbox);
-
- return hbox;
-}
-
-static CORBA_sequence_CORBA_string *
-get_uri_list (GList *file_list)
-{
- CORBA_sequence_CORBA_string *uri_list;
- GList *l;
- int i;
-
- uri_list = CORBA_sequence_CORBA_string__alloc ();
- uri_list->_maximum = g_list_length (file_list);
- uri_list->_length = uri_list->_maximum;
- uri_list->_buffer = CORBA_sequence_CORBA_string_allocbuf (uri_list->_length);
- for (i = 0, l = file_list; l != NULL; i++, l = l->next) {
- char *uri;
-
- uri = nautilus_file_get_uri (NAUTILUS_FILE (l->data));
- uri_list->_buffer[i] = CORBA_string_dup (uri);
- g_free (uri);
- }
-
- return uri_list;
-}
-
-static void
-bonobo_page_activate_callback (CORBA_Object obj,
- const char *error_reason,
- gpointer user_data)
-{
- ActivationData *data;
- FMPropertiesWindow *window;
- GtkWidget *widget;
- CORBA_Environment ev;
-
- data = (ActivationData *)user_data;
- window = data->window;
-
- g_return_if_fail (FM_IS_PROPERTIES_WINDOW (window));
-
- CORBA_exception_init (&ev);
- widget = NULL;
-
- if (obj != CORBA_OBJECT_NIL) {
- Bonobo_Control control;
- Bonobo_PropertyBag pb;
- GList *keys;
-
- control = Bonobo_Unknown_queryInterface
- (obj, "IDL:Bonobo/Control:1.0", &ev);
-
- pb = Bonobo_Control_getProperties (control, &ev);
-
- if (!BONOBO_EX (&ev)) {
- gboolean new_property;
-
- keys = bonobo_pbclient_get_keys (pb, NULL);
- new_property = FALSE;
- if (g_list_find_custom (keys, "uris", (GCompareFunc)strcmp)) {
- new_property = TRUE;
- }
- bonobo_pbclient_free_keys (keys);
-
- if (new_property) {
- /* Set the 'uris' property. */
- CORBA_sequence_CORBA_string *uri_list;
- BonoboArg *arg;
-
- uri_list = get_uri_list (window->details->target_files);
- arg = bonobo_arg_new (TC_CORBA_sequence_CORBA_string);
- arg->_value = uri_list;
- bonobo_pbclient_set_value_async (pb, "uris", arg, &ev);
- bonobo_arg_release (arg);
- } else {
- /* Set the 'URI' property. */
- BonoboArg *arg;
- char *uri;
-
- if (is_multi_file_window (window)) {
- g_warning ("Multifile property page does not support the 'uris' property");
- bonobo_object_release_unref (pb, NULL);
- bonobo_object_release_unref (control, NULL);
- return;
- }
-
- uri = nautilus_file_get_uri (get_target_file (window));
-
- arg = bonobo_arg_new (BONOBO_ARG_STRING);
- BONOBO_ARG_SET_STRING (arg, uri);
- bonobo_pbclient_set_value_async (pb, "URI", arg, &ev);
- bonobo_arg_release (arg);
- g_free (uri);
- }
-
- bonobo_object_release_unref (pb, NULL);
-
- if (!BONOBO_EX (&ev)) {
- widget = bonobo_widget_new_control_from_objref
- (control, CORBA_OBJECT_NIL);
- bonobo_object_release_unref (control, &ev);
- }
- }
- }
-
- if (widget == NULL) {
- widget = bonobo_page_error_message (data->view_name,
- error_reason);
- }
-
- gtk_container_add (GTK_CONTAINER (data->vbox), widget);
- gtk_widget_show (widget);
-
- g_free (data->view_name);
- g_free (data);
-}
-
-static gboolean
-can_handle_multiple_files (Bonobo_ServerInfo *info)
-{
- Bonobo_ActivationProperty *prop;
-
- prop = bonobo_server_info_prop_find (info, "nautilus:can_handle_multiple_files");
-
- return prop && prop->v._u.value_boolean;
-}
-
static void
-append_bonobo_pages (FMPropertiesWindow *window)
+append_extension_pages (FMPropertiesWindow *window)
{
- GList *all_components, *l;
- GList *components;
- CORBA_Environment ev;
-
- /* find all the property pages for this file */
- all_components = nautilus_mime_get_property_components_for_files
- (window->details->target_files);
+ GList *providers;
+ GList *p;
- /* filter out property pages that don't support multiple files */
- if (is_multi_file_window (window)) {
- components = NULL;
- for (l = all_components; l != NULL; l = l->next) {
- if (can_handle_multiple_files (l->data)) {
- components = g_list_prepend (components,
- l->data);
- }
- }
- components = g_list_reverse (components);
- g_list_free (all_components);
- } else {
- components = all_components;
- }
-
- CORBA_exception_init (&ev);
+ providers = nautilus_module_get_extensions_for_type (NAUTILUS_TYPE_PROPERTY_PAGE_PROVIDER);
+
+ for (p = providers; p != NULL; p = p->next) {
+ NautilusPropertyPageProvider *provider;
+ GList *pages;
+ GList *l;
- l = components;
- while (l != NULL) {
- NautilusViewIdentifier *view_id;
- Bonobo_ServerInfo *server;
- ActivationData *data;
- GtkWidget *vbox;
+ provider = NAUTILUS_PROPERTY_PAGE_PROVIDER (p->data);
+
+ pages = nautilus_property_page_provider_get_pages
+ (provider, window->details->target_files);
+
+ for (l = pages; l != NULL; l = l->next) {
+ NautilusPropertyPage *page;
+ GtkWidget *page_widget;
+ GtkWidget *label;
+
+ page = NAUTILUS_PROPERTY_PAGE (l->data);
- server = l->data;
- l = l->next;
+ g_object_get (G_OBJECT (page),
+ "page", &page_widget, "label", &label,
+ NULL);
+
+ gtk_notebook_append_page (window->details->notebook,
+ page_widget, label);
- view_id = nautilus_view_identifier_new_from_property_page (server);
- vbox = create_page_with_vbox (window->details->notebook,
- view_id->name);
+ g_object_set_data (G_OBJECT (page),
+ "is-extension-page",
+ page);
- /* just a tag...the value doesn't matter */
- g_object_set_data (G_OBJECT (vbox), "is-bonobo-page",
- vbox);
+ gtk_widget_unref (page_widget);
+ gtk_widget_unref (label);
- data = g_new (ActivationData, 1);
- data->window = window;
- data->vbox = vbox;
- data->view_name = g_strdup (view_id->name);
+ g_object_unref (page);
+ }
- bonobo_activation_activate_from_id_async (view_id->iid,
- 0, bonobo_page_activate_callback,
- data, &ev);
+ g_list_free (pages);
}
+ nautilus_module_extension_list_free (providers);
}
static gboolean
@@ -3452,7 +3290,7 @@ create_properties_window (StartupData *startup_data)
}
/* append pages from available views */
- append_bonobo_pages (window);
+ append_extension_pages (window);
/* Create box for help and close buttons. */
hbox = gtk_hbutton_box_new ();
diff --git a/src/file-manager/nautilus-directory-view-ui.xml b/src/file-manager/nautilus-directory-view-ui.xml
index 13065cb0e..dbceac809 100644
--- a/src/file-manager/nautilus-directory-view-ui.xml
+++ b/src/file-manager/nautilus-directory-view-ui.xml
@@ -203,6 +203,8 @@
accel="*Shift*Delete"
verb="Delete"/>
</placeholder>
+
+ <placeholder name="Extension Actions"/>
</submenu>
<submenu name="View">
@@ -304,10 +306,11 @@
verb="Trash"/>
<menuitem name="Delete" verb="Delete"/>
</placeholder>
+
<placeholder name="Icon Appearance Items" delimit="top">
</placeholder>
- <placeholder name="Mime Actions" delimit="none"/>
+ <placeholder name="Extension Actions" delimit="top"/>
<separator/>
<menuitem name="Properties"
diff --git a/src/file-manager/nautilus-list-view-ui.xml b/src/file-manager/nautilus-list-view-ui.xml
new file mode 100644
index 000000000..a42bc58f1
--- /dev/null
+++ b/src/file-manager/nautilus-list-view-ui.xml
@@ -0,0 +1,16 @@
+<Root>
+<commands>
+ <cmd name="Visible Columns"
+ _label="Visible _Columns..."
+ _tip="Select the columns visible in this volder"/>
+</commands>
+<menu>
+ <submenu name="View">
+ <placeholder name="View Items Placeholder">
+ <menuitem name="Visible Columns"
+ verb="Visible Columns"/>
+ </placeholder>
+
+ </submenu>
+</menu>
+</Root>
diff --git a/src/nautilus-application.c b/src/nautilus-application.c
index c303cf9ed..a5df8da7e 100644
--- a/src/nautilus-application.c
+++ b/src/nautilus-application.c
@@ -29,6 +29,7 @@
#include "nautilus-application.h"
+#include "file-manager/fm-bonobo-provider.h"
#include "file-manager/fm-desktop-icon-view.h"
#include "file-manager/fm-icon-view.h"
#include "file-manager/fm-list-view.h"
@@ -71,6 +72,7 @@
#include <libnautilus-private/nautilus-global-preferences.h>
#include <libnautilus-private/nautilus-icon-factory.h>
#include <libnautilus-private/nautilus-metafile-factory.h>
+#include <libnautilus-private/nautilus-module.h>
#include <libnautilus-private/nautilus-sound.h>
#include <libnautilus-private/nautilus-bonobo-extensions.h>
#include <libnautilus-private/nautilus-undo-manager.h>
@@ -395,6 +397,11 @@ create_starthere_link_callback (gpointer data)
static void
finish_startup (NautilusApplication *application)
{
+ /* initialize nautilus modules */
+ nautilus_module_init ();
+
+ nautilus_module_add_type (FM_TYPE_BONOBO_PROVIDER);
+
/* initialize the sound machinery */
nautilus_sound_init ();
diff --git a/src/nautilus-file-management-properties-main.c b/src/nautilus-file-management-properties-main.c
index 1ec893f39..d0d51e801 100644
--- a/src/nautilus-file-management-properties-main.c
+++ b/src/nautilus-file-management-properties-main.c
@@ -29,6 +29,7 @@
#include <libgnome/gnome-program.h>
#include <libgnomeui/gnome-ui-init.h>
+#include <libnautilus-private/nautilus-module.h>
#include <libintl.h>
@@ -58,6 +59,8 @@ main (int argc, char *argv[])
eel_preferences_init ("/apps/nautilus");
+ nautilus_module_init ();
+
nautilus_file_management_properties_dialog_show (G_CALLBACK (nautilus_file_management_properties_main_close_callback), NULL);
gtk_main ();
diff --git a/src/nautilus-file-management-properties.c b/src/nautilus-file-management-properties.c
index 2ccba328a..f90400e76 100644
--- a/src/nautilus-file-management-properties.c
+++ b/src/nautilus-file-management-properties.c
@@ -26,10 +26,14 @@
#include "nautilus-file-management-properties.h"
+#include <string.h>
#include <gtk/gtkdialog.h>
+#include <gtk/gtkmenu.h>
+#include <gtk/gtkmenuitem.h>
#include <gtk/gtkmessagedialog.h>
-#include <gtk/gtksizegroup.h>
#include <gtk/gtknotebook.h>
+#include <gtk/gtkoptionmenu.h>
+#include <gtk/gtksizegroup.h>
#include <libgnome/gnome-help.h>
#include <libgnome/gnome-i18n.h>
@@ -37,9 +41,13 @@
#include <glade/glade.h>
#include <eel/eel-gconf-extensions.h>
+#include <eel/eel-glib-extensions.h>
#include <eel/eel-preferences-glade.h>
+#include <libnautilus-private/nautilus-column-chooser.h>
+#include <libnautilus-private/nautilus-column-utilities.h>
#include <libnautilus-private/nautilus-global-preferences.h>
+#include <libnautilus-private/nautilus-module.h>
/* string enum preferences */
#define NAUTILUS_FILE_MANAGEMENT_PROPERTIES_DEFAULT_VIEW_WIDGET "default_view_optionmenu"
@@ -142,20 +150,6 @@ static const char *icon_captions_components[] = {
NULL
};
-static const char *icon_captions_values[] = {
- "size",
- "type",
- "date_modified",
- "date_accessed",
- "owner",
- "group",
- "permissions",
- "octal_permissions",
- "mime_type",
- "none",
- NULL
-};
-
static GladeXML *
nautilus_file_management_properties_dialog_create (void)
{
@@ -282,6 +276,239 @@ nautilus_file_management_properties_dialog_response_cb (GtkDialog *parent,
}
}
+static void
+columns_changed_callback (NautilusColumnChooser *chooser,
+ gpointer callback_data)
+{
+ GList *visible_columns;
+ GList *column_order;
+
+ nautilus_column_chooser_get_settings (NAUTILUS_COLUMN_CHOOSER (chooser),
+ &visible_columns,
+ &column_order);
+
+ eel_preferences_set_string_glist (NAUTILUS_PREFERENCES_LIST_VIEW_DEFAULT_VISIBLE_COLUMNS, visible_columns);
+ eel_preferences_set_string_glist (NAUTILUS_PREFERENCES_LIST_VIEW_DEFAULT_COLUMN_ORDER, column_order);
+
+ eel_g_list_free_deep (visible_columns);
+ eel_g_list_free_deep (column_order);
+}
+
+static GtkWidget *
+create_icon_caption_menu (GladeXML *xml_dialog,
+ GList *columns)
+{
+ GtkWidget *menu;
+ GList *l;
+ GtkWidget *menu_item;
+
+ menu = gtk_menu_new ();
+
+ menu_item = gtk_menu_item_new_with_label (_("None"));
+ gtk_widget_show (menu_item);
+ g_object_set_data (G_OBJECT (menu_item), "column_name", "none");
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
+
+ for (l = columns; l != NULL; l = l->next) {
+ NautilusColumn *column;
+ char *name;
+ char *label;
+
+ column = NAUTILUS_COLUMN (l->data);
+
+ g_object_get (G_OBJECT (column),
+ "name", &name, "label", &label,
+ NULL);
+
+ /* Don't show name here, it doesn't make sense */
+ if (!strcmp (name, "name")) {
+ g_free (name);
+ g_free (label);
+ continue;
+ }
+
+ menu_item = gtk_menu_item_new_with_label (label);
+ gtk_widget_show (menu_item);
+ g_object_set_data_full
+ (G_OBJECT (menu_item), "column_name",
+ g_strdup (name),
+ (GDestroyNotify)g_free);
+ g_free (name);
+ g_free (label);
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
+ }
+
+ gtk_widget_show (menu);
+
+ return menu;
+}
+
+static void
+icon_captions_changed_callback (GtkOptionMenu *option_menu,
+ gpointer user_data)
+{
+ GList *captions;
+ GladeXML *xml;
+ int i;
+
+ xml = GLADE_XML (user_data);
+
+ captions = NULL;
+
+ for (i = 0; icon_captions_components[i] != NULL; i++) {
+ GtkWidget *option_menu;
+ GtkWidget *menu;
+ GtkWidget *item;
+ char *name;
+
+ option_menu = glade_xml_get_widget
+ (GLADE_XML (xml), icon_captions_components[i]);
+ menu = gtk_option_menu_get_menu (GTK_OPTION_MENU (option_menu));
+ item = gtk_menu_get_active (GTK_MENU (menu));
+
+ name = g_object_get_data (G_OBJECT (item), "column_name");
+ captions = g_list_prepend (captions, g_strdup (name));
+ }
+ captions = g_list_reverse (captions);
+ eel_preferences_set_string_glist (NAUTILUS_PREFERENCES_ICON_VIEW_CAPTIONS, captions);
+ eel_g_list_free_deep (captions);
+}
+
+static void
+update_caption_option_menu (GladeXML *xml,
+ const char *option_menu_name,
+ const char *name)
+{
+ GtkWidget *option_menu;
+ GtkWidget *menu;
+ GList *l;
+ int i;
+
+ option_menu = glade_xml_get_widget (xml, option_menu_name);
+
+ g_signal_handlers_block_by_func
+ (option_menu,
+ G_CALLBACK (icon_captions_changed_callback),
+ xml);
+ menu = gtk_option_menu_get_menu (GTK_OPTION_MENU (option_menu));
+ for (l = GTK_MENU_SHELL (menu)->children, i = 0;
+ l != NULL;
+ l = l->next, i++) {
+ char *item_name;
+ item_name = g_object_get_data (G_OBJECT (l->data),
+ "column_name");
+ if (!strcmp (name, item_name)) {
+ gtk_option_menu_set_history (GTK_OPTION_MENU (option_menu), i);
+ break;
+ }
+ }
+
+ g_signal_handlers_unblock_by_func
+ (option_menu,
+ G_CALLBACK (icon_captions_changed_callback),
+ xml);
+}
+
+static void
+update_icon_captions_from_gconf (GladeXML *xml)
+{
+ GList *captions;
+ int i;
+ GList *l;
+
+
+ captions = eel_preferences_get_string_glist (NAUTILUS_PREFERENCES_ICON_VIEW_CAPTIONS);
+
+ for (l = captions, i = 0;
+ captions != NULL && icon_captions_components[i] != NULL;
+ l = l->next, i++) {
+ update_caption_option_menu (xml,
+ icon_captions_components[i],
+ (char *)l->data);
+ }
+ eel_g_list_free_deep (captions);
+}
+
+static void
+nautilus_file_management_properties_dialog_setup_icon_caption_page (GladeXML *xml_dialog)
+{
+ GList *columns;
+ int i;
+ gboolean writable;
+
+ writable = eel_preferences_key_is_writable (NAUTILUS_PREFERENCES_ICON_VIEW_CAPTIONS);
+
+ columns = nautilus_get_all_columns ();
+
+ for (i = 0; icon_captions_components[i] != NULL; i++) {
+ GtkWidget *menu;
+ GtkWidget *option_menu;
+
+ option_menu = glade_xml_get_widget (xml_dialog,
+ icon_captions_components[i]);
+
+ menu = create_icon_caption_menu (xml_dialog, columns);
+ gtk_option_menu_set_menu (GTK_OPTION_MENU (option_menu), menu);
+
+ gtk_widget_set_sensitive (GTK_WIDGET (option_menu), writable);
+
+ g_signal_connect (option_menu, "changed",
+ G_CALLBACK (icon_captions_changed_callback),
+ xml_dialog);
+ }
+
+ nautilus_column_list_free (columns);
+
+ update_icon_captions_from_gconf (xml_dialog);
+}
+
+static void
+set_columns_from_gconf (NautilusColumnChooser *chooser)
+{
+ GList *visible_columns;
+ GList *column_order;
+
+ visible_columns = eel_preferences_get_string_glist (NAUTILUS_PREFERENCES_LIST_VIEW_DEFAULT_VISIBLE_COLUMNS);
+ column_order = eel_preferences_get_string_glist (NAUTILUS_PREFERENCES_LIST_VIEW_DEFAULT_COLUMN_ORDER);
+
+ nautilus_column_chooser_set_settings (NAUTILUS_COLUMN_CHOOSER (chooser),
+ visible_columns,
+ column_order);
+
+
+ eel_g_list_free_deep (visible_columns);
+ eel_g_list_free_deep (column_order);
+}
+
+static void
+use_default_callback (NautilusColumnChooser *chooser,
+ gpointer user_data)
+{
+ eel_preferences_unset (NAUTILUS_PREFERENCES_LIST_VIEW_DEFAULT_VISIBLE_COLUMNS);
+ eel_preferences_unset (NAUTILUS_PREFERENCES_LIST_VIEW_DEFAULT_COLUMN_ORDER);
+ set_columns_from_gconf (chooser);
+}
+
+static void
+nautilus_file_management_properties_dialog_setup_list_column_page (GladeXML *xml_dialog)
+{
+ GtkWidget *chooser;
+ GtkWidget *box;
+
+ chooser = nautilus_column_chooser_new ();
+ g_signal_connect (chooser, "changed",
+ G_CALLBACK (columns_changed_callback), chooser);
+ g_signal_connect (chooser, "use_default",
+ G_CALLBACK (use_default_callback), chooser);
+
+ set_columns_from_gconf (NAUTILUS_COLUMN_CHOOSER (chooser));
+
+ gtk_widget_show (chooser);
+ box = glade_xml_get_widget (xml_dialog, "list_columns_vbox");
+
+ gtk_box_pack_start (GTK_BOX (box), chooser, TRUE, TRUE, 0);
+}
+
static void
nautilus_file_management_properties_dialog_setup (GladeXML *xml_dialog, GtkWindow *window)
{
@@ -333,6 +560,7 @@ nautilus_file_management_properties_dialog_setup (GladeXML *xml_dialog, GtkWindo
eel_preferences_glade_connect_bool (xml_dialog,
NAUTILUS_FILE_MANAGEMENT_PROPERTIES_TREE_VIEW_FOLDERS_WIDGET,
NAUTILUS_PREFERENCES_TREE_SHOW_ONLY_DIRECTORIES);
+
eel_preferences_glade_connect_string_enum_option_menu (xml_dialog,
NAUTILUS_FILE_MANAGEMENT_PROPERTIES_DEFAULT_VIEW_WIDGET,
NAUTILUS_PREFERENCES_DEFAULT_FOLDER_VIEWER,
@@ -378,17 +606,15 @@ nautilus_file_management_properties_dialog_setup (GladeXML *xml_dialog, GtkWindo
NAUTILUS_PREFERENCES_EXECUTABLE_TEXT_ACTIVATION,
executable_text_values);
- eel_preferences_glade_connect_list_enum (xml_dialog,
- icon_captions_components,
- NAUTILUS_PREFERENCES_ICON_VIEW_CAPTIONS,
- icon_captions_values);
-
-
eel_preferences_glade_connect_int_enum (xml_dialog,
NAUTILUS_FILE_MANAGEMENT_PROPERTIES_THUMBNAIL_LIMIT_WIDGET,
NAUTILUS_PREFERENCES_IMAGE_FILE_THUMBNAIL_LIMIT,
thumbnail_limit_values);
+
+ nautilus_file_management_properties_dialog_setup_icon_caption_page (xml_dialog);
+ nautilus_file_management_properties_dialog_setup_list_column_page (xml_dialog);
+
/* UI callbacks */
dialog = glade_xml_get_widget (xml_dialog, "file_management_dialog");
g_signal_connect (G_OBJECT (dialog), "response",
diff --git a/src/nautilus-file-management-properties.glade b/src/nautilus-file-management-properties.glade
index 411834bad..f243f2260 100644
--- a/src/nautilus-file-management-properties.glade
+++ b/src/nautilus-file-management-properties.glade
@@ -1830,6 +1830,144 @@
</child>
<child>
+ <widget class="GtkVBox" id="vbox29">
+ <property name="border_width">12</property>
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">18</property>
+
+ <child>
+ <widget class="GtkVBox" id="vbox30">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">6</property>
+
+ <child>
+ <widget class="GtkLabel" id="label31">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;span weight=&quot;bold&quot;&gt;List Columns&lt;/span&gt;</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">True</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkHBox" id="hbox31">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkLabel" id="label32">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes"> </property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkVBox" id="list_columns_vbox">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">6</property>
+
+ <child>
+ <widget class="GtkLabel" id="label33">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Choose the order of information to appear in the list view.</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">True</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <placeholder/>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="tab_expand">False</property>
+ <property name="tab_fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label30">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">List Columns</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="type">tab</property>
+ </packing>
+ </child>
+
+ <child>
<widget class="GtkVBox" id="vbox9">
<property name="border_width">12</property>
<property name="visible">True</property>
diff --git a/src/nautilus-navigation-window-ui.xml b/src/nautilus-navigation-window-ui.xml
index 71f5ecf01..2fba4df0c 100644
--- a/src/nautilus-navigation-window-ui.xml
+++ b/src/nautilus-navigation-window-ui.xml
@@ -167,14 +167,10 @@
type="toggle"
pixtype="stock" pixname="Search"
verb="Toggle Find Mode"/>
- <toolitem name="Burn CD"
- _label="Write to CD"
- priority="1"
- pixtype="stock" pixname="gtk-cdrom"
- verb="Burn CD"/>
-
- <placeholder name="Extra Buttons Placeholder" delimit="top"/>
+ <placeholder name="Extra Buttons Placeholder" delimit="top">
+ <placeholder name="Extension Actions"/>
+ </placeholder>
<control name="ThrobberWrapper" behavior="pack-end"/>
</dockitem>
diff --git a/src/nautilus-navigation-window.c b/src/nautilus-navigation-window.c
index c7c55a0f9..d89f1ca72 100644
--- a/src/nautilus-navigation-window.c
+++ b/src/nautilus-navigation-window.c
@@ -852,6 +852,19 @@ real_merge_menus (NautilusWindow *nautilus_window)
}
static void
+real_merge_menus_2 (NautilusWindow *nautilus_window)
+{
+ NautilusNavigationWindow *window;
+
+ EEL_CALL_PARENT (NAUTILUS_WINDOW_CLASS,
+ merge_menus_2, (nautilus_window));
+
+ window = NAUTILUS_NAVIGATION_WINDOW (nautilus_window);
+
+ nautilus_navigation_window_initialize_menus_part_2 (window);
+}
+
+static void
zoom_level_changed_callback (NautilusViewFrame *view,
NautilusNavigationWindow *window)
{
@@ -1480,6 +1493,7 @@ nautilus_navigation_window_class_init (NautilusNavigationWindowClass *class)
GTK_WIDGET_CLASS (class)->show = nautilus_navigation_window_show;
GTK_WIDGET_CLASS (class)->unrealize = nautilus_navigation_window_unrealize;
NAUTILUS_WINDOW_CLASS (class)->merge_menus = real_merge_menus;
+ NAUTILUS_WINDOW_CLASS (class)->merge_menus_2 = real_merge_menus_2;
NAUTILUS_WINDOW_CLASS (class)->load_view_as_menu = real_load_view_as_menu;
NAUTILUS_WINDOW_CLASS (class)->set_content_view_widget = real_set_content_view_widget;
NAUTILUS_WINDOW_CLASS (class)->set_throbber_active = real_set_throbber_active;
diff --git a/src/nautilus-shell-ui.xml b/src/nautilus-shell-ui.xml
index 68a28e95a..6b95539f2 100644
--- a/src/nautilus-shell-ui.xml
+++ b/src/nautilus-shell-ui.xml
@@ -25,9 +25,6 @@
<cmd name="Clear" sensitive="0"/>
<cmd name="Reload"
_tip="Display the latest contents of the current location"/>
- <cmd name="Burn CD"
- _label="_Write to CD"
- _tip="Write contents to a CD"/>
<cmd name="Go to Burn CD"
_label="_CD Creator"
_tip="Go to Empty CD folder"/>
@@ -58,12 +55,8 @@
<placeholder name="General Status Placeholder" delimit="top"/>
<placeholder name="File Items Placeholder" delimit="top"/>
-
- <placeholder name="Global File Items Placeholder" delimit="top">
- <menuitem name="Burn CD"
- verb="Burn CD"/>
- </placeholder>
-
+ <placeholder name="Global File Items Placeholder" delimit="top"/>
+ <placeholder name="Extension Actions" delimit="top"/>
<separator/>
<placeholder name="Close Items Placeholder"/>
@@ -124,6 +117,7 @@
<placeholder name="Edit Items Placeholder" delimit="top"/>
<placeholder name="Global Edit Items Placeholder" delimit="none"/>
+ <placeholder name="Extension Actions" delimit="top"/>
<separator/>
<menuitem name="Backgrounds and Emblems"
@@ -226,6 +220,7 @@
</placeholder>
<placeholder name="New Object Items" delimit="none">
</placeholder>
+ <placeholder name="Extension Actions" delimit="top"/>
</placeholder>
<placeholder name="Zoom Items" delimit="top">
<menuitem name="Zoom In"
diff --git a/src/nautilus-window-manage-views.c b/src/nautilus-window-manage-views.c
index edc2e318f..ad285a50c 100644
--- a/src/nautilus-window-manage-views.c
+++ b/src/nautilus-window-manage-views.c
@@ -379,16 +379,6 @@ update_up_button (NautilusWindow *window)
}
static void
-update_burn_cd_items (NautilusWindow *window)
-{
- gboolean show_burn_cd;
-
- show_burn_cd = eel_istr_has_prefix (window->details->location, "burn:");
-
- nautilus_window_allow_burn_cd (window, show_burn_cd);
-}
-
-static void
viewed_file_changed_callback (NautilusFile *file,
NautilusWindow *window)
{
@@ -548,11 +538,11 @@ update_for_new_location (NautilusWindow *window)
/* Check if we can go up. */
update_up_button (window);
- /* Check if we can go up. */
- update_burn_cd_items (window);
-
/* Set up the content view menu for this new location. */
nautilus_window_load_view_as_menus (window);
+
+ /* Load menus from nautilus extensions for this location */
+ nautilus_window_load_extension_menus (window);
#if !NEW_UI_COMPLETE
if (NAUTILUS_IS_NAVIGATION_WINDOW (window)) {
@@ -563,6 +553,8 @@ update_for_new_location (NautilusWindow *window)
/* Change the location bar to match the current location. */
nautilus_navigation_bar_set_location (NAUTILUS_NAVIGATION_BAR (NAUTILUS_NAVIGATION_WINDOW (window)->navigation_bar),
window->details->location);
+
+ nautilus_navigation_window_load_extension_toolbar_items (NAUTILUS_NAVIGATION_WINDOW (window));
}
/* Notify the information panel of the location change. */
diff --git a/src/nautilus-window-menus.c b/src/nautilus-window-menus.c
index 577ae5059..56956690d 100644
--- a/src/nautilus-window-menus.c
+++ b/src/nautilus-window-menus.c
@@ -57,9 +57,11 @@
#include <libgnomevfs/gnome-vfs-file-info.h>
#include <libgnomevfs/gnome-vfs-utils.h>
#include <libgnomevfs/gnome-vfs-ops.h>
+#include <libnautilus-extension/nautilus-menu-provider.h>
#include <libnautilus-private/nautilus-bonobo-extensions.h>
#include <libnautilus-private/nautilus-file-utilities.h>
#include <libnautilus-private/nautilus-icon-factory.h>
+#include <libnautilus-private/nautilus-module.h>
#include <libnautilus-private/nautilus-undo-manager.h>
#include <libnautilus/nautilus-bonobo-ui.h>
@@ -78,6 +80,9 @@
#define MENU_PATH_SHOW_HIDE_LOCATION_BAR "/menu/View/Show Hide Placeholder/Show Hide Location Bar"
#define MENU_PATH_SHOW_HIDE_STATUS_BAR "/menu/View/Show Hide Placeholder/Show Hide Statusbar"
+#define MENU_PATH_EXTENSION_ACTIONS "/menu/File/Extension Actions"
+#define POPUP_PATH_EXTENSION_ACTIONS "/popups/background/Before Zoom Items/Extension Actions"
+
#define COMMAND_PATH_CLOSE_WINDOW "/commands/Close"
#define COMMAND_SHOW_HIDE_SIDEBAR "/commands/Show Hide Sidebar"
#define COMMAND_SHOW_HIDE_TOOLBAR "/commands/Show Hide Toolbar"
@@ -250,14 +255,6 @@ file_menu_close_window_callback (BonoboUIComponent *component,
}
static void
-file_menu_burn_cd_callback (BonoboUIComponent *component,
- gpointer user_data,
- const char *verb)
-{
- nautilus_window_launch_cd_burner (NAUTILUS_WINDOW (user_data));
-}
-
-static void
connect_to_server_callback (BonoboUIComponent *component,
gpointer user_data,
const char *verb)
@@ -664,7 +661,6 @@ nautilus_window_initialize_menus_part_1 (NautilusWindow *window)
BonoboUIVerb verbs [] = {
BONOBO_UI_VERB ("New Window", file_menu_new_window_callback),
BONOBO_UI_VERB ("Close", file_menu_close_window_callback),
- BONOBO_UI_VERB ("Burn CD", file_menu_burn_cd_callback),
BONOBO_UI_VERB ("Connect to Server", connect_to_server_callback),
#ifdef HAVE_MEDUSA
BONOBO_UI_VERB ("Find", file_menu_find_callback),
@@ -734,3 +730,65 @@ nautilus_window_initialize_menus_part_1 (NautilusWindow *window)
nautilus_window_ui_thaw (window);
}
+static GList *
+get_extension_menus (NautilusWindow *window)
+{
+ GList *providers;
+ GList *items;
+ GList *l;
+
+ providers = nautilus_module_get_extensions_for_type (NAUTILUS_TYPE_MENU_PROVIDER);
+ items = NULL;
+
+ for (l = providers; l != NULL; l = l->next) {
+ NautilusMenuProvider *provider;
+ GList *file_items;
+
+ provider = NAUTILUS_MENU_PROVIDER (l->data);
+ file_items = nautilus_menu_provider_get_background_items (provider,
+ GTK_WIDGET (window),
+ window->details->viewed_file);
+ items = g_list_concat (items, file_items);
+ }
+
+ nautilus_module_extension_list_free (providers);
+
+ return items;
+}
+
+void
+nautilus_window_load_extension_menus (NautilusWindow *window)
+{
+ GList *items;
+ GList *l;
+
+ nautilus_bonobo_remove_menu_items_and_commands
+ (window->details->shell_ui, POPUP_PATH_EXTENSION_ACTIONS);
+ nautilus_bonobo_remove_menu_items_and_commands
+ (window->details->shell_ui, MENU_PATH_EXTENSION_ACTIONS);
+
+ items = get_extension_menus (window);
+
+ for (l = items; l != NULL; l = l->next) {
+ NautilusMenuItem *item;
+
+ item = NAUTILUS_MENU_ITEM (l->data);
+
+ nautilus_bonobo_add_extension_item_command
+ (window->details->shell_ui, item);
+
+ nautilus_bonobo_add_extension_item
+ (window->details->shell_ui,
+ MENU_PATH_EXTENSION_ACTIONS,
+ item);
+
+ nautilus_bonobo_add_extension_item
+ (window->details->shell_ui,
+ POPUP_PATH_EXTENSION_ACTIONS,
+ item);
+
+ g_object_unref (item);
+ }
+
+ g_list_free (items);
+}
diff --git a/src/nautilus-window-private.h b/src/nautilus-window-private.h
index 5222da470..e451c7686 100644
--- a/src/nautilus-window-private.h
+++ b/src/nautilus-window-private.h
@@ -151,6 +151,7 @@ typedef void (*NautilusBookmarkFailedCallback) (NautilusWindow *window,
void nautilus_window_set_status (NautilusWindow *window,
const char *status);
void nautilus_window_load_view_as_menus (NautilusWindow *window);
+void nautilus_window_load_extension_menus (NautilusWindow *window);
void nautilus_window_initialize_menus_part_1 (NautilusWindow *window);
void nautilus_window_initialize_menus_part_2 (NautilusWindow *window);
void nautilus_menus_append_bookmark_to_menu (NautilusWindow *window,
@@ -203,6 +204,7 @@ void nautilus_navigation_window_update_show_hide_menu_items
/* Navigation window toolbar */
void nautilus_navigation_window_activate_throbber (NautilusNavigationWindow *window);
void nautilus_navigation_window_initialize_toolbars (NautilusNavigationWindow *window);
+void nautilus_navigation_window_load_extension_toolbar_items (NautilusNavigationWindow *window);
void nautilus_navigation_window_set_throbber_active (NautilusNavigationWindow *window,
gboolean active);
void nautilus_navigation_window_go_back (NautilusNavigationWindow *window);
diff --git a/src/nautilus-window-toolbars.c b/src/nautilus-window-toolbars.c
index dae2b77ac..edac4c6ad 100644
--- a/src/nautilus-window-toolbars.c
+++ b/src/nautilus-window-toolbars.c
@@ -47,10 +47,12 @@
#include <gdk/gdkkeysyms.h>
#include <libgnome/gnome-i18n.h>
#include <libgnomeui/gnome-popup-menu.h>
+#include <libnautilus-extension/nautilus-menu-provider.h>
#include <libnautilus-private/nautilus-bonobo-extensions.h>
#include <libnautilus-private/nautilus-bookmark.h>
#include <libnautilus-private/nautilus-file-utilities.h>
#include <libnautilus-private/nautilus-global-preferences.h>
+#include <libnautilus-private/nautilus-module.h>
#include <libnautilus-private/nautilus-theme.h>
/* FIXME bugzilla.gnome.org 41243:
@@ -59,6 +61,8 @@
*/
#include "nautilus-desktop-window.h"
+#define TOOLBAR_PATH_EXTENSION_ACTIONS "/Toolbar/Extra Buttons Placeholder/Extension Actions"
+
enum {
TOOLBAR_ITEM_STYLE_PROP,
TOOLBAR_ITEM_ORIENTATION_PROP
@@ -366,3 +370,61 @@ nautilus_navigation_window_initialize_toolbars (NautilusNavigationWindow *window
nautilus_window_ui_thaw (NAUTILUS_WINDOW (window));
}
+
+static GList *
+get_extension_toolbar_items (NautilusNavigationWindow *window)
+{
+ GList *items;
+ GList *providers;
+ GList *l;
+
+ providers = nautilus_module_get_extensions_for_type (NAUTILUS_TYPE_MENU_PROVIDER);
+ items = NULL;
+
+ for (l = providers; l != NULL; l = l->next) {
+ NautilusMenuProvider *provider;
+ GList *file_items;
+
+ provider = NAUTILUS_MENU_PROVIDER (l->data);
+ file_items = nautilus_menu_provider_get_toolbar_items
+ (provider,
+ GTK_WIDGET (window),
+ NAUTILUS_WINDOW (window)->details->viewed_file);
+ items = g_list_concat (items, file_items);
+ }
+
+ nautilus_module_extension_list_free (providers);
+
+ return items;
+}
+
+void
+nautilus_navigation_window_load_extension_toolbar_items (NautilusNavigationWindow *window)
+{
+ GList *items;
+ GList *l;
+
+ nautilus_bonobo_remove_menu_items_and_commands
+ (NAUTILUS_WINDOW (window)->details->shell_ui,
+ TOOLBAR_PATH_EXTENSION_ACTIONS);
+
+ items = get_extension_toolbar_items (window);
+
+ for (l = items; l != NULL; l = l->next) {
+ NautilusMenuItem *item;
+
+ item = NAUTILUS_MENU_ITEM (l->data);
+
+ nautilus_bonobo_add_extension_item_command
+ (NAUTILUS_WINDOW (window)->details->shell_ui, item);
+
+ nautilus_bonobo_add_extension_toolbar_item
+ (NAUTILUS_WINDOW (window)->details->shell_ui,
+ TOOLBAR_PATH_EXTENSION_ACTIONS,
+ item);
+
+ g_object_unref (item);
+ }
+
+ g_list_free (items);
+}
diff --git a/src/nautilus-window.c b/src/nautilus-window.c
index 9f491465a..bdb44b00a 100644
--- a/src/nautilus-window.c
+++ b/src/nautilus-window.c
@@ -222,12 +222,8 @@ ui_idle_handler (gpointer data)
old_updating_bonobo_state = window->details->updating_bonobo_state;
if (window->details->ui_pending_initialize_menus_part_2) {
-#if !NEW_UI_COMPLETE
- if (NAUTILUS_IS_NAVIGATION_WINDOW (window)) {
- nautilus_navigation_window_initialize_menus_part_2 (NAUTILUS_NAVIGATION_WINDOW (window));
- }
-#endif
- window->details->ui_pending_initialize_menus_part_2 = FALSE;
+ EEL_CALL_METHOD (NAUTILUS_WINDOW_CLASS, window,
+ merge_menus_2, (window));
}
if (window->details->ui_is_frozen) {
@@ -433,19 +429,6 @@ nautilus_window_allow_reload (NautilusWindow *window, gboolean allow)
}
void
-nautilus_window_allow_burn_cd (NautilusWindow *window, gboolean allow)
-{
- g_return_if_fail (NAUTILUS_IS_WINDOW (window));
-
- nautilus_window_ui_freeze (window);
-
- nautilus_bonobo_set_hidden (window->details->shell_ui,
- NAUTILUS_COMMAND_BURN_CD, !allow);
-
- nautilus_window_ui_thaw (window);
-}
-
-void
nautilus_window_go_home (NautilusWindow *window)
{
char *home_uri;
@@ -470,26 +453,6 @@ nautilus_window_go_home (NautilusWindow *window)
}
void
-nautilus_window_launch_cd_burner (NautilusWindow *window)
-{
- GError *error;
- char *argv[] = { "nautilus-cd-burner", NULL};
-
- error = NULL;
- if (!g_spawn_async (NULL,
- argv, NULL,
- G_SPAWN_SEARCH_PATH,
- NULL, NULL,
- NULL,
- &error)) {
- eel_show_error_dialog (_("Unable to launch the cd burner application."), error->message,
- _("Can't Launch CD Burner"),
- GTK_WINDOW (window));
- g_error_free (error);
- }
-}
-
-void
nautilus_window_prompt_for_location (NautilusWindow *window)
{
g_assert (NAUTILUS_IS_WINDOW (window));
@@ -622,6 +585,12 @@ real_merge_menus (NautilusWindow *window)
}
static void
+real_merge_menus_2 (NautilusWindow *window)
+{
+ window->details->ui_pending_initialize_menus_part_2 = FALSE;
+}
+
+static void
nautilus_window_constructed (NautilusWindow *window)
{
nautilus_window_ui_freeze (window);
@@ -632,7 +601,6 @@ nautilus_window_constructed (NautilusWindow *window)
merge_menus, (window));
nautilus_window_allow_stop (window, FALSE);
- nautilus_window_allow_burn_cd (window, FALSE);
/* Set up undo manager */
nautilus_undo_manager_attach (window->application->undo_manager, G_OBJECT (window));
@@ -1629,6 +1597,7 @@ nautilus_window_class_init (NautilusWindowClass *class)
class->get_title = real_get_title;
class->set_title = real_set_title;
class->merge_menus = real_merge_menus;
+ class->merge_menus_2 = real_merge_menus_2;
class->set_content_view_widget = real_set_content_view_widget;
class->load_view_as_menu = real_load_view_as_menu;
diff --git a/src/nautilus-window.h b/src/nautilus-window.h
index d7e92c1a7..cd4791600 100644
--- a/src/nautilus-window.h
+++ b/src/nautilus-window.h
@@ -69,6 +69,7 @@ typedef struct {
void (* set_title) (NautilusWindow *window, const char *title);
void (* merge_menus) (NautilusWindow *window);
+ void (* merge_menus_2) (NautilusWindow *window);
void (* load_view_as_menu) (NautilusWindow *window);
void (* set_content_view_widget) (NautilusWindow *window,
NautilusViewFrame *frame);