Re: pluggable context menus ...
- From: James Willcox <jwillcox cs indiana edu>
- To: Michael Meeks <michael ximian com>
- Cc: Dave Camp <dave ximian com>, Alexander Larsson <alexl redhat com>, nautilus-list gnome org
- Subject: Re: pluggable context menus ...
- Date: 26 Oct 2002 02:48:30 -0500
On Sat, 2002-10-26 at 02:23, James Willcox wrote:
> 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
Um, that last patch was brain damaged. This one is better, I promise :)
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 26 Oct 2002 07:40:37 -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:40:37 -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:40:37 -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,32 @@
}
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 for %s", event_name,
+ (const char *)any);
+ 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 +261,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:40:38 -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:40:38 -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:40:38 -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,31 @@
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 for %s", event_name,
+ (const char *)any);
+ 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 +411,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:40:38 -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:40:38 -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:40:40 -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,192 @@
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, 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)) {
+ Bonobo_Listener_event (listener, data->verb,
+ (CORBA_any*)data->uri, &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 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;
+ char *uri;
+
+ verb = v->data;
+
+ uri = nautilus_file_get_uri (file);
+ 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);
+
+ 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 +4519,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:40:40 -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]