Re: pluggable context menus ...



Hi,

I've redone this now so that it should be easy to translate the menu
items.  That's the good news.  The bad news is, it's not very flexible
as far as placement in the menu goes.  It should be possible to put
stuff in a submenu still, but it won't be possible for each component to
decide in which submenu to go in, unless we do some more hackery.  Is
this needed?  What was the outcome of the usability discussion about
this?

Thanks,
James
Index: components/image_properties/Makefile.am
===================================================================
RCS file: /cvs/gnome/nautilus/components/image_properties/Makefile.am,v
retrieving revision 1.1
diff -u -r1.1 Makefile.am
--- components/image_properties/Makefile.am	24 Oct 2002 15:54:32 -0000	1.1
+++ components/image_properties/Makefile.am	31 Oct 2002 02:36:43 -0000
@@ -35,5 +35,8 @@
 	sed -e "s|\ BONOBODIR\@|$(bonobodir)|" $< > $@
 @INTLTOOL_SERVER_RULE@
 
+#uidir = $(datadir)/gnome-2.0/ui
+#ui_DATA = nautilus-image-properties-view.xml
+
 EXTRA_DIST = $(server_in_files)
 CLEANFILES = $(server_DATA) $(server_DATA).in
Index: components/image_properties/Nautilus_View_image_properties.server.in.in
===================================================================
RCS file: /cvs/gnome/nautilus/components/image_properties/Nautilus_View_image_properties.server.in.in,v
retrieving revision 1.1
diff -u -r1.1 Nautilus_View_image_properties.server.in.in
--- components/image_properties/Nautilus_View_image_properties.server.in.in	24 Oct 2002 15:54:32 -0000	1.1
+++ components/image_properties/Nautilus_View_image_properties.server.in.in	31 Oct 2002 02:36:43 -0000
@@ -5,6 +5,7 @@
 	<oaf_attribute name="repo_ids" type="stringv">
 		<item value="IDL:Bonobo/Unknown:1.0"/>
 		<item value="IDL:Bonobo/Control:1.0"/>
+		<item value="IDL:Bonobo/Listener:1.0"/>
 		<item value="IDL:Nautilus/View:1.0"/>
 	</oaf_attribute>
 	<oaf_attribute name="name" type="string" _value="Nautilus Image Properties view"/>
@@ -25,6 +26,9 @@
 	</oaf_attribute>
 	<oaf_attribute name="nautilus:view_as_name" type="string" _value="Image"/>
 	<oaf_attribute name="nautilus:property_page_name" type="string" _value="Image"/>
+	<oaf_attribute name="nautilusverb:DoRotate" type="string" _value="Rotate Image..."/>
+	<oaf_attribute name="nautilusverb:DoResize" type="string" _value="Resize Image..."/>
+	<oaf_attribute name="nautilus:context_menu_handler" type="boolean" value="true"/>
 </oaf_server>
 
 </oaf_info>
Index: components/image_properties/nautilus-image-properties-view.c
===================================================================
RCS file: /cvs/gnome/nautilus/components/image_properties/nautilus-image-properties-view.c,v
retrieving revision 1.1
diff -u -r1.1 nautilus-image-properties-view.c
--- components/image_properties/nautilus-image-properties-view.c	24 Oct 2002 15:54:32 -0000	1.1
+++ components/image_properties/nautilus-image-properties-view.c	31 Oct 2002 02:36:44 -0000
@@ -26,6 +26,7 @@
 
 #include <gtk/gtkvbox.h>
 #include <gtk/gtklabel.h>
+#include <gtk/gtkmessagedialog.h>
 #include <libgnome/gnome-macros.h>
 #include <libgnome/gnome-i18n.h>
 #include <libgnomevfs/gnome-vfs-async-ops.h>
@@ -220,6 +221,39 @@
 }
 
 static void
+listener_callback (BonoboListener *listener,
+		   const char *event_name,
+		   const CORBA_any *any,
+		   CORBA_Environment *ev,
+		   gpointer user_data)
+{
+	GtkWidget *dialog;
+	const BonoboArg *arg;
+	char *str;
+
+	arg = any;
+	
+	str = BONOBO_ARG_GET_STRING (arg);
+	dialog = gtk_message_dialog_new (NULL, 0, GTK_MESSAGE_INFO,
+					 GTK_BUTTONS_OK,
+					 "Got event %s for %s", event_name,
+					 str);
+	g_signal_connect (dialog, "response",
+			  G_CALLBACK (gtk_widget_destroy), NULL);
+	gtk_widget_show (dialog);
+}
+
+static void
+setup_listener (NautilusImagePropertiesView *view)
+{
+	BonoboListener *listener;
+
+	listener = bonobo_listener_new (listener_callback, view);
+	bonobo_object_add_interface (BONOBO_OBJECT (view),
+				     BONOBO_OBJECT (listener));
+}
+
+static void
 nautilus_image_properties_view_instance_init (NautilusImagePropertiesView *view)
 {
 	view->details = g_new0 (NautilusImagePropertiesViewDetails, 1);
@@ -234,6 +268,7 @@
 	gtk_widget_show_all (view->details->vbox);
 	
 	nautilus_view_construct (NAUTILUS_VIEW (view), view->details->vbox);
+	setup_listener (view);
 	
 	g_signal_connect (view, "load_location",
 			  G_CALLBACK (image_load_location_callback), NULL);
Index: components/notes/Makefile.am
===================================================================
RCS file: /cvs/gnome/nautilus/components/notes/Makefile.am,v
retrieving revision 1.30
diff -u -r1.30 Makefile.am
--- components/notes/Makefile.am	20 Sep 2002 08:01:12 -0000	1.30
+++ components/notes/Makefile.am	31 Oct 2002 02:36:44 -0000
@@ -26,8 +26,11 @@
 serverdir = $(libdir)/bonobo/servers
 server_DATA = $(server_in_files:.server.in.in=.server)
 $(server_in_files:.server.in.in=.server.in): $(server_in_files)
-	sed -e "s|\ BONOBODIR\@|$(bonobodir)|" $< > $@
+	sed -e "s|\ BONOBODIR\@|$(bonobodir)|" -e "s|\ UIDIR\@|$(datadir)/gnome-2.0/ui|" $< > $@
 @INTLTOOL_SERVER_RULE@
+
+uidir = $(datadir)/gnome-2.0/ui
+ui_DATA = nautilus-notes-view.xml
 
 EXTRA_DIST= $(server_in_files)
 CLEANFILES = $(server_DATA) $(server_DATA).in
Index: components/notes/Nautilus_View_notes.server.in.in
===================================================================
RCS file: /cvs/gnome/nautilus/components/notes/Nautilus_View_notes.server.in.in,v
retrieving revision 1.13
diff -u -r1.13 Nautilus_View_notes.server.in.in
--- components/notes/Nautilus_View_notes.server.in.in	25 Oct 2002 17:38:32 -0000	1.13
+++ components/notes/Nautilus_View_notes.server.in.in	31 Oct 2002 02:36:44 -0000
@@ -5,6 +5,7 @@
 	<oaf_attribute name="repo_ids" type="stringv">
 		<item value="IDL:Bonobo/Unknown:1.0"/>
 		<item value="IDL:Bonobo/Control:1.0"/>
+		<item value="IDL:Bonobo/Listener:1.0"/>
 		<item value="IDL:Nautilus/View:1.0"/>
 	</oaf_attribute>
 	<oaf_attribute name="description" type="string" _value="Nodes side pane for Nautilus"/>
@@ -18,6 +19,8 @@
 	</oaf_attribute>
 	<oaf_attribute name="nautilus:view_as_name" type="string" _value="Notes"/>
 	<oaf_attribute name="nautilus:property_page_name" type="string" _value="Notes"/>
+	<oaf_attribute name="nautilusverb:ShowNotes" type="string" _value="Show Notes..."/>
+	<oaf_attribute name="nautilus:context_menu_handler" type="boolean" value="true"/>
 </oaf_server>
 
 </oaf_info>
Index: components/notes/nautilus-notes.c
===================================================================
RCS file: /cvs/gnome/nautilus/components/notes/nautilus-notes.c,v
retrieving revision 1.86
diff -u -r1.86 nautilus-notes.c
--- components/notes/nautilus-notes.c	19 Jul 2002 20:27:27 -0000	1.86
+++ components/notes/nautilus-notes.c	31 Oct 2002 02:36:45 -0000
@@ -37,6 +37,7 @@
 #include <gtk/gtktextbuffer.h>
 #include <gtk/gtktextview.h>
 #include <gtk/gtkvbox.h>
+#include <gtk/gtkmessagedialog.h>
 #include <bonobo/bonobo-property-bag.h>
 #include <libnautilus-private/nautilus-file-attributes.h>
 #include <libnautilus-private/nautilus-file.h>
@@ -350,6 +351,39 @@
 	return NULL;
 }
 
+static void
+listener_callback (BonoboListener *listener,
+		   const char *event_name,
+		   const CORBA_any *any,
+		   CORBA_Environment *ev,
+		   gpointer user_data)
+{
+	GtkWidget *dialog;
+	const BonoboArg *arg;
+	char *str;
+
+	arg = any;
+	
+	str = BONOBO_ARG_GET_STRING (arg);
+
+	dialog = gtk_message_dialog_new (NULL, 0, GTK_MESSAGE_INFO,
+					 GTK_BUTTONS_OK,
+					 "Got event %s for %s", event_name,
+					 str);
+	g_signal_connect (dialog, "response",
+			  G_CALLBACK (gtk_widget_destroy), NULL);
+	gtk_widget_show (dialog);
+}
+
+static void
+setup_listener (BonoboObject *obj)
+{
+	BonoboListener *listener;
+
+	listener = bonobo_listener_new (listener_callback, obj);
+	bonobo_object_add_interface (obj, BONOBO_OBJECT (listener));
+}
+
 static BonoboObject *
 make_notes_view ()
 {
@@ -385,6 +419,7 @@
 	/* Create CORBA object. */
         notes->view = nautilus_view_new (vbox);
         g_signal_connect (notes->view, "destroy", G_CALLBACK (do_destroy), notes);
+	setup_listener (BONOBO_OBJECT (notes->view));
 
 	/* allocate a property bag to reflect the TAB_IMAGE property */
 	notes->property_bag = bonobo_property_bag_new (get_bonobo_properties,  set_bonobo_properties, notes);
Index: libnautilus-private/nautilus-mime-actions.c
===================================================================
RCS file: /cvs/gnome/nautilus/libnautilus-private/nautilus-mime-actions.c,v
retrieving revision 1.102
diff -u -r1.102 nautilus-mime-actions.c
--- libnautilus-private/nautilus-mime-actions.c	25 Oct 2002 17:38:32 -0000	1.102
+++ libnautilus-private/nautilus-mime-actions.c	31 Oct 2002 02:36:46 -0000
@@ -54,7 +54,8 @@
 								  gboolean                  ignore_content_mime_types,
 								  GList                    *explicit_iids,
 								  char                    **extra_sort_criteria,
-								  char                     *extra_requirements);
+								  char                     *extra_requirements,
+								  gboolean                  must_be_view);
 static GList      *str_list_difference                           (GList                    *a,
 								  GList                    *b);
 static char      **strv_concat                                   (char                    **a,
@@ -393,13 +394,13 @@
 	if (metadata_default) {
 		extra_requirements = g_strconcat ("iid == '", default_component_string, "'", NULL);
 		info_list = nautilus_do_component_query (mime_type, uri_scheme, item_mime_types, TRUE,
-							 explicit_iids, sort_conditions, extra_requirements);
+							 explicit_iids, sort_conditions, extra_requirements, TRUE);
 		g_free (extra_requirements);
 	}
 
 	if (info_list == NULL) {
 		info_list = nautilus_do_component_query (mime_type, uri_scheme, item_mime_types, FALSE, 
-							 explicit_iids, sort_conditions, NULL);
+							 explicit_iids, sort_conditions, NULL, TRUE);
 	}
 
 	if (info_list != NULL) {
@@ -624,7 +625,7 @@
 		extra_sort_conditions[1] = NULL;
 		extra_requirements = build_joined_string (iids, "has (['", "','", "'], iid)");
 		result = nautilus_do_component_query (mime_type, uri_scheme, item_mime_types, FALSE,
-						      explicit_iids, extra_sort_conditions, extra_requirements);
+						      explicit_iids, extra_sort_conditions, extra_requirements, TRUE);
 		g_free (extra_requirements);
 		g_free (extra_sort_conditions[0]);
 	}
@@ -749,7 +750,7 @@
 	explicit_iids = get_explicit_content_view_iids_from_metafile (file); 
 
 	info_list = nautilus_do_component_query (mime_type, uri_scheme, NULL, TRUE,
-						 explicit_iids, NULL, NULL);
+						 explicit_iids, NULL, NULL, TRUE);
 	
 	needs_full_attributes = FALSE;
 
@@ -793,7 +794,7 @@
 	info_list = nautilus_do_component_query (mime_type, uri_scheme,
 						 item_mime_types, FALSE,
 						 explicit_iids, NULL,
-						 extra_reqs);
+						 extra_reqs, TRUE);
 	
 	eel_g_list_free_deep (explicit_iids);
 	eel_g_list_free_deep (item_mime_types);
@@ -805,6 +806,43 @@
 }
 
 GList *
+nautilus_mime_get_popup_components_for_file (NautilusFile *file)
+{
+	char *mime_type;
+	char *uri_scheme;
+	char *extra_reqs;
+	GList *item_mime_types;
+	GList *info_list;
+
+	if (!nautilus_mime_actions_check_if_minimum_attributes_ready (file)) {
+		return NULL;
+	}
+
+	uri_scheme = nautilus_file_get_uri_scheme (file);
+
+	mime_type = nautilus_file_get_mime_type (file);
+
+	if (!nautilus_mime_actions_check_if_full_attributes_ready (file) || 
+	    !nautilus_file_get_directory_item_mime_types (file, &item_mime_types)) {
+		item_mime_types = NULL;
+	}
+
+	extra_reqs = "repo_ids.has ('IDL:Bonobo/Listener:1.0') AND (nautilus:context_menu_handler == true)";
+
+	info_list = nautilus_do_component_query (mime_type, uri_scheme,
+						 item_mime_types, FALSE,
+						 NULL, NULL,
+						 extra_reqs, FALSE);
+	
+	eel_g_list_free_deep (item_mime_types);
+
+	g_free (uri_scheme);
+	g_free (mime_type);
+
+	return info_list;
+}
+
+GList *
 nautilus_mime_get_all_components_for_file (NautilusFile *file)
 {
 	return nautilus_mime_get_all_components_for_file_extended (file, NULL);
@@ -838,7 +876,7 @@
 
 	return nautilus_do_component_query
 		(NULL, uri_scheme, NULL, TRUE,
-		 NULL, NULL, NULL);
+		 NULL, NULL, NULL, TRUE);
 }
 
 gboolean
@@ -1312,32 +1350,28 @@
 make_bonobo_activation_query_with_known_mime_type (const char *mime_type, 
 				     const char *uri_scheme, 
 				     GList      *explicit_iids, 
-				     const char *extra_requirements)
+				     const char *extra_requirements,
+				     gboolean    must_be_view)
 {
         char *mime_supertype;
         char *result;
         char *explicit_iid_query;
+	const char *view_as_name_logic;
 
         mime_supertype = mime_type_get_supertype (mime_type);
 
         explicit_iid_query = make_bonobo_activation_query_for_explicit_content_view_iids (explicit_iids);
 
+	if (must_be_view) {
+		view_as_name_logic = "nautilus:view_as_name.defined ()";
+	} else {
+		view_as_name_logic = "true";
+	}
+
         result = g_strdup_printf 
                 (
-                 /* Check if the component has the interfaces we need.
-                  * We can work with either a Nautilus View, or
-                  * with a Bonobo Control or Embeddable that supports
-                  * one of the three persistence interfaces:
-                  * PersistStream, ProgressiveDataSink, or
-                  * PersistFile.
-                  */
-                 "(((repo_ids.has_all (['IDL:Bonobo/Control:1.0',"
-                                      "'IDL:Nautilus/View:1.0'])"
-                  "OR (repo_ids.has_one (['IDL:Bonobo/Control:1.0',"
-                                         "'IDL:Bonobo/Embeddable:1.0'])"
-                      "AND repo_ids.has_one (['IDL:Bonobo/PersistStream:1.0',"
-                                             "'IDL:Bonobo/ProgressiveDataSink:1.0',"
-                                             "'IDL:Bonobo/PersistFile:1.0'])))"
+
+                 
                  
                  /* Check that the component either has a specific
                   * MIME type or URI scheme. If neither is specified,
@@ -1345,7 +1379,7 @@
                   * and all schemes". For that, you have to do a
                   * wildcard for the MIME type or for the scheme.
                   */
-                 "AND (bonobo:supported_mime_types.defined ()"
+                 "(bonobo:supported_mime_types.defined ()"
                       "OR bonobo:supported_uri_schemes.defined ()"
 		      "OR bonobo:additional_uri_schemes.defined ())"
 
@@ -1379,12 +1413,13 @@
 		 "OR (bonobo:additional_uri_schemes.has ('%s')"
                       "OR bonobo:additional_uri_schemes.has ('*')))"
 
-                  /* Check that the component makes it clear that it's
+		 /* Check that the component makes it clear that it's
                    * intended for Nautilus by providing a "view_as"
                    * name. We could instead support a default, but
                    * that would make components that are untested with
                    * Nautilus appear.  */
-                 "AND nautilus:view_as_name.defined ())"
+		  "AND %s)"
+                  
 
                   /* Also select iids that were specifically requested
                      for this location, even if they do not otherwise
@@ -1397,14 +1432,42 @@
                  /* The MIME type, MIME supertype, and URI scheme for
                   * the %s above.
                   */
-                 , mime_type, mime_supertype, uri_scheme, uri_scheme
+                 , mime_type, mime_supertype, uri_scheme, uri_scheme,
 
                  /* The explicit metafile iid query for the %s above. */
-                 , explicit_iid_query
+                 view_as_name_logic, explicit_iid_query
 
 		 /* extra requirements */
 		 , extra_requirements != NULL ? extra_requirements : "true");
 
+	if (must_be_view) {
+		char *str;
+
+
+                 /* Check if the component has the interfaces we need.
+                  * We can work with either a Nautilus View, or
+                  * with a Bonobo Control or Embeddable that supports
+                  * one of the three persistence interfaces:
+                  * PersistStream, ProgressiveDataSink, or
+                  * PersistFile.
+                  */
+		str = g_strdup_printf ("(((repo_ids.has_all (['IDL:Bonobo/Control:1.0',"
+                                      "'IDL:Nautilus/View:1.0'])"
+                  "OR (repo_ids.has_one (['IDL:Bonobo/Control:1.0',"
+                                         "'IDL:Bonobo/Embeddable:1.0'])"
+                      "AND repo_ids.has_one (['IDL:Bonobo/PersistStream:1.0',"
+                                             "'IDL:Bonobo/ProgressiveDataSink:1.0',"
+                                          "'IDL:Bonobo/PersistFile:1.0']))) "
+					  "AND %s", result);
+		g_free (result);
+		result = str;
+	} else {
+		char *str;
+		str = g_strdup_printf ("((true AND %s", result);
+		g_free (result);
+		result = str;
+	}
+
         g_free (mime_supertype);
         g_free (explicit_iid_query);
         return result;
@@ -1413,31 +1476,28 @@
 static char *
 make_bonobo_activation_query_with_uri_scheme_only (const char *uri_scheme, 
 				     GList      *explicit_iids, 
-				     const char *extra_requirements)
+				     const char *extra_requirements,
+				     gboolean    must_be_view)
 {
         char *result;
         char *explicit_iid_query;
+	const char *view_as_name_logic;
         
         explicit_iid_query = make_bonobo_activation_query_for_explicit_content_view_iids (explicit_iids);
 
+	if (must_be_view) {
+		view_as_name_logic = "nautilus:view_as_name.defined ()";
+	} else {
+		view_as_name_logic = "true";
+	}
+
         result = g_strdup_printf 
                 (
-                 /* Check if the component has the interfaces we need.
-                  * We can work with either a Nautilus tView, or
-                  * with a Bonobo Control or Embeddable that works on
-                  * a file, which is indicated by Bonobo PersistFile.
-                  */
-                  "(((repo_ids.has_all(['IDL:Bonobo/Control:1.0',"
-                                      "'IDL:Nautilus/View:1.0'])"
-                   "OR (repo_ids.has_one(['IDL:Bonobo/Control:1.0',"
-                                         "'IDL:Bonobo/Embeddable:1.0'])"
-                       "AND repo_ids.has('IDL:Bonobo/PersistFile:1.0')))"
-
 
                   /* Check if the component supports this particular
                    * URI scheme.
                    */
-                  "AND (((bonobo:supported_uri_schemes.has ('%s')"
+                  "(((bonobo:supported_uri_schemes.has ('%s')"
                          "OR bonobo:supported_uri_schemes.has ('*'))"
 
                   /* Check that the component doesn't require
@@ -1452,13 +1512,12 @@
 		  "OR (bonobo:additional_uri_schemes.has ('%s')"
 		      "OR bonobo:additional_uri_schemes.has ('*')))"
 
-
-                  /* Check that the component makes it clear that it's
+		 /* Check that the component makes it clear that it's
                    * intended for Nautilus by providing a "view_as"
                    * name. We could instead support a default, but
                    * that would make components that are untested with
                    * Nautilus appear.  */
-                  "AND nautilus:view_as_name.defined ())"
+		  "AND %s)"
 
                  /* Also select iids that were specifically requested
                      for this location, even if they do not otherwise
@@ -1470,11 +1529,41 @@
 		  " AND (%s)"
 
                   /* The URI scheme for the %s above. */
-                  , uri_scheme, uri_scheme
+                  , uri_scheme, uri_scheme, view_as_name_logic
 
                   /* The explicit metafile iid query for the %s above. */
                   , explicit_iid_query,
 		  extra_requirements != NULL ? extra_requirements : "true");
+	
+
+	if (must_be_view) {
+		char *str;
+
+
+                 /* Check if the component has the interfaces we need.
+                  * We can work with either a Nautilus View, or
+                  * with a Bonobo Control or Embeddable that supports
+                  * one of the three persistence interfaces:
+                  * PersistStream, ProgressiveDataSink, or
+                  * PersistFile.
+                  */
+		str = g_strdup_printf ("(((repo_ids.has_all (['IDL:Bonobo/Control:1.0',"
+                                      "'IDL:Nautilus/View:1.0'])"
+                  "OR (repo_ids.has_one (['IDL:Bonobo/Control:1.0',"
+                                         "'IDL:Bonobo/Embeddable:1.0'])"
+                      "AND repo_ids.has_one (['IDL:Bonobo/PersistStream:1.0',"
+                                             "'IDL:Bonobo/ProgressiveDataSink:1.0',"
+                                          "'IDL:Bonobo/PersistFile:1.0']))) "
+					  "AND %s", result);
+		g_free (result);
+		result = str;
+	} else {
+		char *str;
+		str = g_strdup_printf ("((true AND %s", result);
+		g_free (result);
+		result = str;
+	}
+		  
 
 	g_free (explicit_iid_query);
 	
@@ -1591,7 +1680,8 @@
 			     gboolean           ignore_content_mime_types,
 			     GList             *explicit_iids,
 			     char             **extra_sort_criteria,
-			     char              *extra_requirements)
+			     char              *extra_requirements,
+			     gboolean           must_be_view)
 { 
 	Bonobo_ServerInfoList *bonobo_activation_result;
 	char *query;
@@ -1603,9 +1693,9 @@
         query = NULL;
 
         if (is_known_mime_type (mime_type)) {
-                query = make_bonobo_activation_query_with_known_mime_type (mime_type, uri_scheme, explicit_iids, extra_requirements);
+                query = make_bonobo_activation_query_with_known_mime_type (mime_type, uri_scheme, explicit_iids, extra_requirements, must_be_view);
         } else {
-                query = make_bonobo_activation_query_with_uri_scheme_only (uri_scheme, explicit_iids, extra_requirements);
+                query = make_bonobo_activation_query_with_uri_scheme_only (uri_scheme, explicit_iids, extra_requirements, must_be_view);
         }
 
 	all_sort_criteria = strv_concat (extra_sort_criteria, nautilus_sort_criteria);
Index: libnautilus-private/nautilus-mime-actions.h
===================================================================
RCS file: /cvs/gnome/nautilus/libnautilus-private/nautilus-mime-actions.h,v
retrieving revision 1.25
diff -u -r1.25 nautilus-mime-actions.h
--- libnautilus-private/nautilus-mime-actions.h	25 Oct 2002 17:38:33 -0000	1.25
+++ libnautilus-private/nautilus-mime-actions.h	31 Oct 2002 02:36:46 -0000
@@ -44,6 +44,7 @@
 GList *                  nautilus_mime_get_all_applications_for_file               (NautilusFile           *file);
 GList *                  nautilus_mime_get_all_components_for_file                 (NautilusFile           *file);
 GList *                  nautilus_mime_get_all_components_for_file_extended        (NautilusFile           *file, char *extra_requirements);
+GList *                  nautilus_mime_get_popup_components_for_file               (NautilusFile           *file);
  gboolean                 nautilus_mime_has_any_components_for_file                 (NautilusFile           *file);
  gboolean                 nautilus_mime_has_any_components_for_file_extended        (NautilusFile           *file, char *extra_requirements);
 gboolean                 nautilus_mime_has_any_applications_for_file               (NautilusFile           *file);
Index: libnautilus-private/nautilus-program-chooser.c
===================================================================
RCS file: /cvs/gnome/nautilus/libnautilus-private/nautilus-program-chooser.c,v
retrieving revision 1.78
diff -u -r1.78 nautilus-program-chooser.c
--- libnautilus-private/nautilus-program-chooser.c	25 Oct 2002 17:38:33 -0000	1.78
+++ libnautilus-private/nautilus-program-chooser.c	31 Oct 2002 02:36:46 -0000
@@ -441,7 +441,7 @@
 	
 
 	programs = type == GNOME_VFS_MIME_ACTION_TYPE_COMPONENT
-		? nautilus_mime_get_all_components_for_file_extended (program_chooser->details->file, "(NOT nautilus:property_page_name.defined)")
+		? nautilus_mime_get_all_components_for_file_extended (program_chooser->details->file, "NOT nautilus:property_page_name.defined()")
 		: nautilus_mime_get_all_applications_for_file (program_chooser->details->file);
 
 	list_store = program_chooser->details->list_store;
Index: libnautilus-private/nautilus-program-choosing.c
===================================================================
RCS file: /cvs/gnome/nautilus/libnautilus-private/nautilus-program-choosing.c,v
retrieving revision 1.62
diff -u -r1.62 nautilus-program-choosing.c
--- libnautilus-private/nautilus-program-choosing.c	25 Oct 2002 17:38:33 -0000	1.62
+++ libnautilus-private/nautilus-program-choosing.c	31 Oct 2002 02:36:49 -0000
@@ -194,7 +194,7 @@
 	identifier = NULL;
 	dialog = NULL;
 	if (nautilus_mime_has_any_components_for_file_extended (file,
-	    "(NOT nautilus:property_page_name.defined()")) {
+	    "NOT nautilus:property_page_name.defined()")) {
 		dialog = set_up_program_chooser (file, GNOME_VFS_MIME_ACTION_TYPE_COMPONENT,
 						 choose_data->parent_window);
 		if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
Index: src/file-manager/fm-directory-view.c
===================================================================
RCS file: /cvs/gnome/nautilus/src/file-manager/fm-directory-view.c,v
retrieving revision 1.554
diff -u -r1.554 fm-directory-view.c
--- src/file-manager/fm-directory-view.c	11 Oct 2002 22:22:46 -0000	1.554
+++ src/file-manager/fm-directory-view.c	31 Oct 2002 02:36:53 -0000
@@ -38,6 +38,8 @@
 #include <bonobo/bonobo-control.h>
 #include <bonobo/bonobo-window.h>
 #include <bonobo/bonobo-zoomable.h>
+#include <bonobo/bonobo-ui-util.h>
+#include <bonobo/bonobo-exception.h>
 #include <eel/eel-background.h>
 #include <eel/eel-glib-extensions.h>
 #include <eel/eel-gnome-extensions.h>
@@ -53,6 +55,7 @@
 #include <gtk/gtkselection.h>
 #include <gtk/gtksignal.h>
 #include <gtk/gtkstock.h>
+#include <gtk/gtkmessagedialog.h>
 #include <libgnome/gnome-i18n.h>
 #include <libgnome/gnome-util.h>
 #include <libgnomeui/gnome-uidefs.h>
@@ -154,6 +157,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 MAX_MENU_LEVELS 5
 
@@ -260,6 +264,12 @@
 	WindowChoice choice;
 } ActivateParameters;
 
+typedef struct {
+	char *id;
+	char *verb;
+	char *uri;
+} BonoboMimeActionData;
+
 enum {
 	GNOME_COPIED_FILES
 };
@@ -3492,6 +3502,300 @@
 				       sensitive);
 }
 
+static BonoboMimeActionData *
+bonobo_mime_action_data_new (const char *id, const char *verb, const char *uri)
+{
+	BonoboMimeActionData *data;
+
+	data = g_new (BonoboMimeActionData, 1);
+	data->id = g_strdup (id);
+	data->verb = g_strdup (verb);
+	data->uri = g_strdup (uri);
+
+	return data;
+}
+
+static void
+bonobo_mime_action_data_free (BonoboMimeActionData *data)
+{
+	g_free (data->id);
+	g_free (data->verb);
+	g_free (data->uri);
+	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;
+
+	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)) {
+		BonoboArg *arg;
+
+		arg = bonobo_arg_new (BONOBO_ARG_STRING);
+		BONOBO_ARG_SET_STRING (arg, data->uri);
+		Bonobo_Listener_event (listener, data->verb, arg, &ev);
+		bonobo_arg_release (arg);
+		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);
+}
+
+/* pulled from nautilus-view-identifier.c */
+/* Returns a list of languages, containing
+   the LANG or LANGUAGE environment setting (with and without region code).
+   The elements in the returned list must be freed */
+static GSList *
+get_lang_list (void)
+{
+        GSList *retval;
+	const char *tmp;
+        char *lang, *lang_with_locale, *org_pointer;
+        char *equal_char;
+
+        retval = NULL;
+
+        tmp = g_getenv ("LANGUAGE");
+
+        if (tmp == NULL) {
+                tmp = g_getenv ("LANG");
+        }
+
+	lang = g_strdup (tmp);
+	org_pointer = lang;
+
+	if (lang != NULL) {
+		/* envs can be in NAME=VALUE form */
+		equal_char = strchr (lang, '=');
+		if (equal_char != NULL) {
+			lang = equal_char + 1;
+		}
+		
+		/* lang may be in form LANG_LOCALE */
+		equal_char = strchr (lang, '_');
+		if (equal_char != NULL) {
+			lang_with_locale = g_strdup (lang);
+			*equal_char = 0;
+		} else {
+			lang_with_locale = NULL;
+		}
+
+		/* Make sure we don't give oaf an empty
+		   lang string */
+		if (!eel_str_is_empty (lang_with_locale)) {
+			retval = g_slist_prepend (retval, 
+						  g_strdup (lang_with_locale));
+		}
+		g_free (lang_with_locale);
+		if (!eel_str_is_empty (lang)) {
+			retval = g_slist_prepend (retval, g_strdup (lang));
+		}
+        }
+	g_free (org_pointer);
+        
+        return retval;
+}
+
+
+static void
+add_bonobo_menu_ui_and_verbs (FMDirectoryView *view, NautilusFile *file,
+			      Bonobo_ServerInfo *info, GList *verb_names)
+{
+	GList *l;
+	GString *ui_xml;
+	GSList *langs;
+	char *ui_xml_str;
+	char *uri;
+
+	g_return_if_fail (verb_names != NULL);
+
+	langs = get_lang_list ();
+
+	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);
+		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\">");
+
+	/* build the UI */
+	for (l = verb_names; l; l = l->next) {
+		char *verb = l->data;
+
+		g_string_append_printf (ui_xml, "<menuitem name=\"%s\" verb=\"%s\"/>", verb, verb);
+	}
+	
+	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);
+
+	uri = nautilus_file_get_uri (file);
+
+	/* add the verbs */
+	for (l = verb_names; l; l = l->next) {
+		const char *verb;
+		BonoboMimeActionData *data;
+		GClosure *closure;
+
+		verb = l->data;
+		
+		data = bonobo_mime_action_data_new (info->iid,
+						    verb, uri);
+		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); 
+	}
+
+	g_free (uri);
+	eel_g_slist_free_deep (langs);
+}
+
+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:")) {
+			l = g_list_prepend (l,
+			      g_strdup (&info->props._buffer[i].name[offset]));	
+		}
+	}
+
+	return l;
+}
+
+static void
+reset_bonobo_mime_actions_menu (FMDirectoryView *view, GList *selection)
+{
+	NautilusFile *file;
+	gboolean sensitive;
+
+	/* 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);
+
+	/* This menu is only displayed when there's one selected item. */
+	/* FIXME:  We could probably get components that are common to all
+	 * the files and stick those in the menu.
+	 */
+	if (!eel_g_list_exactly_one_item (selection)) {
+		sensitive = FALSE;
+	} else {
+		GList *components, *l;
+		sensitive = TRUE;
+		
+		file = NAUTILUS_FILE (selection->data);
+		
+		components = nautilus_mime_get_popup_components_for_file (file);
+
+		for (l = components; l; l = l->next) {
+			Bonobo_ServerInfo *info;
+			GList *verb_names;
+
+			info = l->data;
+			verb_names = get_bonobo_menu_verb_names (info);
+			
+			add_bonobo_menu_ui_and_verbs (view, file, info,
+						      verb_names);
+			eel_g_list_free_deep (verb_names);
+			
+		}
+		gnome_vfs_mime_component_list_free (components);
+	}
+
+	nautilus_bonobo_set_sensitive (view->details->ui,
+				       FM_DIRECTORY_VIEW_POPUP_PATH_MIME_ACTIONS,
+				       sensitive);
+}
+
 static char *
 change_to_view_directory (FMDirectoryView *view)
 {
@@ -4323,6 +4627,7 @@
 
 	/* Broken into its own function just for convenience */
 	reset_bonobo_open_with_menu (view, selection);
+	reset_bonobo_mime_actions_menu (view, selection);
 
 	if (all_selected_items_in_trash (view)) {
 		label = _("_Delete from Trash");
Index: src/file-manager/nautilus-directory-view-ui.xml
===================================================================
RCS file: /cvs/gnome/nautilus/src/file-manager/nautilus-directory-view-ui.xml,v
retrieving revision 1.49
diff -u -r1.49 nautilus-directory-view-ui.xml
--- src/file-manager/nautilus-directory-view-ui.xml	30 Sep 2002 15:43:09 -0000	1.49
+++ src/file-manager/nautilus-directory-view-ui.xml	31 Oct 2002 02:36:53 -0000
@@ -249,6 +249,7 @@
 			 pixtype="stock" pixname="gtk-paste"
 			 verb="Paste Files"/>
 		</placeholder>
+		<placeholder name="Mime Actions" delimit="top"/>
 		<placeholder name="File Actions" delimit="top">
 			<menuitem name="Duplicate" verb="Duplicate"/>
 			<menuitem name="Create Link" verb="Create Link"/>


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