Re: pluggable context menus ...



On Fri, 2002-10-25 at 04:37, Michael Meeks wrote:
> Hi James,
> 
> On Thu, 2002-10-24 at 19:00, James Willcox wrote:
> > Ok, what if we just hold a path to a UI file in the .server file,
> 
> 	That's fair enough - OTOH, it's nice to have the embedded XML feature
> for evolution, so a single XML file can describe everything ;-) but it's
> understandable that you don't want to delve into b-a-s and do that.
> 
> > If you can better explain to me how to work out the verb stuff, I might
> > be interested in doing this.  Also, do we really want to be activating
> > components when people bring up a menu?  Is it going to be fast enough?
> 
> 	Nope, we don't want to activate the components - hence simply merging
> the XML into the menu - using b-a-s lets you get that far without
> activating anything; clearly as soon as you select the menu item; then
> yes we need to activate something - but that's the case anyway ;-) also,
> hopefully an instance of eg. the image viewer will be running already so
> the latency can best case be ~0.

Ok, so I've attached a patch that implements this.  I had to put the
verb names in the .server file as a separate stringv attribute so I knew
which verbs to add.  Is there a better way to do this?  Other than that,
I think it's pretty straight-forward.  The code that creates the b-a
query string is pretty crappy, but I'm not sure a lot can be done for
it....

To test this, I've modified the notes and image properties components to
put stuff in the context menu.  Give it a shot if you like. 
Screenshot: 
http://snorp.coreyo.net/~snorp/nautilus-mime-context-menus-2.png

Thanks,
James 
? nautilus_jwillcox_context_menus_v1.diff
? components/emblem/Makefile
? components/emblem/Makefile.in
? components/emblem/Nautilus_View_emblem.server
? components/emblem/Nautilus_View_emblem.server.in
? components/image_properties/nautilus-image-properties-view.xml
? components/notes/nautilus-notes-view.xml
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	26 Oct 2002 07:04:59 -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	26 Oct 2002 07:04:59 -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,11 @@
 	</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="nautilus:context_menu_ui" type="string" value="nautilus-image-properties-view.xml"/>
+	<oaf_attribute name="nautilus:context_menu_verbs" type="stringv">
+		<item value="DoRotate"/>
+		<item value="DoResize"/>
+	</oaf_attribute>
 </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	26 Oct 2002 07:04:59 -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,31 @@
 }
 
 static void
+listener_callback (BonoboListener *listener,
+		   const char *event_name,
+		   const CORBA_any *any,
+		   CORBA_Environment *ev,
+		   gpointer user_data)
+{
+	GtkWidget *dialog;
+
+	dialog = gtk_message_dialog_new (NULL, 0, GTK_MESSAGE_INFO,
+					 GTK_BUTTONS_OK,
+					 "Got event %s", event_name);
+	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 +260,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	26 Oct 2002 07:04:59 -0000
@@ -29,5 +29,8 @@
 	sed -e "s|\ BONOBODIR\@|$(bonobodir)|" $< > $@
 @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	26 Oct 2002 07:04:59 -0000
@@ -18,6 +18,10 @@
 	</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="nautilus:context_menu_ui" type="string" value="nautilus-notes-view.xml"/>
+	<oaf_attribute name="nautilus:context_menu_verbs" type="stringv">
+		<item value="ShowNotes"/>
+	</oaf_attribute>
 </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	26 Oct 2002 07:04:59 -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,30 @@
 	return NULL;
 }
 
+static void
+listener_callback (BonoboListener *listener,
+		   const char *event_name,
+		   const CORBA_any *any,
+		   CORBA_Environment *ev,
+		   gpointer user_data)
+{
+	GtkWidget *dialog;
+
+	dialog = gtk_message_dialog_new (NULL, 0, GTK_MESSAGE_INFO,
+					 GTK_BUTTONS_OK,
+					 "Got event %s", event_name);
+	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 +410,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	26 Oct 2002 07:05:02 -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,42 @@
 }
 
 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 = "nautilus:context_menu_ui.defined()";
+	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 +875,7 @@
 
 	return nautilus_do_component_query
 		(NULL, uri_scheme, NULL, TRUE,
-		 NULL, NULL, NULL);
+		 NULL, NULL, NULL, TRUE);
 }
 
 gboolean
@@ -1312,32 +1349,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 +1378,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 +1412,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 +1431,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 +1475,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 +1511,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 +1528,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 +1679,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 +1692,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	26 Oct 2002 07:05:02 -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: 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	26 Oct 2002 07:05:04 -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>
@@ -154,6 +156,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 +263,11 @@
 	WindowChoice choice;
 } ActivateParameters;
 
+typedef struct {
+	char *id;
+	char *verb;
+} BonoboMimeActionData;
+
 enum {
 	GNOME_COPIED_FILES
 };
@@ -3492,6 +3500,190 @@
 				       sensitive);
 }
 
+static GList *
+get_bonobo_verb_names (Bonobo_ServerInfo *info)
+{
+	Bonobo_ActivationProperty *prop;
+	Bonobo_StringList strings;
+	GList *list;
+	unsigned int i;
+
+	prop = bonobo_server_info_prop_find (info,
+				"nautilus:context_menu_verbs");
+
+	g_return_val_if_fail (prop != NULL, NULL);
+
+	strings = prop->v._u.value_stringv;
+	list = NULL;
+
+	for (i=0; i < strings._length; i++) {
+		list = g_list_prepend (list, g_strdup (strings._buffer[i]));
+	}
+	
+	return list;
+}
+
+static BonoboMimeActionData *
+bonobo_mime_action_data_new (const char *id, const char *verb)
+{
+	BonoboMimeActionData *data;
+
+	data = g_new (BonoboMimeActionData, 1);
+	data->id = g_strdup (id);
+	data->verb = g_strdup (verb);
+
+	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;
+	char *verb;
+
+	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);
+		g_free (verb);
+		return;
+	}
+
+	CORBA_exception_init (&ev);
+	verb = user_data;
+
+	listener = Bonobo_Unknown_queryInterface (obj,
+						  "IDL:Bonobo/Listener:1.0",
+						  &ev);
+
+	if (!BONOBO_EX (&ev)) {
+		Bonobo_Listener_event (listener, verb, NULL, &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."),
+				error_reason);
+		g_signal_connect (dialog, "response",
+				  G_CALLBACK (gtk_widget_destroy), NULL);
+		gtk_widget_show (dialog);
+	}
+
+	
+	g_free (verb);
+}
+
+
+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,
+				g_strdup (data->verb), NULL);
+	
+}
+
+static void
+bonobo_mime_action_menu_data_destroy_callback (gpointer data, GClosure *closure)
+{
+	bonobo_mime_action_data_free ((BonoboMimeActionData *)data);
+}
+
+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. */
+	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);
+		l = components;
+		while (l != NULL) {
+			Bonobo_ServerInfo *info;
+			const char *ui_file;
+			GList *verbs, *v;
+
+			info = l->data;
+
+			ui_file = bonobo_server_info_prop_lookup (info,
+						"nautilus:context_menu_ui",
+						NULL);
+
+			bonobo_ui_util_set_ui (view->details->ui,
+					       DATADIR, ui_file,
+					       "nautilus", NULL);
+
+			verbs = get_bonobo_verb_names (info);
+			v = verbs;
+			while (v != NULL) {
+				char *verb;
+				BonoboMimeActionData *data;
+				GClosure *closure;
+
+				verb = v->data;
+
+				data = bonobo_mime_action_data_new (info->iid,
+								    verb);
+				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); 
+
+				v = v->next;
+			}
+			eel_g_list_free_deep (verbs);
+			
+			l = l->next;
+		}
+		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 +4515,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	26 Oct 2002 07:05:05 -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"/>
<Root>
<commands>
	<cmd name="ShowNotes"
	 _label="Show Notes..."
	 _tip="Show Notes"/>
</commands>
<popups>
	<popup name="selection">
		<placeholder name="Mime Actions">
			<menuitem name="Show Notes"
			 verb="ShowNotes"/>
		</placeholder>
	</popup>
</popups>
</Root>
<Root>
<commands>
	<cmd name="DoRotate"
	 _label="Rotate Image..."
	 _tip="Rotate the selected image"/>
	<cmd name="DoResize"
	 _label="Resize Image..."
	 _tip="Resize the selected image"/>
</commands>
<popups>
	<popup name="selection">
		<placeholder name="Mime Actions">
			<menuitem name="Rotate Image"
			 verb="DoRotate"/>
			<menuitem name="Resize Image"
			 verb="DoResize"/>
		</placeholder>
	</popup>
</popups>
</Root>


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